Skip to content

Commit

Permalink
[ELF] - Referencing __start or __stop should keep the section from GC.
Browse files Browse the repository at this point in the history
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

llvm-svn: 261840
  • Loading branch information
George Rimar committed Feb 25, 2016
1 parent 3d3d0f4 commit 12737b7
Show file tree
Hide file tree
Showing 6 changed files with 54 additions and 14 deletions.
6 changes: 6 additions & 0 deletions lld/ELF/MarkLive.cpp
Expand Up @@ -71,6 +71,12 @@ template <class ELFT> static bool isReserved(InputSectionBase<ELFT> *Sec) {
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");
Expand Down
13 changes: 13 additions & 0 deletions lld/ELF/OutputSections.cpp
Expand Up @@ -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)
Expand Down
2 changes: 2 additions & 0 deletions lld/ELF/OutputSections.h
Expand Up @@ -55,6 +55,8 @@ getLocalRelTarget(const ObjectFile<ELFT> &File,

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.
Expand Down
13 changes: 0 additions & 13 deletions lld/ELF/Writer.cpp
Expand Up @@ -1158,19 +1158,6 @@ template <class ELFT> void Writer<ELFT>::addStartEndSymbols() {
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,
Expand Down
2 changes: 1 addition & 1 deletion lld/test/ELF/gc-sections-local-sym.s
Expand Up @@ -6,7 +6,7 @@
.global foo
foo:

.section bar,"a"
.section .bar,"a"
zed:

// CHECK: Name: .strtab
Expand Down
32 changes: 32 additions & 0 deletions lld/test/ELF/startstop-gccollect.s
@@ -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

0 comments on commit 12737b7

Please sign in to comment.