summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRui Ueyama <ruiu@google.com>2017-10-10 22:59:32 +0000
committerRui Ueyama <ruiu@google.com>2017-10-10 22:59:32 +0000
commita1b79dff2af6b739d047d6b43c24e287724cd637 (patch)
tree65d0bb13c93014e58332f840c876c017b15ceb0f
parente9ea08a0974a429c47e060f8ac7e18a80ed1c543 (diff)
downloadbcm5719-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.cpp3
-rw-r--r--lld/ELF/InputFiles.cpp14
-rw-r--r--lld/ELF/InputSection.cpp17
-rw-r--r--lld/ELF/MarkLive.cpp38
-rw-r--r--lld/ELF/SyntheticSections.cpp9
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));
}
OpenPOWER on IntegriCloud