[lld] r249781 - ELF2: Split Writer::createSections into small functions.

Rui Ueyama via llvm-commits llvm-commits at lists.llvm.org
Thu Oct 8 16:49:30 PDT 2015


Author: ruiu
Date: Thu Oct  8 18:49:30 2015
New Revision: 249781

URL: http://llvm.org/viewvc/llvm-project?rev=249781&view=rev
Log:
ELF2: Split Writer::createSections into small functions.

Also added a few comments.

Modified:
    lld/trunk/ELF/Writer.cpp

Modified: lld/trunk/ELF/Writer.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Writer.cpp?rev=249781&r1=249780&r2=249781&view=diff
==============================================================================
--- lld/trunk/ELF/Writer.cpp (original)
+++ lld/trunk/ELF/Writer.cpp Thu Oct  8 18:49:30 2015
@@ -75,6 +75,7 @@ public:
   void run();
 
 private:
+  void copyLocalSymbols();
   void createSections();
   template <bool isRela>
   void scanRelocs(const InputSection<ELFT> &C,
@@ -162,6 +163,8 @@ void lld::elf2::writeResult(SymbolTable
 
 // The main function of the writer.
 template <class ELFT> void Writer<ELFT>::run() {
+  if (!Config->DiscardAll)
+    copyLocalSymbols();
   createSections();
   assignAddresses();
   openFile(Config->OutputFile);
@@ -282,6 +285,91 @@ static void reportUndefined(const Symbol
     error(Message);
 }
 
+// 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() {
+  for (const std::unique_ptr<ObjectFileBase> &FileB : Symtab.getObjectFiles()) {
+    auto &File = cast<ObjectFile<ELFT>>(*FileB);
+    for (const Elf_Sym &Sym : File.getLocalSymbols()) {
+      ErrorOr<StringRef> SymNameOrErr = Sym.getName(File.getStringTable());
+      error(SymNameOrErr);
+      StringRef SymName = *SymNameOrErr;
+      if (shouldKeepInSymtab<ELFT>(SymName, Sym))
+        Out<ELFT>::SymTab->addSymbol(SymName, true);
+    }
+  }
+}
+
+// Output section ordering is determined by this function.
+template <class ELFT>
+static bool compareOutputSections(OutputSectionBase<ELFT::Is64Bits> *A,
+                                  OutputSectionBase<ELFT::Is64Bits> *B) {
+  typedef typename ELFFile<ELFT>::uintX_t uintX_t;
+
+  uintX_t AFlags = A->getFlags();
+  uintX_t BFlags = B->getFlags();
+
+  // Allocatable sections go first to reduce the total PT_LOAD size and
+  // so debug info doesn't change addresses in actual code.
+  bool AIsAlloc = AFlags & SHF_ALLOC;
+  bool BIsAlloc = BFlags & SHF_ALLOC;
+  if (AIsAlloc != BIsAlloc)
+    return AIsAlloc;
+
+  // We don't have any special requirements for the relative order of
+  // two non allocatable sections.
+  if (!AIsAlloc)
+    return false;
+
+  // We want the read only sections first so that they go in the PT_LOAD
+  // covering the program headers at the start of the file.
+  bool AIsWritable = AFlags & SHF_WRITE;
+  bool BIsWritable = BFlags & SHF_WRITE;
+  if (AIsWritable != BIsWritable)
+    return BIsWritable;
+
+  // For a corresponding reason, put non exec sections first (the program
+  // header PT_LOAD is not executable).
+  bool AIsExec = AFlags & SHF_EXECINSTR;
+  bool BIsExec = BFlags & SHF_EXECINSTR;
+  if (AIsExec != BIsExec)
+    return BIsExec;
+
+  // If we got here we know that both A and B and in the same PT_LOAD.
+  // The last requirement we have is to put nobits section last. The
+  // reason is that the only thing the dynamic linker will see about
+  // them is a p_memsz that is larger than p_filesz. Seeing that it
+  // zeros the end of the PT_LOAD, so that has to correspond to the
+  // nobits sections.
+  return A->getType() != SHT_NOBITS && B->getType() == SHT_NOBITS;
+}
+
+// Until this function is called, common symbols do not belong to any section.
+// This function adds them to end of BSS section.
+template <class ELFT>
+static void addCommonSymbols(std::vector<DefinedCommon<ELFT> *> &Syms) {
+  typedef typename ELFFile<ELFT>::uintX_t uintX_t;
+  typedef typename ELFFile<ELFT>::Elf_Sym Elf_Sym;
+
+  // Sort the common symbols by alignment as an heuristic to pack them better.
+  std::stable_sort(
+    Syms.begin(), Syms.end(),
+    [](const DefinedCommon<ELFT> *A, const DefinedCommon<ELFT> *B) {
+      return A->MaxAlignment > B->MaxAlignment;
+    });
+
+  uintX_t Off = Out<ELFT>::Bss->getSize();
+  for (DefinedCommon<ELFT> *C : Syms) {
+    const Elf_Sym &Sym = C->Sym;
+    uintX_t Align = C->MaxAlignment;
+    Off = RoundUpToAlignment(Off, Align);
+    C->OffsetInBSS = Off;
+    Off += Sym.st_size;
+  }
+
+  Out<ELFT>::Bss->setSize(Off);
+}
+
 // Create output section objects and add them to OutputSections.
 template <class ELFT> void Writer<ELFT>::createSections() {
   SmallDenseMap<SectionKey<ELFT::Is64Bits>, OutputSection<ELFT> *> Map;
@@ -308,16 +396,6 @@ template <class ELFT> void Writer<ELFT>:
 
   for (const std::unique_ptr<ObjectFileBase> &FileB : Symtab.getObjectFiles()) {
     auto &File = cast<ObjectFile<ELFT>>(*FileB);
-    if (!Config->DiscardAll) {
-      Elf_Sym_Range Syms = File.getLocalSymbols();
-      for (const Elf_Sym &Sym : Syms) {
-        ErrorOr<StringRef> SymNameOrErr = Sym.getName(File.getStringTable());
-        error(SymNameOrErr);
-        StringRef SymName = *SymNameOrErr;
-        if (shouldKeepInSymtab<ELFT>(SymName, Sym))
-          Out<ELFT>::SymTab->addSymbol(SymName, true);
-      }
-    }
     for (InputSection<ELFT> *C : File.getSections()) {
       if (!C)
         continue;
@@ -376,27 +454,9 @@ template <class ELFT> void Writer<ELFT>:
     if (needsDynamicSections() && includeInDynamicSymtab(*Body))
       Out<ELFT>::HashTab->addSymbol(Body);
   }
-
-  // Sort the common symbols by alignment as an heuristic to pack them better.
-  std::stable_sort(
-      CommonSymbols.begin(), CommonSymbols.end(),
-      [](const DefinedCommon<ELFT> *A, const DefinedCommon<ELFT> *B) {
-        return A->MaxAlignment > B->MaxAlignment;
-      });
-
-  uintX_t Off = Out<ELFT>::Bss->getSize();
-  for (DefinedCommon<ELFT> *C : CommonSymbols) {
-    const Elf_Sym &Sym = C->Sym;
-    uintX_t Align = C->MaxAlignment;
-    Off = RoundUpToAlignment(Off, Align);
-    C->OffsetInBSS = Off;
-    Off += Sym.st_size;
-  }
-
-  Out<ELFT>::Bss->setSize(Off);
+  addCommonSymbols(CommonSymbols);
 
   OutputSections.push_back(Out<ELFT>::SymTab);
-
   if (needsDynamicSections()) {
     if (needsInterpSection())
       OutputSections.push_back(Out<ELFT>::Interp);
@@ -412,47 +472,8 @@ template <class ELFT> void Writer<ELFT>:
   if (!Out<ELFT>::Plt->empty())
     OutputSections.push_back(Out<ELFT>::Plt);
 
-  std::stable_sort(
-      OutputSections.begin(), OutputSections.end(),
-      [](OutputSectionBase<ELFT::Is64Bits> *A,
-         OutputSectionBase<ELFT::Is64Bits> *B) {
-        uintX_t AFlags = A->getFlags();
-        uintX_t BFlags = B->getFlags();
-
-        // Allocatable sections go first to reduce the total PT_LOAD size and
-        // so debug info doesn't change addresses in actual code.
-        bool AIsAlloc = AFlags & SHF_ALLOC;
-        bool BIsAlloc = BFlags & SHF_ALLOC;
-        if (AIsAlloc != BIsAlloc)
-          return AIsAlloc;
-
-        // We don't have any special requirements for the relative order of
-        // two non allocatable sections.
-        if (!AIsAlloc)
-          return false;
-
-        // We want the read only sections first so that they go in the PT_LOAD
-        // covering the program headers at the start of the file.
-        bool AIsWritable = AFlags & SHF_WRITE;
-        bool BIsWritable = BFlags & SHF_WRITE;
-        if (AIsWritable != BIsWritable)
-          return BIsWritable;
-
-        // For a corresponding reason, put non exec sections first (the program
-        // header PT_LOAD is not executable).
-        bool AIsExec = AFlags & SHF_EXECINSTR;
-        bool BIsExec = BFlags & SHF_EXECINSTR;
-        if (AIsExec != BIsExec)
-          return BIsExec;
-
-        // If we got here we know that both A and B and in the same PT_LOAD.
-        // The last requirement we have is to put nobits section last. The
-        // reason is that the only thing the dynamic linker will see about
-        // them is a p_memsz that is larger than p_filesz. Seeing that it
-        // zeros the end of the PT_LOAD, so that has to correspond to the
-        // nobits sections.
-        return A->getType() != SHT_NOBITS && B->getType() == SHT_NOBITS;
-      });
+  std::stable_sort(OutputSections.begin(), OutputSections.end(),
+                   compareOutputSections<ELFT>);
 
   // Always put StrTabSec last so that no section names are added to it after
   // it's finalized.




More information about the llvm-commits mailing list