[lld] r287216 - [ELF] Convert SymbolTableSection to input section

Eugene Leviant via llvm-commits llvm-commits at lists.llvm.org
Thu Nov 17 01:16:34 PST 2016


Author: evgeny777
Date: Thu Nov 17 03:16:34 2016
New Revision: 287216

URL: http://llvm.org/viewvc/llvm-project?rev=287216&view=rev
Log:
[ELF] Convert SymbolTableSection to input section

Differential revision: https://reviews.llvm.org/D26740

Modified:
    lld/trunk/ELF/OutputSections.cpp
    lld/trunk/ELF/OutputSections.h
    lld/trunk/ELF/SyntheticSections.cpp
    lld/trunk/ELF/SyntheticSections.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=287216&r1=287215&r2=287216&view=diff
==============================================================================
--- lld/trunk/ELF/OutputSections.cpp (original)
+++ lld/trunk/ELF/OutputSections.cpp Thu Nov 17 03:16:34 2016
@@ -148,20 +148,20 @@ HashTableSection<ELFT>::HashTableSection
 }
 
 template <class ELFT> void HashTableSection<ELFT>::finalize() {
-  this->Link = Out<ELFT>::DynSymTab->SectionIndex;
+  this->Link = In<ELFT>::DynSymTab->OutSec->SectionIndex;
 
   unsigned NumEntries = 2;                             // nbucket and nchain.
-  NumEntries += Out<ELFT>::DynSymTab->getNumSymbols(); // The chain entries.
+  NumEntries += In<ELFT>::DynSymTab->getNumSymbols();  // The chain entries.
 
   // Create as many buckets as there are symbols.
   // FIXME: This is simplistic. We can try to optimize it, but implementing
   // support for SHT_GNU_HASH is probably even more profitable.
-  NumEntries += Out<ELFT>::DynSymTab->getNumSymbols();
+  NumEntries += In<ELFT>::DynSymTab->getNumSymbols();
   this->Size = NumEntries * sizeof(Elf_Word);
 }
 
 template <class ELFT> void HashTableSection<ELFT>::writeTo(uint8_t *Buf) {
-  unsigned NumSymbols = Out<ELFT>::DynSymTab->getNumSymbols();
+  unsigned NumSymbols = In<ELFT>::DynSymTab->getNumSymbols();
   auto *P = reinterpret_cast<Elf_Word *>(Buf);
   *P++ = NumSymbols; // nbucket
   *P++ = NumSymbols; // nchain
@@ -169,7 +169,7 @@ template <class ELFT> void HashTableSect
   Elf_Word *Buckets = P;
   Elf_Word *Chains = P + NumSymbols;
 
-  for (const SymbolTableEntry &S : Out<ELFT>::DynSymTab->getSymbols()) {
+  for (const SymbolTableEntry &S : In<ELFT>::DynSymTab->getSymbols()) {
     SymbolBody *Body = S.Symbol;
     StringRef Name = Body->getName();
     unsigned I = Body->DynsymIndex;
@@ -234,7 +234,7 @@ template <class ELFT> void GnuHashTableS
   // Second hash shift estimation: just predefined values.
   Shift2 = ELFT::Is64Bits ? 6 : 5;
 
-  this->Link = Out<ELFT>::DynSymTab->SectionIndex;
+  this->Link = In<ELFT>::DynSymTab->OutSec->SectionIndex;
   this->Size = sizeof(Elf_Word) * 4            // Header
                + sizeof(Elf_Off) * MaskWords   // Bloom Filter
                + sizeof(Elf_Word) * NBuckets   // Hash Buckets
@@ -253,7 +253,7 @@ template <class ELFT>
 void GnuHashTableSection<ELFT>::writeHeader(uint8_t *&Buf) {
   auto *P = reinterpret_cast<Elf_Word *>(Buf);
   *P++ = NBuckets;
-  *P++ = Out<ELFT>::DynSymTab->getNumSymbols() - Symbols.size();
+  *P++ = In<ELFT>::DynSymTab->getNumSymbols() - Symbols.size();
   *P++ = MaskWords;
   *P++ = Shift2;
   Buf = reinterpret_cast<uint8_t *>(P);
@@ -419,7 +419,7 @@ template <class ELFT> void OutputSection
 
   if (Type != SHT_RELA && Type != SHT_REL)
     return;
-  this->Link = Out<ELFT>::SymTab->SectionIndex;
+  this->Link = In<ELFT>::SymTab->OutSec->SectionIndex;
   // sh_info for SHT_REL[A] sections should contain the section header index of
   // the section to which the relocation applies.
   InputSectionBase<ELFT> *S = Sections[0]->getRelocatedSection();
@@ -819,188 +819,6 @@ template <class ELFT> void MergeOutputSe
 }
 
 template <class ELFT>
-SymbolTableSection<ELFT>::SymbolTableSection(
-    StringTableSection<ELFT> &StrTabSec)
-    : OutputSectionBase(StrTabSec.isDynamic() ? ".dynsym" : ".symtab",
-                        StrTabSec.isDynamic() ? SHT_DYNSYM : SHT_SYMTAB,
-                        StrTabSec.isDynamic() ? (uintX_t)SHF_ALLOC : 0),
-      StrTabSec(StrTabSec) {
-  this->Entsize = sizeof(Elf_Sym);
-  this->Addralign = sizeof(uintX_t);
-}
-
-// Orders symbols according to their positions in the GOT,
-// in compliance with MIPS ABI rules.
-// See "Global Offset Table" in Chapter 5 in the following document
-// for detailed description:
-// ftp://www.linux-mips.org/pub/linux/mips/doc/ABI/mipsabi.pdf
-static bool sortMipsSymbols(const SymbolBody *L, const SymbolBody *R) {
-  // Sort entries related to non-local preemptible symbols by GOT indexes.
-  // All other entries go to the first part of GOT in arbitrary order.
-  bool LIsInLocalGot = !L->IsInGlobalMipsGot;
-  bool RIsInLocalGot = !R->IsInGlobalMipsGot;
-  if (LIsInLocalGot || RIsInLocalGot)
-    return !RIsInLocalGot;
-  return L->GotIndex < R->GotIndex;
-}
-
-static uint8_t getSymbolBinding(SymbolBody *Body) {
-  Symbol *S = Body->symbol();
-  if (Config->Relocatable)
-    return S->Binding;
-  uint8_t Visibility = S->Visibility;
-  if (Visibility != STV_DEFAULT && Visibility != STV_PROTECTED)
-    return STB_LOCAL;
-  if (Config->NoGnuUnique && S->Binding == STB_GNU_UNIQUE)
-    return STB_GLOBAL;
-  return S->Binding;
-}
-
-template <class ELFT> void SymbolTableSection<ELFT>::finalize() {
-  if (this->Size)
-    return; // Already finalized.
-
-  this->Size = getNumSymbols() * sizeof(Elf_Sym);
-  this->Link = StrTabSec.OutSec->SectionIndex;
-  this->Info = NumLocals + 1;
-
-  if (Config->Relocatable) {
-    size_t I = NumLocals;
-    for (const SymbolTableEntry &S : Symbols)
-      S.Symbol->DynsymIndex = ++I;
-    return;
-  }
-
-  if (!StrTabSec.isDynamic()) {
-    std::stable_sort(Symbols.begin(), Symbols.end(),
-                     [](const SymbolTableEntry &L, const SymbolTableEntry &R) {
-                       return getSymbolBinding(L.Symbol) == STB_LOCAL &&
-                              getSymbolBinding(R.Symbol) != STB_LOCAL;
-                     });
-    return;
-  }
-  if (Out<ELFT>::GnuHashTab)
-    // NB: It also sorts Symbols to meet the GNU hash table requirements.
-    Out<ELFT>::GnuHashTab->addSymbols(Symbols);
-  else if (Config->EMachine == EM_MIPS)
-    std::stable_sort(Symbols.begin(), Symbols.end(),
-                     [](const SymbolTableEntry &L, const SymbolTableEntry &R) {
-                       return sortMipsSymbols(L.Symbol, R.Symbol);
-                     });
-  size_t I = 0;
-  for (const SymbolTableEntry &S : Symbols)
-    S.Symbol->DynsymIndex = ++I;
-}
-
-template <class ELFT> void SymbolTableSection<ELFT>::addSymbol(SymbolBody *B) {
-  Symbols.push_back({B, StrTabSec.addString(B->getName(), false)});
-}
-
-template <class ELFT> void SymbolTableSection<ELFT>::writeTo(uint8_t *Buf) {
-  Buf += sizeof(Elf_Sym);
-
-  // All symbols with STB_LOCAL binding precede the weak and global symbols.
-  // .dynsym only contains global symbols.
-  if (Config->Discard != DiscardPolicy::All && !StrTabSec.isDynamic())
-    writeLocalSymbols(Buf);
-
-  writeGlobalSymbols(Buf);
-}
-
-template <class ELFT>
-void SymbolTableSection<ELFT>::writeLocalSymbols(uint8_t *&Buf) {
-  // Iterate over all input object files to copy their local symbols
-  // to the output symbol table pointed by Buf.
-  for (ObjectFile<ELFT> *File : Symtab<ELFT>::X->getObjectFiles()) {
-    for (const std::pair<const DefinedRegular<ELFT> *, size_t> &P :
-         File->KeptLocalSyms) {
-      const DefinedRegular<ELFT> &Body = *P.first;
-      InputSectionBase<ELFT> *Section = Body.Section;
-      auto *ESym = reinterpret_cast<Elf_Sym *>(Buf);
-
-      if (!Section) {
-        ESym->st_shndx = SHN_ABS;
-        ESym->st_value = Body.Value;
-      } else {
-        const OutputSectionBase *OutSec = Section->OutSec;
-        ESym->st_shndx = OutSec->SectionIndex;
-        ESym->st_value = OutSec->Addr + Section->getOffset(Body);
-      }
-      ESym->st_name = P.second;
-      ESym->st_size = Body.template getSize<ELFT>();
-      ESym->setBindingAndType(STB_LOCAL, Body.Type);
-      Buf += sizeof(*ESym);
-    }
-  }
-}
-
-template <class ELFT>
-void SymbolTableSection<ELFT>::writeGlobalSymbols(uint8_t *Buf) {
-  // Write the internal symbol table contents to the output symbol table
-  // pointed by Buf.
-  auto *ESym = reinterpret_cast<Elf_Sym *>(Buf);
-  for (const SymbolTableEntry &S : Symbols) {
-    SymbolBody *Body = S.Symbol;
-    size_t StrOff = S.StrTabOffset;
-
-    uint8_t Type = Body->Type;
-    uintX_t Size = Body->getSize<ELFT>();
-
-    ESym->setBindingAndType(getSymbolBinding(Body), Type);
-    ESym->st_size = Size;
-    ESym->st_name = StrOff;
-    ESym->setVisibility(Body->symbol()->Visibility);
-    ESym->st_value = Body->getVA<ELFT>();
-
-    if (const OutputSectionBase *OutSec = getOutputSection(Body))
-      ESym->st_shndx = OutSec->SectionIndex;
-    else if (isa<DefinedRegular<ELFT>>(Body))
-      ESym->st_shndx = SHN_ABS;
-
-    if (Config->EMachine == EM_MIPS) {
-      // On MIPS we need to mark symbol which has a PLT entry and requires
-      // pointer equality by STO_MIPS_PLT flag. That is necessary to help
-      // dynamic linker distinguish such symbols and MIPS lazy-binding stubs.
-      // https://sourceware.org/ml/binutils/2008-07/txt00000.txt
-      if (Body->isInPlt() && Body->NeedsCopyOrPltAddr)
-        ESym->st_other |= STO_MIPS_PLT;
-      if (Config->Relocatable) {
-        auto *D = dyn_cast<DefinedRegular<ELFT>>(Body);
-        if (D && D->isMipsPIC())
-          ESym->st_other |= STO_MIPS_PIC;
-      }
-    }
-    ++ESym;
-  }
-}
-
-template <class ELFT>
-const OutputSectionBase *
-SymbolTableSection<ELFT>::getOutputSection(SymbolBody *Sym) {
-  switch (Sym->kind()) {
-  case SymbolBody::DefinedSyntheticKind:
-    return cast<DefinedSynthetic<ELFT>>(Sym)->Section;
-  case SymbolBody::DefinedRegularKind: {
-    auto &D = cast<DefinedRegular<ELFT>>(*Sym);
-    if (D.Section)
-      return D.Section->OutSec;
-    break;
-  }
-  case SymbolBody::DefinedCommonKind:
-    return In<ELFT>::Common->OutSec;
-  case SymbolBody::SharedKind:
-    if (cast<SharedSymbol<ELFT>>(Sym)->needsCopy())
-      return Out<ELFT>::Bss;
-    break;
-  case SymbolBody::UndefinedKind:
-  case SymbolBody::LazyArchiveKind:
-  case SymbolBody::LazyObjectKind:
-    break;
-  }
-  return nullptr;
-}
-
-template <class ELFT>
 VersionDefinitionSection<ELFT>::VersionDefinitionSection()
     : OutputSectionBase(".gnu.version_d", SHT_GNU_verdef, SHF_ALLOC) {
   this->Addralign = sizeof(uint32_t);
@@ -1065,16 +883,16 @@ VersionTableSection<ELFT>::VersionTableS
 
 template <class ELFT> void VersionTableSection<ELFT>::finalize() {
   this->Size =
-      sizeof(Elf_Versym) * (Out<ELFT>::DynSymTab->getSymbols().size() + 1);
+      sizeof(Elf_Versym) * (In<ELFT>::DynSymTab->getSymbols().size() + 1);
   this->Entsize = sizeof(Elf_Versym);
   // At the moment of june 2016 GNU docs does not mention that sh_link field
   // should be set, but Sun docs do. Also readelf relies on this field.
-  this->Link = Out<ELFT>::DynSymTab->SectionIndex;
+  this->Link = In<ELFT>::DynSymTab->OutSec->SectionIndex;
 }
 
 template <class ELFT> void VersionTableSection<ELFT>::writeTo(uint8_t *Buf) {
   auto *OutVersym = reinterpret_cast<Elf_Versym *>(Buf) + 1;
-  for (const SymbolTableEntry &S : Out<ELFT>::DynSymTab->getSymbols()) {
+  for (const SymbolTableEntry &S : In<ELFT>::DynSymTab->getSymbols()) {
     OutVersym->vs_index = S.Symbol->symbol()->VersionId;
     ++OutVersym;
   }
@@ -1293,11 +1111,6 @@ template class MergeOutputSection<ELF32B
 template class MergeOutputSection<ELF64LE>;
 template class MergeOutputSection<ELF64BE>;
 
-template class SymbolTableSection<ELF32LE>;
-template class SymbolTableSection<ELF32BE>;
-template class SymbolTableSection<ELF64LE>;
-template class SymbolTableSection<ELF64BE>;
-
 template class VersionTableSection<ELF32LE>;
 template class VersionTableSection<ELF32BE>;
 template class VersionTableSection<ELF64LE>;

Modified: lld/trunk/ELF/OutputSections.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/OutputSections.h?rev=287216&r1=287215&r2=287216&view=diff
==============================================================================
--- lld/trunk/ELF/OutputSections.h (original)
+++ lld/trunk/ELF/OutputSections.h Thu Nov 17 03:16:34 2016
@@ -52,7 +52,6 @@ public:
     Merge,
     Plt,
     Regular,
-    SymTable,
     VersDef,
     VersNeed,
     VersTable
@@ -160,40 +159,6 @@ struct SymbolTableEntry {
   size_t StrTabOffset;
 };
 
-template <class ELFT>
-class SymbolTableSection final : public OutputSectionBase {
-  typedef OutputSectionBase Base;
-
-public:
-  typedef typename ELFT::Shdr Elf_Shdr;
-  typedef typename ELFT::Sym Elf_Sym;
-  typedef typename ELFT::SymRange Elf_Sym_Range;
-  typedef typename ELFT::uint uintX_t;
-  SymbolTableSection(StringTableSection<ELFT> &StrTabSec);
-
-  void finalize() override;
-  void writeTo(uint8_t *Buf) override;
-  void addSymbol(SymbolBody *Body);
-  StringTableSection<ELFT> &getStrTabSec() const { return StrTabSec; }
-  unsigned getNumSymbols() const { return NumLocals + Symbols.size() + 1; }
-  typename Base::Kind getKind() const override { return Base::SymTable; }
-  static bool classof(const Base *B) { return B->getKind() == Base::SymTable; }
-
-  ArrayRef<SymbolTableEntry> getSymbols() const { return Symbols; }
-
-  unsigned NumLocals = 0;
-  StringTableSection<ELFT> &StrTabSec;
-
-private:
-  void writeLocalSymbols(uint8_t *&Buf);
-  void writeGlobalSymbols(uint8_t *Buf);
-
-  const OutputSectionBase *getOutputSection(SymbolBody *Sym);
-
-  // A vector of symbols and their string table offsets.
-  std::vector<SymbolTableEntry> Symbols;
-};
-
 // For more information about .gnu.version and .gnu.version_r see:
 // https://www.akkadia.org/drepper/symbol-versioning
 
@@ -468,8 +433,6 @@ template <class ELFT> struct Out {
   static OutputSectionBase *Opd;
   static uint8_t *OpdBuf;
   static PltSection<ELFT> *Plt;
-  static SymbolTableSection<ELFT> *DynSymTab;
-  static SymbolTableSection<ELFT> *SymTab;
   static VersionDefinitionSection<ELFT> *VerDef;
   static VersionTableSection<ELFT> *VerSym;
   static VersionNeedSection<ELFT> *VerNeed;
@@ -526,8 +489,6 @@ template <class ELFT> OutputSection<ELFT
 template <class ELFT> OutputSectionBase *Out<ELFT>::Opd;
 template <class ELFT> uint8_t *Out<ELFT>::OpdBuf;
 template <class ELFT> PltSection<ELFT> *Out<ELFT>::Plt;
-template <class ELFT> SymbolTableSection<ELFT> *Out<ELFT>::DynSymTab;
-template <class ELFT> SymbolTableSection<ELFT> *Out<ELFT>::SymTab;
 template <class ELFT> VersionDefinitionSection<ELFT> *Out<ELFT>::VerDef;
 template <class ELFT> VersionTableSection<ELFT> *Out<ELFT>::VerSym;
 template <class ELFT> VersionNeedSection<ELFT> *Out<ELFT>::VerNeed;

Modified: lld/trunk/ELF/SyntheticSections.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/SyntheticSections.cpp?rev=287216&r1=287215&r2=287216&view=diff
==============================================================================
--- lld/trunk/ELF/SyntheticSections.cpp (original)
+++ lld/trunk/ELF/SyntheticSections.cpp Thu Nov 17 03:16:34 2016
@@ -788,7 +788,7 @@ template <class ELFT> void DynamicSectio
     add({DT_PLTREL, uint64_t(Config->Rela ? DT_RELA : DT_REL)});
   }
 
-  add({DT_SYMTAB, Out<ELFT>::DynSymTab});
+  add({DT_SYMTAB, In<ELFT>::DynSymTab});
   add({DT_SYMENT, sizeof(Elf_Sym)});
   add({DT_STRTAB, In<ELFT>::DynStrTab});
   add({DT_STRSZ, In<ELFT>::DynStrTab->getSize()});
@@ -831,12 +831,12 @@ template <class ELFT> void DynamicSectio
     add({DT_MIPS_RLD_VERSION, 1});
     add({DT_MIPS_FLAGS, RHF_NOTPOT});
     add({DT_MIPS_BASE_ADDRESS, Config->ImageBase});
-    add({DT_MIPS_SYMTABNO, Out<ELFT>::DynSymTab->getNumSymbols()});
+    add({DT_MIPS_SYMTABNO, In<ELFT>::DynSymTab->getNumSymbols()});
     add({DT_MIPS_LOCAL_GOTNO, In<ELFT>::MipsGot->getMipsLocalEntriesNum()});
     if (const SymbolBody *B = In<ELFT>::MipsGot->getMipsFirstGlobalEntry())
       add({DT_MIPS_GOTSYM, B->DynsymIndex});
     else
-      add({DT_MIPS_GOTSYM, Out<ELFT>::DynSymTab->getNumSymbols()});
+      add({DT_MIPS_GOTSYM, In<ELFT>::DynSymTab->getNumSymbols()});
     add({DT_PLTGOT, In<ELFT>::MipsGot});
     if (Out<ELFT>::MipsRldMap)
       add({DT_MIPS_RLD_MAP, Out<ELFT>::MipsRldMap});
@@ -953,14 +953,193 @@ template <class ELFT> unsigned Relocatio
 }
 
 template <class ELFT> void RelocationSection<ELFT>::finalize() {
-  this->Link = Out<ELFT>::DynSymTab ? Out<ELFT>::DynSymTab->SectionIndex
-                                    : Out<ELFT>::SymTab->SectionIndex;
+  this->Link = In<ELFT>::DynSymTab ? In<ELFT>::DynSymTab->OutSec->SectionIndex
+                                   : In<ELFT>::SymTab->OutSec->SectionIndex;
 
   // Set required output section properties.
   this->OutSec->Link = this->Link;
   this->OutSec->Entsize = this->Entsize;
 }
 
+template <class ELFT>
+SymbolTableSection<ELFT>::SymbolTableSection(
+    StringTableSection<ELFT> &StrTabSec)
+    : SyntheticSection<ELFT>(StrTabSec.isDynamic() ? (uintX_t)SHF_ALLOC : 0,
+                             StrTabSec.isDynamic() ? SHT_DYNSYM : SHT_SYMTAB,
+                             sizeof(uintX_t),
+                             StrTabSec.isDynamic() ? ".dynsym" : ".symtab"),
+      StrTabSec(StrTabSec) {
+  this->Entsize = sizeof(Elf_Sym);
+}
+
+// Orders symbols according to their positions in the GOT,
+// in compliance with MIPS ABI rules.
+// See "Global Offset Table" in Chapter 5 in the following document
+// for detailed description:
+// ftp://www.linux-mips.org/pub/linux/mips/doc/ABI/mipsabi.pdf
+static bool sortMipsSymbols(const SymbolBody *L, const SymbolBody *R) {
+  // Sort entries related to non-local preemptible symbols by GOT indexes.
+  // All other entries go to the first part of GOT in arbitrary order.
+  bool LIsInLocalGot = !L->IsInGlobalMipsGot;
+  bool RIsInLocalGot = !R->IsInGlobalMipsGot;
+  if (LIsInLocalGot || RIsInLocalGot)
+    return !RIsInLocalGot;
+  return L->GotIndex < R->GotIndex;
+}
+
+static uint8_t getSymbolBinding(SymbolBody *Body) {
+  Symbol *S = Body->symbol();
+  if (Config->Relocatable)
+    return S->Binding;
+  uint8_t Visibility = S->Visibility;
+  if (Visibility != STV_DEFAULT && Visibility != STV_PROTECTED)
+    return STB_LOCAL;
+  if (Config->NoGnuUnique && S->Binding == STB_GNU_UNIQUE)
+    return STB_GLOBAL;
+  return S->Binding;
+}
+
+template <class ELFT> void SymbolTableSection<ELFT>::finalize() {
+  this->OutSec->Link = this->Link = StrTabSec.OutSec->SectionIndex;
+  this->OutSec->Info = this->Info = NumLocals + 1;
+  this->OutSec->Entsize = this->Entsize;
+
+  if (Config->Relocatable) {
+    size_t I = NumLocals;
+    for (const SymbolTableEntry &S : Symbols)
+      S.Symbol->DynsymIndex = ++I;
+    return;
+  }
+
+  if (!StrTabSec.isDynamic()) {
+    std::stable_sort(Symbols.begin(), Symbols.end(),
+                     [](const SymbolTableEntry &L, const SymbolTableEntry &R) {
+                       return getSymbolBinding(L.Symbol) == STB_LOCAL &&
+                              getSymbolBinding(R.Symbol) != STB_LOCAL;
+                     });
+    return;
+  }
+  if (Out<ELFT>::GnuHashTab)
+    // NB: It also sorts Symbols to meet the GNU hash table requirements.
+    Out<ELFT>::GnuHashTab->addSymbols(Symbols);
+  else if (Config->EMachine == EM_MIPS)
+    std::stable_sort(Symbols.begin(), Symbols.end(),
+                     [](const SymbolTableEntry &L, const SymbolTableEntry &R) {
+                       return sortMipsSymbols(L.Symbol, R.Symbol);
+                     });
+  size_t I = 0;
+  for (const SymbolTableEntry &S : Symbols)
+    S.Symbol->DynsymIndex = ++I;
+}
+
+template <class ELFT> void SymbolTableSection<ELFT>::addSymbol(SymbolBody *B) {
+  Symbols.push_back({B, StrTabSec.addString(B->getName(), false)});
+}
+
+template <class ELFT> void SymbolTableSection<ELFT>::writeTo(uint8_t *Buf) {
+  Buf += sizeof(Elf_Sym);
+
+  // All symbols with STB_LOCAL binding precede the weak and global symbols.
+  // .dynsym only contains global symbols.
+  if (Config->Discard != DiscardPolicy::All && !StrTabSec.isDynamic())
+    writeLocalSymbols(Buf);
+
+  writeGlobalSymbols(Buf);
+}
+
+template <class ELFT>
+void SymbolTableSection<ELFT>::writeLocalSymbols(uint8_t *&Buf) {
+  // Iterate over all input object files to copy their local symbols
+  // to the output symbol table pointed by Buf.
+  for (ObjectFile<ELFT> *File : Symtab<ELFT>::X->getObjectFiles()) {
+    for (const std::pair<const DefinedRegular<ELFT> *, size_t> &P :
+         File->KeptLocalSyms) {
+      const DefinedRegular<ELFT> &Body = *P.first;
+      InputSectionBase<ELFT> *Section = Body.Section;
+      auto *ESym = reinterpret_cast<Elf_Sym *>(Buf);
+
+      if (!Section) {
+        ESym->st_shndx = SHN_ABS;
+        ESym->st_value = Body.Value;
+      } else {
+        const OutputSectionBase *OutSec = Section->OutSec;
+        ESym->st_shndx = OutSec->SectionIndex;
+        ESym->st_value = OutSec->Addr + Section->getOffset(Body);
+      }
+      ESym->st_name = P.second;
+      ESym->st_size = Body.template getSize<ELFT>();
+      ESym->setBindingAndType(STB_LOCAL, Body.Type);
+      Buf += sizeof(*ESym);
+    }
+  }
+}
+
+template <class ELFT>
+void SymbolTableSection<ELFT>::writeGlobalSymbols(uint8_t *Buf) {
+  // Write the internal symbol table contents to the output symbol table
+  // pointed by Buf.
+  auto *ESym = reinterpret_cast<Elf_Sym *>(Buf);
+  for (const SymbolTableEntry &S : Symbols) {
+    SymbolBody *Body = S.Symbol;
+    size_t StrOff = S.StrTabOffset;
+
+    uint8_t Type = Body->Type;
+    uintX_t Size = Body->getSize<ELFT>();
+
+    ESym->setBindingAndType(getSymbolBinding(Body), Type);
+    ESym->st_size = Size;
+    ESym->st_name = StrOff;
+    ESym->setVisibility(Body->symbol()->Visibility);
+    ESym->st_value = Body->getVA<ELFT>();
+
+    if (const OutputSectionBase *OutSec = getOutputSection(Body))
+      ESym->st_shndx = OutSec->SectionIndex;
+    else if (isa<DefinedRegular<ELFT>>(Body))
+      ESym->st_shndx = SHN_ABS;
+
+    if (Config->EMachine == EM_MIPS) {
+      // On MIPS we need to mark symbol which has a PLT entry and requires
+      // pointer equality by STO_MIPS_PLT flag. That is necessary to help
+      // dynamic linker distinguish such symbols and MIPS lazy-binding stubs.
+      // https://sourceware.org/ml/binutils/2008-07/txt00000.txt
+      if (Body->isInPlt() && Body->NeedsCopyOrPltAddr)
+        ESym->st_other |= STO_MIPS_PLT;
+      if (Config->Relocatable) {
+        auto *D = dyn_cast<DefinedRegular<ELFT>>(Body);
+        if (D && D->isMipsPIC())
+          ESym->st_other |= STO_MIPS_PIC;
+      }
+    }
+    ++ESym;
+  }
+}
+
+template <class ELFT>
+const OutputSectionBase *
+SymbolTableSection<ELFT>::getOutputSection(SymbolBody *Sym) {
+  switch (Sym->kind()) {
+  case SymbolBody::DefinedSyntheticKind:
+    return cast<DefinedSynthetic<ELFT>>(Sym)->Section;
+  case SymbolBody::DefinedRegularKind: {
+    auto &D = cast<DefinedRegular<ELFT>>(*Sym);
+    if (D.Section)
+      return D.Section->OutSec;
+    break;
+  }
+  case SymbolBody::DefinedCommonKind:
+    return In<ELFT>::Common->OutSec;
+  case SymbolBody::SharedKind:
+    if (cast<SharedSymbol<ELFT>>(Sym)->needsCopy())
+      return Out<ELFT>::Bss;
+    break;
+  case SymbolBody::UndefinedKind:
+  case SymbolBody::LazyArchiveKind:
+  case SymbolBody::LazyObjectKind:
+    break;
+  }
+  return nullptr;
+}
+
 template InputSection<ELF32LE> *elf::createCommonSection();
 template InputSection<ELF32BE> *elf::createCommonSection();
 template InputSection<ELF64LE> *elf::createCommonSection();
@@ -1050,3 +1229,8 @@ template class elf::RelocationSection<EL
 template class elf::RelocationSection<ELF32BE>;
 template class elf::RelocationSection<ELF64LE>;
 template class elf::RelocationSection<ELF64BE>;
+
+template class elf::SymbolTableSection<ELF32LE>;
+template class elf::SymbolTableSection<ELF32BE>;
+template class elf::SymbolTableSection<ELF64LE>;
+template class elf::SymbolTableSection<ELF64BE>;

Modified: lld/trunk/ELF/SyntheticSections.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/SyntheticSections.h?rev=287216&r1=287215&r2=287216&view=diff
==============================================================================
--- lld/trunk/ELF/SyntheticSections.h (original)
+++ lld/trunk/ELF/SyntheticSections.h Thu Nov 17 03:16:34 2016
@@ -11,6 +11,7 @@
 #define LLD_ELF_SYNTHETIC_SECTION_H
 
 #include "InputSection.h"
+#include "OutputSections.h"
 #include "llvm/ADT/SmallPtrSet.h"
 
 namespace lld {
@@ -360,6 +361,37 @@ private:
   std::vector<DynamicReloc<ELFT>> Relocs;
 };
 
+template <class ELFT>
+class SymbolTableSection final : public SyntheticSection<ELFT> {
+public:
+  typedef typename ELFT::Shdr Elf_Shdr;
+  typedef typename ELFT::Sym Elf_Sym;
+  typedef typename ELFT::SymRange Elf_Sym_Range;
+  typedef typename ELFT::uint uintX_t;
+  SymbolTableSection(StringTableSection<ELFT> &StrTabSec);
+
+  void finalize() override;
+  void writeTo(uint8_t *Buf) override;
+  size_t getSize() const override { return getNumSymbols() * sizeof(Elf_Sym); }
+  void addSymbol(SymbolBody *Body);
+  StringTableSection<ELFT> &getStrTabSec() const { return StrTabSec; }
+  unsigned getNumSymbols() const { return NumLocals + Symbols.size() + 1; }
+
+  ArrayRef<SymbolTableEntry> getSymbols() const { return Symbols; }
+
+  unsigned NumLocals = 0;
+  StringTableSection<ELFT> &StrTabSec;
+
+private:
+  void writeLocalSymbols(uint8_t *&Buf);
+  void writeGlobalSymbols(uint8_t *Buf);
+
+  const OutputSectionBase *getOutputSection(SymbolBody *Sym);
+
+  // A vector of symbols and their string table offsets.
+  std::vector<SymbolTableEntry> Symbols;
+};
+
 template <class ELFT> InputSection<ELFT> *createCommonSection();
 template <class ELFT> InputSection<ELFT> *createInterpSection();
 template <class ELFT> MergeInputSection<ELFT> *createCommentSection();
@@ -370,6 +402,7 @@ template <class ELFT> struct In {
   static InputSection<ELFT> *Common;
   static DynamicSection<ELFT> *Dynamic;
   static StringTableSection<ELFT> *DynStrTab;
+  static SymbolTableSection<ELFT> *DynSymTab;
   static GotSection<ELFT> *Got;
   static MipsGotSection<ELFT> *MipsGot;
   static GotPltSection<ELFT> *GotPlt;
@@ -381,12 +414,14 @@ template <class ELFT> struct In {
   static RelocationSection<ELFT> *RelaPlt;
   static StringTableSection<ELFT> *ShStrTab;
   static StringTableSection<ELFT> *StrTab;
+  static SymbolTableSection<ELFT> *SymTab;
 };
 
 template <class ELFT> BuildIdSection<ELFT> *In<ELFT>::BuildId;
 template <class ELFT> InputSection<ELFT> *In<ELFT>::Common;
 template <class ELFT> DynamicSection<ELFT> *In<ELFT>::Dynamic;
 template <class ELFT> StringTableSection<ELFT> *In<ELFT>::DynStrTab;
+template <class ELFT> SymbolTableSection<ELFT> *In<ELFT>::DynSymTab;
 template <class ELFT> GotSection<ELFT> *In<ELFT>::Got;
 template <class ELFT> MipsGotSection<ELFT> *In<ELFT>::MipsGot;
 template <class ELFT> GotPltSection<ELFT> *In<ELFT>::GotPlt;
@@ -398,6 +433,7 @@ template <class ELFT> RelocationSection<
 template <class ELFT> RelocationSection<ELFT> *In<ELFT>::RelaPlt;
 template <class ELFT> StringTableSection<ELFT> *In<ELFT>::ShStrTab;
 template <class ELFT> StringTableSection<ELFT> *In<ELFT>::StrTab;
+template <class ELFT> SymbolTableSection<ELFT> *In<ELFT>::SymTab;
 } // namespace elf
 } // namespace lld
 

Modified: lld/trunk/ELF/Writer.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Writer.cpp?rev=287216&r1=287215&r2=287216&view=diff
==============================================================================
--- lld/trunk/ELF/Writer.cpp (original)
+++ lld/trunk/ELF/Writer.cpp Thu Nov 17 03:16:34 2016
@@ -232,7 +232,7 @@ template <class ELFT> void Writer<ELFT>:
   }
 
   if (!Symtab<ELFT>::X->getSharedFiles().empty() || Config->Pic) {
-    Out<ELFT>::DynSymTab = make<SymbolTableSection<ELFT>>(*In<ELFT>::DynStrTab);
+    In<ELFT>::DynSymTab = make<SymbolTableSection<ELFT>>(*In<ELFT>::DynStrTab);
   }
 
   if (Config->EhFrameHdr)
@@ -249,7 +249,7 @@ template <class ELFT> void Writer<ELFT>:
       Config->Rela ? ".rela.plt" : ".rel.plt", false /*Sort*/);
   if (Config->Strip != StripPolicy::All) {
     In<ELFT>::StrTab = make<StringTableSection<ELFT>>(".strtab", false);
-    Out<ELFT>::SymTab = make<SymbolTableSection<ELFT>>(*In<ELFT>::StrTab);
+    In<ELFT>::SymTab = make<SymbolTableSection<ELFT>>(*In<ELFT>::StrTab);
   }
 
   if (Config->EMachine == EM_MIPS && !Config->Shared) {
@@ -372,7 +372,7 @@ template <class ELFT> static bool includ
 // Local symbols are not in the linker's symbol table. This function scans
 // each object file's symbol table to copy local symbols to the output.
 template <class ELFT> void Writer<ELFT>::copyLocalSymbols() {
-  if (!Out<ELFT>::SymTab)
+  if (!In<ELFT>::SymTab)
     return;
   for (elf::ObjectFile<ELFT> *F : Symtab<ELFT>::X->getObjectFiles()) {
     StringRef StrTab = F->getStringTable();
@@ -392,11 +392,11 @@ template <class ELFT> void Writer<ELFT>:
       InputSectionBase<ELFT> *Sec = DR->Section;
       if (!shouldKeepInSymtab<ELFT>(Sec, SymName, *B))
         continue;
-      ++Out<ELFT>::SymTab->NumLocals;
+      ++In<ELFT>::SymTab->NumLocals;
       if (Config->Relocatable)
-        B->DynsymIndex = Out<ELFT>::SymTab->NumLocals;
+        B->DynsymIndex = In<ELFT>::SymTab->NumLocals;
       F->KeptLocalSyms.push_back(
-          std::make_pair(DR, Out<ELFT>::SymTab->StrTabSec.addString(SymName)));
+          std::make_pair(DR, In<ELFT>::SymTab->StrTabSec.addString(SymName)));
     }
   }
 }
@@ -594,7 +594,7 @@ static Symbol *addOptionalRegular(String
 // need these symbols, since IRELATIVE relocs are resolved through GOT
 // and PLT. For details, see http://www.airs.com/blog/archives/403.
 template <class ELFT> void Writer<ELFT>::addRelIpltSymbols() {
-  if (Out<ELFT>::DynSymTab)
+  if (In<ELFT>::DynSymTab)
     return;
   StringRef S = Config->Rela ? "__rela_iplt_start" : "__rel_iplt_start";
   addOptionalRegular<ELFT>(S, In<ELFT>::RelaPlt, 0);
@@ -647,7 +647,7 @@ template <class ELFT> void Writer<ELFT>:
   // to avoid the undefined symbol error. As usual special cases are ARM and
   // MIPS - the libc for these targets defines __tls_get_addr itself because
   // there are no TLS optimizations for these targets.
-  if (!Out<ELFT>::DynSymTab &&
+  if (!In<ELFT>::DynSymTab &&
       (Config->EMachine != EM_MIPS && Config->EMachine != EM_ARM))
     Symtab<ELFT>::X->addIgnored("__tls_get_addr");
 
@@ -893,7 +893,7 @@ template <class ELFT> void Writer<ELFT>:
   // It should be okay as no one seems to care about the type.
   // Even the author of gold doesn't remember why gold behaves that way.
   // https://sourceware.org/ml/binutils/2002-03/msg00360.html
-  if (Out<ELFT>::DynSymTab)
+  if (In<ELFT>::DynSymTab)
     addRegular("_DYNAMIC", In<ELFT>::Dynamic, 0);
 
   // Define __rel[a]_iplt_{start,end} symbols if needed.
@@ -915,11 +915,11 @@ template <class ELFT> void Writer<ELFT>:
 
     if (!includeInSymtab<ELFT>(*Body))
       continue;
-    if (Out<ELFT>::SymTab)
-      Out<ELFT>::SymTab->addSymbol(Body);
+    if (In<ELFT>::SymTab)
+      In<ELFT>::SymTab->addSymbol(Body);
 
-    if (Out<ELFT>::DynSymTab && S->includeInDynsym()) {
-      Out<ELFT>::DynSymTab->addSymbol(Body);
+    if (In<ELFT>::DynSymTab && S->includeInDynsym()) {
+      In<ELFT>::DynSymTab->addSymbol(Body);
       if (auto *SS = dyn_cast<SharedSymbol<ELFT>>(Body))
         if (SS->file()->isNeeded())
           Out<ELFT>::VerNeed->addSymbol(SS);
@@ -942,10 +942,11 @@ template <class ELFT> void Writer<ELFT>:
     Sec->ShName = In<ELFT>::ShStrTab->addString(Sec->getName());
   }
 
+  // FIXME: this should be removed after converting GnuHashTableSection
+  // to input section.
   // Finalizers fix each section's size.
   // .dynsym is finalized early since that may fill up .gnu.hash.
-  if (Out<ELFT>::DynSymTab)
-    Out<ELFT>::DynSymTab->finalize();
+  finalizeSynthetic<ELFT>({In<ELFT>::DynSymTab});
 
   // Fill other section headers. The dynamic table is finalized
   // at the end because some tags like RELSZ depend on result
@@ -955,9 +956,9 @@ template <class ELFT> void Writer<ELFT>:
 
   // Dynamic section must be the last one in this list.
   finalizeSynthetic<ELFT>(
-      {In<ELFT>::ShStrTab, In<ELFT>::StrTab, In<ELFT>::DynStrTab, In<ELFT>::Got,
-       In<ELFT>::MipsGot, In<ELFT>::GotPlt, In<ELFT>::RelaDyn,
-       In<ELFT>::RelaPlt, In<ELFT>::Dynamic});
+      {In<ELFT>::SymTab, In<ELFT>::ShStrTab, In<ELFT>::StrTab,
+       In<ELFT>::DynStrTab, In<ELFT>::Got, In<ELFT>::MipsGot, In<ELFT>::GotPlt,
+       In<ELFT>::RelaDyn, In<ELFT>::RelaPlt, In<ELFT>::Dynamic});
 
   // Now that all output offsets are fixed. Finalize mergeable sections
   // to fix their maps from input offsets to output offsets.
@@ -990,11 +991,11 @@ template <class ELFT> void Writer<ELFT>:
   // because we sort the sections using their attributes below.
   if (Out<ELFT>::GdbIndex && Out<ELFT>::DebugInfo)
     Add(Out<ELFT>::GdbIndex);
-  Add(Out<ELFT>::SymTab);
+  addInputSec(In<ELFT>::SymTab);
   addInputSec(In<ELFT>::ShStrTab);
   addInputSec(In<ELFT>::StrTab);
-  if (Out<ELFT>::DynSymTab) {
-    Add(Out<ELFT>::DynSymTab);
+  if (In<ELFT>::DynSymTab) {
+    addInputSec(In<ELFT>::DynSymTab);
 
     bool HasVerNeed = Out<ELFT>::VerNeed->getNeedNum() != 0;
     if (Out<ELFT>::VerDef || HasVerNeed)
@@ -1172,7 +1173,7 @@ template <class ELFT> std::vector<PhdrEn
     Ret.push_back(std::move(TlsHdr));
 
   // Add an entry for .dynamic.
-  if (Out<ELFT>::DynSymTab) {
+  if (In<ELFT>::DynSymTab) {
     Phdr &H = *AddHdr(PT_DYNAMIC, In<ELFT>::Dynamic->OutSec->getPhdrFlags());
     H.add(In<ELFT>::Dynamic->OutSec);
   }




More information about the llvm-commits mailing list