[lld] r315384 - Handle input section liveness only in MarkLive.cpp.

Rui Ueyama via llvm-commits llvm-commits at lists.llvm.org
Tue Oct 10 15:59:32 PDT 2017


Author: ruiu
Date: Tue Oct 10 15:59:32 2017
New Revision: 315384

URL: http://llvm.org/viewvc/llvm-project?rev=315384&view=rev
Log:
Handle input section liveness only in MarkLive.cpp.

The condition whether a section is alive or not by default
is becoming increasingly complex, so the decision of garbage
collection is spreading over InputSection.h and MarkLive.cpp,
which is not a good state.

This moves the code to MarkLive.cpp, to keep the file the central
place to make decisions about garbage collection.

Modified:
    lld/trunk/ELF/Driver.cpp
    lld/trunk/ELF/InputFiles.cpp
    lld/trunk/ELF/InputSection.cpp
    lld/trunk/ELF/MarkLive.cpp
    lld/trunk/ELF/SyntheticSections.cpp

Modified: lld/trunk/ELF/Driver.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Driver.cpp?rev=315384&r1=315383&r2=315384&view=diff
==============================================================================
--- lld/trunk/ELF/Driver.cpp (original)
+++ lld/trunk/ELF/Driver.cpp Tue Oct 10 15:59:32 2017
@@ -1106,8 +1106,7 @@ template <class ELFT> void LinkerDriver:
 
   // Do size optimizations: garbage collection, merging of SHF_MERGE sections
   // and identical code folding.
-  if (Config->GcSections)
-    markLive<ELFT>();
+  markLive<ELFT>();
   decompressAndMergeSections();
   if (Config->ICF)
     doIcf<ELFT>();

Modified: lld/trunk/ELF/InputFiles.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/InputFiles.cpp?rev=315384&r1=315383&r2=315384&view=diff
==============================================================================
--- lld/trunk/ELF/InputFiles.cpp (original)
+++ lld/trunk/ELF/InputFiles.cpp Tue Oct 10 15:59:32 2017
@@ -482,20 +482,6 @@ InputSectionBase *ObjFile<ELFT>::createI
   if (Config->Strip != StripPolicy::None && Name.startswith(".debug"))
     return &InputSection::Discarded;
 
-  // If -gdb-index is given, LLD creates .gdb_index section, and that
-  // section serves the same purpose as .debug_gnu_pub{names,types} sections.
-  // If that's the case, we want to eliminate .debug_gnu_pub{names,types}
-  // because they are redundant and can waste large amount of disk space
-  // (for example, they are about 400 MiB in total for a clang debug build.)
-  // We still create the section and mark it dead so that the gdb index code
-  // can use the InputSection to access the data.
-  if (Config->GdbIndex &&
-      (Name == ".debug_gnu_pubnames" || Name == ".debug_gnu_pubtypes")) {
-    auto *Ret = make<InputSection>(this, &Sec, Name);
-    Script->discard({Ret});
-    return Ret;
-  }
-
   // The linkonce feature is a sort of proto-comdat. Some glibc i386 object
   // files contain definitions of symbol "__x86.get_pc_thunk.bx" in linkonce
   // sections. Drop those sections to avoid duplicate symbol errors.

Modified: lld/trunk/ELF/InputSection.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/InputSection.cpp?rev=315384&r1=315383&r2=315384&view=diff
==============================================================================
--- lld/trunk/ELF/InputSection.cpp (original)
+++ lld/trunk/ELF/InputSection.cpp Tue Oct 10 15:59:32 2017
@@ -76,22 +76,6 @@ static ArrayRef<uint8_t> getSectionConte
   return check(File->getObj().getSectionContents(Hdr));
 }
 
-// Return true if a section with given section flags is live (will never be
-// GCed) by default. If a section can be GCed, this function returns false.
-static bool isLiveByDefault(uint64_t Flags, uint32_t Type) {
-  // If GC is enabled, all memory-mapped sections are subject of GC.
-  if (!Config->GcSections)
-    return true;
-  if (Flags & SHF_ALLOC)
-    return false;
-
-  // Besides that, relocation sections can also be GCed because their
-  // relocation target sections may be GCed. This doesn't really matter
-  // in most cases because the linker usually consumes relocation
-  // sections instead of emitting them, but -emit-reloc needs this.
-  return Type != SHT_REL && Type != SHT_RELA;
-}
-
 InputSectionBase::InputSectionBase(InputFile *File, uint64_t Flags,
                                    uint32_t Type, uint64_t Entsize,
                                    uint32_t Link, uint32_t Info,
@@ -100,7 +84,6 @@ InputSectionBase::InputSectionBase(Input
     : SectionBase(SectionKind, Name, Flags, Entsize, Alignment, Type, Info,
                   Link),
       File(File), Data(Data), Repl(this) {
-  Live = isLiveByDefault(Flags, Type);
   Assigned = false;
   NumRelocations = 0;
   AreRelocsRela = false;

Modified: lld/trunk/ELF/MarkLive.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/MarkLive.cpp?rev=315384&r1=315383&r2=315384&view=diff
==============================================================================
--- lld/trunk/ELF/MarkLive.cpp (original)
+++ lld/trunk/ELF/MarkLive.cpp Tue Oct 10 15:59:32 2017
@@ -186,7 +186,7 @@ template <class ELFT> static bool isRese
 // This is the main function of the garbage collector.
 // Starting from GC-root sections, this function visits all reachable
 // sections to set their "Live" bits.
-template <class ELFT> void elf::markLive() {
+template <class ELFT> static void doGcSections() {
   SmallVector<InputSection *, 256> Q;
   CNamedSections.clear();
 
@@ -261,6 +261,42 @@ template <class ELFT> void elf::markLive
     forEachSuccessor<ELFT>(*Q.pop_back_val(), Enqueue);
 }
 
+// Before calling this function, Live bits are off for all
+// input sections. This function make some or all of them on
+// so that they are emitted to the output file.
+template <class ELFT> void elf::markLive() {
+  // If -gc-sections is missing, no sections are removed.
+  if (!Config->GcSections) {
+    for (InputSectionBase *Sec : InputSections)
+      Sec->Live = true;
+    return;
+  }
+
+  // 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.
+  //
+  // Non 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.)
+  //
+  // 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.
+  for (InputSectionBase *Sec : InputSections) {
+    bool IsAlloc = (Sec->Flags & SHF_ALLOC);
+    bool IsRel = (Sec->Type == SHT_REL || Sec->Type == SHT_RELA);
+    if (!IsAlloc && !IsRel)
+      Sec->Live = true;
+  }
+
+  // Follow the graph to mark all live sections.
+  doGcSections<ELFT>();
+}
+
 template void elf::markLive<ELF32LE>();
 template void elf::markLive<ELF32BE>();
 template void elf::markLive<ELF64LE>();

Modified: lld/trunk/ELF/SyntheticSections.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/SyntheticSections.cpp?rev=315384&r1=315383&r2=315384&view=diff
==============================================================================
--- lld/trunk/ELF/SyntheticSections.cpp (original)
+++ lld/trunk/ELF/SyntheticSections.cpp Tue Oct 10 15:59:32 2017
@@ -1831,6 +1831,7 @@ std::vector<std::vector<uint32_t>> GdbIn
 }
 
 template <class ELFT> GdbIndexSection *elf::createGdbIndex() {
+  // Gather debug info to create a .gdb_index section.
   std::vector<InputSection *> Sections = getDebugInfoSections();
   std::vector<GdbIndexChunk> Chunks(Sections.size());
 
@@ -1844,6 +1845,14 @@ template <class ELFT> GdbIndexSection *e
     Chunks[I].NamesAndTypes = readPubNamesAndTypes(Dwarf);
   });
 
+  // .debug_gnu_pub{names,types} are useless in executables.
+  // They are present in input object files solely for creating
+  // a .gdb_index. So we can remove it from the output.
+  for (InputSectionBase *S : InputSections)
+    if (S->Name == ".debug_gnu_pubnames" || S->Name == ".debug_gnu_pubtypes")
+      S->Live = false;
+
+  // Create a .gdb_index and returns it.
   return make<GdbIndexSection>(std::move(Chunks));
 }
 




More information about the llvm-commits mailing list