[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