diff --git a/lld/ELF/InputFiles.h b/lld/ELF/InputFiles.h --- a/lld/ELF/InputFiles.h +++ b/lld/ELF/InputFiles.h @@ -234,8 +234,10 @@ // but had one or more functions with the no_split_stack attribute. bool SomeNoSplitStack = false; - // True if the file has any live Regular or Merge sections that aren't - // the LDSA section. + // True if the garbage-collector marks at least one "real" section, + // e.g. a code or data section except a exception handler table. + // If false, we discard debug sections of this file because we know + // all sections described by the debug sections are dead. bool HasLiveCodeOrData = false; // Pointer to this input file's .llvm_addrsig section, if it has one. diff --git a/lld/ELF/MarkLive.cpp b/lld/ELF/MarkLive.cpp --- a/lld/ELF/MarkLive.cpp +++ b/lld/ELF/MarkLive.cpp @@ -184,19 +184,19 @@ if (auto *MS = dyn_cast(Sec)) MS->getSectionPiece(Offset)->Live = true; - InputSection *S = dyn_cast(Sec); // LSDA does not count as "live code or data" in the object file. // The section may already have been marked live for LSDA in which // case we still need to mark the file. - if (S && !IsLSDA && Sec->File) + if (Sec->File && !IsLSDA) Sec->getFile()->HasLiveCodeOrData = true; if (Sec->Live) return; Sec->Live = true; + // Add input section to the queue. - if (S) + if (InputSection *S = dyn_cast(Sec)) Queue.push_back(S); } @@ -288,44 +288,53 @@ return; } - // Otheriwse, do mark-sweep GC. - // - // The -gc-sections option works only for SHF_ALLOC sections - // (sections that are memory-mapped at runtime). So we can - // unconditionally make non-SHF_ALLOC sections alive except - // SHF_LINK_ORDER and SHT_REL/SHT_RELA sections and .debug sections. + // Otheriwse, do mark-sweep GC. Follow the graph to mark all live + // sections. + MarkLive().run(); + + // Usually, non-SHF_ALLOC sections are not garbage-collected even if + // they are unreachable. It's because reachability is not a good + // signal whether they are garbage or not. Here are a few examples: // - // Usually, SHF_ALLOC sections are not removed even if they are - // unreachable through relocations because reachability is not - // a good signal whether they are garbage or not (e.g. there is - // usually no section referring to a .comment section, but we - // want to keep it.). + // - A .comment section contains some ASCII text. There is usually no + // section referring from/to a .comment section, but we want to + // keep it to not surprise users. // - // Note on SHF_LINK_ORDER: Such sections contain metadata and they - // have a reverse dependency on the InputSection they are linked with. - // We are able to garbage collect them. + // - An object file usually contains only one .debug section + // describing all functions and data in the same object file, even + // if the object file is compiled with -f{function,data}-sections. + // There is no relocation from code/data sections to a debug + // section, but a debug section contains lots of relocations to + // code/data sections (so this is a reverse dependency). If at + // least one code/data is live, we want to keep the entire debug + // info. // - // Note on SHF_REL{,A}: Such sections reach here only when -r - // or -emit-reloc were given. And they are subject of garbage - // collection because, if we remove a text section, we also - // remove its relocation section. + // Here, we mark non-SHF_ALLOC sections. for (InputSectionBase *Sec : InputSections) { - bool IsAlloc = (Sec->Flags & SHF_ALLOC); - bool IsLinkOrder = (Sec->Flags & SHF_LINK_ORDER); - bool IsRel = (Sec->Type == SHT_REL || Sec->Type == SHT_RELA); + if (Sec->Flags & SHF_ALLOC) + continue; - if (!IsAlloc && !IsLinkOrder && !IsRel && !Sec->Debug) - Sec->Live = true; - } + // If a file does not contain any live code nor data, we want to + // discard debug sections as they are completely useless. + if (Sec->File && !Sec->getFile()->HasLiveCodeOrData && + Sec->Debug) + continue; - // Follow the graph to mark all live sections. - MarkLive().run(); + // SHF_LINK_ORDER sections contain metadata and they have a + // reverse dependency on the InputSection they are linked with. + // We are able to garbage collect them. + if (Sec->Flags & SHF_LINK_ORDER) + continue; - // Mark debug sections as live in any object file that has a live - // Regular or Merge section. - for (InputSectionBase *Sec : InputSections) - if (Sec->Debug && Sec->getFile()->HasLiveCodeOrData) - Sec->Live = true; + // SHT_REL sections sections reach here only when -r or + // -emit-reloc were given. And they are subject of garbage + // collection because, if we remove a text section, we also + // remove its relocation section. + if (Sec->Type == SHT_REL || Sec->Type == SHT_RELA) + continue; + + Sec->Live = true; + } // Report garbage-collected sections. if (Config->PrintGcSections)