Index: ELF/LinkerScript.h =================================================================== --- ELF/LinkerScript.h +++ ELF/LinkerScript.h @@ -29,6 +29,7 @@ namespace elf { class DefinedCommon; +class DefinedRegular; class SymbolBody; class InputSectionBase; class InputSection; @@ -41,6 +42,7 @@ SectionBase *Sec; uint64_t Val; bool ForceAbsolute; + bool CanCalculateAbs = true; ExprValue(SectionBase *Sec, bool ForceAbsolute, uint64_t Val) : Sec(Sec), Val(Val), ForceAbsolute(ForceAbsolute) {} @@ -227,6 +229,8 @@ MemoryRegion *findMemoryRegion(OutputSectionCommand *Cmd); + bool canCalcSymValue(DefinedRegular *D); + void switchTo(OutputSection *Sec); void output(InputSection *Sec); void process(BaseCommand &Base); @@ -241,6 +245,9 @@ OutputSection *CurOutSec = nullptr; MemoryRegion *CurMemRegion = nullptr; + // Stores output sections which has VA assigned. + llvm::DenseSet OutputsProccessed; + public: bool hasPhdrsCommands() { return !Opt.PhdrsCommands.empty(); } uint64_t getDot() { return Dot; } Index: ELF/LinkerScript.cpp =================================================================== --- ELF/LinkerScript.cpp +++ ELF/LinkerScript.cpp @@ -48,8 +48,10 @@ LinkerScript *elf::Script; uint64_t ExprValue::getValue() const { - if (Sec) - return Sec->getOffset(Val) + Sec->getOutputSection()->Addr; + if (Sec) { + OutputSection *Out = Sec->getOutputSection(); + return Sec->getOffset(Val) + (Out ? Out->Addr : 0); + } return Val; } @@ -72,7 +74,7 @@ // We want to set symbol values early if we can. This allows us to use symbols // as variables in linker scripts. Doing so allows us to write expressions // like this: `alignment = 16; . = ALIGN(., alignment)` - uint64_t SymValue = Value.isAbsolute() ? Value.getValue() : 0; + uint64_t SymValue = Value.isAbsolute() ? Value.Val : 0; replaceBody(Sym, Cmd->Name, /*IsLocal=*/false, Visibility, STT_NOTYPE, SymValue, 0, Sec, nullptr); return Sym->body(); @@ -133,6 +135,9 @@ auto *Sym = cast(Cmd->Sym); ExprValue V = Cmd->Expression(); if (V.isAbsolute()) { + if (!V.CanCalculateAbs) + error(Cmd->Location + + ": unable to find absolute value for: " + Cmd->Sym->getName()); Sym->Value = V.getValue(); } else { Sym->Section = V.Sec; @@ -539,6 +544,7 @@ Dot = alignTo(Dot, CurOutSec->Alignment); CurOutSec->Addr = isTbss(CurOutSec) ? Dot + ThreadBssOffset : Dot; + OutputsProccessed.insert(CurOutSec); // If neither AT nor AT> is specified for an allocatable section, the linker // will set the LMA such that the difference between VMA and LMA for the @@ -1025,12 +1031,29 @@ return INT_MAX; } +// Sometimes expression can not be calculated. For example absolute expressions +// that depends on address of output section which was not assigned yet. +// Function helps find if we can evaluate absolute expression value or not. +bool LinkerScript::canCalcSymValue(DefinedRegular *D) { + // Absolute expressions are always calculatable. + if (!D->Section) + return true; + + // We can calculate symbol absolute value if it's input section attached + // to output section and output section has address assigned. + OutputSection *OutSec = D->Section->getOutputSection(); + return OutputsProccessed.count(OutSec); +} + ExprValue LinkerScript::getSymbolValue(const Twine &Loc, StringRef S) { if (S == ".") return {CurOutSec, Dot - CurOutSec->Addr}; if (SymbolBody *B = findSymbol(S)) { - if (auto *D = dyn_cast(B)) - return {D->Section, D->Value}; + if (auto *D = dyn_cast(B)) { + ExprValue E = {D->Section, D->Value}; + E.CanCalculateAbs = canCalcSymValue(D); + return E; + } if (auto *C = dyn_cast(B)) return {InX::Common, C->Offset}; } Index: ELF/ScriptParser.cpp =================================================================== --- ELF/ScriptParser.cpp +++ ELF/ScriptParser.cpp @@ -131,11 +131,15 @@ static ExprValue add(ExprValue A, ExprValue B) { moveAbsRight(A, B); - return {A.Sec, A.ForceAbsolute, A.Val + B.getValue()}; + ExprValue E = {A.Sec, A.ForceAbsolute, A.Val + B.getValue()}; + E.CanCalculateAbs = A.CanCalculateAbs && B.CanCalculateAbs; + return E; } static ExprValue sub(ExprValue A, ExprValue B) { - return {A.Sec, A.Val - B.getValue()}; + ExprValue E = {A.Sec, A.Val - B.getValue()}; + E.CanCalculateAbs = A.CanCalculateAbs && B.CanCalculateAbs; + return E; } static ExprValue mul(ExprValue A, ExprValue B) { Index: test/ELF/linkerscript/early-assign-symbol.s =================================================================== --- test/ELF/linkerscript/early-assign-symbol.s +++ test/ELF/linkerscript/early-assign-symbol.s @@ -0,0 +1,14 @@ +# REQUIRES: x86 +# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o + +# RUN: echo "SECTIONS { aaa = ABSOLUTE(foo - 1); }" > %t1.script +# RUN: not ld.lld -o %t --script %t1.script %t.o 2>&1 | FileCheck %s + +# RUN: echo "SECTIONS { aaa = ABSOLUTE(foo - 1) + 1; }" > %t2.script +# RUN: not ld.lld -o %t --script %t2.script %t.o 2>&1 | FileCheck %s + +# CHECK: error: {{.*}}.script:1: unable to find absolute value for: aaa + +.section .text +.globl foo +foo: