Index: lld/ELF/SyntheticSections.h =================================================================== --- lld/ELF/SyntheticSections.h +++ lld/ELF/SyntheticSections.h @@ -26,6 +26,7 @@ #include "InputSection.h" #include "llvm/ADT/MapVector.h" #include "llvm/MC/StringTableBuilder.h" +#include namespace lld { namespace elf { @@ -335,29 +336,8 @@ typedef typename ELFT::Shdr Elf_Shdr; typedef typename ELFT::Sym Elf_Sym; - // 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 { - OutputSection *OutSec; - InputSection *InSec; - uint64_t Val; - const Symbol *Sym; - }; - enum KindT { SecAddr, SecSize, SymAddr, PlainInt, InSecAddr } Kind; - Entry(int32_t Tag, OutputSection *OutSec, KindT Kind = SecAddr) - : Tag(Tag), OutSec(OutSec), Kind(Kind) {} - Entry(int32_t Tag, InputSection *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 Symbol *Sym) : Tag(Tag), Sym(Sym), Kind(SymAddr) {} - }; - // finalizeContents() fills this vector with the section contents. - std::vector Entries; + std::vector>> Entries; public: DynamicSection(); @@ -367,7 +347,13 @@ private: void addEntries(); - void add(Entry E) { Entries.push_back(E); } + + void addInt(int32_t Tag, uint64_t Val); + void addInSec(int32_t Tag, InputSection *Sec); + void addOutSec(int32_t Tag, OutputSection *Sec); + void addSize(int32_t Tag, OutputSection *Sec); + void addSym(int32_t Tag, Symbol *Sym); + uint64_t Size = 0; }; Index: lld/ELF/SyntheticSections.cpp =================================================================== --- lld/ELF/SyntheticSections.cpp +++ lld/ELF/SyntheticSections.cpp @@ -983,25 +983,52 @@ addEntries(); } +template +void DynamicSection::addInt(int32_t Tag, uint64_t Val) { + Entries.push_back({Tag, [=] { return Val; }}); +} + +template +void DynamicSection::addInSec(int32_t Tag, InputSection *Sec) { + Entries.push_back({Tag, [=] { return Sec->getParent()->Addr + Sec->OutSecOff; }}); +} + +template +void DynamicSection::addOutSec(int32_t Tag, OutputSection *Sec) { + Entries.push_back({Tag, [=] { return Sec->Addr; }}); +} + +template +void DynamicSection::addSize(int32_t Tag, OutputSection *Sec) { + Entries.push_back({Tag, [=] { return Sec->Size; }}); +} + +template +void DynamicSection::addSym(int32_t Tag, Symbol *Sym) { + Entries.push_back({Tag, [=] { return Sym->getVA(); }}); +} + // There are some dynamic entries that don't depend on other sections. // Such entries can be set early. template void DynamicSection::addEntries() { // Add strings to .dynstr early so that .dynstr's size will be // fixed early. for (StringRef S : Config->FilterList) - add({DT_FILTER, InX::DynStrTab->addString(S)}); + addInt(DT_FILTER, InX::DynStrTab->addString(S)); for (StringRef S : Config->AuxiliaryList) - add({DT_AUXILIARY, InX::DynStrTab->addString(S)}); + addInt(DT_AUXILIARY, InX::DynStrTab->addString(S)); + if (!Config->Rpath.empty()) - add({Config->EnableNewDtags ? DT_RUNPATH : DT_RPATH, - InX::DynStrTab->addString(Config->Rpath)}); + addInt(Config->EnableNewDtags ? DT_RUNPATH : DT_RPATH, + InX::DynStrTab->addString(Config->Rpath)); + for (InputFile *File : SharedFiles) { SharedFile *F = cast>(File); if (F->isNeeded()) - add({DT_NEEDED, InX::DynStrTab->addString(F->SoName)}); + addInt(DT_NEEDED, InX::DynStrTab->addString(F->SoName)); } if (!Config->SoName.empty()) - add({DT_SONAME, InX::DynStrTab->addString(Config->SoName)}); + addInt(DT_SONAME, InX::DynStrTab->addString(Config->SoName)); // Set DT_FLAGS and DT_FLAGS_1. uint32_t DtFlags = 0; @@ -1022,9 +1049,9 @@ } if (DtFlags) - add({DT_FLAGS, DtFlags}); + addInt(DT_FLAGS, DtFlags); if (DtFlags1) - add({DT_FLAGS_1, DtFlags1}); + addInt(DT_FLAGS_1, DtFlags1); // DT_DEBUG is a pointer to debug informaion used by debuggers at runtime. We // need it for each process, so we don't write it for DSOs. The loader writes @@ -1035,7 +1062,7 @@ // debugger this information. Such systems may choose make .dynamic read-only. // If the target is such a system (used -z rodynamic) don't write DT_DEBUG. if (!Config->Shared && !Config->Relocatable && !Config->ZRodynamic) - add({DT_DEBUG, (uint64_t)0}); + addInt(DT_DEBUG, 0); } // Add remaining entries to complete .dynamic contents. @@ -1045,13 +1072,12 @@ this->Link = InX::DynStrTab->getParent()->SectionIndex; if (In::RelaDyn->getParent() && !In::RelaDyn->empty()) { - add({In::RelaDyn->DynamicTag, In::RelaDyn}); - add({In::RelaDyn->SizeDynamicTag, In::RelaDyn->getParent(), - Entry::SecSize}); + addInSec(In::RelaDyn->DynamicTag, In::RelaDyn); + addSize(In::RelaDyn->SizeDynamicTag, In::RelaDyn->getParent()); bool IsRela = Config->IsRela; - add({IsRela ? DT_RELAENT : DT_RELENT, - uint64_t(IsRela ? sizeof(Elf_Rela) : sizeof(Elf_Rel))}); + addInt(IsRela ? DT_RELAENT : DT_RELENT, + IsRela ? sizeof(Elf_Rela) : sizeof(Elf_Rel)); // MIPS dynamic loader does not support RELCOUNT tag. // The problem is in the tight relation between dynamic @@ -1059,85 +1085,85 @@ if (Config->EMachine != EM_MIPS) { size_t NumRelativeRels = In::RelaDyn->getRelativeRelocCount(); if (Config->ZCombreloc && NumRelativeRels) - add({IsRela ? DT_RELACOUNT : DT_RELCOUNT, NumRelativeRels}); + addInt(IsRela ? DT_RELACOUNT : DT_RELCOUNT, NumRelativeRels); } } if (In::RelaPlt->getParent() && !In::RelaPlt->empty()) { - add({DT_JMPREL, In::RelaPlt}); - add({DT_PLTRELSZ, In::RelaPlt->getParent(), Entry::SecSize}); + addInSec(DT_JMPREL, In::RelaPlt); + addSize(DT_PLTRELSZ, In::RelaPlt->getParent()); switch (Config->EMachine) { case EM_MIPS: - add({DT_MIPS_PLTGOT, InX::GotPlt}); + addInSec(DT_MIPS_PLTGOT, InX::GotPlt); break; case EM_SPARCV9: - add({DT_PLTGOT, InX::Plt}); + addInSec(DT_PLTGOT, InX::Plt); break; default: - add({DT_PLTGOT, InX::GotPlt}); + addInSec(DT_PLTGOT, InX::GotPlt); break; } - add({DT_PLTREL, uint64_t(Config->IsRela ? DT_RELA : DT_REL)}); + addInt(DT_PLTREL, Config->IsRela ? DT_RELA : DT_REL); } - add({DT_SYMTAB, InX::DynSymTab}); - add({DT_SYMENT, sizeof(Elf_Sym)}); - add({DT_STRTAB, InX::DynStrTab}); - add({DT_STRSZ, InX::DynStrTab->getSize()}); + addInSec(DT_SYMTAB, InX::DynSymTab); + addInt(DT_SYMENT, sizeof(Elf_Sym)); + addInSec(DT_STRTAB, InX::DynStrTab); + addInt(DT_STRSZ, InX::DynStrTab->getSize()); if (!Config->ZText) - add({DT_TEXTREL, (uint64_t)0}); + addInt(DT_TEXTREL, 0); if (InX::GnuHashTab) - add({DT_GNU_HASH, InX::GnuHashTab}); + addInSec(DT_GNU_HASH, InX::GnuHashTab); if (InX::HashTab) - add({DT_HASH, InX::HashTab}); + addInSec(DT_HASH, InX::HashTab); if (Out::PreinitArray) { - add({DT_PREINIT_ARRAY, Out::PreinitArray}); - add({DT_PREINIT_ARRAYSZ, Out::PreinitArray, Entry::SecSize}); + addOutSec(DT_PREINIT_ARRAY, Out::PreinitArray); + addSize(DT_PREINIT_ARRAYSZ, Out::PreinitArray); } if (Out::InitArray) { - add({DT_INIT_ARRAY, Out::InitArray}); - add({DT_INIT_ARRAYSZ, Out::InitArray, Entry::SecSize}); + addOutSec(DT_INIT_ARRAY, Out::InitArray); + addSize(DT_INIT_ARRAYSZ, Out::InitArray); } if (Out::FiniArray) { - add({DT_FINI_ARRAY, Out::FiniArray}); - add({DT_FINI_ARRAYSZ, Out::FiniArray, Entry::SecSize}); + addOutSec(DT_FINI_ARRAY, Out::FiniArray); + addSize(DT_FINI_ARRAYSZ, Out::FiniArray); } if (Symbol *B = Symtab->find(Config->Init)) if (B->isDefined()) - add({DT_INIT, B}); + addSym(DT_INIT, B); if (Symbol *B = Symtab->find(Config->Fini)) if (B->isDefined()) - add({DT_FINI, B}); + addSym(DT_FINI, B); bool HasVerNeed = In::VerNeed->getNeedNum() != 0; if (HasVerNeed || In::VerDef) - add({DT_VERSYM, In::VerSym}); + addInSec(DT_VERSYM, In::VerSym); if (In::VerDef) { - add({DT_VERDEF, In::VerDef}); - add({DT_VERDEFNUM, getVerDefNum()}); + addInSec(DT_VERDEF, In::VerDef); + addInt(DT_VERDEFNUM, getVerDefNum()); } if (HasVerNeed) { - add({DT_VERNEED, In::VerNeed}); - add({DT_VERNEEDNUM, In::VerNeed->getNeedNum()}); + addInSec(DT_VERNEED, In::VerNeed); + addInt(DT_VERNEEDNUM, In::VerNeed->getNeedNum()); } if (Config->EMachine == EM_MIPS) { - add({DT_MIPS_RLD_VERSION, 1}); - add({DT_MIPS_FLAGS, RHF_NOTPOT}); - add({DT_MIPS_BASE_ADDRESS, Target->getImageBase()}); - add({DT_MIPS_SYMTABNO, InX::DynSymTab->getNumSymbols()}); - add({DT_MIPS_LOCAL_GOTNO, InX::MipsGot->getLocalEntriesNum()}); + addInt(DT_MIPS_RLD_VERSION, 1); + addInt(DT_MIPS_FLAGS, RHF_NOTPOT); + addInt(DT_MIPS_BASE_ADDRESS, Target->getImageBase()); + addInt(DT_MIPS_SYMTABNO, InX::DynSymTab->getNumSymbols()); + addInt(DT_MIPS_LOCAL_GOTNO, InX::MipsGot->getLocalEntriesNum()); if (const Symbol *B = InX::MipsGot->getFirstGlobalEntry()) - add({DT_MIPS_GOTSYM, B->DynsymIndex}); + addInt(DT_MIPS_GOTSYM, B->DynsymIndex); else - add({DT_MIPS_GOTSYM, InX::DynSymTab->getNumSymbols()}); - add({DT_PLTGOT, InX::MipsGot}); + addInt(DT_MIPS_GOTSYM, InX::DynSymTab->getNumSymbols()); + addInSec(DT_PLTGOT, InX::MipsGot); if (InX::MipsRldMap) - add({DT_MIPS_RLD_MAP, InX::MipsRldMap}); + addInSec(DT_MIPS_RLD_MAP, InX::MipsRldMap); } - add({DT_NULL, (uint64_t)0}); + addInt(DT_NULL, 0); getParent()->Link = this->Link; this->Size = Entries.size() * this->Entsize; @@ -1146,25 +1172,9 @@ template void DynamicSection::writeTo(uint8_t *Buf) { auto *P = reinterpret_cast(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->getParent()->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->getVA(); - break; - case Entry::PlainInt: - P->d_un.d_val = E.Val; - break; - } + for (std::pair> &KV : Entries) { + P->d_tag = KV.first; + P->d_un.d_val = KV.second(); ++P; } }