Index: lld/trunk/ELF/InputSection.cpp =================================================================== --- lld/trunk/ELF/InputSection.cpp +++ lld/trunk/ELF/InputSection.cpp @@ -151,6 +151,8 @@ } else if (!Target->relocNeedsCopy(Type, Body) && isa>(Body)) { continue; + } else if (Target->isTlsDynReloc(Type)) { + continue; } Target->relocateOne(BufLoc, BufEnd, Type, AddrLoc, SymVA + getAddend(RI)); Index: lld/trunk/ELF/OutputSections.cpp =================================================================== --- lld/trunk/ELF/OutputSections.cpp +++ lld/trunk/ELF/OutputSections.cpp @@ -241,7 +241,8 @@ Config->Mips64EL); else P->setSymbolAndType(Body->getDynamicSymbolTableIndex(), - NeedsCopy ? Target->getCopyReloc() : Type, + NeedsCopy ? Target->getCopyReloc() + : Target->getDynReloc(Type), Config->Mips64EL); } else { P->setSymbolAndType(0, Target->getRelativeReloc(), Config->Mips64EL); Index: lld/trunk/ELF/Target.h =================================================================== --- lld/trunk/ELF/Target.h +++ lld/trunk/ELF/Target.h @@ -28,7 +28,6 @@ unsigned getPltReloc() const { return PltReloc; } unsigned getRelativeReloc() const { return RelativeReloc; } unsigned getTlsGotReloc() const { return TlsGotReloc; } - unsigned getTlsPcRelGotReloc() const { return TlsPcRelGotReloc; } bool isTlsLocalDynamicReloc(unsigned Type) const { return Type == TlsLocalDynamicReloc; } @@ -42,6 +41,8 @@ bool supportsLazyRelocations() const { return LazyRelocations; } unsigned getGotHeaderEntriesNum() const { return GotHeaderEntriesNum; } unsigned getGotPltHeaderEntriesNum() const { return GotPltHeaderEntriesNum; } + virtual unsigned getDynReloc(unsigned Type) const { return Type; } + virtual bool isTlsDynReloc(unsigned Type) const { return false; } virtual unsigned getGotRefReloc(unsigned Type) const; virtual unsigned getPltRefReloc(unsigned Type) const; virtual void writeGotHeaderEntries(uint8_t *Buf) const; @@ -84,7 +85,6 @@ unsigned TlsGlobalDynamicReloc = 0; unsigned TlsModuleIndexReloc; unsigned TlsOffsetReloc; - unsigned TlsPcRelGotReloc = 0; unsigned PltEntrySize = 8; unsigned PltZeroEntrySize = 0; unsigned GotHeaderEntriesNum = 0; Index: lld/trunk/ELF/Target.cpp =================================================================== --- lld/trunk/ELF/Target.cpp +++ lld/trunk/ELF/Target.cpp @@ -46,6 +46,8 @@ class X86TargetInfo final : public TargetInfo { public: X86TargetInfo(); + unsigned getDynReloc(unsigned Type) const override; + bool isTlsDynReloc(unsigned Type) const override; void writeGotPltEntry(uint8_t *Buf, uint64_t Plt) const override; void writePltZeroEntry(uint8_t *Buf, uint64_t GotEntryAddr, uint64_t PltEntryAddr) const override; @@ -62,6 +64,7 @@ public: X86_64TargetInfo(); unsigned getPltRefReloc(unsigned Type) const override; + bool isTlsDynReloc(unsigned Type) const override; void writeGotPltHeaderEntries(uint8_t *Buf) const override; void writeGotPltEntry(uint8_t *Buf, uint64_t Plt) const override; void writePltZeroEntry(uint8_t *Buf, uint64_t GotEntryAddr, @@ -182,6 +185,20 @@ PltReloc = R_386_JUMP_SLOT; } +unsigned X86TargetInfo::getDynReloc(unsigned Type) const { + if (Type == R_386_TLS_LE) + return R_386_TLS_TPOFF; + if (Type == R_386_TLS_LE_32) + return R_386_TLS_TPOFF32; + return Type; +} + +bool X86TargetInfo::isTlsDynReloc(unsigned Type) const { + if (Type == R_386_TLS_LE || Type == R_386_TLS_LE_32) + return Config->Shared; + return false; +} + void X86TargetInfo::writeGotPltEntry(uint8_t *Buf, uint64_t Plt) const {} void X86TargetInfo::writePltZeroEntry(uint8_t *Buf, uint64_t GotEntryAddr, uint64_t PltEntryAddr) const {} @@ -225,6 +242,12 @@ case R_386_32: add32le(Loc, SA); break; + case R_386_TLS_LE: + write32le(Loc, SA - Out::TlsPhdr->p_memsz); + break; + case R_386_TLS_LE_32: + write32le(Loc, Out::TlsPhdr->p_memsz - SA); + break; default: error("unrecognized reloc " + Twine(Type)); } @@ -242,7 +265,6 @@ TlsGlobalDynamicReloc = R_X86_64_TLSGD; TlsModuleIndexReloc = R_X86_64_DTPMOD64; TlsOffsetReloc = R_X86_64_DTPOFF64; - TlsPcRelGotReloc = R_X86_64_GOTTPOFF; LazyRelocations = true; PltEntrySize = 16; PltZeroEntrySize = 16; @@ -300,6 +322,10 @@ relocNeedsPlt(Type, S); } +bool X86_64TargetInfo::isTlsDynReloc(unsigned Type) const { + return Type == R_X86_64_GOTTPOFF; +} + unsigned X86_64TargetInfo::getPltRefReloc(unsigned Type) const { if (Type == R_X86_64_PLT32) return R_X86_64_PC32; Index: lld/trunk/ELF/Writer.cpp =================================================================== --- lld/trunk/ELF/Writer.cpp +++ lld/trunk/ELF/Writer.cpp @@ -229,7 +229,7 @@ continue; } - if ((Body && Body->isTLS()) && Type != Target->getTlsPcRelGotReloc()) + if ((Body && Body->isTLS()) && !Target->isTlsDynReloc(Type)) continue; bool NeedsGot = false; Index: lld/trunk/test/ELF/tls-i686.s =================================================================== --- lld/trunk/test/ELF/tls-i686.s +++ lld/trunk/test/ELF/tls-i686.s @@ -0,0 +1,69 @@ +// REQUIRES: x86 +// RUN: llvm-mc -filetype=obj -triple=i686-pc-linux %s -o %t +// RUN: ld.lld %t -o %tout +// RUN: ld.lld %t -shared -o %tsharedout +// RUN: llvm-objdump -d %tout | FileCheck %s --check-prefix=DIS +// RUN: llvm-readobj -r %tout | FileCheck %s --check-prefix=RELOC +// RUN: llvm-objdump -d %tsharedout | FileCheck %s --check-prefix=DISSHARED +// RUN: llvm-readobj -r %tsharedout | FileCheck %s --check-prefix=RELOCSHARED + +.section ".tdata", "awT", @progbits +.globl var +.globl var1 +var: +.long 0 +var1: +.long 1 + +.text +.global _start +_start: + movl $var@tpoff, %edx + movl %gs:0, %ecx + subl %edx, %eax + movl $var1@tpoff, %edx + movl %gs:0, %ecx + subl %edx, %eax + + movl %gs:0, %ecx + leal var@ntpoff(%ecx), %eax + movl %gs:0, %ecx + leal var1@ntpoff(%ecx), %eax + +// DIS: Disassembly of section .text: +// DIS-NEXT: _start: +// DIS-NEXT: 11000: ba 08 00 00 00 movl $8, %edx +// DIS-NEXT: 11005: 65 8b 0d 00 00 00 00 movl %gs:0, %ecx +// DIS-NEXT: 1100c: 29 d0 subl %edx, %eax +// DIS-NEXT: 1100e: ba 04 00 00 00 movl $4, %edx +// DIS-NEXT: 11013: 65 8b 0d 00 00 00 00 movl %gs:0, %ecx +// DIS-NEXT: 1101a: 29 d0 subl %edx, %eax +// DIS-NEXT: 1101c: 65 8b 0d 00 00 00 00 movl %gs:0, %ecx +// DIS-NEXT: 11023: 8d 81 f8 ff ff ff leal -8(%ecx), %eax +// DIS-NEXT: 11029: 65 8b 0d 00 00 00 00 movl %gs:0, %ecx +// DIS-NEXT: 11030: 8d 81 fc ff ff ff leal -4(%ecx), %eax + +// RELOC: Relocations [ +// RELOC-NEXT: ] + +// DISSHARED: Disassembly of section .text: +// DISSHARED-NEXT: _start: +// DISSHARED-NEXT: 1000: ba 00 00 00 00 movl $0, %edx +// DISSHARED-NEXT: 1005: 65 8b 0d 00 00 00 00 movl %gs:0, %ecx +// DISSHARED-NEXT: 100c: 29 d0 subl %edx, %eax +// DISSHARED-NEXT: 100e: ba 00 00 00 00 movl $0, %edx +// DISSHARED-NEXT: 1013: 65 8b 0d 00 00 00 00 movl %gs:0, %ecx +// DISSHARED-NEXT: 101a: 29 d0 subl %edx, %eax +// DISSHARED-NEXT: 101c: 65 8b 0d 00 00 00 00 movl %gs:0, %ecx +// DISSHARED-NEXT: 1023: 8d 81 00 00 00 00 leal (%ecx), %eax +// DISSHARED-NEXT: 1029: 65 8b 0d 00 00 00 00 movl %gs:0, %ecx +// DISSHARED-NEXT: 1030: 8d 81 00 00 00 00 leal (%ecx), %eax + +// RELOCSHARED: Relocations [ +// RELOCSHARED-NEXT: Section (4) .rel.dyn { +// RELOCSHARED-NEXT: 0x1001 R_386_TLS_TPOFF32 var 0x0 +// RELOCSHARED-NEXT: 0x100F R_386_TLS_TPOFF32 var1 0x0 +// RELOCSHARED-NEXT: 0x1025 R_386_TLS_TPOFF var 0x0 +// RELOCSHARED-NEXT: 0x1032 R_386_TLS_TPOFF var1 0x0 +// RELOCSHARED-NEXT: } +// RELOCSHARED-NEXT: ]