Create only one section for a name in LinkerScript.
authorRui Ueyama <ruiu@google.com>
Fri, 12 Aug 2016 03:16:56 +0000 (03:16 +0000)
committerRui Ueyama <ruiu@google.com>
Fri, 12 Aug 2016 03:16:56 +0000 (03:16 +0000)
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.

llvm-svn: 278461

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

index f6712d3..980d27e 100644 (file)
@@ -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(const InputSectionBase<ELFT> *S) {
 }
 
 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(OutputSectionCommand &Cmd) {
 }
 
 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.
index 866326a..8029c74 100644 (file)
@@ -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;
 
index cd6bf82..775e002 100644 (file)
@@ -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:    ]
 
index 4feeaa0..29ecdf8 100644 (file)
@@ -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: