This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [PATCH] Fix up --enable-initfini-array autodetection in configure (PR bootstrap/50237)


Paolo Bonzini <bonzini@gnu.org> writes:

> This must be a separate macro in acinclude.m4 that is AC_REQUIREd from
> gcc_AC_INITFINI_ARRAY.

Here's an updated patch that does so.  During testing, I found one
additional complication, though.  With the Sun as/GNU ld combination on
Solaris 11/x86, after the bootstrap had completed, all programs linked
against libgcc_s.so.1 SEGVed with a stacktrace like this:

Program received signal SIGSEGV, Segmentation fault.
[Switching to Thread 1 (LWP 1)]
0x00002000 in ?? ()
(gdb) where
#0  0x00002000 in ?? ()
#1  0xfefcd73f in call_array () from /usr/lib/ld.so.1
#2  0xfefcd8bd in call_init () from /usr/lib/ld.so.1
#3  0xfefcc8e1 in setup () from /usr/lib/ld.so.1
#4  0xfefdcfd8 in _setup () from /usr/lib/ld.so.1
#5  0xfefc0674 in _rt_boot () from /usr/lib/ld.so.1
#6  0x0804796c in ?? ()
#7  0x08047ab0 in ?? ()
Backtrace stopped: previous frame inner to this frame (corrupt stack?)

The problem turned out to be that with

	.section        .init_array

as generates 

Section Header[5]:  sh_name: .init_array
    sh_addr:      0               sh_flags:   0
    sh_size:      0x4             sh_type:    [ SHT_PROGBITS ]
    sh_offset:    0x344           sh_entsize: 0
    sh_link:      0               sh_info:    0
    sh_addralign: 0x4       

i.e. empty sh_flags.  gld seems to mishandle this, since the
corresponding .initarray entry is bad, as can be seen with runtime
linker debugging:

$ LD_DEBUG=init LD_PRELOAD=./libgcc_s.so.1 ls
[...]
02032: 1: calling .initarray[0]:0xfed77100: ./libgcc_s.so.1
02032: 1: calling .initarray[1]:0x2000: ./libgcc_s.so.1
Segmentation Fault

If I change the above to

	.section        .init_array,"aw",@progbits

everything works fine with as/gld, but breaks again with gas/gld since
gas warns about @progbits here.  It turned out that 

	.section        .init_array,"aw"

is fine with both assemblers, while as doesn't understand @init_array.
That's what the patch below uses.

> Can you test Linux too?  The change of -e0 looks good, but I'd rather check
> on the actual system.

This patch has been bootstrapped on i386-pc-solaris2.{8, 9, 10, 11} with
as/ld, gas/ld and gas/gld, i386-pc-solaris2.11 with as/gld, as well as
x86_64-unknown-linux-gnu, correctly detecting .init_array etc. support
on the gld configurations.  It was also included with
sparc-sun-solaris2.* bootstraps, but even with gas/gld the configure
test fails.  I've got to investigate that separately.

Ok for mainline now?

Thanks.
	Rainer


2012-01-20  Rainer Orth  <ro@CeBiTec.Uni-Bielefeld.DE>

	PR target/50166
	* acinclude.m4 (gcc_AC_INITFINI_ARRAY): Require gcc_SUN_LD_VERSION.
	Define _start.
	Remove -e 0 from $gcc_cv_ld invocation.
	Only use __GLIBC_PREREQ if defined.
	Enable on Solaris since Solaris 8 patch.
	(gcc_SUN_LD_VERSION): New macro.
	* configure.ac (ld_ver) <*-*-solaris2*>: Refer to
	gcc_SUN_LD_VERSION for version number format.
	* configure: Regenerate.
	* varasm.c (get_elf_initfini_array_priority_section): Use
	get_section instead of get_unnamed_section to emit
	.init_array/.fini_array with default priority.

# HG changeset patch
# Parent f6f07805e84c98b61a355272d359379b57cca7d2
Enable initfini array support on Solaris

diff --git a/gcc/acinclude.m4 b/gcc/acinclude.m4
--- a/gcc/acinclude.m4
+++ b/gcc/acinclude.m4
@@ -1,4 +1,5 @@
-dnl Copyright (C) 2005, 2006, 2007, 2008, 2011 Free Software Foundation, Inc.
+dnl Copyright (C) 2005, 2006, 2007, 2008, 2011, 2012
+dnl Free Software Foundation, Inc.
 dnl
 dnl This file is part of GCC.
 dnl
@@ -370,7 +371,8 @@ fi
 fi])
 
 AC_DEFUN([gcc_AC_INITFINI_ARRAY],
-[AC_ARG_ENABLE(initfini-array,
+[AC_REQUIRE([gcc_SUN_LD_VERSION])dnl
+AC_ARG_ENABLE(initfini-array,
 	[  --enable-initfini-array	use .init_array/.fini_array sections],
 	[], [
 AC_CACHE_CHECK(for .preinit_array/.init_array/.fini_array support,
@@ -427,9 +429,11 @@ int (*fp) (void) __attribute__ ((section
 .balign 4
 .byte 'H', 'H', 'H', 'H'
 .text
+.globl _start
+_start:
 EOF
 	  if $gcc_cv_as -o conftest.o conftest.s > /dev/null 2>&1 \
-	     && $gcc_cv_ld -e 0 -o conftest conftest.o > /dev/null 2>&1 \
+	     && $gcc_cv_ld -o conftest conftest.o > /dev/null 2>&1 \
 	     && $gcc_cv_objdump -s -j .init_array conftest \
 		| grep HHHHFFFFDDDDBBBB > /dev/null 2>&1 \
 	     && $gcc_cv_objdump -s -j .fini_array conftest \
@@ -442,14 +446,38 @@ changequote([,])dnl
 	fi
 	AC_PREPROC_IFELSE([AC_LANG_SOURCE([
 #ifndef __ELF__
-#error Not an ELF OS
+# error Not an ELF OS
 #endif
 #include <stdlib.h>
-#if defined __GLIBC_PREREQ && __GLIBC_PREREQ (2, 4)
+#if defined __GLIBC_PREREQ
+# if __GLIBC_PREREQ (2, 4)
+# else
+#  error GLIBC 2.4 required
+# endif
 #else
-#error The C library not known to support .init_array/.fini_array
+# if defined __sun__ && defined __svr4__
+   /* Solaris ld.so.1 supports .init_array/.fini_array since Solaris 8.  */
+# else
+#  error The C library not known to support .init_array/.fini_array
+# endif
 #endif
-])],, [gcc_cv_initfini_array=no]);;
+])],[
+    case "${target}" in
+      *-*-solaris2.8*)
+	# .init_array/.fini_array support was introduced in Solaris 8
+	# patches 109147-08 (sparc) and 109148-08 (x86).  Since ld.so.1 and
+	# ld are guaranteed to be updated in lockstep, we can check ld -V
+	# instead.  Unfortunately, proper ld version numbers were only
+	# introduced in rev. -14, so we check for that.
+  	if test "$gcc_cv_sun_ld_vers_minor" -lt 272; then
+	  gcc_cv_initfini_array=no
+	fi
+      ;;
+      *-*-solaris2.9* | *-*-solaris2.1[[0-9]]*)
+        # .init_array/.fini_array support is present since Solaris 9 FCS.
+        ;;
+    esac
+], [gcc_cv_initfini_array=no]);;
     esac
   else
     AC_MSG_CHECKING(cross compile... guessing)
@@ -569,6 +597,43 @@ if test $[$2] = yes; then
   $7
 fi])])
 
+dnl gcc_SUN_LD_VERSION
+dnl
+dnl Determines Sun linker version numbers, setting gcc_cv_sun_ld_vers to
+dnl the complete version number and gcc_cv_sun_ld_vers_{major, minor} to
+dnl the corresponding fields.
+dnl
+dnl ld and ld.so.1 are guaranteed to be updated in lockstep, so ld version
+dnl numbers can be used in ld.so.1 feature checks even if a different
+dnl linker is configured.
+dnl
+AC_DEFUN([gcc_SUN_LD_VERSION],
+[changequote(,)dnl
+if test "x${build}" = "x${target}" && test "x${build}" = "x${host}"; then
+  case "${target}" in
+    *-*-solaris2*)
+      #
+      # Solaris 2 ld -V output looks like this for a regular version:
+      #
+      # ld: Software Generation Utilities - Solaris Link Editors: 5.11-1.1699
+      #
+      # but test versions add stuff at the end:
+      #
+      # ld: Software Generation Utilities - Solaris Link Editors: 5.11-1.1701:onnv-ab196087-6931056-03/25/10
+      #
+      gcc_cv_sun_ld_ver=`/usr/ccs/bin/ld -V 2>&1`
+      if echo "$gcc_cv_sun_ld_ver" | grep 'Solaris Link Editors' > /dev/null; then
+	gcc_cv_sun_ld_vers=`echo $gcc_cv_sun_ld_ver | sed -n \
+	  -e 's,^.*: 5\.[0-9][0-9]*-\([0-9]\.[0-9][0-9]*\).*$,\1,p'`
+	gcc_cv_sun_ld_vers_major=`expr "$gcc_cv_sun_ld_vers" : '\([0-9]*\)'`
+	gcc_cv_sun_ld_vers_minor=`expr "$gcc_cv_sun_ld_vers" : '[0-9]*\.\([0-9]*\)'`
+      fi
+      ;;
+  esac
+fi
+changequote([,])dnl
+])
+
 dnl GCC_TARGET_TEMPLATE(KEY)
 dnl ------------------------
 dnl Define KEY as a valid configure key on the target machine.
diff --git a/gcc/configure b/gcc/configure
--- a/gcc/configure
+++ b/gcc/configure
@@ -22214,15 +22214,11 @@ if test $in_tree_ld != yes ; then
   else
     case "${target}" in
       *-*-solaris2*)
+	# See acinclude.m4 (gcc_SUN_LD_VERSION) for the version number
+	# format.
 	#
-	# Solaris 2 ld -V output looks like this for a regular version:
-	#
-	# ld: Software Generation Utilities - Solaris Link Editors: 5.11-1.1699
-	#
-	# but test versions add stuff at the end:
-	#
-	# ld: Software Generation Utilities - Solaris Link Editors: 5.11-1.1701:onnv-ab196087-6931056-03/25/10
-	#
+	# Don't reuse gcc_gv_sun_ld_vers_* in case a linker other than
+	# /usr/ccs/bin/ld has been configured.
 	ld_ver=`$gcc_cv_ld -V 2>&1`
 	if echo "$ld_ver" | grep 'Solaris Link Editors' > /dev/null; then
 	  ld_vers=`echo $ld_ver | sed -n \
@@ -22350,6 +22346,29 @@ fi
 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $gcc_cv_ld_ro_rw_mix" >&5
 $as_echo "$gcc_cv_ld_ro_rw_mix" >&6; }
 
+if test "x${build}" = "x${target}" && test "x${build}" = "x${host}"; then
+  case "${target}" in
+    *-*-solaris2*)
+      #
+      # Solaris 2 ld -V output looks like this for a regular version:
+      #
+      # ld: Software Generation Utilities - Solaris Link Editors: 5.11-1.1699
+      #
+      # but test versions add stuff at the end:
+      #
+      # ld: Software Generation Utilities - Solaris Link Editors: 5.11-1.1701:onnv-ab196087-6931056-03/25/10
+      #
+      gcc_cv_sun_ld_ver=`/usr/ccs/bin/ld -V 2>&1`
+      if echo "$gcc_cv_sun_ld_ver" | grep 'Solaris Link Editors' > /dev/null; then
+	gcc_cv_sun_ld_vers=`echo $gcc_cv_sun_ld_ver | sed -n \
+	  -e 's,^.*: 5\.[0-9][0-9]*-\([0-9]\.[0-9][0-9]*\).*$,\1,p'`
+	gcc_cv_sun_ld_vers_major=`expr "$gcc_cv_sun_ld_vers" : '\([0-9]*\)'`
+	gcc_cv_sun_ld_vers_minor=`expr "$gcc_cv_sun_ld_vers" : '[0-9]*\.\([0-9]*\)'`
+      fi
+      ;;
+  esac
+fi
+
 # Check whether --enable-initfini-array was given.
 if test "${enable_initfini_array+set}" = set; then :
   enableval=$enable_initfini_array;
@@ -22425,9 +22444,11 @@ fi
 .balign 4
 .byte 'H', 'H', 'H', 'H'
 .text
+.globl _start
+_start:
 EOF
 	  if $gcc_cv_as -o conftest.o conftest.s > /dev/null 2>&1 \
-	     && $gcc_cv_ld -e 0 -o conftest conftest.o > /dev/null 2>&1 \
+	     && $gcc_cv_ld -o conftest conftest.o > /dev/null 2>&1 \
 	     && $gcc_cv_objdump -s -j .init_array conftest \
 		| grep HHHHFFFFDDDDBBBB > /dev/null 2>&1 \
 	     && $gcc_cv_objdump -s -j .fini_array conftest \
@@ -22440,17 +22461,41 @@ EOF
 /* end confdefs.h.  */
 
 #ifndef __ELF__
-#error Not an ELF OS
+# error Not an ELF OS
 #endif
 #include <stdlib.h>
-#if defined __GLIBC_PREREQ && __GLIBC_PREREQ (2, 4)
+#if defined __GLIBC_PREREQ
+# if __GLIBC_PREREQ (2, 4)
+# else
+#  error GLIBC 2.4 required
+# endif
 #else
-#error The C library not known to support .init_array/.fini_array
+# if defined __sun__ && defined __svr4__
+   /* Solaris ld.so.1 supports .init_array/.fini_array since Solaris 8.  */
+# else
+#  error The C library not known to support .init_array/.fini_array
+# endif
 #endif
 
 _ACEOF
 if ac_fn_c_try_cpp "$LINENO"; then :
 
+    case "${target}" in
+      *-*-solaris2.8*)
+	# .init_array/.fini_array support was introduced in Solaris 8
+	# patches 109147-08 (sparc) and 109148-08 (x86).  Since ld.so.1 and
+	# ld are guaranteed to be updated in lockstep, we can check ld -V
+	# instead.  Unfortunately, proper ld version numbers were only
+	# introduced in rev. -14, so we check for that.
+  	if test "$gcc_cv_sun_ld_vers_minor" -lt 272; then
+	  gcc_cv_initfini_array=no
+	fi
+      ;;
+      *-*-solaris2.9* | *-*-solaris2.1[0-9]*)
+        # .init_array/.fini_array support is present since Solaris 9 FCS.
+        ;;
+    esac
+
 else
   gcc_cv_initfini_array=no
 fi
diff --git a/gcc/configure.ac b/gcc/configure.ac
--- a/gcc/configure.ac
+++ b/gcc/configure.ac
@@ -2296,15 +2296,11 @@ if test $in_tree_ld != yes ; then
   else
     case "${target}" in
       *-*-solaris2*)
+	# See acinclude.m4 (gcc_SUN_LD_VERSION) for the version number
+	# format.
 	#
-	# Solaris 2 ld -V output looks like this for a regular version:
-	#
-	# ld: Software Generation Utilities - Solaris Link Editors: 5.11-1.1699
-	#
-	# but test versions add stuff at the end:
-	#
-	# ld: Software Generation Utilities - Solaris Link Editors: 5.11-1.1701:onnv-ab196087-6931056-03/25/10
-	#
+	# Don't reuse gcc_gv_sun_ld_vers_* in case a linker other than
+	# /usr/ccs/bin/ld has been configured.
 	ld_ver=`$gcc_cv_ld -V 2>&1`
 	if echo "$ld_ver" | grep 'Solaris Link Editors' > /dev/null; then
 	  ld_vers=`echo $ld_ver | sed -n \
diff --git a/gcc/varasm.c b/gcc/varasm.c
--- a/gcc/varasm.c
+++ b/gcc/varasm.c
@@ -7669,16 +7669,16 @@ get_elf_initfini_array_priority_section 
 	{
 	  if (elf_init_array_section == NULL)
 	    elf_init_array_section
-	      = get_unnamed_section (0, output_section_asm_op,
-				     "\t.section\t.init_array");
+	      = get_section (".init_array",
+			     SECTION_WRITE | SECTION_NOTYPE, NULL_TREE);
 	  sec = elf_init_array_section;
 	}
       else
 	{
 	  if (elf_fini_array_section == NULL)
 	    elf_fini_array_section
-	      = get_unnamed_section (0, output_section_asm_op,
-				     "\t.section\t.fini_array");
+	      = get_section (".fini_array",
+			     SECTION_WRITE | SECTION_NOTYPE, NULL_TREE);
 	  sec = elf_fini_array_section;
 	}
     }
-- 
-----------------------------------------------------------------------------
Rainer Orth, Center for Biotechnology, Bielefeld University

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]