diff options
Diffstat (limited to 'lld/ELF/MarkLive.cpp')
| -rw-r--r-- | lld/ELF/MarkLive.cpp | 23 |
1 files changed, 15 insertions, 8 deletions
diff --git a/lld/ELF/MarkLive.cpp b/lld/ELF/MarkLive.cpp index 8f75de6dc30..9528708b584 100644 --- a/lld/ELF/MarkLive.cpp +++ b/lld/ELF/MarkLive.cpp @@ -170,12 +170,7 @@ template <class ELFT> static bool isReserved(InputSectionBase *Sec) { if (!(Sec->Flags & SHF_ALLOC)) return true; - // We do not want to reclaim sections if they can be referred - // by __start_* and __stop_* symbols. StringRef S = Sec->Name; - if (isValidCIdentifier(S)) - return true; - return S.startswith(".ctors") || S.startswith(".dtors") || S.startswith(".init") || S.startswith(".fini") || S.startswith(".jcr"); @@ -226,11 +221,22 @@ template <class ELFT> void elf::markLive() { for (StringRef S : Config->Undefined) MarkSymbol(Symtab<ELFT>::X->find(S)); + // Remember which __start_* or __stop_* symbols are used so that we don't gc + // those sections. + DenseSet<StringRef> 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<ELFT>::X->getSymbols()) - if (S->includeInDynsym()) + for (const Symbol *S : Symtab<ELFT>::X->getSymbols()) { + if (auto *U = dyn_cast_or_null<Undefined>(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()) { MarkSymbol(S->body()); + } + } // Preserve special sections and those which are specified in linker // script KEEP command. @@ -240,7 +246,8 @@ template <class ELFT> void elf::markLive() { // referred by .eh_frame here. if (auto *EH = dyn_cast_or_null<EhInputSection<ELFT>>(Sec)) scanEhFrameSection<ELFT>(*EH, Enqueue); - if (isReserved<ELFT>(Sec) || Script<ELFT>::X->shouldKeep(Sec)) + if (isReserved<ELFT>(Sec) || Script<ELFT>::X->shouldKeep(Sec) || + UsedStartStopNames.count(Sec->Name)) Enqueue({Sec, 0}); } |

