Index: ELF/Relocations.h =================================================================== --- ELF/Relocations.h +++ ELF/Relocations.h @@ -114,6 +114,10 @@ SymbolBody *Sym; }; +template void reportUndefined(SymbolBody &Sym, + InputSectionBase &S, + uint64_t Offset); + template void scanRelocations(InputSectionBase &); class ThunkSection; Index: ELF/Relocations.cpp =================================================================== --- ELF/Relocations.cpp +++ ELF/Relocations.cpp @@ -671,8 +671,8 @@ } template -static void reportUndefined(SymbolBody &Sym, InputSectionBase &S, - uint64_t Offset) { +void elf::reportUndefined(SymbolBody &Sym, InputSectionBase &S, + uint64_t Offset) { if (Config->UnresolvedSymbols == UnresolvedPolicy::IgnoreAll) return; Index: ELF/Symbols.h =================================================================== --- ELF/Symbols.h +++ ELF/Symbols.h @@ -305,6 +305,9 @@ // __bss_start static DefinedRegular *Bss; + // __ehdr_start + static DefinedRegular *EhdrStart; + // etext and _etext static DefinedRegular *Etext1; static DefinedRegular *Etext2; Index: ELF/Symbols.cpp =================================================================== --- ELF/Symbols.cpp +++ ELF/Symbols.cpp @@ -29,6 +29,7 @@ using namespace lld::elf; DefinedRegular *ElfSym::Bss; +DefinedRegular *ElfSym::EhdrStart; DefinedRegular *ElfSym::Etext1; DefinedRegular *ElfSym::Etext2; DefinedRegular *ElfSym::Edata1; Index: ELF/Writer.cpp =================================================================== --- ELF/Writer.cpp +++ ELF/Writer.cpp @@ -863,13 +863,13 @@ if (!In::DynSymTab) Symtab::X->addIgnored("__tls_get_addr"); + // __ehdr_start is the location of ELF file headers. + ElfSym::EhdrStart = addOptionalRegular("__ehdr_start", Out::ElfHeader, 0, STV_HIDDEN); + // If linker script do layout we do not need to create any standart symbols. if (Script->Opt.HasSections) return; - // __ehdr_start is the location of ELF file headers. - addOptionalRegular("__ehdr_start", Out::ElfHeader, 0, STV_HIDDEN); - auto Add = [](StringRef S) { return addOptionalRegular(S, Out::ElfHeader, 0, STV_DEFAULT); }; @@ -1089,6 +1089,14 @@ } } +template +static void checkUndefined(InputSectionBase &Sec, ArrayRef Rels, + SymbolBody *S) { + for (auto &I : Rels) + if (&Sec.getFile()->getRelocTargetSym(I) == S) + reportUndefined(*S, Sec, I.r_offset); +} + // Create output section objects and add them to OutputSections. template void Writer::finalizeSections() { Out::DebugInfo = findSection(".debug_info"); @@ -1179,6 +1187,20 @@ fixHeaders(); } + if (ElfSym::EhdrStart) { + auto PhdrI = + std::find_if(Phdrs.begin(), Phdrs.end(), [](const PhdrEntry &E) { + return E.p_type == PT_LOAD && E.First == Out::ElfHeader; }); + if (PhdrI == Phdrs.end()) { + forEachRelSec([&](InputSectionBase &S) { + if (S.AreRelocsRela) + checkUndefined(S, S.relas(), ElfSym::EhdrStart); + else + checkUndefined(S, S.rels(), ElfSym::EhdrStart); + }); + } + } + // Dynamic section must be the last one in this list and dynamic // symbol table section (DynSymTab) must be the first one. applySynthetic({In::DynSymTab, In::Bss, In::BssRelRo, Index: test/ELF/linkerscript/ehdr_start.s =================================================================== --- test/ELF/linkerscript/ehdr_start.s +++ test/ELF/linkerscript/ehdr_start.s @@ -1,11 +1,32 @@ # REQUIRES: x86 # RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o -# RUN: echo "SECTIONS { }" > %t.script -# RUN: not ld.lld %t.o -script %t.script -o %t 2>&1 | FileCheck %s +# RUN: echo "SECTIONS { }" > %t1.script +# RUN: not ld.lld %t.o -script %t1.script -o %t1 2>&1 | FileCheck %s # CHECK: error: undefined symbol: __ehdr_start # CHECK: >>> referenced by {{.*}}:(.text+0x0) +# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o +# RUN: echo "SECTIONS { \ +# RUN: . = SIZEOF_HEADERS; \ +# RUN: .text : { *(.text*) } : text \ +# RUN: } \ +# RUN: PHDRS { \ +# RUN: text PT_LOAD FILEHDR PHDRS; \ +# RUN: }" > %t2.script +# RUN: ld.lld %t.o -script %t2.script -o %t2 2>&1 +# RUN: llvm-readobj -symbols %t2 | FileCheck %s --check-prefix=PHDRS + +# PHDRS: Name: __ehdr_start (1) +# PHDRS-NEXT: Value: 0x0 +# PHDRS-NEXT: Size: 0 +# PHDRS-NEXT: Binding: Local (0x0) +# PHDRS-NEXT: Type: None (0x0) +# PHDRS-NEXT: Other [ (0x2) +# PHDRS-NEXT: STV_HIDDEN (0x2) +# PHDRS-NEXT: ] +# PHDRS-NEXT: Section: .text (0x1) + .text .global _start, __ehdr_start _start: