Index: head/contrib/llvm/tools/lld/ELF/Driver.cpp =================================================================== --- head/contrib/llvm/tools/lld/ELF/Driver.cpp +++ head/contrib/llvm/tools/lld/ELF/Driver.cpp @@ -1010,6 +1010,15 @@ if (Args.hasArg(OPT_exclude_libs)) excludeLibs(Args, Files); + // Create ElfHeader early. We need a dummy section in + // addReservedSymbols to mark the created symbols as not absolute. + Out::ElfHeader = make("", 0, SHF_ALLOC); + Out::ElfHeader->Size = sizeof(typename ELFT::Ehdr); + + // We need to create some reserved symbols such as _end. Create them. + if (!Config->Relocatable) + addReservedSymbols(); + // Apply version scripts. Symtab.scanVersionScript(); Index: head/contrib/llvm/tools/lld/ELF/MarkLive.cpp =================================================================== --- head/contrib/llvm/tools/lld/ELF/MarkLive.cpp +++ head/contrib/llvm/tools/lld/ELF/MarkLive.cpp @@ -73,12 +73,13 @@ std::function Fn) { SymbolBody &B = Sec.getFile()->getRelocTargetSym(Rel); if (auto *D = dyn_cast(&B)) { - if (!D->Section) + auto *RelSec = dyn_cast_or_null(D->Section); + if (!RelSec) return; typename ELFT::uint Offset = D->Value; if (D->isSection()) Offset += getAddend(Sec, Rel); - Fn({cast(D->Section), Offset}); + Fn({RelSec, Offset}); } else if (auto *U = dyn_cast(&B)) { for (InputSectionBase *Sec : CNamedSections.lookup(U->getName())) Fn({Sec, 0}); @@ -220,7 +221,7 @@ auto MarkSymbol = [&](const SymbolBody *Sym) { if (auto *D = dyn_cast_or_null(Sym)) - if (auto *IS = cast_or_null(D->Section)) + if (auto *IS = dyn_cast_or_null(D->Section)) Enqueue({IS, D->Value}); }; Index: head/contrib/llvm/tools/lld/ELF/Writer.h =================================================================== --- head/contrib/llvm/tools/lld/ELF/Writer.h +++ head/contrib/llvm/tools/lld/ELF/Writer.h @@ -47,6 +47,7 @@ bool HasLMA = false; }; +template void addReservedSymbols(); llvm::StringRef getOutputSectionName(llvm::StringRef Name); template uint32_t getMipsEFlags(); Index: head/contrib/llvm/tools/lld/ELF/Writer.cpp =================================================================== --- head/contrib/llvm/tools/lld/ELF/Writer.cpp +++ head/contrib/llvm/tools/lld/ELF/Writer.cpp @@ -50,7 +50,6 @@ void createSyntheticSections(); void copyLocalSymbols(); void addSectionSymbols(); - void addReservedSymbols(); void createSections(); void forEachRelSec(std::function Fn); void sortSections(); @@ -168,10 +167,6 @@ if (!Config->Relocatable) combineEhFrameSections(); - // We need to create some reserved symbols such as _end. Create them. - if (!Config->Relocatable) - addReservedSymbols(); - // Create output sections. if (Script->Opt.HasSections) { // If linker script contains SECTIONS commands, let it create sections. @@ -286,8 +281,6 @@ Config->IsRela ? ".rela.dyn" : ".rel.dyn", Config->ZCombreloc); InX::ShStrTab = make(".shstrtab", false); - Out::ElfHeader = make("", 0, SHF_ALLOC); - Out::ElfHeader->Size = sizeof(Elf_Ehdr); Out::ProgramHeaders = make("", 0, SHF_ALLOC); Out::ProgramHeaders->updateAlignment(Config->Wordsize); @@ -796,7 +789,7 @@ // The linker is expected to define some symbols depending on // the linking result. This function defines such symbols. -template void Writer::addReservedSymbols() { +template void elf::addReservedSymbols() { if (Config->EMachine == EM_MIPS) { // Define _gp for MIPS. st_value of _gp symbol will be updated by Writer // so that it points to an absolute address which by default is relative @@ -820,21 +813,9 @@ Symtab::X->addAbsolute("__gnu_local_gp", STV_HIDDEN, STB_LOCAL); } - // The _GLOBAL_OFFSET_TABLE_ symbol is defined by target convention to - // be at some offset from the base of the .got section, usually 0 or the end - // of the .got - InputSection *GotSection = InX::MipsGot ? cast(InX::MipsGot) - : cast(InX::Got); ElfSym::GlobalOffsetTable = addOptionalRegular( - "_GLOBAL_OFFSET_TABLE_", GotSection, Target->GotBaseSymOff); + "_GLOBAL_OFFSET_TABLE_", Out::ElfHeader, Target->GotBaseSymOff); - // __tls_get_addr is defined by the dynamic linker for dynamic ELFs. For - // static linking the linker is required to optimize away any references to - // __tls_get_addr, so it's not defined anywhere. Create a hidden definition - // to avoid the undefined symbol error. - if (!InX::DynSymTab) - Symtab::X->addIgnored("__tls_get_addr"); - // __ehdr_start is the location of ELF file headers. Note that we define // this symbol unconditionally even when using a linker script, which // differs from the behavior implemented by GNU linker which only define @@ -1721,6 +1702,15 @@ // to each section. This function fixes some predefined // symbol values that depend on section address and size. template void Writer::fixPredefinedSymbols() { + if (ElfSym::GlobalOffsetTable) { + // The _GLOBAL_OFFSET_TABLE_ symbol is defined by target convention to + // be at some offset from the base of the .got section, usually 0 or the end + // of the .got + InputSection *GotSection = InX::MipsGot ? cast(InX::MipsGot) + : cast(InX::Got); + ElfSym::GlobalOffsetTable->Section = GotSection; + } + // _etext is the first location after the last read-only loadable segment. // _edata is the first location after the last read-write loadable segment. // _end is the first location after the uninitialized data region. @@ -1911,3 +1901,8 @@ template void elf::writeResult(); template void elf::writeResult(); template void elf::writeResult(); + +template void elf::addReservedSymbols(); +template void elf::addReservedSymbols(); +template void elf::addReservedSymbols(); +template void elf::addReservedSymbols();