Index: ELF/Driver.cpp =================================================================== --- ELF/Driver.cpp +++ ELF/Driver.cpp @@ -511,6 +511,7 @@ Target = TI.get(); LinkerScript LS; Script::X = &LS; + ScriptConfig->ExprBridge = &LS; Config->Rela = ELFT::Is64Bits || Config->EMachine == EM_X86_64; Config->Mips64EL = Index: ELF/LinkerScript.h =================================================================== --- ELF/LinkerScript.h +++ ELF/LinkerScript.h @@ -93,6 +93,11 @@ unsigned Flags; }; +class ExpressionsBridge { +public: + virtual uint64_t getSymbolValue(StringRef Sym) = 0; +}; + // ScriptConfiguration holds linker script parse results. struct ScriptConfiguration { // Used to assign addresses to sections. @@ -108,12 +113,14 @@ // List of section patterns specified with KEEP commands. They will // be kept even if they are unused and --gc-sections is specified. std::vector KeptSections; + + ExpressionsBridge *ExprBridge = nullptr; }; extern ScriptConfiguration *ScriptConfig; // This is a runner of the linker script. -template class LinkerScript { +template class LinkerScript : public ExpressionsBridge { typedef typename ELFT::uint uintX_t; public: @@ -130,6 +137,8 @@ void addScriptedSymbols(); bool hasPhdrsCommands(); + uint64_t getSymbolValue(StringRef Sym) override; + private: // "ScriptConfig" is a bit too long, so define a short name for it. ScriptConfiguration &Opt = *ScriptConfig; Index: ELF/LinkerScript.cpp =================================================================== --- ELF/LinkerScript.cpp +++ ELF/LinkerScript.cpp @@ -369,6 +369,14 @@ return !Opt.PhdrsCommands.empty(); } +template +uint64_t LinkerScript::getSymbolValue(StringRef Sym) { + if (SymbolBody *B = Symtab::X->find(Sym)) + return B->getVA(); + error("malformed number: " + Sym); + return 0; +} + // 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. @@ -765,6 +773,10 @@ return 0; } +uint64_t static getSymbolValue(StringRef S) { + return ScriptConfig->ExprBridge->getSymbolValue(S); +} + Expr ScriptParser::readPrimary() { StringRef Tok = next(); @@ -811,8 +823,11 @@ // Parse a number literal uint64_t V = 0; - if (Tok.getAsInteger(0, V)) - setError("malformed number: " + Tok); + if (Tok.getAsInteger(0, V)) { + if (!isValidCIdentifier(Tok)) + setError("malformed number: " + Tok); + return [=](uint64_t Dot) { return getSymbolValue(Tok); }; + } return [=](uint64_t Dot) { return V; }; } Index: test/ELF/linkerscript/linkerscript-symbol-assignexpr.s =================================================================== --- test/ELF/linkerscript/linkerscript-symbol-assignexpr.s +++ test/ELF/linkerscript/linkerscript-symbol-assignexpr.s @@ -0,0 +1,25 @@ +# REQUIRES: x86 +# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t + +# RUN: echo "SECTIONS { \ +# RUN: symbol = CONSTANT(MAXPAGESIZE); \ +# RUN: symbol2 = symbol + 0x1234; \ +# RUN: symbol3 = symbol2; \ +# RUN: }" > %t.script +# RUN: ld.lld -o %t1 --script %t.script %t +# RUN: llvm-objdump -t %t1 | FileCheck %s + +# CHECK: SYMBOL TABLE: +# CHECK-NEXT: 0000000000000000 *UND* 00000000 +# CHECK-NEXT: 0000000000000120 .text 00000000 _start +# CHECK-NEXT: 0000000000000121 .text 00000000 foo +# CHECK-NEXT: 0000000000001000 *ABS* 00000000 symbol +# CHECK-NEXT: 0000000000002234 *ABS* 00000000 symbol2 +# CHECK-NEXT: 0000000000002234 *ABS* 00000000 symbol3 + +.global _start +_start: + nop + +.global foo +foo: