[lld] r313048 - Simplify handling of predefined symbols.

Rafael Espindola via llvm-commits llvm-commits at lists.llvm.org
Tue Sep 12 09:38:01 PDT 2017


Author: rafael
Date: Tue Sep 12 09:38:01 2017
New Revision: 313048

URL: http://llvm.org/viewvc/llvm-project?rev=313048&view=rev
Log:
Simplify handling of predefined symbols.

Given our representation of symbols as section + offset, we can
finalize symbols like _end as soon as the section is known.

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=313048&r1=313047&r2=313048&view=diff
==============================================================================
--- lld/trunk/ELF/Writer.cpp (original)
+++ lld/trunk/ELF/Writer.cpp Tue Sep 12 09:38:01 2017
@@ -54,7 +54,7 @@ private:
   void sortSections();
   void finalizeSections();
   void addPredefinedSections();
-  void addPredefinedSymbols();
+  void setReservedSymbolSections();
 
   std::vector<PhdrEntry *> createPhdrs();
   void removeEmptyPTLoad();
@@ -63,7 +63,7 @@ private:
   void assignFileOffsetsBinary();
   void setPhdrs();
   void fixSectionAlignments();
-  void fixPredefinedSymbols();
+  void makeMipsGpAbs();
   void openFile();
   void writeTrapInstr();
   void writeHeader();
@@ -198,12 +198,6 @@ template <class ELFT> void Writer<ELFT>:
   parallelForEach(OutputSections,
                   [](OutputSection *Sec) { Sec->maybeCompress<ELFT>(); });
 
-  // Generate assignments for predefined symbols (e.g. _end or _etext)
-  // before assigning addresses. These symbols may be referred to from
-  // the linker script and we need to ensure they have the correct value
-  // prior evaluating any expressions using these symbols.
-  addPredefinedSymbols();
-
   Script->assignAddresses();
   Script->allocateHeaders(Phdrs);
 
@@ -223,7 +217,7 @@ template <class ELFT> void Writer<ELFT>:
     for (OutputSection *Sec : OutputSections)
       Sec->Addr = 0;
   } else {
-    fixPredefinedSymbols();
+    makeMipsGpAbs();
   }
 
   // It does not make sense try to open the file if we have error already.
@@ -846,11 +840,11 @@ template <class ELFT> void Writer<ELFT>:
   if (Script->Opt.HasSections)
     return;
 
-  auto Add = [](StringRef S) {
-    return addOptionalRegular<ELFT>(S, Out::ElfHeader, 0, STV_DEFAULT);
+  auto Add = [](StringRef S, int64_t Pos = -1) {
+    return addOptionalRegular<ELFT>(S, Out::ElfHeader, Pos, STV_DEFAULT);
   };
 
-  ElfSym::Bss = Add("__bss_start");
+  ElfSym::Bss = Add("__bss_start", 0);
   ElfSym::End1 = Add("end");
   ElfSym::End2 = Add("_end");
   ElfSym::Etext1 = Add("etext");
@@ -928,7 +922,7 @@ template <class ELFT> void Writer<ELFT>:
 // appropriate time. This ensures that the value is going to be correct by the
 // time any references to these symbols are processed and is equivalent to
 // defining these symbols explicitly in the linker script.
-template <class ELFT> void Writer<ELFT>::addPredefinedSymbols() {
+template <class ELFT> void Writer<ELFT>::setReservedSymbolSections() {
   PhdrEntry *Last = nullptr;
   PhdrEntry *LastRO = nullptr;
   PhdrEntry *LastRW = nullptr;
@@ -943,58 +937,55 @@ template <class ELFT> void Writer<ELFT>:
       LastRO = P;
   }
 
-  auto Make = [](DefinedRegular *S) {
-    auto *Cmd = make<SymbolAssignment>(
-        S->getName(), [=] { return Script->getSymbolValue("", "."); }, "");
-    Cmd->Sym = S;
-    return Cmd;
-  };
-
-  std::vector<BaseCommand *> &V = Script->Opt.Commands;
-
   // _end is the first location after the uninitialized data region.
   if (Last) {
-    for (size_t I = 0; I < V.size(); ++I) {
-      if (V[I] != Last->LastSec)
-        continue;
-      if (ElfSym::End2)
-        V.insert(V.begin() + I + 1, Make(ElfSym::End2));
-      if (ElfSym::End1)
-        V.insert(V.begin() + I + 1, Make(ElfSym::End1));
-      break;
-    }
+    if (ElfSym::End1)
+      ElfSym::End1->Section = Last->LastSec;
+    if (ElfSym::End2)
+      ElfSym::End2->Section = Last->LastSec;
   }
 
   // _etext is the first location after the last read-only loadable segment.
   if (LastRO) {
-    for (size_t I = 0; I < V.size(); ++I) {
-      if (V[I] != LastRO->LastSec)
-        continue;
-      if (ElfSym::Etext2)
-        V.insert(V.begin() + I + 1, Make(ElfSym::Etext2));
-      if (ElfSym::Etext1)
-        V.insert(V.begin() + I + 1, Make(ElfSym::Etext1));
-      break;
-    }
+    if (ElfSym::Etext1)
+      ElfSym::Etext1->Section = LastRO->LastSec;
+    if (ElfSym::Etext2)
+      ElfSym::Etext2->Section = LastRO->LastSec;
   }
 
   // _edata points to the end of the last non SHT_NOBITS section.
   if (LastRW) {
     size_t I = 0;
-    for (; I < V.size(); ++I)
-      if (V[I] == LastRW->FirstSec)
+    for (; I < OutputSections.size(); ++I)
+      if (OutputSections[I] == LastRW->FirstSec)
         break;
 
-    for (; I < V.size(); ++I) {
-      auto *Sec = dyn_cast<OutputSection>(V[I]);
-      if (!Sec || Sec->Type != SHT_NOBITS)
+    for (; I < OutputSections.size(); ++I) {
+      if (OutputSections[I]->Type != SHT_NOBITS)
         continue;
-      if (ElfSym::Edata2)
-        V.insert(V.begin() + I, Make(ElfSym::Edata2));
-      if (ElfSym::Edata1)
-        V.insert(V.begin() + I, Make(ElfSym::Edata1));
       break;
     }
+    if (ElfSym::Edata1)
+      ElfSym::Edata1->Section = OutputSections[I - 1];
+    if (ElfSym::Edata2)
+      ElfSym::Edata2->Section = OutputSections[I - 1];
+  }
+
+  if (ElfSym::Bss)
+    ElfSym::Bss->Section = findSection(".bss");
+
+  // Setup MIPS _gp_disp/__gnu_local_gp symbols which should
+  // be equal to the _gp symbol's value.
+  if (ElfSym::MipsGp && !ElfSym::MipsGp->Value) {
+    // Find GP-relative section with the lowest address
+    // and use this address to calculate default _gp value.
+    for (OutputSection *OS : OutputSections) {
+      if (OS->Flags & SHF_MIPS_GPREL) {
+        ElfSym::MipsGp->Section = OS;
+        ElfSym::MipsGp->Value = 0x7ff0;
+        break;
+      }
+    }
   }
 }
 
@@ -1360,6 +1351,10 @@ template <class ELFT> void Writer<ELFT>:
     Out::ProgramHeaders->Size = sizeof(Elf_Phdr) * Phdrs.size();
   }
 
+  // Some symbols are defined in term of program headers. Now that we
+  // have the headers, we can find out which sections they point to.
+  setReservedSymbolSections();
+
   // Dynamic section must be the last one in this list and dynamic
   // symbol table section (DynSymTab) must be the first one.
   applySynthetic({InX::DynSymTab,    InX::Bss,
@@ -1790,25 +1785,11 @@ static uint16_t getELFType() {
   return ET_EXEC;
 }
 
-// This function is called after we have assigned address and size
-// to each section. This function fixes some predefined
-// symbol values that depend on section address and size.
-template <class ELFT> void Writer<ELFT>::fixPredefinedSymbols() {
-  if (ElfSym::Bss)
-    ElfSym::Bss->Section = findSection(".bss");
-
-  // Setup MIPS _gp_disp/__gnu_local_gp symbols which should
-  // be equal to the _gp symbol's value.
-  if (Config->EMachine == EM_MIPS && !ElfSym::MipsGp->Value) {
-    // Find GP-relative section with the lowest address
-    // and use this address to calculate default _gp value.
-    for (const OutputSection *Cmd : OutputSections) {
-      const OutputSection *OS = Cmd;
-      if (OS->Flags & SHF_MIPS_GPREL) {
-        ElfSym::MipsGp->Value = OS->Addr + 0x7ff0;
-        break;
-      }
-    }
+// For some reason we have to make the mips gp symbol absolute.
+template <class ELFT> void Writer<ELFT>::makeMipsGpAbs() {
+  if (ElfSym::MipsGp && ElfSym::MipsGp->Section) {
+    ElfSym::MipsGp->Value += cast<OutputSection>(ElfSym::MipsGp->Section)->Addr;
+    ElfSym::MipsGp->Section = nullptr;
   }
 }
 




More information about the llvm-commits mailing list