Index: ELF/MarkLive.cpp =================================================================== --- ELF/MarkLive.cpp +++ ELF/MarkLive.cpp @@ -22,6 +22,7 @@ #include "InputSection.h" #include "LinkerScript.h" +#include "Memory.h" #include "OutputSections.h" #include "Strings.h" #include "SymbolTable.h" @@ -63,17 +64,25 @@ return Rel.r_addend; } +// There are normally few input sections whose names are valid C +// identifiers, so we just store a std::vector instead of a multimap. +static DenseMap> CNamedSections; + template static void resolveReloc(InputSectionBase &Sec, RelT &Rel, std::function Fn) { SymbolBody &B = Sec.getFile()->getRelocTargetSym(Rel); - auto *D = dyn_cast(&B); - if (!D || !D->Section) - return; - typename ELFT::uint Offset = D->Value; - if (D->isSection()) - Offset += getAddend(Sec, Rel); - Fn({D->Section->Repl, Offset}); + if (auto *D = dyn_cast(&B)) { + if (!D->Section) + return; + typename ELFT::uint Offset = D->Value; + if (D->isSection()) + Offset += getAddend(Sec, Rel); + Fn({D->Section->Repl, Offset}); + } else if (auto *U = dyn_cast(&B)) { + for (InputSectionBase *Sec : CNamedSections.lookup(U->getName())) + Fn({Sec, 0}); + } } // Calls Fn for each section that Sec refers to via relocations. @@ -184,6 +193,7 @@ // sections to set their "Live" bits. template void elf::markLive() { SmallVector Q; + CNamedSections.clear(); auto Enqueue = [&](ResolvedReloc R) { // Skip over discarded sections. This in theory shouldn't happen, because @@ -223,22 +233,11 @@ for (StringRef S : Config->Undefined) MarkSymbol(Symtab::X->find(S)); - // Remember which __start_* or __stop_* symbols are used so that we don't gc - // those sections. - DenseSet UsedStartStopNames; - // Preserve externally-visible symbols if the symbols defined by this // file can interrupt other ELF file's symbols at runtime. - for (const Symbol *S : Symtab::X->getSymbols()) { - if (auto *U = dyn_cast_or_null(S->body())) { - StringRef Name = U->getName(); - for (StringRef Prefix : {"__start_", "__stop_"}) - if (Name.startswith(Prefix)) - UsedStartStopNames.insert(Name.substr(Prefix.size())); - } else if (S->includeInDynsym()) { + for (const Symbol *S : Symtab::X->getSymbols()) + if (S->includeInDynsym()) MarkSymbol(S->body()); - } - } // Preserve special sections and those which are specified in linker // script KEEP command. @@ -248,9 +247,12 @@ // referred by .eh_frame here. if (auto *EH = dyn_cast_or_null>(Sec)) scanEhFrameSection(*EH, Enqueue); - if (isReserved(Sec) || Script::X->shouldKeep(Sec) || - UsedStartStopNames.count(Sec->Name)) + if (isReserved(Sec) || Script::X->shouldKeep(Sec)) Enqueue({Sec, 0}); + else if (isValidCIdentifier(Sec->Name)) { + CNamedSections[Saver.save("__start_" + Sec->Name)].push_back(Sec); + CNamedSections[Saver.save("__end_" + Sec->Name)].push_back(Sec); + } } // Mark all reachable sections. Index: test/ELF/linkerscript/sections-gc2.s =================================================================== --- test/ELF/linkerscript/sections-gc2.s +++ test/ELF/linkerscript/sections-gc2.s @@ -25,7 +25,7 @@ .quad 0 .section used_in_script,"a" - .quad 0 + .quad __start_used_in_script .section used_in_reloc,"a" .quad 0