[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