diff options
Diffstat (limited to 'lld/ELF/OutputSections.cpp')
-rw-r--r-- | lld/ELF/OutputSections.cpp | 23 |
1 files changed, 21 insertions, 2 deletions
diff --git a/lld/ELF/OutputSections.cpp b/lld/ELF/OutputSections.cpp index 1c8311c9864..9def8708595 100644 --- a/lld/ELF/OutputSections.cpp +++ b/lld/ELF/OutputSections.cpp @@ -80,6 +80,9 @@ GotSection<ELFT>::GotSection() template <class ELFT> void GotSection<ELFT>::addEntry(SymbolBody *Sym) { Sym->GotIndex = Target->getGotHeaderEntriesNum() + Entries.size(); Entries.push_back(Sym); + // Global Dynamic TLS entries take two GOT slots. + if (Sym->isTLS()) + Entries.push_back(nullptr); } template <class ELFT> uint32_t GotSection<ELFT>::addLocalModuleTlsIndex() { @@ -187,8 +190,13 @@ template <class ELFT> void RelocationSection<ELFT>::writeTo(uint8_t *Buf) { auto *P = reinterpret_cast<Elf_Rel *>(Buf); Buf += EntrySize; - InputSectionBase<ELFT> &C = Rel.C; - const Elf_Rel &RI = Rel.RI; + // Skip placeholder for global dynamic TLS relocation pair. It was already + // handled by the previous relocation. + if (!Rel.C || !Rel.RI) + continue; + + InputSectionBase<ELFT> &C = *Rel.C; + const Elf_Rel &RI = *Rel.RI; uint32_t SymIndex = RI.getSymbol(Config->Mips64EL); const ObjectFile<ELFT> &File = *C.getFile(); SymbolBody *Body = File.getSymbolBody(SymIndex); @@ -205,6 +213,17 @@ template <class ELFT> void RelocationSection<ELFT>::writeTo(uint8_t *Buf) { continue; } + if (Body && Type == Target->getTlsGlobalDynamicReloc()) { + P->setSymbolAndType(Body->getDynamicSymbolTableIndex(), + Target->getTlsModuleIndexReloc(), Config->Mips64EL); + P->r_offset = Out<ELFT>::Got->getEntryAddr(*Body); + auto *PNext = reinterpret_cast<Elf_Rel *>(Buf); + PNext->setSymbolAndType(Body->getDynamicSymbolTableIndex(), + Target->getTlsOffsetReloc(), Config->Mips64EL); + PNext->r_offset = Out<ELFT>::Got->getEntryAddr(*Body) + sizeof(uintX_t); + continue; + } + bool NeedsCopy = Body && Target->relocNeedsCopy(Type, *Body); bool NeedsGot = Body && Target->relocNeedsGot(Type, *Body); bool CanBePreempted = canBePreempted(Body, NeedsGot); |