[lld] r318938 - Use lambdas to store lazy-evaluated .dynamic entries.
Rui Ueyama via llvm-commits
llvm-commits at lists.llvm.org
Thu Nov 23 18:15:51 PST 2017
Author: ruiu
Date: Thu Nov 23 18:15:51 2017
New Revision: 318938
URL: http://llvm.org/viewvc/llvm-project?rev=318938&view=rev
Log:
Use lambdas to store lazy-evaluated .dynamic entries.
Differential Revision: https://reviews.llvm.org/D40338
Modified:
lld/trunk/ELF/SyntheticSections.cpp
lld/trunk/ELF/SyntheticSections.h
Modified: lld/trunk/ELF/SyntheticSections.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/SyntheticSections.cpp?rev=318938&r1=318937&r2=318938&view=diff
==============================================================================
--- lld/trunk/ELF/SyntheticSections.cpp (original)
+++ lld/trunk/ELF/SyntheticSections.cpp Thu Nov 23 18:15:51 2017
@@ -983,25 +983,58 @@ DynamicSection<ELFT>::DynamicSection()
addEntries();
}
+template <class ELFT>
+void DynamicSection<ELFT>::add(int32_t Tag, std::function<uint64_t()> Fn) {
+ Entries.push_back({Tag, Fn});
+}
+
+template <class ELFT>
+void DynamicSection<ELFT>::addInt(int32_t Tag, uint64_t Val) {
+ Entries.push_back({Tag, [=] { return Val; }});
+}
+
+template <class ELFT>
+void DynamicSection<ELFT>::addInSec(int32_t Tag, InputSection *Sec) {
+ Entries.push_back(
+ {Tag, [=] { return Sec->getParent()->Addr + Sec->OutSecOff; }});
+}
+
+template <class ELFT>
+void DynamicSection<ELFT>::addOutSec(int32_t Tag, OutputSection *Sec) {
+ Entries.push_back({Tag, [=] { return Sec->Addr; }});
+}
+
+template <class ELFT>
+void DynamicSection<ELFT>::addSize(int32_t Tag, OutputSection *Sec) {
+ Entries.push_back({Tag, [=] { return Sec->Size; }});
+}
+
+template <class ELFT>
+void DynamicSection<ELFT>::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 <class ELFT> void DynamicSection<ELFT>::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<ELFT> *F = cast<SharedFile<ELFT>>(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 +1055,9 @@ template <class ELFT> void DynamicSectio
}
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 +1068,7 @@ template <class ELFT> void DynamicSectio
// 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 +1078,12 @@ template <class ELFT> void DynamicSectio
this->Link = InX::DynStrTab->getParent()->SectionIndex;
if (In<ELFT>::RelaDyn->getParent() && !In<ELFT>::RelaDyn->empty()) {
- add({In<ELFT>::RelaDyn->DynamicTag, In<ELFT>::RelaDyn});
- add({In<ELFT>::RelaDyn->SizeDynamicTag, In<ELFT>::RelaDyn->getParent(),
- Entry::SecSize});
+ addInSec(In<ELFT>::RelaDyn->DynamicTag, In<ELFT>::RelaDyn);
+ addSize(In<ELFT>::RelaDyn->SizeDynamicTag, In<ELFT>::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,89 +1091,87 @@ template <class ELFT> void DynamicSectio
if (Config->EMachine != EM_MIPS) {
size_t NumRelativeRels = In<ELFT>::RelaDyn->getRelativeRelocCount();
if (Config->ZCombreloc && NumRelativeRels)
- add({IsRela ? DT_RELACOUNT : DT_RELCOUNT, NumRelativeRels});
+ addInt(IsRela ? DT_RELACOUNT : DT_RELCOUNT, NumRelativeRels);
}
}
if (In<ELFT>::RelaPlt->getParent() && !In<ELFT>::RelaPlt->empty()) {
- add({DT_JMPREL, In<ELFT>::RelaPlt});
- add({DT_PLTRELSZ, In<ELFT>::RelaPlt->getParent(), Entry::SecSize});
+ addInSec(DT_JMPREL, In<ELFT>::RelaPlt);
+ addSize(DT_PLTRELSZ, In<ELFT>::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<ELFT>::VerNeed->getNeedNum() != 0;
if (HasVerNeed || In<ELFT>::VerDef)
- add({DT_VERSYM, In<ELFT>::VerSym});
+ addInSec(DT_VERSYM, In<ELFT>::VerSym);
if (In<ELFT>::VerDef) {
- add({DT_VERDEF, In<ELFT>::VerDef});
- add({DT_VERDEFNUM, getVerDefNum()});
+ addInSec(DT_VERDEF, In<ELFT>::VerDef);
+ addInt(DT_VERDEFNUM, getVerDefNum());
}
if (HasVerNeed) {
- add({DT_VERNEED, In<ELFT>::VerNeed});
- add({DT_VERNEEDNUM, In<ELFT>::VerNeed->getNeedNum()});
+ addInSec(DT_VERNEED, In<ELFT>::VerNeed);
+ addInt(DT_VERNEEDNUM, In<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, Target->getImageBase()});
- add({DT_MIPS_SYMTABNO, InX::DynSymTab->getNumSymbols()});
-
- // The number of local GOT entries has not yet been finalized. This value
- // will be set in writeTo().
- add({DT_MIPS_LOCAL_GOTNO, uint64_t(0)});
+ 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());
+
+ add(DT_MIPS_LOCAL_GOTNO, [] { return 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;
@@ -1150,28 +1180,9 @@ template <class ELFT> void DynamicSectio
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->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:
- if (Config->EMachine == EM_MIPS && E.Tag == DT_MIPS_LOCAL_GOTNO)
- P->d_un.d_val = InX::MipsGot->getLocalEntriesNum();
- else
- P->d_un.d_val = E.Val;
- break;
- }
+ for (std::pair<int32_t, std::function<uint64_t()>> &KV : Entries) {
+ P->d_tag = KV.first;
+ P->d_un.d_val = KV.second();
++P;
}
}
Modified: lld/trunk/ELF/SyntheticSections.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/SyntheticSections.h?rev=318938&r1=318937&r2=318938&view=diff
==============================================================================
--- lld/trunk/ELF/SyntheticSections.h (original)
+++ lld/trunk/ELF/SyntheticSections.h Thu Nov 23 18:15:51 2017
@@ -26,6 +26,7 @@
#include "InputSection.h"
#include "llvm/ADT/MapVector.h"
#include "llvm/MC/StringTableBuilder.h"
+#include <functional>
namespace lld {
namespace elf {
@@ -335,29 +336,8 @@ template <class ELFT> class DynamicSecti
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<Entry> Entries;
+ std::vector<std::pair<int32_t, std::function<uint64_t()>>> Entries;
public:
DynamicSection();
@@ -367,7 +347,14 @@ public:
private:
void addEntries();
- void add(Entry E) { Entries.push_back(E); }
+
+ void add(int32_t Tag, std::function<uint64_t()> Fn);
+ 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;
};
More information about the llvm-commits
mailing list