[lld] r278461 - Create only one section for a name in LinkerScript.

Rui Ueyama via llvm-commits llvm-commits at lists.llvm.org
Thu Aug 11 20:16:57 PDT 2016


Author: ruiu
Date: Thu Aug 11 22:16:56 2016
New Revision: 278461

URL: http://llvm.org/viewvc/llvm-project?rev=278461&view=rev
Log:
Create only one section for a name in LinkerScript.

Previously, we created two or more output sections if there are
input sections with the same name but with different attributes.
That is a wrong behavior. This patch fixes the issue.

One thing we need to do is to merge output section attributes.
Currently, we create an output section based on the first input
section's attributes. This may make a wrong output section
attributes. What we need to do is to bitwise-OR attributes.
We'll do it in a follow-up patch.

Modified:
    lld/trunk/ELF/LinkerScript.cpp
    lld/trunk/ELF/LinkerScript.h
    lld/trunk/test/ELF/linkerscript/linkerscript-phdrs.s
    lld/trunk/test/ELF/linkerscript/linkerscript-repsection-va.s

Modified: lld/trunk/ELF/LinkerScript.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/LinkerScript.cpp?rev=278461&r1=278460&r2=278461&view=diff
==============================================================================
--- lld/trunk/ELF/LinkerScript.cpp (original)
+++ lld/trunk/ELF/LinkerScript.cpp Thu Aug 11 22:16:56 2016
@@ -155,27 +155,14 @@ private:
   typename ELFT::Shdr Hdr;
 };
 
-// Helper class, which builds output section list, also
-// creating symbol sections, when needed
-namespace {
-template <class ELFT> class OutputSectionBuilder {
-public:
-  OutputSectionBuilder(OutputSectionFactory<ELFT> &F,
-                       std::vector<OutputSectionBase<ELFT> *> *Out)
-      : Factory(F), OutputSections(Out) {}
-
-  void addSection(StringRef OutputName, InputSectionBase<ELFT> *I);
-  void addSymbol(LayoutInputSection<ELFT> *S) { PendingSymbols.push_back(S); }
-  void flushSymbols();
-  void flushSection();
-
-private:
-  OutputSectionFactory<ELFT> &Factory;
-  std::vector<OutputSectionBase<ELFT> *> *OutputSections;
-  OutputSectionBase<ELFT> *Current = nullptr;
-  std::vector<LayoutInputSection<ELFT> *> PendingSymbols;
-};
-} // anonymous namespace
+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));
@@ -197,38 +184,6 @@ bool LayoutInputSection<ELFT>::classof(c
 }
 
 template <class ELFT>
-void OutputSectionBuilder<ELFT>::addSection(StringRef OutputName,
-                                            InputSectionBase<ELFT> *C) {
-  bool IsNew;
-  std::tie(Current, IsNew) = Factory.create(C, OutputName);
-  if (IsNew)
-    OutputSections->push_back(Current);
-  flushSymbols();
-  Current->addSection(C);
-}
-
-template <class ELFT> void OutputSectionBuilder<ELFT>::flushSymbols() {
-  // Only regular output sections are supported.
-  if (dyn_cast_or_null<OutputSection<ELFT>>(Current)) {
-    for (LayoutInputSection<ELFT> *I : PendingSymbols) {
-      if (I->Cmd->Name == ".") {
-        Current->addSection(I);
-      } else if (shouldDefine<ELFT>(I->Cmd)) {
-        addSynthetic<ELFT>(I->Cmd, Current);
-        Current->addSection(I);
-      }
-    }
-  }
-
-  PendingSymbols.clear();
-}
-
-template <class ELFT> void OutputSectionBuilder<ELFT>::flushSection() {
-  flushSymbols();
-  Current = nullptr;
-}
-
-template <class ELFT>
 static bool compareName(InputSectionBase<ELFT> *A, InputSectionBase<ELFT> *B) {
   return A->getSectionName() < B->getSectionName();
 }
@@ -263,47 +218,76 @@ void LinkerScript<ELFT>::discard(OutputS
 }
 
 template <class ELFT>
-void LinkerScript<ELFT>::createSections(
-    OutputSectionFactory<ELFT> &Factory) {
-  OutputSectionBuilder<ELFT> Builder(Factory, OutputSections);
+std::vector<InputSectionBase<ELFT> *>
+LinkerScript<ELFT>::createInputSectionList(OutputSectionCommand &Cmd) {
+  std::vector<InputSectionBase<ELFT> *> Ret;
+
+  for (const std::unique_ptr<BaseCommand> &Base : Cmd.Commands) {
+    if (auto *Cmd = dyn_cast<SymbolAssignment>(Base.get())) {
+      Ret.push_back(new (LAlloc.Allocate()) LayoutInputSection<ELFT>(Cmd));
+      continue;
+    }
 
+    auto *Cmd = cast<InputSectionDescription>(Base.get());
+    std::vector<InputSectionBase<ELFT> *> V = getInputSections(Cmd);
+    if (Cmd->SortInner)
+      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());
+  }
+  return Ret;
+}
+
+template <class ELFT>
+void LinkerScript<ELFT>::createSections(OutputSectionFactory<ELFT> &Factory) {
   for (const std::unique_ptr<BaseCommand> &Base1 : Opt.Commands) {
     if (auto *Cmd = dyn_cast<OutputSectionCommand>(Base1.get())) {
       if (Cmd->Name == "/DISCARD/") {
         discard(*Cmd);
         continue;
       }
-      for (const std::unique_ptr<BaseCommand> &Base2 : Cmd->Commands) {
-        if (auto *Cmd2 = dyn_cast<SymbolAssignment>(Base2.get())) {
-          Builder.addSymbol(new (LAlloc.Allocate())
-                                LayoutInputSection<ELFT>(Cmd2));
-          continue;
+
+      std::vector<InputSectionBase<ELFT> *> V = createInputSectionList(*Cmd);
+      InputSectionBase<ELFT> *Head = getNonLayoutSection<ELFT>(V);
+      if (!Head)
+        continue;
+
+      OutputSectionBase<ELFT> *OutSec;
+      bool IsNew;
+      std::tie(OutSec, IsNew) = Factory.create(Head, Cmd->Name);
+      if (IsNew)
+        OutputSections->push_back(OutSec);
+
+      for (InputSectionBase<ELFT> *Sec : V) {
+        if (auto *L = dyn_cast<LayoutInputSection<ELFT>>(Sec)) {
+          if (shouldDefine<ELFT>(L->Cmd))
+            addSynthetic<ELFT>(L->Cmd, OutSec);
+          else if (L->Cmd->Name != ".")
+            continue;
         }
-        auto *Cmd2 = cast<InputSectionDescription>(Base2.get());
-        std::vector<InputSectionBase<ELFT> *> Sections = getInputSections(Cmd2);
-        if (Cmd2->SortInner)
-          std::stable_sort(Sections.begin(), Sections.end(),
-                           getComparator<ELFT>(Cmd2->SortInner));
-        if (Cmd2->SortOuter)
-          std::stable_sort(Sections.begin(), Sections.end(),
-                           getComparator<ELFT>(Cmd2->SortOuter));
-        for (InputSectionBase<ELFT> *S : Sections)
-          Builder.addSection(Cmd->Name, S);
+        OutSec->addSection(Sec);
       }
-
-      Builder.flushSection();
     } else if (auto *Cmd2 = dyn_cast<SymbolAssignment>(Base1.get())) {
       if (shouldDefine<ELFT>(Cmd2))
         addRegular<ELFT>(Cmd2);
     }
   }
 
-  // Add all other input sections, which are not listed in script.
+  // Add orphan sections.
   for (const std::unique_ptr<ObjectFile<ELFT>> &F :
-       Symtab<ELFT>::X->getObjectFiles())
-    for (InputSectionBase<ELFT> *S : F->getSections())
-      if (!isDiscarded(S) && !S->OutSec)
-        Builder.addSection(getOutputSectionName(S), S);
+       Symtab<ELFT>::X->getObjectFiles()) {
+    for (InputSectionBase<ELFT> *S : F->getSections()) {
+      if (!isDiscarded(S) && !S->OutSec) {
+        OutputSectionBase<ELFT> *OutSec;
+        bool IsNew;
+        std::tie(OutSec, IsNew) = Factory.create(S, getOutputSectionName(S));
+        if (IsNew)
+          OutputSections->push_back(OutSec);
+        OutSec->addSection(S);
+      }
+    }
+  }
 
   // Remove from the output all the sections which did not meet
   // the optional constraints.

Modified: lld/trunk/ELF/LinkerScript.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/LinkerScript.h?rev=278461&r1=278460&r2=278461&view=diff
==============================================================================
--- lld/trunk/ELF/LinkerScript.h (original)
+++ lld/trunk/ELF/LinkerScript.h Thu Aug 11 22:16:56 2016
@@ -161,6 +161,9 @@ private:
 
   void discard(OutputSectionCommand &Cmd);
 
+  std::vector<InputSectionBase<ELFT> *>
+  createInputSectionList(OutputSectionCommand &Cmd);
+
   // "ScriptConfig" is a bit too long, so define a short name for it.
   ScriptConfiguration &Opt = *ScriptConfig;
 

Modified: lld/trunk/test/ELF/linkerscript/linkerscript-phdrs.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/linkerscript/linkerscript-phdrs.s?rev=278461&r1=278460&r2=278461&view=diff
==============================================================================
--- lld/trunk/test/ELF/linkerscript/linkerscript-phdrs.s (original)
+++ lld/trunk/test/ELF/linkerscript/linkerscript-phdrs.s Thu Aug 11 22:16:56 2016
@@ -17,9 +17,8 @@
 # CHECK-NEXT:    PhysicalAddress: 0x10000000
 # CHECK-NEXT:    FileSize: 521
 # CHECK-NEXT:    MemSize: 521
-# CHECK-NEXT:    Flags [ (0x7)
+# CHECK-NEXT:    Flags [ (0x5)
 # CHECK-NEXT:      PF_R (0x4)
-# CHECK-NEXT:      PF_W (0x2)
 # CHECK-NEXT:      PF_X (0x1)
 # CHECK-NEXT:    ]
 

Modified: lld/trunk/test/ELF/linkerscript/linkerscript-repsection-va.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/linkerscript/linkerscript-repsection-va.s?rev=278461&r1=278460&r2=278461&view=diff
==============================================================================
--- lld/trunk/test/ELF/linkerscript/linkerscript-repsection-va.s (original)
+++ lld/trunk/test/ELF/linkerscript/linkerscript-repsection-va.s Thu Aug 11 22:16:56 2016
@@ -7,9 +7,8 @@
 # CHECK:      Sections:
 # CHECK-NEXT: Idx Name          Size      Address          Type
 # CHECK-NEXT:   0               00000000 0000000000000000
-# CHECK-NEXT:   1 .foo          00000004 0000000000000158 DATA
-# CHECK-NEXT:   2 .foo          00000004 000000000000015c DATA
-# CHECK-NEXT:   3 .text         00000001 0000000000000160 TEXT DATA
+# CHECK-NEXT:   1 .foo          00000008 0000000000000120 DATA
+# CHECK-NEXT:   2 .text         00000001 0000000000000128 TEXT DATA
 
 .global _start
 _start:




More information about the llvm-commits mailing list