[lld] 60ce444 - [ELF] Refine section group --gc-sections rules to not discard .debug_types

Fangrui Song via llvm-commits llvm-commits at lists.llvm.org
Tue Dec 10 09:01:28 PST 2019


Author: Fangrui Song
Date: 2019-12-10T09:00:58-08:00
New Revision: 60ce444eaa146bc2f762c70d433d4a0c847508f0

URL: https://github.com/llvm/llvm-project/commit/60ce444eaa146bc2f762c70d433d4a0c847508f0
DIFF: https://github.com/llvm/llvm-project/commit/60ce444eaa146bc2f762c70d433d4a0c847508f0.diff

LOG: [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

Added: 
    lld/test/ELF/gc-sections-group-debug.s

Modified: 
    lld/ELF/InputFiles.cpp
    lld/test/ELF/gc-sections-group.s

Removed: 
    


################################################################################
diff  --git a/lld/ELF/InputFiles.cpp b/lld/ELF/InputFiles.cpp
index 7dc72361abd7..d732f0d2564b 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 000000000000..959e10d49681
--- /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", at 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 ad4e313f84e7..8f713f5cf1e4 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


        


More information about the llvm-commits mailing list