Bug 40027 - [4.4/4.5 regression] i686-pc-solaris2.10 bootstrap fails using Sun ld
Bug#: 40027 Product:  gcc Version: 4.4.0
Host: i686-pc-solaris2.10 Target: i686-pc-solaris2.10 Build: i686-pc-solaris2.10
Status: RESOLVED Severity: normal Priority: P4
Resolution: FIXED Assigned To: ro@gcc.gnu.org Reported By: jwakely.gcc@gmail.com
Component: bootstrap Target Milestone: 4.4.1
Summary: [4.4/4.5 regression] i686-pc-solaris2.10 bootstrap fails using Sun ld
Keywords:  build
Opened: 2009-05-05 15:18
Description:   Last confirmed: 2009-05-06 13:01 Opened: 2009-05-05 15:18
As first reported here:
http://gcc.gnu.org/ml/gcc-help/2009-04/msg00292.html

bootstrapping 4.4.0 fails on Solaris 10 x86 if you configure with
--build=i686-pc-solaris2.10

/var/tmp/build-gcc/gcc-4.4.0/configure --prefix=/opt/gcc/32-bit/4.4.0
--enable-languages=c --with-gnu-as
--with-as=/var/tmp/build-gcc/binutils_2.18/bin/as --without-gnu-ld
--with-ld=/usr/ccs/bin/ld --with-gmp=/var/tmp/build-gcc/stage
--with-mpfr=/var/tmp/build-gcc/stage --with-system-zlib
--build=i686-pc-solaris2.10

/var/tmp/build/stage contains gmp-4.2.3 and mpfr-2.3.1 both built with
--disable-shared, /var/tmp/build-gcc/binutils_2.18 contains (unsurprisingly)
binutils 2.18

As recommended I'm using GNU as and Sun ld, but the build fails with:

/bin/bash /var/tmp/build-gcc/gcc-4.4.0/libgcc/../mkinstalldirs .
/var/tmp/build-gcc/gcc/./gcc/xgcc -B/var/tmp/build-gcc/gcc/./gcc/
-B/opt/gcc/32-bit/4.4.0/i686-pc-solaris2.10/bin/
-B/opt/gcc/32-bit/4.4.0/i686-pc-solaris2.10/lib/ -isystem
/opt/gcc/32-bit/4.4.0/i686-pc-solaris2.10/include -isystem
/opt/gcc/32-bit/4.4.0/i686-pc-solaris2.10/sys-include -O2  -g -O2 -DIN_GCC   -W
-Wall -Wwrite-strings -Wstrict-prototypes -Wmissing-prototypes -Wcast-qual
-Wold-style-definition  -isystem ./include  -fPIC -g -DHAVE_GTHR_DEFAULT
-DIN_LIBGCC2 -D__GCC_FLOAT_NOT_NEEDED  -shared -nodefaultlibs
-Wl,-h,libgcc_s.so.1 -Wl,-z,text -Wl,-z,defs -Wl,-M,libgcc.map -o
./libgcc_s.so.1.tmp -g -O2 -B./ _muldi3_s.o _negdi2_s.o _lshrdi3_s.o
_ashldi3_s.o _ashrdi3_s.o _cmpdi2_s.o _ucmpdi2_s.o _clear_cache_s.o
_enable_execute_stack_s.o _trampoline_s.o __main_s.o _absvsi2_s.o _absvdi2_s.o
_addvsi3_s.o _addvdi3_s.o _subvsi3_s.o _subvdi3_s.o _mulvsi3_s.o _mulvdi3_s.o
_negvsi2_s.o _negvdi2_s.o _ctors_s.o _ffssi2_s.o _ffsdi2_s.o _clz_s.o
_clzsi2_s.o _clzdi2_s.o _ctzsi2_s.o _ctzdi2_s.o _popcount_tab_s.o
_popcountsi2_s.o _popcountdi2_s.o _paritysi2_s.o _paritydi2_s.o _powisf2_s.o
_powidf2_s.o _powixf2_s.o _powitf2_s.o _mulsc3_s.o _muldc3_s.o _mulxc3_s.o
_multc3_s.o _divsc3_s.o _divdc3_s.o _divxc3_s.o _divtc3_s.o _bswapsi2_s.o
_bswapdi2_s.o _fixunssfsi_s.o _fixunsdfsi_s.o _fixunsxfsi_s.o _fixsfdi_s.o
_fixdfdi_s.o _fixxfdi_s.o _fixtfdi_s.o _fixunssfdi_s.o _fixunsdfdi_s.o
_fixunsxfdi_s.o _fixunstfdi_s.o _floatdisf_s.o _floatdidf_s.o _floatdixf_s.o
_floatditf_s.o _floatundisf_s.o _floatundidf_s.o _floatundixf_s.o
_floatunditf_s.o _divdi3_s.o _moddi3_s.o _udivdi3_s.o _umoddi3_s.o
_udiv_w_sdiv_s.o _udivmoddi4_s.o unwind-dw2_s.o unwind-dw2-fde_s.o
unwind-sjlj_s.o gthr-gnat_s.o unwind-c_s.o emutls_s.o -lc && rm -f
./libgcc_s.so && if [ -f ./libgcc_s.so.1 ]; then mv -f ./libgcc_s.so.1
./libgcc_s.so.1.backup; else true; fi && mv ./libgcc_s.so.1.tmp ./libgcc_s.so.1
&& ln -s libgcc_s.so.1 ./libgcc_s.so
ld: fatal: symbol `__i686.get_pc_thunk.bx' is multiply-defined:
        (file /var/tmp/build-gcc/gcc/./gcc/crtbegin.o type=FUNC; file
_enable_execute_stack_s.o type=FUNC);
ld: fatal: symbol `__i686.get_pc_thunk.bx' is multiply-defined:
        (file /var/tmp/build-gcc/gcc/./gcc/crtbegin.o type=FUNC; file
_absvsi2_s.o type=FUNC);
ld: fatal: symbol `__i686.get_pc_thunk.bx' is multiply-defined:
        (file /var/tmp/build-gcc/gcc/./gcc/crtbegin.o type=FUNC; file
_absvdi2_s.o type=FUNC);
ld: fatal: symbol `__i686.get_pc_thunk.bx' is multiply-defined:
        (file /var/tmp/build-gcc/gcc/./gcc/crtbegin.o type=FUNC; file
_addvsi3_s.o type=FUNC);
ld: fatal: symbol `__i686.get_pc_thunk.bx' is multiply-defined:
        (file /var/tmp/build-gcc/gcc/./gcc/crtbegin.o type=FUNC; file
_addvdi3_s.o type=FUNC);
ld: fatal: symbol `__i686.get_pc_thunk.bx' is multiply-defined:
        (file /var/tmp/build-gcc/gcc/./gcc/crtbegin.o type=FUNC; file
_subvsi3_s.o type=FUNC);
ld: fatal: symbol `__i686.get_pc_thunk.bx' is multiply-defined:
        (file /var/tmp/build-gcc/gcc/./gcc/crtbegin.o type=FUNC; file
_subvdi3_s.o type=FUNC);
ld: fatal: symbol `__i686.get_pc_thunk.bx' is multiply-defined:
        (file /var/tmp/build-gcc/gcc/./gcc/crtbegin.o type=FUNC; file
_mulvsi3_s.o type=FUNC);
ld: fatal: symbol `__i686.get_pc_thunk.bx' is multiply-defined:
        (file /var/tmp/build-gcc/gcc/./gcc/crtbegin.o type=FUNC; file
_mulvdi3_s.o type=FUNC);
ld: fatal: symbol `__i686.get_pc_thunk.bx' is multiply-defined:
        (file /var/tmp/build-gcc/gcc/./gcc/crtbegin.o type=FUNC; file
_negvsi2_s.o type=FUNC);
ld: fatal: symbol `__i686.get_pc_thunk.bx' is multiply-defined:
        (file /var/tmp/build-gcc/gcc/./gcc/crtbegin.o type=FUNC; file
_negvdi2_s.o type=FUNC);
ld: fatal: symbol `__i686.get_pc_thunk.bx' is multiply-defined:
        (file /var/tmp/build-gcc/gcc/./gcc/crtbegin.o type=FUNC; file
_popcountsi2_s.o type=FUNC);
ld: fatal: symbol `__i686.get_pc_thunk.bx' is multiply-defined:
        (file /var/tmp/build-gcc/gcc/./gcc/crtbegin.o type=FUNC; file
_popcountdi2_s.o type=FUNC);
ld: fatal: symbol `__i686.get_pc_thunk.bx' is multiply-defined:
        (file /var/tmp/build-gcc/gcc/./gcc/crtbegin.o type=FUNC; file
_powisf2_s.o type=FUNC);
ld: fatal: symbol `__i686.get_pc_thunk.bx' is multiply-defined:
        (file /var/tmp/build-gcc/gcc/./gcc/crtbegin.o type=FUNC; file
_powidf2_s.o type=FUNC);
ld: fatal: symbol `__i686.get_pc_thunk.bx' is multiply-defined:
        (file /var/tmp/build-gcc/gcc/./gcc/crtbegin.o type=FUNC; file
_powixf2_s.o type=FUNC);
ld: fatal: symbol `__i686.get_pc_thunk.bx' is multiply-defined:
        (file /var/tmp/build-gcc/gcc/./gcc/crtbegin.o type=FUNC; file
_muldc3_s.o type=FUNC);
ld: fatal: symbol `__i686.get_pc_thunk.bx' is multiply-defined:
        (file /var/tmp/build-gcc/gcc/./gcc/crtbegin.o type=FUNC; file
_mulxc3_s.o type=FUNC);
ld: fatal: symbol `__i686.get_pc_thunk.cx' is multiply-defined:
        (file _mulsc3_s.o type=FUNC; file _divsc3_s.o type=FUNC);
ld: fatal: symbol `__i686.get_pc_thunk.bx' is multiply-defined:
        (file /var/tmp/build-gcc/gcc/./gcc/crtbegin.o type=FUNC; file
_divdc3_s.o type=FUNC);
ld: fatal: symbol `__i686.get_pc_thunk.bx' is multiply-defined:
        (file /var/tmp/build-gcc/gcc/./gcc/crtbegin.o type=FUNC; file
_divxc3_s.o type=FUNC);
ld: fatal: symbol `__i686.get_pc_thunk.cx' is multiply-defined:
        (file _mulsc3_s.o type=FUNC; file _fixunssfsi_s.o type=FUNC);
ld: fatal: symbol `__i686.get_pc_thunk.cx' is multiply-defined:
        (file _mulsc3_s.o type=FUNC; file _fixunsdfsi_s.o type=FUNC);
ld: fatal: symbol `__i686.get_pc_thunk.cx' is multiply-defined:
        (file _mulsc3_s.o type=FUNC; file _fixunsxfsi_s.o type=FUNC);
ld: fatal: symbol `__i686.get_pc_thunk.bx' is multiply-defined:
        (file /var/tmp/build-gcc/gcc/./gcc/crtbegin.o type=FUNC; file
_fixsfdi_s.o type=FUNC);
ld: fatal: symbol `__i686.get_pc_thunk.bx' is multiply-defined:
        (file /var/tmp/build-gcc/gcc/./gcc/crtbegin.o type=FUNC; file
_fixdfdi_s.o type=FUNC);
ld: fatal: symbol `__i686.get_pc_thunk.bx' is multiply-defined:
        (file /var/tmp/build-gcc/gcc/./gcc/crtbegin.o type=FUNC; file
_fixxfdi_s.o type=FUNC);
ld: fatal: symbol `__i686.get_pc_thunk.bx' is multiply-defined:
        (file /var/tmp/build-gcc/gcc/./gcc/crtbegin.o type=FUNC; file
_fixunssfdi_s.o type=FUNC);
ld: fatal: symbol `__i686.get_pc_thunk.bx' is multiply-defined:
        (file /var/tmp/build-gcc/gcc/./gcc/crtbegin.o type=FUNC; file
_fixunsdfdi_s.o type=FUNC);
ld: fatal: symbol `__i686.get_pc_thunk.bx' is multiply-defined:
        (file /var/tmp/build-gcc/gcc/./gcc/crtbegin.o type=FUNC; file
_fixunsxfdi_s.o type=FUNC);
ld: fatal: symbol `__i686.get_pc_thunk.bx' is multiply-defined:
        (file /var/tmp/build-gcc/gcc/./gcc/crtbegin.o type=FUNC; file
_floatdisf_s.o type=FUNC);
ld: fatal: symbol `__i686.get_pc_thunk.cx' is multiply-defined:
        (file _mulsc3_s.o type=FUNC; file _floatdidf_s.o type=FUNC);
ld: fatal: symbol `__i686.get_pc_thunk.cx' is multiply-defined:
        (file _mulsc3_s.o type=FUNC; file _floatdixf_s.o type=FUNC);
ld: fatal: symbol `__i686.get_pc_thunk.bx' is multiply-defined:
        (file /var/tmp/build-gcc/gcc/./gcc/crtbegin.o type=FUNC; file
_floatundisf_s.o type=FUNC);
ld: fatal: symbol `__i686.get_pc_thunk.cx' is multiply-defined:
        (file _mulsc3_s.o type=FUNC; file _floatundidf_s.o type=FUNC);
ld: fatal: symbol `__i686.get_pc_thunk.cx' is multiply-defined:
        (file _mulsc3_s.o type=FUNC; file _floatundixf_s.o type=FUNC);
ld: fatal: symbol `__i686.get_pc_thunk.cx' is multiply-defined:
        (file _mulsc3_s.o type=FUNC; file unwind-dw2_s.o type=FUNC);
ld: fatal: symbol `__i686.get_pc_thunk.bx' is multiply-defined:
        (file /var/tmp/build-gcc/gcc/./gcc/crtbegin.o type=FUNC; file
unwind-dw2_s.o type=FUNC);
ld: fatal: symbol `__i686.get_pc_thunk.cx' is multiply-defined:
        (file _mulsc3_s.o type=FUNC; file unwind-dw2-fde_s.o type=FUNC);
ld: fatal: symbol `__i686.get_pc_thunk.bx' is multiply-defined:
        (file /var/tmp/build-gcc/gcc/./gcc/crtbegin.o type=FUNC; file
unwind-dw2-fde_s.o type=FUNC);
ld: fatal: symbol `__i686.get_pc_thunk.cx' is multiply-defined:
        (file _mulsc3_s.o type=FUNC; file gthr-gnat_s.o type=FUNC);
ld: fatal: symbol `__i686.get_pc_thunk.bx' is multiply-defined:
        (file /var/tmp/build-gcc/gcc/./gcc/crtbegin.o type=FUNC; file
gthr-gnat_s.o type=FUNC);
ld: fatal: symbol `__i686.get_pc_thunk.bx' is multiply-defined:
        (file /var/tmp/build-gcc/gcc/./gcc/crtbegin.o type=FUNC; file
unwind-c_s.o type=FUNC);
ld: fatal: symbol `__i686.get_pc_thunk.cx' is multiply-defined:
        (file _mulsc3_s.o type=FUNC; file emutls_s.o type=FUNC);
ld: fatal: symbol `__i686.get_pc_thunk.bx' is multiply-defined:
        (file /var/tmp/build-gcc/gcc/./gcc/crtbegin.o type=FUNC; file
emutls_s.o type=FUNC);
ld: fatal: symbol `__i686.get_pc_thunk.bx' is multiply-defined:
        (file /var/tmp/build-gcc/gcc/./gcc/crtbegin.o type=FUNC; file
/var/tmp/build-gcc/gcc/./gcc/crtend.o type=FUNC);
ld: fatal: File processing errors. No output written to ./libgcc_s.so.1.tmp
collect2: ld returned 1 exit status
make[3]: *** [libgcc_s.so] Error 1
make[3]: Leaving directory `/var/tmp/build-gcc/gcc/i686-pc-solaris2.10/libgcc'
make[2]: *** [all-stage1-target-libgcc] Error 2
make[2]: Leaving directory `/var/tmp/build-gcc/gcc'
make[1]: *** [stage1-bubble] Error 2
make[1]: Leaving directory `/var/tmp/build-gcc/gcc'
make: *** [all] Error 2


The problem seems to be that gcc/configure in 4.4.0 was changed to
unconditionally set gcc_cv_ld_hidden=yes for Solaris targets:

       *-*-solaris2.9* | *-*-solaris2.1[0-9]*)
        gcc_cv_ld_hidden=yes
        ;;

$ grep gcc_cv_.._hidden gcc/config.log
gcc_cv_as_hidden=yes
gcc_cv_ld_hidden=yes

Judging by the failure, this doesn't seem to be correct.

A similar configuration using --build=i686-pc-solaris2.10 with 4.3.2
successfully bootstraps, because gcc/configure sets gcc_cv_ld_hidden=no

$ /usr/ccs/bin/ld -V
ld: Software Generation Utilities - Solaris Link Editors: 5.10-1.487
$ uname -a
SunOS xxx 5.10 Generic_127112-03 i86pc i386 i86pc

Is building for i686-pc-solaris2.10 no longer supported, is my linker too old,
or is gcc/configure making incorrect assumptions?

------- Comment #1 From Rainer Orth 2009-05-06 13:01 -------
I've just confirmed the bug on i686-pc-solaris2.10.  It doesn't occur on
i686-pc-solaris2.11, though, so this is indeed a Sun ld bug.

I've got a few questions to resolve, though:

* Why does generating code for i686 instead of i386 change gcc's assembler
output
  so significantly?

* Is it possible to get the relevant CRs backported to Solaris 10 (or are fixes
  already included in recent linker/kernel patches)?

* How to handle this in gcc/configure.ac?  I'd like to avoid completely
  disabling hidden support on Solaris 10 (and even early versions of Solaris 11
  before the linker bug got fixed).

------- Comment #2 From H.J. Lu 2009-05-06 14:51 -------
(In reply to comment #1)
> I've just confirmed the bug on i686-pc-solaris2.10.  It doesn't occur on
> i686-pc-solaris2.11, though, so this is indeed a Sun ld bug.
> 
> I've got a few questions to resolve, though:
> 
> * Why does generating code for i686 instead of i386 change gcc's assembler
> output
>   so significantly?
> 

The difference is in how to get PC for -fPIC:

bash-3.2$ cat p.c
void
foo ()
{
  bar ();
}
bash-3.2$ gcc -m32 -fPIC p.c -S -O3 -mtune=i386
bash-3.2$ cat p.s
        .file   "p.c"
        .text
        .p2align 2,,3
.globl foo
        .type   foo, @function
foo:
        pushl   %ebp
        movl    %esp, %ebp
        pushl   %ebx
        subl    $4, %esp
        call    .L3
.L3:
        popl    %ebx
        addl    $_GLOBAL_OFFSET_TABLE_+[.-.L3], %ebx
        call    bar@PLT
        popl    %eax
        popl    %ebx
        leave
        ret
        .size   foo, .-foo
        .ident  "GCC: (GNU) 4.3.2 20081105 (Red Hat 4.3.2-7)"
        .section        .note.GNU-stack,"",@progbits
bash-3.2$ gcc -m32 -fPIC p.c -S -O3 -mtune=i686
bash-3.2$ cat p.s
        .file   "p.c"
        .text
        .p2align 4,,15
.globl foo
        .type   foo, @function
foo:
        pushl   %ebp
        movl    %esp, %ebp
        pushl   %ebx
        call    __i686.get_pc_thunk.bx
        addl    $_GLOBAL_OFFSET_TABLE_, %ebx
        subl    $4, %esp
        call    bar@PLT
        addl    $4, %esp
        popl    %ebx
        popl    %ebp
        ret
        .size   foo, .-foo
        .ident  "GCC: (GNU) 4.3.2 20081105 (Red Hat 4.3.2-7)"
        .section       
.text.__i686.get_pc_thunk.bx,"axG",@progbits,__i686.get_pc_thunk.bx,comdat
.globl __i686.get_pc_thunk.bx
        .hidden __i686.get_pc_thunk.bx
        .type   __i686.get_pc_thunk.bx, @function
__i686.get_pc_thunk.bx:
        movl    (%esp), %ebx
        ret
        .section        .note.GNU-stack,"",@progbits
bash-3.2$ 

------- Comment #3 From Rainer Orth 2009-05-07 16:30 -------
Subject: Re:  [4.4/4.5 regression] i686-pc-solaris2.10 bootstrap fails using
Sun ld

hjl dot tools at gmail dot com writes:

> The difference is in how to get PC for -fPIC:
> 
> bash-3.2$ cat p.c
> void
> foo ()
> {
>   bar ();
> }
> bash-3.2$ gcc -m32 -fPIC p.c -S -O3 -mtune=i386
[...]
> bash-3.2$ gcc -m32 -fPIC p.c -S -O3 -mtune=i686
[...]

That's what I saw already when comparing crtbegin.s for i386 and i686.
What I still don't understand is why the code is different between those
two.

        Rainer

------- Comment #4 From Jakub Jelinek 2009-05-07 16:52 -------
Look for DEEP_BRANCH_PREDICTION in config/i386/*.  On i386/i486/i586 doing
call 1f; 1:
is just fine, but on several newer CPUs it confuses return prediction logic
(more calls than rets), so when optimizing for those CPUs gcc calls a separate
pad which just reads the return address from the stack and immediately returns.
This pad can be shared among all functions within the same binary or shared
library.  If hidden linkonce doesn't work on some Solaris version, you should
just make sure USE_HIDDEN_LINKONCE is 0 for that target.

------- Comment #5 From Rainer Orth 2009-05-13 13:02 -------
Subject: Re:  [4.4/4.5 regression] i686-pc-solaris2.10 bootstrap fails using
Sun ld

jakub at gcc dot gnu dot org writes:

> Look for DEEP_BRANCH_PREDICTION in config/i386/*.  On i386/i486/i586 doing
> call 1f; 1:
> is just fine, but on several newer CPUs it confuses return prediction logic
> (more calls than rets), so when optimizing for those CPUs gcc calls a separate
> pad which just reads the return address from the stack and immediately returns.
> This pad can be shared among all functions within the same binary or shared

Ok, thanks for the explanation.

> library.  If hidden linkonce doesn't work on some Solaris version, you should
> just make sure USE_HIDDEN_LINKONCE is 0 for that target.

Indeed: that far easier than determining which version of Sun ld has all
the necessary support.

Proposed patch here:

        http://gcc.gnu.org/ml/gcc-patches/2009-05/msg00723.html

Thanks.
        Rainer

------- Comment #6 From Rainer Orth 2009-05-25 12:12 -------
Subject: Bug 40027

Author: ro
Date: Mon May 25 12:12:08 2009
New Revision: 147845

URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=147845
Log:
        PR bootstrap/40027
        * config/i386/i386.c (USE_HIDDEN_LINKONCE): Only define if missing.
        * config/i386/sol2.h [!TARGET_GNU_LD] (USE_HIDDEN_LINKONCE): Define.

Modified:
    trunk/gcc/ChangeLog
    trunk/gcc/config/i386/i386.c
    trunk/gcc/config/i386/sol2.h

------- Comment #7 From Rainer Orth 2009-05-25 12:13 -------
Subject: Bug 40027

Author: ro
Date: Mon May 25 12:13:38 2009
New Revision: 147846

URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=147846
Log:
        PR bootstrap/40027
        * config/i386/i386.c (USE_HIDDEN_LINKONCE): Only define if missing.
        * config/i386/sol2.h [!TARGET_GNU_LD] (USE_HIDDEN_LINKONCE): Define.

Modified:
    branches/gcc-4_4-branch/gcc/ChangeLog
    branches/gcc-4_4-branch/gcc/config/i386/i386.c
    branches/gcc-4_4-branch/gcc/config/i386/sol2.h

------- Comment #8 From Rainer Orth 2009-05-25 12:56 -------
Fixed for 4.4.1, 4.5.0.