[lld] 3f90918 - [ELF] --gc-sections: collect unused .gcc_except_table in section groups and associated text sections

Fangrui Song via llvm-commits llvm-commits at lists.llvm.org
Tue Nov 17 09:11:26 PST 2020


Author: Fangrui Song
Date: 2020-11-17T09:11:20-08:00
New Revision: 3f9091888656ff3aabf677caac6054b3fd4eaa0d

URL: https://github.com/llvm/llvm-project/commit/3f9091888656ff3aabf677caac6054b3fd4eaa0d
DIFF: https://github.com/llvm/llvm-project/commit/3f9091888656ff3aabf677caac6054b3fd4eaa0d.diff

LOG: [ELF] --gc-sections: collect unused .gcc_except_table in section groups and associated text sections

`try ... catch` in an inline function produces `.gcc_except_table.*` in a COMDAT
group with GCC or newer Clang (since D83655). For --gc-sections, currently we
scan `.eh_frame` pieces and mark liveness of such a `.gcc_except_table.*` and
then the associated `.text.*` (if a member in a section group is retained, the
others should be retained as well).

Essentially all `.text.*` and `.gcc_except_table.*` compiled from inline
functions with `try ... catch` cannot be discarded by the imprecise
--gc-sections.  Compared with the state before D83655, the output
`.gcc_except_table` is smaller (non-prevailing copies in COMDAT groups can now
be discarded) but `.text` may be larger, i.e. size regression.

This patch teaches the .eh_frame piece scanning code to not mark
`.gcc_except_table` in a section group, thus allow unused `.text.*` and
`.gcc_except_table.*` in a section group to be discarded.

Note, non-group `.gcc_except_table` can still not be discarded. That is the status quo.

Reviewed By: grimar, echristo

Differential Revision: https://reviews.llvm.org/D91579

Added: 
    

Modified: 
    lld/ELF/MarkLive.cpp
    lld/test/ELF/gc-sections-lsda.s

Removed: 
    


################################################################################
diff  --git a/lld/ELF/MarkLive.cpp b/lld/ELF/MarkLive.cpp
index fe5d32c80bfe..2c350e275e6c 100644
--- a/lld/ELF/MarkLive.cpp
+++ b/lld/ELF/MarkLive.cpp
@@ -56,7 +56,7 @@ template <class ELFT> class MarkLive {
   void mark();
 
   template <class RelTy>
-  void resolveReloc(InputSectionBase &sec, RelTy &rel, bool isLSDA);
+  void resolveReloc(InputSectionBase &sec, RelTy &rel, bool fromFDE);
 
   template <class RelTy>
   void scanEhFrameSection(EhInputSection &eh, ArrayRef<RelTy> rels);
@@ -89,7 +89,7 @@ static uint64_t getAddend(InputSectionBase &sec,
 template <class ELFT>
 template <class RelTy>
 void MarkLive<ELFT>::resolveReloc(InputSectionBase &sec, RelTy &rel,
-                                  bool isLSDA) {
+                                  bool fromFDE) {
   Symbol &sym = sec.getFile<ELFT>()->getRelocTargetSym(rel);
 
   // If a symbol is referenced in a live section, it is used.
@@ -104,7 +104,16 @@ void MarkLive<ELFT>::resolveReloc(InputSectionBase &sec, RelTy &rel,
     if (d->isSection())
       offset += getAddend<ELFT>(sec, rel);
 
-    if (!isLSDA || !(relSec->flags & SHF_EXECINSTR))
+    // fromFDE being true means this is referenced by a FDE in a .eh_frame
+    // piece. The relocation points to the described function or to a LSDA. We
+    // only need to keep the LSDA live, so ignore anything that points to
+    // executable sections. If the LSDA is in a section group, we ignore the
+    // relocation as well because (a) if the associated text section is live,
+    // the LSDA will be retained due to section group rules (b) if the
+    // associated text section should be discarded, marking the LSDA will
+    // unnecessarily retain the text section.
+    if (!(fromFDE &&
+          ((relSec->flags & SHF_EXECINSTR) || relSec->nextInSectionGroup)))
       enqueue(relSec, offset);
     return;
   }
@@ -148,9 +157,6 @@ void MarkLive<ELFT>::scanEhFrameSection(EhInputSection &eh,
       continue;
     }
 
-    // This is a FDE. The relocations point to the described function or to
-    // a LSDA. We only need to keep the LSDA alive, so ignore anything that
-    // points to executable sections.
     uint64_t pieceEnd = piece.inputOff + piece.size;
     for (size_t j = firstRelI, end2 = rels.size();
          j < end2 && rels[j].r_offset < pieceEnd; ++j)

diff  --git a/lld/test/ELF/gc-sections-lsda.s b/lld/test/ELF/gc-sections-lsda.s
index 701c6a7b3b21..9889cd0e7a13 100644
--- a/lld/test/ELF/gc-sections-lsda.s
+++ b/lld/test/ELF/gc-sections-lsda.s
@@ -1,21 +1,48 @@
-// REQUIRES: x86
-
-// RUN: llvm-mc %s -o %t.o -filetype=obj -triple=x86_64-pc-linux
-// RUN: ld.lld -shared --gc-sections %t.o -o %t
-
-// Test that we handle .eh_frame keeping sections alive. We could be more
-// precise and gc the entire contents of this file, but test that at least
-// we are consistent: if we keep .abc, we have to keep .foo
-
-// RUN: llvm-readobj -S %t | FileCheck %s
-// CHECK:  Name: .abc
-// CHECK: Name: .foo
-
-        .cfi_startproc
-        .cfi_lsda 0x1b,zed
-        .cfi_endproc
-        .section        .abc,"a"
-zed:
-        .long   bar-.
-        .section        .foo,"ax"
-bar:
+# REQUIRES: x86
+# RUN: llvm-mc %s -o %t.o -filetype=obj -triple=x86_64-pc-linux
+
+## Discard an unused .gcc_except_table in a COMDAT group if the associated text
+## section is discarded.
+
+# RUN: ld.lld --gc-sections --print-gc-sections -u _Z3foov %t.o -o /dev/null | \
+# RUN:   FileCheck %s --implicit-check-not=.gcc_except_table
+
+# CHECK:      removing unused section {{.*}}.o:(.text._Z6comdatv)
+# CHECK-NEXT: removing unused section {{.*}}.o:(.gcc_except_table._Z6comdatv)
+
+## An unused non-group .gcc_except_table is not discarded.
+
+# RUN: ld.lld --gc-sections --print-gc-sections -u _Z6comdatv %t.o -o /dev/null | \
+# RUN:   FileCheck /dev/null --implicit-check-not=.gcc_except_table
+
+## If the text sections are live, the .gcc_except_table sections are retained as
+## well because they are referenced by .eh_frame pieces.
+
+# RUN: ld.lld --gc-sections --print-gc-sections -u _Z3foov -u _Z6comdatv %t.o -o /dev/null | \
+# RUN:   FileCheck %s --check-prefix=KEEP
+
+# KEEP-NOT: .gcc_except_table
+
+.section .text._Z3foov,"ax", at progbits
+.globl _Z3foov
+_Z3foov:
+  .cfi_startproc
+  ret
+  .cfi_lsda 0x1b,.Lexception0
+  .cfi_endproc
+
+.section .text._Z6comdatv,"axG", at progbits,_Z6comdatv,comdat
+.globl _Z6comdatv
+_Z6comdatv:
+  .cfi_startproc
+  ret
+  .cfi_lsda 0x1b,.Lexception1
+  .cfi_endproc
+
+.section .gcc_except_table._Z3foov,"a", at progbits
+.Lexception0:
+  .byte 255
+
+.section .gcc_except_table._Z6comdatv,"aG", at progbits,_Z6comdatv,comdat
+.Lexception1:
+  .byte 255


        


More information about the llvm-commits mailing list