diff --git a/lld/ELF/MarkLive.cpp b/lld/ELF/MarkLive.cpp index 308357b81eaa74d7e9921c0652940d21a8d4de9b..2551557d01d558c7e4923051982a6afa18091d43 100644 --- a/lld/ELF/MarkLive.cpp +++ b/lld/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 @@ static typename ELFT::uint getAddend(InputSectionBase &Sec, 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 @@ template static bool isReserved(InputSectionBase *Sec) { // 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 @@ template void elf::markLive() { 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 @@ template void elf::markLive() { // 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. diff --git a/lld/test/ELF/linkerscript/sections-gc2.s b/lld/test/ELF/linkerscript/sections-gc2.s index 4f4b022a476e6cef7149803a5eb950a3017fe292..e2941aa57ed643a4113e3d2aba95ee042b6d0923 100644 --- a/lld/test/ELF/linkerscript/sections-gc2.s +++ b/lld/test/ELF/linkerscript/sections-gc2.s @@ -25,7 +25,7 @@ _start: .quad 0 .section used_in_script,"a" - .quad 0 + .quad __start_used_in_script .section used_in_reloc,"a" .quad 0