diff options
-rw-r--r-- | lld/ELF/InputSection.cpp | 16 | ||||
-rw-r--r-- | lld/ELF/OutputSections.cpp | 117 | ||||
-rw-r--r-- | lld/ELF/OutputSections.h | 62 | ||||
-rw-r--r-- | lld/ELF/Relocations.cpp | 46 | ||||
-rw-r--r-- | lld/ELF/SyntheticSections.cpp | 105 | ||||
-rw-r--r-- | lld/ELF/SyntheticSections.h | 59 | ||||
-rw-r--r-- | lld/ELF/Writer.cpp | 19 |
7 files changed, 215 insertions, 209 deletions
diff --git a/lld/ELF/InputSection.cpp b/lld/ELF/InputSection.cpp index 1cfb1f93629..28e1d71402d 100644 --- a/lld/ELF/InputSection.cpp +++ b/lld/ELF/InputSection.cpp @@ -104,8 +104,12 @@ template <class ELFT> typename ELFT::uint InputSectionBase<ELFT>::getOffset(uintX_t Offset) const { switch (kind()) { case Regular: - case Synthetic: return cast<InputSection<ELFT>>(this)->OutSecOff + Offset; + case Synthetic: + // For synthetic sections we treat offset -1 as the end of the section. + // The same approach is used for synthetic symbols (DefinedSynthetic). + return cast<InputSection<ELFT>>(this)->OutSecOff + + (Offset == uintX_t(-1) ? getSize() : Offset); case EHFrame: // The file crtbeginT.o has relocations pointing to the start of an empty // .eh_frame that is known to be the first in the link. It does that to @@ -525,6 +529,11 @@ template <class ELFT> void InputSection<ELFT>::writeTo(uint8_t *Buf) { if (this->Type == SHT_NOBITS) return; + if (auto *S = dyn_cast<SyntheticSection<ELFT>>(this)) { + S->writeTo(Buf); + return; + } + // If -r is given, then an InputSection may be a relocation section. if (this->Type == SHT_RELA) { copyRelocations(Buf + OutSecOff, this->template getDataAs<Elf_Rela>()); @@ -535,11 +544,6 @@ template <class ELFT> void InputSection<ELFT>::writeTo(uint8_t *Buf) { return; } - if (auto *S = dyn_cast<SyntheticSection<ELFT>>(this)) { - S->writeTo(Buf); - return; - } - // Copy section contents from source object file to output file. ArrayRef<uint8_t> Data = this->Data; memcpy(Buf + OutSecOff, Data.data(), Data.size()); diff --git a/lld/ELF/OutputSections.cpp b/lld/ELF/OutputSections.cpp index e2c0afb00dc..dfbde2f9556 100644 --- a/lld/ELF/OutputSections.cpp +++ b/lld/ELF/OutputSections.cpp @@ -132,7 +132,7 @@ template <class ELFT> void PltSection<ELFT>::writeTo(uint8_t *Buf) { template <class ELFT> void PltSection<ELFT>::addEntry(SymbolBody &Sym) { Sym.PltIndex = Entries.size(); - unsigned RelOff = Out<ELFT>::RelaPlt->getRelocOffset(); + unsigned RelOff = In<ELFT>::RelaPlt->getRelocOffset(); Entries.push_back(std::make_pair(&Sym, RelOff)); } @@ -141,69 +141,6 @@ template <class ELFT> void PltSection<ELFT>::finalize() { } template <class ELFT> -RelocationSection<ELFT>::RelocationSection(StringRef Name, bool Sort) - : OutputSectionBase(Name, Config->Rela ? SHT_RELA : SHT_REL, SHF_ALLOC), - Sort(Sort) { - this->Entsize = Config->Rela ? sizeof(Elf_Rela) : sizeof(Elf_Rel); - this->Addralign = sizeof(uintX_t); -} - -template <class ELFT> -void RelocationSection<ELFT>::addReloc(const DynamicReloc<ELFT> &Reloc) { - if (Reloc.Type == Target->RelativeRel) - ++NumRelativeRelocs; - Relocs.push_back(Reloc); -} - -template <class ELFT, class RelTy> -static bool compRelocations(const RelTy &A, const RelTy &B) { - bool AIsRel = A.getType(Config->Mips64EL) == Target->RelativeRel; - bool BIsRel = B.getType(Config->Mips64EL) == Target->RelativeRel; - if (AIsRel != BIsRel) - return AIsRel; - - return A.getSymbol(Config->Mips64EL) < B.getSymbol(Config->Mips64EL); -} - -template <class ELFT> void RelocationSection<ELFT>::writeTo(uint8_t *Buf) { - uint8_t *BufBegin = Buf; - for (const DynamicReloc<ELFT> &Rel : Relocs) { - auto *P = reinterpret_cast<Elf_Rela *>(Buf); - Buf += Config->Rela ? sizeof(Elf_Rela) : sizeof(Elf_Rel); - - if (Config->Rela) - P->r_addend = Rel.getAddend(); - P->r_offset = Rel.getOffset(); - if (Config->EMachine == EM_MIPS && Rel.getInputSec() == In<ELFT>::Got) - // Dynamic relocation against MIPS GOT section make deal TLS entries - // allocated in the end of the GOT. We need to adjust the offset to take - // in account 'local' and 'global' GOT entries. - P->r_offset += In<ELFT>::Got->getMipsTlsOffset(); - P->setSymbolAndType(Rel.getSymIndex(), Rel.Type, Config->Mips64EL); - } - - if (Sort) { - if (Config->Rela) - std::stable_sort((Elf_Rela *)BufBegin, - (Elf_Rela *)BufBegin + Relocs.size(), - compRelocations<ELFT, Elf_Rela>); - else - std::stable_sort((Elf_Rel *)BufBegin, (Elf_Rel *)BufBegin + Relocs.size(), - compRelocations<ELFT, Elf_Rel>); - } -} - -template <class ELFT> unsigned RelocationSection<ELFT>::getRelocOffset() { - return this->Entsize * Relocs.size(); -} - -template <class ELFT> void RelocationSection<ELFT>::finalize() { - this->Link = Out<ELFT>::DynSymTab ? Out<ELFT>::DynSymTab->SectionIndex - : Out<ELFT>::SymTab->SectionIndex; - this->Size = Relocs.size() * this->Entsize; -} - -template <class ELFT> HashTableSection<ELFT>::HashTableSection() : OutputSectionBase(".hash", SHT_HASH, SHF_ALLOC) { this->Entsize = sizeof(Elf_Word); @@ -463,20 +400,21 @@ OutputSection<ELFT>::OutputSection(StringRef Name, uint32_t Type, uintX_t Flags) } template <class ELFT> void OutputSection<ELFT>::finalize() { + if (!Config->Relocatable) { + // SHF_LINK_ORDER only has meaning in relocatable objects + this->Flags &= ~SHF_LINK_ORDER; + return; + } + uint32_t Type = this->Type; - if (this->Flags & SHF_LINK_ORDER) { - if (!Config->Relocatable) { - // SHF_LINK_ORDER only has meaning in relocatable objects - this->Flags &= ~SHF_LINK_ORDER; - } else if (!this->Sections.empty()) { - // When doing a relocatable link we must preserve the link order - // dependency of sections with the SHF_LINK_ORDER flag. The dependency - // is indicated by the sh_link field. We need to translate the - // InputSection sh_link to the OutputSection sh_link, all InputSections - // in the OutputSection have the same dependency. - if (auto *D = this->Sections.front()->getLinkOrderDep()) - this->Link = D->OutSec->SectionIndex; - } + if ((this->Flags & SHF_LINK_ORDER) && !this->Sections.empty()) { + // When doing a relocatable link we must preserve the link order + // dependency of sections with the SHF_LINK_ORDER flag. The dependency + // is indicated by the sh_link field. We need to translate the + // InputSection sh_link to the OutputSection sh_link, all InputSections + // in the OutputSection have the same dependency. + if (auto *D = this->Sections.front()->getLinkOrderDep()) + this->Link = D->OutSec->SectionIndex; } if (Type != SHT_RELA && Type != SHT_REL) @@ -881,26 +819,6 @@ template <class ELFT> void MergeOutputSection<ELFT>::finalizePieces() { } template <class ELFT> -typename ELFT::uint DynamicReloc<ELFT>::getOffset() const { - if (OutputSec) - return OutputSec->Addr + OffsetInSec; - return InputSec->OutSec->Addr + InputSec->getOffset(OffsetInSec); -} - -template <class ELFT> -typename ELFT::uint DynamicReloc<ELFT>::getAddend() const { - if (UseSymVA) - return Sym->getVA<ELFT>(Addend); - return Addend; -} - -template <class ELFT> uint32_t DynamicReloc<ELFT>::getSymIndex() const { - if (Sym && !UseSymVA) - return Sym->DynsymIndex; - return 0; -} - -template <class ELFT> SymbolTableSection<ELFT>::SymbolTableSection( StringTableSection<ELFT> &StrTabSec) : OutputSectionBase(StrTabSec.isDynamic() ? ".dynsym" : ".symtab", @@ -1350,11 +1268,6 @@ template class PltSection<ELF32BE>; template class PltSection<ELF64LE>; template class PltSection<ELF64BE>; -template class RelocationSection<ELF32LE>; -template class RelocationSection<ELF32BE>; -template class RelocationSection<ELF64LE>; -template class RelocationSection<ELF64BE>; - template class GnuHashTableSection<ELF32LE>; template class GnuHashTableSection<ELF32BE>; template class GnuHashTableSection<ELF64LE>; diff --git a/lld/ELF/OutputSections.h b/lld/ELF/OutputSections.h index df72e755425..0fe9328c8bf 100644 --- a/lld/ELF/OutputSections.h +++ b/lld/ELF/OutputSections.h @@ -52,7 +52,6 @@ public: Merge, Plt, Regular, - Reloc, SymTable, VersDef, VersNeed, @@ -156,39 +155,6 @@ private: std::vector<std::pair<const SymbolBody *, unsigned>> Entries; }; -template <class ELFT> class DynamicReloc { - typedef typename ELFT::uint uintX_t; - -public: - DynamicReloc(uint32_t Type, const InputSectionBase<ELFT> *InputSec, - uintX_t OffsetInSec, bool UseSymVA, SymbolBody *Sym, - uintX_t Addend) - : Type(Type), Sym(Sym), InputSec(InputSec), OffsetInSec(OffsetInSec), - UseSymVA(UseSymVA), Addend(Addend) {} - - DynamicReloc(uint32_t Type, const OutputSectionBase *OutputSec, - uintX_t OffsetInSec, bool UseSymVA, SymbolBody *Sym, - uintX_t Addend) - : Type(Type), Sym(Sym), OutputSec(OutputSec), OffsetInSec(OffsetInSec), - UseSymVA(UseSymVA), Addend(Addend) {} - - uintX_t getOffset() const; - uintX_t getAddend() const; - uint32_t getSymIndex() const; - const OutputSectionBase *getOutputSec() const { return OutputSec; } - const InputSectionBase<ELFT> *getInputSec() const { return InputSec; } - - uint32_t Type; - -private: - SymbolBody *Sym; - const InputSectionBase<ELFT> *InputSec = nullptr; - const OutputSectionBase *OutputSec = nullptr; - uintX_t OffsetInSec; - bool UseSymVA; - uintX_t Addend; -}; - struct SymbolTableEntry { SymbolBody *Symbol; size_t StrTabOffset; @@ -305,30 +271,6 @@ public: } }; -template <class ELFT> class RelocationSection final : public OutputSectionBase { - typedef typename ELFT::Rel Elf_Rel; - typedef typename ELFT::Rela Elf_Rela; - typedef typename ELFT::uint uintX_t; - -public: - RelocationSection(StringRef Name, bool Sort); - void addReloc(const DynamicReloc<ELFT> &Reloc); - unsigned getRelocOffset(); - void finalize() override; - void writeTo(uint8_t *Buf) override; - bool hasRelocs() const { return !Relocs.empty(); } - Kind getKind() const override { return Reloc; } - size_t getRelativeRelocCount() const { return NumRelativeRelocs; } - static bool classof(const OutputSectionBase *B) { - return B->getKind() == Reloc; - } - -private: - bool Sort; - size_t NumRelativeRelocs = 0; - std::vector<DynamicReloc<ELFT>> Relocs; -}; - template <class ELFT> class OutputSection final : public OutputSectionBase { public: @@ -526,8 +468,6 @@ template <class ELFT> struct Out { static OutputSectionBase *Opd; static uint8_t *OpdBuf; static PltSection<ELFT> *Plt; - static RelocationSection<ELFT> *RelaDyn; - static RelocationSection<ELFT> *RelaPlt; static SymbolTableSection<ELFT> *DynSymTab; static SymbolTableSection<ELFT> *SymTab; static VersionDefinitionSection<ELFT> *VerDef; @@ -586,8 +526,6 @@ template <class ELFT> OutputSection<ELFT> *Out<ELFT>::MipsRldMap; template <class ELFT> OutputSectionBase *Out<ELFT>::Opd; template <class ELFT> uint8_t *Out<ELFT>::OpdBuf; template <class ELFT> PltSection<ELFT> *Out<ELFT>::Plt; -template <class ELFT> RelocationSection<ELFT> *Out<ELFT>::RelaDyn; -template <class ELFT> RelocationSection<ELFT> *Out<ELFT>::RelaPlt; template <class ELFT> SymbolTableSection<ELFT> *Out<ELFT>::DynSymTab; template <class ELFT> SymbolTableSection<ELFT> *Out<ELFT>::SymTab; template <class ELFT> VersionDefinitionSection<ELFT> *Out<ELFT>::VerDef; diff --git a/lld/ELF/Relocations.cpp b/lld/ELF/Relocations.cpp index 526ea97b743..ebcb17e3ea9 100644 --- a/lld/ELF/Relocations.cpp +++ b/lld/ELF/Relocations.cpp @@ -103,9 +103,9 @@ static unsigned handleNoRelaxTlsRelocation(uint32_t Type, SymbolBody &Body, if (Expr == R_MIPS_TLSLD || Expr == R_TLSLD_PC) { if (In<ELFT>::Got->addTlsIndex() && (Config->Pic || Config->EMachine == EM_ARM)) - Out<ELFT>::RelaDyn->addReloc({Target->TlsModuleIndexRel, In<ELFT>::Got, - In<ELFT>::Got->getTlsIndexOff(), false, - nullptr, 0}); + In<ELFT>::RelaDyn->addReloc({Target->TlsModuleIndexRel, In<ELFT>::Got, + In<ELFT>::Got->getTlsIndexOff(), false, + nullptr, 0}); C.Relocations.push_back({Expr, Type, Offset, Addend, &Body}); return 1; } @@ -114,12 +114,12 @@ static unsigned handleNoRelaxTlsRelocation(uint32_t Type, SymbolBody &Body, if (In<ELFT>::Got->addDynTlsEntry(Body) && (Body.isPreemptible() || Config->EMachine == EM_ARM)) { uintX_t Off = In<ELFT>::Got->getGlobalDynOffset(Body); - Out<ELFT>::RelaDyn->addReloc( + In<ELFT>::RelaDyn->addReloc( {Target->TlsModuleIndexRel, In<ELFT>::Got, Off, false, &Body, 0}); if (Body.isPreemptible()) - Out<ELFT>::RelaDyn->addReloc({Target->TlsOffsetRel, In<ELFT>::Got, - Off + (uintX_t)sizeof(uintX_t), false, - &Body, 0}); + In<ELFT>::RelaDyn->addReloc({Target->TlsOffsetRel, In<ELFT>::Got, + Off + (uintX_t)sizeof(uintX_t), false, + &Body, 0}); } C.Relocations.push_back({Expr, Type, Offset, Addend, &Body}); return 1; @@ -149,7 +149,7 @@ static unsigned handleTlsRelocation(uint32_t Type, SymbolBody &Body, Config->Shared) { if (In<ELFT>::Got->addDynTlsEntry(Body)) { uintX_t Off = In<ELFT>::Got->getGlobalDynOffset(Body); - Out<ELFT>::RelaDyn->addReloc( + In<ELFT>::RelaDyn->addReloc( {Target->TlsDescRel, In<ELFT>::Got, Off, false, &Body, 0}); } if (Expr != R_TLSDESC_CALL) @@ -165,9 +165,9 @@ static unsigned handleTlsRelocation(uint32_t Type, SymbolBody &Body, return 2; } if (In<ELFT>::Got->addTlsIndex()) - Out<ELFT>::RelaDyn->addReloc({Target->TlsModuleIndexRel, In<ELFT>::Got, - In<ELFT>::Got->getTlsIndexOff(), false, - nullptr, 0}); + In<ELFT>::RelaDyn->addReloc({Target->TlsModuleIndexRel, In<ELFT>::Got, + In<ELFT>::Got->getTlsIndexOff(), false, + nullptr, 0}); C.Relocations.push_back({Expr, Type, Offset, Addend, &Body}); return 1; } @@ -184,15 +184,15 @@ static unsigned handleTlsRelocation(uint32_t Type, SymbolBody &Body, if (Config->Shared) { if (In<ELFT>::Got->addDynTlsEntry(Body)) { uintX_t Off = In<ELFT>::Got->getGlobalDynOffset(Body); - Out<ELFT>::RelaDyn->addReloc( + In<ELFT>::RelaDyn->addReloc( {Target->TlsModuleIndexRel, In<ELFT>::Got, Off, false, &Body, 0}); // If the symbol is preemptible we need the dynamic linker to write // the offset too. if (isPreemptible(Body, Type)) - Out<ELFT>::RelaDyn->addReloc({Target->TlsOffsetRel, In<ELFT>::Got, - Off + (uintX_t)sizeof(uintX_t), false, - &Body, 0}); + In<ELFT>::RelaDyn->addReloc({Target->TlsOffsetRel, In<ELFT>::Got, + Off + (uintX_t)sizeof(uintX_t), false, + &Body, 0}); } C.Relocations.push_back({Expr, Type, Offset, Addend, &Body}); return 1; @@ -206,9 +206,9 @@ static unsigned handleTlsRelocation(uint32_t Type, SymbolBody &Body, Offset, Addend, &Body}); if (!Body.isInGot()) { In<ELFT>::Got->addEntry(Body); - Out<ELFT>::RelaDyn->addReloc({Target->TlsGotRel, In<ELFT>::Got, - Body.getGotOffset<ELFT>(), false, &Body, - 0}); + In<ELFT>::RelaDyn->addReloc({Target->TlsGotRel, In<ELFT>::Got, + Body.getGotOffset<ELFT>(), false, &Body, + 0}); } return Target->TlsGdRelaxSkip; } @@ -417,7 +417,7 @@ template <class ELFT> static void addCopyRelSymbol(SharedSymbol<ELFT> *SS) { Alias->NeedsCopyOrPltAddr = true; Alias->symbol()->IsUsedInRegularObj = true; } - Out<ELFT>::RelaDyn->addReloc( + In<ELFT>::RelaDyn->addReloc( {Target->CopyRel, Out<ELFT>::Bss, SS->OffsetInBss, false, SS, 0}); } @@ -619,7 +619,7 @@ static void scanRelocs(InputSectionBase<ELFT> &C, ArrayRef<RelTy> Rels) { bool IsWrite = C.Flags & SHF_WRITE; auto AddDyn = [=](const DynamicReloc<ELFT> &Reloc) { - Out<ELFT>::RelaDyn->addReloc(Reloc); + In<ELFT>::RelaDyn->addReloc(Reloc); }; const elf::ObjectFile<ELFT> *File = C.getFile(); @@ -754,9 +754,9 @@ static void scanRelocs(InputSectionBase<ELFT> &C, ArrayRef<RelTy> Rels) { Rel = Target->PltRel; In<ELFT>::GotPlt->addEntry(Body); - Out<ELFT>::RelaPlt->addReloc({Rel, In<ELFT>::GotPlt, - Body.getGotPltOffset<ELFT>(), !Preemptible, - &Body, 0}); + In<ELFT>::RelaPlt->addReloc({Rel, In<ELFT>::GotPlt, + Body.getGotPltOffset<ELFT>(), !Preemptible, + &Body, 0}); continue; } diff --git a/lld/ELF/SyntheticSections.cpp b/lld/ELF/SyntheticSections.cpp index 8e54ee7cbc5..b84df2b30df 100644 --- a/lld/ELF/SyntheticSections.cpp +++ b/lld/ELF/SyntheticSections.cpp @@ -737,10 +737,10 @@ template <class ELFT> void DynamicSection<ELFT>::finalize() { this->Link = In<ELFT>::DynStrTab->OutSec->SectionIndex; - if (Out<ELFT>::RelaDyn->hasRelocs()) { + if (In<ELFT>::RelaDyn->hasRelocs()) { bool IsRela = Config->Rela; - Add({IsRela ? DT_RELA : DT_REL, Out<ELFT>::RelaDyn}); - Add({IsRela ? DT_RELASZ : DT_RELSZ, Out<ELFT>::RelaDyn->Size}); + Add({IsRela ? DT_RELA : DT_REL, In<ELFT>::RelaDyn}); + Add({IsRela ? DT_RELASZ : DT_RELSZ, In<ELFT>::RelaDyn->getSize()}); Add({IsRela ? DT_RELAENT : DT_RELENT, uintX_t(IsRela ? sizeof(Elf_Rela) : sizeof(Elf_Rel))}); @@ -748,14 +748,14 @@ template <class ELFT> void DynamicSection<ELFT>::finalize() { // The problem is in the tight relation between dynamic // relocations and GOT. So do not emit this tag on MIPS. if (Config->EMachine != EM_MIPS) { - size_t NumRelativeRels = Out<ELFT>::RelaDyn->getRelativeRelocCount(); + size_t NumRelativeRels = In<ELFT>::RelaDyn->getRelativeRelocCount(); if (Config->ZCombreloc && NumRelativeRels) Add({IsRela ? DT_RELACOUNT : DT_RELCOUNT, NumRelativeRels}); } } - if (Out<ELFT>::RelaPlt && Out<ELFT>::RelaPlt->hasRelocs()) { - Add({DT_JMPREL, Out<ELFT>::RelaPlt}); - Add({DT_PLTRELSZ, Out<ELFT>::RelaPlt->Size}); + if (In<ELFT>::RelaPlt->hasRelocs()) { + Add({DT_JMPREL, In<ELFT>::RelaPlt}); + Add({DT_PLTRELSZ, In<ELFT>::RelaPlt->getSize()}); Add({Config->EMachine == EM_MIPS ? DT_MIPS_PLTGOT : DT_PLTGOT, In<ELFT>::GotPlt}); Add({DT_PLTREL, uint64_t(Config->Rela ? DT_RELA : DT_REL)}); @@ -848,6 +848,92 @@ template <class ELFT> void DynamicSection<ELFT>::writeTo(uint8_t *Buf) { } } +template <class ELFT> +typename ELFT::uint DynamicReloc<ELFT>::getOffset() const { + if (OutputSec) + return OutputSec->Addr + OffsetInSec; + return InputSec->OutSec->Addr + InputSec->getOffset(OffsetInSec); +} + +template <class ELFT> +typename ELFT::uint DynamicReloc<ELFT>::getAddend() const { + if (UseSymVA) + return Sym->getVA<ELFT>(Addend); + return Addend; +} + +template <class ELFT> uint32_t DynamicReloc<ELFT>::getSymIndex() const { + if (Sym && !UseSymVA) + return Sym->DynsymIndex; + return 0; +} + +template <class ELFT> +RelocationSection<ELFT>::RelocationSection(StringRef Name, bool Sort) + : SyntheticSection<ELFT>(SHF_ALLOC, Config->Rela ? SHT_RELA : SHT_REL, + sizeof(uintX_t), Name), + Sort(Sort) { + this->Entsize = Config->Rela ? sizeof(Elf_Rela) : sizeof(Elf_Rel); +} + +template <class ELFT> +void RelocationSection<ELFT>::addReloc(const DynamicReloc<ELFT> &Reloc) { + if (Reloc.Type == Target->RelativeRel) + ++NumRelativeRelocs; + Relocs.push_back(Reloc); +} + +template <class ELFT, class RelTy> +static bool compRelocations(const RelTy &A, const RelTy &B) { + bool AIsRel = A.getType(Config->Mips64EL) == Target->RelativeRel; + bool BIsRel = B.getType(Config->Mips64EL) == Target->RelativeRel; + if (AIsRel != BIsRel) + return AIsRel; + + return A.getSymbol(Config->Mips64EL) < B.getSymbol(Config->Mips64EL); +} + +template <class ELFT> void RelocationSection<ELFT>::writeTo(uint8_t *Buf) { + uint8_t *BufBegin = Buf; + for (const DynamicReloc<ELFT> &Rel : Relocs) { + auto *P = reinterpret_cast<Elf_Rela *>(Buf); + Buf += Config->Rela ? sizeof(Elf_Rela) : sizeof(Elf_Rel); + + if (Config->Rela) + P->r_addend = Rel.getAddend(); + P->r_offset = Rel.getOffset(); + if (Config->EMachine == EM_MIPS && Rel.getInputSec() == In<ELFT>::Got) + // Dynamic relocation against MIPS GOT section make deal TLS entries + // allocated in the end of the GOT. We need to adjust the offset to take + // in account 'local' and 'global' GOT entries. + P->r_offset += In<ELFT>::Got->getMipsTlsOffset(); + P->setSymbolAndType(Rel.getSymIndex(), Rel.Type, Config->Mips64EL); + } + + if (Sort) { + if (Config->Rela) + std::stable_sort((Elf_Rela *)BufBegin, + (Elf_Rela *)BufBegin + Relocs.size(), + compRelocations<ELFT, Elf_Rela>); + else + std::stable_sort((Elf_Rel *)BufBegin, (Elf_Rel *)BufBegin + Relocs.size(), + compRelocations<ELFT, Elf_Rel>); + } +} + +template <class ELFT> unsigned RelocationSection<ELFT>::getRelocOffset() { + return this->Entsize * Relocs.size(); +} + +template <class ELFT> void RelocationSection<ELFT>::finalize() { + this->Link = Out<ELFT>::DynSymTab ? Out<ELFT>::DynSymTab->SectionIndex + : Out<ELFT>::SymTab->SectionIndex; + + // Set required output section properties. + this->OutSec->Link = this->Link; + this->OutSec->Entsize = this->Entsize; +} + template InputSection<ELF32LE> *elf::createCommonSection(); template InputSection<ELF32BE> *elf::createCommonSection(); template InputSection<ELF64LE> *elf::createCommonSection(); @@ -927,3 +1013,8 @@ template class elf::DynamicSection<ELF32LE>; template class elf::DynamicSection<ELF32BE>; template class elf::DynamicSection<ELF64LE>; template class elf::DynamicSection<ELF64BE>; + +template class elf::RelocationSection<ELF32LE>; +template class elf::RelocationSection<ELF32BE>; +template class elf::RelocationSection<ELF64LE>; +template class elf::RelocationSection<ELF64BE>; diff --git a/lld/ELF/SyntheticSections.h b/lld/ELF/SyntheticSections.h index 0e9b7f8a719..f420f9bf460 100644 --- a/lld/ELF/SyntheticSections.h +++ b/lld/ELF/SyntheticSections.h @@ -239,6 +239,39 @@ private: std::vector<StringRef> Strings; }; +template <class ELFT> class DynamicReloc { + typedef typename ELFT::uint uintX_t; + +public: + DynamicReloc(uint32_t Type, const InputSectionBase<ELFT> *InputSec, + uintX_t OffsetInSec, bool UseSymVA, SymbolBody *Sym, + uintX_t Addend) + : Type(Type), Sym(Sym), InputSec(InputSec), OffsetInSec(OffsetInSec), + UseSymVA(UseSymVA), Addend(Addend) {} + + DynamicReloc(uint32_t Type, const OutputSectionBase *OutputSec, + uintX_t OffsetInSec, bool UseSymVA, SymbolBody *Sym, + uintX_t Addend) + : Type(Type), Sym(Sym), OutputSec(OutputSec), OffsetInSec(OffsetInSec), + UseSymVA(UseSymVA), Addend(Addend) {} + + uintX_t getOffset() const; + uintX_t getAddend() const; + uint32_t getSymIndex() const; + const OutputSectionBase *getOutputSec() const { return OutputSec; } + const InputSectionBase<ELFT> *getInputSec() const { return InputSec; } + + uint32_t Type; + +private: + SymbolBody *Sym; + const InputSectionBase<ELFT> *InputSec = nullptr; + const OutputSectionBase *OutputSec = nullptr; + uintX_t OffsetInSec; + bool UseSymVA; + uintX_t Addend; +}; + template <class ELFT> class DynamicSection final : public SyntheticSection<ELFT> { typedef typename ELFT::Dyn Elf_Dyn; @@ -287,6 +320,28 @@ private: uintX_t Size = 0; }; +template <class ELFT> +class RelocationSection final : public SyntheticSection<ELFT> { + typedef typename ELFT::Rel Elf_Rel; + typedef typename ELFT::Rela Elf_Rela; + typedef typename ELFT::uint uintX_t; + +public: + RelocationSection(StringRef Name, bool Sort); + void addReloc(const DynamicReloc<ELFT> &Reloc); + unsigned getRelocOffset(); + void finalize() override; + void writeTo(uint8_t *Buf) override; + size_t getSize() const override { return Relocs.size() * this->Entsize; } + bool hasRelocs() const { return !Relocs.empty(); } + size_t getRelativeRelocCount() const { return NumRelativeRelocs; } + +private: + bool Sort; + size_t NumRelativeRelocs = 0; + std::vector<DynamicReloc<ELFT>> Relocs; +}; + template <class ELFT> InputSection<ELFT> *createCommonSection(); template <class ELFT> InputSection<ELFT> *createInterpSection(); template <class ELFT> MergeInputSection<ELFT> *createCommentSection(); @@ -303,6 +358,8 @@ template <class ELFT> struct In { static MipsAbiFlagsSection<ELFT> *MipsAbiFlags; static MipsOptionsSection<ELFT> *MipsOptions; static MipsReginfoSection<ELFT> *MipsReginfo; + static RelocationSection<ELFT> *RelaDyn; + static RelocationSection<ELFT> *RelaPlt; static StringTableSection<ELFT> *ShStrTab; static StringTableSection<ELFT> *StrTab; }; @@ -317,6 +374,8 @@ template <class ELFT> InputSection<ELFT> *In<ELFT>::Interp; template <class ELFT> MipsAbiFlagsSection<ELFT> *In<ELFT>::MipsAbiFlags; template <class ELFT> MipsOptionsSection<ELFT> *In<ELFT>::MipsOptions; template <class ELFT> MipsReginfoSection<ELFT> *In<ELFT>::MipsReginfo; +template <class ELFT> RelocationSection<ELFT> *In<ELFT>::RelaDyn; +template <class ELFT> RelocationSection<ELFT> *In<ELFT>::RelaPlt; template <class ELFT> StringTableSection<ELFT> *In<ELFT>::ShStrTab; template <class ELFT> StringTableSection<ELFT> *In<ELFT>::StrTab; } // namespace elf diff --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp index 9ab4cda1de4..9b749c7cd0a 100644 --- a/lld/ELF/Writer.cpp +++ b/lld/ELF/Writer.cpp @@ -213,7 +213,7 @@ template <class ELFT> void Writer<ELFT>::createSyntheticSections() { In<ELFT>::Dynamic = make<DynamicSection<ELFT>>(); Out<ELFT>::EhFrame = make<EhOutputSection<ELFT>>(); Out<ELFT>::Plt = make<PltSection<ELFT>>(); - Out<ELFT>::RelaDyn = make<RelocationSection<ELFT>>( + In<ELFT>::RelaDyn = make<RelocationSection<ELFT>>( Config->Rela ? ".rela.dyn" : ".rel.dyn", Config->ZCombreloc); In<ELFT>::ShStrTab = make<StringTableSection<ELFT>>(".shstrtab", false); Out<ELFT>::VerSym = make<VersionTableSection<ELFT>>(); @@ -245,7 +245,7 @@ template <class ELFT> void Writer<ELFT>::createSyntheticSections() { if (Config->GdbIndex) Out<ELFT>::GdbIndex = make<GdbIndexSection<ELFT>>(); - Out<ELFT>::RelaPlt = make<RelocationSection<ELFT>>( + In<ELFT>::RelaPlt = make<RelocationSection<ELFT>>( Config->Rela ? ".rela.plt" : ".rel.plt", false /*Sort*/); if (Config->Strip != StripPolicy::All) { In<ELFT>::StrTab = make<StringTableSection<ELFT>>(".strtab", false); @@ -589,11 +589,10 @@ template <class ELFT> void Writer<ELFT>::addRelIpltSymbols() { if (Out<ELFT>::DynSymTab) return; StringRef S = Config->Rela ? "__rela_iplt_start" : "__rel_iplt_start"; - addOptionalSynthetic<ELFT>(S, Out<ELFT>::RelaPlt, 0); + addOptionalRegular<ELFT>(S, In<ELFT>::RelaPlt, 0); S = Config->Rela ? "__rela_iplt_end" : "__rel_iplt_end"; - addOptionalSynthetic<ELFT>(S, Out<ELFT>::RelaPlt, - DefinedSynthetic<ELFT>::SectionEnd); + addOptionalRegular<ELFT>(S, In<ELFT>::RelaPlt, -1); } // The linker is expected to define some symbols depending on @@ -945,8 +944,10 @@ template <class ELFT> void Writer<ELFT>::finalizeSections() { for (OutputSectionBase *Sec : OutputSections) Sec->finalize(); + // Dynamic section must be the last one in this list. finalizeSynthetic<ELFT>({In<ELFT>::ShStrTab, In<ELFT>::StrTab, In<ELFT>::DynStrTab, In<ELFT>::Got, In<ELFT>::GotPlt, + In<ELFT>::RelaDyn, In<ELFT>::RelaPlt, In<ELFT>::Dynamic}); // Now that all output offsets are fixed. Finalize mergeable sections @@ -997,15 +998,15 @@ template <class ELFT> void Writer<ELFT>::addPredefinedSections() { Add(Out<ELFT>::HashTab); addInputSec(In<ELFT>::Dynamic); addInputSec(In<ELFT>::DynStrTab); - if (Out<ELFT>::RelaDyn->hasRelocs()) - Add(Out<ELFT>::RelaDyn); + if (In<ELFT>::RelaDyn->hasRelocs()) + addInputSec(In<ELFT>::RelaDyn); Add(Out<ELFT>::MipsRldMap); } // We always need to add rel[a].plt to output if it has entries. // Even during static linking it can contain R_[*]_IRELATIVE relocations. - if (Out<ELFT>::RelaPlt->hasRelocs()) - Add(Out<ELFT>::RelaPlt); + if (In<ELFT>::RelaPlt->hasRelocs()) + addInputSec(In<ELFT>::RelaPlt); // We fill .got and .got.plt sections in scanRelocs(). This is the // reason we don't add it earlier in createSections(). |