summaryrefslogtreecommitdiff
path: root/lld/ELF/MarkLive.cpp
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
commit71560db925acf3ee0ee9a17be394bddeace53f13 (patch)
tree57fcd4077fa2b5721815c04b9b220607a678b24d /lld/ELF/MarkLive.cpp
parent4aa8db9232d95cf654ceb909d3406a5fe6b30bd5 (diff)
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.
Diffstat (limited to 'lld/ELF/MarkLive.cpp')
-rw-r--r--lld/ELF/MarkLive.cpp38
1 files changed, 37 insertions, 1 deletions
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>();