diff --git a/lld/ELF/MarkLive.cpp b/lld/ELF/MarkLive.cpp --- a/lld/ELF/MarkLive.cpp +++ b/lld/ELF/MarkLive.cpp @@ -291,14 +291,31 @@ // GOT, which means that the ifunc must be available when the main partition is // loaded) and TLS symbols (because we only know how to correctly process TLS // relocations for the main partition). +// +// We also need to move sections whose names are C identifiers that are referred +// to from __start_/__stop_ symbols because there will only be one set of +// symbols for the whole program. template void MarkLive::moveToMain() { - for (InputFile *file : objectFiles) - for (Symbol *s : file->getSymbols()) + StringSet<> startStopSymbolNames; + for (InputFile *file : objectFiles) { + for (Symbol *s : file->getSymbols()) { if (auto *d = dyn_cast(s)) if ((d->type == STT_GNU_IFUNC || d->type == STT_TLS) && d->section && d->section->isLive()) markSymbol(s); + StringRef name = s->getName(); + if (name.startswith("__start_")) + startStopSymbolNames.insert(name.substr(8)); + else if (name.startswith("__stop_")) + startStopSymbolNames.insert(name.substr(7)); + } + } + + for (InputSectionBase *sec : inputSections) + if (sec->isLive() && startStopSymbolNames.count(sec->name)) + enqueue(sec, 0); + mark(); }