From 74031ba1e9470d9b108aa5256d326c5b0053b004 Mon Sep 17 00:00:00 2001 From: Rafael Espindola Date: Thu, 7 Apr 2016 15:20:56 +0000 Subject: [PATCH] Simplify dynamic relocation creation. The position of a relocation can always be expressed as an offset in an output section. llvm-svn: 265682 --- lld/ELF/OutputSections.cpp | 27 +++++++-------------------- lld/ELF/OutputSections.h | 24 ++++-------------------- lld/ELF/Symbols.cpp | 25 +++++++++++++++++++++---- lld/ELF/Symbols.h | 2 ++ lld/ELF/Writer.cpp | 36 +++++++++++++++++++++--------------- 5 files changed, 55 insertions(+), 59 deletions(-) diff --git a/lld/ELF/OutputSections.cpp b/lld/ELF/OutputSections.cpp index 243f571..cb82e22 100644 --- a/lld/ELF/OutputSections.cpp +++ b/lld/ELF/OutputSections.cpp @@ -195,6 +195,12 @@ GotSection::getGlobalDynAddr(const SymbolBody &B) const { } template +typename GotSection::uintX_t +GotSection::getGlobalDynOffset(const SymbolBody &B) const { + return B.GlobalDynIndex * sizeof(uintX_t); +} + +template const SymbolBody *GotSection::getMipsFirstGlobalEntry() const { return Entries.empty() ? nullptr : Entries.front(); } @@ -297,25 +303,6 @@ void RelocationSection::addReloc(const DynamicReloc &Reloc) { Relocs.push_back(Reloc); } -template -typename ELFT::uint DynamicReloc::getOffset() const { - switch (OKind) { - case Off_GTlsIndex: - return Out::Got->getGlobalDynAddr(*Sym); - case Off_GTlsOffset: - return Out::Got->getGlobalDynAddr(*Sym) + sizeof(uintX_t); - case Off_LTlsIndex: - return Out::Got->getTlsIndexVA(); - case Off_Sec: - return OffsetInSec + OffsetSec->getVA(); - case Off_Got: - return Sym->getGotVA(); - case Off_GotPlt: - return Sym->getGotPltVA(); - } - llvm_unreachable("invalid offset kind"); -} - template void RelocationSection::writeTo(uint8_t *Buf) { for (const DynamicReloc &Rel : Relocs) { auto *P = reinterpret_cast(Buf); @@ -324,7 +311,7 @@ template void RelocationSection::writeTo(uint8_t *Buf) { if (Config->Rela) P->r_addend = Rel.UseSymVA ? Sym->getVA(Rel.Addend) : Rel.Addend; - P->r_offset = Rel.getOffset(); + P->r_offset = Rel.OffsetInSec + Rel.OffsetSec->getVA(); uint32_t SymIdx = (!Rel.UseSymVA && Sym) ? Sym->DynsymIndex : 0; P->setSymbolAndType(SymIdx, Rel.Type, Config->Mips64EL); } diff --git a/lld/ELF/OutputSections.h b/lld/ELF/OutputSections.h index 7abdd5b..aa552dc 100644 --- a/lld/ELF/OutputSections.h +++ b/lld/ELF/OutputSections.h @@ -113,6 +113,7 @@ public: uintX_t getMipsLocalFullAddr(const SymbolBody &B); uintX_t getMipsLocalPageAddr(uintX_t Addr); uintX_t getGlobalDynAddr(const SymbolBody &B) const; + uintX_t getGlobalDynOffset(const SymbolBody &B) const; uintX_t getNumEntries() const { return Entries.size(); } // Returns the symbol which corresponds to the first entry of the global part @@ -126,6 +127,7 @@ public: unsigned getMipsLocalEntriesNum() const; uintX_t getTlsIndexVA() { return Base::getVA() + TlsIndexOff; } + uint32_t getTlsIndexOff() { return TlsIndexOff; } private: std::vector Entries; @@ -172,35 +174,17 @@ template struct DynamicReloc { typedef typename ELFT::uint uintX_t; uint32_t Type; - // Where the relocation is. - enum OffsetKind { - Off_Got, // The got entry of Sym. - Off_GotPlt, // The got.plt entry of Sym. - Off_Sec, // The final position of the given input section and offset. - Off_LTlsIndex, // The local tls index. - Off_GTlsIndex, // The global tls index of Sym. - Off_GTlsOffset // The global tls offset of Sym. - } OKind; - SymbolBody *Sym = nullptr; OutputSectionBase *OffsetSec = nullptr; uintX_t OffsetInSec = 0; bool UseSymVA = false; uintX_t Addend = 0; - DynamicReloc(uint32_t Type, OffsetKind OKind, SymbolBody *Sym) - : Type(Type), OKind(OKind), Sym(Sym) {} - - DynamicReloc(uint32_t Type, OffsetKind OKind, bool UseSymVA, SymbolBody *Sym) - : Type(Type), OKind(OKind), Sym(Sym), UseSymVA(UseSymVA) {} - DynamicReloc(uint32_t Type, OutputSectionBase *OffsetSec, uintX_t OffsetInSec, bool UseSymVA, SymbolBody *Sym, uintX_t Addend) - : Type(Type), OKind(Off_Sec), Sym(Sym), OffsetSec(OffsetSec), - OffsetInSec(OffsetInSec), UseSymVA(UseSymVA), Addend(Addend) {} - - uintX_t getOffset() const; + : Type(Type), Sym(Sym), OffsetSec(OffsetSec), OffsetInSec(OffsetInSec), + UseSymVA(UseSymVA), Addend(Addend) {} }; template diff --git a/lld/ELF/Symbols.cpp b/lld/ELF/Symbols.cpp index 95f5b9b..5ce5738 100644 --- a/lld/ELF/Symbols.cpp +++ b/lld/ELF/Symbols.cpp @@ -150,13 +150,20 @@ typename ELFT::uint SymbolBody::getVA(typename ELFT::uint Addend) const { } template typename ELFT::uint SymbolBody::getGotVA() const { - return Out::Got->getVA() + - (Out::Got->getMipsLocalEntriesNum() + GotIndex) * - sizeof(typename ELFT::uint); + return Out::Got->getVA() + getGotOffset(); +} + +template typename ELFT::uint SymbolBody::getGotOffset() const { + return (Out::Got->getMipsLocalEntriesNum() + GotIndex) * + sizeof(typename ELFT::uint); } template typename ELFT::uint SymbolBody::getGotPltVA() const { - return Out::GotPlt->getVA() + GotPltIndex * sizeof(typename ELFT::uint); + return Out::GotPlt->getVA() + getGotPltOffset(); +} + +template typename ELFT::uint SymbolBody::getGotPltOffset() const { + return GotPltIndex * sizeof(typename ELFT::uint); } template typename ELFT::uint SymbolBody::getPltVA() const { @@ -340,11 +347,21 @@ template uint32_t SymbolBody::template getGotVA() const; template uint64_t SymbolBody::template getGotVA() const; template uint64_t SymbolBody::template getGotVA() const; +template uint32_t SymbolBody::template getGotOffset() const; +template uint32_t SymbolBody::template getGotOffset() const; +template uint64_t SymbolBody::template getGotOffset() const; +template uint64_t SymbolBody::template getGotOffset() const; + template uint32_t SymbolBody::template getGotPltVA() const; template uint32_t SymbolBody::template getGotPltVA() const; template uint64_t SymbolBody::template getGotPltVA() const; template uint64_t SymbolBody::template getGotPltVA() const; +template uint32_t SymbolBody::template getGotPltOffset() const; +template uint32_t SymbolBody::template getGotPltOffset() const; +template uint64_t SymbolBody::template getGotPltOffset() const; +template uint64_t SymbolBody::template getGotPltOffset() const; + template uint32_t SymbolBody::template getPltVA() const; template uint32_t SymbolBody::template getPltVA() const; template uint64_t SymbolBody::template getPltVA() const; diff --git a/lld/ELF/Symbols.h b/lld/ELF/Symbols.h index 35f146d..e4dcb1c 100644 --- a/lld/ELF/Symbols.h +++ b/lld/ELF/Symbols.h @@ -104,7 +104,9 @@ public: template typename ELFT::uint getVA(typename ELFT::uint Addend = 0) const; + template typename ELFT::uint getGotOffset() const; template typename ELFT::uint getGotVA() const; + template typename ELFT::uint getGotPltOffset() const; template typename ELFT::uint getGotPltVA() const; template typename ELFT::uint getPltVA() const; template typename ELFT::uint getThunkVA() const; diff --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp index 626e39a..ff197ce 100644 --- a/lld/ELF/Writer.cpp +++ b/lld/ELF/Writer.cpp @@ -266,13 +266,14 @@ template struct DenseMapInfo> { template static unsigned handleTlsRelocation(uint32_t Type, SymbolBody &Body, InputSectionBase &C, RelT &RI) { + typedef typename ELFT::uint uintX_t; if (Target->pointsToLocalDynamicGotEntry(Type)) { if (Target->canRelaxTls(Type, nullptr)) return 2; if (Out::Got->addTlsIndex()) - Out::RelaDyn->addReloc({Target->TlsModuleIndexRel, - DynamicReloc::Off_LTlsIndex, - nullptr}); + Out::RelaDyn->addReloc({Target->TlsModuleIndexRel, Out::Got, + Out::Got->getTlsIndexOff(), false, + nullptr, 0}); return 1; } @@ -282,11 +283,12 @@ static unsigned handleTlsRelocation(uint32_t Type, SymbolBody &Body, if (Target->isTlsGlobalDynamicRel(Type)) { if (!Target->canRelaxTls(Type, &Body)) { if (Out::Got->addDynTlsEntry(Body)) { - Out::RelaDyn->addReloc({Target->TlsModuleIndexRel, - DynamicReloc::Off_GTlsIndex, - &Body}); + uintX_t Off = Out::Got->getGlobalDynOffset(Body); Out::RelaDyn->addReloc( - {Target->TlsOffsetRel, DynamicReloc::Off_GTlsOffset, &Body}); + {Target->TlsModuleIndexRel, Out::Got, Off, false, &Body, 0}); + Out::RelaDyn->addReloc({Target->TlsOffsetRel, Out::Got, + Off + (uintX_t)sizeof(uintX_t), false, + &Body, 0}); } return 1; } @@ -294,8 +296,9 @@ static unsigned handleTlsRelocation(uint32_t Type, SymbolBody &Body, return 2; if (!Body.isInGot()) { Out::Got->addEntry(Body); - Out::RelaDyn->addReloc( - {Target->TlsGotRel, DynamicReloc::Off_Got, false, &Body}); + Out::RelaDyn->addReloc({Target->TlsGotRel, Out::Got, + Body.getGotOffset(), false, &Body, + 0}); } return 2; } @@ -400,14 +403,16 @@ void Writer::scanRelocs(InputSectionBase &C, ArrayRef Rels) { if (Target->UseLazyBinding) { Out::GotPlt->addEntry(Body); - Out::RelaPlt->addReloc( - {Rel, DynamicReloc::Off_GotPlt, !Preemptible, &Body}); + Out::RelaPlt->addReloc({Rel, Out::GotPlt, + Body.getGotPltOffset(), + !Preemptible, &Body, 0}); } else { if (Body.isInGot()) continue; Out::Got->addEntry(Body); - Out::RelaDyn->addReloc( - {Rel, DynamicReloc::Off_Got, !Preemptible, &Body}); + Out::RelaDyn->addReloc({Rel, Out::Got, + Body.getGotOffset(), !Preemptible, + &Body, 0}); } continue; } @@ -434,8 +439,9 @@ void Writer::scanRelocs(InputSectionBase &C, ArrayRef Rels) { DynType = Target->GotRel; else DynType = Target->RelativeRel; - Out::RelaDyn->addReloc( - {DynType, DynamicReloc::Off_Got, !Preemptible, &Body}); + Out::RelaDyn->addReloc({DynType, Out::Got, + Body.getGotOffset(), !Preemptible, + &Body, 0}); } continue; } -- 2.7.4