Index: ELF/Driver.cpp =================================================================== --- ELF/Driver.cpp +++ ELF/Driver.cpp @@ -1026,6 +1026,8 @@ for (StringRef Sym : Script->Opt.ReferencedSymbols) Symtab->addUndefined(Sym); + Script->prefetchSymbols(); + // If an entry symbol is in a static archive, pull out that file now // to complete the symbol table. After this, no new names except a // few linker-synthesized ones will be added to the symbol table. Index: ELF/LTO.cpp =================================================================== --- ELF/LTO.cpp +++ ELF/LTO.cpp @@ -129,11 +129,6 @@ std::vector Syms = F.getSymbols(); std::vector Resols(Syms.size()); - DenseSet ScriptSymbols; - for (BaseCommand *Base : Script->Opt.Commands) - if (auto *Cmd = dyn_cast(Base)) - ScriptSymbols.insert(Cmd->Name); - // Provide a resolution to the LTO API for each symbol. for (const lto::InputFile::Symbol &ObjSym : Obj.symbols()) { SymbolBody *B = Syms[SymNum]; @@ -165,7 +160,7 @@ // still not final: // 1) Aliased (with --defsym) or wrapped (with --wrap) symbols. // 2) Symbols redefined in linker script. - R.LinkerRedefined = !Sym->CanInline || ScriptSymbols.count(B->getName()); + R.LinkerRedefined = !Sym->CanInline; } checkError(LTOObj->add(std::move(F.Obj), Resols)); } Index: ELF/LinkerScript.h =================================================================== --- ELF/LinkerScript.h +++ ELF/LinkerScript.h @@ -256,7 +256,8 @@ void assignOffsets(OutputSection *Sec); void assignAddresses(); void allocateHeaders(std::vector &Phdrs); - void addSymbol(SymbolAssignment *Cmd); + SymbolBody *addSymbol(SymbolAssignment *Cmd); + void prefetchSymbols(); void processCommands(OutputSectionFactory &Factory); // Parsed linker script configurations are set to this struct. Index: ELF/LinkerScript.cpp =================================================================== --- ELF/LinkerScript.cpp +++ ELF/LinkerScript.cpp @@ -79,13 +79,21 @@ return getValue() - getSecAddr(); } -static SymbolBody *addRegular(SymbolAssignment *Cmd) { +static SymbolBody *addRegular(SymbolAssignment *Cmd, bool Prefetch) { Symbol *Sym; uint8_t Visibility = Cmd->Hidden ? STV_HIDDEN : STV_DEFAULT; std::tie(Sym, std::ignore) = Symtab->insert(Cmd->Name, /*Type*/ 0, Visibility, /*CanOmitFromDynSym*/ false, /*File*/ nullptr); Sym->Binding = STB_GLOBAL; + + // Create dummy symbols when prefetching, their values will be updated later. + if (Prefetch) { + replaceBody(Sym, nullptr, Cmd->Name, /*IsLocal=*/false, + Visibility, STT_NOTYPE, 0, 0, nullptr); + return Sym->body(); + } + ExprValue Value = Cmd->Expression(); SectionBase *Sec = Value.isAbsolute() ? nullptr : Value.Sec; @@ -155,17 +163,32 @@ } } -void LinkerScript::addSymbol(SymbolAssignment *Cmd) { +SymbolBody *LinkerScript::addSymbol(SymbolAssignment *Cmd) { if (Cmd->Name == ".") - return; + return nullptr; + SymbolBody *B = Symtab->find(Cmd->Name); // If a symbol was in PROVIDE(), we need to define it only when // it is a referenced undefined symbol. - SymbolBody *B = Symtab->find(Cmd->Name); if (Cmd->Provide && (!B || B->isDefined())) - return; + return nullptr; - Cmd->Sym = addRegular(Cmd); + // During prefetching symbols we ignore those we already know about. + bool Prefetch = CurAddressState == nullptr; + if (B && Prefetch) + return B; + return addRegular(Cmd, Prefetch); +} + +// We want to prefetch symbols assigned by linker script early enough, +// so we can work with them before script commands are processed. +void LinkerScript::prefetchSymbols() { + assert(!CurAddressState); + // Tell LTO to stop inlining symbols redefined by linker script. + for (BaseCommand *Base : Opt.Commands) + if (SymbolAssignment *Cmd = dyn_cast(Base)) + if (SymbolBody *Body = addSymbol(Cmd)) + Body->symbol()->CanInline = false; } bool SymbolAssignment::classof(const BaseCommand *C) { @@ -370,7 +393,7 @@ for (size_t I = 0; I < Opt.Commands.size(); ++I) { // Handle symbol assignments outside of any output section. if (auto *Cmd = dyn_cast(Opt.Commands[I])) { - addSymbol(Cmd); + Cmd->Sym = addSymbol(Cmd); continue; } @@ -403,7 +426,7 @@ // ".foo : { ...; bar = .; }". Handle them. for (BaseCommand *Base : Sec->Commands) if (auto *OutCmd = dyn_cast(Base)) - addSymbol(OutCmd); + OutCmd->Sym = addSymbol(OutCmd); // Handle subalign (e.g. ".foo : SUBALIGN(32) { ... }"). If subalign // is given, input sections are aligned to that value, whether the Index: ELF/Writer.cpp =================================================================== --- ELF/Writer.cpp +++ ELF/Writer.cpp @@ -787,7 +787,11 @@ // to GOT. Default offset is 0x7ff0. // See "Global Data Symbols" in Chapter 6 in the following document: // ftp://www.linux-mips.org/pub/linux/mips/doc/ABI/mipsabi.pdf - ElfSym::MipsGp = Symtab->addAbsolute("_gp", STV_HIDDEN, STB_LOCAL); + SymbolBody *Gp = Symtab->find("_gp"); + if (!Gp || !isa(Gp)) + ElfSym::MipsGp = Symtab->addAbsolute("_gp", STV_HIDDEN, STB_LOCAL); + else + ElfSym::MipsGp = dyn_cast(Gp); // On MIPS O32 ABI, _gp_disp is a magic symbol designates offset between // start of function and 'gp' pointer into GOT. Index: test/ELF/linkerscript/symbols-synthetic.s =================================================================== --- test/ELF/linkerscript/symbols-synthetic.s +++ test/ELF/linkerscript/symbols-synthetic.s @@ -61,6 +61,7 @@ # SIMPLE-NEXT: 0000000000000120 .foo 00000000 _begin_sec # SIMPLE-NEXT: 0000000000000128 *ABS* 00000000 _end_sec_abs # SIMPLE-NEXT: 0000000000001048 .text 00000000 _start +# SIMPLE-NEXT: 0000000000000ee4 *ABS* 00000000 size_foo_3 # SIMPLE-NEXT: 0000000000000120 .foo 00000000 begin_foo # SIMPLE-NEXT: 0000000000000128 .foo 00000000 end_foo # SIMPLE-NEXT: 0000000000000008 *ABS* 00000000 size_foo_1 @@ -68,7 +69,6 @@ # SIMPLE-NEXT: 0000000000001000 .foo 00000000 begin_bar # SIMPLE-NEXT: 0000000000001004 .foo 00000000 end_bar # SIMPLE-NEXT: 0000000000000ee4 *ABS* 00000000 size_foo_2 -# SIMPLE-NEXT: 0000000000000ee4 *ABS* 00000000 size_foo_3 # SIMPLE-NEXT: 0000000000001004 .eh_frame_hdr 00000000 __eh_frame_hdr_start # SIMPLE-NEXT: 0000000000001010 *ABS* 00000000 __eh_frame_hdr_start2 # SIMPLE-NEXT: 0000000000001018 .eh_frame_hdr 00000000 __eh_frame_hdr_end Index: test/ELF/mips-gp-ext.s =================================================================== --- test/ELF/mips-gp-ext.s +++ test/ELF/mips-gp-ext.s @@ -27,10 +27,10 @@ # REQUIRES: mips # REL: Contents of section .text: -# REL-NEXT: 0000 3c080000 2108010c 8f82fffc +# REL-NEXT: 0000 3c080000 2108010c 8f82001c # ^-- %hi(_gp_disp) # ^-- %lo(_gp_disp) -# ^-- 8 - (0x10c - 0x100) +# ^-- 8 - (0x10c - 0x120) # G - (GP - .got) # REL: Contents of section .reginfo: @@ -39,18 +39,18 @@ # ^-- _gp # REL: Contents of section .data: -# REL-NEXT: 00f0 fffffef4 +# REL-NEXT: 0110 fffffef4 # ^-- 0-0x10c # REL: 00000000 .text 00000000 foo # REL: 00000000 *ABS* 00000000 .hidden _gp_disp -# REL: 0000010c *ABS* 00000000 .hidden _gp +# REL: 0000010c *ABS* 00000000 _gp # ABS: Contents of section .text: -# ABS-NEXT: 0000 3c080000 21080200 8f82ff08 +# ABS-NEXT: 0000 3c080000 21080200 8f82ff28 # ^-- %hi(_gp_disp) # ^-- %lo(_gp_disp) -# ^-- 8 - (0x200 - 0x100) +# ^-- 8 - (0x200 - 0x120) # G - (GP - .got) # ABS: Contents of section .reginfo: @@ -59,12 +59,12 @@ # ^-- _gp # ABS: Contents of section .data: -# ABS-NEXT: 00f0 fffffe00 +# ABS-NEXT: 0110 fffffe00 # ^-- 0-0x200 # ABS: 00000000 .text 00000000 foo # ABS: 00000000 *ABS* 00000000 .hidden _gp_disp -# ABS: 00000200 *ABS* 00000000 .hidden _gp +# ABS: 00000200 *ABS* 00000000 _gp .text foo: