Bug 14992 - --as-needed patch makes -shared-libgcc the default on some systems
Summary: --as-needed patch makes -shared-libgcc the default on some systems
Alias: None
Product: gcc
Classification: Unclassified
Component: bootstrap (show other bugs)
Version: 3.4.0
: P2 critical
Target Milestone: 4.0.0
Assignee: Not yet assigned to anyone
Keywords: build, patch
Depends on:
Blocks: 16406 21782
  Show dependency treegraph
Reported: 2004-04-17 15:19 UTC by rsandifo@gcc.gnu.org
Modified: 2005-05-30 14:46 UTC (History)
6 users (show)

See Also:
Host: mips-sgi-irix6.5
Target: mips-sgi-irix6.5
Build: mips-sgi-irix6.5
Known to work:
Known to fail:
Last reconfirmed: 2004-04-18 15:54:40


Note You need to log in before you can comment on or make changes to this bug.
Description rsandifo@gcc.gnu.org 2004-04-17 15:19:10 UTC

The following 3.4 patch:

2004-04-01  Alan Modra  <amodra@bigpond.net.au>
	    Jakub Jelinek  <jakub@redhat.com>

	* gcc.c (init_gcc_specs): If HAVE_LD_AS_NEEDED, link with
	-lgcc --as-needed -lgcc_s --no-as-needed by default.
	* configure.ac (HAVE_LD_AS_NEEDED): Check for ld --as-needed.
	* configure: Rebuilt.
	* config.in: Rebuilt.
	* Makefile.in (stage1-start): Copy also libgcc_s*$(SHLIB_EXT).
	(stage2-start, stage3-start, stage4-start): Likewise.
	(stageprofile-start, stagefeedback-start): Likewise.

effectively makes -shared-libgcc the default for mips-sgi-irix6.5 when
using binutils 2.15.  This seems undesirable for its own sake, and breaks
bootstrap unless you take elaborate countermeasures.  It also wasn't the
intended effect of the patch.

Although the problem only seems to have been reported for IRIX so far,
I believe it could occur on most hosted, non-glibc ELF systems if
binutils 2.15 is used.


The rationale for the patch can be found here:


As I understand it, the problem described in the message above can be
solved simply by linking with -shared-libgcc.  The purpose of the patch
is to make this extra option unnecessary.

It seems that, on glibc systems, symbols in libgcc_s.so are only
referenced by code that needs to use the EH routines.  The default
behaviour can therefore be to link against libgcc_s.so "as needed".

Unfortunately, the patch seems to be very invasive.  It changes the
default link line for all targets whose binutils support --as-needed
linking of shared libraries.  And not all targets follow the glibc model
wrt EH routines.

An initial posting about the problem can be found here:


It boils down to target-specific variations in crtbegin.o.
In particular, crtstuff.c contains:

#if defined(OBJECT_FORMAT_ELF) && defined(HAVE_LD_EH_FRAME_HDR) \
    && !defined(inhibit_libc) && !defined(CRTSTUFFT_O) \
    && defined(__GLIBC__) && __GLIBC__ >= 2
#include <link.h>
# if (__GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ > 2) \
     || (__GLIBC__ == 2 && __GLIBC_MINOR__ == 2 && defined(DT_CONFIG)))
# endif
#if defined(EH_FRAME_SECTION_NAME) && !defined(USE_PT_GNU_EH_FRAME)
  static struct object object;
  if (__register_frame_info)
    __register_frame_info (__EH_FRAME_BEGIN__, &object);

Thus, if a system doesn't satisfy the __GLIBC__ check above, and uses a
.eh_frame section, then crtbegin.o will include a call to the weak function
__register_frame_info.  Since this function is provided by libgcc_s.so,
any program linked with crtbegin.o will end up requiring libgcc_s.so
when linked with --as-needed -lgcc_s.

As I said above, this effectively makes --shared-libgcc the default
on IRIX, and probably other ELF systems that don't satisfy the __GLIBC__
check.  This is an unannounced (and IMO undesirable) change in behaviour.
It also causes bootstrap problems because LD_LIBRARY_PATH (or whatever)
doesn't typically include the gcc/ and gcc/stage* directories that are
necessary for finding the new libgcc_s.so.  Anything built by the stage1
compiler will therefore fail to run.

I'm not sure how much to read into the fact that the problem has only been
reported for IRIX so far.  However, I suspect folks probably haven't had
that much opportunity to trip over it.  They'll only have noticed if:

  (1) They tested a 3.4 snapshot from the last two weeks.  (The patch
      was only applied at the beginning of April.)

  (2) They tested with a recent CVS version of binutils (cvs HEAD since
      18th March, or 2.15 branch since 8th April.)

  (3) Not only do they test with CVS versions of binutils, but they
      build binutils separately from gcc itself.  If you use a combined
      tree instead, ./configure will look for binutils 2.16 or above,
      and not even CVS mainline has a version number that high.  The
      only way the ./configure check can pass is if you have a
      preinstalled linker that supports --as-needed.

As Jakub says here:


the proper fix is probably to tighten the check in gcc.c:

So probably the #if conditional in init_gcc_specs needs to be
#if defined HAVE_LD_AS_NEEDED &&
The question is how to find that out, since in crtstuff.c it uses target
headers to find that out, but we don't have such luxury in gcc.c.

Unfortunately, no-one has yet suggested a viable way of doing this.

FWIW, a band-aid fix for IRIX is:


However, if I'm not completely overegging the potential fallout,
I wonder if would be better to revert the patch for now, and perhaps
revisit it for 3.4.1?

Comment 1 Mark Mitchell 2004-04-17 19:07:58 UTC
Jakub, I'm inclined, on the 3.4 branch, to mark the changes to gcc.c with
"#ifdef __linux__".  That will prevent possible problems on other systems. 
(It's probably not safe to use "__gnu_linux__" because older versions of GCC
define that.)

If I don't hear from you within the next 24 hours, that's what I plan to do.

I'm also inclined to revert the patch entirely on the mainline, and leave you to
figure out a better way to do what you want to do.  That might be as simple as
defining a new target macro saying whether or not this behavior is desirable.
Comment 2 Alan Modra 2004-04-18 15:19:22 UTC
This is really just a configure problem.  We have a macro, HAVE_LD_AS_NEEDED,
defined in config.h by configure, that controls exactly one piece of code in
gcc.c.  For clarity, I suggest renaming the macro to USE_LD_AS_NEEDED, and
sorting out the Irix problem in configure.
Comment 3 Alan Modra 2004-04-18 15:54:40 UTC
There seems to be plenty of precedent for defining HAVE_* macros on a per-target
basis.  Minimal patch at http://gcc.gnu.org/ml/gcc-patches/2004-04/msg01102.html
well into stage2 bootstrap.  Mark, please commit if you're in a hurry, I need
some sleep..
Comment 4 CVS Commits 2004-04-18 22:43:28 UTC
Subject: Bug 14992

CVSROOT:	/cvs/gcc
Module name:	gcc
Branch: 	gcc-3_4-branch
Changes by:	mmitchel@gcc.gnu.org	2004-04-18 22:43:24

Modified files:
	gcc            : ChangeLog gcc.c 

Log message:
	PR bootstrap/14992
	* gcc.c (init_gcc_specs): Only honor HAVE_LD_AS_NEEDED on


Comment 5 Mark Mitchell 2004-04-18 22:45:14 UTC
I applied the "#if defined(__linux__)" patch on the branch.

Therefore, retargeting at 3.5.0.
Comment 7 Mark Mitchell 2004-04-18 23:46:17 UTC
I decided what-the-heck and applied Alan's patch.  

Dan, if the release blows up it's all your fault. :-) :-)

Alan, please make the HAVE_LD_AS_NEEDED => USE_LD_AS_NEEDED change you suggest
before applying to mainline.
Comment 8 Alan Modra 2004-04-23 02:21:56 UTC
CVSROOT:	/cvs/gcc
Module name:	gcc
Changes by:	amodra@gcc.gnu.org	2004-04-23 02:16:26

Modified files:
	gcc            : ChangeLog gcc.c 
	gcc/config     : linux.h 
	gcc/config/alpha: linux.h 
	gcc/config/arm : linux-elf.h 
	gcc/config/rs6000: linux.h linux64.h 
	gcc/config/sh  : linux.h 
	gcc/config/sparc: linux.h linux64.h 

Log message:
	* gcc.c (init_gcc_specs): Test USE_LD_AS_NEEDED, not HAVE_LD_AS_NEEDED.
	* config/linux.h (USE_LD_AS_NEEDED): Define.
	* gcc/config/alpha/linux.h (USE_LD_AS_NEEDED): Define.
	* gcc/config/arm/linux-elf.h (USE_LD_AS_NEEDED): Define.
	* gcc/config/rs6000/linux.h (USE_LD_AS_NEEDED): Define.
	* gcc/config/rs6000/linux64.h (USE_LD_AS_NEEDED): Define.
	* gcc/config/sh/linux.h (USE_LD_AS_NEEDED): Define.
	* gcc/config/sparc/linux.h (USE_LD_AS_NEEDED): Define.
	* gcc/config/sparc/linux64.h (USE_LD_AS_NEEDED): Define.

Comment 9 Eric Botcazou 2005-05-30 14:40:36 UTC
Someone forgot that the HAVE_LD_AS_NEEDED patch had also been put on the 3.3
branch, so the silent switch from -static-libgcc to -shared-libgcc is present on
that branch too.  See PR bootstrap/21782.