diff options
author | Rui Ueyama <ruiu@google.com> | 2017-10-10 22:59:32 +0000 |
---|---|---|
committer | Rui Ueyama <ruiu@google.com> | 2017-10-10 22:59:32 +0000 |
commit | a1b79dff2af6b739d047d6b43c24e287724cd637 (patch) | |
tree | 65d0bb13c93014e58332f840c876c017b15ceb0f | |
parent | e9ea08a0974a429c47e060f8ac7e18a80ed1c543 (diff) | |
download | bcm5719-llvm-a1b79dff2af6b739d047d6b43c24e287724cd637.tar.gz bcm5719-llvm-a1b79dff2af6b739d047d6b43c24e287724cd637.zip |
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.
llvm-svn: 315384
-rw-r--r-- | lld/ELF/Driver.cpp | 3 | ||||
-rw-r--r-- | lld/ELF/InputFiles.cpp | 14 | ||||
-rw-r--r-- | lld/ELF/InputSection.cpp | 17 | ||||
-rw-r--r-- | lld/ELF/MarkLive.cpp | 38 | ||||
-rw-r--r-- | lld/ELF/SyntheticSections.cpp | 9 |
5 files changed, 47 insertions, 34 deletions
diff --git a/lld/ELF/Driver.cpp b/lld/ELF/Driver.cpp index 61bf93def89..fea7fb552c4 100644 --- a/lld/ELF/Driver.cpp +++ b/lld/ELF/Driver.cpp @@ -1106,8 +1106,7 @@ template <class ELFT> void LinkerDriver::link(opt::InputArgList &Args) { // 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>(); diff --git a/lld/ELF/InputFiles.cpp b/lld/ELF/InputFiles.cpp index 3bf9a39b0e2..69930d0e49a 100644 --- a/lld/ELF/InputFiles.cpp +++ b/lld/ELF/InputFiles.cpp @@ -482,20 +482,6 @@ InputSectionBase *ObjFile<ELFT>::createInputSection(const Elf_Shdr &Sec) { 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. diff --git a/lld/ELF/InputSection.cpp b/lld/ELF/InputSection.cpp index 2b883d5886a..b63c09a7ba7 100644 --- a/lld/ELF/InputSection.cpp +++ b/lld/ELF/InputSection.cpp @@ -76,22 +76,6 @@ static ArrayRef<uint8_t> getSectionContents(ObjFile<ELFT> *File, 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(InputFile *File, uint64_t Flags, : 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; diff --git a/lld/ELF/MarkLive.cpp b/lld/ELF/MarkLive.cpp index 8579b148a1b..e710374e430 100644 --- a/lld/ELF/MarkLive.cpp +++ b/lld/ELF/MarkLive.cpp @@ -186,7 +186,7 @@ template <class ELFT> static bool isReserved(InputSectionBase *Sec) { // 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>(); diff --git a/lld/ELF/SyntheticSections.cpp b/lld/ELF/SyntheticSections.cpp index bc76c9648b2..44ee6e1c209 100644 --- a/lld/ELF/SyntheticSections.cpp +++ b/lld/ELF/SyntheticSections.cpp @@ -1831,6 +1831,7 @@ std::vector<std::vector<uint32_t>> GdbIndexSection::createCuVectors() { } 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 *elf::createGdbIndex() { 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)); } |