[lld] r296723 - Make gc a bit more aggressive.

Rafael Espindola via llvm-commits llvm-commits at lists.llvm.org
Wed Mar 1 17:50:35 PST 2017


Author: rafael
Date: Wed Mar  1 19:50:34 2017
New Revision: 296723

URL: http://llvm.org/viewvc/llvm-project?rev=296723&view=rev
Log:
Make gc a bit more aggressive.

We were not gcing any section whose name was a C identifier. Both gold
and bfd only keep those if they are used.

To avoid having to create the __start/__stop symbols early or doing
string lookups in resolvedReloc, this patch just looks for undefined
symbols __start/__stop to decide if a section is needed or not.

Added:
    lld/trunk/test/ELF/linkerscript/sections-gc2.s
Modified:
    lld/trunk/ELF/MarkLive.cpp
    lld/trunk/test/ELF/startstop-gccollect.s

Modified: lld/trunk/ELF/MarkLive.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/MarkLive.cpp?rev=296723&r1=296722&r2=296723&view=diff
==============================================================================
--- lld/trunk/ELF/MarkLive.cpp (original)
+++ lld/trunk/ELF/MarkLive.cpp Wed Mar  1 19:50:34 2017
@@ -170,12 +170,7 @@ template <class ELFT> static bool isRese
     if (!(Sec->Flags & SHF_ALLOC))
       return true;
 
-    // We do not want to reclaim sections if they can be referred
-    // by __start_* and __stop_* symbols.
     StringRef S = Sec->Name;
-    if (isValidCIdentifier(S))
-      return true;
-
     return S.startswith(".ctors") || S.startswith(".dtors") ||
            S.startswith(".init") || S.startswith(".fini") ||
            S.startswith(".jcr");
@@ -226,11 +221,22 @@ template <class ELFT> void elf::markLive
   for (StringRef S : Config->Undefined)
     MarkSymbol(Symtab<ELFT>::X->find(S));
 
+  // Remember which __start_* or __stop_* symbols are used so that we don't gc
+  // those sections.
+  DenseSet<StringRef> UsedStartStopNames;
+
   // Preserve externally-visible symbols if the symbols defined by this
   // file can interrupt other ELF file's symbols at runtime.
-  for (const Symbol *S : Symtab<ELFT>::X->getSymbols())
-    if (S->includeInDynsym())
+  for (const Symbol *S : Symtab<ELFT>::X->getSymbols()) {
+    if (auto *U = dyn_cast_or_null<Undefined>(S->body())) {
+      StringRef Name = U->getName();
+      for (StringRef Prefix : {"__start_", "__stop_"})
+        if (Name.startswith(Prefix))
+          UsedStartStopNames.insert(Name.substr(Prefix.size()));
+    } else if (S->includeInDynsym()) {
       MarkSymbol(S->body());
+    }
+  }
 
   // Preserve special sections and those which are specified in linker
   // script KEEP command.
@@ -240,7 +246,8 @@ template <class ELFT> void elf::markLive
     // referred by .eh_frame here.
     if (auto *EH = dyn_cast_or_null<EhInputSection<ELFT>>(Sec))
       scanEhFrameSection<ELFT>(*EH, Enqueue);
-    if (isReserved<ELFT>(Sec) || Script<ELFT>::X->shouldKeep(Sec))
+    if (isReserved<ELFT>(Sec) || Script<ELFT>::X->shouldKeep(Sec) ||
+        UsedStartStopNames.count(Sec->Name))
       Enqueue({Sec, 0});
   }
 

Added: lld/trunk/test/ELF/linkerscript/sections-gc2.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/linkerscript/sections-gc2.s?rev=296723&view=auto
==============================================================================
--- lld/trunk/test/ELF/linkerscript/sections-gc2.s (added)
+++ lld/trunk/test/ELF/linkerscript/sections-gc2.s Wed Mar  1 19:50:34 2017
@@ -0,0 +1,37 @@
+# REQUIRES: x86
+# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o
+# RUN: echo "SECTIONS { \
+# RUN:         used_in_reloc : { *(used_in_reloc) } \
+# RUN:         used_in_script : { *(used_in_script) } \
+# RUN:         .data : { *(.data) } \
+# RUN:       }" > %t.script
+# RUN: ld.lld -T %t.script -o %t.so %t.o -shared --gc-sections
+# RUN: llvm-objdump -h %t.so | FileCheck %s
+
+# CHECK: Idx Name          Size      Address          Type
+# CHECK-NEXT:  0
+# CHECK-NEXT:    used_in_reloc
+# CHECK-NEXT:    .dynsym
+# CHECK-NEXT:    .hash
+# CHECK-NEXT:    .dynstr
+# CHECK-NEXT:    .rela.dyn
+# CHECK-NEXT:    .data
+# CHECK-NEXT:    .dynamic
+# CHECK-NEXT:    .comment
+# CHECK-NEXT:    .symtab
+# CHECK-NEXT:    .shstrtab
+# CHECK-NEXT:    .strtab
+
+        .data
+        .global foo
+foo:
+        .quad __start_used_in_reloc
+
+        .section unused,"a"
+        .quad 0
+
+        .section used_in_script,"a"
+        .quad 0
+
+        .section used_in_reloc,"a"
+        .quad 0

Modified: lld/trunk/test/ELF/startstop-gccollect.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/startstop-gccollect.s?rev=296723&r1=296722&r2=296723&view=diff
==============================================================================
--- lld/trunk/test/ELF/startstop-gccollect.s (original)
+++ lld/trunk/test/ELF/startstop-gccollect.s Wed Mar  1 19:50:34 2017
@@ -6,24 +6,26 @@
 # RUN: llvm-objdump -d %tout | FileCheck -check-prefix=DISASM %s
 
 ## Check that foo and bar sections are not garbage collected,
-## we do not want to reclaim sections if they can be referred
+## we do not want to reclaim sections if they are referred
 ## by __start_* and __stop_* symbols.
 # RUN: ld.lld %t --gc-sections -o %tout
 # RUN: llvm-objdump -d %tout | FileCheck -check-prefix=DISASM %s
 
 # DISASM:      _start:
-# DISASM-NEXT:    201000:       90      nop
+# DISASM-NEXT: 201000:        e8 05 00 00 00  callq   5 <__start_foo>
+# DISASM-NEXT: 201005:        e8 01 00 00 00  callq   1 <__start_bar>
 # DISASM-NEXT: Disassembly of section foo:
-# DISASM-NEXT: foo:
-# DISASM-NEXT:    201001:       90      nop
+# DISASM-NEXT: __start_foo:
+# DISASM-NEXT: 20100a:        90      nop
 # DISASM-NEXT: Disassembly of section bar:
-# DISASM-NEXT: bar:
-# DISASM-NEXT:    201002:       90      nop
+# DISASM-NEXT: __start_bar:
+# DISASM-NEXT: 20100b:        90      nop
 
 .global _start
 .text
 _start:
- nop
+ callq __start_foo
+ callq __start_bar
 
 .section foo,"ax"
  nop




More information about the llvm-commits mailing list