diff mbox

Fix up --enable-initfini-array autodetection in configure (PR bootstrap/50237)

Message ID 20120118232441.GO18768@tyan-ft48-01.lab.bos.redhat.com
State New
Headers show

Commit Message

Jakub Jelinek Jan. 18, 2012, 11:24 p.m. UTC
Hi!

As discussed in the PR, compiling the initfini testcase with the
host compiler and running it is problematic for bootstrap, as
in stage1 we use the host compiler which might use one version of as/ld,
but stage2 is using stage1 compiler as host compiler and might use
a different as/ld.  If one of the linkers does support merging of
.init_array and .ctors properly and the other does not, we end up
with comparison failures e.g. because of go1 C++ sources.

The following patch attempts to perform a separate linker check
(grepping objdump of a linked binary) and checks so far glibc version
which is known to support .init_array properly.  Perhaps other
C libraries could be added there too (does e.g. Solaris support .init_array
properly, or FreeBSD, other OSes?).

Bootstrapped/regtested on x86_64-linux and i686-linux both with a linker
that does it right and a buggy one.

2012-01-18  Jakub Jelinek  <jakub@redhat.com>

	PR bootstrap/50237
	* config/initfini-array.h: Guard content of the header
	with #ifdef HAVE_INITFINI_ARRAY.
	* configure.ac: Move gcc_AC_INITFINI_ARRAY much later into the file.
	Add initfini-array.h to tm_file here.
	* acinclude.m4 (gcc_AC_INITFINI_ARRAY): For non-ia64 do a linker
	test.
	* config.gcc: Don't add initfini-array.h to tm_file here.
	* configure: Regenerated.


	Jakub

Comments

Paolo Bonzini Jan. 19, 2012, 8:54 a.m. UTC | #1
On 01/19/2012 12:24 AM, Jakub Jelinek wrote:
>     if test "x${build}" = "x${target}"&&  test "x${build}" = "x${host}"; then

This test is no longer necessary, is it? ia64 does its own cross-compile 
detection via AC_RUN_IFELSE, and other hosts are cross-compile safe. 
The patch is okay if you remove it.

H.J., can ia64 fall back to the common test when cross compiling?  Or 
perhaps even always?

Paolo
Jakub Jelinek Jan. 19, 2012, 9:06 a.m. UTC | #2
On Thu, Jan 19, 2012 at 09:54:43AM +0100, Paolo Bonzini wrote:
> On 01/19/2012 12:24 AM, Jakub Jelinek wrote:
> >    if test "x${build}" = "x${target}"&&  test "x${build}" = "x${host}"; then
> 
> This test is no longer necessary, is it? ia64 does its own
> cross-compile detection via AC_RUN_IFELSE, and other hosts are
> cross-compile safe. The patch is okay if you remove it.

While the linker test is done using the target linker (it uses default
linker flags btw, so in case a linker would be buggy for one target and not
for a different target also supported by the same linker, it would be
a problem, but let's assume that the linker is either buggy or not for
all targets it supports), AC_PREPROC_IFELSE is done using the host compiler.
For cross-compiling we would need to check the target libc headers.
For glibc we could certainly do something similar to the
    case "$target" in
       *-*-linux* | *-*-kfreebsd*-gnu | *-*-knetbsd*-gnu)
      [# glibc 2.4 and later provides __stack_chk_fail and
      # either __stack_chk_guard, or TLS access to stack guard canary.
      if test -f $target_header_dir/features.h \
         && $EGREP '^[  ]*#[    ]*define[       ]+__GNU_LIBRARY__[ 	]+([1-9][0-9]|[6-9])' \
            $target_header_dir/features.h > /dev/null; then
        if $EGREP '^[   ]*#[    ]*define[       ]+__GLIBC__[ 	]+([1-9][0-9]|[3-9])' \
           $target_header_dir/features.h > /dev/null; then
          gcc_cv_libc_provides_ssp=yes
        elif $EGREP '^[         ]*#[    ]*define[       ]+__GLIBC__[    ]+2' \
             $target_header_dir/features.h > /dev/null \
             && $EGREP '^[      ]*#[    ]*define[       ]+__GLIBC_MINOR__[ 	]+([1-9][0-9]|[4-9])' \
             $target_header_dir/features.h > /dev/null; then
          gcc_cv_libc_provides_ssp=yes
        fi
      fi]
test configure already does (and glibc only supports ELF targets, so
the ELF check could be avoided).

> H.J., can ia64 fall back to the common test when cross compiling?
> Or perhaps even always?

I've kept ia64 as is because that is what we did for ia64 configure already
in 4.6 and earlier.  As ia64 was using .init_array etc. far before the
linker merging of .ctors and .init_array has been fixed, probably it just
switched over to .init_array completely many years ago or something.

	Jakub
Paolo Bonzini Jan. 19, 2012, 9:29 a.m. UTC | #3
On 01/19/2012 10:06 AM, Jakub Jelinek wrote:
> While the linker test is done using the target linker (it uses default
> linker flags btw, so in case a linker would be buggy for one target and not
> for a different target also supported by the same linker, it would be
> a problem, but let's assume that the linker is either buggy or not for
> all targets it supports), AC_PREPROC_IFELSE is done using the host compiler.
> For cross-compiling we would need to check the target libc headers.

Ah, right, so the patch is okay.

> For glibc we could certainly do something similar to the
>      case "$target" in
>         *-*-linux* | *-*-kfreebsd*-gnu | *-*-knetbsd*-gnu)
>        [# glibc 2.4 and later provides __stack_chk_fail and
>        # either __stack_chk_guard, or TLS access to stack guard canary.
>        if test -f $target_header_dir/features.h \
>           &&  $EGREP '^[  ]*#[    ]*define[       ]+__GNU_LIBRARY__[ 	]+([1-9][0-9]|[6-9])' \
>              $target_header_dir/features.h>  /dev/null; then
>          if $EGREP '^[   ]*#[    ]*define[       ]+__GLIBC__[ 	]+([1-9][0-9]|[3-9])' \
>             $target_header_dir/features.h>  /dev/null; then
>            gcc_cv_libc_provides_ssp=yes
>          elif $EGREP '^[         ]*#[    ]*define[       ]+__GLIBC__[    ]+2' \
>               $target_header_dir/features.h>  /dev/null \
>               &&  $EGREP '^[      ]*#[    ]*define[       ]+__GLIBC_MINOR__[ 	]+([1-9][0-9]|[4-9])' \
>               $target_header_dir/features.h>  /dev/null; then
>            gcc_cv_libc_provides_ssp=yes
>          fi
>        fi]

Or something like

(cat $target_header_dir/features.h;
  echo glibc_so_ver=__GNU_LIBRARY__
  echo glibc_ver=__GLIBC__
  echo glibc_minor_ver=__GLIBC_MINOR__) | gcc -x c - | \
  grep ^glibc.*ver= > glibc-ver.sh
. glibc.sh

which could be moved more easily to a helper macro.

Paolo
Jakub Jelinek Feb. 22, 2012, 3:05 p.m. UTC | #4
On Wed, Feb 22, 2012 at 03:55:34PM +0100, Ulrich Weigand wrote:
> However, the macro HAVE_INITFINI_ARRAY is defined anyway; this
> definition is done by an internal "newlib.h" header that is pulled
> in via the <stdio.h> include in GCC's "tsystem.h".  [ This is clearly
> a violation of C namespace rules, but this has been the situation
> for all newlib releases since about 2005 ... ]

Ugh, clearly newlib bug...

> Any suggestions how to proceed with this welcome!  I'd really
> like to see this fixed for 4.7, otherwise the compiler will be
> seriously broken ...

I guess the easiest would be just to rename the gcc HAVE_INITFINI_ARRAY
macro to something else, HAVE_INITFINI_ARRAY_SUPPORT or whatever.

	Jakub
Jakub Jelinek Feb. 23, 2012, 10:05 a.m. UTC | #5
On Thu, Feb 23, 2012 at 11:03:47AM +0100, Ulrich Weigand wrote:
> OK for mainline?

Yes, thanks.

	Jakub
diff mbox

Patch

--- gcc/config/initfini-array.h.jj	2011-08-22 08:17:06.000000000 +0200
+++ gcc/config/initfini-array.h	2012-01-17 16:28:39.219571262 +0100
@@ -19,6 +19,8 @@ 
    along with GCC; see the file COPYING3.  If not see
    <http://www.gnu.org/licenses/>.  */
 
+#ifdef HAVE_INITFINI_ARRAY
+
 #define USE_INITFINI_ARRAY
 
 #undef INIT_SECTION_ASM_OP
@@ -35,3 +37,5 @@ 
 #define TARGET_ASM_CONSTRUCTOR default_elf_init_array_asm_out_constructor
 #undef TARGET_ASM_DESTRUCTOR
 #define TARGET_ASM_DESTRUCTOR default_elf_fini_array_asm_out_destructor
+
+#endif
--- gcc/configure.ac.jj	2012-01-13 21:47:35.000000000 +0100
+++ gcc/configure.ac	2012-01-17 16:28:00.461795315 +0100
@@ -1197,8 +1197,6 @@  fi
 CFLAGS="$saved_CFLAGS"
 CXXFLAGS="$saved_CXXFLAGS"
 
-gcc_AC_INITFINI_ARRAY
-
 # mkdir takes a single argument on some systems. 
 gcc_AC_FUNC_MKDIR_TAKES_ONE_ARG
 
@@ -1271,6 +1269,11 @@  if test x"$tmake_file" = x
 then tmake_file=$cpu_type/t-$cpu_type
 fi
 
+# Support --enable-initfini-array.
+if test x$enable_initfini_array != xno; then
+  tm_file="${tm_file} initfini-array.h"
+fi
+
 if test x"$dwarf2" = xyes
 then tm_file="$tm_file tm-dwarf2.h"
 fi
@@ -2422,6 +2425,8 @@  if test x$gcc_cv_ld_ro_rw_mix = xread-wr
 fi
 AC_MSG_RESULT($gcc_cv_ld_ro_rw_mix)
 
+gcc_AC_INITFINI_ARRAY
+
 # Check if we have .[us]leb128, and support symbol arithmetic with it.
 gcc_GAS_CHECK_FEATURE([.sleb128 and .uleb128], gcc_cv_as_leb128,
   [elf,2,11,0],,
--- gcc/acinclude.m4.jj	2011-08-26 18:41:44.000000000 +0200
+++ gcc/acinclude.m4	2012-01-18 20:41:51.448002554 +0100
@@ -376,119 +376,85 @@  AC_DEFUN([gcc_AC_INITFINI_ARRAY],
 AC_CACHE_CHECK(for .preinit_array/.init_array/.fini_array support,
 		 gcc_cv_initfini_array, [dnl
   if test "x${build}" = "x${target}" && test "x${build}" = "x${host}"; then
-    AC_RUN_IFELSE([AC_LANG_SOURCE([
+    case "${target}" in
+      ia64-*)
+	AC_RUN_IFELSE([AC_LANG_SOURCE([
 #ifndef __ELF__
 #error Not an ELF OS
 #endif
-#ifdef __ia64__
 /* We turn on .preinit_array/.init_array/.fini_array support for ia64
    if it can be used.  */
 static int x = -1;
 int main (void) { return x; }
 int foo (void) { x = 0; }
 int (*fp) (void) __attribute__ ((section (".init_array"))) = foo;
-#else
-extern void abort ();
-static int count;
-
-static void
-init1005 ()
-{
-  if (count != 0)
-    abort ();
-  count = 1005;
-}
-void (*const init_array1005[]) ()
-  __attribute__ ((section (".init_array.01005"), aligned (sizeof (void *))))
-  = { init1005 };
-static void
-fini1005 ()
-{
-  if (count != 1005)
-    abort ();
-}
-void (*const fini_array1005[]) ()
-  __attribute__ ((section (".fini_array.01005"), aligned (sizeof (void *))))
-  = { fini1005 };
-
-static void
-ctor1007 ()
-{
-  if (count != 1005)
-    abort ();
-  count = 1007;
-}
-void (*const ctors1007[]) ()
-  __attribute__ ((section (".ctors.64528"), aligned (sizeof (void *))))
-  = { ctor1007 };
-static void
-dtor1007 ()
-{
-  if (count != 1007)
-    abort ();
-  count = 1005;
-}
-void (*const dtors1007[]) ()
-  __attribute__ ((section (".dtors.64528"), aligned (sizeof (void *))))
-  = { dtor1007 };
-
-static void
-init65530 ()
-{
-  if (count != 1007)
-    abort ();
-  count = 65530;
-}
-void (*const init_array65530[]) ()
-  __attribute__ ((section (".init_array.65530"), aligned (sizeof (void *))))
-  = { init65530 };
-static void
-fini65530 ()
-{
-  if (count != 65530)
-    abort ();
-  count = 1007;
-}
-void (*const fini_array65530[]) ()
-  __attribute__ ((section (".fini_array.65530"), aligned (sizeof (void *))))
-  = { fini65530 };
-
-static void
-ctor65535 ()
-{
-  if (count != 65530)
-    abort ();
-  count = 65535;
-}
-void (*const ctors65535[]) ()
-  __attribute__ ((section (".ctors"), aligned (sizeof (void *))))
-  = { ctor65535 };
-static void
-dtor65535 ()
-{
-  if (count != 65535)
-    abort ();
-  count = 65530;
-}
-void (*const dtors65535[]) ()
-  __attribute__ ((section (".dtors"), aligned (sizeof (void *))))
-  = { dtor65535 };
-
-int
-main ()
-{
-  if (count != 65535)
-    abort ();
-  return 0;
-}
-#endif
 ])],
 	     [gcc_cv_initfini_array=yes], [gcc_cv_initfini_array=no],
-	     [gcc_cv_initfini_array=no])
-   else
-     AC_MSG_CHECKING(cross compile... guessing)
-     gcc_cv_initfini_array=no
-   fi])
+	     [gcc_cv_initfini_array=no]);;
+      *)
+	gcc_cv_initfini_array=no
+	if test $in_tree_ld = yes ; then
+	  if test "$gcc_cv_gld_major_version" -eq 2 \
+	     -a "$gcc_cv_gld_minor_version" -ge 22 \
+	     -o "$gcc_cv_gld_major_version" -gt 2 \
+	     && test $in_tree_ld_is_elf = yes; then
+	    gcc_cv_initfini_array=yes
+	  fi
+	elif test x$gcc_cv_as != x -a x$gcc_cv_ld != x -a x$gcc_cv_objdump != x ; then
+	  cat > conftest.s <<\EOF
+.section .dtors,"a",%progbits
+.balign 4
+.byte 'A', 'A', 'A', 'A'
+.section .ctors,"a",%progbits
+.balign 4
+.byte 'B', 'B', 'B', 'B'
+.section .fini_array.65530,"a",%progbits
+.balign 4
+.byte 'C', 'C', 'C', 'C'
+.section .init_array.65530,"a",%progbits
+.balign 4
+.byte 'D', 'D', 'D', 'D'
+.section .dtors.64528,"a",%progbits
+.balign 4
+.byte 'E', 'E', 'E', 'E'
+.section .ctors.64528,"a",%progbits
+.balign 4
+.byte 'F', 'F', 'F', 'F'
+.section .fini_array.01005,"a",%progbits
+.balign 4
+.byte 'G', 'G', 'G', 'G'
+.section .init_array.01005,"a",%progbits
+.balign 4
+.byte 'H', 'H', 'H', 'H'
+.text
+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_objdump -s -j .init_array conftest \
+		| grep HHHHFFFFDDDDBBBB > /dev/null 2>&1 \
+	     && $gcc_cv_objdump -s -j .fini_array conftest \
+		| grep GGGGEEEECCCCAAAA > /dev/null 2>&1; then
+	    gcc_cv_initfini_array=yes
+	  fi
+changequote(,)dnl
+	  rm -f conftest conftest.*
+changequote([,])dnl
+	fi
+	AC_PREPROC_IFELSE([AC_LANG_SOURCE([
+#ifndef __ELF__
+#error Not an ELF OS
+#endif
+#include <stdlib.h>
+#if defined __GLIBC_PREREQ && __GLIBC_PREREQ (2, 4)
+#else
+#error The C library not known to support .init_array/.fini_array
+#endif
+])],, [gcc_cv_initfini_array=no]);;
+    esac
+  else
+    AC_MSG_CHECKING(cross compile... guessing)
+    gcc_cv_initfini_array=no
+  fi])
   enable_initfini_array=$gcc_cv_initfini_array
 ])
 if test $enable_initfini_array = yes; then
--- gcc/config.gcc.jj	2012-01-02 20:39:59.000000000 +0100
+++ gcc/config.gcc	2012-01-17 16:26:54.442178715 +0100
@@ -2941,11 +2941,6 @@  if test x$with_schedule = x; then
 	esac
 fi
 
-# Support --enable-initfini-array.
-if test x$enable_initfini_array = xyes; then
-  tm_file="${tm_file} initfini-array.h"
-fi
-
 # Validate and mark as valid any --with options supported
 # by this target.  In order to use a particular --with option
 # you must list it in supported_defaults; validating the value
--- gcc/configure.jj	2012-01-13 21:47:35.000000000 +0100
+++ gcc/configure	2012-01-18 20:42:14.193761057 +0100
@@ -893,7 +893,6 @@  enable_languages
 with_multilib_list
 enable_rpath
 with_libiconv_prefix
-enable_initfini_array
 enable_sjlj_exceptions
 enable_secureplt
 enable_leading_mingw64_underscores
@@ -906,6 +905,7 @@  enable_fast_install
 enable_libtool_lock
 with_plugin_ld
 enable_gnu_indirect_function
+enable_initfini_array
 enable_comdat
 enable_gnu_unique_object
 enable_linker_build_id
@@ -1591,7 +1591,6 @@  Optional Features:
   --disable-shared        don't provide a shared libgcc
   --enable-languages=LIST specify which front-ends to build
   --disable-rpath         do not hardcode runtime library paths
-  --enable-initfini-array	use .init_array/.fini_array sections
   --enable-sjlj-exceptions
                           arrange to use setjmp/longjmp exception handling
   --enable-secureplt      enable -msecure-plt by default for PowerPC
@@ -1615,6 +1614,7 @@  Optional Features:
   --enable-gnu-indirect-function
                           enable the use of the @gnu_indirect_function to
                           glibc systems
+  --enable-initfini-array	use .init_array/.fini_array sections
   --enable-comdat         enable COMDAT group support
   --enable-gnu-unique-object
                           enable the use of the @gnu_unique_object ELF
@@ -10986,157 +10986,6 @@  fi
 CFLAGS="$saved_CFLAGS"
 CXXFLAGS="$saved_CXXFLAGS"
 
-# Check whether --enable-initfini-array was given.
-if test "${enable_initfini_array+set}" = set; then :
-  enableval=$enable_initfini_array;
-else
-
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for .preinit_array/.init_array/.fini_array support" >&5
-$as_echo_n "checking for .preinit_array/.init_array/.fini_array support... " >&6; }
-if test "${gcc_cv_initfini_array+set}" = set; then :
-  $as_echo_n "(cached) " >&6
-else
-    if test "x${build}" = "x${target}" && test "x${build}" = "x${host}"; then
-    if test "$cross_compiling" = yes; then :
-  gcc_cv_initfini_array=no
-else
-  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h.  */
-
-#ifndef __ELF__
-#error Not an ELF OS
-#endif
-#ifdef __ia64__
-/* We turn on .preinit_array/.init_array/.fini_array support for ia64
-   if it can be used.  */
-static int x = -1;
-int main (void) { return x; }
-int foo (void) { x = 0; }
-int (*fp) (void) __attribute__ ((section (".init_array"))) = foo;
-#else
-extern void abort ();
-static int count;
-
-static void
-init1005 ()
-{
-  if (count != 0)
-    abort ();
-  count = 1005;
-}
-void (*const init_array1005) ()
-  __attribute__ ((section (".init_array.01005"), aligned (sizeof (void *))))
-  = { init1005 };
-static void
-fini1005 ()
-{
-  if (count != 1005)
-    abort ();
-}
-void (*const fini_array1005) ()
-  __attribute__ ((section (".fini_array.01005"), aligned (sizeof (void *))))
-  = { fini1005 };
-
-static void
-ctor1007 ()
-{
-  if (count != 1005)
-    abort ();
-  count = 1007;
-}
-void (*const ctors1007) ()
-  __attribute__ ((section (".ctors.64528"), aligned (sizeof (void *))))
-  = { ctor1007 };
-static void
-dtor1007 ()
-{
-  if (count != 1007)
-    abort ();
-  count = 1005;
-}
-void (*const dtors1007) ()
-  __attribute__ ((section (".dtors.64528"), aligned (sizeof (void *))))
-  = { dtor1007 };
-
-static void
-init65530 ()
-{
-  if (count != 1007)
-    abort ();
-  count = 65530;
-}
-void (*const init_array65530) ()
-  __attribute__ ((section (".init_array.65530"), aligned (sizeof (void *))))
-  = { init65530 };
-static void
-fini65530 ()
-{
-  if (count != 65530)
-    abort ();
-  count = 1007;
-}
-void (*const fini_array65530) ()
-  __attribute__ ((section (".fini_array.65530"), aligned (sizeof (void *))))
-  = { fini65530 };
-
-static void
-ctor65535 ()
-{
-  if (count != 65530)
-    abort ();
-  count = 65535;
-}
-void (*const ctors65535) ()
-  __attribute__ ((section (".ctors"), aligned (sizeof (void *))))
-  = { ctor65535 };
-static void
-dtor65535 ()
-{
-  if (count != 65535)
-    abort ();
-  count = 65530;
-}
-void (*const dtors65535) ()
-  __attribute__ ((section (".dtors"), aligned (sizeof (void *))))
-  = { dtor65535 };
-
-int
-main ()
-{
-  if (count != 65535)
-    abort ();
-  return 0;
-}
-#endif
-
-_ACEOF
-if ac_fn_c_try_run "$LINENO"; then :
-  gcc_cv_initfini_array=yes
-else
-  gcc_cv_initfini_array=no
-fi
-rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
-  conftest.$ac_objext conftest.beam conftest.$ac_ext
-fi
-
-   else
-     { $as_echo "$as_me:${as_lineno-$LINENO}: checking cross compile... guessing" >&5
-$as_echo_n "checking cross compile... guessing... " >&6; }
-     gcc_cv_initfini_array=no
-   fi
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gcc_cv_initfini_array" >&5
-$as_echo "$gcc_cv_initfini_array" >&6; }
-  enable_initfini_array=$gcc_cv_initfini_array
-
-fi
-
-if test $enable_initfini_array = yes; then
-
-$as_echo "#define HAVE_INITFINI_ARRAY 1" >>confdefs.h
-
-fi
-
 # mkdir takes a single argument on some systems.
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking if mkdir takes one argument" >&5
 $as_echo_n "checking if mkdir takes one argument... " >&6; }
@@ -11255,6 +11104,11 @@  if test x"$tmake_file" = x
 then tmake_file=$cpu_type/t-$cpu_type
 fi
 
+# Support --enable-initfini-array.
+if test x$enable_initfini_array != xno; then
+  tm_file="${tm_file} initfini-array.h"
+fi
+
 if test x"$dwarf2" = xyes
 then tm_file="$tm_file tm-dwarf2.h"
 fi
@@ -18116,7 +17970,7 @@  else
   lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
   lt_status=$lt_dlunknown
   cat > conftest.$ac_ext <<_LT_EOF
-#line 18119 "configure"
+#line 17973 "configure"
 #include "confdefs.h"
 
 #if HAVE_DLFCN_H
@@ -18222,7 +18076,7 @@  else
   lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
   lt_status=$lt_dlunknown
   cat > conftest.$ac_ext <<_LT_EOF
-#line 18225 "configure"
+#line 18079 "configure"
 #include "confdefs.h"
 
 #if HAVE_DLFCN_H
@@ -22496,6 +22350,130 @@  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; }
 
+# Check whether --enable-initfini-array was given.
+if test "${enable_initfini_array+set}" = set; then :
+  enableval=$enable_initfini_array;
+else
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for .preinit_array/.init_array/.fini_array support" >&5
+$as_echo_n "checking for .preinit_array/.init_array/.fini_array support... " >&6; }
+if test "${gcc_cv_initfini_array+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+    if test "x${build}" = "x${target}" && test "x${build}" = "x${host}"; then
+    case "${target}" in
+      ia64-*)
+	if test "$cross_compiling" = yes; then :
+  gcc_cv_initfini_array=no
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+#ifndef __ELF__
+#error Not an ELF OS
+#endif
+/* We turn on .preinit_array/.init_array/.fini_array support for ia64
+   if it can be used.  */
+static int x = -1;
+int main (void) { return x; }
+int foo (void) { x = 0; }
+int (*fp) (void) __attribute__ ((section (".init_array"))) = foo;
+
+_ACEOF
+if ac_fn_c_try_run "$LINENO"; then :
+  gcc_cv_initfini_array=yes
+else
+  gcc_cv_initfini_array=no
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
+  conftest.$ac_objext conftest.beam conftest.$ac_ext
+fi
+;;
+      *)
+	gcc_cv_initfini_array=no
+	if test $in_tree_ld = yes ; then
+	  if test "$gcc_cv_gld_major_version" -eq 2 \
+	     -a "$gcc_cv_gld_minor_version" -ge 22 \
+	     -o "$gcc_cv_gld_major_version" -gt 2 \
+	     && test $in_tree_ld_is_elf = yes; then
+	    gcc_cv_initfini_array=yes
+	  fi
+	elif test x$gcc_cv_as != x -a x$gcc_cv_ld != x -a x$gcc_cv_objdump != x ; then
+	  cat > conftest.s <<\EOF
+.section .dtors,"a",%progbits
+.balign 4
+.byte 'A', 'A', 'A', 'A'
+.section .ctors,"a",%progbits
+.balign 4
+.byte 'B', 'B', 'B', 'B'
+.section .fini_array.65530,"a",%progbits
+.balign 4
+.byte 'C', 'C', 'C', 'C'
+.section .init_array.65530,"a",%progbits
+.balign 4
+.byte 'D', 'D', 'D', 'D'
+.section .dtors.64528,"a",%progbits
+.balign 4
+.byte 'E', 'E', 'E', 'E'
+.section .ctors.64528,"a",%progbits
+.balign 4
+.byte 'F', 'F', 'F', 'F'
+.section .fini_array.01005,"a",%progbits
+.balign 4
+.byte 'G', 'G', 'G', 'G'
+.section .init_array.01005,"a",%progbits
+.balign 4
+.byte 'H', 'H', 'H', 'H'
+.text
+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_objdump -s -j .init_array conftest \
+		| grep HHHHFFFFDDDDBBBB > /dev/null 2>&1 \
+	     && $gcc_cv_objdump -s -j .fini_array conftest \
+		| grep GGGGEEEECCCCAAAA > /dev/null 2>&1; then
+	    gcc_cv_initfini_array=yes
+	  fi
+	  rm -f conftest conftest.*
+	fi
+	cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+#ifndef __ELF__
+#error Not an ELF OS
+#endif
+#include <stdlib.h>
+#if defined __GLIBC_PREREQ && __GLIBC_PREREQ (2, 4)
+#else
+#error The C library not known to support .init_array/.fini_array
+#endif
+
+_ACEOF
+if ac_fn_c_try_cpp "$LINENO"; then :
+
+else
+  gcc_cv_initfini_array=no
+fi
+rm -f conftest.err conftest.$ac_ext;;
+    esac
+  else
+    { $as_echo "$as_me:${as_lineno-$LINENO}: checking cross compile... guessing" >&5
+$as_echo_n "checking cross compile... guessing... " >&6; }
+    gcc_cv_initfini_array=no
+  fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gcc_cv_initfini_array" >&5
+$as_echo "$gcc_cv_initfini_array" >&6; }
+  enable_initfini_array=$gcc_cv_initfini_array
+
+fi
+
+if test $enable_initfini_array = yes; then
+
+$as_echo "#define HAVE_INITFINI_ARRAY 1" >>confdefs.h
+
+fi
+
 # Check if we have .[us]leb128, and support symbol arithmetic with it.
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler for .sleb128 and .uleb128" >&5
 $as_echo_n "checking assembler for .sleb128 and .uleb128... " >&6; }