Index: ELF/Driver.cpp =================================================================== --- ELF/Driver.cpp +++ ELF/Driver.cpp @@ -920,6 +920,11 @@ if (ErrorCount) return; + // Some symbols (such as __ehdr_start) are defined lazily only when there + // are undefined symbols for them, so we add these to trigger that logic. + for (StringRef Sym : Script->Opt.UndefinedSymbols) + Symtab.addUndefined(Sym); + for (auto *Arg : Args.filtered(OPT_wrap)) Symtab.wrap(Arg->getValue()); Index: ELF/LinkerScript.h =================================================================== --- ELF/LinkerScript.h +++ ELF/LinkerScript.h @@ -217,6 +217,9 @@ // A map from memory region name to a memory region descriptor. llvm::DenseMap MemoryRegions; + + // A list of undefined symbols referenced by the script. + std::vector UndefinedSymbols; }; class LinkerScript { Index: ELF/LinkerScript.cpp =================================================================== --- ELF/LinkerScript.cpp +++ ELF/LinkerScript.cpp @@ -999,8 +999,8 @@ if (SymbolBody *B = findSymbol(S)) { if (auto *D = dyn_cast(B)) return {D->Section, D->Value}; - auto *C = cast(B); - return {InX::Common, C->Offset}; + if (auto *C = dyn_cast(B)) + return {InX::Common, C->Offset}; } error(Loc + ": symbol not found: " + S); return 0; @@ -1867,8 +1867,11 @@ return [=] { return V; }; // Tok is a symbol name. - if (Tok != "." && !isValidCIdentifier(Tok)) - setError("malformed number: " + Tok); + if (Tok != ".") { + if (!isValidCIdentifier(Tok)) + setError("malformed number: " + Tok); + Script->Opt.UndefinedSymbols.push_back(Tok); + } return [=] { return Script->getSymbolValue(Location, Tok); }; } Index: test/ELF/linkerscript/symbol-reserved.s =================================================================== --- /dev/null +++ test/ELF/linkerscript/symbol-reserved.s @@ -0,0 +1,16 @@ +# REQUIRES: x86 +# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t +# RUN: echo "PROVIDE_HIDDEN(newsym = __ehdr_start + 5);" > %t.script +# RUN: ld.lld -o %t1 %t.script %t +# RUN: llvm-objdump -t %t1 | FileCheck %s + +# CHECK: 0000000000200005 .text 00000000 .hidden newsym + +# RUN: ld.lld -o %t1.so %t.script %t -shared +# RUN: llvm-objdump -t %t1.so | FileCheck --check-prefix=SHARED %s + +# SHARED: 0000000000000005 .dynsym 00000000 .hidden newsym + +.global _start +_start: + lea newsym(%rip),%rax