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

*** 413,427 **** * 0x0c */ 0x90 }; ! static uchar_t tlsinstr_gd_ie_movgs[] = { /* ! * movl %gs:0x0,%eax */ ! 0x65, 0xa1, 0x00, 0x00, 0x00, 00 }; #define TLS_GD_IE_MOV 0x8b /* movl opcode */ #define TLS_GD_IE_POP 0x58 /* popl + reg */ --- 413,438 ---- * 0x0c */ 0x90 }; ! static uchar_t tlsinstr_ld_le_movgs[] = { /* ! * 0x00 movl %gs:0x0,%eax */ ! 0x65, 0xa1, 0x00, 0x00, 0x00, 0x00, ! }; ! ! /* ! * 0x00 nopl 0(%eax,%eax) -- the intel recommended 5-byte nop ! * See Intel® 64 and IA-32 Architectures Software Developer’s Manual ! * Volume 2B: Instruction Set Reference, M-U ! * Table 4-12, Recommended Multi-Byte Sequence of NOP Instruction ! */ ! static uchar_t tlsinstr_nop5[] = { ! ! 0x0f, 0x1f, 0x44, 0x00, 0x00 }; #define TLS_GD_IE_MOV 0x8b /* movl opcode */ #define TLS_GD_IE_POP 0x58 /* popl + reg */
*** 526,536 **** return (FIX_RELOC); case R_386_TLS_GD_PLT: case R_386_PLT32: /* ! * Fixup done via the TLS_GD relocation */ DBG_CALL(Dbg_reloc_transition(ofl->ofl_lml, M_MACH, R_386_NONE, arsp, ld_reloc_sym_name)); return (FIX_DONE); --- 537,548 ---- return (FIX_RELOC); case R_386_TLS_GD_PLT: case R_386_PLT32: /* ! * Fixup done via the TLS_GD/TLS_LDM relocation processing ! * and ld_reloc_plt() handling __tls_get_addr(). */ DBG_CALL(Dbg_reloc_transition(ofl->ofl_lml, M_MACH, R_386_NONE, arsp, ld_reloc_sym_name)); return (FIX_DONE);
*** 540,560 **** /* * Transition: * call __tls_get_addr() * to: ! * nop ! * nop ! * nop ! * nop ! * nop ! */ ! *(offset - 1) = TLS_NOP; ! *(offset) = TLS_NOP; ! *(offset + 1) = TLS_NOP; ! *(offset + 2) = TLS_NOP; ! *(offset + 3) = TLS_NOP; return (FIX_DONE); case R_386_TLS_LDM: DBG_CALL(Dbg_reloc_transition(ofl->ofl_lml, M_MACH, R_386_NONE, arsp, ld_reloc_sym_name)); --- 552,565 ---- /* * Transition: * call __tls_get_addr() * to: ! * nopl 0x0(%eax,%eax) ! */ ! (void) memcpy(offset - 1, tlsinstr_nop5, ! sizeof (tlsinstr_nop5)); return (FIX_DONE); case R_386_TLS_LDM: DBG_CALL(Dbg_reloc_transition(ofl->ofl_lml, M_MACH, R_386_NONE, arsp, ld_reloc_sym_name));
*** 567,578 **** * * to: * * 0x00 movl %gs:0, %eax */ ! (void) memcpy(offset - 2, tlsinstr_gd_ie_movgs, ! sizeof (tlsinstr_gd_ie_movgs)); return (FIX_DONE); case R_386_TLS_LDO_32: /* * Instructions: --- 572,592 ---- * * to: * * 0x00 movl %gs:0, %eax */ ! (void) memcpy(offset - 2, tlsinstr_ld_le_movgs, ! sizeof (tlsinstr_ld_le_movgs)); ! ! /* ! * We implicitly treat this as if a R_386_TLS_LDM_PLT for the ! * __tls_get_addr call followed it as the GNU compiler ! * doesn't generate one. This is safe, because if one _does_ ! * exist we'll just write the nop again. ! */ ! (void) memcpy(offset + 4, tlsinstr_nop5, ! sizeof (tlsinstr_nop5)); return (FIX_DONE); case R_386_TLS_LDO_32: /* * Instructions: