diff options
| -rw-r--r-- | lld/ELF/InputSection.cpp | 15 | ||||
| -rw-r--r-- | lld/ELF/OutputSections.cpp | 17 | ||||
| -rw-r--r-- | lld/ELF/OutputSections.h | 3 | ||||
| -rw-r--r-- | lld/ELF/Target.cpp | 3 | ||||
| -rw-r--r-- | lld/ELF/Target.h | 4 | ||||
| -rw-r--r-- | lld/ELF/Writer.cpp | 9 | ||||
| -rw-r--r-- | lld/test/elf2/tls-dynamic.s | 48 |
7 files changed, 96 insertions, 3 deletions
diff --git a/lld/ELF/InputSection.cpp b/lld/ELF/InputSection.cpp index 1e5f37b86f9..9b9e99c67d3 100644 --- a/lld/ELF/InputSection.cpp +++ b/lld/ELF/InputSection.cpp @@ -90,14 +90,23 @@ void InputSection<ELFT>::relocate( for (const RelType &RI : Rels) { uint32_t SymIndex = RI.getSymbol(Config->Mips64EL); uint32_t Type = RI.getType(Config->Mips64EL); + uint8_t *BufLoc = Buf + RI.r_offset; + uintX_t AddrLoc = BaseAddr + RI.r_offset; + + if (Type == Target->getTlsLocalDynamicReloc()) { + Target->relocateOne(BufLoc, BufEnd, Type, AddrLoc, + Out<ELFT>::Got->getVA() + + Out<ELFT>::LocalModuleTlsIndexOffset + + getAddend<ELFT>(RI)); + continue; + } // Handle relocations for local symbols -- they never get // resolved so we don't allocate a SymbolBody. const Elf_Shdr *SymTab = File.getSymbolTable(); if (SymIndex < SymTab->sh_info) { uintX_t SymVA = getLocalRelTarget(File, RI); - Target->relocateOne(Buf + RI.r_offset, BufEnd, Type, - BaseAddr + RI.r_offset, SymVA); + Target->relocateOne(BufLoc, BufEnd, Type, AddrLoc, SymVA); continue; } @@ -116,7 +125,7 @@ void InputSection<ELFT>::relocate( isa<SharedSymbol<ELFT>>(Body)) { continue; } - Target->relocateOne(Buf + RI.r_offset, BufEnd, Type, BaseAddr + RI.r_offset, + Target->relocateOne(BufLoc, BufEnd, Type, AddrLoc, SymVA + getAddend<ELFT>(RI)); } } diff --git a/lld/ELF/OutputSections.cpp b/lld/ELF/OutputSections.cpp index 0a6c33c1d02..c6b74fffc46 100644 --- a/lld/ELF/OutputSections.cpp +++ b/lld/ELF/OutputSections.cpp @@ -82,6 +82,12 @@ template <class ELFT> void GotSection<ELFT>::addEntry(SymbolBody *Sym) { Entries.push_back(Sym); } +template <class ELFT> uint32_t GotSection<ELFT>::addLocalModuleTlsIndex() { + Entries.push_back(nullptr); + Entries.push_back(nullptr); + return (Entries.size() - 2) * sizeof(uintX_t); +} + template <class ELFT> typename GotSection<ELFT>::uintX_t GotSection<ELFT>::getEntryAddr(const SymbolBody &B) const { @@ -99,6 +105,8 @@ template <class ELFT> void GotSection<ELFT>::writeTo(uint8_t *Buf) { for (const SymbolBody *B : Entries) { uint8_t *Entry = Buf; Buf += sizeof(uintX_t); + if (!B) + continue; // MIPS has special rules to fill up GOT entries. // See "Global Offset Table" in Chapter 5 in the following document // for detailed description: @@ -177,6 +185,15 @@ template <class ELFT> void RelocationSection<ELFT>::writeTo(uint8_t *Buf) { Body = Body->repl(); uint32_t Type = RI.getType(Config->Mips64EL); + + if (Type == Target->getTlsLocalDynamicReloc()) { + P->setSymbolAndType(0, Target->getTlsModuleIndexReloc(), + Config->Mips64EL); + P->r_offset = + Out<ELFT>::Got->getVA() + Out<ELFT>::LocalModuleTlsIndexOffset; + continue; + } + bool NeedsCopy = Body && Target->relocNeedsCopy(Type, *Body); bool NeedsGot = Body && Target->relocNeedsGot(Type, *Body); bool CanBePreempted = canBePreempted(Body, NeedsGot); diff --git a/lld/ELF/OutputSections.h b/lld/ELF/OutputSections.h index 1714f51990c..1afd8bf8631 100644 --- a/lld/ELF/OutputSections.h +++ b/lld/ELF/OutputSections.h @@ -116,6 +116,7 @@ public: void finalize() override; void writeTo(uint8_t *Buf) override; void addEntry(SymbolBody *Sym); + uint32_t addLocalModuleTlsIndex(); bool empty() const { return Entries.empty(); } uintX_t getEntryAddr(const SymbolBody &B) const; @@ -371,6 +372,7 @@ template <class ELFT> struct Out { static SymbolTableSection<ELFT> *DynSymTab; static SymbolTableSection<ELFT> *SymTab; static Elf_Phdr *TlsPhdr; + static uint32_t LocalModuleTlsIndexOffset; }; template <class ELFT> DynamicSection<ELFT> *Out<ELFT>::Dynamic; @@ -391,6 +393,7 @@ template <class ELFT> StringTableSection<ELFT> *Out<ELFT>::StrTab; template <class ELFT> SymbolTableSection<ELFT> *Out<ELFT>::DynSymTab; template <class ELFT> SymbolTableSection<ELFT> *Out<ELFT>::SymTab; template <class ELFT> typename Out<ELFT>::Elf_Phdr *Out<ELFT>::TlsPhdr; +template <class ELFT> uint32_t Out<ELFT>::LocalModuleTlsIndexOffset = -1; } // namespace elf2 } // namespace lld diff --git a/lld/ELF/Target.cpp b/lld/ELF/Target.cpp index f01c7299ec8..34e567052d5 100644 --- a/lld/ELF/Target.cpp +++ b/lld/ELF/Target.cpp @@ -215,6 +215,8 @@ X86_64TargetInfo::X86_64TargetInfo() { GotRefReloc = R_X86_64_PC32; PltReloc = R_X86_64_JUMP_SLOT; RelativeReloc = R_X86_64_RELATIVE; + TlsLocalDynamicReloc = R_X86_64_TLSLD; + TlsModuleIndexReloc = R_X86_64_DTPMOD64; LazyRelocations = true; PltEntrySize = 16; PltZeroEntrySize = 16; @@ -330,6 +332,7 @@ void X86_64TargetInfo::relocateOne(uint8_t *Loc, uint8_t *BufEnd, uint32_t Type, case R_X86_64_PC32: case R_X86_64_GOTPCREL: case R_X86_64_PLT32: + case R_X86_64_TLSLD: write32le(Loc, SA - P); break; case R_X86_64_64: diff --git a/lld/ELF/Target.h b/lld/ELF/Target.h index 71ef7eb8584..43c4d49e0d4 100644 --- a/lld/ELF/Target.h +++ b/lld/ELF/Target.h @@ -29,6 +29,8 @@ public: unsigned getPltReloc() const { return PltReloc; } unsigned getGotRefReloc() const { return GotRefReloc; } unsigned getRelativeReloc() const { return RelativeReloc; } + unsigned getTlsLocalDynamicReloc() const { return TlsLocalDynamicReloc; } + unsigned getTlsModuleIndexReloc() const { return TlsModuleIndexReloc; } unsigned getPltZeroEntrySize() const { return PltZeroEntrySize; } unsigned getPltEntrySize() const { return PltEntrySize; } bool supportsLazyRelocations() const { return LazyRelocations; } @@ -67,6 +69,8 @@ protected: unsigned GotReloc; unsigned PltReloc; unsigned RelativeReloc; + unsigned TlsLocalDynamicReloc = 0; + unsigned TlsModuleIndexReloc; unsigned PltEntrySize = 8; unsigned PltZeroEntrySize = 0; unsigned GotHeaderEntriesNum = 0; diff --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp index 5bed591ab9e..8739a33325c 100644 --- a/lld/ELF/Writer.cpp +++ b/lld/ELF/Writer.cpp @@ -190,6 +190,15 @@ void Writer<ELFT>::scanRelocs( SymbolBody *Body = File.getSymbolBody(SymIndex); uint32_t Type = RI.getType(Config->Mips64EL); + if (Type == Target->getTlsLocalDynamicReloc()) { + if (Out<ELFT>::LocalModuleTlsIndexOffset == uint32_t(-1)) { + Out<ELFT>::LocalModuleTlsIndexOffset = + Out<ELFT>::Got->addLocalModuleTlsIndex(); + Out<ELFT>::RelaDyn->addReloc({C, RI}); + } + continue; + } + // Set "used" bit for --as-needed. if (Body && Body->isUndefined() && !Body->isWeak()) if (auto *S = dyn_cast<SharedSymbol<ELFT>>(Body->repl())) diff --git a/lld/test/elf2/tls-dynamic.s b/lld/test/elf2/tls-dynamic.s new file mode 100644 index 00000000000..4cadfc69aa9 --- /dev/null +++ b/lld/test/elf2/tls-dynamic.s @@ -0,0 +1,48 @@ +// REQUIRES: x86 +// RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t +// RUN: ld.lld2 -shared %t -o %tout +// RUN: llvm-readobj -sections -relocations %tout | FileCheck %s +// RUN: llvm-objdump -d %tout | FileCheck %s --check-prefix=DIS + + leaq a@tlsld(%rip), %rdi + callq __tls_get_addr@PLT + leaq b@tlsld(%rip), %rdi + callq __tls_get_addr@PLT + + .global a + .section .tbss,"awT",@nobits + .align 4 +a: + .long 0 + + .global b + .section .tbss,"awT",@nobits + .align 4 +b: + .long 0 + +// Get the address of the got, and check that it has two entries. + +// CHECK: Sections [ +// CHECK: Name: .got +// CHECK-NEXT: Type: SHT_PROGBITS +// CHECK-NEXT: Flags [ +// CHECK-NEXT: SHF_ALLOC +// CHECK-NEXT: SHF_WRITE +// CHECK-NEXT: ] +// CHECK-NEXT: Address: 0x20D0 +// CHECK-NEXT: Offset: +// CHECK-NEXT: Size: 16 + +// CHECK: Relocations [ +// CHECK: Section ({{.+}}) .rela.dyn { +// CHECK-NEXT: 0x20D0 R_X86_64_DTPMOD64 - 0x0 +// CHECK-NEXT: } + +// 4297 = (0x20D0 + -4) - (0x1000 + 3) // PC relative offset to got entry. + +// DIS: Disassembly of section .text: +// DIS-NEXT: .text: +// DIS-NEXT: 1000: {{.+}} leaq 4297(%rip), %rdi +// DIS-NEXT: 1007: {{.+}} callq +// DIS-NEXT: 100c: {{.+}} leaq 4285(%rip), %rdi |

