[lld] ed399d5 - [ELF] Make SHF_GNU_RETAIN sections GC roots

Fangrui Song via llvm-commits llvm-commits at lists.llvm.org
Thu Feb 4 09:23:07 PST 2021


Author: Fangrui Song
Date: 2021-02-04T09:23:01-08:00
New Revision: ed399d508ff6e0df657e251afe936fac713ff417

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

LOG: [ELF] Make SHF_GNU_RETAIN sections GC roots

binutils 2.36 introduced the new section flag SHF_GNU_RETAIN (for ELFOSABI_GNU &
ELFOSABI_FREEBSD) to mark a sections as a GC root. Several LLVM side toolchain
folks (including me) were involved in the design process of SHF_GNU_RETAIN and
were happy with this proposal.

Currently GNU ld only respects SHF_GNU_RETAIN semantics for ELFOSABI_GNU &
ELFOSABI_FREEBSD object files
(https://sourceware.org/bugzilla/show_bug.cgi?id=27282).  GNU ld sets EI_OSABI
to ELFOSABI_GNU for relocatable output
(https://sourceware.org/bugzilla/show_bug.cgi?id=27091). In practice the single
value EI_OSABI is neither a good indicator for object file compatibility, nor a
useful mechanism marking used ELF extensions.

For input, we respect SHF_GNU_RETAIN semantics even for ELFOSABI_NONE object
files. This is compatible with how LLD and GNU ld handle (mildly useful) STT_GNU_IFUNC
/ (emitted by GCC, considered misfeature by some folks) STB_GNU_UNIQUE input.
(As of LLVM 12.0.0, the integrated assembler does not set ELFOSABI_GNU for
STT_GNU_IFUNC/STB_GNU_UNIQUE).
Arguably STT_GNU_IFUNC/STB_GNU_UNIQUE probably need indicators in object files
but SHF_GNU_RETAIN is more likely accepted by more OSABI platforms.

For output, we take a step further than GNU ld: we don't promote ELFOSABI_NONE
to ELFOSABI_GNU for all output.

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

Added: 
    lld/test/ELF/gc-sections-retain.s

Modified: 
    lld/ELF/MarkLive.cpp

Removed: 
    


################################################################################
diff  --git a/lld/ELF/MarkLive.cpp b/lld/ELF/MarkLive.cpp
index 35220e168df3..702187bdf4e7 100644
--- a/lld/ELF/MarkLive.cpp
+++ b/lld/ELF/MarkLive.cpp
@@ -261,6 +261,10 @@ template <class ELFT> void MarkLive<ELFT>::run() {
         scanEhFrameSection(*eh, eh->template rels<ELFT>());
     }
 
+    if (sec->flags & SHF_GNU_RETAIN) {
+      enqueue(sec, 0);
+      continue;
+    }
     if (sec->flags & SHF_LINK_ORDER)
       continue;
 

diff  --git a/lld/test/ELF/gc-sections-retain.s b/lld/test/ELF/gc-sections-retain.s
new file mode 100644
index 000000000000..edde321754ab
--- /dev/null
+++ b/lld/test/ELF/gc-sections-retain.s
@@ -0,0 +1,44 @@
+# REQUIRES: x86
+## SHF_GNU_RETAIN is a generic feature defined in the OS specific range. The
+## flag marks a section as a GC root.
+
+# RUN: llvm-mc -filetype=obj -triple=x86_64 %s -o %t.o
+# RUN: ld.lld --gc-sections --print-gc-sections %t.o -o %t | count 0
+# RUN: llvm-readobj -hS %t | FileCheck %s
+# RUN: ld.lld -r -e _start --gc-sections --print-gc-sections %t.o -o %t.ro | count 0
+# RUN: llvm-readobj -hS %t.ro | FileCheck %s
+
+## SHF_GNU_RETAIN has no significance in executables/shared objects. Multiple
+## OSABI values can benefit from this flag. Test that we don't change EI_OSABI,
+## even for relocatable output.
+# CHECK:       OS/ABI: SystemV (0x0)
+
+# CHECK:      Name: .retain
+# CHECK-NEXT: Type: SHT_PROGBITS
+# CHECK-NEXT: Flags [
+# CHECK-NEXT:   SHF_ALLOC
+# CHECK-NEXT:   SHF_GNU_RETAIN
+# CHECK-NEXT: ]
+
+# RUN: llvm-mc -filetype=obj -triple=x86_64 --defsym NONALLOC=1 %s -o %t1.o
+# RUN: not ld.lld --gc-sections %t1.o -o /dev/null 2>&1 | FileCheck %s --check-prefix=ERR
+
+# ERR: error: {{.*}}.o:(.nonalloc): sh_link points to discarded section {{.*}}.o:(.discard)
+
+.global _start
+_start:
+
+.section .retain,"aR", at progbits
+.quad .foo
+
+.section .foo,"a", at progbits
+.quad 0
+
+.ifdef NONALLOC
+.section .discard,"a", at progbits
+
+## With SHF_GNU_RETAIN, .nonalloc is retained while its linked-to section
+## .discard is discarded, so there will be an error.
+.section .nonalloc,"oR", at progbits,.discard
+.quad .text
+.endif


        


More information about the llvm-commits mailing list