forked from OSchip/llvm-project
Support ABSOLUTE on the right hand side in linker scripts
This also requires postponing the assignment the assignment of symbols defined in input linker scripts since those can refer to output sections and in case we don't have a SECTIONS command, we need to wait until all output sections have been created and assigned addresses. Differential Revision: https://reviews.llvm.org/D30851 llvm-svn: 297802
This commit is contained in:
parent
c6ee33852b
commit
02ad516b2e
lld
|
@ -153,11 +153,6 @@ void LinkerScript<ELFT>::addSymbol(SymbolAssignment *Cmd) {
|
||||||
return;
|
return;
|
||||||
|
|
||||||
Cmd->Sym = addRegular<ELFT>(Cmd);
|
Cmd->Sym = addRegular<ELFT>(Cmd);
|
||||||
|
|
||||||
// If there are sections, then let the value be assigned later in
|
|
||||||
// `assignAddresses`.
|
|
||||||
if (!ScriptConfig->HasSections)
|
|
||||||
assignSymbol(Cmd);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SymbolAssignment::classof(const BaseCommand *C) {
|
bool SymbolAssignment::classof(const BaseCommand *C) {
|
||||||
|
@ -344,15 +339,6 @@ void LinkerScript<ELFT>::processCommands(OutputSectionFactory &Factory) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (auto *Cmd = dyn_cast<AssertCommand>(Base1.get())) {
|
|
||||||
// If we don't have SECTIONS then output sections have already been
|
|
||||||
// created by Writer<ELFT>. The LinkerScript<ELFT>::assignAddresses
|
|
||||||
// will not be called, so ASSERT should be evaluated now.
|
|
||||||
if (!Opt.HasSections)
|
|
||||||
Cmd->Expression();
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (auto *Cmd = dyn_cast<OutputSectionCommand>(Base1.get())) {
|
if (auto *Cmd = dyn_cast<OutputSectionCommand>(Base1.get())) {
|
||||||
std::vector<InputSectionBase *> V = createInputSectionList(*Cmd);
|
std::vector<InputSectionBase *> V = createInputSectionList(*Cmd);
|
||||||
|
|
||||||
|
@ -779,6 +765,15 @@ void LinkerScriptBase::placeOrphanSections() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void LinkerScriptBase::processNonSectionCommands() {
|
||||||
|
for (const std::unique_ptr<BaseCommand> &Base : Opt.Commands) {
|
||||||
|
if (auto *Cmd = dyn_cast<SymbolAssignment>(Base.get()))
|
||||||
|
assignSymbol(Cmd);
|
||||||
|
else if (auto *Cmd = dyn_cast<AssertCommand>(Base.get()))
|
||||||
|
Cmd->Expression();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void LinkerScriptBase::assignAddresses(std::vector<PhdrEntry> &Phdrs) {
|
void LinkerScriptBase::assignAddresses(std::vector<PhdrEntry> &Phdrs) {
|
||||||
// Assign addresses as instructed by linker script SECTIONS sub-commands.
|
// Assign addresses as instructed by linker script SECTIONS sub-commands.
|
||||||
Dot = 0;
|
Dot = 0;
|
||||||
|
@ -1556,14 +1551,8 @@ SymbolAssignment *ScriptParser::readProvideOrAssignment(StringRef Tok) {
|
||||||
|
|
||||||
SymbolAssignment *ScriptParser::readAssignment(StringRef Name) {
|
SymbolAssignment *ScriptParser::readAssignment(StringRef Name) {
|
||||||
StringRef Op = next();
|
StringRef Op = next();
|
||||||
Expr E;
|
|
||||||
assert(Op == "=" || Op == "+=");
|
assert(Op == "=" || Op == "+=");
|
||||||
if (consume("ABSOLUTE")) {
|
Expr E = readExpr();
|
||||||
E = readExpr();
|
|
||||||
E.IsAbsolute = [] { return true; };
|
|
||||||
} else {
|
|
||||||
E = readExpr();
|
|
||||||
}
|
|
||||||
if (Op == "+=") {
|
if (Op == "+=") {
|
||||||
std::string Loc = getCurrentLocation();
|
std::string Loc = getCurrentLocation();
|
||||||
E = [=] { return ScriptBase->getSymbolValue(Loc, Name) + E(); };
|
E = [=] { return ScriptBase->getSymbolValue(Loc, Name) + E(); };
|
||||||
|
@ -1739,6 +1728,11 @@ Expr ScriptParser::readPrimary() {
|
||||||
|
|
||||||
// Built-in functions are parsed here.
|
// Built-in functions are parsed here.
|
||||||
// https://sourceware.org/binutils/docs/ld/Builtin-Functions.html.
|
// https://sourceware.org/binutils/docs/ld/Builtin-Functions.html.
|
||||||
|
if (Tok == "ABSOLUTE") {
|
||||||
|
Expr E = readParenExpr();
|
||||||
|
E.IsAbsolute = [] { return true; };
|
||||||
|
return E;
|
||||||
|
}
|
||||||
if (Tok == "ADDR") {
|
if (Tok == "ADDR") {
|
||||||
StringRef Name = readParenLiteral();
|
StringRef Name = readParenLiteral();
|
||||||
return {[=] { return ScriptBase->getOutputSection(Location, Name)->Addr; },
|
return {[=] { return ScriptBase->getOutputSection(Location, Name)->Addr; },
|
||||||
|
|
|
@ -287,6 +287,7 @@ public:
|
||||||
bool shouldKeep(InputSectionBase *S);
|
bool shouldKeep(InputSectionBase *S);
|
||||||
void assignOffsets(OutputSectionCommand *Cmd);
|
void assignOffsets(OutputSectionCommand *Cmd);
|
||||||
void placeOrphanSections();
|
void placeOrphanSections();
|
||||||
|
void processNonSectionCommands();
|
||||||
void assignAddresses(std::vector<PhdrEntry> &Phdrs);
|
void assignAddresses(std::vector<PhdrEntry> &Phdrs);
|
||||||
int getSectionIndex(StringRef Name);
|
int getSectionIndex(StringRef Name);
|
||||||
};
|
};
|
||||||
|
|
|
@ -270,6 +270,7 @@ template <class ELFT> void Writer<ELFT>::run() {
|
||||||
} else {
|
} else {
|
||||||
fixSectionAlignments();
|
fixSectionAlignments();
|
||||||
assignAddresses();
|
assignAddresses();
|
||||||
|
Script<ELFT>::X->processNonSectionCommands();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remove empty PT_LOAD to avoid causing the dynamic linker to try to mmap a
|
// Remove empty PT_LOAD to avoid causing the dynamic linker to try to mmap a
|
||||||
|
|
|
@ -4,6 +4,11 @@
|
||||||
# RUN: ld.lld -o %t --script %t.script %t.o
|
# RUN: ld.lld -o %t --script %t.script %t.o
|
||||||
# RUN: llvm-readobj --symbols %t | FileCheck %s
|
# RUN: llvm-readobj --symbols %t | FileCheck %s
|
||||||
|
|
||||||
|
# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o
|
||||||
|
# RUN: echo "PROVIDE(foo = 1 + ABSOLUTE(ADDR(.text)));" > %t.script
|
||||||
|
# RUN: ld.lld -o %t --script %t.script %t.o
|
||||||
|
# RUN: llvm-readobj --symbols %t | FileCheck --check-prefix=CHECK-RHS %s
|
||||||
|
|
||||||
# CHECK: Name: foo
|
# CHECK: Name: foo
|
||||||
# CHECK-NEXT: Value:
|
# CHECK-NEXT: Value:
|
||||||
# CHECK-NEXT: Size:
|
# CHECK-NEXT: Size:
|
||||||
|
@ -13,6 +18,18 @@
|
||||||
# CHECK-NEXT: Section: Absolute
|
# CHECK-NEXT: Section: Absolute
|
||||||
# CHECK-NEXT: }
|
# CHECK-NEXT: }
|
||||||
|
|
||||||
|
# CHECK-RHS: Name: foo
|
||||||
|
# CHECK-RHS-NEXT: Value: 0x201001
|
||||||
|
# CHECK-RHS-NEXT: Size:
|
||||||
|
# CHECK-RHS-NEXT: Binding:
|
||||||
|
# CHECK-RHS-NEXT: Type:
|
||||||
|
# CHECK-RHS-NEXT: Other:
|
||||||
|
# CHECK-RHS-NEXT: Section: Absolute
|
||||||
|
# CHECK-RHS-NEXT: }
|
||||||
|
|
||||||
.text
|
.text
|
||||||
.globl _start
|
.globl _start
|
||||||
_start:
|
_start:
|
||||||
|
nop
|
||||||
|
|
||||||
|
.global foo
|
||||||
|
|
Loading…
Reference in New Issue