summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lld/ELF/LinkerScript.cpp26
-rw-r--r--lld/ELF/LinkerScript.h3
-rw-r--r--lld/ELF/ScriptParser.cpp12
-rw-r--r--lld/test/ELF/linkerscript/insert-after.test4
-rw-r--r--lld/test/ELF/linkerscript/insert-before.test29
-rw-r--r--lld/test/ELF/linkerscript/insert-broken.test2
6 files changed, 60 insertions, 16 deletions
diff --git a/lld/ELF/LinkerScript.cpp b/lld/ELF/LinkerScript.cpp
index fcfe0783300..fd101a0b0cd 100644
--- a/lld/ELF/LinkerScript.cpp
+++ b/lld/ELF/LinkerScript.cpp
@@ -207,18 +207,26 @@ static void declareSymbol(SymbolAssignment *Cmd) {
// the list of script commands to mix sections inserted into.
void LinkerScript::processInsertCommands() {
std::vector<BaseCommand *> V;
+ auto Insert = [&](std::vector<BaseCommand *> &From) {
+ V.insert(V.end(), From.begin(), From.end());
+ From.clear();
+ };
+
for (BaseCommand *Base : SectionCommands) {
- V.push_back(Base);
- if (auto *Cmd = dyn_cast<OutputSection>(Base)) {
- std::vector<BaseCommand *> &W = InsertAfterCommands[Cmd->Name];
- V.insert(V.end(), W.begin(), W.end());
- W.clear();
+ if (auto *OS = dyn_cast<OutputSection>(Base)) {
+ Insert(InsertBeforeCommands[OS->Name]);
+ V.push_back(Base);
+ Insert(InsertAfterCommands[OS->Name]);
+ continue;
}
+ V.push_back(Base);
}
- for (std::pair<StringRef, std::vector<BaseCommand *>> &P :
- InsertAfterCommands)
- if (!P.second.empty())
- error("unable to INSERT AFTER " + P.first + ": section not defined");
+
+ for (auto &Cmds : {InsertBeforeCommands, InsertAfterCommands})
+ for (const std::pair<StringRef, std::vector<BaseCommand *>> &P : Cmds)
+ if (!P.second.empty())
+ error("unable to INSERT AFTER/BEFORE " + P.first +
+ ": section not defined");
SectionCommands = std::move(V);
}
diff --git a/lld/ELF/LinkerScript.h b/lld/ELF/LinkerScript.h
index fe5d6d8ef6f..782176a91ee 100644
--- a/lld/ELF/LinkerScript.h
+++ b/lld/ELF/LinkerScript.h
@@ -289,9 +289,10 @@ public:
// A list of symbols referenced by the script.
std::vector<llvm::StringRef> ReferencedSymbols;
- // Used to implement INSERT AFTER. Contains commands that need
+ // Used to implement INSERT [AFTER|BEFORE]. Contains commands that need
// to be inserted into SECTIONS commands list.
llvm::DenseMap<StringRef, std::vector<BaseCommand *>> InsertAfterCommands;
+ llvm::DenseMap<StringRef, std::vector<BaseCommand *>> InsertBeforeCommands;
};
extern LinkerScript *Script;
diff --git a/lld/ELF/ScriptParser.cpp b/lld/ELF/ScriptParser.cpp
index 2ff94650dbd..cc51cb0437b 100644
--- a/lld/ELF/ScriptParser.cpp
+++ b/lld/ELF/ScriptParser.cpp
@@ -450,9 +450,15 @@ void ScriptParser::readSections() {
}
if (!atEOF() && consume("INSERT")) {
- expect("AFTER");
- std::vector<BaseCommand *> &Dest = Script->InsertAfterCommands[next()];
- Dest.insert(Dest.end(), V.begin(), V.end());
+ std::vector<BaseCommand *> *Dest = nullptr;
+ if (consume("AFTER"))
+ Dest = &Script->InsertAfterCommands[next()];
+ else if (consume("BEFORE"))
+ Dest = &Script->InsertBeforeCommands[next()];
+ else
+ setError("expected AFTER/BEFORE, but got '" + next() + "'");
+ if (Dest)
+ Dest->insert(Dest->end(), V.begin(), V.end());
return;
}
diff --git a/lld/test/ELF/linkerscript/insert-after.test b/lld/test/ELF/linkerscript/insert-after.test
index 2da0e296aa0..ab5ba183de2 100644
--- a/lld/test/ELF/linkerscript/insert-after.test
+++ b/lld/test/ELF/linkerscript/insert-after.test
@@ -25,5 +25,5 @@ SECTIONS {
# RUN: not ld.lld %t1.o -o %t1 --script %s 2>&1 \
# RUN: | FileCheck %s --check-prefix=ERR
-# ERR-DAG: error: unable to INSERT AFTER .text: section not defined
-# ERR-DAG: error: unable to INSERT AFTER .data: section not defined
+# ERR-DAG: error: unable to INSERT AFTER/BEFORE .text: section not defined
+# ERR-DAG: error: unable to INSERT AFTER/BEFORE .data: section not defined
diff --git a/lld/test/ELF/linkerscript/insert-before.test b/lld/test/ELF/linkerscript/insert-before.test
new file mode 100644
index 00000000000..507e8bdce08
--- /dev/null
+++ b/lld/test/ELF/linkerscript/insert-before.test
@@ -0,0 +1,29 @@
+# REQUIRES: x86
+# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %p/Inputs/insert-after.s -o %t1.o
+
+## Main linker script contains .text and .data sections. Here
+## we check that can use INSERT BEFORE to insert sections .foo.data
+## and .foo.text at the right places.
+
+SECTIONS {
+ .foo.data : { *(.foo.data) }
+} INSERT BEFORE .data;
+
+SECTIONS {
+ .foo.text : { *(.foo.text) }
+} INSERT BEFORE .text;
+
+# RUN: ld.lld %t1.o -o %t1 --script %p/Inputs/insert-after.script --script %s
+# RUN: llvm-objdump -section-headers %t1 | FileCheck %s
+# CHECK: Sections:
+# CHECK-NEXT: Idx Name Size Address Type
+# CHECK-NEXT: 0 00000000 0000000000000000
+# CHECK-NEXT: 1 .foo.text 00000008 0000000000000000 TEXT DATA
+# CHECK-NEXT: 2 .text 00000008 0000000000000008 TEXT DATA
+# CHECK-NEXT: 3 .foo.data 00000008 0000000000000010 DATA
+# CHECK-NEXT: 4 .data 00000008 0000000000000018 DATA
+
+# RUN: not ld.lld %t1.o -o %t1 --script %s 2>&1 \
+# RUN: | FileCheck %s --check-prefix=ERR
+# ERR-DAG: error: unable to INSERT AFTER/BEFORE .text: section not defined
+# ERR-DAG: error: unable to INSERT AFTER/BEFORE .data: section not defined
diff --git a/lld/test/ELF/linkerscript/insert-broken.test b/lld/test/ELF/linkerscript/insert-broken.test
index 19bc2ef1214..9a295623a2c 100644
--- a/lld/test/ELF/linkerscript/insert-broken.test
+++ b/lld/test/ELF/linkerscript/insert-broken.test
@@ -3,4 +3,4 @@ SECTIONS {
} INSERT .data;
# RUN: not ld.lld -o %t1 --script %s 2>&1 | FileCheck %s
-# CHECK: {{.*}}:3: AFTER expected, but got .data
+# CHECK: {{.*}}:3: expected AFTER/BEFORE, but got '.data'
OpenPOWER on IntegriCloud