Index: ELF/LinkerScript.cpp =================================================================== --- ELF/LinkerScript.cpp +++ ELF/LinkerScript.cpp @@ -97,13 +97,14 @@ if (ScriptConfig->HasSections) return; - uint64_t Value = Cmd->Expression(0); if (Cmd->Expression.IsAbsolute()) { - cast>(Cmd->Sym)->Value = Value; + cast>(Cmd->Sym)->Value = Cmd->Expression(0); } else { const OutputSectionBase *Sec = Cmd->Expression.Section(); if (Sec) - cast(Cmd->Sym)->Value = Value - Sec->Addr; + cast(Cmd->Sym)->GetValue = [=] { + return Cmd->Expression(0) - Sec->Addr; + }; } } @@ -381,9 +382,16 @@ if (!Cmd->Sym) return; + // Sometimes Section->Addr is not yet set when we proccess the assign command. + // It can happen when non-absolute value is assigned before processing + // first section. Example: Sym = . + 0x1; .sec : { ... }; + // In that case Sym contains offset depending on VA of the .sec, but VA value + // was not yet set. To solve it we postpone the evaluation of symbol value. if (auto *Body = dyn_cast(Cmd->Sym)) { Body->Section = Cmd->Expression.Section(); - Body->Value = Cmd->Expression(Value) - Body->Section->Addr; + Body->GetValue = [=] { + return Cmd->Expression(Value) - Body->Section->Addr; + }; return; } auto *Body = cast>(Cmd->Sym); Index: ELF/Symbols.h =================================================================== --- ELF/Symbols.h +++ ELF/Symbols.h @@ -226,13 +226,13 @@ const OutputSectionBase *Section) : Defined(SymbolBody::DefinedSyntheticKind, Name, /*IsLocal=*/false, llvm::ELF::STV_HIDDEN, 0 /* Type */), - Value(Value), Section(Section) {} + GetValue([=] { return Value; }), Section(Section) {} static bool classof(const SymbolBody *S) { return S->kind() == SymbolBody::DefinedSyntheticKind; } - uint64_t Value; + std::function GetValue; const OutputSectionBase *Section; }; Index: ELF/Symbols.cpp =================================================================== --- ELF/Symbols.cpp +++ ELF/Symbols.cpp @@ -37,11 +37,12 @@ case SymbolBody::DefinedSyntheticKind: { auto &D = cast(Body); const OutputSectionBase *Sec = D.Section; + uintX_t Value = D.GetValue(); if (!Sec) - return D.Value; - if (D.Value == uintX_t(-1)) + return Value; + if (Value == uintX_t(-1)) return Sec->Addr + Sec->Size; - return Sec->Addr + D.Value; + return Sec->Addr + Value; } case SymbolBody::DefinedRegularKind: { auto &D = cast>(Body); Index: ELF/Writer.cpp =================================================================== --- ELF/Writer.cpp +++ ELF/Writer.cpp @@ -1607,11 +1607,11 @@ OutputSectionBase *Sec, uint64_t Value) { if (S1) { S1->Section = Sec; - S1->Value = Value; + S1->GetValue = [=] { return Value; }; } if (S2) { S2->Section = Sec; - S2->Value = Value; + S2->GetValue = [=] { return Value; }; } }; Index: test/ELF/linkerscript/non-absolute2.s =================================================================== --- test/ELF/linkerscript/non-absolute2.s +++ test/ELF/linkerscript/non-absolute2.s @@ -0,0 +1,28 @@ +# REQUIRES: x86 +# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t1.o +# RUN: echo "SECTIONS { A = . - 0x9; . += 0x1000; }" > %t.script +# RUN: ld.lld -shared %t1.o --script %t.script -o %t +# RUN: llvm-objdump -section-headers %t | FileCheck %s --check-prefix=DUMP +# RUN: llvm-readobj -t %t | FileCheck %s --check-prefix=SYMBOL + +# DUMP: Sections: +# DUMP-NEXT: Idx Name Size Address +# DUMP-NEXT: 0 00000000 0000000000000000 +# DUMP-NEXT: 1 .text 00000006 0000000000001000 + +# SYMBOL: Symbol { +# SYMBOL: Name: A +# SYMBOL-NEXT: Value: 0xFFFFFFFFFFFFFFF7 +# SYMBOL-NEXT: Size: 0 +# SYMBOL-NEXT: Binding: Local +# SYMBOL-NEXT: Type: None +# SYMBOL-NEXT: Other [ +# SYMBOL-NEXT: STV_HIDDEN +# SYMBOL-NEXT: ] +# SYMBOL-NEXT: Section: .text +# SYMBOL-NEXT: } + +.text + movl A(%rip), %eax + +.hidden A