forked from OSchip/llvm-project
[ELF] Add -z start-stop-gc to let __start_/__stop_ not retain C identifier name sections
For one metadata section usage, each text section references a metadata section. The metadata sections have a C identifier name to allow the runtime to collect them via `__start_/__stop_` symbols. Since `__start_`/`__stop_` references are always present from live sections, the C identifier name sections appear like GC roots, which means they cannot be discarded by `ld --gc-sections`. To make such sections GCable, either SHF_LINK_ORDER or a section group is needed. SHF_LINK_ORDER is not suitable for the references can be inlined into other functions (See D97430: Function A (in the section .text.A) references its `__sancov_guard` section. Function B inlines A (so now .text.B references `__sancov_guard` - this is invalid with the semantics of SHF_LINK_ORDER). In the linking stage, if `.text.A` gets discarded, and `__sancov_guard` is retained via the reference from `.text.B`, the output will be invalid because `__sancov_guard` references the discarded `.text.A`. LLD errors "sh_link points to discarded section". ) A section group have size overhead, and is cumbersome when there is just one metadata section. Add `-z start-stop-gc` to drop the "__start_/__stop_ references retain non-SHF_LINK_ORDER non-SHF_GROUP C identifier name sections" rule. We reserve the rights to switch the default in the future. Reviewed By: phosek, jrtc27 Differential Revision: https://reviews.llvm.org/D96914
This commit is contained in:
parent
6d102f15a3
commit
4bbcd63eea
|
@ -239,6 +239,7 @@ struct Configuration {
|
|||
bool zRelro;
|
||||
bool zRodynamic;
|
||||
bool zShstk;
|
||||
bool zStartStopGC;
|
||||
uint8_t zStartStopVisibility;
|
||||
bool zText;
|
||||
bool zRetpolineplt;
|
||||
|
|
|
@ -451,10 +451,11 @@ static bool isKnownZFlag(StringRef s) {
|
|||
s == "initfirst" || s == "interpose" ||
|
||||
s == "keep-text-section-prefix" || s == "lazy" || s == "muldefs" ||
|
||||
s == "separate-code" || s == "separate-loadable-segments" ||
|
||||
s == "nocombreloc" || s == "nocopyreloc" || s == "nodefaultlib" ||
|
||||
s == "nodelete" || s == "nodlopen" || s == "noexecstack" ||
|
||||
s == "nognustack" || s == "nokeep-text-section-prefix" ||
|
||||
s == "norelro" || s == "noseparate-code" || s == "notext" ||
|
||||
s == "start-stop-gc" || s == "nocombreloc" || s == "nocopyreloc" ||
|
||||
s == "nodefaultlib" || s == "nodelete" || s == "nodlopen" ||
|
||||
s == "noexecstack" || s == "nognustack" ||
|
||||
s == "nokeep-text-section-prefix" || s == "norelro" ||
|
||||
s == "noseparate-code" || s == "nostart-stop-gc" || s == "notext" ||
|
||||
s == "now" || s == "origin" || s == "pac-plt" || s == "rel" ||
|
||||
s == "rela" || s == "relro" || s == "retpolineplt" ||
|
||||
s == "rodynamic" || s == "shstk" || s == "text" || s == "undefs" ||
|
||||
|
@ -1119,6 +1120,8 @@ static void readConfigs(opt::InputArgList &args) {
|
|||
config->zSeparate = getZSeparate(args);
|
||||
config->zShstk = hasZOption(args, "shstk");
|
||||
config->zStackSize = args::getZOptionValue(args, OPT_z, "stack-size", 0);
|
||||
config->zStartStopGC =
|
||||
getZFlag(args, "start-stop-gc", "nostart-stop-gc", false);
|
||||
config->zStartStopVisibility = getZStartStopVisibility(args);
|
||||
config->zText = getZFlag(args, "text", "notext", true);
|
||||
config->zWxneeded = hasZOption(args, "wxneeded");
|
||||
|
|
|
@ -270,7 +270,8 @@ template <class ELFT> void MarkLive<ELFT>::run() {
|
|||
|
||||
if (isReserved(sec) || script->shouldKeep(sec)) {
|
||||
enqueue(sec, 0);
|
||||
} else if (isValidCIdentifier(sec->name) && !sec->nextInSectionGroup) {
|
||||
} else if (!config->zStartStopGC && isValidCIdentifier(sec->name) &&
|
||||
!sec->nextInSectionGroup) {
|
||||
cNamedSections[saver.save("__start_" + sec->name)].push_back(sec);
|
||||
cNamedSections[saver.save("__stop_" + sec->name)].push_back(sec);
|
||||
}
|
||||
|
|
|
@ -802,6 +802,8 @@ The stack size is recorded as the size of the
|
|||
.Dv PT_GNU_STACK
|
||||
program segment.
|
||||
.Pp
|
||||
.It Cm start-stop-gc
|
||||
Don't let __start_/__stop_ references retain non-SHF_LINK_ORDER non-SHF_GROUP C identifier name sections.
|
||||
.It Cm text
|
||||
Do not allow relocations against read-only segments.
|
||||
This is the default.
|
||||
|
|
|
@ -4,6 +4,13 @@
|
|||
# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o
|
||||
# RUN: ld.lld --gc-sections %t.o -o %t
|
||||
# RUN: llvm-objdump --section-headers -t %t | FileCheck %s
|
||||
# RUN: ld.lld --gc-sections -z start-stop-gc -z nostart-stop-gc %t.o -o %t
|
||||
# RUN: llvm-objdump --section-headers -t %t | FileCheck %s
|
||||
|
||||
## With -z start-stop-gc, non-SHF_LINK_ORDER non-SHF_GROUP C identifier name
|
||||
## sections are not retained by __start_/__stop_ references.
|
||||
# RUN: ld.lld --gc-sections -z start-stop-gc %t.o -o %t1
|
||||
# RUN: llvm-readelf -S -s %t1 | FileCheck %s --check-prefix=GC
|
||||
|
||||
# CHECK: Sections:
|
||||
# CHECK-NOT: yy
|
||||
|
@ -14,6 +21,13 @@
|
|||
# CHECK: xx 0000000000000000 .protected __start_xx
|
||||
# CHECK: w *UND* 0000000000000000 __start_yy
|
||||
|
||||
# GC: Section Headers:
|
||||
# GC-NOT: xx
|
||||
# GC-NOT: yy
|
||||
|
||||
# GC: WEAK DEFAULT UND __start_xx
|
||||
# GC: WEAK DEFAULT UND __start_yy
|
||||
|
||||
.weak __start_xx
|
||||
.weak __start_yy
|
||||
|
||||
|
|
Loading…
Reference in New Issue