Index: ELF/LinkerScript.h =================================================================== --- ELF/LinkerScript.h +++ ELF/LinkerScript.h @@ -52,8 +52,9 @@ }; struct SymbolAssignment : BaseCommand { - SymbolAssignment(StringRef Name, Expr E) - : BaseCommand(AssignmentKind), Name(Name), Expression(E) {} + SymbolAssignment(StringRef Name, Expr E, bool ForceAbs) + : BaseCommand(AssignmentKind), Name(Name), Expression(E), + ForceAbsolute(ForceAbs) {} static bool classof(const BaseCommand *C); // The LHS of an expression. Name is either a symbol name or ".". @@ -66,6 +67,7 @@ // Command attributes for PROVIDE, HIDDEN and PROVIDE_HIDDEN. bool Provide = false; bool Hidden = false; + bool ForceAbsolute; InputSectionData *GoesAfter = nullptr; }; Index: ELF/LinkerScript.cpp =================================================================== --- ELF/LinkerScript.cpp +++ ELF/LinkerScript.cpp @@ -276,6 +276,23 @@ } } +template +static void finalizeSectionSym(SymbolAssignment *Cmd, + OutputSectionBase *Sec, + typename ELFT::uint Off) { + if (auto *Body = cast_or_null>(Cmd->Sym)) { + Symbol *S = Body->symbol(); + if (Cmd->ForceAbsolute) { + replaceBody>(S, Cmd->Name, + static_cast(S->Visibility)); + Body->Value = Cmd->Expression(Sec->getVA() + Off); + } else { + Body->Section = Sec; + Body->Value = Cmd->Expression(Sec->getVA() + Off) - Sec->getVA(); + } + } +} + // Linker script may define start and end symbols for special section types, // like .got, .eh_frame_hdr, .eh_frame and others. Those sections are not a list // of regular input input sections, therefore our way of defining symbols for @@ -289,12 +306,7 @@ for (std::unique_ptr &Base : Cmd->Commands) { if (auto *AssignCmd = dyn_cast(Base.get())) { - if (auto *Sym = cast_or_null>(AssignCmd->Sym)) { - Sym->Section = Sec; - Sym->Value = - AssignCmd->Expression(Sec->getVA() + (Start ? 0 : Sec->getSize())) - - Sec->getVA(); - } + finalizeSectionSym(AssignCmd, Sec, Start ? 0 : Sec->getSize()); } else { if (!Start && isa(PrevCmd)) error("section '" + Sec->getName() + @@ -331,19 +343,13 @@ if (D != AssignCmd->GoesAfter) break; - uintX_t Value = AssignCmd->Expression(Sec->getVA() + Off) - Sec->getVA(); if (AssignCmd->Name == ".") { // Update to location counter means update to section size. - Off = Value; + Off = AssignCmd->Expression(Sec->getVA() + Off) - Sec->getVA(); Sec->setSize(Off); continue; } - - if (DefinedSynthetic *Sym = - cast_or_null>(AssignCmd->Sym)) { - Sym->Section = OutSec; - Sym->Value = Value; - } + finalizeSectionSym(AssignCmd, Sec, Off); } }; @@ -1147,11 +1153,21 @@ SymbolAssignment *ScriptParser::readAssignment(StringRef Name) { StringRef Op = next(); + Expr E; + bool ForceAbs = false; assert(Op == "=" || Op == "+="); - Expr E = readExpr(); + if (peek() == "ABSOLUTE") { + next(); + expect("("); + E = readExpr(); + expect(")"); + ForceAbs = true; + } else { + E = readExpr(); + } if (Op == "+=") E = [=](uint64_t Dot) { return getSymbolValue(Name, Dot) + E(Dot); }; - return new SymbolAssignment(Name, E); + return new SymbolAssignment(Name, E, ForceAbs); } // This is an operator-precedence parser to parse a linker Index: test/ELF/linkerscript/linkerscript-symbols-synthetic.s =================================================================== --- test/ELF/linkerscript/linkerscript-symbols-synthetic.s +++ test/ELF/linkerscript/linkerscript-symbols-synthetic.s @@ -10,7 +10,9 @@ # RUN: *(.foo) \ # RUN: end_foo = .; \ # RUN: PROVIDE_HIDDEN(_end_sec = .); \ +# RUN: PROVIDE(_end_sec_abs = ABSOLUTE(.)); \ # RUN: size_foo_1 = SIZEOF(.foo); \ +# RUN: size_foo_1_abs = ABSOLUTE(SIZEOF(.foo)); \ # RUN: . = ALIGN(0x1000); \ # RUN: begin_bar = .; \ # RUN: *(.bar) \ @@ -19,10 +21,10 @@ # RUN: size_foo_3 = SIZEOF(.foo); \ # RUN: .eh_frame_hdr : { \ # RUN: __eh_frame_hdr_start = .; \ -# RUN: __eh_frame_hdr_start2 = ALIGN(0x10); \ +# RUN: __eh_frame_hdr_start2 = ABSOLUTE(ALIGN(0x10)); \ # RUN: *(.eh_frame_hdr) \ # RUN: __eh_frame_hdr_end = .; \ -# RUN: __eh_frame_hdr_end2 = ALIGN(0x10); } \ +# RUN: __eh_frame_hdr_end2 = ABSOLUTE(ALIGN(0x10)); } \ # RUN: }" > %t.script # RUN: ld.lld -o %t1 --eh-frame-hdr --script %t.script %t # RUN: llvm-objdump -t %t1 | FileCheck --check-prefix=SIMPLE %s @@ -34,7 +36,7 @@ # RUN: PROVIDE_HIDDEN(_begin_sec = .); \ # RUN: __eh_frame_hdr_start = .; \ # RUN: *(.eh_frame_hdr) \ -# RUN: __eh_frame_hdr_end = .; \ +# RUN: PROVIDE_HIDDEN(_end_sec_abs = ABSOLUTE(.)); \ # RUN: *(.eh_frame_hdr) } \ # RUN: PROVIDE_HIDDEN(_end_sec = .); \ # RUN: }" > %t.script @@ -46,23 +48,26 @@ # RUN: PROVIDE_HIDDEN(_begin_sec = .); \ # RUN: *(.eh_frame_hdr) \ # RUN: *(.eh_frame_hdr) \ +# RUN: PROVIDE_HIDDEN(_end_sec_abs = ABSOLUTE(.)); \ # RUN: PROVIDE_HIDDEN(_end_sec = .); } \ # RUN: }" > %t.script # RUN: ld.lld -o %t1 --eh-frame-hdr --script %t.script %t # SIMPLE: 0000000000000160 .foo 00000000 .hidden _end_sec # SIMPLE: 0000000000000158 .foo 00000000 _begin_sec +# SIMPLE-NEXT: 0000000000000160 *ABS* 00000000 _end_sec_abs # SIMPLE-NEXT: 0000000000000158 .foo 00000000 begin_foo # SIMPLE-NEXT: 0000000000000160 .foo 00000000 end_foo # SIMPLE-NEXT: 0000000000000008 .foo 00000000 size_foo_1 +# SIMPLE-NEXT: 0000000000000008 *ABS* 00000000 size_foo_1_abs # SIMPLE-NEXT: 0000000000001000 .foo 00000000 begin_bar # SIMPLE-NEXT: 0000000000001004 .foo 00000000 end_bar # SIMPLE-NEXT: 0000000000000eac .foo 00000000 size_foo_2 # SIMPLE-NEXT: 0000000000000eac *ABS* 00000000 size_foo_3 # SIMPLE-NEXT: 0000000000001004 .eh_frame_hdr 00000000 __eh_frame_hdr_start -# SIMPLE-NEXT: 0000000000001010 .eh_frame_hdr 00000000 __eh_frame_hdr_start2 +# SIMPLE-NEXT: 0000000000001010 *ABS* 00000000 __eh_frame_hdr_start2 # SIMPLE-NEXT: 0000000000001018 .eh_frame_hdr 00000000 __eh_frame_hdr_end -# SIMPLE-NEXT: 0000000000001020 .eh_frame_hdr 00000000 __eh_frame_hdr_end2 +# SIMPLE-NEXT: 0000000000001020 *ABS* 00000000 __eh_frame_hdr_end2 # ERROR: section '.eh_frame_hdr' supports only start and end symbols .global _start @@ -80,4 +85,4 @@ nop .cfi_endproc -.global _begin_sec, _end_sec +.global _begin_sec, _end_sec, _end_sec_abs