summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPetr Hosek <phosek@chromium.org>2017-03-15 03:33:23 +0000
committerPetr Hosek <phosek@chromium.org>2017-03-15 03:33:23 +0000
commit02ad516b2e0040bd54a4f668b98b1c54dc8e31f2 (patch)
tree119d6b4f6aad11dfe5a4ffc1ab65624fba1def41
parentc6ee33852b177914a0f517f64401d21f50013c0f (diff)
downloadbcm5719-llvm-02ad516b2e0040bd54a4f668b98b1c54dc8e31f2.tar.gz
bcm5719-llvm-02ad516b2e0040bd54a4f668b98b1c54dc8e31f2.zip
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
-rw-r--r--lld/ELF/LinkerScript.cpp36
-rw-r--r--lld/ELF/LinkerScript.h1
-rw-r--r--lld/ELF/Writer.cpp1
-rw-r--r--lld/test/ELF/linkerscript/absolute.s17
4 files changed, 34 insertions, 21 deletions
diff --git a/lld/ELF/LinkerScript.cpp b/lld/ELF/LinkerScript.cpp
index 647725ebf67..5f2c9a16906 100644
--- a/lld/ELF/LinkerScript.cpp
+++ b/lld/ELF/LinkerScript.cpp
@@ -153,11 +153,6 @@ void LinkerScript<ELFT>::addSymbol(SymbolAssignment *Cmd) {
return;
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) {
@@ -344,15 +339,6 @@ void LinkerScript<ELFT>::processCommands(OutputSectionFactory &Factory) {
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())) {
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) {
// Assign addresses as instructed by linker script SECTIONS sub-commands.
Dot = 0;
@@ -1556,14 +1551,8 @@ SymbolAssignment *ScriptParser::readProvideOrAssignment(StringRef Tok) {
SymbolAssignment *ScriptParser::readAssignment(StringRef Name) {
StringRef Op = next();
- Expr E;
assert(Op == "=" || Op == "+=");
- if (consume("ABSOLUTE")) {
- E = readExpr();
- E.IsAbsolute = [] { return true; };
- } else {
- E = readExpr();
- }
+ Expr E = readExpr();
if (Op == "+=") {
std::string Loc = getCurrentLocation();
E = [=] { return ScriptBase->getSymbolValue(Loc, Name) + E(); };
@@ -1739,6 +1728,11 @@ Expr ScriptParser::readPrimary() {
// Built-in functions are parsed here.
// https://sourceware.org/binutils/docs/ld/Builtin-Functions.html.
+ if (Tok == "ABSOLUTE") {
+ Expr E = readParenExpr();
+ E.IsAbsolute = [] { return true; };
+ return E;
+ }
if (Tok == "ADDR") {
StringRef Name = readParenLiteral();
return {[=] { return ScriptBase->getOutputSection(Location, Name)->Addr; },
diff --git a/lld/ELF/LinkerScript.h b/lld/ELF/LinkerScript.h
index 3180f9913f1..27a157033ea 100644
--- a/lld/ELF/LinkerScript.h
+++ b/lld/ELF/LinkerScript.h
@@ -287,6 +287,7 @@ public:
bool shouldKeep(InputSectionBase *S);
void assignOffsets(OutputSectionCommand *Cmd);
void placeOrphanSections();
+ void processNonSectionCommands();
void assignAddresses(std::vector<PhdrEntry> &Phdrs);
int getSectionIndex(StringRef Name);
};
diff --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp
index c4795f02820..e66ba91dd2f 100644
--- a/lld/ELF/Writer.cpp
+++ b/lld/ELF/Writer.cpp
@@ -270,6 +270,7 @@ template <class ELFT> void Writer<ELFT>::run() {
} else {
fixSectionAlignments();
assignAddresses();
+ Script<ELFT>::X->processNonSectionCommands();
}
// Remove empty PT_LOAD to avoid causing the dynamic linker to try to mmap a
diff --git a/lld/test/ELF/linkerscript/absolute.s b/lld/test/ELF/linkerscript/absolute.s
index e4b156e2f01..54f1c7037d2 100644
--- a/lld/test/ELF/linkerscript/absolute.s
+++ b/lld/test/ELF/linkerscript/absolute.s
@@ -4,6 +4,11 @@
# RUN: ld.lld -o %t --script %t.script %t.o
# 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-NEXT: Value:
# CHECK-NEXT: Size:
@@ -13,6 +18,18 @@
# CHECK-NEXT: Section: Absolute
# 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
.globl _start
_start:
+ nop
+
+.global foo
OpenPOWER on IntegriCloud