[PATCH] Workaround ld 2.18 --gc-sections issues (PR middle-end/46790)

Jakub Jelinek jakub@redhat.com
Tue Feb 22 09:19:00 GMT 2011


Hi!

GNU linkers around 2.18 don't handle --gc-sections together with
Honza's recent changes where say main is put into
.text.startup.main
section instead of
.text.main
but .gcc_except_table hunks go into
.gcc_except_table.main
Even older linkers will just emit one big .gcc_except_table and don't
have this problem.
IMHO either we can add a workaround as in the patch below (this one
will cause it to just use .text.main instead of .text.startup.main or
.text.foo instead of .text.exit.foo like in 4.5 and earlier with old buggy
linkers), or force .gcc_except_table instead of .gcc_except_table.main
even for 2.18-ish linkers instead of just 2.17-ish and earlier
(untested such patch is in the PR), or maybe (but would leave that to Honza)
arrange for .gcc_except_table hunks in those cases to go into
.gcc_except_table.startup.main or .gcc_except_table.exit.foo
sections.

I've bootstrapped/regtested this on x86_64-linux and i686-linux (with recent
linker) and tested configury + cc1plus build against old linker and looked
up on the problematic testcase.

2011-02-22  Jakub Jelinek  <jakub@redhat.com>

	PR middle-end/46790
	* configure.ac (HAVE_LD_EH_GC_SECTIONS_BUG): New test.
	* configure: Regenerated.
	* config.in: Regenerated.
	* varasm.c (default_function_section): Return NULL
	if HAVE_LD_EH_GC_SECTIONS_BUG and decl has implicit
	section name.

--- gcc/configure.ac.jj	2011-02-21 19:26:30.000000000 +0100
+++ gcc/configure.ac	2011-02-21 19:41:59.000000000 +0100
@@ -4097,6 +4097,51 @@ if test x$gcc_cv_ld_eh_gc_sections = xye
 fi
 AC_MSG_RESULT($gcc_cv_ld_eh_gc_sections)
 
+AC_MSG_CHECKING(linker EH garbage collection of sections bug)
+gcc_cv_ld_eh_gc_sections_bug=no
+if test $in_tree_ld = yes ; then
+  if test "$gcc_cv_gld_major_version" -eq 2 -a "$gcc_cv_gld_minor_version" -lt 19 -o "$gcc_cv_gld_major_version" -lt 2 \
+     && test $in_tree_ld_is_elf = yes; then
+    gcc_cv_ld_eh_gc_sections_bug=yes
+  fi
+elif test x$gcc_cv_as != x -a x$gcc_cv_ld != x -a x$gcc_cv_objdump != x -a x$gcc_cv_as_comdat_group = xyes; then
+  gcc_cv_ld_eh_gc_sections_bug=yes
+  cat > conftest.s <<EOF
+	.section	.text
+.globl _start
+	.type _start, @function
+_start:
+	.long foo
+	.size _start, .-_start
+	.section	.text.startup.foo,"ax",@progbits
+	.type foo, @function
+foo:
+	.long 0
+	.size foo, .-foo
+	.section	.gcc_except_table.foo,"a",@progbits
+.L0:
+	.long 0
+	.section	.eh_frame,"a",@progbits
+	.long .L0
+EOF
+  if $gcc_cv_as -o conftest.o conftest.s > /dev/null 2>&1; then
+    if $gcc_cv_ld -o conftest conftest.o --entry=_start --gc-sections 2>&1 \
+	 | grep "gc-sections option ignored" > /dev/null; then
+      :
+    elif $gcc_cv_objdump -h conftest 2> /dev/null \
+	 | grep gcc_except_table > /dev/null; then
+      gcc_cv_ld_eh_gc_sections_bug=no
+    fi
+  fi
+  rm -f conftest.s conftest.o conftest
+fi
+if test x$gcc_cv_ld_eh_gc_sections_bug = xyes; then
+	AC_DEFINE(HAVE_LD_EH_GC_SECTIONS_BUG, 1,
+  [Define if your linker has buggy garbage collection of
+   sections support when .text.startup.foo like sections are used.])
+fi
+AC_MSG_RESULT($gcc_cv_ld_eh_gc_sections_bug)
+
 # --------
 # UNSORTED
 # --------
--- gcc/varasm.c.jj	2011-02-21 19:26:30.000000000 +0100
+++ gcc/varasm.c	2011-02-21 19:43:37.000000000 +0100
@@ -554,6 +554,15 @@ section *
 default_function_section (tree decl, enum node_frequency freq,
 			  bool startup, bool exit)
 {
+#if defined HAVE_LD_EH_GC_SECTIONS && defined HAVE_LD_EH_GC_SECTIONS_BUG
+  /* Old GNU linkers have buggy --gc-section support, which sometimes
+     results in .gcc_except_table* sections being garbage collected.  */
+  if (decl
+      && DECL_SECTION_NAME (decl)
+      && DECL_HAS_IMPLICIT_SECTION_NAME_P (decl))
+    return NULL;
+#endif
+
   if (!flag_reorder_functions
       || !targetm.have_named_sections)
     return NULL;
--- gcc/config.in.jj	2011-02-21 19:26:30.000000000 +0100
+++ gcc/config.in	2011-02-21 19:42:26.000000000 +0100
@@ -1171,6 +1171,13 @@
 #endif
 
 
+/* Define if your linker has buggy garbage collection of sections support when
+   .text.startup.foo like sections are used. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_LD_EH_GC_SECTIONS_BUG
+#endif
+
+
 /* Define if your PowerPC64 linker supports a large TOC. */
 #ifndef USED_FOR_TARGET
 #undef HAVE_LD_LARGE_TOC
--- gcc/configure.jj	2011-02-21 19:26:29.000000000 +0100
+++ gcc/configure	2011-02-21 19:42:24.000000000 +0100
@@ -25442,6 +25442,53 @@ fi
 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $gcc_cv_ld_eh_gc_sections" >&5
 $as_echo "$gcc_cv_ld_eh_gc_sections" >&6; }
 
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking linker EH garbage collection of sections bug" >&5
+$as_echo_n "checking linker EH garbage collection of sections bug... " >&6; }
+gcc_cv_ld_eh_gc_sections_bug=no
+if test $in_tree_ld = yes ; then
+  if test "$gcc_cv_gld_major_version" -eq 2 -a "$gcc_cv_gld_minor_version" -lt 19 -o "$gcc_cv_gld_major_version" -lt 2 \
+     && test $in_tree_ld_is_elf = yes; then
+    gcc_cv_ld_eh_gc_sections_bug=yes
+  fi
+elif test x$gcc_cv_as != x -a x$gcc_cv_ld != x -a x$gcc_cv_objdump != x -a x$gcc_cv_as_comdat_group = xyes; then
+  gcc_cv_ld_eh_gc_sections_bug=yes
+  cat > conftest.s <<EOF
+	.section	.text
+.globl _start
+	.type _start, @function
+_start:
+	.long foo
+	.size _start, .-_start
+	.section	.text.startup.foo,"ax",@progbits
+	.type foo, @function
+foo:
+	.long 0
+	.size foo, .-foo
+	.section	.gcc_except_table.foo,"a",@progbits
+.L0:
+	.long 0
+	.section	.eh_frame,"a",@progbits
+	.long .L0
+EOF
+  if $gcc_cv_as -o conftest.o conftest.s > /dev/null 2>&1; then
+    if $gcc_cv_ld -o conftest conftest.o --entry=_start --gc-sections 2>&1 \
+	 | grep "gc-sections option ignored" > /dev/null; then
+      :
+    elif $gcc_cv_objdump -h conftest 2> /dev/null \
+	 | grep gcc_except_table > /dev/null; then
+      gcc_cv_ld_eh_gc_sections_bug=no
+    fi
+  fi
+  rm -f conftest.s conftest.o conftest
+fi
+if test x$gcc_cv_ld_eh_gc_sections_bug = xyes; then
+
+$as_echo "#define HAVE_LD_EH_GC_SECTIONS_BUG 1" >>confdefs.h
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gcc_cv_ld_eh_gc_sections_bug" >&5
+$as_echo "$gcc_cv_ld_eh_gc_sections_bug" >&6; }
+
 # --------
 # UNSORTED
 # --------

	Jakub



More information about the Gcc-patches mailing list