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.
llvm-svn: 278461
diff --git a/lld/ELF/LinkerScript.cpp b/lld/ELF/LinkerScript.cpp
index f6712d3..980d27e 100644
--- a/lld/ELF/LinkerScript.cpp
+++ b/lld/ELF/LinkerScript.cpp
@@ -155,27 +155,14 @@
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 @@
}
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 @@
}
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;
- }
- 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);
- }
- Builder.flushSection();
+ 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;
+ }
+ OutSec->addSection(Sec);
+ }
} 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.
diff --git a/lld/ELF/LinkerScript.h b/lld/ELF/LinkerScript.h
index 866326a..8029c74 100644
--- a/lld/ELF/LinkerScript.h
+++ b/lld/ELF/LinkerScript.h
@@ -161,6 +161,9 @@
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;
diff --git a/lld/test/ELF/linkerscript/linkerscript-phdrs.s b/lld/test/ELF/linkerscript/linkerscript-phdrs.s
index cd6bf82..775e002 100644
--- a/lld/test/ELF/linkerscript/linkerscript-phdrs.s
+++ b/lld/test/ELF/linkerscript/linkerscript-phdrs.s
@@ -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: ]
diff --git a/lld/test/ELF/linkerscript/linkerscript-repsection-va.s b/lld/test/ELF/linkerscript/linkerscript-repsection-va.s
index 4feeaa0..29ecdf8 100644
--- a/lld/test/ELF/linkerscript/linkerscript-repsection-va.s
+++ b/lld/test/ELF/linkerscript/linkerscript-repsection-va.s
@@ -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: