[ELF] - Linkerscript: implemented += operator.
Sometimes += is used to move the location counter.
Example from the wild is:
.dbg_excpt _DBG_EXCPT_ADDR (NOLOAD) :
{
. += (DEFINED (_DEBUGGER) ? 0x8 : 0x0);
https://github.com/chipKIT32/pic32-Arduino-USB-Bootloader-original/blob/master/boot-linkerscript.ld
Patch implements it and opens way for others type of assignments (-= *= etc), though I think only += is
actual to support.
Differential revision: https://reviews.llvm.org/D22916
llvm-svn: 277035
diff --git a/lld/ELF/LinkerScript.cpp b/lld/ELF/LinkerScript.cpp
index 8642153..339c06d 100644
--- a/lld/ELF/LinkerScript.cpp
+++ b/lld/ELF/LinkerScript.cpp
@@ -643,7 +643,7 @@
expect("{");
while (!Error && !skip("}")) {
StringRef Tok = next();
- if (peek() == "=") {
+ if (peek() == "=" || peek() == "+=") {
readAssignment(Tok);
expect(";");
} else if (Tok == "PROVIDE") {
@@ -777,19 +777,10 @@
expect(";");
}
-SymbolAssignment *ScriptParser::readAssignment(StringRef Name) {
- expect("=");
- Expr E = readExpr();
- auto *Cmd = new SymbolAssignment(Name, E);
- Opt.Commands.emplace_back(Cmd);
- return Cmd;
-}
+static uint64_t getSymbolValue(StringRef S, uint64_t Dot) {
+ if (S == ".")
+ return Dot;
-// This is an operator-precedence parser to parse a linker
-// script expression.
-Expr ScriptParser::readExpr() { return readExpr1(readPrimary(), 0); }
-
-static uint64_t getSymbolValue(StringRef S) {
switch (Config->EKind) {
case ELF32LEKind:
if (SymbolBody *B = Symtab<ELF32LE>::X->find(S))
@@ -814,6 +805,21 @@
return 0;
}
+SymbolAssignment *ScriptParser::readAssignment(StringRef Name) {
+ StringRef Op = next();
+ assert(Op == "=" || Op == "+=");
+ Expr E = readExpr();
+ if (Op == "+=")
+ E = [=](uint64_t Dot) { return getSymbolValue(Name, Dot) + E(Dot); };
+ auto *Cmd = new SymbolAssignment(Name, E);
+ Opt.Commands.emplace_back(Cmd);
+ return Cmd;
+}
+
+// This is an operator-precedence parser to parse a linker
+// script expression.
+Expr ScriptParser::readExpr() { return readExpr1(readPrimary(), 0); }
+
// This is a part of the operator-precedence parser. This function
// assumes that the remaining token stream starts with an operator.
Expr ScriptParser::readExpr1(Expr Lhs, int MinPrec) {
@@ -853,9 +859,6 @@
Expr ScriptParser::readPrimary() {
StringRef Tok = next();
- if (Tok == ".")
- return [](uint64_t Dot) { return Dot; };
-
if (Tok == "(") {
Expr E = readExpr();
expect(")");
@@ -914,9 +917,9 @@
// Parse a symbol name or a number literal.
uint64_t V = 0;
if (Tok.getAsInteger(0, V)) {
- if (!isValidCIdentifier(Tok))
+ if (Tok != "." && !isValidCIdentifier(Tok))
setError("malformed number: " + Tok);
- return [=](uint64_t Dot) { return getSymbolValue(Tok); };
+ return [=](uint64_t Dot) { return getSymbolValue(Tok, Dot); };
}
return [=](uint64_t Dot) { return V; };
}