blob: b7063c6ebc5eb04bf63d8a276f1f19473bfe8105 [file] [log] [blame]
commit 60ce444eaa146bc2f762c70d433d4a0c847508f0
Author: Fangrui Song <maskray@google.com>
Date: Fri Dec 6 16:26:55 2019 -0800
[ELF] Refine section group --gc-sections rules to not discard .debug_types
clang/gcc -fdebug-type-sections places .debug_types and
.rela.debug_types in a section group, with a signature symbol which
represents the type signature. The section group is for deduplication
purposes.
After D70146, we will discard such section groups. Refine the rule so
that we will retain the group if no member has the SHF_ALLOC flag.
GNU ld has a similar rule to retain the group if all members have the
SEC_DEBUGGING flag. We try to be more general for future-proof purposes:
if other non-SHF_ALLOC sections have deduplication needs, they may be
placed in a section group. Don't discard them.
Reviewed By: grimar
Differential Revision: https://reviews.llvm.org/D71157
diff --git a/lld/ELF/InputFiles.cpp b/lld/ELF/InputFiles.cpp
index 7dc72361abd..d732f0d2564 100644
--- a/lld/ELF/InputFiles.cpp
+++ b/lld/ELF/InputFiles.cpp
@@ -497,6 +497,42 @@ static void addDependentLibrary(StringRef specifier, const InputFile *f) {
specifier);
}
+template <class ELFT>
+static void handleSectionGroup(ArrayRef<InputSectionBase *> sections,
+ ArrayRef<typename ELFT::Word> entries) {
+ bool hasAlloc = false;
+ for (uint32_t index : entries.slice(1)) {
+ if (index >= sections.size())
+ return;
+ if (InputSectionBase *s = sections[index])
+ if (s != &InputSection::discarded && s->flags & SHF_ALLOC)
+ hasAlloc = true;
+ }
+
+ // If any member has the SHF_ALLOC flag, the whole group is subject to garbage
+ // collection. See the comment in markLive(). This rule retains .debug_types
+ // and .rela.debug_types.
+ if (!hasAlloc)
+ return;
+
+ // Connect the members in a circular doubly-linked list via
+ // nextInSectionGroup.
+ InputSectionBase *head;
+ InputSectionBase *prev = nullptr;
+ for (uint32_t index : entries.slice(1)) {
+ InputSectionBase *s = sections[index];
+ if (!s || s == &InputSection::discarded)
+ continue;
+ if (prev)
+ prev->nextInSectionGroup = s;
+ else
+ head = s;
+ prev = s;
+ }
+ if (prev)
+ prev->nextInSectionGroup = head;
+}
+
template <class ELFT>
void ObjFile<ELFT>::initializeSections(bool ignoreComdats) {
const ELFFile<ELFT> &obj = this->getObj();
@@ -615,26 +651,8 @@ void ObjFile<ELFT>::initializeSections(bool ignoreComdats) {
toString(linkSec));
}
- // For each secion group, connect its members in a circular doubly-linked list
- // via nextInSectionGroup. See the comment in markLive().
- for (ArrayRef<Elf_Word> entries : selectedGroups) {
- InputSectionBase *head;
- InputSectionBase *prev = nullptr;
- for (uint32_t secIndex : entries.slice(1)) {
- if (secIndex >= this->sections.size())
- continue;
- InputSectionBase *s = this->sections[secIndex];
- if (!s || s == &InputSection::discarded)
- continue;
- if (prev)
- prev->nextInSectionGroup = s;
- else
- head = s;
- prev = s;
- }
- if (prev)
- prev->nextInSectionGroup = head;
- }
+ for (ArrayRef<Elf_Word> entries : selectedGroups)
+ handleSectionGroup<ELFT>(this->sections, entries);
}
// For ARM only, to set the EF_ARM_ABI_FLOAT_SOFT or EF_ARM_ABI_FLOAT_HARD
diff --git a/lld/test/ELF/gc-sections-group-debug.s b/lld/test/ELF/gc-sections-group-debug.s
new file mode 100644
index 00000000000..959e10d4968
--- /dev/null
+++ b/lld/test/ELF/gc-sections-group-debug.s
@@ -0,0 +1,12 @@
+# REQUIRES: x86
+## Check that group members are retained, if no member has the SHF_ALLOC flag.
+## This rule retains .debug_types and .rela.debug_types emitted by clang/gcc.
+
+# RUN: llvm-mc -filetype=obj -triple=x86_64 %s -o %t.o
+# RUN: ld.lld --gc-sections %t.o -o %t
+# RUN: llvm-readobj -S %t | FileCheck %s
+
+# CHECK: Name: .debug_types
+
+.section .debug_types,"G",@progbits,abcd,comdat
+.quad .debug_types
diff --git a/lld/test/ELF/gc-sections-group.s b/lld/test/ELF/gc-sections-group.s
index ad4e313f84e..8f713f5cf1e 100644
--- a/lld/test/ELF/gc-sections-group.s
+++ b/lld/test/ELF/gc-sections-group.s
@@ -1,7 +1,7 @@
# REQUIRES: x86
## Check that group members are retained or discarded as a unit, and
-## non-SHF_ALLOC sections in a group are subject to garbage collection.
-## This is compatible with GNU ld.
+## non-SHF_ALLOC sections in a group are subject to garbage collection,
+## if at least one member has the SHF_ALLOC flag.
# RUN: llvm-mc -filetype=obj -triple=x86_64 %s -o %t.o
# RUN: ld.lld --gc-sections %t.o -o %t.dead