Index: lld/trunk/ELF/InputSection.cpp =================================================================== --- lld/trunk/ELF/InputSection.cpp +++ lld/trunk/ELF/InputSection.cpp @@ -132,7 +132,7 @@ if (Target->isTlsGlobalDynamicReloc(Type) && !Target->isTlsOptimized(Type, &Body)) { Target->relocateOne(BufLoc, BufEnd, Type, AddrLoc, - Out::Got->getEntryAddr(Body) + + Out::Got->getGlobalDynAddr(Body) + getAddend(RI)); continue; } Index: lld/trunk/ELF/OutputSections.h =================================================================== --- lld/trunk/ELF/OutputSections.h +++ lld/trunk/ELF/OutputSections.h @@ -118,10 +118,11 @@ void finalize() override; void writeTo(uint8_t *Buf) override; void addEntry(SymbolBody *Sym); - void addDynTlsEntry(SymbolBody *Sym); + bool addDynTlsEntry(SymbolBody *Sym); bool addLocalModelTlsIndex(); bool empty() const { return Entries.empty(); } uintX_t getEntryAddr(const SymbolBody &B) const; + uintX_t getGlobalDynAddr(const SymbolBody &B) const; // Returns the symbol which corresponds to the first entry of the global part // of GOT on MIPS platform. It is required to fill up MIPS-specific dynamic Index: lld/trunk/ELF/OutputSections.cpp =================================================================== --- lld/trunk/ELF/OutputSections.cpp +++ lld/trunk/ELF/OutputSections.cpp @@ -80,11 +80,14 @@ Entries.push_back(Sym); } -template void GotSection::addDynTlsEntry(SymbolBody *Sym) { - Sym->GotIndex = Target->getGotHeaderEntriesNum() + Entries.size(); +template bool GotSection::addDynTlsEntry(SymbolBody *Sym) { + if (Sym->hasGlobalDynIndex()) + return false; + Sym->GlobalDynIndex = Target->getGotHeaderEntriesNum() + Entries.size(); // Global Dynamic TLS entries take two GOT slots. Entries.push_back(Sym); Entries.push_back(nullptr); + return true; } template bool GotSection::addLocalModelTlsIndex() { @@ -103,6 +106,12 @@ } template +typename GotSection::uintX_t +GotSection::getGlobalDynAddr(const SymbolBody &B) const { + return this->getVA() + B.GlobalDynIndex * sizeof(uintX_t); +} + +template const SymbolBody *GotSection::getMipsFirstGlobalEntry() const { return Entries.empty() ? nullptr : Entries.front(); } @@ -211,10 +220,10 @@ if (Body && Target->isTlsGlobalDynamicReloc(Type)) { P->setSymbolAndType(Body->getDynamicSymbolTableIndex(), Target->getTlsModuleIndexReloc(), Config->Mips64EL); - P->r_offset = Out::Got->getEntryAddr(*Body); + P->r_offset = Out::Got->getGlobalDynAddr(*Body); N->setSymbolAndType(Body->getDynamicSymbolTableIndex(), Target->getTlsOffsetReloc(), Config->Mips64EL); - N->r_offset = Out::Got->getEntryAddr(*Body) + sizeof(uintX_t); + N->r_offset = Out::Got->getGlobalDynAddr(*Body) + sizeof(uintX_t); return true; } return false; Index: lld/trunk/ELF/Symbols.h =================================================================== --- lld/trunk/ELF/Symbols.h +++ lld/trunk/ELF/Symbols.h @@ -90,9 +90,11 @@ } void setDynamicSymbolTableIndex(unsigned V) { DynamicSymbolTableIndex = V; } + uint32_t GlobalDynIndex = -1; uint32_t GotIndex = -1; uint32_t GotPltIndex = -1; uint32_t PltIndex = -1; + bool hasGlobalDynIndex() { return GlobalDynIndex != uint32_t(-1); } bool isInGot() const { return GotIndex != -1U; } bool isInGotPlt() const { return GotPltIndex != -1U; } bool isInPlt() const { return PltIndex != -1U; } Index: lld/trunk/ELF/Writer.cpp =================================================================== --- lld/trunk/ELF/Writer.cpp +++ lld/trunk/ELF/Writer.cpp @@ -221,12 +221,11 @@ if (Body && Body->isTLS() && Target->isTlsGlobalDynamicReloc(Type)) { if (Target->isTlsOptimized(Type, Body)) continue; - if (Body->isInGot()) - continue; - Out::Got->addDynTlsEntry(Body); - Out::RelaDyn->addReloc({&C, &RI}); - Out::RelaDyn->addReloc({nullptr, nullptr}); - Body->setUsedInDynamicReloc(); + if (Out::Got->addDynTlsEntry(Body)) { + Out::RelaDyn->addReloc({&C, &RI}); + Out::RelaDyn->addReloc({nullptr, nullptr}); + Body->setUsedInDynamicReloc(); + } continue; } Index: lld/trunk/test/ELF/tls-dynamic.s =================================================================== --- lld/trunk/test/ELF/tls-dynamic.s +++ lld/trunk/test/ELF/tls-dynamic.s @@ -15,6 +15,9 @@ rex64 callq __tls_get_addr@PLT leaq c@dtpoff(%rax), %rcx + // Initial Exec Model Code Sequence, II + movq c@gottpoff(%rip),%rax + movq %fs:(%rax),%rax .global a .hidden a @@ -44,18 +47,20 @@ // CHECK-NEXT: ] // CHECK-NEXT: Address: 0x20D0 // CHECK-NEXT: Offset: -// CHECK-NEXT: Size: 32 +// CHECK-NEXT: Size: 40 // CHECK: Relocations [ // CHECK: Section ({{.+}}) .rela.dyn { // CHECK-NEXT: 0x20D0 R_X86_64_DTPMOD64 - 0x0 // CHECK-NEXT: 0x20E0 R_X86_64_DTPMOD64 c 0x0 // CHECK-NEXT: 0x20E8 R_X86_64_DTPOFF64 c 0x0 +// CHECK-NEXT: 0x20F0 R_X86_64_TPOFF64 c 0x0 // CHECK-NEXT: } // 4297 = (0x20D0 + -4) - (0x1000 + 3) // PC relative offset to got entry. // 4285 = (0x20D0 + -4) - (0x100c + 3) // PC relative offset to got entry. // 4267 = (0x20E0 + -4) - (0x102e + 3) // PC relative offset to got entry. +// 4263 = (0x20F0 + -4) - (0x1042 + 3) // PC relative offset to got entry. // DIS: Disassembly of section .text: // DIS-NEXT: .text: @@ -72,3 +77,5 @@ // DIS-NEXT: 102e: {{.+}} leaq 4267(%rip), %rdi // DIS-NEXT: 1035: {{.+}} callq // DIS-NEXT: 103b: {{.+}} leaq 8(%rax), %rcx +// DIS-NEXT: 1042: {{.+}} movq 4263(%rip), %rax +// DIS-NEXT: 1049: {{.+}} movq %fs:(%rax), %rax