Summary ------- 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. Detail ------ The rationale for the patch can be found here: http://gcc.gnu.org/ml/gcc-patches/2004-03/msg02210.html 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: http://gcc.gnu.org/ml/gcc-patches/2004-04/msg00855.html 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))) # define USE_PT_GNU_EH_FRAME # endif #endif #if defined(EH_FRAME_SECTION_NAME) && !defined(USE_PT_GNU_EH_FRAME) # define USE_EH_FRAME_REGISTRY #endif -------------------------------------------------------------------- .... -------------------------------------------------------------------- #ifdef USE_EH_FRAME_REGISTRY static struct object object; if (__register_frame_info) __register_frame_info (__EH_FRAME_BEGIN__, &object); #endif -------------------------------------------------------------------- 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: http://gcc.gnu.org/ml/gcc-patches/2004-04/msg00857.html: 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 && test_whether_USE_EH_FRAME_REGISTRY_will_not_be_defined 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. Ideas? --------------------------------------------------------------------- Unfortunately, no-one has yet suggested a viable way of doing this. FWIW, a band-aid fix for IRIX is: http://gcc.gnu.org/ml/gcc-patches/2004-04/msg00931.html 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? Richard
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.
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.
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..
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 GNU/Linux. Patches: http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/ChangeLog.diff?cvsroot=gcc&only_with_tag=gcc-3_4-branch&r1=2.2326.2.395&r2=2.2326.2.396 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/gcc.c.diff?cvsroot=gcc&only_with_tag=gcc-3_4-branch&r1=1.403.4.6&r2=1.403.4.7
I applied the "#if defined(__linux__)" patch on the branch. Therefore, retargeting at 3.5.0.
Subject: Bug 14992 CVSROOT: /cvs/gcc Module name: gcc Branch: gcc-3_4-branch Changes by: mmitchel@gcc.gnu.org 2004-04-18 23:45:12 Modified files: gcc : ChangeLog configure.ac configure gcc.c Log message: PR bootstrap/14992 * configure.ac: Define HAVE_LD_AS_NEEDED only for linux. * configure: Regenerate. * gcc.c (init_gcc_specs): Revert earlier change. Patches: http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/ChangeLog.diff?cvsroot=gcc&only_with_tag=gcc-3_4-branch&r1=2.2326.2.397&r2=2.2326.2.398 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/configure.ac.diff?cvsroot=gcc&only_with_tag=gcc-3_4-branch&r1=2.6.2.13&r2=2.6.2.14 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/configure.diff?cvsroot=gcc&only_with_tag=gcc-3_4-branch&r1=1.794.2.15&r2=1.794.2.16 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/gcc.c.diff?cvsroot=gcc&only_with_tag=gcc-3_4-branch&r1=1.403.4.7&r2=1.403.4.8
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.
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. Patches: http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/ChangeLog.diff?cvsroot=gcc&r1=2.3466&r2=2.3467 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/gcc.c.diff?cvsroot=gcc&r1=1.416&r2=1.417 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/config/linux.h.diff?cvsroot=gcc&r1=1.27&r2=1.28 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/config/alpha/linux.h.diff?cvsroot=gcc&r1=1.39&r2=1.40 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/config/arm/linux-elf.h.diff?cvsroot=gcc&r1=1.47&r2=1.48 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/config/rs6000/linux.h.diff?cvsroot=gcc&r1=1.45&r2=1.46 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/config/rs6000/linux64.h.diff?cvsroot=gcc&r1=1.60&r2=1.61 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/config/sh/linux.h.diff?cvsroot=gcc&r1=1.22&r2=1.23 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/config/sparc/linux.h.diff?cvsroot=gcc&r1=1.60&r2=1.61 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/config/sparc/linux64.h.diff?cvsroot=gcc&r1=1.81&r2=1.82
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.