summaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorjakub <jakub@138bc75d-0d04-0410-961f-82ee72b054a4>2001-12-15 11:49:18 +0000
committerjakub <jakub@138bc75d-0d04-0410-961f-82ee72b054a4>2001-12-15 11:49:18 +0000
commit0d6378a9e3e589217fda7be9ae273aee14540fe0 (patch)
tree1e290b8253af587309d21dfa2217501a304a75ac /gcc
parentbee0e6ed4aac405fc7e97f44c491966e086649ba (diff)
downloadgcc-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/ChangeLog38
-rw-r--r--gcc/Makefile.in35
-rw-r--r--gcc/config.gcc22
-rw-r--r--gcc/config.in3
-rw-r--r--gcc/config/i386/gnu.h3
-rw-r--r--gcc/config/ia64/fde-glibc.c4
-rw-r--r--gcc/config/ia64/linux.h15
-rw-r--r--gcc/config/linux.h14
-rw-r--r--gcc/config/sparc/linux.h11
-rw-r--r--gcc/config/sparc/linux64.h12
-rw-r--r--gcc/config/sparc/t-linux642
-rw-r--r--gcc/config/t-linux5
-rw-r--r--gcc/config/t-linux-gnulibc15
-rwxr-xr-xgcc/configure107
-rw-r--r--gcc/configure.in109
-rw-r--r--gcc/crtstuff.c27
-rw-r--r--gcc/gcc.c38
-rw-r--r--gcc/mklibgcc.in35
-rw-r--r--gcc/unwind-dw2-fde-glibc.c291
-rw-r--r--gcc/unwind-dw2-fde.c2
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