Print this page
10267 ld and GCC disagree about i386 local dynamic TLS


 398          */
 399         0x03, 0x80, 0x00, 0x00, 0x00, 0x00
 400 };
 401 
 402 static uchar_t tlsinstr_gd_le[] = {
 403         /*
 404          * 0x00 movl %gs:0x0, %eax
 405          */
 406         0x65, 0xa1, 0x00, 0x00, 0x00, 0x00,
 407         /*
 408          * 0x06 addl $0x0, %eax
 409          */
 410         0x05, 0x00, 0x00, 0x00, 0x00,
 411         /*
 412          * 0x0b nop
 413          * 0x0c
 414          */
 415         0x90
 416 };
 417 
 418 static uchar_t tlsinstr_gd_ie_movgs[] = {
 419         /*
 420          *      movl %gs:0x0,%eax
 421          */
 422         0x65, 0xa1, 0x00, 0x00, 0x00, 00











 423 };
 424 
 425 #define TLS_GD_IE_MOV   0x8b    /* movl opcode */
 426 #define TLS_GD_IE_POP   0x58    /* popl + reg */
 427 
 428 #define TLS_GD_LE_MOVL  0xb8    /* movl + reg */
 429 
 430 #define TLS_NOP         0x90    /* NOP instruction */
 431 
 432 #define MODRM_MSK_MOD   0xc0
 433 #define MODRM_MSK_RO    0x38
 434 #define MODRM_MSK_RM    0x07
 435 
 436 #define SIB_MSK_SS      0xc0
 437 #define SIB_MSK_IND     0x38
 438 #define SIB_MSK_BS      0x07
 439 
 440 static Fixupret
 441 tls_fixups(Ofl_desc *ofl, Rel_desc *arsp)
 442 {


 511                  *      0xc
 512                  */
 513                 DBG_CALL(Dbg_reloc_transition(ofl->ofl_lml, M_MACH,
 514                     R_386_TLS_LE, arsp, ld_reloc_sym_name));
 515 
 516                 arsp->rel_rtype = R_386_TLS_LE;
 517                 arsp->rel_roffset += 4;
 518 
 519                 /*
 520                  * Adjust 'offset' to beginning of instruction
 521                  * sequence.
 522                  */
 523                 offset -= 3;
 524                 (void) memcpy(offset, tlsinstr_gd_le,
 525                     sizeof (tlsinstr_gd_le));
 526                 return (FIX_RELOC);
 527 
 528         case R_386_TLS_GD_PLT:
 529         case R_386_PLT32:
 530                 /*
 531                  * Fixup done via the TLS_GD relocation

 532                  */
 533                 DBG_CALL(Dbg_reloc_transition(ofl->ofl_lml, M_MACH,
 534                     R_386_NONE, arsp, ld_reloc_sym_name));
 535                 return (FIX_DONE);
 536 
 537         case R_386_TLS_LDM_PLT:
 538                 DBG_CALL(Dbg_reloc_transition(ofl->ofl_lml, M_MACH,
 539                     R_386_NONE, arsp, ld_reloc_sym_name));
 540 
 541                 /*
 542                  * Transition:
 543                  *      call __tls_get_addr()
 544                  * to:
 545                  *      nop
 546                  *      nop
 547                  *      nop
 548                  *      nop
 549                  *      nop
 550                  */
 551                 *(offset - 1) = TLS_NOP;
 552                 *(offset) = TLS_NOP;
 553                 *(offset + 1) = TLS_NOP;
 554                 *(offset + 2) = TLS_NOP;
 555                 *(offset + 3) = TLS_NOP;
 556                 return (FIX_DONE);
 557 
 558         case R_386_TLS_LDM:
 559                 DBG_CALL(Dbg_reloc_transition(ofl->ofl_lml, M_MACH,
 560                     R_386_NONE, arsp, ld_reloc_sym_name));
 561 
 562                 /*
 563                  * Transition:
 564                  *
 565                  *  0x00 leal x1@tlsldm(%ebx), %eax
 566                  *  0x06 call ___tls_get_addr
 567                  *
 568                  * to:
 569                  *
 570                  *  0x00 movl %gs:0, %eax
 571                  */
 572                 (void) memcpy(offset - 2, tlsinstr_gd_ie_movgs,
 573                     sizeof (tlsinstr_gd_ie_movgs));









 574                 return (FIX_DONE);
 575 
 576         case R_386_TLS_LDO_32:
 577                 /*
 578                  *  Instructions:
 579                  *
 580                  *  0x10 leal x1@dtpoff(%eax), %edx     R_386_TLS_LDO_32
 581                  *              to
 582                  *  0x10 leal x1@ntpoff(%eax), %edx     R_386_TLS_LE
 583                  *
 584                  */
 585                 offset -= 2;
 586 
 587                 DBG_CALL(Dbg_reloc_transition(ofl->ofl_lml, M_MACH,
 588                     R_386_TLS_LE, arsp, ld_reloc_sym_name));
 589                 arsp->rel_rtype = R_386_TLS_LE;
 590                 return (FIX_RELOC);
 591 
 592         case R_386_TLS_GOTIE:
 593                 /*




 398          */
 399         0x03, 0x80, 0x00, 0x00, 0x00, 0x00
 400 };
 401 
 402 static uchar_t tlsinstr_gd_le[] = {
 403         /*
 404          * 0x00 movl %gs:0x0, %eax
 405          */
 406         0x65, 0xa1, 0x00, 0x00, 0x00, 0x00,
 407         /*
 408          * 0x06 addl $0x0, %eax
 409          */
 410         0x05, 0x00, 0x00, 0x00, 0x00,
 411         /*
 412          * 0x0b nop
 413          * 0x0c
 414          */
 415         0x90
 416 };
 417 
 418 static uchar_t tlsinstr_ld_le_movgs[] = {
 419         /*
 420          * 0x00 movl %gs:0x0,%eax
 421          */
 422         0x65, 0xa1, 0x00, 0x00, 0x00, 0x00,
 423 };
 424 
 425 /*
 426  * 0x00 nopl 0(%eax,%eax) -- the intel recommended 5-byte nop
 427  * See Intel® 64 and IA-32 Architectures Software Developer’s Manual
 428  *    Volume 2B: Instruction Set Reference, M-U
 429  *    Table 4-12, Recommended Multi-Byte Sequence of NOP Instruction
 430  */
 431 static uchar_t tlsinstr_nop5[] = {
 432 
 433         0x0f, 0x1f, 0x44, 0x00, 0x00
 434 };
 435 
 436 #define TLS_GD_IE_MOV   0x8b    /* movl opcode */
 437 #define TLS_GD_IE_POP   0x58    /* popl + reg */
 438 
 439 #define TLS_GD_LE_MOVL  0xb8    /* movl + reg */
 440 
 441 #define TLS_NOP         0x90    /* NOP instruction */
 442 
 443 #define MODRM_MSK_MOD   0xc0
 444 #define MODRM_MSK_RO    0x38
 445 #define MODRM_MSK_RM    0x07
 446 
 447 #define SIB_MSK_SS      0xc0
 448 #define SIB_MSK_IND     0x38
 449 #define SIB_MSK_BS      0x07
 450 
 451 static Fixupret
 452 tls_fixups(Ofl_desc *ofl, Rel_desc *arsp)
 453 {


 522                  *      0xc
 523                  */
 524                 DBG_CALL(Dbg_reloc_transition(ofl->ofl_lml, M_MACH,
 525                     R_386_TLS_LE, arsp, ld_reloc_sym_name));
 526 
 527                 arsp->rel_rtype = R_386_TLS_LE;
 528                 arsp->rel_roffset += 4;
 529 
 530                 /*
 531                  * Adjust 'offset' to beginning of instruction
 532                  * sequence.
 533                  */
 534                 offset -= 3;
 535                 (void) memcpy(offset, tlsinstr_gd_le,
 536                     sizeof (tlsinstr_gd_le));
 537                 return (FIX_RELOC);
 538 
 539         case R_386_TLS_GD_PLT:
 540         case R_386_PLT32:
 541                 /*
 542                  * Fixup done via the TLS_GD/TLS_LDM relocation processing
 543                  * and ld_reloc_plt() handling __tls_get_addr().
 544                  */
 545                 DBG_CALL(Dbg_reloc_transition(ofl->ofl_lml, M_MACH,
 546                     R_386_NONE, arsp, ld_reloc_sym_name));
 547                 return (FIX_DONE);
 548 
 549         case R_386_TLS_LDM_PLT:
 550                 DBG_CALL(Dbg_reloc_transition(ofl->ofl_lml, M_MACH,
 551                     R_386_NONE, arsp, ld_reloc_sym_name));
 552 
 553                 /*
 554                  * Transition:
 555                  *      call __tls_get_addr()
 556                  * to:
 557                  *      nopl 0x0(%eax,%eax)
 558                  */
 559                 (void) memcpy(offset - 1, tlsinstr_nop5,
 560                     sizeof (tlsinstr_nop5));







 561                 return (FIX_DONE);
 562 
 563         case R_386_TLS_LDM:
 564                 DBG_CALL(Dbg_reloc_transition(ofl->ofl_lml, M_MACH,
 565                     R_386_NONE, arsp, ld_reloc_sym_name));
 566 
 567                 /*
 568                  * Transition:
 569                  *
 570                  *  0x00 leal x1@tlsldm(%ebx), %eax
 571                  *  0x06 call ___tls_get_addr
 572                  *
 573                  * to:
 574                  *
 575                  *  0x00 movl %gs:0, %eax
 576                  */
 577                 (void) memcpy(offset - 2, tlsinstr_ld_le_movgs,
 578                     sizeof (tlsinstr_ld_le_movgs));
 579 
 580                 /*
 581                  *  We implicitly treat this as if a R_386_TLS_LDM_PLT for the
 582                  *  __tls_get_addr call followed it as the GNU compiler
 583                  *  doesn't generate one.  This is safe, because if one _does_
 584                  *  exist we'll just write the nop again.
 585                  */
 586                 (void) memcpy(offset + 4, tlsinstr_nop5,
 587                     sizeof (tlsinstr_nop5));
 588                 return (FIX_DONE);
 589 
 590         case R_386_TLS_LDO_32:
 591                 /*
 592                  *  Instructions:
 593                  *
 594                  *  0x10 leal x1@dtpoff(%eax), %edx     R_386_TLS_LDO_32
 595                  *              to
 596                  *  0x10 leal x1@ntpoff(%eax), %edx     R_386_TLS_LE
 597                  *
 598                  */
 599                 offset -= 2;
 600 
 601                 DBG_CALL(Dbg_reloc_transition(ofl->ofl_lml, M_MACH,
 602                     R_386_TLS_LE, arsp, ld_reloc_sym_name));
 603                 arsp->rel_rtype = R_386_TLS_LE;
 604                 return (FIX_RELOC);
 605 
 606         case R_386_TLS_GOTIE:
 607                 /*