diff options
| author | Eugene Leviant <eleviant@accesssoftek.com> | 2016-11-15 12:26:55 +0000 |
|---|---|---|
| committer | Eugene Leviant <eleviant@accesssoftek.com> | 2016-11-15 12:26:55 +0000 |
| commit | 6380ce22127370f34b9d958209d634ddde3abe97 (patch) | |
| tree | 670efe9bce57a988bcc9aa213dfeb2fb14192d68 | |
| parent | f043dac25d5cbe86e75c15a4078811d9961b3fd4 (diff) | |
| download | bcm5719-llvm-6380ce22127370f34b9d958209d634ddde3abe97.tar.gz bcm5719-llvm-6380ce22127370f34b9d958209d634ddde3abe97.zip | |
[ELF] Convert DynamicSection to input section.
This patch introduces the following changes:
- DynamicSection now inherits InputSection<ELFT> and was moved
to SyntheticSections.h/.cpp.
- Link and Entsize fields of DynamicSection are propagated to
its output section
- In<ELFT>::SyntheticSections was removed.
- Finalization of synthetic sections was removed from
OutputSection<ELFT>::finalize. Now finalizeSyntheticSections is
used instead.
Differential revision: https://reviews.llvm.org/D26603
llvm-svn: 286950
| -rw-r--r-- | lld/ELF/OutputSections.cpp | 184 | ||||
| -rw-r--r-- | lld/ELF/OutputSections.h | 52 | ||||
| -rw-r--r-- | lld/ELF/SyntheticSections.cpp | 180 | ||||
| -rw-r--r-- | lld/ELF/SyntheticSections.h | 61 | ||||
| -rw-r--r-- | lld/ELF/Target.cpp | 4 | ||||
| -rw-r--r-- | lld/ELF/Writer.cpp | 43 |
6 files changed, 256 insertions, 268 deletions
diff --git a/lld/ELF/OutputSections.cpp b/lld/ELF/OutputSections.cpp index 20bd23c4558..e2c0afb00dc 100644 --- a/lld/ELF/OutputSections.cpp +++ b/lld/ELF/OutputSections.cpp @@ -395,177 +395,6 @@ void GnuHashTableSection<ELFT>::addSymbols(std::vector<SymbolTableEntry> &V) { static unsigned getVerDefNum() { return Config->VersionDefinitions.size() + 1; } template <class ELFT> -DynamicSection<ELFT>::DynamicSection() - : OutputSectionBase(".dynamic", SHT_DYNAMIC, SHF_ALLOC | SHF_WRITE) { - this->Addralign = sizeof(uintX_t); - this->Entsize = ELFT::Is64Bits ? 16 : 8; - - // .dynamic section is not writable on MIPS. - // See "Special Section" in Chapter 4 in the following document: - // ftp://www.linux-mips.org/pub/linux/mips/doc/ABI/mipsabi.pdf - if (Config->EMachine == EM_MIPS) - this->Flags = SHF_ALLOC; - - addEntries(); -} - -// There are some dynamic entries that don't depend on other sections. -// Such entries can be set early. -template <class ELFT> void DynamicSection<ELFT>::addEntries() { - // Add strings to .dynstr early so that .dynstr's size will be - // fixed early. - for (StringRef S : Config->AuxiliaryList) - Add({DT_AUXILIARY, In<ELFT>::DynStrTab->addString(S)}); - if (!Config->RPath.empty()) - Add({Config->EnableNewDtags ? DT_RUNPATH : DT_RPATH, - In<ELFT>::DynStrTab->addString(Config->RPath)}); - for (SharedFile<ELFT> *F : Symtab<ELFT>::X->getSharedFiles()) - if (F->isNeeded()) - Add({DT_NEEDED, In<ELFT>::DynStrTab->addString(F->getSoName())}); - if (!Config->SoName.empty()) - Add({DT_SONAME, In<ELFT>::DynStrTab->addString(Config->SoName)}); - - // Set DT_FLAGS and DT_FLAGS_1. - uint32_t DtFlags = 0; - uint32_t DtFlags1 = 0; - if (Config->Bsymbolic) - DtFlags |= DF_SYMBOLIC; - if (Config->ZNodelete) - DtFlags1 |= DF_1_NODELETE; - if (Config->ZNow) { - DtFlags |= DF_BIND_NOW; - DtFlags1 |= DF_1_NOW; - } - if (Config->ZOrigin) { - DtFlags |= DF_ORIGIN; - DtFlags1 |= DF_1_ORIGIN; - } - - if (DtFlags) - Add({DT_FLAGS, DtFlags}); - if (DtFlags1) - Add({DT_FLAGS_1, DtFlags1}); - - if (!Config->Entry.empty()) - Add({DT_DEBUG, (uint64_t)0}); -} - -// Add remaining entries to complete .dynamic contents. -template <class ELFT> void DynamicSection<ELFT>::finalize() { - if (this->Size) - return; // Already finalized. - - this->Link = In<ELFT>::DynStrTab->OutSec->SectionIndex; - - if (Out<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_RELAENT : DT_RELENT, - uintX_t(IsRela ? sizeof(Elf_Rela) : sizeof(Elf_Rel))}); - - // MIPS dynamic loader does not support RELCOUNT tag. - // 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(); - 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}); - Add({Config->EMachine == EM_MIPS ? DT_MIPS_PLTGOT : DT_PLTGOT, - In<ELFT>::GotPlt}); - Add({DT_PLTREL, uint64_t(Config->Rela ? DT_RELA : DT_REL)}); - } - - Add({DT_SYMTAB, Out<ELFT>::DynSymTab}); - Add({DT_SYMENT, sizeof(Elf_Sym)}); - Add({DT_STRTAB, In<ELFT>::DynStrTab}); - Add({DT_STRSZ, In<ELFT>::DynStrTab->getSize()}); - if (Out<ELFT>::GnuHashTab) - Add({DT_GNU_HASH, Out<ELFT>::GnuHashTab}); - if (Out<ELFT>::HashTab) - Add({DT_HASH, Out<ELFT>::HashTab}); - - if (Out<ELFT>::PreinitArray) { - Add({DT_PREINIT_ARRAY, Out<ELFT>::PreinitArray}); - Add({DT_PREINIT_ARRAYSZ, Out<ELFT>::PreinitArray, Entry::SecSize}); - } - if (Out<ELFT>::InitArray) { - Add({DT_INIT_ARRAY, Out<ELFT>::InitArray}); - Add({DT_INIT_ARRAYSZ, Out<ELFT>::InitArray, Entry::SecSize}); - } - if (Out<ELFT>::FiniArray) { - Add({DT_FINI_ARRAY, Out<ELFT>::FiniArray}); - Add({DT_FINI_ARRAYSZ, Out<ELFT>::FiniArray, Entry::SecSize}); - } - - if (SymbolBody *B = Symtab<ELFT>::X->find(Config->Init)) - Add({DT_INIT, B}); - if (SymbolBody *B = Symtab<ELFT>::X->find(Config->Fini)) - Add({DT_FINI, B}); - - bool HasVerNeed = Out<ELFT>::VerNeed->getNeedNum() != 0; - if (HasVerNeed || Out<ELFT>::VerDef) - Add({DT_VERSYM, Out<ELFT>::VerSym}); - if (Out<ELFT>::VerDef) { - Add({DT_VERDEF, Out<ELFT>::VerDef}); - Add({DT_VERDEFNUM, getVerDefNum()}); - } - if (HasVerNeed) { - Add({DT_VERNEED, Out<ELFT>::VerNeed}); - Add({DT_VERNEEDNUM, Out<ELFT>::VerNeed->getNeedNum()}); - } - - if (Config->EMachine == EM_MIPS) { - Add({DT_MIPS_RLD_VERSION, 1}); - Add({DT_MIPS_FLAGS, RHF_NOTPOT}); - Add({DT_MIPS_BASE_ADDRESS, Config->ImageBase}); - Add({DT_MIPS_SYMTABNO, Out<ELFT>::DynSymTab->getNumSymbols()}); - Add({DT_MIPS_LOCAL_GOTNO, In<ELFT>::Got->getMipsLocalEntriesNum()}); - if (const SymbolBody *B = In<ELFT>::Got->getMipsFirstGlobalEntry()) - Add({DT_MIPS_GOTSYM, B->DynsymIndex}); - else - Add({DT_MIPS_GOTSYM, Out<ELFT>::DynSymTab->getNumSymbols()}); - Add({DT_PLTGOT, In<ELFT>::Got}); - if (Out<ELFT>::MipsRldMap) - Add({DT_MIPS_RLD_MAP, Out<ELFT>::MipsRldMap}); - } - - // +1 for DT_NULL - this->Size = (Entries.size() + 1) * this->Entsize; -} - -template <class ELFT> void DynamicSection<ELFT>::writeTo(uint8_t *Buf) { - auto *P = reinterpret_cast<Elf_Dyn *>(Buf); - - for (const Entry &E : Entries) { - P->d_tag = E.Tag; - switch (E.Kind) { - case Entry::SecAddr: - P->d_un.d_ptr = E.OutSec->Addr; - break; - case Entry::InSecAddr: - P->d_un.d_ptr = E.InSec->OutSec->Addr + E.InSec->OutSecOff; - break; - case Entry::SecSize: - P->d_un.d_val = E.OutSec->Size; - break; - case Entry::SymAddr: - P->d_un.d_ptr = E.Sym->template getVA<ELFT>(); - break; - case Entry::PlainInt: - P->d_un.d_val = E.Val; - break; - } - ++P; - } -} - -template <class ELFT> EhFrameHeader<ELFT>::EhFrameHeader() : OutputSectionBase(".eh_frame_hdr", SHT_PROGBITS, SHF_ALLOC) {} @@ -650,14 +479,6 @@ template <class ELFT> void OutputSection<ELFT>::finalize() { } } - // Recalculate input section offsets if we own any synthetic section - for (auto *SS : In<ELFT>::SyntheticSections) - if (SS && this == SS->OutSec) { - this->Size = 0; - assignOffsets(); - break; - } - if (Type != SHT_RELA && Type != SHT_REL) return; this->Link = Out<ELFT>::SymTab->SectionIndex; @@ -1544,11 +1365,6 @@ template class HashTableSection<ELF32BE>; template class HashTableSection<ELF64LE>; template class HashTableSection<ELF64BE>; -template class DynamicSection<ELF32LE>; -template class DynamicSection<ELF32BE>; -template class DynamicSection<ELF64LE>; -template class DynamicSection<ELF64BE>; - template class OutputSection<ELF32LE>; template class OutputSection<ELF32BE>; template class OutputSection<ELF64LE>; diff --git a/lld/ELF/OutputSections.h b/lld/ELF/OutputSections.h index bc820390d2e..df72e755425 100644 --- a/lld/ELF/OutputSections.h +++ b/lld/ELF/OutputSections.h @@ -45,7 +45,6 @@ class OutputSectionBase { public: enum Kind { Base, - Dynamic, EHFrame, EHFrameHdr, GnuHashTable, @@ -478,55 +477,6 @@ private: unsigned Shift2; }; -template <class ELFT> class DynamicSection final : public OutputSectionBase { - typedef typename ELFT::Dyn Elf_Dyn; - typedef typename ELFT::Rel Elf_Rel; - typedef typename ELFT::Rela Elf_Rela; - typedef typename ELFT::Shdr Elf_Shdr; - typedef typename ELFT::Sym Elf_Sym; - typedef typename ELFT::uint uintX_t; - - // The .dynamic section contains information for the dynamic linker. - // The section consists of fixed size entries, which consist of - // type and value fields. Value are one of plain integers, symbol - // addresses, or section addresses. This struct represents the entry. - struct Entry { - int32_t Tag; - union { - OutputSectionBase *OutSec; - InputSection<ELFT> *InSec; - uint64_t Val; - const SymbolBody *Sym; - }; - enum KindT { SecAddr, SecSize, SymAddr, PlainInt, InSecAddr } Kind; - Entry(int32_t Tag, OutputSectionBase *OutSec, KindT Kind = SecAddr) - : Tag(Tag), OutSec(OutSec), Kind(Kind) {} - Entry(int32_t Tag, InputSection<ELFT> *Sec) - : Tag(Tag), InSec(Sec), Kind(InSecAddr) {} - Entry(int32_t Tag, uint64_t Val) : Tag(Tag), Val(Val), Kind(PlainInt) {} - Entry(int32_t Tag, const SymbolBody *Sym) - : Tag(Tag), Sym(Sym), Kind(SymAddr) {} - }; - - // finalize() fills this vector with the section contents. finalize() - // cannot directly create final section contents because when the - // function is called, symbol or section addresses are not fixed yet. - std::vector<Entry> Entries; - -public: - DynamicSection(); - void finalize() override; - void writeTo(uint8_t *Buf) override; - Kind getKind() const override { return Dynamic; } - static bool classof(const OutputSectionBase *B) { - return B->getKind() == Dynamic; - } - -private: - void addEntries(); - void Add(Entry E) { Entries.push_back(E); } -}; - // --eh-frame-hdr option tells linker to construct a header for all the // .eh_frame sections. This header is placed to a section named .eh_frame_hdr // and also to a PT_GNU_EH_FRAME segment. @@ -566,7 +516,6 @@ template <class ELFT> struct Out { typedef typename ELFT::Phdr Elf_Phdr; static uint8_t First; - static DynamicSection<ELFT> *Dynamic; static EhFrameHeader<ELFT> *EhFrameHdr; static EhOutputSection<ELFT> *EhFrame; static GdbIndexSection<ELFT> *GdbIndex; @@ -627,7 +576,6 @@ template <class ELFT> uint64_t getHeaderSize() { } template <class ELFT> uint8_t Out<ELFT>::First; -template <class ELFT> DynamicSection<ELFT> *Out<ELFT>::Dynamic; template <class ELFT> EhFrameHeader<ELFT> *Out<ELFT>::EhFrameHdr; template <class ELFT> EhOutputSection<ELFT> *Out<ELFT>::EhFrame; template <class ELFT> GdbIndexSection<ELFT> *Out<ELFT>::GdbIndex; diff --git a/lld/ELF/SyntheticSections.cpp b/lld/ELF/SyntheticSections.cpp index d432758bfa8..8e54ee7cbc5 100644 --- a/lld/ELF/SyntheticSections.cpp +++ b/lld/ELF/SyntheticSections.cpp @@ -673,6 +673,181 @@ template <class ELFT> void StringTableSection<ELFT>::writeTo(uint8_t *Buf) { } } +static unsigned getVerDefNum() { return Config->VersionDefinitions.size() + 1; } + +template <class ELFT> +DynamicSection<ELFT>::DynamicSection() + : SyntheticSection<ELFT>(SHF_ALLOC | SHF_WRITE, SHT_DYNAMIC, + sizeof(uintX_t), ".dynamic") { + this->Entsize = ELFT::Is64Bits ? 16 : 8; + // .dynamic section is not writable on MIPS. + // See "Special Section" in Chapter 4 in the following document: + // ftp://www.linux-mips.org/pub/linux/mips/doc/ABI/mipsabi.pdf + if (Config->EMachine == EM_MIPS) + this->Flags = SHF_ALLOC; + + addEntries(); +} + +// There are some dynamic entries that don't depend on other sections. +// Such entries can be set early. +template <class ELFT> void DynamicSection<ELFT>::addEntries() { + // Add strings to .dynstr early so that .dynstr's size will be + // fixed early. + for (StringRef S : Config->AuxiliaryList) + Add({DT_AUXILIARY, In<ELFT>::DynStrTab->addString(S)}); + if (!Config->RPath.empty()) + Add({Config->EnableNewDtags ? DT_RUNPATH : DT_RPATH, + In<ELFT>::DynStrTab->addString(Config->RPath)}); + for (SharedFile<ELFT> *F : Symtab<ELFT>::X->getSharedFiles()) + if (F->isNeeded()) + Add({DT_NEEDED, In<ELFT>::DynStrTab->addString(F->getSoName())}); + if (!Config->SoName.empty()) + Add({DT_SONAME, In<ELFT>::DynStrTab->addString(Config->SoName)}); + + // Set DT_FLAGS and DT_FLAGS_1. + uint32_t DtFlags = 0; + uint32_t DtFlags1 = 0; + if (Config->Bsymbolic) + DtFlags |= DF_SYMBOLIC; + if (Config->ZNodelete) + DtFlags1 |= DF_1_NODELETE; + if (Config->ZNow) { + DtFlags |= DF_BIND_NOW; + DtFlags1 |= DF_1_NOW; + } + if (Config->ZOrigin) { + DtFlags |= DF_ORIGIN; + DtFlags1 |= DF_1_ORIGIN; + } + + if (DtFlags) + Add({DT_FLAGS, DtFlags}); + if (DtFlags1) + Add({DT_FLAGS_1, DtFlags1}); + + if (!Config->Entry.empty()) + Add({DT_DEBUG, (uint64_t)0}); +} + +// Add remaining entries to complete .dynamic contents. +template <class ELFT> void DynamicSection<ELFT>::finalize() { + if (this->Size) + return; // Already finalized. + + this->Link = In<ELFT>::DynStrTab->OutSec->SectionIndex; + + if (Out<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_RELAENT : DT_RELENT, + uintX_t(IsRela ? sizeof(Elf_Rela) : sizeof(Elf_Rel))}); + + // MIPS dynamic loader does not support RELCOUNT tag. + // 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(); + 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}); + Add({Config->EMachine == EM_MIPS ? DT_MIPS_PLTGOT : DT_PLTGOT, + In<ELFT>::GotPlt}); + Add({DT_PLTREL, uint64_t(Config->Rela ? DT_RELA : DT_REL)}); + } + + Add({DT_SYMTAB, Out<ELFT>::DynSymTab}); + Add({DT_SYMENT, sizeof(Elf_Sym)}); + Add({DT_STRTAB, In<ELFT>::DynStrTab}); + Add({DT_STRSZ, In<ELFT>::DynStrTab->getSize()}); + if (Out<ELFT>::GnuHashTab) + Add({DT_GNU_HASH, Out<ELFT>::GnuHashTab}); + if (Out<ELFT>::HashTab) + Add({DT_HASH, Out<ELFT>::HashTab}); + + if (Out<ELFT>::PreinitArray) { + Add({DT_PREINIT_ARRAY, Out<ELFT>::PreinitArray}); + Add({DT_PREINIT_ARRAYSZ, Out<ELFT>::PreinitArray, Entry::SecSize}); + } + if (Out<ELFT>::InitArray) { + Add({DT_INIT_ARRAY, Out<ELFT>::InitArray}); + Add({DT_INIT_ARRAYSZ, Out<ELFT>::InitArray, Entry::SecSize}); + } + if (Out<ELFT>::FiniArray) { + Add({DT_FINI_ARRAY, Out<ELFT>::FiniArray}); + Add({DT_FINI_ARRAYSZ, Out<ELFT>::FiniArray, Entry::SecSize}); + } + + if (SymbolBody *B = Symtab<ELFT>::X->find(Config->Init)) + Add({DT_INIT, B}); + if (SymbolBody *B = Symtab<ELFT>::X->find(Config->Fini)) + Add({DT_FINI, B}); + + bool HasVerNeed = Out<ELFT>::VerNeed->getNeedNum() != 0; + if (HasVerNeed || Out<ELFT>::VerDef) + Add({DT_VERSYM, Out<ELFT>::VerSym}); + if (Out<ELFT>::VerDef) { + Add({DT_VERDEF, Out<ELFT>::VerDef}); + Add({DT_VERDEFNUM, getVerDefNum()}); + } + if (HasVerNeed) { + Add({DT_VERNEED, Out<ELFT>::VerNeed}); + Add({DT_VERNEEDNUM, Out<ELFT>::VerNeed->getNeedNum()}); + } + + if (Config->EMachine == EM_MIPS) { + Add({DT_MIPS_RLD_VERSION, 1}); + Add({DT_MIPS_FLAGS, RHF_NOTPOT}); + Add({DT_MIPS_BASE_ADDRESS, Config->ImageBase}); + Add({DT_MIPS_SYMTABNO, Out<ELFT>::DynSymTab->getNumSymbols()}); + Add({DT_MIPS_LOCAL_GOTNO, In<ELFT>::Got->getMipsLocalEntriesNum()}); + if (const SymbolBody *B = In<ELFT>::Got->getMipsFirstGlobalEntry()) + Add({DT_MIPS_GOTSYM, B->DynsymIndex}); + else + Add({DT_MIPS_GOTSYM, Out<ELFT>::DynSymTab->getNumSymbols()}); + Add({DT_PLTGOT, In<ELFT>::Got}); + if (Out<ELFT>::MipsRldMap) + Add({DT_MIPS_RLD_MAP, Out<ELFT>::MipsRldMap}); + } + + this->OutSec->Entsize = this->Entsize; + this->OutSec->Link = this->Link; + + // +1 for DT_NULL + this->Size = (Entries.size() + 1) * this->Entsize; +} + +template <class ELFT> void DynamicSection<ELFT>::writeTo(uint8_t *Buf) { + auto *P = reinterpret_cast<Elf_Dyn *>(Buf); + + for (const Entry &E : Entries) { + P->d_tag = E.Tag; + switch (E.Kind) { + case Entry::SecAddr: + P->d_un.d_ptr = E.OutSec->Addr; + break; + case Entry::InSecAddr: + P->d_un.d_ptr = E.InSec->OutSec->Addr + E.InSec->OutSecOff; + break; + case Entry::SecSize: + P->d_un.d_val = E.OutSec->Size; + break; + case Entry::SymAddr: + P->d_un.d_ptr = E.Sym->template getVA<ELFT>(); + break; + case Entry::PlainInt: + P->d_un.d_val = E.Val; + break; + } + ++P; + } +} + template InputSection<ELF32LE> *elf::createCommonSection(); template InputSection<ELF32BE> *elf::createCommonSection(); template InputSection<ELF64LE> *elf::createCommonSection(); @@ -747,3 +922,8 @@ template class elf::StringTableSection<ELF32LE>; template class elf::StringTableSection<ELF32BE>; template class elf::StringTableSection<ELF64LE>; template class elf::StringTableSection<ELF64BE>; + +template class elf::DynamicSection<ELF32LE>; +template class elf::DynamicSection<ELF32BE>; +template class elf::DynamicSection<ELF64LE>; +template class elf::DynamicSection<ELF64BE>; diff --git a/lld/ELF/SyntheticSections.h b/lld/ELF/SyntheticSections.h index 2f165956a34..0e9b7f8a719 100644 --- a/lld/ELF/SyntheticSections.h +++ b/lld/ELF/SyntheticSections.h @@ -72,6 +72,7 @@ public: virtual void writeTo(uint8_t *Buf) = 0; virtual size_t getSize() const { return this->Data.size(); } + virtual void finalize() {} uintX_t getVA() const { return this->OutSec ? this->OutSec->Addr + this->OutSecOff : 0; } @@ -144,7 +145,7 @@ public: GotSection(); void writeTo(uint8_t *Buf) override; size_t getSize() const override { return Size; } - void finalize(); + void finalize() override; void addEntry(SymbolBody &Sym); void addMipsEntry(SymbolBody &Sym, uintX_t Addend, RelExpr Expr); bool addDynTlsEntry(SymbolBody &Sym); @@ -238,6 +239,54 @@ private: std::vector<StringRef> Strings; }; +template <class ELFT> +class DynamicSection final : public SyntheticSection<ELFT> { + typedef typename ELFT::Dyn Elf_Dyn; + typedef typename ELFT::Rel Elf_Rel; + typedef typename ELFT::Rela Elf_Rela; + typedef typename ELFT::Shdr Elf_Shdr; + typedef typename ELFT::Sym Elf_Sym; + typedef typename ELFT::uint uintX_t; + + // The .dynamic section contains information for the dynamic linker. + // The section consists of fixed size entries, which consist of + // type and value fields. Value are one of plain integers, symbol + // addresses, or section addresses. This struct represents the entry. + struct Entry { + int32_t Tag; + union { + OutputSectionBase *OutSec; + InputSection<ELFT> *InSec; + uint64_t Val; + const SymbolBody *Sym; + }; + enum KindT { SecAddr, SecSize, SymAddr, PlainInt, InSecAddr } Kind; + Entry(int32_t Tag, OutputSectionBase *OutSec, KindT Kind = SecAddr) + : Tag(Tag), OutSec(OutSec), Kind(Kind) {} + Entry(int32_t Tag, InputSection<ELFT> *Sec) + : Tag(Tag), InSec(Sec), Kind(InSecAddr) {} + Entry(int32_t Tag, uint64_t Val) : Tag(Tag), Val(Val), Kind(PlainInt) {} + Entry(int32_t Tag, const SymbolBody *Sym) + : Tag(Tag), Sym(Sym), Kind(SymAddr) {} + }; + + // finalize() fills this vector with the section contents. finalize() + // cannot directly create final section contents because when the + // function is called, symbol or section addresses are not fixed yet. + std::vector<Entry> Entries; + +public: + DynamicSection(); + void finalize() override; + void writeTo(uint8_t *Buf) override; + size_t getSize() const override { return Size; } + +private: + void addEntries(); + void Add(Entry E) { Entries.push_back(E); } + uintX_t Size = 0; +}; + template <class ELFT> InputSection<ELFT> *createCommonSection(); template <class ELFT> InputSection<ELFT> *createInterpSection(); template <class ELFT> MergeInputSection<ELFT> *createCommentSection(); @@ -246,6 +295,7 @@ template <class ELFT> MergeInputSection<ELFT> *createCommentSection(); template <class ELFT> struct In { static BuildIdSection<ELFT> *BuildId; static InputSection<ELFT> *Common; + static DynamicSection<ELFT> *Dynamic; static StringTableSection<ELFT> *DynStrTab; static GotSection<ELFT> *Got; static GotPltSection<ELFT> *GotPlt; @@ -255,15 +305,11 @@ template <class ELFT> struct In { static MipsReginfoSection<ELFT> *MipsReginfo; static StringTableSection<ELFT> *ShStrTab; static StringTableSection<ELFT> *StrTab; - - // Contains list of sections, which size is not known when - // createSections() is called. This list is used when output - // sections are being finalized to calculate their size correctly. - static std::vector<SyntheticSection<ELFT> *> SyntheticSections; }; template <class ELFT> BuildIdSection<ELFT> *In<ELFT>::BuildId; template <class ELFT> InputSection<ELFT> *In<ELFT>::Common; +template <class ELFT> DynamicSection<ELFT> *In<ELFT>::Dynamic; template <class ELFT> StringTableSection<ELFT> *In<ELFT>::DynStrTab; template <class ELFT> GotSection<ELFT> *In<ELFT>::Got; template <class ELFT> GotPltSection<ELFT> *In<ELFT>::GotPlt; @@ -273,9 +319,6 @@ template <class ELFT> MipsOptionsSection<ELFT> *In<ELFT>::MipsOptions; template <class ELFT> MipsReginfoSection<ELFT> *In<ELFT>::MipsReginfo; template <class ELFT> StringTableSection<ELFT> *In<ELFT>::ShStrTab; template <class ELFT> StringTableSection<ELFT> *In<ELFT>::StrTab; -template <class ELFT> -std::vector<SyntheticSection<ELFT> *> In<ELFT>::SyntheticSections; - } // namespace elf } // namespace lld diff --git a/lld/ELF/Target.cpp b/lld/ELF/Target.cpp index 56ea6a4400a..447490ceece 100644 --- a/lld/ELF/Target.cpp +++ b/lld/ELF/Target.cpp @@ -356,7 +356,7 @@ RelExpr X86TargetInfo::adjustRelaxExpr(uint32_t Type, const uint8_t *Data, } void X86TargetInfo::writeGotPltHeader(uint8_t *Buf) const { - write32le(Buf, Out<ELF32LE>::Dynamic->Addr); + write32le(Buf, In<ELF32LE>::Dynamic->getVA()); } void X86TargetInfo::writeGotPlt(uint8_t *Buf, const SymbolBody &S) const { @@ -596,7 +596,7 @@ void X86_64TargetInfo<ELFT>::writeGotPltHeader(uint8_t *Buf) const { // required, but it is documented in the psabi and the glibc dynamic linker // seems to use it (note that this is relevant for linking ld.so, not any // other program). - write64le(Buf, Out<ELFT>::Dynamic->Addr); + write64le(Buf, In<ELFT>::Dynamic->getVA()); } template <class ELFT> diff --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp index 15b4b32ec18..f8600ed2823 100644 --- a/lld/ELF/Writer.cpp +++ b/lld/ELF/Writer.cpp @@ -210,7 +210,7 @@ template <class ELFT> void Writer<ELFT>::createSyntheticSections() { Out<ELFT>::Bss = make<OutputSection<ELFT>>(".bss", SHT_NOBITS, SHF_ALLOC | SHF_WRITE); In<ELFT>::DynStrTab = make<StringTableSection<ELFT>>(".dynstr", true); - Out<ELFT>::Dynamic = make<DynamicSection<ELFT>>(); + In<ELFT>::Dynamic = make<DynamicSection<ELFT>>(); Out<ELFT>::EhFrame = make<EhOutputSection<ELFT>>(); Out<ELFT>::Plt = make<PltSection<ELFT>>(); Out<ELFT>::RelaDyn = make<RelocationSection<ELFT>>( @@ -314,13 +314,6 @@ template <class ELFT> void Writer<ELFT>::createSyntheticSections() { In<ELFT>::Got = make<GotSection<ELFT>>(); In<ELFT>::GotPlt = make<GotPltSection<ELFT>>(); - - // These sections are filled after createSections() is called. - // We use this list to fixup size of output sections, when they - // are finalized. - In<ELFT>::SyntheticSections = {In<ELFT>::ShStrTab, In<ELFT>::StrTab, - In<ELFT>::DynStrTab, In<ELFT>::Got, - In<ELFT>::GotPlt}; } template <class ELFT> @@ -434,7 +427,7 @@ template <class ELFT> bool elf::isRelroSection(const OutputSectionBase *Sec) { return true; if (Sec == In<ELFT>::GotPlt->OutSec) return Config->ZNow; - if (Sec == Out<ELFT>::Dynamic || Sec == In<ELFT>::Got->OutSec) + if (Sec == In<ELFT>::Dynamic->OutSec || Sec == In<ELFT>::Got->OutSec) return true; StringRef S = Sec->getName(); return S == ".data.rel.ro" || S == ".ctors" || S == ".dtors" || S == ".jcr" || @@ -861,6 +854,17 @@ template <class ELFT> void Writer<ELFT>::sortSections() { Script<ELFT>::X->adjustSectionsAfterSorting(); } +template <class ELFT> +static void +finalizeSynthetic(const std::vector<SyntheticSection<ELFT> *> &Sections) { + for (SyntheticSection<ELFT> *SS : Sections) + if (SS && SS->OutSec) { + SS->finalize(); + SS->OutSec->Size = 0; + SS->OutSec->assignOffsets(); + } +} + // Create output section objects and add them to OutputSections. template <class ELFT> void Writer<ELFT>::finalizeSections() { Out<ELFT>::DebugInfo = findSection(".debug_info"); @@ -882,8 +886,7 @@ template <class ELFT> void Writer<ELFT>::finalizeSections() { // Even the author of gold doesn't remember why gold behaves that way. // https://sourceware.org/ml/binutils/2002-03/msg00360.html if (Out<ELFT>::DynSymTab) - Symtab<ELFT>::X->addSynthetic("_DYNAMIC", Out<ELFT>::Dynamic, 0, - STV_HIDDEN); + addRegular("_DYNAMIC", In<ELFT>::Dynamic, 0); // Define __rel[a]_iplt_{start,end} symbols if needed. addRelIpltSymbols(); @@ -940,11 +943,11 @@ template <class ELFT> void Writer<ELFT>::finalizeSections() { // at the end because some tags like RELSZ depend on result // of finalizing other sections. for (OutputSectionBase *Sec : OutputSections) - if (Sec != Out<ELFT>::Dynamic) - Sec->finalize(); + Sec->finalize(); - if (Out<ELFT>::DynSymTab) - Out<ELFT>::Dynamic->finalize(); + finalizeSynthetic<ELFT>({In<ELFT>::ShStrTab, In<ELFT>::StrTab, + In<ELFT>::DynStrTab, In<ELFT>::Got, In<ELFT>::GotPlt, + In<ELFT>::Dynamic}); // Now that all output offsets are fixed. Finalize mergeable sections // to fix their maps from input offsets to output offsets. @@ -992,7 +995,7 @@ template <class ELFT> void Writer<ELFT>::addPredefinedSections() { Add(Out<ELFT>::GnuHashTab); Add(Out<ELFT>::HashTab); - Add(Out<ELFT>::Dynamic); + addInputSec(In<ELFT>::Dynamic); addInputSec(In<ELFT>::DynStrTab); if (Out<ELFT>::RelaDyn->hasRelocs()) Add(Out<ELFT>::RelaDyn); @@ -1006,10 +1009,8 @@ template <class ELFT> void Writer<ELFT>::addPredefinedSections() { // We fill .got and .got.plt sections in scanRelocs(). This is the // reason we don't add it earlier in createSections(). - if (needsGot()) { - In<ELFT>::Got->finalize(); + if (needsGot()) addInputSec(In<ELFT>::Got); - } if (!In<ELFT>::GotPlt->empty()) addInputSec(In<ELFT>::GotPlt); @@ -1158,8 +1159,8 @@ template <class ELFT> std::vector<PhdrEntry<ELFT>> Writer<ELFT>::createPhdrs() { // Add an entry for .dynamic. if (Out<ELFT>::DynSymTab) { - Phdr &H = *AddHdr(PT_DYNAMIC, Out<ELFT>::Dynamic->getPhdrFlags()); - H.add(Out<ELFT>::Dynamic); + Phdr &H = *AddHdr(PT_DYNAMIC, In<ELFT>::Dynamic->OutSec->getPhdrFlags()); + H.add(In<ELFT>::Dynamic->OutSec); } // PT_GNU_RELRO includes all sections that should be marked as |

