diff mbox

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

Message ID yddwr7ouipv.fsf@manam.CeBiTec.Uni-Bielefeld.DE
State New
Headers show

Commit Message

Rainer Orth Feb. 15, 2012, 5:09 p.m. UTC
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.

Comments

Paolo Bonzini Feb. 15, 2012, 5:16 p.m. UTC | #1
On 02/15/2012 06:09 PM, Rainer Orth wrote:
> 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.

Build parts are okay.  I cannot approve the varasm.c changes.

Paolo
Richard Biener Feb. 16, 2012, 9:32 a.m. UTC | #2
On Wed, Feb 15, 2012 at 6:09 PM, Rainer Orth
<ro@cebitec.uni-bielefeld.de> wrote:
> 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.

I'm not sure about the varasm.c change - it's definitely not a no-op
(callback will be not set, and the flags will be different).  Certainly
the current code is inconsistent wrt the priority != DEFAULT_INIT_PRIORITY
case, not sure why, but you don't make it consistent either because
you don't change that case to SECTION_NOTYPE either.  I'd be fine
with it with both calls using SECTION_NOTYPE, but would like to
know what the callback difference is about.

HJ, can you shed some light on this?

Thx,
Richard.

> 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.
>
>
>
> --
> -----------------------------------------------------------------------------
> Rainer Orth, Center for Biotechnology, Bielefeld University
>
H.J. Lu Feb. 16, 2012, 5:14 p.m. UTC | #3
On Thu, Feb 16, 2012 at 1:32 AM, Richard Guenther
<richard.guenther@gmail.com> wrote:
> On Wed, Feb 15, 2012 at 6:09 PM, Rainer Orth
> <ro@cebitec.uni-bielefeld.de> wrote:
>> 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.
>
> I'm not sure about the varasm.c change - it's definitely not a no-op
> (callback will be not set, and the flags will be different).  Certainly
> the current code is inconsistent wrt the priority != DEFAULT_INIT_PRIORITY
> case, not sure why, but you don't make it consistent either because
> you don't change that case to SECTION_NOTYPE either.  I'd be fine
> with it with both calls using SECTION_NOTYPE, but would like to
> know what the callback difference is about.
>
> HJ, can you shed some light on this?
>

GNU assembler understands:

.section        .init_array*

If Solaris assembler doesn't, I don't know how it will work
with .init_array with priority.
Rainer Orth Feb. 16, 2012, 8:16 p.m. UTC | #4
"H.J. Lu" <hjl.tools@gmail.com> writes:

> GNU assembler understands:
>
> .section        .init_array*
>
> If Solaris assembler doesn't, I don't know how it will work
> with .init_array with priority.

That's not the issue: merging .init_array* sections is handled all right
by gld irrespective of sh_type; there's nothing required from the
assembler here.

My problem is different: consider

$ cat ia-no-sht.s
        .section .init_array
$ cat ia-no-sht-f.s
        .section .init_array,"aw"

If I assemble this with gas 2.22, I get the same section header for both
inputs:

gas/ia-no-sht.o:


Section Header[4]:  sh_name: .init_array
    sh_addr:      0               sh_flags:   [ SHF_WRITE SHF_ALLOC ]
    sh_size:      0               sh_type:    [ SHT_INIT_ARRAY ]
    sh_offset:    0x34            sh_entsize: 0
    sh_link:      0               sh_info:    0
    sh_addralign: 0x1       

gas/ia-no-sht-f.o:


Section Header[4]:  sh_name: .init_array
    sh_addr:      0               sh_flags:   [ SHF_WRITE SHF_ALLOC ]
    sh_size:      0               sh_type:    [ SHT_INIT_ARRAY ]
    sh_offset:    0x34            sh_entsize: 0
    sh_link:      0               sh_info:    0
    sh_addralign: 0x1       

With as instead, I get

as/ia-no-sht.o:


Section Header[3]:  sh_name: .init_array
    sh_addr:      0               sh_flags:   0
    sh_size:      0               sh_type:    [ SHT_PROGBITS ]
    sh_offset:    0x59            sh_entsize: 0
    sh_link:      0               sh_info:    0
    sh_addralign: 0x1       

as/ia-no-sht-f.o:


Section Header[3]:  sh_name: .init_array
    sh_addr:      0               sh_flags:   [ SHF_WRITE SHF_ALLOC ]
    sh_size:      0               sh_type:    [ SHT_PROGBITS ]
    sh_offset:    0x59            sh_entsize: 0
    sh_link:      0               sh_info:    0
    sh_addralign: 0x1       


The problem is not the wrong sh_type (SHT_PROGBITS instead of
SHT_INIT_ARRAY): gld handles both input sections alike and doesn't care.
Rather, the 0 sh_flags when no section flags are specified seem to cause
gld to mishandle the resulting objects.

So for gas, my patch makes no difference, but fixes/works around the
problematic as/gld combo.

	Rainer
Rainer Orth Feb. 16, 2012, 8:33 p.m. UTC | #5
Richard Guenther <richard.guenther@gmail.com> writes:

> I'm not sure about the varasm.c change - it's definitely not a no-op
> (callback will be not set, and the flags will be different).  Certainly

As I've demonstrated in my response to H.J., the effect with gas is none.

> the current code is inconsistent wrt the priority != DEFAULT_INIT_PRIORITY
> case, not sure why, but you don't make it consistent either because
> you don't change that case to SECTION_NOTYPE either.  I'd be fine

I didn't find a need for that, but agree that the inconsistency is
disturbing.  default_section_type_flags suggests that SECTION_NOTYPE
should be set for .init_array and friends, but it's only used by
get_named_section.

> with it with both calls using SECTION_NOTYPE, but would like to
> know what the callback difference is about.

I don't think the callback is needed, which is effectively a

	printf ("\t.section\t.init_array");

Looking at it, this is e.g. wrong for Sun as on SPARC, which requires
the section name to be in double quotes.

	Rainer
diff mbox

Patch

# 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;
 	}
     }