[lld] 4e80c76 - [ELF] Support -r --gc-sections

Fangrui Song via llvm-commits llvm-commits at lists.llvm.org
Thu Jul 23 08:19:01 PDT 2020


Author: Fangrui Song
Date: 2020-07-23T08:16:01-07:00
New Revision: 4e80c768c28fa919aa3d4fd662af8ea99feda4d6

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

LOG: [ELF] Support -r --gc-sections

-r --gc-sections is usually not useful because it just makes intermediate output
smaller. https://bugs.llvm.org/show_bug.cgi?id=46700#c7 mentions a use case:
validating the absence of undefined symbols ealier than in the final link.

After D84129 (SHT_GROUP support in -r links), we can support -r
--gc-sections without extra code. So let's allow it.

Reviewed By: grimar, jhenderson

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

Added: 
    lld/test/ELF/relocatable-gc.s

Modified: 
    lld/ELF/Driver.cpp
    lld/ELF/InputFiles.cpp
    lld/test/ELF/driver.test

Removed: 
    


################################################################################
diff  --git a/lld/ELF/Driver.cpp b/lld/ELF/Driver.cpp
index 4637a3b306da..30bff945f1a5 100644
--- a/lld/ELF/Driver.cpp
+++ b/lld/ELF/Driver.cpp
@@ -330,8 +330,6 @@ static void checkOptions() {
   if (config->relocatable) {
     if (config->shared)
       error("-r and -shared may not be used together");
-    if (config->gcSections)
-      error("-r and --gc-sections may not be used together");
     if (config->gdbIndex)
       error("-r and --gdb-index may not be used together");
     if (config->icf != ICFLevel::None)

diff  --git a/lld/ELF/InputFiles.cpp b/lld/ELF/InputFiles.cpp
index c2f1830a981b..c142c00517cc 100644
--- a/lld/ELF/InputFiles.cpp
+++ b/lld/ELF/InputFiles.cpp
@@ -926,20 +926,6 @@ InputSectionBase *ObjFile<ELFT>::createInputSection(const Elf_Shdr &sec) {
       this->sections[sec.sh_info] = target;
     }
 
-    // This section contains relocation information.
-    // If -r is given, we do not interpret or apply relocation
-    // but just copy relocation sections to output.
-    if (config->relocatable) {
-      InputSection *relocSec = make<InputSection>(*this, sec, name);
-      // We want to add a dependency to target, similar like we do for
-      // -emit-relocs below. This is useful for the case when linker script
-      // contains the "/DISCARD/". It is perhaps uncommon to use a script with
-      // -r, but we faced it in the Linux kernel and have to handle such case
-      // and not to crash.
-      target->dependentSections.push_back(relocSec);
-      return relocSec;
-    }
-
     if (target->firstRelocation)
       fatal(toString(this) +
             ": multiple relocation sections to one section are not supported");
@@ -957,17 +943,17 @@ InputSectionBase *ObjFile<ELFT>::createInputSection(const Elf_Shdr &sec) {
     }
     assert(isUInt<31>(target->numRelocations));
 
-    // Relocation sections processed by the linker are usually removed
-    // from the output, so returning `nullptr` for the normal case.
-    // However, if -emit-relocs is given, we need to leave them in the output.
-    // (Some post link analysis tools need this information.)
-    if (config->emitRelocs) {
-      InputSection *relocSec = make<InputSection>(*this, sec, name);
-      // We will not emit relocation section if target was discarded.
-      target->dependentSections.push_back(relocSec);
-      return relocSec;
-    }
-    return nullptr;
+    // Relocation sections are usually removed from the output, so return
+    // `nullptr` for the normal case. However, if -r or --emit-relocs is
+    // specified, we need to copy them to the output. (Some post link analysis
+    // tools specify --emit-relocs to obtain the information.)
+    if (!config->relocatable && !config->emitRelocs)
+      return nullptr;
+    InputSection *relocSec = make<InputSection>(*this, sec, name);
+    // If the relocated section is discarded (due to /DISCARD/ or
+    // --gc-sections), the relocation section should be discarded as well.
+    target->dependentSections.push_back(relocSec);
+    return relocSec;
   }
   }
 

diff  --git a/lld/test/ELF/driver.test b/lld/test/ELF/driver.test
index bec8301bb9a0..cd7edc647854 100644
--- a/lld/test/ELF/driver.test
+++ b/lld/test/ELF/driver.test
@@ -34,10 +34,6 @@
 # RUN: not ld.lld -r -shared %t -o /dev/null 2>&1 | FileCheck -check-prefix=ERR2 %s
 # ERR2: -r and -shared may not be used together
 
-## Attempt to use -r and --gc-sections together
-# RUN: not ld.lld -r --gc-sections %t -o /dev/null 2>&1 | FileCheck -check-prefix=ERR3 %s
-# ERR3: -r and --gc-sections may not be used together
-
 ## Attempt to use -r and --gdb-index together
 # RUN: not ld.lld -r --gdb-index %t -o /dev/null 2>&1 | FileCheck -check-prefix=ERR4 %s
 # ERR4: -r and --gdb-index may not be used together

diff  --git a/lld/test/ELF/relocatable-gc.s b/lld/test/ELF/relocatable-gc.s
new file mode 100644
index 000000000000..caa23314f37a
--- /dev/null
+++ b/lld/test/ELF/relocatable-gc.s
@@ -0,0 +1,80 @@
+# REQUIRES: x86
+## Test -r --gc-sections.
+
+# RUN: llvm-mc -filetype=obj -triple=x86_64 %s -o %t.o
+
+## By default all regular sections are discarded. We currently don't track
+## usage of group signature symbols and will retain them and their associated
+## STT_SECTION symbols.
+# RUN: ld.lld -r --gc-sections --print-gc-sections %t.o -o %t
+# RUN: llvm-readelf -S -s %t | FileCheck %s
+
+# CHECK:      [ 1] .group
+# CHECK-NEXT: [ 2] .note.GNU-stack
+
+# CHECK:      Symbol table '.symtab' contains 3 entries:
+# CHECK-NEXT: Num:
+# CHECK-NEXT: 0:
+# CHECK-NEXT: 1: {{.*}} NOTYPE  LOCAL DEFAULT  1 group
+# CHECK-NEXT: 2: {{.*}} SECTION LOCAL DEFAULT  1
+
+## -u keeps .text.bar alive. Other group members are kept alive as well.
+# RUN: ld.lld -r --gc-sections -u bar %t.o -o - | llvm-readelf -Ss - | \
+# RUN:   FileCheck %s --check-prefix=KEEP_GROUP
+## -e, --init and --fini are similar.
+# RUN: ld.lld -r --gc-sections -e bar %t.o -o - | llvm-readelf -Ss - | \
+# RUN:   FileCheck %s --check-prefix=KEEP_GROUP
+# RUN: ld.lld -r --gc-sections --init=bar %t.o -o - | llvm-readelf -Ss - | \
+# RUN:   FileCheck %s --check-prefix=KEEP_GROUP
+# RUN: ld.lld -r --gc-sections --fini=bar %t.o -o - | llvm-readelf -Ss - | \
+# RUN:   FileCheck %s --check-prefix=KEEP_GROUP
+
+# KEEP_GROUP:      [ 1] .group
+# KEEP_GROUP-NEXT: [ 2] .text.bar
+# KEEP_GROUP-NEXT: [ 3] .text.foo
+# KEEP_GROUP-NEXT: [ 4] .note.GNU-stack
+
+# KEEP_GROUP:      Symbol table '.symtab' contains 7 entries:
+# KEEP_GROUP:      4: {{.*}} SECTION
+# KEEP_GROUP-NEXT: 5: {{.*}}   2 bar
+# KEEP_GROUP-NEXT: 6: {{.*}}   3 foo
+
+## If .text is retained, its referenced qux and .fred are retained as well.
+## fred_und is used (by .fred) and thus emitted.
+## Note, GNU ld does not retain qux.
+# RUN: ld.lld -r --gc-sections -e _start %t.o -o %tstart.ro
+# RUN: llvm-readelf -Ss %tstart.ro | FileCheck %s --check-prefix=KEEP_START
+
+# KEEP_START:      [ 1] .text
+# KEEP_START-NEXT: [ 2] .rela.text
+# KEEP_START-NEXT: [ 3] qux
+# KEEP_START-NEXT: [ 4] .group
+# KEEP_START-NEXT: [ 5] .fred
+# KEEP_START-NEXT: [ 6] .rela.fred
+# KEEP_START-NEXT: [ 7] .note.GNU-stack
+
+# KEEP_START:      Symbol table '.symtab' contains 10 entries:
+# KEEP_START:      5: {{.*}} SECTION
+# KEEP_START-NEXT: 6: {{.*}} UND __start_qux
+# KEEP_START-NEXT: 7: {{.*}}   1 _start
+# KEEP_START-NEXT: 8: {{.*}}   5 fred
+# KEEP_START-NEXT: 9: {{.*}} UND fred_und
+
+.section qux,"a", at progbits
+  .byte 0
+
+.text
+.globl _start, bar, foo, fred
+_start:
+  call fred
+  .quad __start_qux
+
+.section .text.bar,"axG", at progbits,group,comdat
+bar:
+  .byte 1
+.section .text.foo,"axG", at progbits,group,comdat
+foo:
+  .byte 2
+.section .fred,"ax", at progbits
+fred:
+  call fred_und


        


More information about the llvm-commits mailing list