[ELF] - Implement INSERT BEFORE.

This finishes PR35877.

INSERT BEFORE used similar to INSERT AFTER,
it inserts sections before the given target section.

Differential revision: https://reviews.llvm.org/D44380

llvm-svn: 327378
This commit is contained in:
George Rimar 2018-03-13 09:18:11 +00:00
parent ebc1d1fdde
commit 796684b451
6 changed files with 60 additions and 16 deletions

View File

@ -207,18 +207,26 @@ static void declareSymbol(SymbolAssignment *Cmd) {
// the list of script commands to mix sections inserted into. // the list of script commands to mix sections inserted into.
void LinkerScript::processInsertCommands() { void LinkerScript::processInsertCommands() {
std::vector<BaseCommand *> V; std::vector<BaseCommand *> V;
auto Insert = [&](std::vector<BaseCommand *> &From) {
V.insert(V.end(), From.begin(), From.end());
From.clear();
};
for (BaseCommand *Base : SectionCommands) { for (BaseCommand *Base : SectionCommands) {
V.push_back(Base); if (auto *OS = dyn_cast<OutputSection>(Base)) {
if (auto *Cmd = dyn_cast<OutputSection>(Base)) { Insert(InsertBeforeCommands[OS->Name]);
std::vector<BaseCommand *> &W = InsertAfterCommands[Cmd->Name]; V.push_back(Base);
V.insert(V.end(), W.begin(), W.end()); Insert(InsertAfterCommands[OS->Name]);
W.clear(); continue;
} }
V.push_back(Base);
} }
for (std::pair<StringRef, std::vector<BaseCommand *>> &P :
InsertAfterCommands) for (auto &Cmds : {InsertBeforeCommands, InsertAfterCommands})
if (!P.second.empty()) for (const std::pair<StringRef, std::vector<BaseCommand *>> &P : Cmds)
error("unable to INSERT AFTER " + P.first + ": section not defined"); if (!P.second.empty())
error("unable to INSERT AFTER/BEFORE " + P.first +
": section not defined");
SectionCommands = std::move(V); SectionCommands = std::move(V);
} }

View File

@ -289,9 +289,10 @@ public:
// A list of symbols referenced by the script. // A list of symbols referenced by the script.
std::vector<llvm::StringRef> ReferencedSymbols; 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. // to be inserted into SECTIONS commands list.
llvm::DenseMap<StringRef, std::vector<BaseCommand *>> InsertAfterCommands; llvm::DenseMap<StringRef, std::vector<BaseCommand *>> InsertAfterCommands;
llvm::DenseMap<StringRef, std::vector<BaseCommand *>> InsertBeforeCommands;
}; };
extern LinkerScript *Script; extern LinkerScript *Script;

View File

@ -450,9 +450,15 @@ void ScriptParser::readSections() {
} }
if (!atEOF() && consume("INSERT")) { if (!atEOF() && consume("INSERT")) {
expect("AFTER"); std::vector<BaseCommand *> *Dest = nullptr;
std::vector<BaseCommand *> &Dest = Script->InsertAfterCommands[next()]; if (consume("AFTER"))
Dest.insert(Dest.end(), V.begin(), V.end()); 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; return;
} }

View File

@ -25,5 +25,5 @@ SECTIONS {
# RUN: not ld.lld %t1.o -o %t1 --script %s 2>&1 \ # RUN: not ld.lld %t1.o -o %t1 --script %s 2>&1 \
# RUN: | FileCheck %s --check-prefix=ERR # RUN: | FileCheck %s --check-prefix=ERR
# ERR-DAG: error: unable to INSERT AFTER .text: section not defined # ERR-DAG: error: unable to INSERT AFTER/BEFORE .text: section not defined
# ERR-DAG: error: unable to INSERT AFTER .data: section not defined # ERR-DAG: error: unable to INSERT AFTER/BEFORE .data: section not defined

View File

@ -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

View File

@ -3,4 +3,4 @@ SECTIONS {
} INSERT .data; } INSERT .data;
# RUN: not ld.lld -o %t1 --script %s 2>&1 | FileCheck %s # 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'