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; @@ -232,6 +233,8 @@ void output(InputSection *Sec); void process(BaseCommand &Base); + void convertForcedAbsoluteSymbols(); + OutputSection *Aether; bool ErrorOnMissingSection = false; @@ -245,6 +248,8 @@ llvm::DenseSet AlreadyOutputOS; llvm::DenseSet AlreadyOutputIS; + std::vector ForcedAbsoluteSyms; + public: bool hasPhdrsCommands() { return !Opt.PhdrsCommands.empty(); } uint64_t getDot() { return Dot; } Index: ELF/LinkerScript.cpp =================================================================== --- ELF/LinkerScript.cpp +++ ELF/LinkerScript.cpp @@ -72,7 +72,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 +133,20 @@ auto *Sym = cast(Cmd->Sym); ExprValue V = Cmd->Expression(); if (V.isAbsolute()) { + // We handle forced absolute symbols as regular until we assign all + // output sections addresses. Then we convert such symbols to absolutes. + // That is done because some scripts may assign absolute values + // earlier than value can be calculated, like: + // aaa = ABSOLUTE(foo - 1); + // .text : { *(.text*) } }; + // where 'foo' is a symbol in .text and it's absolute value depends + // on output section address which is not known during assignment. + if (V.ForceAbsolute && V.Sec) { + Sym->Section = V.Sec; + Sym->Value = V.Val; + ForcedAbsoluteSyms.push_back(Sym); + return; + } Sym->Value = V.getValue(); } else { Sym->Section = V.Sec; @@ -794,6 +808,15 @@ else if (auto *Cmd = dyn_cast(Base)) Cmd->Expression(); } + convertForcedAbsoluteSymbols(); +} + +void LinkerScript::convertForcedAbsoluteSymbols() { + for (DefinedRegular *DR : ForcedAbsoluteSyms) { + DR->Value = DR->Section->getOffset(DR->Value) + + DR->Section->getOutputSection()->Addr; + DR->Section = nullptr; + } } void LinkerScript::assignAddresses(std::vector &Phdrs) { @@ -825,6 +848,8 @@ Sec->Addr = 0; } + convertForcedAbsoluteSymbols(); + allocateHeaders(Phdrs, *OutputSections, MinVA); } @@ -932,7 +957,9 @@ return {CurOutSec, Dot - CurOutSec->Addr}; if (SymbolBody *B = findSymbol(S)) { if (auto *D = dyn_cast(B)) - return {D->Section, D->Value}; + return {D->Section, + llvm::find(ForcedAbsoluteSyms, D) != ForcedAbsoluteSyms.end(), + D->Value}; if (auto *C = dyn_cast(B)) return {InX::Common, C->Offset}; } Index: ELF/ScriptParser.cpp =================================================================== --- ELF/ScriptParser.cpp +++ ELF/ScriptParser.cpp @@ -123,7 +123,7 @@ // Some operations only support one non absolute value. Move the // absolute one to the right hand side for convenience. static void moveAbsRight(ExprValue &A, ExprValue &B) { - if (A.isAbsolute()) + if (A.Sec == nullptr) std::swap(A, B); if (!B.isAbsolute()) error("At least one side of the expression must be absolute"); 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,23 @@ +# REQUIRES: x86 +# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o +# RUN: echo "SECTIONS { . = 0x1000; \ +# RUN: aaa = ABSOLUTE(foo - 1); \ +# RUN: bbb = aaa + 2; \ +# RUN: .text : { *(.text*) } }; \ +# RUN: ccc = ABSOLUTE(foo - 1); \ +# RUN: ddd = ccc + 2;" > %t.script +# RUN: ld.lld -o %t --script %t.script %t.o +# RUN: llvm-objdump -t %t | FileCheck %s + +# CHECK: SYMBOL TABLE: +# CHECK: 0000000000000000 *UND* 00000000 +# CHECK: 0000000000001000 .text 00000000 foo +# CHECK: 0000000000000fff *ABS* 00000000 aaa +# CHECK: 0000000000000fff *ABS* 00000000 ccc +# CHECK: 0000000000001001 *ABS* 00000000 bbb +# CHECK: 0000000000001001 *ABS* 00000000 ddd + +.section .text +.globl foo +foo: + nop