summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lld/ELF/LinkerScript.cpp24
-rw-r--r--lld/ELF/LinkerScript.h10
-rw-r--r--lld/test/ELF/linkerscript/absolute-expr.s24
3 files changed, 50 insertions, 8 deletions
diff --git a/lld/ELF/LinkerScript.cpp b/lld/ELF/LinkerScript.cpp
index ae52ed9d27f..9061dacf259 100644
--- a/lld/ELF/LinkerScript.cpp
+++ b/lld/ELF/LinkerScript.cpp
@@ -64,7 +64,7 @@ template <class ELFT> static void addSynthetic(SymbolAssignment *Cmd) {
}
template <class ELFT> static void addSymbol(SymbolAssignment *Cmd) {
- if (Cmd->Expression.IsAbsolute)
+ if (Cmd->Expression.IsAbsolute())
addRegular<ELFT>(Cmd);
else
addSynthetic<ELFT>(Cmd);
@@ -867,6 +867,12 @@ template <class ELFT> bool LinkerScript<ELFT>::isDefined(StringRef S) {
return Symtab<ELFT>::X->find(S) != nullptr;
}
+template <class ELFT> bool LinkerScript<ELFT>::isAbsolute(StringRef S) {
+ SymbolBody *Sym = Symtab<ELFT>::X->find(S);
+ auto *DR = dyn_cast_or_null<DefinedRegular<ELFT>>(Sym);
+ return DR && !DR->Section;
+}
+
// Returns indices of ELF headers containing specific section, identified
// by Name. Each index is a zero based number of ELF header listed within
// PHDRS {} script block.
@@ -1424,7 +1430,7 @@ SymbolAssignment *ScriptParser::readProvideOrAssignment(StringRef Tok,
Cmd = readProvideHidden(true, true);
}
if (Cmd && MakeAbsolute)
- Cmd->Expression.IsAbsolute = true;
+ Cmd->Expression.IsAbsolute = []() { return true; };
return Cmd;
}
@@ -1434,6 +1440,12 @@ static uint64_t getSymbolValue(StringRef S, uint64_t Dot) {
return ScriptBase->getSymbolValue(S);
}
+static bool isAbsolute(StringRef S) {
+ if (S == ".")
+ return false;
+ return ScriptBase->isAbsolute(S);
+}
+
SymbolAssignment *ScriptParser::readAssignment(StringRef Name) {
StringRef Op = next();
Expr E;
@@ -1442,7 +1454,7 @@ SymbolAssignment *ScriptParser::readAssignment(StringRef Name) {
// The RHS may be something like "ABSOLUTE(.) & 0xff".
// Call readExpr1 to read the whole expression.
E = readExpr1(readParenExpr(), 0);
- E.IsAbsolute = true;
+ E.IsAbsolute = []() { return true; };
} else {
E = readExpr();
}
@@ -1469,7 +1481,8 @@ static Expr combine(StringRef Op, Expr L, Expr R) {
};
}
if (Op == "+")
- return [=](uint64_t Dot) { return L(Dot) + R(Dot); };
+ return {[=](uint64_t Dot) { return L(Dot) + R(Dot); },
+ [=]() { return L.IsAbsolute() && R.IsAbsolute(); }};
if (Op == "-")
return [=](uint64_t Dot) { return L(Dot) - R(Dot); };
if (Op == "<<")
@@ -1687,7 +1700,8 @@ Expr ScriptParser::readPrimary() {
// Tok is a symbol name.
if (Tok != "." && !isValidCIdentifier(Tok))
setError("malformed number: " + Tok);
- return [=](uint64_t Dot) { return getSymbolValue(Tok, Dot); };
+ return {[=](uint64_t Dot) { return getSymbolValue(Tok, Dot); },
+ [=]() { return isAbsolute(Tok); }};
}
Expr ScriptParser::readTernary(Expr Cond) {
diff --git a/lld/ELF/LinkerScript.h b/lld/ELF/LinkerScript.h
index 7542191643e..57536203a71 100644
--- a/lld/ELF/LinkerScript.h
+++ b/lld/ELF/LinkerScript.h
@@ -39,12 +39,16 @@ class InputSectionData;
// with the value of special context variable ".".
struct Expr {
std::function<uint64_t(uint64_t)> Val;
- bool IsAbsolute;
+ std::function<bool()> IsAbsolute;
uint64_t operator()(uint64_t Dot) const { return Val(Dot); }
operator bool() const { return (bool)Val; }
template <typename T>
- Expr(T Val, bool IsAbsolute) : Val(Val), IsAbsolute(IsAbsolute) {}
+ Expr(T Val, std::function<bool()> IsAbsolute)
+ : Val(Val), IsAbsolute(IsAbsolute) {}
+ template <typename T> Expr(T Val, bool IsAbsolute) : Val(Val) {
+ this->IsAbsolute = [=]() { return IsAbsolute; };
+ }
template <typename T> Expr(T V) : Expr(V, false) {}
Expr() : Expr(nullptr) {}
};
@@ -184,6 +188,7 @@ public:
virtual uint64_t getHeaderSize() = 0;
virtual uint64_t getSymbolValue(StringRef S) = 0;
virtual bool isDefined(StringRef S) = 0;
+ virtual bool isAbsolute(StringRef S) = 0;
};
// ScriptConfiguration holds linker script parse results.
@@ -231,6 +236,7 @@ public:
uint64_t getHeaderSize() override;
uint64_t getSymbolValue(StringRef S) override;
bool isDefined(StringRef S) override;
+ bool isAbsolute(StringRef S) override;
std::vector<OutputSectionBase<ELFT> *> *OutputSections;
diff --git a/lld/test/ELF/linkerscript/absolute-expr.s b/lld/test/ELF/linkerscript/absolute-expr.s
index 0d3ec7f22c9..53737834d8f 100644
--- a/lld/test/ELF/linkerscript/absolute-expr.s
+++ b/lld/test/ELF/linkerscript/absolute-expr.s
@@ -7,14 +7,27 @@
# RUN: bar3 = SIZEOF (.text); \
# RUN: bar4 = SIZEOF_HEADERS; \
# RUN: bar5 = 0x42; \
+# RUN: bar6 = foo + 1; \
# RUN: *(.text) \
# RUN: } \
# RUN: };" > %t.script
# RUN: ld.lld -o %t.so --script %t.script %t.o -shared
# RUN: llvm-readobj -t %t.so | FileCheck %s
+.global foo
+foo = 0x123
+
# CHECK: Symbol {
-# CHECK: Name: bar1
+# CHECK: Name: foo
+# CHECK-NEXT: Value: 0x123
+# CHECK-NEXT: Size: 0
+# CHECK-NEXT: Binding: Global
+# CHECK-NEXT: Type: None
+# CHECK-NEXT: Other: 0
+# CHECK-NEXT: Section: Absolute (0xFFF1)
+# CHECK-NEXT: }
+# CHECK-NEXT: Symbol {
+# CHECK-NEXT: Name: bar1
# CHECK-NEXT: Value: 0x4
# CHECK-NEXT: Size: 0
# CHECK-NEXT: Binding: Global
@@ -58,3 +71,12 @@
# CHECK-NEXT: Other: 0
# CHECK-NEXT: Section: Absolute
# CHECK-NEXT: }
+# CHECK-NEXT: Symbol {
+# CHECK-NEXT: Name: bar6 (30)
+# CHECK-NEXT: Value: 0x124
+# CHECK-NEXT: Size: 0
+# CHECK-NEXT: Binding: Global (0x1)
+# CHECK-NEXT: Type: None (0x0)
+# CHECK-NEXT: Other: 0
+# CHECK-NEXT: Section: Absolute (0xFFF1)
+# CHECK-NEXT: }
OpenPOWER on IntegriCloud