[PATCH] ld: Add -z start-stop-gc to let __start_/__stop_ not retain C identifier name sections

Fangrui Song maskray@google.com
Sat Feb 27 20:26:17 GMT 2021


This rule was initially added in PR11133 to work around glibc.  However,
it makes GC on C identifier name sections ineffective.  In particular,
many modern metadata sections (e.g. clang -fsanitize-coverage and
-fprofile-generate) cannot be GCed.

Add -z start-stop-gc to drop the rule.

	PR 27451
include/
	* bfdlink.h (struct bfd_link_info): Add start_stop_gc.
ld/
	* emultempl/elf.em: Handle -z start-stop-gc and -z nostart-stop-gc.
	* ldmain.c: Initialize start_stop_gc.
	* lang.c (lang_process): Handle start_stop_gc.
	* testsuite/ld-gc/gc.exp: New test.
	* testsuite/ld-gc/start.s: Add .weak directive.
	* testsuite/ld-gc/start2.d: New test.
	* ld.texi: Mention -z start-stop-gc and -z nostart-stop-gc.
	* NEWS: Mention -z start-stop-gc.
---
 include/bfdlink.h            |  4 ++++
 ld/NEWS                      |  3 +++
 ld/emultempl/elf.em          |  4 ++++
 ld/ld.texi                   | 10 ++++++++++
 ld/ldlang.c                  |  4 ++--
 ld/ldmain.c                  |  1 +
 ld/testsuite/ld-gc/gc.exp    |  1 +
 ld/testsuite/ld-gc/start-2.d | 11 +++++++++++
 ld/testsuite/ld-gc/start.s   |  1 +
 9 files changed, 37 insertions(+), 2 deletions(-)
 create mode 100644 ld/testsuite/ld-gc/start-2.d

diff --git a/include/bfdlink.h b/include/bfdlink.h
index 95728b6f031..c4222929ae5 100644
--- a/include/bfdlink.h
+++ b/include/bfdlink.h
@@ -662,6 +662,10 @@ struct bfd_link_info
   /* May be used to set DT_GNU_FLAGS_1 for ELF. */
   bfd_vma gnu_flags_1;
 
+  /* TRUE if __start_/__stop_ references do not retain C identifier name
+   * sections.  */
+  int start_stop_gc;
+
   /* May be used to set ELF visibility for __start_* / __stop_.  */
   unsigned int start_stop_visibility;
 
diff --git a/ld/NEWS b/ld/NEWS
index 4bb4ba3f466..dfb9e9ca66b 100644
--- a/ld/NEWS
+++ b/ld/NEWS
@@ -5,6 +5,9 @@
 * Add -z report-relative-reloc to x86 ELF linker to report dynamic
   relative relocations.
 
+* Add -z start-stop-gc to let __start_/__stop_ refeferences not retain
+  the associated C identifier name sections.
+
 Changes in 2.36:
 
 * Add libdep plugin, for linking dependencies of static libraries that
diff --git a/ld/emultempl/elf.em b/ld/emultempl/elf.em
index 5e59f3853ee..cea89e57e25 100644
--- a/ld/emultempl/elf.em
+++ b/ld/emultempl/elf.em
@@ -760,6 +760,10 @@ fragment <<EOF
 	{
 	  link_info.flags_1 |= DF_1_GLOBAUDIT;
 	}
+      else if (CONST_STRNEQ (optarg, "start-stop-gc"))
+	link_info.start_stop_gc = TRUE;
+      else if (CONST_STRNEQ (optarg, "nostart-stop-gc"))
+	link_info.start_stop_gc = FALSE;
       else if (CONST_STRNEQ (optarg, "start-stop-visibility="))
 	{
 	  if (strcmp (optarg, "start-stop-visibility=default") == 0)
diff --git a/ld/ld.texi b/ld/ld.texi
index 9643818e3ed..03a4966887f 100644
--- a/ld/ld.texi
+++ b/ld/ld.texi
@@ -1453,6 +1453,16 @@ Specify a stack size for an ELF @code{PT_GNU_STACK} segment.
 Specifying zero will override any default non-zero sized
 @code{PT_GNU_STACK} segment creation.
 
+@item start-stop-gc
+@itemx nostart-stop-gc
+@cindex start-stop-gc
+@code{__start_SECNAME} and @code{__stop_SECNAME} symbol references
+retain all input sections @code{SECNAME} by default as a workaround
+for some old programs. This makes GC ineffective on such sections.
+@samp{-z start-stop-gc} drops this rule and allows @code{SECNAME} to
+be discarded.  It is recommended to use the @code{SHF_GNU_RETAIN} flag
+to retain an input section, instead of relying on the special rule.
+
 @item start-stop-visibility=@var{value}
 @cindex visibility
 @cindex ELF symbol visibility
diff --git a/ld/ldlang.c b/ld/ldlang.c
index 5ffc8444c77..c9d764fc9ff 100644
--- a/ld/ldlang.c
+++ b/ld/ldlang.c
@@ -8089,7 +8089,7 @@ lang_process (void)
   /* Give initial values for __start and __stop symbols, so that  ELF
      gc_sections will keep sections referenced by these symbols.  Must
      be done before lang_do_assignments below.  */
-  if (config.build_constructors)
+  if (config.build_constructors && !link_info.start_stop_gc)
     lang_init_start_stop ();
 
   /* PR 13683: We must rerun the assignments prior to running garbage
@@ -8161,7 +8161,7 @@ lang_process (void)
   /* Defining __start/__stop symbols early for --gc-sections to work
      around a glibc build problem can result in these symbols being
      defined when they should not be.  Fix them now.  */
-  if (config.build_constructors)
+  if (config.build_constructors && !link_info.start_stop_gc)
     lang_undef_start_stop ();
 
   /* Define .startof./.sizeof. symbols with preliminary values before
diff --git a/ld/ldmain.c b/ld/ldmain.c
index 5c88ee744f8..7a3c02aeaa6 100644
--- a/ld/ldmain.c
+++ b/ld/ldmain.c
@@ -357,6 +357,7 @@ main (int argc, char **argv)
 #ifdef DEFAULT_NEW_DTAGS
   link_info.new_dtags = DEFAULT_NEW_DTAGS;
 #endif
+  link_info.start_stop_gc = FALSE;
   link_info.start_stop_visibility = STV_PROTECTED;
 
   ldfile_add_arch ("");
diff --git a/ld/testsuite/ld-gc/gc.exp b/ld/testsuite/ld-gc/gc.exp
index b3245bb915e..67489ee8d04 100644
--- a/ld/testsuite/ld-gc/gc.exp
+++ b/ld/testsuite/ld-gc/gc.exp
@@ -89,6 +89,7 @@ test_gc "Check --gc-section/-r/-u" "gcrel" $ld "-r --gc-sections -u used_func"
 run_dump_test "noent"
 run_dump_test "abi-note"
 run_dump_test "start"
+run_dump_test "start-2"
 run_dump_test "stop"
 run_dump_test "pr19167"
 if { [is_elf_format] } then {
diff --git a/ld/testsuite/ld-gc/start-2.d b/ld/testsuite/ld-gc/start-2.d
new file mode 100644
index 00000000000..b1f0d6ba8fc
--- /dev/null
+++ b/ld/testsuite/ld-gc/start-2.d
@@ -0,0 +1,11 @@
+#name: --gc-sections with __start_
+#source: start.s
+#ld: --gc-sections -e _start -z start-stop-gc
+#nm: -n
+#target: *-*-linux* *-*-gnu* arm*-*-uclinuxfdpiceabi
+#xfail: frv-*-* metag-*-*
+
+#failif
+#...
+[0-9a-f]+ D +__start__foo
+#...
diff --git a/ld/testsuite/ld-gc/start.s b/ld/testsuite/ld-gc/start.s
index a417a97b22c..b0084a188ae 100644
--- a/ld/testsuite/ld-gc/start.s
+++ b/ld/testsuite/ld-gc/start.s
@@ -1,5 +1,6 @@
 .globl _start
 _start:
+	.weak	__start__foo
 	.dc.a	__start__foo
 	.section	_foo,"aw",%progbits
 foo:
-- 
2.30.1.766.gb4fecdf3b7-goog



More information about the Binutils mailing list