configure.in: Check for ld.

* 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.

From-SVN: r48039
This commit is contained in:
Jakub Jelinek 2001-12-15 12:49:18 +01:00 committed by Jakub Jelinek
parent 861ef92859
commit 275b60d6d8
20 changed files with 731 additions and 47 deletions

View File

@ -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

View File

@ -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; \

View File

@ -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'

View File

@ -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

View File

@ -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

View File

@ -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;

View File

@ -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 */

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

107
gcc/configure vendored
View File

@ -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"

View File

@ -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

View File

@ -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--)

View File

@ -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;
}

View File

@ -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";

291
gcc/unwind-dw2-fde-glibc.c Normal file
View File

@ -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

View File

@ -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