[PATCH] D40338: Use lambdas to store lazy-evaluated .dynamic entries.

Rafael Avila de Espindola via llvm-commits llvm-commits at lists.llvm.org
Wed Nov 22 09:11:50 PST 2017


A version rebased to cover the recently added mips case LGTM.

Cheers,
Rafael

Rui Ueyama via Phabricator via llvm-commits
<llvm-commits at lists.llvm.org> writes:

> ruiu created this revision.
> Herald added subscribers: arichardson, emaste.
>
> Use lambdas to store lazy-evaluated .dynamic entries.
>
>
> https://reviews.llvm.org/D40338
>
> Files:
>   lld/ELF/SyntheticSections.cpp
>   lld/ELF/SyntheticSections.h
>
> 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 <functional>
>  
>  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<Entry> Entries;
> +  std::vector<std::pair<int32_t, std::function<uint64_t()>>> 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 <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 +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,126 +1072,109 @@
>  
>    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
>      // relocations and GOT. So do not emit this tag on MIPS.
>      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()});
> -    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;
>  }
>  
>  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:
> -      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;
>    }
>  }
> _______________________________________________
> llvm-commits mailing list
> llvm-commits at lists.llvm.org
> http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits


More information about the llvm-commits mailing list