mirror of
https://github.com/capstone-engine/llvm-capstone.git
synced 2025-02-19 01:09:39 +00:00
[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 llvm-svn: 261840
This commit is contained in:
parent
3d3d0f4151
commit
12737b7f72
@ -71,6 +71,12 @@ template <class ELFT> static bool isReserved(InputSectionBase<ELFT> *Sec) {
|
|||||||
return true;
|
return true;
|
||||||
default:
|
default:
|
||||||
StringRef S = Sec->getSectionName();
|
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") ||
|
return S.startswith(".ctors") || S.startswith(".dtors") ||
|
||||||
S.startswith(".init") || S.startswith(".fini") ||
|
S.startswith(".init") || S.startswith(".fini") ||
|
||||||
S.startswith(".jcr");
|
S.startswith(".jcr");
|
||||||
|
@ -24,6 +24,19 @@ using namespace llvm::ELF;
|
|||||||
using namespace lld;
|
using namespace lld;
|
||||||
using namespace lld::elf2;
|
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>
|
template <class ELFT>
|
||||||
OutputSectionBase<ELFT>::OutputSectionBase(StringRef Name, uint32_t Type,
|
OutputSectionBase<ELFT>::OutputSectionBase(StringRef Name, uint32_t Type,
|
||||||
uintX_t Flags)
|
uintX_t Flags)
|
||||||
|
@ -55,6 +55,8 @@ getLocalRelTarget(const ObjectFile<ELFT> &File,
|
|||||||
|
|
||||||
bool canBePreempted(const SymbolBody *Body, bool NeedsGot);
|
bool canBePreempted(const SymbolBody *Body, bool NeedsGot);
|
||||||
|
|
||||||
|
bool isValidCIdentifier(StringRef S);
|
||||||
|
|
||||||
// This represents a section in an output file.
|
// This represents a section in an output file.
|
||||||
// Different sub classes represent different types of sections. Some contain
|
// Different sub classes represent different types of sections. Some contain
|
||||||
// input sections, others are created by the linker.
|
// input sections, others are created by the linker.
|
||||||
|
@ -1158,19 +1158,6 @@ template <class ELFT> void Writer<ELFT>::addStartEndSymbols() {
|
|||||||
Out<ELFT>::Dynamic->FiniArraySec);
|
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
|
// 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
|
// the leading '.'), linkers are expected to define __start_<secname> and
|
||||||
// __stop_<secname> symbols. They are at beginning and end of the section,
|
// __stop_<secname> symbols. They are at beginning and end of the section,
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
.global foo
|
.global foo
|
||||||
foo:
|
foo:
|
||||||
|
|
||||||
.section bar,"a"
|
.section .bar,"a"
|
||||||
zed:
|
zed:
|
||||||
|
|
||||||
// CHECK: Name: .strtab
|
// CHECK: Name: .strtab
|
||||||
|
32
lld/test/ELF/startstop-gccollect.s
Normal file
32
lld/test/ELF/startstop-gccollect.s
Normal file
@ -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
|
Loading…
x
Reference in New Issue
Block a user