[lld] r280348 - Eliminate LayoutInputSection class

Eugene Leviant via llvm-commits llvm-commits at lists.llvm.org
Thu Sep 1 02:55:58 PDT 2016


Author: evgeny777
Date: Thu Sep  1 04:55:57 2016
New Revision: 280348

URL: http://llvm.org/viewvc/llvm-project?rev=280348&view=rev
Log:
Eliminate LayoutInputSection class

Previously we used LayoutInputSection class to correctly assign
symbols defined in linker script. This patch removes it and uses
pointer to preceding input section in SymbolAssignment class instead.

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

Modified:
    lld/trunk/ELF/InputSection.cpp
    lld/trunk/ELF/InputSection.h
    lld/trunk/ELF/LinkerScript.cpp
    lld/trunk/ELF/LinkerScript.h
    lld/trunk/ELF/OutputSections.cpp

Modified: lld/trunk/ELF/InputSection.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/InputSection.cpp?rev=280348&r1=280347&r2=280348&view=diff
==============================================================================
--- lld/trunk/ELF/InputSection.cpp (original)
+++ lld/trunk/ELF/InputSection.cpp Thu Sep  1 04:55:57 2016
@@ -30,14 +30,10 @@ using namespace lld::elf;
 
 template <class ELFT>
 InputSectionBase<ELFT>::InputSectionBase(elf::ObjectFile<ELFT> *File,
-                                         const Elf_Shdr *Header,
-                                         Kind SectionKind)
-    : Header(Header), File(File), SectionKind(SectionKind), Repl(this),
-      Compressed(Header->sh_flags & SHF_COMPRESSED) {
-  // The garbage collector sets sections' Live bits.
-  // If GC is disabled, all sections are considered live by default.
-  Live = !Config->GcSections;
-
+                                         const Elf_Shdr *Hdr, Kind SectionKind)
+    : InputSectionData(SectionKind, Hdr->sh_flags & SHF_COMPRESSED,
+                       !Config->GcSections),
+      Header(Hdr), File(File), Repl(this) {
   // The ELF spec states that a value of 0 means the section has
   // no alignment constraits.
   Alignment = std::max<uintX_t>(Header->sh_addralign, 1);
@@ -71,7 +67,6 @@ template <class ELFT>
 typename ELFT::uint InputSectionBase<ELFT>::getOffset(uintX_t Offset) const {
   switch (SectionKind) {
   case Regular:
-  case Layout:
     return cast<InputSection<ELFT>>(this)->OutSecOff + Offset;
   case EHFrame:
     // The file crtbeginT.o has relocations pointing to the start of an empty
@@ -131,7 +126,7 @@ InputSection<ELFT>::InputSection(elf::Ob
 
 template <class ELFT>
 bool InputSection<ELFT>::classof(const InputSectionBase<ELFT> *S) {
-  return S->SectionKind == Base::Regular || S->SectionKind == Base::Layout;
+  return S->SectionKind == Base::Regular;
 }
 
 template <class ELFT>

Modified: lld/trunk/ELF/InputSection.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/InputSection.h?rev=280348&r1=280347&r2=280348&view=diff
==============================================================================
--- lld/trunk/ELF/InputSection.h (original)
+++ lld/trunk/ELF/InputSection.h Thu Sep  1 04:55:57 2016
@@ -30,8 +30,33 @@ template <class ELFT> class ObjectFile;
 template <class ELFT> class OutputSection;
 template <class ELFT> class OutputSectionBase;
 
+// We need non-template input section class to store symbol layout
+// in linker script parser structures, where we do not have ELFT
+// template parameter. For each scripted output section symbol we
+// store pointer to preceding InputSectionData object or nullptr,
+// if symbol should be placed at the very beginning of the output
+// section
+class InputSectionData {
+public:
+  enum Kind { Regular, EHFrame, Merge, MipsReginfo, MipsOptions, MipsAbiFlags };
+
+  // The garbage collector sets sections' Live bits.
+  // If GC is disabled, all sections are considered live by default.
+  InputSectionData(Kind SectionKind, bool Compressed, bool Live)
+      : SectionKind(SectionKind), Live(Live), Compressed(Compressed) {}
+
+  Kind SectionKind;
+  uint32_t Alignment;
+  // Used for garbage collection.
+  bool Live;
+
+  bool Compressed;
+  // If a section is compressed, this vector has uncompressed section data.
+  SmallVector<char, 0> Uncompressed;
+};
+
 // This corresponds to a section of an input file.
-template <class ELFT> class InputSectionBase {
+template <class ELFT> class InputSectionBase : public InputSectionData {
 protected:
   typedef typename ELFT::Chdr Elf_Chdr;
   typedef typename ELFT::Rel Elf_Rel;
@@ -44,30 +69,12 @@ protected:
   // The file this section is from.
   ObjectFile<ELFT> *File;
 
-  // If a section is compressed, this vector has uncompressed section data.
-  SmallVector<char, 0> Uncompressed;
-
 public:
-  enum Kind {
-    Regular,
-    EHFrame,
-    Merge,
-    MipsReginfo,
-    MipsOptions,
-    MipsAbiFlags,
-    Layout
-  };
-  Kind SectionKind;
-
-  InputSectionBase() : Repl(this) {}
+  InputSectionBase() : InputSectionData(Regular, false, false), Repl(this) {}
 
   InputSectionBase(ObjectFile<ELFT> *File, const Elf_Shdr *Header,
                    Kind SectionKind);
   OutputSectionBase<ELFT> *OutSec = nullptr;
-  uint32_t Alignment;
-
-  // Used for garbage collection.
-  bool Live;
 
   // This pointer points to the "real" instance of this instance.
   // Usually Repl == this. However, if ICF merges two sections,
@@ -96,8 +103,6 @@ public:
 
   void relocate(uint8_t *Buf, uint8_t *BufEnd);
   std::vector<Relocation<ELFT>> Relocations;
-
-  bool Compressed;
 };
 
 template <class ELFT> InputSectionBase<ELFT> InputSectionBase<ELFT>::Discarded;

Modified: lld/trunk/ELF/LinkerScript.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/LinkerScript.cpp?rev=280348&r1=280347&r2=280348&view=diff
==============================================================================
--- lld/trunk/ELF/LinkerScript.cpp (original)
+++ lld/trunk/ELF/LinkerScript.cpp Thu Sep  1 04:55:57 2016
@@ -133,54 +133,6 @@ LinkerScript<ELFT>::getInputSections(con
   return Ret;
 }
 
-// You can define new symbols using linker scripts. For example,
-// ".text { abc.o(.text); foo = .; def.o(.text); }" defines symbol
-// foo just after abc.o's text section contents. This class is to
-// handle such symbol definitions.
-//
-// In order to handle scripts like the above one, we want to
-// keep symbol definitions in output sections. Because output sections
-// can contain only input sections, we wrap symbol definitions
-// with dummy input sections. This class serves that purpose.
-template <class ELFT>
-class elf::LayoutInputSection : public InputSectionBase<ELFT> {
-public:
-  explicit LayoutInputSection(SymbolAssignment *Cmd);
-  static bool classof(const InputSectionBase<ELFT> *S);
-  SymbolAssignment *Cmd;
-
-private:
-  typename ELFT::Shdr Hdr;
-};
-
-template <class ELFT>
-static InputSectionBase<ELFT> *
-getNonLayoutSection(std::vector<InputSectionBase<ELFT> *> &Vec) {
-  for (InputSectionBase<ELFT> *S : Vec)
-    if (!isa<LayoutInputSection<ELFT>>(S))
-      return S;
-  return nullptr;
-}
-
-template <class T> static T *zero(T *Val) {
-  memset(Val, 0, sizeof(*Val));
-  return Val;
-}
-
-template <class ELFT>
-LayoutInputSection<ELFT>::LayoutInputSection(SymbolAssignment *Cmd)
-    : InputSectionBase<ELFT>(nullptr, zero(&Hdr),
-                             InputSectionBase<ELFT>::Layout),
-      Cmd(Cmd) {
-  this->Live = true;
-  Hdr.sh_type = SHT_NOBITS;
-}
-
-template <class ELFT>
-bool LayoutInputSection<ELFT>::classof(const InputSectionBase<ELFT> *S) {
-  return S->SectionKind == InputSectionBase<ELFT>::Layout;
-}
-
 template <class ELFT>
 static bool compareName(InputSectionBase<ELFT> *A, InputSectionBase<ELFT> *B) {
   return A->getSectionName() < B->getSectionName();
@@ -236,12 +188,13 @@ template <class ELFT>
 std::vector<InputSectionBase<ELFT> *>
 LinkerScript<ELFT>::createInputSectionList(OutputSectionCommand &OutCmd) {
   std::vector<InputSectionBase<ELFT> *> Ret;
+  DenseSet<InputSectionBase<ELFT> *> SectionIndex;
 
   for (const std::unique_ptr<BaseCommand> &Base : OutCmd.Commands) {
     if (auto *OutCmd = dyn_cast<SymbolAssignment>(Base.get())) {
       if (shouldDefine<ELFT>(OutCmd))
         addSynthetic<ELFT>(OutCmd);
-      Ret.push_back(new (LAlloc.Allocate()) LayoutInputSection<ELFT>(OutCmd));
+      OutCmd->GoesAfter = Ret.empty() ? nullptr : Ret.back();
       continue;
     }
 
@@ -253,7 +206,12 @@ LinkerScript<ELFT>::createInputSectionLi
       std::stable_sort(V.begin(), V.end(), getComparator<ELFT>(Cmd->SortInner));
     if (Cmd->SortOuter)
       std::stable_sort(V.begin(), V.end(), getComparator<ELFT>(Cmd->SortOuter));
-    Ret.insert(Ret.end(), V.begin(), V.end());
+
+    // Add all input sections corresponding to rule 'Cmd' to
+    // resulting vector. We do not add duplicate input sections.
+    for (InputSectionBase<ELFT> *S : V)
+      if (SectionIndex.insert(S).second)
+        Ret.push_back(S);
   }
   return Ret;
 }
@@ -284,13 +242,12 @@ void LinkerScript<ELFT>::createSections(
       }
 
       std::vector<InputSectionBase<ELFT> *> V = createInputSectionList(*Cmd);
-      InputSectionBase<ELFT> *Head = getNonLayoutSection<ELFT>(V);
-      if (!Head)
+      if (V.empty())
         continue;
 
       OutputSectionBase<ELFT> *OutSec;
       bool IsNew;
-      std::tie(OutSec, IsNew) = Factory.create(Head, Cmd->Name);
+      std::tie(OutSec, IsNew) = Factory.create(V.front(), Cmd->Name);
       if (IsNew)
         OutputSections->push_back(OutSec);
 
@@ -298,8 +255,7 @@ void LinkerScript<ELFT>::createSections(
       for (InputSectionBase<ELFT> *Sec : V) {
         if (Subalign)
           Sec->Alignment = Subalign;
-        if (!Sec->OutSec)
-          OutSec->addSection(Sec);
+        OutSec->addSection(Sec);
       }
     }
   }
@@ -359,31 +315,49 @@ void assignOffsets(OutputSectionCommand
     addStartEndSymbols(Cmd, Sec);
     return;
   }
-
   typedef typename ELFT::uint uintX_t;
   uintX_t Off = 0;
+  auto ItCmd = Cmd->Commands.begin();
 
-  for (InputSection<ELFT> *I : OutSec->Sections) {
-    if (auto *L = dyn_cast<LayoutInputSection<ELFT>>(I)) {
-      uintX_t Value = L->Cmd->Expression(Sec->getVA() + Off) - Sec->getVA();
-      if (L->Cmd->Name == ".") {
+  // Assigns values to all symbols following the given
+  // input section 'D' in output section 'Sec'. When symbols
+  // are in the beginning of output section the value of 'D'
+  // is nullptr.
+  auto AssignSuccessors = [&](InputSectionData *D) {
+    for (; ItCmd != Cmd->Commands.end(); ++ItCmd) {
+      auto *AssignCmd = dyn_cast<SymbolAssignment>(ItCmd->get());
+      if (!AssignCmd)
+        continue;
+      if (D != AssignCmd->GoesAfter)
+        break;
+
+      uintX_t Value = AssignCmd->Expression(Sec->getVA() + Off) - Sec->getVA();
+      if (AssignCmd->Name == ".") {
+        // Update to location counter means update to section size.
         Off = Value;
-      } else if (auto *Sym =
-                     cast_or_null<DefinedSynthetic<ELFT>>(L->Cmd->Sym)) {
-        // shouldDefine could have returned false, so we need to check Sym,
-        // for non-null value.
+        Sec->setSize(Off);
+        continue;
+      }
+
+      if (DefinedSynthetic<ELFT> *Sym =
+              cast_or_null<DefinedSynthetic<ELFT>>(AssignCmd->Sym)) {
         Sym->Section = OutSec;
         Sym->Value = Value;
       }
-    } else {
-      Off = alignTo(Off, I->Alignment);
-      I->OutSecOff = Off;
-      Off += I->getSize();
     }
+  };
+
+  AssignSuccessors(nullptr);
+  for (InputSection<ELFT> *I : OutSec->Sections) {
+    Off = alignTo(Off, I->Alignment);
+    I->OutSecOff = Off;
+    Off += I->getSize();
     // Update section size inside for-loop, so that SIZEOF
     // works correctly in the case below:
     // .foo { *(.aaa) a = SIZEOF(.foo); *(.bbb) }
     Sec->setSize(Off);
+    // Add symbols following current input section.
+    AssignSuccessors(I);
   }
 }
 

Modified: lld/trunk/ELF/LinkerScript.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/LinkerScript.h?rev=280348&r1=280347&r2=280348&view=diff
==============================================================================
--- lld/trunk/ELF/LinkerScript.h (original)
+++ lld/trunk/ELF/LinkerScript.h Thu Sep  1 04:55:57 2016
@@ -26,7 +26,7 @@ class SymbolBody;
 template <class ELFT> class InputSectionBase;
 template <class ELFT> class OutputSectionBase;
 template <class ELFT> class OutputSectionFactory;
-template <class ELFT> class LayoutInputSection;
+class InputSectionData;
 
 typedef std::function<uint64_t(uint64_t)> Expr;
 
@@ -66,6 +66,7 @@ struct SymbolAssignment : BaseCommand {
   // Command attributes for PROVIDE, HIDDEN and PROVIDE_HIDDEN.
   bool Provide = false;
   bool Hidden = false;
+  InputSectionData *GoesAfter = nullptr;
 };
 
 // Linker scripts allow additional constraints to be put on ouput sections.
@@ -178,8 +179,6 @@ private:
   std::vector<size_t> getPhdrIndices(StringRef SectionName);
   size_t getPhdrIndex(StringRef PhdrName);
 
-  llvm::SpecificBumpPtrAllocator<LayoutInputSection<ELFT>> LAlloc;
-
   uintX_t Dot;
 };
 

Modified: lld/trunk/ELF/OutputSections.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/OutputSections.cpp?rev=280348&r1=280347&r2=280348&view=diff
==============================================================================
--- lld/trunk/ELF/OutputSections.cpp (original)
+++ lld/trunk/ELF/OutputSections.cpp Thu Sep  1 04:55:57 2016
@@ -1825,8 +1825,6 @@ OutputSectionFactory<ELFT>::create(Input
   case InputSectionBase<ELFT>::MipsAbiFlags:
     Sec = new MipsAbiFlagsOutputSection<ELFT>();
     break;
-  case InputSectionBase<ELFT>::Layout:
-    llvm_unreachable("Invalid section type");
   }
   Out<ELFT>::Pool.emplace_back(Sec);
   return {Sec, true};




More information about the llvm-commits mailing list