From 2f831dcafd98f068e0af3029545e0465db14c989 Mon Sep 17 00:00:00 2001 From: Rafael Espindola Date: Mon, 31 Oct 2016 19:56:37 +0000 Subject: [PATCH] Delay computation of IsAbsolute. We parse linker scripts very early, but whether an expression is absolute or not can depend on a symbol defined in a .o. Given that, we have to delay the computation of IsAbsolute. We can do that by storing an AST when parsing or by also making IsAbsolute a function like we do for the expression value. This patch implements the second option. llvm-svn: 285628 --- lld/ELF/LinkerScript.cpp | 24 +++++++++++++++++++----- lld/ELF/LinkerScript.h | 10 ++++++++-- lld/test/ELF/linkerscript/absolute-expr.s | 24 +++++++++++++++++++++++- 3 files changed, 50 insertions(+), 8 deletions(-) diff --git a/lld/ELF/LinkerScript.cpp b/lld/ELF/LinkerScript.cpp index ae52ed9..9061dac 100644 --- a/lld/ELF/LinkerScript.cpp +++ b/lld/ELF/LinkerScript.cpp @@ -64,7 +64,7 @@ template static void addSynthetic(SymbolAssignment *Cmd) { } template static void addSymbol(SymbolAssignment *Cmd) { - if (Cmd->Expression.IsAbsolute) + if (Cmd->Expression.IsAbsolute()) addRegular(Cmd); else addSynthetic(Cmd); @@ -867,6 +867,12 @@ template bool LinkerScript::isDefined(StringRef S) { return Symtab::X->find(S) != nullptr; } +template bool LinkerScript::isAbsolute(StringRef S) { + SymbolBody *Sym = Symtab::X->find(S); + auto *DR = dyn_cast_or_null>(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 7542191..5753620 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 Val; - bool IsAbsolute; + std::function IsAbsolute; uint64_t operator()(uint64_t Dot) const { return Val(Dot); } operator bool() const { return (bool)Val; } template - Expr(T Val, bool IsAbsolute) : Val(Val), IsAbsolute(IsAbsolute) {} + Expr(T Val, std::function IsAbsolute) + : Val(Val), IsAbsolute(IsAbsolute) {} + template Expr(T Val, bool IsAbsolute) : Val(Val) { + this->IsAbsolute = [=]() { return IsAbsolute; }; + } template 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 *> *OutputSections; diff --git a/lld/test/ELF/linkerscript/absolute-expr.s b/lld/test/ELF/linkerscript/absolute-expr.s index 0d3ec7f..5373783 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: } -- 2.7.4