summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lld/ELF/Driver.cpp4
-rw-r--r--lld/ELF/LinkerScript.cpp20
-rw-r--r--lld/ELF/LinkerScript.h7
-rw-r--r--lld/ELF/ScriptParser.cpp13
-rw-r--r--lld/test/ELF/linkerscript/Inputs/insert-after.s11
-rw-r--r--lld/test/ELF/linkerscript/Inputs/insert-after.script4
-rw-r--r--lld/test/ELF/linkerscript/insert-after.test29
7 files changed, 87 insertions, 1 deletions
diff --git a/lld/ELF/Driver.cpp b/lld/ELF/Driver.cpp
index ebfab486c01..9f32e6aab3c 100644
--- a/lld/ELF/Driver.cpp
+++ b/lld/ELF/Driver.cpp
@@ -1087,6 +1087,10 @@ template <class ELFT> void LinkerDriver::link(opt::InputArgList &Args) {
if (errorCount())
return;
+ // Now when we read all script files, we want to finalize order of linker
+ // script commands, which can be not yet final because of INSERT commands.
+ Script->processInsertCommands();
+
// We want to declare linker script's symbols early,
// so that we can version them.
// They also might be exported if referenced by DSOs.
diff --git a/lld/ELF/LinkerScript.cpp b/lld/ELF/LinkerScript.cpp
index 6b7f8ed2216..e4b3bc99210 100644
--- a/lld/ELF/LinkerScript.cpp
+++ b/lld/ELF/LinkerScript.cpp
@@ -203,6 +203,26 @@ static void declareSymbol(SymbolAssignment *Cmd) {
Cmd->Provide = false;
}
+// This method is used to handle INSERT AFTER statement. Here we rebuild
+// the list of script commands to mix sections inserted into.
+void LinkerScript::processInsertCommands() {
+ std::vector<BaseCommand *> V;
+ 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();
+ }
+ }
+ for (std::pair<StringRef, std::vector<BaseCommand *>> &P :
+ InsertAfterCommands)
+ if (!P.second.empty())
+ error("unable to INSERT AFTER " + P.first + ": section not defined");
+
+ SectionCommands = std::move(V);
+}
+
// Symbols defined in script should not be inlined by LTO. At the same time
// we don't know their final values until late stages of link. Here we scan
// over symbol assignment commands and create placeholder symbols if needed.
diff --git a/lld/ELF/LinkerScript.h b/lld/ELF/LinkerScript.h
index 4eddafa4996..fe5d6d8ef6f 100644
--- a/lld/ELF/LinkerScript.h
+++ b/lld/ELF/LinkerScript.h
@@ -267,6 +267,9 @@ public:
void processSectionCommands();
void declareSymbols();
+ // Used to handle INSERT AFTER statements.
+ void processInsertCommands();
+
// SECTIONS command list.
std::vector<BaseCommand *> SectionCommands;
@@ -285,6 +288,10 @@ public:
// A list of symbols referenced by the script.
std::vector<llvm::StringRef> ReferencedSymbols;
+
+ // Used to implement INSERT AFTER. Contains commands that need
+ // to be inserted into SECTIONS commands list.
+ llvm::DenseMap<StringRef, std::vector<BaseCommand *>> InsertAfterCommands;
};
extern LinkerScript *Script;
diff --git a/lld/ELF/ScriptParser.cpp b/lld/ELF/ScriptParser.cpp
index c68c25ad615..29dec116ce8 100644
--- a/lld/ELF/ScriptParser.cpp
+++ b/lld/ELF/ScriptParser.cpp
@@ -436,6 +436,7 @@ void ScriptParser::readSections() {
Config->SingleRoRx = true;
expect("{");
+ std::vector<BaseCommand *> V;
while (!errorCount() && !consume("}")) {
StringRef Tok = next();
BaseCommand *Cmd = readProvideOrAssignment(Tok);
@@ -445,8 +446,18 @@ void ScriptParser::readSections() {
else
Cmd = readOutputSectionDescription(Tok);
}
- Script->SectionCommands.push_back(Cmd);
+ V.push_back(Cmd);
}
+
+ if (!atEOF() && consume("INSERT")) {
+ consume("AFTER");
+ std::vector<BaseCommand *> &Dest = Script->InsertAfterCommands[next()];
+ Dest.insert(Dest.end(), V.begin(), V.end());
+ return;
+ }
+
+ Script->SectionCommands.insert(Script->SectionCommands.end(), V.begin(),
+ V.end());
}
static int precedence(StringRef Op) {
diff --git a/lld/test/ELF/linkerscript/Inputs/insert-after.s b/lld/test/ELF/linkerscript/Inputs/insert-after.s
new file mode 100644
index 00000000000..88a6044cc96
--- /dev/null
+++ b/lld/test/ELF/linkerscript/Inputs/insert-after.s
@@ -0,0 +1,11 @@
+.section .foo.text,"ax"
+.quad 0
+
+.section .foo.data,"aw"
+.quad 0
+
+.section .text.1,"ax"
+.quad 0
+
+.section .data.1,"aw"
+.quad 0
diff --git a/lld/test/ELF/linkerscript/Inputs/insert-after.script b/lld/test/ELF/linkerscript/Inputs/insert-after.script
new file mode 100644
index 00000000000..cb95878bc5c
--- /dev/null
+++ b/lld/test/ELF/linkerscript/Inputs/insert-after.script
@@ -0,0 +1,4 @@
+SECTIONS {
+ .text : { *(.text.*) }
+ .data : { *(.data.*) }
+}
diff --git a/lld/test/ELF/linkerscript/insert-after.test b/lld/test/ELF/linkerscript/insert-after.test
new file mode 100644
index 00000000000..2da0e296aa0
--- /dev/null
+++ b/lld/test/ELF/linkerscript/insert-after.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 AFTER to insert sections .foo.data
+## and .foo.text at the right places.
+
+SECTIONS {
+ .foo.data : { *(.foo.data) }
+} INSERT AFTER .data;
+
+SECTIONS {
+ .foo.text : { *(.foo.text) }
+} INSERT AFTER .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 .text 00000008 0000000000000000 TEXT DATA
+# CHECK-NEXT: 2 .foo.text 00000008 0000000000000008 TEXT DATA
+# CHECK-NEXT: 3 .data 00000008 0000000000000010 DATA
+# CHECK-NEXT: 4 .foo.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 .text: section not defined
+# ERR-DAG: error: unable to INSERT AFTER .data: section not defined
OpenPOWER on IntegriCloud