Skip to content

Commit 9e2c8a9

Browse files
author
George Rimar
committedMar 8, 2018
[ELF] - Support "INSERT AFTER" statement.
This implements INSERT AFTER in a following way: During reading scripts it collects all insert statements. After we done and read all files it inserts statements into script commands list. With that: * Rest of code does know nothing about INSERT. * Approach is straightforward and have no visible limitations. * It is also easy to support INSERT BEFORE (was seen in clang code once). * Should work for PR35877 and similar cases. Cons: * It assumes we have "main" scripts that describes sections. Differential revision: https://reviews.llvm.org/D43468 llvm-svn: 327003
1 parent 9003b3b commit 9e2c8a9

File tree

7 files changed

+87
-1
lines changed

7 files changed

+87
-1
lines changed
 

‎lld/ELF/Driver.cpp

+4
Original file line numberDiff line numberDiff line change
@@ -1087,6 +1087,10 @@ template <class ELFT> void LinkerDriver::link(opt::InputArgList &Args) {
10871087
if (errorCount())
10881088
return;
10891089

1090+
// Now when we read all script files, we want to finalize order of linker
1091+
// script commands, which can be not yet final because of INSERT commands.
1092+
Script->processInsertCommands();
1093+
10901094
// We want to declare linker script's symbols early,
10911095
// so that we can version them.
10921096
// They also might be exported if referenced by DSOs.

‎lld/ELF/LinkerScript.cpp

+20
Original file line numberDiff line numberDiff line change
@@ -203,6 +203,26 @@ static void declareSymbol(SymbolAssignment *Cmd) {
203203
Cmd->Provide = false;
204204
}
205205

206+
// This method is used to handle INSERT AFTER statement. Here we rebuild
207+
// the list of script commands to mix sections inserted into.
208+
void LinkerScript::processInsertCommands() {
209+
std::vector<BaseCommand *> V;
210+
for (BaseCommand *Base : SectionCommands) {
211+
V.push_back(Base);
212+
if (auto *Cmd = dyn_cast<OutputSection>(Base)) {
213+
std::vector<BaseCommand *> &W = InsertAfterCommands[Cmd->Name];
214+
V.insert(V.end(), W.begin(), W.end());
215+
W.clear();
216+
}
217+
}
218+
for (std::pair<StringRef, std::vector<BaseCommand *>> &P :
219+
InsertAfterCommands)
220+
if (!P.second.empty())
221+
error("unable to INSERT AFTER " + P.first + ": section not defined");
222+
223+
SectionCommands = std::move(V);
224+
}
225+
206226
// Symbols defined in script should not be inlined by LTO. At the same time
207227
// we don't know their final values until late stages of link. Here we scan
208228
// over symbol assignment commands and create placeholder symbols if needed.

‎lld/ELF/LinkerScript.h

+7
Original file line numberDiff line numberDiff line change
@@ -267,6 +267,9 @@ class LinkerScript final {
267267
void processSectionCommands();
268268
void declareSymbols();
269269

270+
// Used to handle INSERT AFTER statements.
271+
void processInsertCommands();
272+
270273
// SECTIONS command list.
271274
std::vector<BaseCommand *> SectionCommands;
272275

@@ -285,6 +288,10 @@ class LinkerScript final {
285288

286289
// A list of symbols referenced by the script.
287290
std::vector<llvm::StringRef> ReferencedSymbols;
291+
292+
// Used to implement INSERT AFTER. Contains commands that need
293+
// to be inserted into SECTIONS commands list.
294+
llvm::DenseMap<StringRef, std::vector<BaseCommand *>> InsertAfterCommands;
288295
};
289296

290297
extern LinkerScript *Script;

‎lld/ELF/ScriptParser.cpp

+12-1
Original file line numberDiff line numberDiff line change
@@ -436,6 +436,7 @@ void ScriptParser::readSections() {
436436
Config->SingleRoRx = true;
437437

438438
expect("{");
439+
std::vector<BaseCommand *> V;
439440
while (!errorCount() && !consume("}")) {
440441
StringRef Tok = next();
441442
BaseCommand *Cmd = readProvideOrAssignment(Tok);
@@ -445,8 +446,18 @@ void ScriptParser::readSections() {
445446
else
446447
Cmd = readOutputSectionDescription(Tok);
447448
}
448-
Script->SectionCommands.push_back(Cmd);
449+
V.push_back(Cmd);
449450
}
451+
452+
if (!atEOF() && consume("INSERT")) {
453+
consume("AFTER");
454+
std::vector<BaseCommand *> &Dest = Script->InsertAfterCommands[next()];
455+
Dest.insert(Dest.end(), V.begin(), V.end());
456+
return;
457+
}
458+
459+
Script->SectionCommands.insert(Script->SectionCommands.end(), V.begin(),
460+
V.end());
450461
}
451462

452463
static int precedence(StringRef Op) {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
.section .foo.text,"ax"
2+
.quad 0
3+
4+
.section .foo.data,"aw"
5+
.quad 0
6+
7+
.section .text.1,"ax"
8+
.quad 0
9+
10+
.section .data.1,"aw"
11+
.quad 0
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
SECTIONS {
2+
.text : { *(.text.*) }
3+
.data : { *(.data.*) }
4+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
# REQUIRES: x86
2+
# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %p/Inputs/insert-after.s -o %t1.o
3+
4+
## Main linker script contains .text and .data sections. Here
5+
## we check that can use INSERT AFTER to insert sections .foo.data
6+
## and .foo.text at the right places.
7+
8+
SECTIONS {
9+
.foo.data : { *(.foo.data) }
10+
} INSERT AFTER .data;
11+
12+
SECTIONS {
13+
.foo.text : { *(.foo.text) }
14+
} INSERT AFTER .text;
15+
16+
# RUN: ld.lld %t1.o -o %t1 --script %p/Inputs/insert-after.script --script %s
17+
# RUN: llvm-objdump -section-headers %t1 | FileCheck %s
18+
# CHECK: Sections:
19+
# CHECK-NEXT: Idx Name Size Address Type
20+
# CHECK-NEXT: 0 00000000 0000000000000000
21+
# CHECK-NEXT: 1 .text 00000008 0000000000000000 TEXT DATA
22+
# CHECK-NEXT: 2 .foo.text 00000008 0000000000000008 TEXT DATA
23+
# CHECK-NEXT: 3 .data 00000008 0000000000000010 DATA
24+
# CHECK-NEXT: 4 .foo.data 00000008 0000000000000018 DATA
25+
26+
# RUN: not ld.lld %t1.o -o %t1 --script %s 2>&1 \
27+
# RUN: | FileCheck %s --check-prefix=ERR
28+
# ERR-DAG: error: unable to INSERT AFTER .text: section not defined
29+
# ERR-DAG: error: unable to INSERT AFTER .data: section not defined

0 commit comments

Comments
 (0)
Please sign in to comment.