summaryrefslogtreecommitdiffstats
path: root/lld/ELF/OutputSections.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lld/ELF/OutputSections.cpp')
-rw-r--r--lld/ELF/OutputSections.cpp23
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);
OpenPOWER on IntegriCloud