[lld] r258723 - Avoid almost duplication in .dynamic finalize and write.

Rafael Espindola via llvm-commits llvm-commits at lists.llvm.org
Mon Jan 25 13:32:04 PST 2016


Author: rafael
Date: Mon Jan 25 15:32:04 2016
New Revision: 258723

URL: http://llvm.org/viewvc/llvm-project?rev=258723&view=rev
Log:
Avoid almost duplication in .dynamic finalize and write.

There are a few cases where we have almost duplicated code.

This patches fixes the simplest: the finalize and write of dynamic
section. Right now they have to have exactly the same structure to
decide if a DT_* entry is needed and then to actually write it.

We cannot just write it to a std::vector in the first pass since
addresses have not been computed yet.

Modified:
    lld/trunk/ELF/OutputSections.cpp
    lld/trunk/ELF/OutputSections.h
    lld/trunk/ELF/Writer.cpp

Modified: lld/trunk/ELF/OutputSections.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/OutputSections.cpp?rev=258723&r1=258722&r2=258723&view=diff
==============================================================================
--- lld/trunk/ELF/OutputSections.cpp (original)
+++ lld/trunk/ELF/OutputSections.cpp Mon Jan 25 15:32:04 2016
@@ -593,61 +593,76 @@ template <class ELFT> void DynamicSectio
   Elf_Shdr &Header = this->Header;
   Header.sh_link = Out<ELFT>::DynStrTab->SectionIndex;
 
-  unsigned NumEntries = 0;
+  // Reserve strings. We know that these are the last string to be added to
+  // DynStrTab and doing this here allows this function to set DT_STRSZ.
+  if (!Config->RPath.empty())
+    Out<ELFT>::DynStrTab->reserve(Config->RPath);
+  if (!Config->SoName.empty())
+    Out<ELFT>::DynStrTab->reserve(Config->SoName);
+  for (const std::unique_ptr<SharedFile<ELFT>> &F : SymTab.getSharedFiles())
+    if (F->isNeeded())
+      Out<ELFT>::DynStrTab->reserve(F->getSoName());
+  Out<ELFT>::DynStrTab->finalize();
+
   if (Out<ELFT>::RelaDyn->hasRelocs()) {
-    ++NumEntries; // DT_RELA / DT_REL
-    ++NumEntries; // DT_RELASZ / DT_RELSZ
-    ++NumEntries; // DT_RELAENT / DT_RELENT
+    bool IsRela = Out<ELFT>::RelaDyn->isRela();
+    Entries.push_back({IsRela ? DT_RELA : DT_REL, Out<ELFT>::RelaDyn});
+    Entries.push_back(
+        {IsRela ? DT_RELASZ : DT_RELSZ, Out<ELFT>::RelaDyn->getSize()});
+    Entries.push_back({IsRela ? DT_RELAENT : DT_RELENT,
+                       uintX_t(IsRela ? sizeof(Elf_Rela) : sizeof(Elf_Rel))});
   }
   if (Out<ELFT>::RelaPlt && Out<ELFT>::RelaPlt->hasRelocs()) {
-    ++NumEntries; // DT_JMPREL
-    ++NumEntries; // DT_PLTRELSZ
-    ++NumEntries; // DT_PLTGOT / DT_MIPS_PLTGOT
-    ++NumEntries; // DT_PLTREL
+    Entries.push_back({DT_JMPREL, Out<ELFT>::RelaPlt});
+    Entries.push_back({DT_PLTRELSZ, Out<ELFT>::RelaPlt->getSize()});
+    Entries.push_back({Config->EMachine == EM_MIPS ? DT_MIPS_PLTGOT : DT_PLTGOT,
+                       Out<ELFT>::GotPlt});
+    Entries.push_back(
+        {DT_PLTREL, Out<ELFT>::RelaPlt->isRela() ? DT_RELA : DT_REL});
   }
 
-  ++NumEntries; // DT_SYMTAB
-  ++NumEntries; // DT_SYMENT
-  ++NumEntries; // DT_STRTAB
-  ++NumEntries; // DT_STRSZ
+  Entries.push_back({DT_SYMTAB, Out<ELFT>::DynSymTab});
+  Entries.push_back({DT_SYMENT, sizeof(Elf_Sym)});
+  Entries.push_back({DT_STRTAB, Out<ELFT>::DynStrTab});
+  Entries.push_back({DT_STRSZ, Out<ELFT>::DynStrTab->getSize()});
   if (Out<ELFT>::GnuHashTab)
-    ++NumEntries; // DT_GNU_HASH
+    Entries.push_back({DT_GNU_HASH, Out<ELFT>::GnuHashTab});
   if (Out<ELFT>::HashTab)
-    ++NumEntries; // DT_HASH
+    Entries.push_back({DT_HASH, Out<ELFT>::HashTab});
 
-  if (!Config->RPath.empty()) {
-    ++NumEntries; // DT_RUNPATH / DT_RPATH
-    Out<ELFT>::DynStrTab->reserve(Config->RPath);
-  }
+  if (!Config->RPath.empty())
+    Entries.push_back({Config->EnableNewDtags ? DT_RUNPATH : DT_RPATH,
+                       Out<ELFT>::DynStrTab->addString(Config->RPath)});
 
-  if (!Config->SoName.empty()) {
-    ++NumEntries; // DT_SONAME
-    Out<ELFT>::DynStrTab->reserve(Config->SoName);
-  }
+  if (!Config->SoName.empty())
+    Entries.push_back(
+        {DT_SONAME, Out<ELFT>::DynStrTab->addString(Config->SoName)});
 
-  if (PreInitArraySec)
-    NumEntries += 2;
-  if (InitArraySec)
-    NumEntries += 2;
-  if (FiniArraySec)
-    NumEntries += 2;
-
-  for (const std::unique_ptr<SharedFile<ELFT>> &F : SymTab.getSharedFiles()) {
-    if (!F->isNeeded())
-      continue;
-    Out<ELFT>::DynStrTab->reserve(F->getSoName());
-    ++NumEntries;
+  if (PreInitArraySec) {
+    Entries.push_back({DT_PREINIT_ARRAY, PreInitArraySec});
+    Entries.push_back({DT_PREINIT_ARRAYSZ, PreInitArraySec->getSize()});
+  }
+  if (InitArraySec) {
+    Entries.push_back({DT_INIT_ARRAY, InitArraySec});
+    Entries.push_back({DT_INIT_ARRAYSZ, (uintX_t)InitArraySec->getSize()});
+  }
+  if (FiniArraySec) {
+    Entries.push_back({DT_FINI_ARRAY, FiniArraySec});
+    Entries.push_back({DT_FINI_ARRAYSZ, (uintX_t)FiniArraySec->getSize()});
   }
 
+  for (const std::unique_ptr<SharedFile<ELFT>> &F : SymTab.getSharedFiles())
+    if (F->isNeeded())
+      Entries.push_back(
+          {DT_NEEDED, Out<ELFT>::DynStrTab->addString(F->getSoName())});
+
   if (Symbol *S = SymTab.getSymbols().lookup(Config->Init))
-    InitSym = S->Body;
+    Entries.push_back({DT_INIT, S->Body});
   if (Symbol *S = SymTab.getSymbols().lookup(Config->Fini))
-    FiniSym = S->Body;
-  if (InitSym)
-    ++NumEntries; // DT_INIT
-  if (FiniSym)
-    ++NumEntries; // DT_FINI
+    Entries.push_back({DT_FINI, S->Body});
 
+  uint32_t DtFlags = 0;
+  uint32_t DtFlags1 = 0;
   if (Config->Bsymbolic)
     DtFlags |= DF_SYMBOLIC;
   if (Config->ZNodelete)
@@ -662,133 +677,53 @@ template <class ELFT> void DynamicSectio
   }
 
   if (DtFlags)
-    ++NumEntries; // DT_FLAGS
+    Entries.push_back({DT_FLAGS, DtFlags});
   if (DtFlags1)
-    ++NumEntries; // DT_FLAGS_1
+    Entries.push_back({DT_FLAGS_1, DtFlags1});
 
   if (!Config->Entry.empty())
-    ++NumEntries; // DT_DEBUG
+    Entries.push_back({DT_DEBUG, (uintX_t)0});
 
   if (Config->EMachine == EM_MIPS) {
-    ++NumEntries; // DT_MIPS_RLD_VERSION
-    ++NumEntries; // DT_MIPS_FLAGS
-    ++NumEntries; // DT_MIPS_BASE_ADDRESS
-    ++NumEntries; // DT_MIPS_SYMTABNO
-    ++NumEntries; // DT_MIPS_LOCAL_GOTNO
-    ++NumEntries; // DT_MIPS_GOTSYM;
-    ++NumEntries; // DT_PLTGOT
+    Entries.push_back({DT_MIPS_RLD_VERSION, 1});
+    Entries.push_back({DT_MIPS_FLAGS, RHF_NOTPOT});
+    Entries.push_back({DT_MIPS_BASE_ADDRESS, (uintX_t)Target->getVAStart()});
+    Entries.push_back(
+        {DT_MIPS_SYMTABNO, Out<ELFT>::DynSymTab->getNumSymbols()});
+    Entries.push_back(
+        {DT_MIPS_LOCAL_GOTNO, Out<ELFT>::Got->getMipsLocalEntriesNum()});
+    if (const SymbolBody *B = Out<ELFT>::Got->getMipsFirstGlobalEntry())
+      Entries.push_back({DT_MIPS_GOTSYM, B->DynamicSymbolTableIndex});
+    else
+      Entries.push_back(
+          {DT_MIPS_GOTSYM, Out<ELFT>::DynSymTab->getNumSymbols()});
+    Entries.push_back({DT_PLTGOT, Out<ELFT>::Got});
     if (Out<ELFT>::MipsRldMap)
-      ++NumEntries; // DT_MIPS_RLD_MAP
+      Entries.push_back({DT_MIPS_RLD_MAP, Out<ELFT>::MipsRldMap});
   }
 
-  ++NumEntries; // DT_NULL
-
-  Header.sh_size = NumEntries * Header.sh_entsize;
+  // +1 for DT_NULL
+  Header.sh_size = (Entries.size() + 1) * Header.sh_entsize;
 }
 
 template <class ELFT> void DynamicSection<ELFT>::writeTo(uint8_t *Buf) {
   auto *P = reinterpret_cast<Elf_Dyn *>(Buf);
 
-  auto WritePtr = [&](int32_t Tag, uint64_t Val) {
-    P->d_tag = Tag;
-    P->d_un.d_ptr = Val;
-    ++P;
-  };
-
-  auto WriteVal = [&](int32_t Tag, uint32_t Val) {
-    P->d_tag = Tag;
-    P->d_un.d_val = Val;
+  for (const Entry &E : Entries) {
+    P->d_tag = E.Tag;
+    switch (E.Kind) {
+    case Entry::SecAddr:
+      P->d_un.d_ptr = E.OutSec->getVA();
+      break;
+    case Entry::SymAddr:
+      P->d_un.d_ptr = getSymVA<ELFT>(*E.Sym);
+      break;
+    case Entry::PlainInt:
+      P->d_un.d_val = E.Val;
+      break;
+    }
     ++P;
-  };
-
-  if (Out<ELFT>::RelaDyn->hasRelocs()) {
-    bool IsRela = Out<ELFT>::RelaDyn->isRela();
-    WritePtr(IsRela ? DT_RELA : DT_REL, Out<ELFT>::RelaDyn->getVA());
-    WriteVal(IsRela ? DT_RELASZ : DT_RELSZ, Out<ELFT>::RelaDyn->getSize());
-    WriteVal(IsRela ? DT_RELAENT : DT_RELENT,
-             IsRela ? sizeof(Elf_Rela) : sizeof(Elf_Rel));
   }
-  if (Out<ELFT>::RelaPlt && Out<ELFT>::RelaPlt->hasRelocs()) {
-    WritePtr(DT_JMPREL, Out<ELFT>::RelaPlt->getVA());
-    WriteVal(DT_PLTRELSZ, Out<ELFT>::RelaPlt->getSize());
-    // On MIPS, the address of the .got.plt section is stored in
-    // the DT_MIPS_PLTGOT entry because the DT_PLTGOT entry points to
-    // the .got section. See "Dynamic Section" in the following document:
-    // https://sourceware.org/ml/binutils/2008-07/txt00000.txt
-    WritePtr((Config->EMachine == EM_MIPS) ? DT_MIPS_PLTGOT : DT_PLTGOT,
-             Out<ELFT>::GotPlt->getVA());
-    WriteVal(DT_PLTREL, Out<ELFT>::RelaPlt->isRela() ? DT_RELA : DT_REL);
-  }
-
-  WritePtr(DT_SYMTAB, Out<ELFT>::DynSymTab->getVA());
-  WritePtr(DT_SYMENT, sizeof(Elf_Sym));
-  WritePtr(DT_STRTAB, Out<ELFT>::DynStrTab->getVA());
-  WriteVal(DT_STRSZ, Out<ELFT>::DynStrTab->getSize());
-  if (Out<ELFT>::GnuHashTab)
-    WritePtr(DT_GNU_HASH, Out<ELFT>::GnuHashTab->getVA());
-  if (Out<ELFT>::HashTab)
-    WritePtr(DT_HASH, Out<ELFT>::HashTab->getVA());
-
-  // If --enable-new-dtags is set, lld emits DT_RUNPATH
-  // instead of DT_RPATH. The two tags are functionally
-  // equivalent except for the following:
-  // - DT_RUNPATH is searched after LD_LIBRARY_PATH, while
-  //   DT_RPATH is searched before.
-  // - DT_RUNPATH is used only to search for direct
-  //   dependencies of the object it's contained in, while
-  //   DT_RPATH is used for indirect dependencies as well.
-  if (!Config->RPath.empty())
-    WriteVal(Config->EnableNewDtags ? DT_RUNPATH : DT_RPATH,
-             Out<ELFT>::DynStrTab->addString(Config->RPath));
-
-  if (!Config->SoName.empty())
-    WriteVal(DT_SONAME, Out<ELFT>::DynStrTab->addString(Config->SoName));
-
-  auto WriteArray = [&](int32_t T1, int32_t T2,
-                        const OutputSectionBase<ELFT> *Sec) {
-    if (!Sec)
-      return;
-    WritePtr(T1, Sec->getVA());
-    WriteVal(T2, Sec->getSize());
-  };
-  WriteArray(DT_PREINIT_ARRAY, DT_PREINIT_ARRAYSZ, PreInitArraySec);
-  WriteArray(DT_INIT_ARRAY, DT_INIT_ARRAYSZ, InitArraySec);
-  WriteArray(DT_FINI_ARRAY, DT_FINI_ARRAYSZ, FiniArraySec);
-
-  for (const std::unique_ptr<SharedFile<ELFT>> &F : SymTab.getSharedFiles())
-    if (F->isNeeded())
-      WriteVal(DT_NEEDED, Out<ELFT>::DynStrTab->addString(F->getSoName()));
-
-  if (InitSym)
-    WritePtr(DT_INIT, getSymVA<ELFT>(*InitSym));
-  if (FiniSym)
-    WritePtr(DT_FINI, getSymVA<ELFT>(*FiniSym));
-  if (DtFlags)
-    WriteVal(DT_FLAGS, DtFlags);
-  if (DtFlags1)
-    WriteVal(DT_FLAGS_1, DtFlags1);
-  if (!Config->Entry.empty())
-    WriteVal(DT_DEBUG, 0);
-
-  // See "Dynamic Section" in Chapter 5 in the following document
-  // for detailed description:
-  // ftp://www.linux-mips.org/pub/linux/mips/doc/ABI/mipsabi.pdf
-  if (Config->EMachine == EM_MIPS) {
-    WriteVal(DT_MIPS_RLD_VERSION, 1);
-    WriteVal(DT_MIPS_FLAGS, RHF_NOTPOT);
-    WritePtr(DT_MIPS_BASE_ADDRESS, Target->getVAStart());
-    WriteVal(DT_MIPS_SYMTABNO, Out<ELFT>::DynSymTab->getNumSymbols());
-    WriteVal(DT_MIPS_LOCAL_GOTNO, Out<ELFT>::Got->getMipsLocalEntriesNum());
-    if (const SymbolBody *B = Out<ELFT>::Got->getMipsFirstGlobalEntry())
-      WriteVal(DT_MIPS_GOTSYM, B->DynamicSymbolTableIndex);
-    else
-      WriteVal(DT_MIPS_GOTSYM, Out<ELFT>::DynSymTab->getNumSymbols());
-    WritePtr(DT_PLTGOT, Out<ELFT>::Got->getVA());
-    if (Out<ELFT>::MipsRldMap)
-      WritePtr(DT_MIPS_RLD_MAP, Out<ELFT>::MipsRldMap->getVA());
-  }
-
-  WriteVal(DT_NULL, 0);
 }
 
 template <class ELFT>

Modified: lld/trunk/ELF/OutputSections.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/OutputSections.h?rev=258723&r1=258722&r2=258723&view=diff
==============================================================================
--- lld/trunk/ELF/OutputSections.h (original)
+++ lld/trunk/ELF/OutputSections.h Mon Jan 25 15:32:04 2016
@@ -403,6 +403,23 @@ class DynamicSection final : public Outp
   typedef typename llvm::object::ELFFile<ELFT>::Elf_Rela Elf_Rela;
   typedef typename llvm::object::ELFFile<ELFT>::Elf_Shdr Elf_Shdr;
   typedef typename llvm::object::ELFFile<ELFT>::Elf_Sym Elf_Sym;
+  typedef typename llvm::object::ELFFile<ELFT>::uintX_t uintX_t;
+
+  struct Entry {
+    int32_t Tag;
+    union {
+      OutputSectionBase<ELFT> *OutSec;
+      uint64_t Val;
+      const SymbolBody *Sym;
+    };
+    enum KindT { SecAddr, SymAddr, PlainInt } Kind;
+    Entry(int32_t Tag, OutputSectionBase<ELFT> *OutSec)
+        : Tag(Tag), OutSec(OutSec), Kind(SecAddr) {}
+    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) {}
+  };
+  std::vector<Entry> Entries;
 
 public:
   DynamicSection(SymbolTable<ELFT> &SymTab);
@@ -415,10 +432,6 @@ public:
 
 private:
   SymbolTable<ELFT> &SymTab;
-  const SymbolBody *InitSym = nullptr;
-  const SymbolBody *FiniSym = nullptr;
-  uint32_t DtFlags = 0;
-  uint32_t DtFlags1 = 0;
 };
 
 template <class ELFT>

Modified: lld/trunk/ELF/Writer.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Writer.cpp?rev=258723&r1=258722&r2=258723&view=diff
==============================================================================
--- lld/trunk/ELF/Writer.cpp (original)
+++ lld/trunk/ELF/Writer.cpp Mon Jan 25 15:32:04 2016
@@ -874,16 +874,15 @@ template <class ELFT> void Writer<ELFT>:
     Out<ELFT>::ShStrTab->reserve(Sec->getName());
 
   // Finalizers fix each section's size.
-  // .dynamic section's finalizer may add strings to .dynstr,
-  // so finalize that early.
-  // Likewise, .dynsym is finalized early since that may fill up .gnu.hash.
-  Out<ELFT>::Dynamic->finalize();
+  // .dynsym is finalized early since that may fill up .gnu.hash.
   if (isOutputDynamic())
     Out<ELFT>::DynSymTab->finalize();
 
-  // Fill other section headers.
+  // Fill other section headers. The dynamic string table in finalized
+  // once the .dynamic finalizer has added a few last strings.
   for (OutputSectionBase<ELFT> *Sec : OutputSections)
-    Sec->finalize();
+    if (Sec != Out<ELFT>::DynStrTab)
+      Sec->finalize();
 }
 
 // This function add Out<ELFT>::* sections to OutputSections.




More information about the llvm-commits mailing list