[lld] r296423 - Improve SymbolTableSection synthetic section.

Rui Ueyama via llvm-commits llvm-commits at lists.llvm.org
Mon Feb 27 17:56:37 PST 2017


Author: ruiu
Date: Mon Feb 27 19:56:36 2017
New Revision: 296423

URL: http://llvm.org/viewvc/llvm-project?rev=296423&view=rev
Log:
Improve SymbolTableSection synthetic section.

The previous code was a bit hard to understand because it unnecessarily
distinguished local and non-local symbols. It had NumLocals member
variable, but that variable didn't have a number of local symbols but
had some value that I cannot describe easily.

This patch rewrites SynbolTableSection::finalizeContents and
SymbolTableSection::writeTo to make it easy to understand. NumLocals
member variable has been removed, and writeGlobalSymbols and
writeLocalSymbols have been merged into one function.

There's still a piece of code that I think unnecessary. I'm not removing
that code in this patch, but will do in a follow-up patch.

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=296423&r1=296422&r2=296423&view=diff
==============================================================================
--- lld/trunk/ELF/SyntheticSections.cpp (original)
+++ lld/trunk/ELF/SyntheticSections.cpp Mon Feb 27 19:56:36 2017
@@ -1308,29 +1308,24 @@ template <class ELFT> void SymbolTableSe
   this->OutSec->Link = this->Link = StrTabSec.OutSec->SectionIndex;
   this->OutSec->Entsize = this->Entsize;
 
+  // Move all local symbols before global symbols.
+  size_t NumLocals = 0;
   if (!StrTabSec.isDynamic()) {
-    // All explictly added STB_LOCAL symbols without a Symbol are first
     auto It = std::stable_partition(
-        Symbols.begin(), Symbols.end(),
-        [](const SymbolTableEntry &S) { return S.Symbol->isLocal(); });
+        Symbols.begin(), Symbols.end(), [](const SymbolTableEntry &S) {
+          return S.Symbol->isLocal() ||
+                 S.Symbol->symbol()->computeBinding() == STB_LOCAL;
+        });
     NumLocals = It - Symbols.begin();
   }
-  this->OutSec->Info = this->Info = 1 + NumLocals;
 
-  if (Config->Relocatable)
-    return;
+  // Section's Info field has the index of the first non-local symbol.
+  // Because the first symbol entry is a null entry, +1 is needed.
+  this->Info = NumLocals + 1;
+  this->OutSec->Info = NumLocals + 1;
 
-  if (!StrTabSec.isDynamic()) {
-    auto GlobalBegin = Symbols.begin() + NumLocals;
-    auto It = std::stable_partition(
-        GlobalBegin, Symbols.end(), [](const SymbolTableEntry &S) {
-          return S.Symbol->symbol()->computeBinding() == STB_LOCAL;
-        });
-    // update sh_info with number of Global symbols output with computed
-    // binding of STB_LOCAL
-    this->OutSec->Info = this->Info = 1 + (It - Symbols.begin());
+  if (Config->Relocatable || !StrTabSec.isDynamic())
     return;
-  }
 
   if (In<ELFT>::GnuHashTab) {
     // NB: It also sorts Symbols to meet the GNU hash table requirements.
@@ -1370,81 +1365,64 @@ size_t SymbolTableSection<ELFT>::getSymb
   return I - Symbols.begin() + 1;
 }
 
+// Write the internal symbol table contents to the output symbol table.
 template <class ELFT> void SymbolTableSection<ELFT>::writeTo(uint8_t *Buf) {
+  // The first entry is a null entry as per the ELF spec.
   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);
-}
+  auto *ESym = reinterpret_cast<Elf_Sym *>(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 (auto It = Symbols.begin(), End = Symbols.begin() + NumLocals;
-       It != End; ++It) {
-    auto *Body = cast<DefinedRegular<ELFT>>(It->Symbol);
-    InputSectionBase *Section = Body->Section;
-    auto *ESym = reinterpret_cast<Elf_Sym *>(Buf);
+  for (SymbolTableEntry &Ent : Symbols) {
+    SymbolBody *Body = Ent.Symbol;
 
-    if (!Section) {
-      ESym->st_shndx = SHN_ABS;
-      ESym->st_value = Body->Value;
+    if (Body->isLocal()) {
+      ESym->setBindingAndType(STB_LOCAL, Body->Type);
     } else {
-      const OutputSection *OutSec = Section->getOutputSection<ELFT>();
-      ESym->st_shndx = OutSec->SectionIndex;
-      ESym->st_value = OutSec->Addr + Section->getOffset(*Body);
+      ESym->setBindingAndType(Body->symbol()->computeBinding(), Body->Type);
+      ESym->setVisibility(Body->symbol()->Visibility);
     }
-    ESym->st_name = It->StrTabOffset;
-    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 (auto It = Symbols.begin() + NumLocals, End = Symbols.end();
-       It != End; ++It) {
-    SymbolBody *Body = It->Symbol;
 
-    ESym->setBindingAndType(Body->symbol()->computeBinding(), Body->Type);
+    ESym->st_name = Ent.StrTabOffset;
     ESym->st_size = Body->getSize<ELFT>();
-    ESym->st_name = It->StrTabOffset;
-    ESym->setVisibility(Body->symbol()->Visibility);
     ESym->st_value = Body->getVA<ELFT>();
 
     if (const OutputSection *OutSec = getOutputSection(Body)) {
       ESym->st_shndx = OutSec->SectionIndex;
+
+      // This piece of code should go away as it doesn't make sense,
+      // but we want to keep it tentatively because some tests for TLS
+      // variable depends on this. We should fix the test and remove
+      // this code.
+      if (Body->isLocal())
+        if (auto *DS = dyn_cast<DefinedRegular<ELFT>>(Body))
+          ESym->st_value = OutSec->Addr + DS->Section->getOffset(*DS);
     } else if (isa<DefinedRegular<ELFT>>(Body)) {
       ESym->st_shndx = SHN_ABS;
     } else if (isa<DefinedCommon>(Body)) {
       ESym->st_shndx = SHN_COMMON;
       ESym->st_value = cast<DefinedCommon>(Body)->Alignment;
     }
+    ++ESym;
+  }
+
+  // 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 (Config->EMachine == EM_MIPS) {
+    auto *ESym = reinterpret_cast<Elf_Sym *>(Buf);
 
-    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
+    for (SymbolTableEntry &Ent : Symbols) {
+      SymbolBody *Body = Ent.Symbol;
       if (Body->isInPlt() && Body->NeedsPltAddr)
         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;
-      }
+
+      if (Config->Relocatable)
+        if (auto *D = dyn_cast<DefinedRegular<ELFT>>(Body))
+          if (D->isMipsPIC())
+            ESym->st_other |= STO_MIPS_PIC;
+      ++ESym;
     }
-    ++ESym;
   }
 }
 

Modified: lld/trunk/ELF/SyntheticSections.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/SyntheticSections.h?rev=296423&r1=296422&r2=296423&view=diff
==============================================================================
--- lld/trunk/ELF/SyntheticSections.h (original)
+++ lld/trunk/ELF/SyntheticSections.h Mon Feb 27 19:56:36 2017
@@ -427,15 +427,10 @@ public:
   static const OutputSection *getOutputSection(SymbolBody *Sym);
 
 private:
-  void writeLocalSymbols(uint8_t *&Buf);
-  void writeGlobalSymbols(uint8_t *Buf);
-
   // A vector of symbols and their string table offsets.
   std::vector<SymbolTableEntry> Symbols;
 
   StringTableSection<ELFT> &StrTabSec;
-
-  unsigned NumLocals = 0;
 };
 
 // Outputs GNU Hash section. For detailed explanation see:




More information about the llvm-commits mailing list