[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