[lld] r287515 - Add comments.

Rui Ueyama via llvm-commits llvm-commits at lists.llvm.org
Sun Nov 20 18:11:05 PST 2016


Author: ruiu
Date: Sun Nov 20 20:11:05 2016
New Revision: 287515

URL: http://llvm.org/viewvc/llvm-project?rev=287515&view=rev
Log:
Add comments.

This patch rearranges code a bit to make it easy to explain.

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

Modified: lld/trunk/ELF/LinkerScript.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/LinkerScript.cpp?rev=287515&r1=287514&r2=287515&view=diff
==============================================================================
--- lld/trunk/ELF/LinkerScript.cpp (original)
+++ lld/trunk/ELF/LinkerScript.cpp Sun Nov 20 20:11:05 2016
@@ -8,12 +8,6 @@
 //===----------------------------------------------------------------------===//
 //
 // This file contains the parser/evaluator of the linker script.
-// It parses a linker script and write the result to Config or ScriptConfig
-// objects.
-//
-// If SECTIONS command is used, a ScriptConfig contains an AST
-// of the command which will later be consumed by createSections() and
-// assignAddresses().
 //
 //===----------------------------------------------------------------------===//
 
@@ -308,11 +302,14 @@ void LinkerScript<ELFT>::processCommands
   for (unsigned I = 0; I < Opt.Commands.size(); ++I) {
     auto Iter = Opt.Commands.begin() + I;
     const std::unique_ptr<BaseCommand> &Base1 = *Iter;
+
+    // Handle symbol assignments outside of any output section.
     if (auto *Cmd = dyn_cast<SymbolAssignment>(Base1.get())) {
       if (shouldDefine<ELFT>(Cmd))
         addSymbol<ELFT>(Cmd);
       continue;
     }
+
     if (auto *Cmd = dyn_cast<AssertCommand>(Base1.get())) {
       // If we don't have SECTIONS then output sections have already been
       // created by Writer<ELFT>. The LinkerScript<ELFT>::assignAddresses
@@ -325,11 +322,20 @@ void LinkerScript<ELFT>::processCommands
     if (auto *Cmd = dyn_cast<OutputSectionCommand>(Base1.get())) {
       std::vector<InputSectionBase<ELFT> *> V = createInputSectionList(*Cmd);
 
+      // The output section name `/DISCARD/' is special.
+      // Any input section assigned to it is discarded.
       if (Cmd->Name == "/DISCARD/") {
         discard(V);
         continue;
       }
 
+      // This is for ONLY_IF_RO and ONLY_IF_RW. An output section directive
+      // ".foo : ONLY_IF_R[OW] { ... }" is handled only if all member input
+      // sections satisfy a given constraint. If not, a directive is handled
+      // as if it wasn't present from the beginning.
+      //
+      // Because we'll iterate over Commands many more times, the easiest
+      // way to "make it as if it wasn't present" is to just remove it.
       if (!matchConstraints<ELFT>(V, Cmd->Constraint)) {
         for (InputSectionBase<ELFT> *S : V)
           S->Assigned = false;
@@ -338,25 +344,32 @@ void LinkerScript<ELFT>::processCommands
         continue;
       }
 
+      // A directive may contain symbol definitions like this:
+      // ".foo : { ...; bar = .; }". Handle them.
       for (const std::unique_ptr<BaseCommand> &Base : Cmd->Commands)
         if (auto *OutCmd = dyn_cast<SymbolAssignment>(Base.get()))
           if (shouldDefine<ELFT>(OutCmd))
             addSymbol<ELFT>(OutCmd);
 
-      for (InputSectionBase<ELFT> *Sec : V) {
-        addSection(Factory, Sec, Cmd->Name);
-        if (uint32_t Subalign = Cmd->SubalignExpr ? Cmd->SubalignExpr(0) : 0)
-          Sec->Alignment = Subalign;
+      // Handle subalign (e.g. ".foo : SUBALIGN(32) { ... }"). If subalign
+      // is given, input sections are aligned to that value, whether the
+      // given value is larger or smaller than the original section alignment.
+      if (Cmd->SubalignExpr) {
+        uint32_t Subalign = Cmd->SubalignExpr(0);
+        for (InputSectionBase<ELFT> *S : V)
+          S->Alignment = Subalign;
       }
+
+      // Add input sections to an output section.
+      for (InputSectionBase<ELFT> *S : V)
+        addSection(Factory, S, Cmd->Name);
     }
   }
 }
 
+// Add sections that didn't match any sections command.
 template <class ELFT>
-void LinkerScript<ELFT>::createSections(OutputSectionFactory<ELFT> &Factory) {
-  processCommands(Factory);
-
-  // Add orphan sections.
+void LinkerScript<ELFT>::addOrphanSections(OutputSectionFactory<ELFT> &Factory) {
   for (InputSectionBase<ELFT> *S : Symtab<ELFT>::X->Sections)
     if (S->Live && !S->OutSec)
       addSection(Factory, S, getOutputSectionName(S->Name));
@@ -482,6 +495,8 @@ findSections(StringRef Name, const std::
   return Ret;
 }
 
+// This function assigns offsets to input sections and an output section
+// for a single sections command (e.g. ".text { *(.text); }").
 template <class ELFT>
 void LinkerScript<ELFT>::assignOffsets(OutputSectionCommand *Cmd) {
   if (Cmd->LMAExpr)
@@ -491,6 +506,7 @@ void LinkerScript<ELFT>::assignOffsets(O
   if (Sections.empty())
     return;
   switchTo(Sections[0]);
+
   // Find the last section output location. We will output orphan sections
   // there so that end symbols point to the correct location.
   auto E = std::find_if(Cmd->Commands.rbegin(), Cmd->Commands.rend(),
@@ -517,10 +533,9 @@ template <class ELFT> void LinkerScript<
   auto Pos = std::remove_if(
       Opt.Commands.begin(), Opt.Commands.end(),
       [&](const std::unique_ptr<BaseCommand> &Base) {
-        auto *Cmd = dyn_cast<OutputSectionCommand>(Base.get());
-        if (!Cmd)
-          return false;
-        return findSections<ELFT>(Cmd->Name, *OutputSections).empty();
+        if (auto *Cmd = dyn_cast<OutputSectionCommand>(Base.get()))
+          return findSections<ELFT>(Cmd->Name, *OutputSections).empty();
+        return false;
       });
   Opt.Commands.erase(Pos, Opt.Commands.end());
 }
@@ -672,10 +687,8 @@ void LinkerScript<ELFT>::assignAddresses
     }
 
     auto *Cmd = cast<OutputSectionCommand>(Base.get());
-
     if (Cmd->AddrExpr)
       Dot = Cmd->AddrExpr(Dot);
-
     assignOffsets(Cmd);
   }
 

Modified: lld/trunk/ELF/LinkerScript.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/LinkerScript.h?rev=287515&r1=287514&r2=287515&view=diff
==============================================================================
--- lld/trunk/ELF/LinkerScript.h (original)
+++ lld/trunk/ELF/LinkerScript.h Sun Nov 20 20:11:05 2016
@@ -224,7 +224,7 @@ public:
   ~LinkerScript();
 
   void processCommands(OutputSectionFactory<ELFT> &Factory);
-  void createSections(OutputSectionFactory<ELFT> &Factory);
+  void addOrphanSections(OutputSectionFactory<ELFT> &Factory);
   void removeEmptyCommands();
   void adjustSectionsBeforeSorting();
   void adjustSectionsAfterSorting();

Modified: lld/trunk/ELF/Writer.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Writer.cpp?rev=287515&r1=287514&r2=287515&view=diff
==============================================================================
--- lld/trunk/ELF/Writer.cpp (original)
+++ lld/trunk/ELF/Writer.cpp Sun Nov 20 20:11:05 2016
@@ -133,18 +133,34 @@ template <class ELFT> void elf::writeRes
 
 // The main function of the writer.
 template <class ELFT> void Writer<ELFT>::run() {
+  // Create linker-synthesized sections such as .got or .plt.
+  // Such sections are of type input section.
   createSyntheticSections();
 
+  // We need to create some reserved symbols such as _end. Create them.
   if (!Config->Relocatable)
     addReservedSymbols();
 
+  // Some architectures use small displacements for jump instructions.
+  // It is linker's responsibility to create thunks containing long
+  // jump instructions if jump targets are too far. Create thunks.
   if (Target->NeedsThunks)
     forEachRelSec(createThunks<ELFT>);
 
+  // Create output sections.
   Script<ELFT>::X->OutputSections = &OutputSections;
   if (ScriptConfig->HasSections) {
-    Script<ELFT>::X->createSections(Factory);
+    // If linker script contains SECTIONS commands, let it create sections.
+    Script<ELFT>::X->processCommands(Factory);
+
+    // Linker scripts may have left some input sections unassigned.
+    // Assign such sections using the default rule.
+    Script<ELFT>::X->addOrphanSections(Factory);
   } else {
+    // If linker script does not contain SECTIONS commands, create
+    // output sections by default rules. We still need to give the
+    // linker script a chance to run, because it might contain
+    // non-SECTIONS commands such as ASSERT.
     createSections();
     Script<ELFT>::X->processCommands(Factory);
   }
@@ -152,6 +168,10 @@ template <class ELFT> void Writer<ELFT>:
   if (Config->Discard != DiscardPolicy::All)
     copyLocalSymbols();
 
+  // Now that we have a complete set of output sections. This function
+  // completes section contents. For example, we need to add strings
+  // to the string table, and add entries to .got and .plt.
+  // finalizeSections does that.
   finalizeSections();
   if (HasError)
     return;
@@ -178,6 +198,7 @@ template <class ELFT> void Writer<ELFT>:
     fixAbsoluteSymbols();
   }
 
+  // Write the result down to a file.
   openFile();
   if (HasError)
     return;
@@ -187,17 +208,21 @@ template <class ELFT> void Writer<ELFT>:
   } else {
     writeSectionsBinary();
   }
+
+  // Backfill .note.gnu.build-id section content. This is done at last
+  // because the content is usually a hash value of the entire output file.
   writeBuildId();
   if (HasError)
     return;
+
   if (auto EC = Buffer->commit())
     error(EC, "failed to write to the output file");
-  if (Config->ExitEarly) {
-    // Flush the output streams and exit immediately.  A full shutdown is a good
-    // test that we are keeping track of all allocated memory, but actually
-    // freeing it is a waste of time in a regular linker run.
+
+  // Flush the output streams and exit immediately. A full shutdown
+  // is a good test that we are keeping track of all allocated memory,
+  // but actually freeing it is a waste of time in a regular linker run.
+  if (Config->ExitEarly)
     exitLld(0);
-  }
 }
 
 // Initialize Out<ELFT> members.




More information about the llvm-commits mailing list