[lld] 497c76e - [ELF] Keep local symbols when both --emit-relocs and --discard-all are specified

Fangrui Song via llvm-commits llvm-commits at lists.llvm.org
Tue Apr 21 08:28:57 PDT 2020


Author: Fangrui Song
Date: 2020-04-21T08:28:12-07:00
New Revision: 497c76e96dcdfe39f486853ea3b17810be5b6e45

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

LOG: [ELF] Keep local symbols when both --emit-relocs and --discard-all are specified

This fixes a bug as exposed by D77807.

Add tests for {--emit-relocs,-r} x {--discard-locals,--discard-all}. They add coverage for previously undertested cases:

* STT_SECTION associated to GCed sections (`gc`)
* STT_SECTION associated to retained sections (`text`)
* STT_SECTION associated to non-SHF_ALLOC sections (`.comment`)
* STB_LOCAL in GCed sections (`unused_gc`)

Reviewed By: grimar, ikudrin

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

Added: 
    lld/test/ELF/emit-relocs-discard-locals.s
    lld/test/ELF/relocatable-discard-locals.s

Modified: 
    lld/ELF/Driver.cpp
    lld/ELF/Writer.cpp

Removed: 
    


################################################################################
diff  --git a/lld/ELF/Driver.cpp b/lld/ELF/Driver.cpp
index b074ae68d012..a5b117913356 100644
--- a/lld/ELF/Driver.cpp
+++ b/lld/ELF/Driver.cpp
@@ -609,9 +609,6 @@ static bool isOutputFormatBinary(opt::InputArgList &args) {
 }
 
 static DiscardPolicy getDiscard(opt::InputArgList &args) {
-  if (args.hasArg(OPT_relocatable))
-    return DiscardPolicy::None;
-
   auto *arg =
       args.getLastArg(OPT_discard_all, OPT_discard_locals, OPT_discard_none);
   if (!arg)

diff  --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp
index 55df6b7c5e4c..91fdff145c62 100644
--- a/lld/ELF/Writer.cpp
+++ b/lld/ELF/Writer.cpp
@@ -560,8 +560,7 @@ template <class ELFT> void createSyntheticSections() {
 
 // The main function of the writer.
 template <class ELFT> void Writer<ELFT>::run() {
-  if (config->discard != DiscardPolicy::All)
-    copyLocalSymbols();
+  copyLocalSymbols();
 
   if (config->copyRelocs)
     addSectionSymbols();
@@ -642,13 +641,15 @@ static bool shouldKeepInSymtab(const Defined &sym) {
   if (sym.isSection())
     return false;
 
-  if (config->discard == DiscardPolicy::None)
+  // If --emit-reloc or -r is given, all symbols including local ones need to be
+  // copied because they may be referenced by relocations.
+  if (config->copyRelocs)
     return true;
 
-  // If -emit-reloc is given, all symbols including local ones need to be
-  // copied because they may be referenced by relocations.
-  if (config->emitRelocs)
+  if (config->discard == DiscardPolicy::None)
     return true;
+  if (config->discard == DiscardPolicy::All)
+    return false;
 
   // In ELF assembly .L symbols are normally discarded by the assembler.
   // If the assembler fails to do so, the linker discards them if

diff  --git a/lld/test/ELF/emit-relocs-discard-locals.s b/lld/test/ELF/emit-relocs-discard-locals.s
new file mode 100644
index 000000000000..39d1aa56dc37
--- /dev/null
+++ b/lld/test/ELF/emit-relocs-discard-locals.s
@@ -0,0 +1,51 @@
+# REQUIRES: x86
+## Test that --emit-relocs keeps local symbols and overrides --discard-{locals,all}.
+
+# RUN: llvm-mc -filetype=obj -triple=x86_64 -save-temp-labels %s -o %t.o
+
+# RUN: ld.lld --emit-relocs --discard-locals %t.o -o %tlocal
+# RUN: llvm-readelf -s %tlocal | FileCheck --check-prefixes=SYM,SYM-NOGC %s
+# RUN: llvm-readobj -r %tlocal | FileCheck --check-prefix=REL %s
+## --gc-sections can discard symbols relative to GCed sections (including STT_SECTION).
+# RUN: ld.lld --emit-relocs --discard-locals --gc-sections %t.o -o %tlocal.gc
+# RUN: llvm-readelf -s %tlocal.gc | FileCheck --check-prefix=SYM %s
+# RUN: llvm-readobj -r %tlocal | FileCheck --check-prefix=REL %s
+
+# RUN: ld.lld --emit-relocs --discard-all %t.o -o %tall
+# RUN: llvm-readelf -s %tall | FileCheck --check-prefixes=SYM,SYM-NOGC %s
+# RUN: llvm-readobj -r %tall | FileCheck --check-prefix=REL %s
+
+# SYM:           NOTYPE  LOCAL  DEFAULT {{.*}} .Lunused
+# SYM-NOGC-NEXT: NOTYPE  LOCAL  DEFAULT {{.*}} .Lunused_gc
+# SYM-NEXT:      NOTYPE  LOCAL  DEFAULT {{.*}} .Lused
+# SYM-NEXT:      NOTYPE  LOCAL  DEFAULT {{.*}} unused
+# SYM-NOGC-NEXT: NOTYPE  LOCAL  DEFAULT {{.*}} unused_gc
+# SYM-NEXT:      NOTYPE  LOCAL  DEFAULT {{.*}} used
+# SYM-NEXT:      SECTION LOCAL  DEFAULT {{.*}} .text
+# SYM-NEXT:      SECTION LOCAL  DEFAULT {{.*}} text
+# SYM-NOGC-NEXT: SECTION LOCAL  DEFAULT {{.*}} gc
+# SYM-NEXT:      SECTION LOCAL  DEFAULT {{.*}} .comment
+# SYM-NEXT:      NOTYPE  GLOBAL DEFAULT {{.*}} _start
+
+# REL:      .rela.text {
+# REL-NEXT:   R_X86_64_PLT32 text 0xFFFFFFFFFFFFFFFC
+# REL-NEXT:   R_X86_64_PLT32 .Lused 0xFFFFFFFFFFFFFFFC
+# REL-NEXT:   R_X86_64_PLT32 used 0xFFFFFFFFFFFFFFFC
+# REL-NEXT: }
+
+.globl _start
+_start:
+  call text at plt
+  jmp .Lused at plt
+  call used at plt
+
+.section text,"ax"
+.Lunused:
+.Lused:
+unused:
+used:
+
+.section gc,"ax"
+.Lunused_gc:
+unused_gc:
+  ret

diff  --git a/lld/test/ELF/relocatable-discard-locals.s b/lld/test/ELF/relocatable-discard-locals.s
new file mode 100644
index 000000000000..c1e06bda8b64
--- /dev/null
+++ b/lld/test/ELF/relocatable-discard-locals.s
@@ -0,0 +1,47 @@
+# REQUIRES: x86
+## Test that -r keeps local symbols and overrides --discard-{locals,all}.
+## Also see emit-relocs-discard-locals.s
+
+# RUN: llvm-mc -filetype=obj -triple=x86_64 -save-temp-labels %s -o %t.o
+
+# RUN: ld.lld -r --discard-locals %t.o -o %tlocal.ro
+# RUN: llvm-readelf -s %tlocal.ro | FileCheck --check-prefixes=SYM,SYM-NOGC %s
+# RUN: llvm-readobj -r %tlocal.ro | FileCheck --check-prefix=REL %s
+
+# RUN: ld.lld -r --discard-all %t.o -o %tall.ro
+# RUN: llvm-readelf -s %tall.ro | FileCheck --check-prefixes=SYM,SYM-NOGC %s
+# RUN: llvm-readobj -r %tall.ro | FileCheck --check-prefix=REL %s
+
+# SYM:           NOTYPE  LOCAL  DEFAULT {{.*}} .Lunused
+# SYM-NOGC-NEXT: NOTYPE  LOCAL  DEFAULT {{.*}} .Lunused_gc
+# SYM-NEXT:      NOTYPE  LOCAL  DEFAULT {{.*}} .Lused
+# SYM-NEXT:      NOTYPE  LOCAL  DEFAULT {{.*}} unused
+# SYM-NOGC-NEXT: NOTYPE  LOCAL  DEFAULT {{.*}} unused_gc
+# SYM-NEXT:      NOTYPE  LOCAL  DEFAULT {{.*}} used
+# SYM-NEXT:      SECTION LOCAL  DEFAULT {{.*}} .text
+# SYM-NEXT:      SECTION LOCAL  DEFAULT {{.*}} text
+# SYM-NOGC-NEXT: SECTION LOCAL  DEFAULT {{.*}} gc
+# SYM-NEXT:      NOTYPE  GLOBAL DEFAULT {{.*}} _start
+
+# REL:      .rela.text {
+# REL-NEXT:   R_X86_64_PLT32 text 0xFFFFFFFFFFFFFFFC
+# REL-NEXT:   R_X86_64_PLT32 .Lused 0xFFFFFFFFFFFFFFFC
+# REL-NEXT:   R_X86_64_PLT32 used 0xFFFFFFFFFFFFFFFC
+# REL-NEXT: }
+
+.globl _start
+_start:
+  call text at plt
+  jmp .Lused at plt
+  call used at plt
+
+.section text,"ax"
+.Lunused:
+.Lused:
+unused:
+used:
+
+.section gc,"ax"
+.Lunused_gc:
+unused_gc:
+  ret


        


More information about the llvm-commits mailing list