[lld] r261840 - [ELF] - Referencing __start or __stop should keep the section from GC.

George Rimar via llvm-commits llvm-commits at lists.llvm.org
Thu Feb 25 00:40:28 PST 2016


Author: grimar
Date: Thu Feb 25 02:40:26 2016
New Revision: 261840

URL: http://llvm.org/viewvc/llvm-project?rev=261840&view=rev
Log:
[ELF] - Referencing __start or __stop should keep the section from GC.

This fixes the https://llvm.org/bugs/show_bug.cgi?id=22906 bug.

In GNU Binutils, a reference to start or stop is sufficient to 
prevent the section from being garbage collected.
Patch implements the same behavior for lld.

Differential revision: http://reviews.llvm.org/D17502

Added:
    lld/trunk/test/ELF/startstop-gccollect.s
Modified:
    lld/trunk/ELF/MarkLive.cpp
    lld/trunk/ELF/OutputSections.cpp
    lld/trunk/ELF/OutputSections.h
    lld/trunk/ELF/Writer.cpp
    lld/trunk/test/ELF/gc-sections-local-sym.s

Modified: lld/trunk/ELF/MarkLive.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/MarkLive.cpp?rev=261840&r1=261839&r2=261840&view=diff
==============================================================================
--- lld/trunk/ELF/MarkLive.cpp (original)
+++ lld/trunk/ELF/MarkLive.cpp Thu Feb 25 02:40:26 2016
@@ -71,6 +71,12 @@ template <class ELFT> static bool isRese
     return true;
   default:
     StringRef S = Sec->getSectionName();
+
+    // We do not want to reclaim sections if they can be referred
+    // by __start_* and __stop_* symbols.
+    if (isValidCIdentifier(S))
+      return true;
+
     return S.startswith(".ctors") || S.startswith(".dtors") ||
            S.startswith(".init") || S.startswith(".fini") ||
            S.startswith(".jcr");

Modified: lld/trunk/ELF/OutputSections.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/OutputSections.cpp?rev=261840&r1=261839&r2=261840&view=diff
==============================================================================
--- lld/trunk/ELF/OutputSections.cpp (original)
+++ lld/trunk/ELF/OutputSections.cpp Thu Feb 25 02:40:26 2016
@@ -24,6 +24,19 @@ using namespace llvm::ELF;
 using namespace lld;
 using namespace lld::elf2;
 
+static bool isAlpha(char C) {
+  return ('a' <= C && C <= 'z') || ('A' <= C && C <= 'Z') || C == '_';
+}
+
+static bool isAlnum(char C) { return isAlpha(C) || ('0' <= C && C <= '9'); }
+
+// Returns true if S is valid as a C language identifier.
+bool elf2::isValidCIdentifier(StringRef S) {
+  if (S.empty() || !isAlpha(S[0]))
+    return false;
+  return std::all_of(S.begin() + 1, S.end(), isAlnum);
+}
+
 template <class ELFT>
 OutputSectionBase<ELFT>::OutputSectionBase(StringRef Name, uint32_t Type,
                                            uintX_t Flags)

Modified: lld/trunk/ELF/OutputSections.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/OutputSections.h?rev=261840&r1=261839&r2=261840&view=diff
==============================================================================
--- lld/trunk/ELF/OutputSections.h (original)
+++ lld/trunk/ELF/OutputSections.h Thu Feb 25 02:40:26 2016
@@ -55,6 +55,8 @@ getLocalRelTarget(const ObjectFile<ELFT>
 
 bool canBePreempted(const SymbolBody *Body, bool NeedsGot);
 
+bool isValidCIdentifier(StringRef S);
+
 // This represents a section in an output file.
 // Different sub classes represent different types of sections. Some contain
 // input sections, others are created by the linker.

Modified: lld/trunk/ELF/Writer.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Writer.cpp?rev=261840&r1=261839&r2=261840&view=diff
==============================================================================
--- lld/trunk/ELF/Writer.cpp (original)
+++ lld/trunk/ELF/Writer.cpp Thu Feb 25 02:40:26 2016
@@ -1158,19 +1158,6 @@ template <class ELFT> void Writer<ELFT>:
          Out<ELFT>::Dynamic->FiniArraySec);
 }
 
-static bool isAlpha(char C) {
-  return ('a' <= C && C <= 'z') || ('A' <= C && C <= 'Z') || C == '_';
-}
-
-static bool isAlnum(char C) { return isAlpha(C) || ('0' <= C && C <= '9'); }
-
-// Returns true if S is valid as a C language identifier.
-static bool isValidCIdentifier(StringRef S) {
-  if (S.empty() || !isAlpha(S[0]))
-    return false;
-  return std::all_of(S.begin() + 1, S.end(), isAlnum);
-}
-
 // If a section name is valid as a C identifier (which is rare because of
 // the leading '.'), linkers are expected to define __start_<secname> and
 // __stop_<secname> symbols. They are at beginning and end of the section,

Modified: lld/trunk/test/ELF/gc-sections-local-sym.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/gc-sections-local-sym.s?rev=261840&r1=261839&r2=261840&view=diff
==============================================================================
--- lld/trunk/test/ELF/gc-sections-local-sym.s (original)
+++ lld/trunk/test/ELF/gc-sections-local-sym.s Thu Feb 25 02:40:26 2016
@@ -6,7 +6,7 @@
 .global foo
 foo:
 
-.section bar,"a"
+.section .bar,"a"
 zed:
 
 // CHECK:      Name: .strtab

Added: lld/trunk/test/ELF/startstop-gccollect.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/startstop-gccollect.s?rev=261840&view=auto
==============================================================================
--- lld/trunk/test/ELF/startstop-gccollect.s (added)
+++ lld/trunk/test/ELF/startstop-gccollect.s Thu Feb 25 02:40:26 2016
@@ -0,0 +1,32 @@
+# REQUIRES: x86
+# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t
+
+## Default run: sections foo and bar exist in output
+# RUN: ld.lld %t -o %tout
+# 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
+## 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:    11000:       90      nop
+# DISASM-NEXT: Disassembly of section foo:
+# DISASM-NEXT: foo:
+# DISASM-NEXT:    11001:       90      nop
+# DISASM-NEXT: Disassembly of section bar:
+# DISASM-NEXT: bar:
+# DISASM-NEXT:    11002:       90      nop
+
+.global _start
+.text
+_start:
+ nop
+
+.section foo,"ax"
+ nop
+
+.section bar,"ax"
+ nop




More information about the llvm-commits mailing list