diff options
author | jakub <jakub@138bc75d-0d04-0410-961f-82ee72b054a4> | 2001-12-15 11:49:18 +0000 |
---|---|---|
committer | jakub <jakub@138bc75d-0d04-0410-961f-82ee72b054a4> | 2001-12-15 11:49:18 +0000 |
commit | 0d6378a9e3e589217fda7be9ae273aee14540fe0 (patch) | |
tree | 1e290b8253af587309d21dfa2217501a304a75ac /gcc | |
parent | bee0e6ed4aac405fc7e97f44c491966e086649ba (diff) | |
download | gcc-0d6378a9e3e589217fda7be9ae273aee14540fe0.tar.gz |
* configure.in: Check for ld.
(HAVE_LD_EH_FRAME_HDR): Define if ld supports --eh-frame-hdr option.
* configure, config.in: Rebuilt.
* config.gcc: Add crtbeginT.o to extra_parts where needed.
* config/t-linux (LIB2ADDEH, LIB2ADDEHDEP): Use unwind-dw2-fde-glibc
frame unwinding on Linux.
* config/t-linux-gnulibc1 (LIB2ADDEH, LIB2ADDEHDEP): Use unwind-dw2-fde
frame unwinding.
* config/linux.h (STARTFILE_SPEC): Use crtbeginT.o for -static.
(LINK_EH_SPEC): Define.
* config/i386/gnu.h (STARTFILE_SPEC): Use crtbeginT.o for -static.
* config/ia64/linux.h (STARTFILE_SPEC, LINK_EH_SPEC): Define.
* config/ia64/fde-glibc.c (_Unwind_IteratePhdrCallback): Don't
iterate further if pc falls into current library, but fde was not
found.
* config/sparc/linux.h (STARTFILE_SPEC): Use crtbeginT.o for -static
if using glibc.
(LINK_EH_SPEC): Define.
* config/sparc/linux64.h (STARTFILE_SPEC32, STARTFILE_SPEC64):
Use crtbeginT.o for -static.
(LINK_EH_SPEC): Define.
* config/sparc/t-linux64 (EXTRA_MULTILIB_PARTS): Add crtbeginT.o.
* Makefile.in (crtbeginT.o): Add rule.
* gcc.c (init_gcc_specs): For -static-libgcc, use -lgcc -lgcc_eh.
If neither -static-libgcc nor -shared-libgcc is passed and -shared,
use -lgcc if LINK_EH_SPEC is defined and -lgcc_s -lgcc if not.
If none of the above switches are passed, use -lgcc -lgcc_eh.
(init_spec): If LINK_EH_SPEC is defined, prepend it to link_spec.
* mklibgcc.in: Don't include LIB2ADDEH objects into libgcc.a if
creating libgcc_s.so, put them into separate libgcc_eh.a instead.
* unwind-dw2-fde.c: Don't include any headers if this file
is included from other .c file.
* unwind-dw2-fde-glibc.c: New file.
* crtstuff.c (USE_PT_GNU_EH_FRAME, USE_EH_FRAME_REGISTRY): Define.
Use it instead of EH_FRAME_SECTION_NAME where appropriate.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@48039 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 38 | ||||
-rw-r--r-- | gcc/Makefile.in | 35 | ||||
-rw-r--r-- | gcc/config.gcc | 22 | ||||
-rw-r--r-- | gcc/config.in | 3 | ||||
-rw-r--r-- | gcc/config/i386/gnu.h | 3 | ||||
-rw-r--r-- | gcc/config/ia64/fde-glibc.c | 4 | ||||
-rw-r--r-- | gcc/config/ia64/linux.h | 15 | ||||
-rw-r--r-- | gcc/config/linux.h | 14 | ||||
-rw-r--r-- | gcc/config/sparc/linux.h | 11 | ||||
-rw-r--r-- | gcc/config/sparc/linux64.h | 12 | ||||
-rw-r--r-- | gcc/config/sparc/t-linux64 | 2 | ||||
-rw-r--r-- | gcc/config/t-linux | 5 | ||||
-rw-r--r-- | gcc/config/t-linux-gnulibc1 | 5 | ||||
-rwxr-xr-x | gcc/configure | 107 | ||||
-rw-r--r-- | gcc/configure.in | 109 | ||||
-rw-r--r-- | gcc/crtstuff.c | 27 | ||||
-rw-r--r-- | gcc/gcc.c | 38 | ||||
-rw-r--r-- | gcc/mklibgcc.in | 35 | ||||
-rw-r--r-- | gcc/unwind-dw2-fde-glibc.c | 291 | ||||
-rw-r--r-- | gcc/unwind-dw2-fde.c | 2 |
20 files changed, 731 insertions, 47 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index f4321c37d4e..36f16c6e5fd 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,41 @@ +2001-12-15 Jakub Jelinek <jakub@redhat.com> + + * configure.in: Check for ld. + (HAVE_LD_EH_FRAME_HDR): Define if ld supports --eh-frame-hdr option. + * configure, config.in: Rebuilt. + * config.gcc: Add crtbeginT.o to extra_parts where needed. + * config/t-linux (LIB2ADDEH, LIB2ADDEHDEP): Use unwind-dw2-fde-glibc + frame unwinding on Linux. + * config/t-linux-gnulibc1 (LIB2ADDEH, LIB2ADDEHDEP): Use unwind-dw2-fde + frame unwinding. + * config/linux.h (STARTFILE_SPEC): Use crtbeginT.o for -static. + (LINK_EH_SPEC): Define. + * config/i386/gnu.h (STARTFILE_SPEC): Use crtbeginT.o for -static. + * config/ia64/linux.h (STARTFILE_SPEC, LINK_EH_SPEC): Define. + * config/ia64/fde-glibc.c (_Unwind_IteratePhdrCallback): Don't + iterate further if pc falls into current library, but fde was not + found. + * config/sparc/linux.h (STARTFILE_SPEC): Use crtbeginT.o for -static + if using glibc. + (LINK_EH_SPEC): Define. + * config/sparc/linux64.h (STARTFILE_SPEC32, STARTFILE_SPEC64): + Use crtbeginT.o for -static. + (LINK_EH_SPEC): Define. + * config/sparc/t-linux64 (EXTRA_MULTILIB_PARTS): Add crtbeginT.o. + * Makefile.in (crtbeginT.o): Add rule. + * gcc.c (init_gcc_specs): For -static-libgcc, use -lgcc -lgcc_eh. + If neither -static-libgcc nor -shared-libgcc is passed and -shared, + use -lgcc if LINK_EH_SPEC is defined and -lgcc_s -lgcc if not. + If none of the above switches are passed, use -lgcc -lgcc_eh. + (init_spec): If LINK_EH_SPEC is defined, prepend it to link_spec. + * mklibgcc.in: Don't include LIB2ADDEH objects into libgcc.a if + creating libgcc_s.so, put them into separate libgcc_eh.a instead. + * unwind-dw2-fde.c: Don't include any headers if this file + is included from other .c file. + * unwind-dw2-fde-glibc.c: New file. + * crtstuff.c (USE_PT_GNU_EH_FRAME, USE_EH_FRAME_REGISTRY): Define. + Use it instead of EH_FRAME_SECTION_NAME where appropriate. + 2001-12-14 Kaveh R. Ghazi <ghazi@caip.rutgers.edu> * builtins.c (expand_builtin_memcmp): Mark parameter with diff --git a/gcc/Makefile.in b/gcc/Makefile.in index adb7281d1b9..ecba14f7a79 100644 --- a/gcc/Makefile.in +++ b/gcc/Makefile.in @@ -1106,6 +1106,15 @@ $(T)crtendS.o: crtstuff.c $(GCC_PASSES) $(TCONFIG_H) auto-host.h \ -c $(srcdir)/crtstuff.c -DCRT_END -DCRTSTUFFS_O \ -o $(T)crtendS$(objext) +# This is a version of crtbegin for -static links. +$(T)crtbeginT.o: crtstuff.c $(GCC_PASSES) $(TCONFIG_H) auto-host.h \ + gbl-ctors.h stmp-int-hdrs tsystem.h + $(GCC_FOR_TARGET) $(GCC_CFLAGS) $(INCLUDES) $(MULTILIB_CFLAGS) -g0 \ + -finhibit-size-directive -fno-inline-functions \ + -fno-exceptions $(CRTSTUFF_T_CFLAGS) @inhibit_libc@ \ + -c $(srcdir)/crtstuff.c -DCRT_BEGIN -DCRTSTUFFT_O \ + -o $(T)crtbeginT$(objext) + # Compile the start modules crt0.o and mcrt0.o that are linked with # every program crt0.o: s-crt0 ; @true @@ -2384,7 +2393,7 @@ mostlyclean: $(INTL_MOSTLYCLEAN) lang.mostlyclean # that don't exist in the distribution. INTL_CLEAN = intl.clean clean: mostlyclean $(INTL_CLEAN) lang.clean - -rm -f libgcc.a libgcc_s$(SHLIB_EXT) libgcc_s$(SHLIB_EXT).1 + -rm -f libgcc.a libgcc_eh.a libgcc_s$(SHLIB_EXT) libgcc_s$(SHLIB_EXT).1 -rm -f config.h tconfig.h hconfig.h tm_p.h -rm -f cs-* -rm -rf libgcc @@ -3140,11 +3149,15 @@ stage1-start: -if [ -f as$(exeext) ] ; then (cd stage1 && $(LN_S) ../as$(exeext) .) ; else true ; fi -if [ -f ld$(exeext) ] ; then (cd stage1 && $(LN_S) ../ld$(exeext) .) ; else true ; fi -if [ -f collect-ld$(exeext) ] ; then (cd stage1 && $(LN_S) ../collect-ld$(exeext) .) ; else true ; fi - -rm -f stage1/libgcc.a + -rm -f stage1/libgcc.a stage1/libgcc_eh.a -cp libgcc.a stage1 -if $(RANLIB_TEST_FOR_TARGET) ; then \ $(RANLIB_FOR_TARGET) stage1/libgcc.a; \ else true; fi + -if [ -f libgcc_eh.a ] ; then cp libgcc_eh.a stage1; \ + if $(RANLIB_TEST_FOR_TARGET) ; then \ + $(RANLIB_FOR_TARGET) stage1/libgcc_eh.a; \ + else true; fi; fi -for f in .. $(EXTRA_MULTILIB_PARTS); do if [ x$${f} != x.. ]; then \ cp stage1/$${f} . ; \ else true; \ @@ -3165,11 +3178,15 @@ stage2-start: -if [ -f as$(exeext) ] ; then (cd stage2 && $(LN_S) ../as$(exeext) .) ; else true ; fi -if [ -f ld$(exeext) ] ; then (cd stage2 && $(LN_S) ../ld$(exeext) .) ; else true ; fi -if [ -f collect-ld$(exeext) ] ; then (cd stage2 && $(LN_S) ../collect-ld$(exeext) .) ; else true ; fi - -rm -f stage2/libgcc.a + -rm -f stage2/libgcc.a stage2/libgcc_eh.a -cp libgcc.a stage2 -if $(RANLIB_TEST_FOR_TARGET) ; then \ $(RANLIB_FOR_TARGET) stage2/libgcc.a; \ else true; fi + -if [ -f libgcc_eh.a ] ; then cp libgcc_eh.a stage2; \ + if $(RANLIB_TEST_FOR_TARGET) ; then \ + $(RANLIB_FOR_TARGET) stage2/libgcc_eh.a; \ + else true; fi; fi -for f in .. $(EXTRA_MULTILIB_PARTS); do if [ x$${f} != x.. ]; then \ cp stage2/$${f} . ; \ else true; \ @@ -3190,11 +3207,15 @@ stage3-start: -if [ -f as$(exeext) ] ; then (cd stage3 && $(LN_S) ../as$(exeext) .) ; else true ; fi -if [ -f ld$(exeext) ] ; then (cd stage3 && $(LN_S) ../ld$(exeext) .) ; else true ; fi -if [ -f collect-ld$(exeext) ] ; then (cd stage3 && $(LN_S) ../collect-ld$(exeext) .) ; else true ; fi - -rm -f stage3/libgcc.a + -rm -f stage3/libgcc.a stage3/libgcc_eh.a -cp libgcc.a stage3 -if $(RANLIB_TEST_FOR_TARGET) ; then \ $(RANLIB_FOR_TARGET) stage3/libgcc.a; \ else true; fi + -if [ -f libgcc_eh.a ] ; then cp libgcc_eh.a stage3; \ + if $(RANLIB_TEST_FOR_TARGET) ; then \ + $(RANLIB_FOR_TARGET) stage3/libgcc_eh.a; \ + else true; fi; fi -for f in .. $(EXTRA_MULTILIB_PARTS); do if [ x$${f} != x.. ]; then \ cp stage3/$${f} . ; \ else true; \ @@ -3215,11 +3236,15 @@ stage4-start: -if [ -f as$(exeext) ] ; then (cd stage4 && $(LN_S) ../as$(exeext) .) ; else true ; fi -if [ -f ld$(exeext) ] ; then (cd stage4 && $(LN_S) ../ld$(exeext) .) ; else true ; fi -if [ -f collect-ld$(exeext) ] ; then (cd stage4 && $(LN_S) ../collect-ld$(exeext) .) ; else true ; fi - -rm -f stage4/libgcc.a + -rm -f stage4/libgcc.a stage4/libgcc_eh.a -cp libgcc.a stage4 -if $(RANLIB_TEST_FOR_TARGET) ; then \ $(RANLIB_FOR_TARGET) stage4/libgcc.a; \ else true; fi + -if [ -f libgcc_eh.a ] ; then cp libgcc_eh.a stage4; \ + if $(RANLIB_TEST_FOR_TARGET) ; then \ + $(RANLIB_FOR_TARGET) stage4/libgcc_eh.a; \ + else true; fi; fi -for f in .. $(EXTRA_MULTILIB_PARTS); do if [ x$${f} != x.. ]; then \ cp stage4/$${f} . ; \ else true; \ diff --git a/gcc/config.gcc b/gcc/config.gcc index 5b3118b7858..061c970074c 100644 --- a/gcc/config.gcc +++ b/gcc/config.gcc @@ -276,7 +276,7 @@ case $machine in # support are matched above and just set $cpu_type. xm_defines=POSIX tm_file="${cpu_type}/gnu.h" - extra_parts="crtbegin.o crtend.o crtbeginS.o crtendS.o" + extra_parts="crtbegin.o crtend.o crtbeginS.o crtendS.o crtbeginT.o" # GNU always uses ELF. elf=yes # GNU tools are the only tools. @@ -700,7 +700,7 @@ cris-*-elf | cris-*-none) cris-*-linux*) tm_file="dbxelf.h elfos.h svr4.h ${tm_file} linux.h cris/linux.h" tmake_file="cris/t-cris t-slibgcc-elf-ver cris/t-linux" - extra_parts="crtbegin.o crtbeginS.o crtend.o crtendS.o" + extra_parts="crtbegin.o crtbeginS.o crtbeginT.o crtend.o crtendS.o" case x${enable_threads} in x | xyes | xpthreads | xposix) thread_file=posix @@ -750,7 +750,7 @@ hppa*-*-linux* | parisc*-*-linux*) tm_file="${tm_file} dbxelf.h elfos.h svr4.h linux.h pa/pa-linux.h \ pa/pa32-regs.h pa/pa32-linux.h" tmake_file="t-slibgcc-elf-ver t-linux pa/t-linux" - extra_parts="crtbegin.o crtbeginS.o crtend.o crtendS.o" + extra_parts="crtbegin.o crtbeginS.o crtbeginT.o crtend.o crtendS.o" gas=yes gnu_ld=yes if test x$enable_threads = xyes; then thread_file='posix' @@ -981,7 +981,7 @@ i370-*-linux*) tm_file="dbxelf.h elfos.h svr4.h linux.h i370/linux.h ${tm_file}" tmake_file="t-slibgcc-elf-ver t-linux" # broken_install=yes - extra_parts="crtbegin.o crtbeginS.o crtend.o crtendS.o" + extra_parts="crtbegin.o crtbeginS.o crtbeginT.o crtend.o crtendS.o" # extra_parts="crtbegin.o crtend.o" gnu_ld=yes gas=yes @@ -1178,7 +1178,7 @@ i[34567]86-*-linux*) # Intel 80386's running GNU/Linux # aka GNU/Linux C library 6 tm_file="${tm_file} i386/att.h dbxelf.h elfos.h svr4.h linux.h i386/linux.h" tmake_file="t-slibgcc-elf-ver t-linux i386/t-crtstuff" - extra_parts="crtbegin.o crtbeginS.o crtend.o crtendS.o" + extra_parts="crtbegin.o crtbeginS.o crtbeginT.o crtend.o crtendS.o" gnu_ld=yes float_format=i386 if test x$enable_threads = xyes; then @@ -1189,7 +1189,7 @@ x86_64-*-linux*) tm_file="i386/biarch64.h i386/i386.h i386/att.h dbxelf.h elfos.h svr4.h linux.h \ i386/x86-64.h i386/linux64.h" tmake_file="t-slibgcc-elf-ver t-linux i386/t-crtstuff" - extra_parts="crtbegin.o crtbeginS.o crtend.o crtendS.o" + extra_parts="crtbegin.o crtbeginS.o crtbeginT.o crtend.o crtendS.o" gnu_ld=yes float_format=i386 if test x$enable_threads = xyes; then @@ -2280,7 +2280,7 @@ mips*-*-linux*) # Linux MIPS, either endian. ;; esac tmake_file="t-slibgcc-elf-ver t-linux" - extra_parts="crtbegin.o crtbeginS.o crtend.o crtendS.o" + extra_parts="crtbegin.o crtbeginS.o crtbeginT.o crtend.o crtendS.o" gnu_ld=yes gas=yes if test x$enable_threads = xyes; then @@ -2867,7 +2867,7 @@ rs6000-*-lynxos*) s390-*-linux*) tm_file="s390/s390.h dbxelf.h elfos.h svr4.h linux.h s390/linux.h" tmake_file="t-slibgcc-elf-ver t-linux s390/t-linux" - extra_parts="crtbegin.o crtend.o crtbeginS.o crtendS.o" + extra_parts="crtbegin.o crtend.o crtbeginS.o crtendS.o crtbeginT.o" if test x$enable_threads = xyes; then thread_file='posix' fi @@ -2878,7 +2878,7 @@ s390x-*-linux*) md_file=s390/s390.md out_file=s390/s390.c tmake_file="t-slibgcc-elf-ver t-linux s390/t-linux" - extra_parts="crtbegin.o crtend.o crtbeginS.o crtendS.o" + extra_parts="crtbegin.o crtend.o crtbeginS.o crtendS.o crtbeginT.o" if test x$enable_threads = xyes; then thread_file='posix' fi @@ -2982,7 +2982,7 @@ sparc-*-linux*libc1*) # Sparc's running GNU/Linux, libc5 sparc-*-linux*) # Sparc's running GNU/Linux, libc6 tm_file="${tm_file} dbxelf.h elfos.h svr4.h sparc/sysv4.h sparc/linux.h" tmake_file="t-slibgcc-elf-ver t-linux" - extra_parts="crtbegin.o crtbeginS.o crtend.o crtendS.o" + extra_parts="crtbegin.o crtbeginS.o crtbeginT.o crtend.o crtendS.o" gnu_ld=yes if test x$enable_threads = xyes; then thread_file='posix' @@ -3177,7 +3177,7 @@ sparc64-*-elf*) sparc64-*-linux*) # 64-bit Sparc's running GNU/Linux tmake_file="t-slibgcc-elf-ver t-linux sparc/t-linux64" tm_file="sparc/sparc_bi.h ${tm_file} dbxelf.h elfos.h svr4.h sparc/sysv4.h sparc/linux64.h" - extra_parts="crtbegin.o crtbeginS.o crtend.o crtendS.o" + extra_parts="crtbegin.o crtbeginS.o crtbeginT.o crtend.o crtendS.o" gnu_ld=yes if test x$enable_threads = xyes; then thread_file='posix' diff --git a/gcc/config.in b/gcc/config.in index a750775f482..d1b8068045c 100644 --- a/gcc/config.in +++ b/gcc/config.in @@ -551,6 +551,9 @@ /* Define if your assembler supports the --gstabs option. */ #undef HAVE_AS_GSTABS_DEBUG_FLAG +/* Define if your linker supports --eh-frame-hdr option. */ +#undef HAVE_LD_EH_FRAME_HDR + /* Define 0/1 to force the choice for exception handling model. */ #undef CONFIG_SJLJ_EXCEPTIONS diff --git a/gcc/config/i386/gnu.h b/gcc/config/i386/gnu.h index 205d5767991..0214c05771f 100644 --- a/gcc/config/i386/gnu.h +++ b/gcc/config/i386/gnu.h @@ -29,7 +29,8 @@ %{!static: \ %{pg:gcrt1.o%s} %{!pg:%{p:gcrt1.o%s} %{!p:crt1.o%s}}} \ %{static:crt0.o%s}} \ - crti.o%s %{!shared:crtbegin.o%s} %{shared:crtbeginS.o%s}" + crti.o%s %{static:crtbeginT.o%s}\ + %{!static:%{!shared:crtbegin.o%s} %{shared:crtbeginS.o%s}}" /* FIXME: Is a Hurd-specific fallback mechanism necessary? */ #undef MD_FALLBACK_FRAME_STATE_FOR diff --git a/gcc/config/ia64/fde-glibc.c b/gcc/config/ia64/fde-glibc.c index c663f584458..83cc93a9256 100644 --- a/gcc/config/ia64/fde-glibc.c +++ b/gcc/config/ia64/fde-glibc.c @@ -110,7 +110,9 @@ _Unwind_IteratePhdrCallback (struct dl_phdr_info *info, size_t size, void *ptr) else goto found; } - return 0; + /* No need to search for further libraries when we know pc is contained + in this library. */ + return 1; found: *data->segment_base = seg_base; diff --git a/gcc/config/ia64/linux.h b/gcc/config/ia64/linux.h index a25844fb6d8..91f2f39d845 100644 --- a/gcc/config/ia64/linux.h +++ b/gcc/config/ia64/linux.h @@ -18,6 +18,15 @@ #undef ASM_SPEC #define ASM_SPEC "-x %{mconstant-gp} %{mauto-pic}" +/* Need to override linux.h STARTFILE_SPEC, since it has crtbeginT.o in. */ +#undef STARTFILE_SPEC +#define STARTFILE_SPEC \ + "%{!shared: \ + %{pg:gcrt1.o%s} %{!pg:%{p:gcrt1.o%s} \ + %{!p:%{profile:gcrt1.o%s} \ + %{!profile:crt1.o%s}}}} \ + crti.o%s %{!shared:crtbegin.o%s} %{shared:crtbeginS.o%s}" + /* Similar to standard Linux, but adding -ffast-math support. */ #undef ENDFILE_SPEC #define ENDFILE_SPEC \ @@ -45,4 +54,10 @@ #undef PROFILE_BEFORE_PROLOGUE #define PROFILE_BEFORE_PROLOGUE 1 +/* Override linux.h LINK_EH_SPEC definition. + Signalize that because we have fde-glibc, we don't need all C shared libs + linked against -lgcc_s. */ +#undef LINK_EH_SPEC +#define LINK_EH_SPEC "" + /* End of linux.h */ diff --git a/gcc/config/linux.h b/gcc/config/linux.h index 4743ffedb28..6e60c008d85 100644 --- a/gcc/config/linux.h +++ b/gcc/config/linux.h @@ -50,12 +50,22 @@ Boston, MA 02111-1307, USA. */ object constructed before entering `main'. */ #undef STARTFILE_SPEC +#ifdef USE_GNULIBC_1 #define STARTFILE_SPEC \ "%{!shared: \ %{pg:gcrt1.o%s} %{!pg:%{p:gcrt1.o%s} \ %{!p:%{profile:gcrt1.o%s} \ %{!profile:crt1.o%s}}}} \ crti.o%s %{!shared:crtbegin.o%s} %{shared:crtbeginS.o%s}" +#else +#define STARTFILE_SPEC \ + "%{!shared: \ + %{pg:gcrt1.o%s} %{!pg:%{p:gcrt1.o%s} \ + %{!p:%{profile:gcrt1.o%s} \ + %{!profile:crt1.o%s}}}} \ + crti.o%s %{static:crtbeginT.o%s}\ + %{!static:%{!shared:crtbegin.o%s} %{shared:crtbeginS.o%s}}" +#endif /* Provide a ENDFILE_SPEC appropriate for GNU/Linux. Here we tack on the GNU/Linux magical crtend.o file (see crtstuff.c) which @@ -98,5 +108,9 @@ Boston, MA 02111-1307, USA. */ %{!p:%{!pg:%{!g*:-lc} %{g*:-lg}}}}" #endif +#if !defined(USE_GNULIBC_1) && defined(HAVE_LD_EH_FRAME_HDR) +#define LINK_EH_SPEC "%{!static:--eh-frame-hdr} " +#endif + /* Define this so we can compile MS code for use with WINE. */ #define HANDLE_PRAGMA_PACK_PUSH_POP diff --git a/gcc/config/sparc/linux.h b/gcc/config/sparc/linux.h index dff005ba360..cfc3e527d18 100644 --- a/gcc/config/sparc/linux.h +++ b/gcc/config/sparc/linux.h @@ -44,10 +44,17 @@ Boston, MA 02111-1307, USA. */ object constructed before entering `main'. */ #undef STARTFILE_SPEC +#ifdef USE_GNULIBC_1 #define STARTFILE_SPEC \ "%{!shared: \ %{pg:gcrt1.o%s} %{!pg:%{p:gcrt1.o%s} %{!p:crt1.o%s}}}\ crti.o%s %{!shared:crtbegin.o%s} %{shared:crtbeginS.o%s}" +#else + "%{!shared: \ + %{pg:gcrt1.o%s} %{!pg:%{p:gcrt1.o%s} %{!p:crt1.o%s}}}\ + crti.o%s %{static:crtbeginT.o%s}\ + %{!static:%{!shared:crtbegin.o%s} %{shared:crtbeginS.o%s}}" +#endif /* Provide a ENDFILE_SPEC appropriate for GNU/Linux. Here we tack on the GNU/Linux magical crtend.o file (see crtstuff.c) which @@ -242,4 +249,8 @@ do { \ #else #define LIBGCC2_LONG_DOUBLE_TYPE_SIZE 64 #endif + +#if !defined(USE_GNULIBC_1) && defined(HAVE_LD_EH_FRAME_HDR) +#define LINK_EH_SPEC "%{!static:--eh-frame-hdr} " +#endif diff --git a/gcc/config/sparc/linux64.h b/gcc/config/sparc/linux64.h index b82b31fcdd7..54b672e826f 100644 --- a/gcc/config/sparc/linux64.h +++ b/gcc/config/sparc/linux64.h @@ -59,13 +59,15 @@ Boston, MA 02111-1307, USA. */ #define STARTFILE_SPEC32 \ "%{!shared: \ %{pg:gcrt1.o%s} %{!pg:%{p:gcrt1.o%s} %{!p:crt1.o%s}}}\ - crti.o%s %{!shared:crtbegin.o%s} %{shared:crtbeginS.o%s}" + crti.o%s %{static:crtbeginT.o%s}\ + %{!static:%{!shared:crtbegin.o%s} %{shared:crtbeginS.o%s}}" #define STARTFILE_SPEC64 \ "%{!shared: \ %{pg:/usr/lib64/gcrt1.o%s} %{!pg:%{p:/usr/lib64/gcrt1.o%s} %{!p:/usr/lib64/crt1.o%s}}}\ - /usr/lib64/crti.o%s %{!shared:crtbegin.o%s} %{shared:crtbeginS.o%s}" - + /usr/lib64/crti.o%s %{static:crtbeginT.o%s}\ + %{!static:%{!shared:crtbegin.o%s} %{shared:crtbeginS.o%s}}" + #ifdef SPARC_BI_ARCH #if DEFAULT_ARCH32_P @@ -367,4 +369,8 @@ do { \ RELATIVE relocations. */ /* #define DWARF_OFFSET_SIZE PTR_SIZE */ + +#if defined(HAVE_LD_EH_FRAME_HDR) +#define LINK_EH_SPEC "%{!static:--eh-frame-hdr} " +#endif diff --git a/gcc/config/sparc/t-linux64 b/gcc/config/sparc/t-linux64 index 2a3ec4b07ec..4f552e07d1e 100644 --- a/gcc/config/sparc/t-linux64 +++ b/gcc/config/sparc/t-linux64 @@ -7,4 +7,4 @@ MULTILIB_EXCLUSIONS = m32/!m64/mno-app-regs m32/!m64/mcmodel=medany LIBGCC = stmp-multilib INSTALL_LIBGCC = install-multilib -EXTRA_MULTILIB_PARTS=crtbegin.o crtend.o crtbeginS.o crtendS.o +EXTRA_MULTILIB_PARTS=crtbegin.o crtend.o crtbeginS.o crtendS.o crtbeginT.o diff --git a/gcc/config/t-linux b/gcc/config/t-linux index 06283bd65b7..570135aef50 100644 --- a/gcc/config/t-linux +++ b/gcc/config/t-linux @@ -9,3 +9,8 @@ TARGET_LIBGCC2_CFLAGS = -fPIC # Override t-slibgcc-elf-ver to export some libgcc symbols with # the symbol versions that glibc used. SHLIB_MAPFILES += $(srcdir)/config/libgcc-glibc.ver + +# Use unwind-dw2-fde-glibc +LIB2ADDEH = $(srcdir)/unwind-dw2.c $(srcdir)/unwind-dw2-fde-glibc.c \ + $(srcdir)/unwind-sjlj.c +LIB2ADDEHDEP = unwind.inc unwind-dw2-fde.h unwind-dw2-fde.c diff --git a/gcc/config/t-linux-gnulibc1 b/gcc/config/t-linux-gnulibc1 index 7bb7bce85b3..56a471579ed 100644 --- a/gcc/config/t-linux-gnulibc1 +++ b/gcc/config/t-linux-gnulibc1 @@ -1,2 +1,7 @@ # We are building for the Linux C library 5. T_CFLAGS = -DUSE_GNULIBC_1 + +# Use unwind-dw2-fde +LIB2ADDEH = $(srcdir)/unwind-dw2.c $(srcdir)/unwind-dw2-fde.c \ + $(srcdir)/unwind-sjlj.c +LIB2ADDEHDEP = unwind.inc unwind-dw2-fde.h diff --git a/gcc/configure b/gcc/configure index 3b214f5c838..39107bca71a 100755 --- a/gcc/configure +++ b/gcc/configure @@ -6904,6 +6904,92 @@ else echo "$ac_t""$gcc_cv_as" 1>&6 fi +# Figure out what linker we will be using. +echo $ac_n "checking what linker to use""... $ac_c" 1>&6 +echo "configure:6904: checking what linker to use" >&5 +gcc_cv_ld= +gcc_cv_gld_major_version= +gcc_cv_gld_minor_version= +gcc_cv_ld_gld_srcdir=`echo $srcdir | sed -e 's,/gcc$,,'`/ld +gcc_cv_ld_bfd_srcdir=`echo $srcdir | sed -e 's,/gcc$,,'`/bfd +if test -x "$DEFAULT_LINKER"; then + gcc_cv_ld="$DEFAULT_LINKER" +elif test -x "$LD"; then + gcc_cv_ld="$LD" +elif test -x ld$host_exeext; then + # Build using linker in the current directory. + gcc_cv_ld=./ld$host_exeext +elif test -f $gcc_cv_ld_gld_srcdir/configure.in -a -f ../ld/Makefile; then + # Single tree build which includes ld. + for f in $gcc_cv_ld_bfd_srcdir/configure $gcc_cv_ld_gld_srcdir/configure $gcc_cv_ld_gld_srcdir/configure.in $gcc_cv_ld_gld_srcdir/Makefile.in + do + gcc_cv_gld_version=`grep '^VERSION=[0-9]*\.[0-9]*' $f` + if test x$gcc_cv_gld_version != x; then + break + fi + done + gcc_cv_gld_major_version=`expr "$gcc_cv_gld_version" : "VERSION=\([0-9]*\)"` + gcc_cv_gld_minor_version=`expr "$gcc_cv_gld_version" : "VERSION=[0-9]*\.\([0-9]*\)"` +fi + +if test "x$gcc_cv_ld" = x -a x$host = x$target; then + # Native build. + # Search the same directories that the installed compiler will + # search. Else we may find the wrong linker and lose. If we + # do not find a suitable linker binary, then try the user's + # path. + # + # Also note we have to check MD_EXEC_PREFIX before checking the + # user's path. Unfortunately, there is no good way to get at the + # value of MD_EXEC_PREFIX here. So we do a brute force search + # through all the known MD_EXEC_PREFIX values. Ugh. This needs + # to be fixed as part of the make/configure rewrite too. + + if test "x$exec_prefix" = xNONE; then + if test "x$prefix" = xNONE; then + test_prefix=/usr/local + else + test_prefix=$prefix + fi + else + test_prefix=$exec_prefix + fi + + # If the loop below does not find an linker, then use whatever + # one we can find in the users's path. + # user's path. + gcc_cv_ld=ld$host_exeext + + test_dirs="$test_prefix/lib/gcc-lib/$target/$gcc_version \ + $test_prefix/lib/gcc-lib/$target \ + /usr/lib/gcc/$target/$gcc_version \ + /usr/lib/gcc/$target \ + $test_prefix/$target/bin/$target/$gcc_version \ + $test_prefix/$target/bin \ + /usr/libexec \ + /usr/ccs/gcc \ + /usr/ccs/bin \ + /udk/usr/ccs/bin \ + /bsd43/usr/lib/cmplrs/cc \ + /usr/cross64/usr/bin \ + /usr/lib/cmplrs/cc \ + /sysv/usr/lib/cmplrs/cc \ + /svr4/usr/lib/cmplrs/cc \ + /usr/bin" + + for dir in $test_dirs; do + if test -f $dir/ld$host_exeext; then + gcc_cv_ld=$dir/ld$host_exeext + break; + fi + done +fi +if test x$gcc_cv_gld_major_version != x -a x$gcc_cv_gld_minor_version != x; then + echo "$ac_t"""newly built ld"" 1>&6 +else + echo "$ac_t""$gcc_cv_ld" 1>&6 +fi + # Figure out what nm we will be using. echo $ac_n "checking what nm to use""... $ac_c" 1>&6 echo "configure:6910: checking what nm to use" >&5 @@ -7526,6 +7612,27 @@ EOF fi echo "$ac_t""$gcc_cv_as_gstabs_flag" 1>&6 +echo $ac_n "checking linker PT_GNU_EH_FRAME support""... $ac_c" 1>&6 +echo "configure:7611: checking linker PT_GNU_EH_FRAME support" >&5 +gcc_cv_ld_eh_frame_hdr=no +if test x$gcc_cv_gld_major_version != x -a x$gcc_cv_gld_minor_version != x; then + if test "$gcc_cv_gld_major_version" -eq 2 -a "$gcc_cv_gld_minor_version" -ge 12 -o "$gcc_cv_gld_major_version" -gt 2 && grep 'EMUL = elf' ../ld/Makefile > /dev/null; then + gcc_cv_ld_eh_frame_hdr=yes + fi +elif test x$gcc_cv_ld != x; then + # Check if linker supports --eh-frame-hdr option + if $gcc_cv_ld --help 2>/dev/null | grep eh-frame-hdr > /dev/null; then + gcc_cv_ld_eh_frame_hdr=yes + fi +fi +if test x"$gcc_cv_ld_eh_frame_hdr" = xyes; then + cat >> confdefs.h <<\EOF +#define HAVE_LD_EH_FRAME_HDR 1 +EOF + +fi +echo "$ac_t""$gcc_cv_ld_eh_frame_hdr" 1>&6 + if test "$prefix" != "/usr" && test "$prefix" != "/usr/local" ; then cat >> confdefs.h <<EOF #define PREFIX_INCLUDE_DIR "$prefix/include" diff --git a/gcc/configure.in b/gcc/configure.in index 71f463e0ed3..34a5b2bc7b0 100644 --- a/gcc/configure.in +++ b/gcc/configure.in @@ -1257,6 +1257,95 @@ else AC_MSG_RESULT($gcc_cv_as) fi +# Figure out what linker we will be using. +AC_MSG_CHECKING(what linker to use) +gcc_cv_ld= +gcc_cv_gld_major_version= +gcc_cv_gld_minor_version= +gcc_cv_ld_gld_srcdir=`echo $srcdir | sed -e 's,/gcc$,,'`/ld +gcc_cv_ld_bfd_srcdir=`echo $srcdir | sed -e 's,/gcc$,,'`/bfd +if test -x "$DEFAULT_LINKER"; then + gcc_cv_ld="$DEFAULT_LINKER" +elif test -x "$LD"; then + gcc_cv_ld="$LD" +elif test -x ld$host_exeext; then + # Build using linker in the current directory. + gcc_cv_ld=./ld$host_exeext +elif test -f $gcc_cv_ld_gld_srcdir/configure.in -a -f ../ld/Makefile; then + # Single tree build which includes ld. + for f in $gcc_cv_ld_bfd_srcdir/configure $gcc_cv_ld_gld_srcdir/configure $gcc_cv_ld_gld_srcdir/configure.in $gcc_cv_ld_gld_srcdir/Makefile.in + do +changequote(,)dnl + gcc_cv_gld_version=`grep '^VERSION=[0-9]*\.[0-9]*' $f` +changequote([,])dnl + if test x$gcc_cv_gld_version != x; then + break + fi + done +changequote(,)dnl + gcc_cv_gld_major_version=`expr "$gcc_cv_gld_version" : "VERSION=\([0-9]*\)"` + gcc_cv_gld_minor_version=`expr "$gcc_cv_gld_version" : "VERSION=[0-9]*\.\([0-9]*\)"` +changequote([,])dnl +fi + +if test "x$gcc_cv_ld" = x -a x$host = x$target; then + # Native build. + # Search the same directories that the installed compiler will + # search. Else we may find the wrong linker and lose. If we + # do not find a suitable linker binary, then try the user's + # path. + # + # Also note we have to check MD_EXEC_PREFIX before checking the + # user's path. Unfortunately, there is no good way to get at the + # value of MD_EXEC_PREFIX here. So we do a brute force search + # through all the known MD_EXEC_PREFIX values. Ugh. This needs + # to be fixed as part of the make/configure rewrite too. + + if test "x$exec_prefix" = xNONE; then + if test "x$prefix" = xNONE; then + test_prefix=/usr/local + else + test_prefix=$prefix + fi + else + test_prefix=$exec_prefix + fi + + # If the loop below does not find an linker, then use whatever + # one we can find in the users's path. + # user's path. + gcc_cv_ld=ld$host_exeext + + test_dirs="$test_prefix/lib/gcc-lib/$target/$gcc_version \ + $test_prefix/lib/gcc-lib/$target \ + /usr/lib/gcc/$target/$gcc_version \ + /usr/lib/gcc/$target \ + $test_prefix/$target/bin/$target/$gcc_version \ + $test_prefix/$target/bin \ + /usr/libexec \ + /usr/ccs/gcc \ + /usr/ccs/bin \ + /udk/usr/ccs/bin \ + /bsd43/usr/lib/cmplrs/cc \ + /usr/cross64/usr/bin \ + /usr/lib/cmplrs/cc \ + /sysv/usr/lib/cmplrs/cc \ + /svr4/usr/lib/cmplrs/cc \ + /usr/bin" + + for dir in $test_dirs; do + if test -f $dir/ld$host_exeext; then + gcc_cv_ld=$dir/ld$host_exeext + break; + fi + done +fi +if test x$gcc_cv_gld_major_version != x -a x$gcc_cv_gld_minor_version != x; then + AC_MSG_RESULT("newly built ld") +else + AC_MSG_RESULT($gcc_cv_ld) +fi + # Figure out what nm we will be using. AC_MSG_CHECKING(what nm to use) if test -x nm$host_exeext; then @@ -1533,7 +1622,7 @@ if test x"$gcc_cv_as_shf_merge" = xyes; then fi AC_MSG_RESULT($gcc_cv_as_shf_merge) -case "$target" in +case "$target" in sparc*-*-*) AC_CACHE_CHECK([assembler .register pseudo-op support], gcc_cv_as_register_pseudo_op, [ @@ -1800,6 +1889,24 @@ if test x"$gcc_cv_as_gstabs_flag" = xyes; then fi AC_MSG_RESULT($gcc_cv_as_gstabs_flag) +AC_MSG_CHECKING(linker PT_GNU_EH_FRAME support) +gcc_cv_ld_eh_frame_hdr=no +if test x$gcc_cv_gld_major_version != x -a x$gcc_cv_gld_minor_version != x; then + if test "$gcc_cv_gld_major_version" -eq 2 -a "$gcc_cv_gld_minor_version" -ge 12 -o "$gcc_cv_gld_major_version" -gt 2 && grep 'EMUL = elf' ../ld/Makefile > /dev/null; then + gcc_cv_ld_eh_frame_hdr=yes + fi +elif test x$gcc_cv_ld != x; then + # Check if linker supports --eh-frame-hdr option + if $gcc_cv_ld --help 2>/dev/null | grep eh-frame-hdr > /dev/null; then + gcc_cv_ld_eh_frame_hdr=yes + fi +fi +if test x"$gcc_cv_ld_eh_frame_hdr" = xyes; then + AC_DEFINE(HAVE_LD_EH_FRAME_HDR, 1, +[Define if your linker supports --eh-frame-hdr option.]) +fi +AC_MSG_RESULT($gcc_cv_ld_eh_frame_hdr) + if test "$prefix" != "/usr" && test "$prefix" != "/usr/local" ; then AC_DEFINE_UNQUOTED(PREFIX_INCLUDE_DIR, "$prefix/include") fi diff --git a/gcc/crtstuff.c b/gcc/crtstuff.c index dae5190f904..8beb64cf51c 100644 --- a/gcc/crtstuff.c +++ b/gcc/crtstuff.c @@ -66,6 +66,19 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA # define CRT_CALL_STATIC_FUNCTION(func) func () #endif +#if defined(OBJECT_FORMAT_ELF) && defined(HAVE_LD_EH_FRAME_HDR) \ + && !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 + /* We do not want to add the weak attribute to the declarations of these routines in unwind-dw2-fde.h because that will cause the definition of these symbols to be weak as well. @@ -245,7 +258,7 @@ __do_global_dtors_aux (void) f (); } -#ifdef EH_FRAME_SECTION_NAME +#ifdef USE_EH_FRAME_REGISTRY #if defined(CRT_GET_RFIB_TEXT) || defined(CRT_GET_RFIB_DATA) /* If we used the new __register_frame_info_bases interface, make sure that we deregister from the same place. */ @@ -274,7 +287,7 @@ fini_dummy (void) asm (TEXT_SECTION_ASM_OP); } -#if defined(EH_FRAME_SECTION_NAME) || defined(JCR_SECTION_NAME) +#if defined(USE_EH_FRAME_REGISTRY) || defined(JCR_SECTION_NAME) /* Stick a call to __register_frame_info into the .init section. For some reason calls with no arguments work more reliably in .init, so stick the call in another function. */ @@ -282,7 +295,7 @@ fini_dummy (void) static void frame_dummy (void) { -#ifdef EH_FRAME_SECTION_NAME +#ifdef USE_EH_FRAME_REGISTRY static struct object object; #if defined(CRT_GET_RFIB_TEXT) || defined(CRT_GET_RFIB_DATA) void *tbase, *dbase; @@ -386,13 +399,13 @@ __do_global_dtors (void) for (p = __DTOR_LIST__ + 1; (f = *p); p++) f (); -#ifdef EH_FRAME_SECTION_NAME +#ifdef USE_EH_FRAME_REGISTRY if (__deregister_frame_info) __deregister_frame_info (__EH_FRAME_BEGIN__); #endif } -#if defined(EH_FRAME_SECTION_NAME) || defined(JCR_SECTION_NAME) +#if defined(USE_EH_FRAME_REGISTRY) || defined(JCR_SECTION_NAME) /* A helper function for __do_global_ctors, which is in crtend.o. Here in crtbegin.o, we can reference a couple of symbols not visible there. Plus, since we're before libgcc.a, we have no problems referencing @@ -400,7 +413,7 @@ __do_global_dtors (void) void __do_global_ctors_1(void) { -#ifdef EH_FRAME_SECTION_NAME +#ifdef USE_EH_FRAME_REGISTRY static struct object object; if (__register_frame_info) __register_frame_info (__EH_FRAME_BEGIN__, &object); @@ -547,7 +560,7 @@ void __do_global_ctors (void) { func_ptr *p; -#if defined(EH_FRAME_SECTION_NAME) || defined(JCR_SECTION_NAME) +#if defined(USE_EH_FRAME_REGISTRY) || defined(JCR_SECTION_NAME) __do_global_ctors_1(); #endif for (p = __CTOR_END__ - 1; *p != (func_ptr) -1; p--) diff --git a/gcc/gcc.c b/gcc/gcc.c index 1e150c838a2..466f6cdb1a7 100644 --- a/gcc/gcc.c +++ b/gcc/gcc.c @@ -323,7 +323,7 @@ static void clear_args PARAMS ((void)); static void fatal_error PARAMS ((int)); #ifdef ENABLE_SHARED_LIBGCC static void init_gcc_specs PARAMS ((struct obstack *, - const char *, + const char *, const char *, const char *)); #endif #if defined(HAVE_TARGET_OBJECT_SUFFIX) || defined(HAVE_TARGET_EXECUTABLE_SUFFIX) @@ -1416,28 +1416,36 @@ static struct spec_list *specs = (struct spec_list *) 0; #ifdef ENABLE_SHARED_LIBGCC static void -init_gcc_specs (obstack, shared_name, static_name) +init_gcc_specs (obstack, shared_name, static_name, eh_name) struct obstack *obstack; const char *shared_name; const char *static_name; + const char *eh_name; { char buffer[128]; + const char *p; /* If we see -shared-libgcc, then use the shared version. */ sprintf (buffer, "%%{shared-libgcc:%s %s}", shared_name, static_name); obstack_grow (obstack, buffer, strlen (buffer)); /* If we see -static-libgcc, then use the static version. */ - sprintf (buffer, "%%{static-libgcc:%s}", static_name); + sprintf (buffer, "%%{static-libgcc:%s %s}", static_name, eh_name); obstack_grow (obstack, buffer, strlen (buffer)); - /* Otherwise, if we see -shared, then use the shared version. */ - sprintf (buffer, - "%%{!shared-libgcc:%%{!static-libgcc:%%{shared:%s %s}}}", - shared_name, static_name); + /* Otherwise, if we see -shared, then use the shared version + if using EH registration routines or static version without + exception handling routines otherwise. */ + p = "%{!shared-libgcc:%{!static-libgcc:%{shared:"; + obstack_grow (obstack, p, strlen (p)); +#ifdef LINK_EH_SPEC + sprintf (buffer, "%s}}}", static_name); +#else + sprintf (buffer, "%s %s}}}", shared_name, static_name); +#endif obstack_grow (obstack, buffer, strlen (buffer)); /* Otherwise, use the static version. */ sprintf (buffer, - "%%{!shared-libgcc:%%{!static-libgcc:%%{!shared:%s}}}", - static_name); + "%%{!shared-libgcc:%%{!static-libgcc:%%{!shared:%s %s}}}", + static_name, eh_name); obstack_grow (obstack, buffer, strlen (buffer)); } #endif /* ENABLE_SHARED_LIBGCC */ @@ -1525,7 +1533,8 @@ init_spec () "-lgcc_s%M" #endif , - "-lgcc"); + "-lgcc", + "-lgcc_eh"); p += 5; in_sep = 0; } @@ -1540,7 +1549,8 @@ init_spec () "-lgcc_s%M" #endif , - "libgcc.a%s"); + "libgcc.a%s", + "libgcc_eh.a%s"); p += 10; in_sep = 0; } @@ -1565,6 +1575,12 @@ init_spec () asm_spec = obstack_finish (&obstack); } #endif +#ifdef LINK_EH_SPEC + /* Prepend LINK_EH_SPEC to whatever link_spec we had before. */ + obstack_grow (&obstack, LINK_EH_SPEC, sizeof(LINK_EH_SPEC) - 1); + obstack_grow0 (&obstack, link_spec, strlen (link_spec)); + link_spec = obstack_finish (&obstack); +#endif specs = sl; } diff --git a/gcc/mklibgcc.in b/gcc/mklibgcc.in index de633497973..8f9174a0f5d 100644 --- a/gcc/mklibgcc.in +++ b/gcc/mklibgcc.in @@ -97,6 +97,7 @@ done libgcc2_objs="" libgcc2_st_objs="" +libgcc2_eh_objs="" for name in $LIB2FUNCS; do for ml in $MULTILIBS; do @@ -200,7 +201,11 @@ for file in $LIB2ADDEH; do echo $out: stmp-dirs $file echo " $gcc_compile" $flags -fexceptions -c $file -o $out done - libgcc2_objs="$libgcc2_objs ${oname}${objext}" + if [ "$SHLIB_LINK" ]; then + libgcc2_eh_objs="$libgcc2_eh_objs ${oname}${objext}" + else + libgcc2_objs="$libgcc2_objs ${oname}${objext}" + fi done for file in $LIB2ADD_ST; do @@ -228,13 +233,18 @@ for ml in $MULTILIBS; do flags=`echo ${ml} | sed -e 's/^[^;]*;//' -e 's/@/ -/g'`; libgcc_objs="" + libgcc_eh_objs="" for o in $libgcc1_objs; do libgcc_objs="$libgcc_objs libgcc/${dir}/$o" done for o in $libgcc2_objs; do libgcc_objs="$libgcc_objs libgcc/${dir}/$o" done - shlib_deps="$libgcc_objs" + for o in $libgcc2_eh_objs; do + libgcc_eh_objs="$libgcc_eh_objs libgcc/${dir}/$o" + done + libgcc_sh_objs="$libgcc_objs $libgcc_eh_objs" + shlib_deps="$libgcc_sh_objs" libgcc_st_objs="" for o in $libgcc2_st_objs; do @@ -244,8 +254,8 @@ for ml in $MULTILIBS; do if [ "$SHLIB_LINK" -a "$SHLIB_MKMAP" -a -z "$mapfile" ]; then mapfile="libgcc.map" echo "" - echo "${mapfile}: $SHLIB_MKMAP $SHLIB_MAPFILES $libgcc_objs" - echo ' { $(NM_FOR_TARGET)'" $SHLIB_NM_FLAGS $libgcc_objs; echo %%; cat $SHLIB_MAPFILES; } | "'$(AWK)'" -f $SHLIB_MKMAP > "'tmp-$@' + echo "${mapfile}: $SHLIB_MKMAP $SHLIB_MAPFILES $libgcc_sh_objs" + echo ' { $(NM_FOR_TARGET)'" $SHLIB_NM_FLAGS $libgcc_sh_objs; echo %%; cat $SHLIB_MAPFILES; } | "'$(AWK)'" -f $SHLIB_MKMAP > "'tmp-$@' echo ' mv tmp-$@ $@' fi shlib_deps="$shlib_deps $mapfile" @@ -265,6 +275,15 @@ for ml in $MULTILIBS; do echo ' else true; fi;' if [ "$SHLIB_LINK" ]; then + + echo "" + echo "${dir}/libgcc_eh.a: $libgcc_eh_objs" + echo " -rm -rf ${dir}/libgcc_eh.a" + echo ' $(AR_CREATE_FOR_TARGET)' ${dir}/libgcc_eh.a $libgcc_eh_objs + echo ' if $(RANLIB_TEST_FOR_TARGET) ; then' \\ + echo ' $(RANLIB_FOR_TARGET)' ${dir}/libgcc_eh.a ';' \\ + echo ' else true; fi;' + if [ -z "$SHLIB_MULTILIB" ]; then if [ "$dir" = "." ]; then shlib_base_name="libgcc_s"; @@ -276,7 +295,7 @@ for ml in $MULTILIBS; do echo " $SHLIB_LINK" \ | sed -e "s%@multilib_flags@%$flags%g" \ -e "s%@multilib_dir@%$dir%g" \ - -e "s%@shlib_objs@%$libgcc_objs%g" \ + -e "s%@shlib_objs@%$libgcc_sh_objs%g" \ -e "s%@shlib_base_name@%$shlib_base_name%g" \ -e "s%@shlib_map_file@%$mapfile%g" elif [ "$SHLIB_MULTILIB" = "$dir" ]; then @@ -286,7 +305,7 @@ for ml in $MULTILIBS; do echo " $SHLIB_LINK" \ | sed -e "s%@multilib_flags@%$flags%g" \ -e "s%@multilib_dir@%$dir%g" \ - -e "s%@shlib_objs@%$libgcc_objs%g" \ + -e "s%@shlib_objs@%$libgcc_sh_objs%g" \ -e "s%@shlib_base_name@%$shlib_base_name%g" \ -e "s%@shlib_map_file@%$mapfile%g" fi @@ -320,6 +339,7 @@ for ml in $MULTILIBS; do fi all="$all ${dir}/libgcc.a" if [ "$SHLIB_LINK" ]; then + all="$all ${dir}/libgcc_eh.a" if [ -z "$SHLIB_MULTILIB" ]; then if [ "$dir" = "." ]; then suff=""; @@ -379,6 +399,9 @@ for ml in $MULTILIBS; do echo ' $(RANLIB_FOR_TARGET)' ${ldir}/libgcc.a if [ "$SHLIB_LINK" ]; then + echo ' $(INSTALL_DATA)' ${dir}/libgcc_eh.a ${ldir}/ + echo ' $(RANLIB_FOR_TARGET)' ${ldir}/libgcc_eh.a + if [ -z "$SHLIB_MULTILIB" ]; then if [ "$dir" = "." ]; then shlib_base_name="libgcc_s"; diff --git a/gcc/unwind-dw2-fde-glibc.c b/gcc/unwind-dw2-fde-glibc.c new file mode 100644 index 00000000000..c57986118a4 --- /dev/null +++ b/gcc/unwind-dw2-fde-glibc.c @@ -0,0 +1,291 @@ +/* Copyright (C) 2001 Free Software Foundation, Inc. + Contributed by Jakub Jelinek <jakub@redhat.com>. + + This file is part of GNU CC. + + GNU CC is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + GNU CC is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with GNU CC; see the file COPYING. If not, write to + the Free Software Foundation, 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +/* As a special exception, if you link this library with other files, + some of which are compiled with GCC, to produce an executable, + this library does not by itself cause the resulting executable + to be covered by the GNU General Public License. + This exception does not however invalidate any other reasons why + the executable file might be covered by the GNU General Public License. */ + +/* Locate the FDE entry for a given address, using PT_GNU_EH_FRAME ELF + segment and dl_iterate_phdr to avoid register/deregister calls at + DSO load/unload. */ + +#include "auto-host.h" /* For HAVE_LD_EH_FRAME_HDR. */ +#include "tconfig.h" +#include <stddef.h> +#include <stdlib.h> +#include <link.h> +#include "tsystem.h" +#include "dwarf2.h" +#include "unwind.h" +#define NO_BASE_OF_ENCODED_VALUE +#include "unwind-pe.h" +#include "unwind-dw2-fde.h" +#include "gthr.h" + +#if defined(HAVE_LD_EH_FRAME_HDR) \ + && (__GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ > 2) \ + || (__GLIBC__ == 2 && __GLIBC_MINOR__ == 2 && defined(DT_CONFIG))) + +static fde * _Unwind_Find_registered_FDE (void *pc, struct dwarf_eh_bases *bases); + +#define _Unwind_Find_FDE _Unwind_Find_registered_FDE +#include "unwind-dw2-fde.c" +#undef _Unwind_Find_FDE + +#ifndef PT_GNU_EH_FRAME +#define PT_GNU_EH_FRAME (PT_LOOS + 0x474e550) +#endif + +struct unw_eh_callback_data +{ + _Unwind_Ptr pc; + void *tbase; + void *dbase; + void *func; + fde *ret; +}; + +struct unw_eh_frame_hdr +{ + unsigned char version; + unsigned char eh_frame_ptr_enc; + unsigned char fde_count_enc; + unsigned char table_enc; +}; + +/* Like base_of_encoded_value, but take the base from a struct object + instead of an _Unwind_Context. */ + +static _Unwind_Ptr +base_from_cb_data (unsigned char encoding, struct unw_eh_callback_data *data) +{ + if (encoding == DW_EH_PE_omit) + return 0; + + switch (encoding & 0x70) + { + case DW_EH_PE_absptr: + case DW_EH_PE_pcrel: + case DW_EH_PE_aligned: + return 0; + + case DW_EH_PE_textrel: + return (_Unwind_Ptr) data->tbase; + case DW_EH_PE_datarel: + return (_Unwind_Ptr) data->dbase; + } + abort (); +} + +static int +_Unwind_IteratePhdrCallback (struct dl_phdr_info *info, size_t size, void *ptr) +{ + struct unw_eh_callback_data *data = (struct unw_eh_callback_data *) ptr; + const ElfW(Phdr) *phdr, *p_eh_frame_hdr, *p_dynamic; + long n, match; + _Unwind_Ptr load_base; + const unsigned char *p; + const struct unw_eh_frame_hdr *hdr; + _Unwind_Ptr eh_frame; + struct object ob; + + /* Make sure struct dl_phdr_info is at least as big as we need. */ + if (size < offsetof (struct dl_phdr_info, dlpi_phnum) + + sizeof (info->dlpi_phnum)) + return -1; + + match = 0; + phdr = info->dlpi_phdr; + load_base = info->dlpi_addr; + p_eh_frame_hdr = NULL; + p_dynamic = NULL; + + /* See if PC falls into one of the loaded segments. Find the eh_frame + segment at the same time. */ + for (n = info->dlpi_phnum; --n >= 0; phdr++) + { + if (phdr->p_type == PT_LOAD) + { + _Unwind_Ptr vaddr = phdr->p_vaddr + load_base; + if (data->pc >= vaddr && data->pc < vaddr + phdr->p_memsz) + match = 1; + } + else if (phdr->p_type == PT_GNU_EH_FRAME) + p_eh_frame_hdr = phdr; + else if (phdr->p_type == PT_DYNAMIC) + p_dynamic = phdr; + } + if (!match || !p_eh_frame_hdr) + return 0; + + /* Read .eh_frame_hdr header. */ + hdr = (const struct unw_eh_frame_hdr *) + (p_eh_frame_hdr->p_vaddr + load_base); + if (hdr->version != 1) + return 1; + +#ifdef CRT_GET_RFIB_DATA +# ifdef __i386__ + data->dbase = NULL; + if (p_dynamic) + { + /* For dynamicly linked executables and shared libraries, + DT_PLTGOT is the gp value for that object. */ + ElfW(Dyn) *dyn = (ElfW(Dyn) *)(p_dynamic->p_vaddr + load_base); + for (; dyn->d_tag != DT_NULL ; dyn++) + if (dyn->d_tag == DT_PLTGOT) + { + /* On IA-32, _DYNAMIC is writable and GLIBC has relocated it. */ + data->dbase = (void *) dyn->d_un.d_ptr; + break; + } + } +# else +# error What is DW_EH_PE_datarel base on this platform? +# endif +#endif +#ifdef CRT_GET_RFIB_TEXT +# error What is DW_EH_PE_textrel base on this platform? +#endif + + p = read_encoded_value_with_base (hdr->eh_frame_ptr_enc, + base_from_cb_data (hdr->eh_frame_ptr_enc, + data), + (const unsigned char *) (hdr + 1), + &eh_frame); + + /* We require here specific table encoding to speed things up. + Also, DW_EH_PE_datarel here means using PT_GNU_EH_FRAME start + as base, not the processor specific DW_EH_PE_datarel. */ + if (hdr->fde_count_enc != DW_EH_PE_omit + && hdr->table_enc == (DW_EH_PE_datarel | DW_EH_PE_sdata4)) + { + _Unwind_Ptr fde_count; + + p = read_encoded_value_with_base (hdr->fde_count_enc, + base_from_cb_data (hdr->fde_count_enc, + data), + p, &fde_count); + /* Shouldn't happen. */ + if (fde_count == 0) + return 1; + if ((((_Unwind_Ptr) p) & 3) == 0) + { + struct fde_table { + signed initial_loc __attribute__ ((mode (SI))); + signed fde __attribute__ ((mode (SI))); + }; + const struct fde_table *table = (const struct fde_table *) p; + size_t lo, hi, mid; + _Unwind_Ptr data_base = (_Unwind_Ptr) hdr; + fde *f; + unsigned int f_enc, f_enc_size; + _Unwind_Ptr range; + + mid = fde_count - 1; + if (data->pc < table[0].initial_loc + data_base) + return 1; + else if (data->pc < table[mid].initial_loc + data_base) + { + lo = 0; + hi = mid; + + while (lo < hi) + { + mid = (lo + hi) / 2; + if (data->pc < table[mid].initial_loc + data_base) + hi = mid; + else if (data->pc >= table[mid + 1].initial_loc + data_base) + lo = mid + 1; + else + break; + } + + if (lo >= hi) + __gxx_abort (); + } + + f = (fde *) (table[mid].fde + data_base); + f_enc = get_fde_encoding (f); + f_enc_size = size_of_encoded_value (f_enc); + read_encoded_value_with_base (f_enc & 0x0f, 0, + &f->pc_begin[f_enc_size], &range); + if (data->pc < table[mid].initial_loc + data_base + range) + data->ret = f; + data->func = (void *) (table[mid].initial_loc + data_base); + return 1; + } + } + + /* We have no sorted search table, so need to go the slow way. + As soon as GLIBC will provide API so to notify that a library has been + removed, we could cache this (and thus use search_object). */ + ob.pc_begin = NULL; + ob.tbase = data->tbase; + ob.dbase = data->dbase; + ob.u.single = (fde *) eh_frame; + ob.s.i = 0; + ob.s.b.mixed_encoding = 1; /* Need to assume worst case. */ + data->ret = linear_search_fdes (&ob, (fde *) eh_frame, (void *) data->pc); + if (data->ret != NULL) + { + unsigned int encoding = get_fde_encoding (data->ret); + read_encoded_value_with_base (encoding, + base_from_cb_data (encoding, data), + data->ret->pc_begin, + (_Unwind_Ptr *)&data->func); + } + return 1; +} + +fde * +_Unwind_Find_FDE (void *pc, struct dwarf_eh_bases *bases) +{ + struct unw_eh_callback_data data; + fde *ret; + + ret = _Unwind_Find_registered_FDE (pc, bases); + if (ret != NULL) + return ret; + + data.pc = (_Unwind_Ptr) pc; + data.tbase = NULL; + data.dbase = NULL; + data.func = NULL; + data.ret = NULL; + + if (dl_iterate_phdr (_Unwind_IteratePhdrCallback, &data) < 0) + return NULL; + + if (data.ret) + { + bases->tbase = data.tbase; + bases->dbase = data.dbase; + bases->func = data.func; + } + return data.ret; +} + +#else +#include "unwind-dw2-fde.c" +#endif diff --git a/gcc/unwind-dw2-fde.c b/gcc/unwind-dw2-fde.c index d87cac5b625..29d84cee6a5 100644 --- a/gcc/unwind-dw2-fde.c +++ b/gcc/unwind-dw2-fde.c @@ -28,6 +28,7 @@ along with GCC; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ +#ifndef _Unwind_Find_FDE #include "tconfig.h" #include "tsystem.h" #include "dwarf2.h" @@ -36,6 +37,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA #include "unwind-pe.h" #include "unwind-dw2-fde.h" #include "gthr.h" +#endif /* The unseen_objects list contains objects that have been registered but not yet categorized in any way. The seen_objects list has had |