diff options
53 files changed, 4446 insertions, 156 deletions
diff --git a/ChangeLog b/ChangeLog index 7851b1b87c..239cc91ff6 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,69 @@ +2001-10-02 Jakub Jelinek <jakub@redhat.com> + H.J. Lu <hjl@gnu.org> + + * configure.in (libc_cv_gcc_static_libgcc): Set to -static-libgcc + if gcc supports this flag. + (EXPORT_UNWIND_FIND_FDE): Define unless target configure disables it. + (gcc3): Allow glibc to be compiled with gcc 3.x. + * config.h.in (EXPORT_UNWIND_FIND_FDE): Add. + * config.make.in (static-libgcc, unwind-find-fde): Add. + * Makerules (build-shlib-helper, build-module-helper): Use it. + * scripts/versions.awk: Make sure GLIBC_ versions come first. + * elf/soinit.c (__libc_global_ctors): Set tbases and dbases if + necessary. + (_fini): Call __deregister_frame_info_bases if + __register_frame_info_bases was used to register. + * elf/Versions (__register_frame_info, __deregister_frame_info): Add + for GLIBC_2.0. + (__register_frame_info_bases, __register_frame_info_table_bases, + __deregister_frame_info_bases, _Unwind_Find_FDE): Add for GLIBC_2.2.5. + * elf/Makefile (routines): Add unwind-dw2-fde. + (shared-only-routines): Add unwind-dw2-fde. + * sysdeps/alpha/gccframe.h: New file. + * sysdeps/arm/gccframe.h: New file. + * sysdeps/generic/framestate.c: New file. + * sysdeps/generic/dwarf2.h: New file. + * sysdeps/generic/gccframe.h (struct object): Update from gcc 3.0. + * sysdeps/generic/unwind-dw2-fde.c: New file. + * sysdeps/unix/sysv/linux/ia64/unwind-dw2-fde.c: New file. + * sysdeps/generic/unwind-dw2-fde.h: New file. + * sysdeps/generic/unwind-dw2.c: New file. + * sysdeps/generic/unwind-pe.h: New file. + * sysdeps/generic/unwind.h: New file. + * sysdeps/hppa/gccframe.h: New file. + * sysdeps/i386/gccframe.h: New file. + * sysdeps/m68k/gccframe.h: New file. + * sysdeps/mips/gccframe.h: New file. + * sysdeps/powerpc/gccframe.h: New file. + * sysdeps/s390/gccframe.h: New file. + * sysdeps/sh/gccframe.h: New file. + * sysdeps/sparc/gccframe.h: New file. + * sysdeps/vax/gccframe.h: New file. + * sysdeps/unix/sysv/linux/configure.in (libc_cv_gcc_unwind_find_fde): + Set on all architectures except ia64. + * sysdeps/mach/hurd/configure.in (libc_cv_gcc_unwind_find_fde): Set + for i386. + * sysdeps/mach/hurd/i386/Versions (__register_frame_info, + __deregister_frame_info): Move to elf/Versions. + * sysdeps/unix/sysv/linux/m68k/Versions: Likewise. + * sysdeps/unix/sysv/linux/arm/Versions: Likewise. + * sysdeps/unix/sysv/linux/alpha/Versions: Likewise. + * sysdeps/unix/sysv/linux/i386/Versions: Likewise. + * sysdeps/unix/sysv/linux/mips/Versions: Likewise. + * sysdeps/unix/sysv/linux/powerpc/Versions: Likewise. + * sysdeps/unix/sysv/linux/s390/s390-32/Versions: Likewise. + * sysdeps/unix/sysv/linux/sparc/sparc32/Versions: Likewise. + * sysdeps/unix/sysv/linux/sparc/sparc64/Versions: Likewise. + * sysdeps/mach/hurd/i386/Makefile (sysdep-routines): Add framestate. + * sysdeps/unix/sysv/linux/arm/Makefile: Likewise. + * sysdeps/unix/sysv/linux/alpha/Makefile: Likewise. + * sysdeps/unix/sysv/linux/i386/Makefile: Likewise. + * sysdeps/unix/sysv/linux/m68k/Makefile: Likewise. + * sysdeps/unix/sysv/linux/mips/Makefile: Likewise. + * sysdeps/unix/sysv/linux/powerpc/Makefile: Likewise. + * sysdeps/unix/sysv/linux/s390/s390-32/Makefile: Likewise. + * sysdeps/unix/sysv/linux/sparc/Makefile: Likewise. + 2001-11-15 Jeff Law <law@redhat.com> * posix/regex.c (uintptr_t): Do not provide a definition if the @@ -798,8 +864,8 @@ 2001-09-18 Jakub Jelinek <jakub@redhat.com> - * sysdeps/unix/sysv/linux/ia64/ldd-rewrite.sed: New. - * sysdeps/unix/sysv/linux/s390/ldd-rewrite.sed: New. + * sysdeps/unix/sysv/linux/ia64/ldd-rewrite.sed: New file. + * sysdeps/unix/sysv/linux/s390/ldd-rewrite.sed: New file. * sysdeps/unix/sysv/linux/configure.in: Add ia64 and s390 ldd-rewrite scripts. @@ -1632,7 +1698,7 @@ 2001-08-21 Jakub Jelinek <jakub@redhat.com> * string/strnlen.c: Remove. - * sysdeps/generic/strnlen.c: New. + * sysdeps/generic/strnlen.c: New file. * sysdeps/i386/i486/bits/string.h (strnlen): Remove. 2001-08-21 Roland McGrath <roland@frob.com> diff --git a/Makerules b/Makerules index 59ca838166..ac1bdb7830 100644 --- a/Makerules +++ b/Makerules @@ -400,7 +400,7 @@ endif ifeq ($(elf),yes) define build-shlib-helper -$(LINK.o) -shared -Wl,-O1 $(sysdep-LDFLAGS) $(config-LDFLAGS) \ +$(LINK.o) -shared $(static-libgcc) -Wl,-O1 $(sysdep-LDFLAGS) $(config-LDFLAGS) \ $(extra-B-$(@F:lib%.so=%).so) -B$(csu-objpfx) \ $(extra-B-$(@F:lib%.so=%).so) $(load-map-file) \ -Wl,-soname=lib$(libprefix)$(@F:lib%.so=%).so$($(@F)-version) \ @@ -460,7 +460,7 @@ $(LINK.o) -Wl,-G -Wl,-bM:SRE -Wl,-bnoentry -Wl,-bexpall \ endef else define build-module-helper -$(LINK.o) -shared $(sysdep-LDFLAGS) $(config-LDFLAGS) \ +$(LINK.o) -shared $(static-libgcc) $(sysdep-LDFLAGS) $(config-LDFLAGS) \ -B$(csu-objpfx) $(load-map-file) \ $(LDFLAGS.so) $(LDFLAGS-$(@F:%.so=%).so) \ -L$(subst :, -L,$(rpath-link)) -Wl,-rpath-link=$(rpath-link) diff --git a/config.h.in b/config.h.in index ffeb1f39de..475bd72a38 100644 --- a/config.h.in +++ b/config.h.in @@ -48,6 +48,9 @@ /* Define a symbol_name as a global .symbol_name for ld. */ #undef HAVE_ASM_GLOBAL_DOT_NAME +/* Define if _Unwind_Find_FDE should be exported from glibc. */ +#undef EXPORT_UNWIND_FIND_FDE + /* Define to use GNU libio instead of GNU stdio. This is defined by configure under --enable-libio. */ #undef USE_IN_LIBIO diff --git a/config.make.in b/config.make.in index 625e328bc8..4c382b2f49 100644 --- a/config.make.in +++ b/config.make.in @@ -46,6 +46,9 @@ have-Bgroup = @libc_cv_Bgroup@ need-nopic-initfini = @nopic_initfini@ with-cvs = @with_cvs@ old-glibc-headers = @old_glibc_headers@ +unwind-find-fde = @libc_cv_gcc_unwind_find_fde@ + +static-libgcc = @libc_cv_gcc_static_libgcc@ versioning = @VERSIONING@ oldest-abi = @oldest_abi@ diff --git a/configure b/configure index 7025017910..a07ca8a882 100755 --- a/configure +++ b/configure @@ -2105,27 +2105,6 @@ test -n "$aux_missing" && echo "configure: warning: CCVERSION=`$CC -v 2>&1 | sed -n 's/gcc version //p'` -case $CCVERSION in - 3.*) gcc3=yes;; -esac - -if test x"$gcc3" = xyes; then - echo "\ -*** This version of GNU libc cannot be compiled by GCC 3.x. -*** GCC 3.x will generate a library that is binary incompatible to -*** older and future releases of GNU libc. -*** You should compile this GNU libc release by an older GCC version -*** or wait for the next GNU libc release." - if test $enable_sanity = yes; then - echo "\ -*** If you really mean to use GCC 3.x, run configure again -*** using the extra parameter \`--disable-sanity-checks'." - exit 1 - else - echo "\ -*** This configuration is not supported by the GNU libc developers." - fi -fi # if using special system headers, find out the compiler's sekrit # header directory and add that to the list. NOTE: Only does the right # thing on a system that doesn't need fixincludes. (Not presently a problem.) @@ -2137,7 +2116,7 @@ fi # check if ranlib is necessary echo $ac_n "checking whether ranlib is necessary""... $ac_c" 1>&6 -echo "configure:2141: checking whether ranlib is necessary" >&5 +echo "configure:2120: checking whether ranlib is necessary" >&5 if eval "test \"`echo '$''{'libc_cv_ranlib_necessary'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -2171,7 +2150,7 @@ fi # - two terminals occur directly after each other # - the path contains an element with a dot in it echo $ac_n "checking LD_LIBRARY_PATH variable""... $ac_c" 1>&6 -echo "configure:2175: checking LD_LIBRARY_PATH variable" >&5 +echo "configure:2154: checking LD_LIBRARY_PATH variable" >&5 case ${LD_LIBRARY_PATH} in [:\;]* | *[:\;] | *[:\;][:\;]* | *[:\;]. | .[:\;]*| . | *[:\;].[:\;]* ) ld_library_path_setting="contains current directory" @@ -2188,10 +2167,25 @@ if test "$ld_library_path_setting" != "ok"; then *** and run configure again." 1>&2; exit 1; } fi +echo $ac_n "checking whether GCC supports -static-libgcc""... $ac_c" 1>&6 +echo "configure:2172: checking whether GCC supports -static-libgcc" >&5 +if eval "test \"`echo '$''{'libc_cv_gcc_static_libgcc'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + if $CC -v -static-libgcc 2>&1 | grep -q 'unrecognized option.*static-libgcc'; then + libc_cv_gcc_static_libgcc= +else + libc_cv_gcc_static_libgcc=-static-libgcc +fi +fi + +echo "$ac_t""$libc_cv_gcc_static_libgcc" 1>&6 + + # Extract the first word of "bash", so it can be a program name with args. set dummy bash; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:2195: checking for $ac_word" >&5 +echo "configure:2189: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_path_BASH'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -2237,7 +2231,7 @@ if test "$BASH" = no; then # Extract the first word of "ksh", so it can be a program name with args. set dummy ksh; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:2241: checking for $ac_word" >&5 +echo "configure:2235: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_path_KSH'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -2287,7 +2281,7 @@ do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:2291: checking for $ac_word" >&5 +echo "configure:2285: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_prog_AWK'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -2319,7 +2313,7 @@ done # Extract the first word of "perl", so it can be a program name with args. set dummy perl; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:2323: checking for $ac_word" >&5 +echo "configure:2317: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_path_PERL'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -2359,7 +2353,7 @@ fi # Extract the first word of "install-info", so it can be a program name with args. set dummy install-info; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:2363: checking for $ac_word" >&5 +echo "configure:2357: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_path_INSTALL_INFO'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -2394,7 +2388,7 @@ fi if test "$INSTALL_INFO" != "no"; then echo $ac_n "checking for old Debian install-info""... $ac_c" 1>&6 -echo "configure:2398: checking for old Debian install-info" >&5 +echo "configure:2392: checking for old Debian install-info" >&5 if eval "test \"`echo '$''{'libc_cv_old_debian_install_info'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -2429,7 +2423,7 @@ fi # Extract the first word of "bison", so it can be a program name with args. set dummy bison; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:2433: checking for $ac_word" >&5 +echo "configure:2427: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_path_BISON'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -2464,7 +2458,7 @@ fi echo $ac_n "checking for signed size_t type""... $ac_c" 1>&6 -echo "configure:2468: checking for signed size_t type" >&5 +echo "configure:2462: checking for signed size_t type" >&5 if eval "test \"`echo '$''{'libc_cv_signed_size_t'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -2488,12 +2482,12 @@ EOF fi echo $ac_n "checking for libc-friendly stddef.h""... $ac_c" 1>&6 -echo "configure:2492: checking for libc-friendly stddef.h" >&5 +echo "configure:2486: checking for libc-friendly stddef.h" >&5 if eval "test \"`echo '$''{'libc_cv_friendly_stddef'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <<EOF -#line 2497 "configure" +#line 2491 "configure" #include "confdefs.h" #define __need_size_t #define __need_wchar_t @@ -2508,7 +2502,7 @@ size_t size; wchar_t wchar; if (&size == NULL || &wchar == NULL) abort (); ; return 0; } EOF -if { (eval echo configure:2512: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:2506: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* libc_cv_friendly_stddef=yes else @@ -2527,7 +2521,7 @@ override stddef.h = # The installed <stddef.h> seems to be libc-friendly." fi echo $ac_n "checking whether we need to use -P to assemble .S files""... $ac_c" 1>&6 -echo "configure:2531: checking whether we need to use -P to assemble .S files" >&5 +echo "configure:2525: checking whether we need to use -P to assemble .S files" >&5 if eval "test \"`echo '$''{'libc_cv_need_minus_P'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -2550,7 +2544,7 @@ asm-CPPFLAGS = -P # The assembler can't grok cpp's # line directives." fi echo $ac_n "checking whether .text pseudo-op must be used""... $ac_c" 1>&6 -echo "configure:2554: checking whether .text pseudo-op must be used" >&5 +echo "configure:2548: checking whether .text pseudo-op must be used" >&5 if eval "test \"`echo '$''{'libc_cv_dot_text'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -2571,7 +2565,7 @@ else fi echo $ac_n "checking for assembler global-symbol directive""... $ac_c" 1>&6 -echo "configure:2575: checking for assembler global-symbol directive" >&5 +echo "configure:2569: checking for assembler global-symbol directive" >&5 if eval "test \"`echo '$''{'libc_cv_asm_global_directive'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -2601,7 +2595,7 @@ EOF fi echo $ac_n "checking for .set assembler directive""... $ac_c" 1>&6 -echo "configure:2605: checking for .set assembler directive" >&5 +echo "configure:2599: checking for .set assembler directive" >&5 if eval "test \"`echo '$''{'libc_cv_asm_set_directive'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -2644,7 +2638,7 @@ EOF esac echo $ac_n "checking for .symver assembler directive""... $ac_c" 1>&6 -echo "configure:2648: checking for .symver assembler directive" >&5 +echo "configure:2642: checking for .symver assembler directive" >&5 if eval "test \"`echo '$''{'libc_cv_asm_symver_directive'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -2663,7 +2657,7 @@ fi echo "$ac_t""$libc_cv_asm_symver_directive" 1>&6 echo $ac_n "checking for ld --version-script""... $ac_c" 1>&6 -echo "configure:2667: checking for ld --version-script" >&5 +echo "configure:2661: checking for ld --version-script" >&5 if eval "test \"`echo '$''{'libc_cv_ld_version_script_option'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -2686,7 +2680,7 @@ EOF if { ac_try='${CC-cc} $CFLAGS -shared -o conftest.so conftest.o -nostartfiles -nostdlib -Wl,--version-script,conftest.map - 1>&5'; { (eval echo configure:2690: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; }; + 1>&5'; { (eval echo configure:2684: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; }; then libc_cv_ld_version_script_option=yes else @@ -2725,7 +2719,7 @@ if test $elf = yes && test $shared != no && test $VERSIONING = no; then fi if test $elf = yes; then echo $ac_n "checking for .previous assembler directive""... $ac_c" 1>&6 -echo "configure:2729: checking for .previous assembler directive" >&5 +echo "configure:2723: checking for .previous assembler directive" >&5 if eval "test \"`echo '$''{'libc_cv_asm_previous_directive'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -2733,7 +2727,7 @@ else .section foo_section .previous EOF - if { ac_try='${CC-cc} -c $CFLAGS conftest.s 1>&5'; { (eval echo configure:2737: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; }; then + if { ac_try='${CC-cc} -c $CFLAGS conftest.s 1>&5'; { (eval echo configure:2731: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; }; then libc_cv_asm_previous_directive=yes else libc_cv_asm_previous_directive=no @@ -2749,7 +2743,7 @@ EOF else echo $ac_n "checking for .popsection assembler directive""... $ac_c" 1>&6 -echo "configure:2753: checking for .popsection assembler directive" >&5 +echo "configure:2747: checking for .popsection assembler directive" >&5 if eval "test \"`echo '$''{'libc_cv_asm_popsection_directive'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -2757,7 +2751,7 @@ else .pushsection foo_section .popsection EOF - if { ac_try='${CC-cc} -c $CFLAGS conftest.s 1>&5'; { (eval echo configure:2761: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; }; then + if { ac_try='${CC-cc} -c $CFLAGS conftest.s 1>&5'; { (eval echo configure:2755: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; }; then libc_cv_asm_popsection_directive=yes else libc_cv_asm_popsection_directive=no @@ -2774,7 +2768,7 @@ EOF fi fi echo $ac_n "checking for .protected and .hidden assembler directive""... $ac_c" 1>&6 -echo "configure:2778: checking for .protected and .hidden assembler directive" >&5 +echo "configure:2772: checking for .protected and .hidden assembler directive" >&5 if eval "test \"`echo '$''{'libc_cv_asm_protected_directive'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -2784,7 +2778,7 @@ foo: .hidden bar bar: EOF - if { ac_try='${CC-cc} -c $CFLAGS conftest.s 1>&5'; { (eval echo configure:2788: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; }; then + if { ac_try='${CC-cc} -c $CFLAGS conftest.s 1>&5'; { (eval echo configure:2782: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; }; then libc_cv_asm_protected_directive=yes else libc_cv_asm_protected_directive=no @@ -2796,14 +2790,14 @@ echo "$ac_t""$libc_cv_asm_protected_directive" 1>&6 echo $ac_n "checking for -z nodelete option""... $ac_c" 1>&6 -echo "configure:2800: checking for -z nodelete option" >&5 +echo "configure:2794: checking for -z nodelete option" >&5 if eval "test \"`echo '$''{'libc_cv_z_nodelete'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.c <<EOF int _start (void) { return 42; } EOF - if { ac_try='${CC-cc} -shared -o conftest.so conftest.c -Wl,--enable-new-dtags,-z,nodelete 1>&5'; { (eval echo configure:2807: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } + if { ac_try='${CC-cc} -shared -o conftest.so conftest.c -Wl,--enable-new-dtags,-z,nodelete 1>&5'; { (eval echo configure:2801: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } then libc_cv_z_nodelete=yes else @@ -2816,14 +2810,14 @@ echo "$ac_t""$libc_cv_z_nodelete" 1>&6 echo $ac_n "checking for -z nodlopen option""... $ac_c" 1>&6 -echo "configure:2820: checking for -z nodlopen option" >&5 +echo "configure:2814: checking for -z nodlopen option" >&5 if eval "test \"`echo '$''{'libc_cv_z_nodlopen'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.c <<EOF int _start (void) { return 42; } EOF - if { ac_try='${CC-cc} -shared -o conftest.so conftest.c -Wl,--enable-new-dtags,-z,nodlopen 1>&5'; { (eval echo configure:2827: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } + if { ac_try='${CC-cc} -shared -o conftest.so conftest.c -Wl,--enable-new-dtags,-z,nodlopen 1>&5'; { (eval echo configure:2821: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } then libc_cv_z_nodlopen=yes else @@ -2836,14 +2830,14 @@ echo "$ac_t""$libc_cv_z_nodlopen" 1>&6 echo $ac_n "checking for -z initfirst option""... $ac_c" 1>&6 -echo "configure:2840: checking for -z initfirst option" >&5 +echo "configure:2834: checking for -z initfirst option" >&5 if eval "test \"`echo '$''{'libc_cv_z_initfirst'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.c <<EOF int _start (void) { return 42; } EOF - if { ac_try='${CC-cc} -shared -o conftest.so conftest.c -Wl,--enable-new-dtags,-z,initfirst 1>&5'; { (eval echo configure:2847: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } + if { ac_try='${CC-cc} -shared -o conftest.so conftest.c -Wl,--enable-new-dtags,-z,initfirst 1>&5'; { (eval echo configure:2841: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } then libc_cv_z_initfirst=yes else @@ -2856,14 +2850,14 @@ echo "$ac_t""$libc_cv_z_initfirst" 1>&6 echo $ac_n "checking for -Bgroup option""... $ac_c" 1>&6 -echo "configure:2860: checking for -Bgroup option" >&5 +echo "configure:2854: checking for -Bgroup option" >&5 if eval "test \"`echo '$''{'libc_cv_Bgroup'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.c <<EOF int _start (void) { return 42; } EOF - if { ac_try='${CC-cc} -shared -o conftest.so conftest.c -Wl,-Bgroup -nostdlib 1>&5'; { (eval echo configure:2867: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } + if { ac_try='${CC-cc} -shared -o conftest.so conftest.c -Wl,-Bgroup -nostdlib 1>&5'; { (eval echo configure:2861: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } then libc_cv_Bgroup=yes else @@ -2876,14 +2870,14 @@ echo "$ac_t""$libc_cv_Bgroup" 1>&6 echo $ac_n "checking for -z combreloc""... $ac_c" 1>&6 -echo "configure:2880: checking for -z combreloc" >&5 +echo "configure:2874: checking for -z combreloc" >&5 if eval "test \"`echo '$''{'libc_cv_z_combreloc'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.c <<EOF int foo (void) { return 0; } EOF - if { ac_try='${CC-cc} -shared -o conftest.so conftest.c -Wl,-z,combreloc 1>&5'; { (eval echo configure:2887: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } + if { ac_try='${CC-cc} -shared -o conftest.so conftest.c -Wl,-z,combreloc 1>&5'; { (eval echo configure:2881: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } then if readelf -S conftest.so | grep '\.rel\(a\|\)\.dyn' > /dev/null; then libc_cv_z_combreloc=yes @@ -2908,12 +2902,12 @@ fi if test $elf != yes; then echo $ac_n "checking for .init and .fini sections""... $ac_c" 1>&6 -echo "configure:2912: checking for .init and .fini sections" >&5 +echo "configure:2906: checking for .init and .fini sections" >&5 if eval "test \"`echo '$''{'libc_cv_have_initfini'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <<EOF -#line 2917 "configure" +#line 2911 "configure" #include "confdefs.h" int main() { @@ -2922,7 +2916,7 @@ asm (".section .init"); asm ("${libc_cv_dot_text}"); ; return 0; } EOF -if { (eval echo configure:2926: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:2920: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* libc_cv_have_initfini=yes else @@ -2945,7 +2939,7 @@ fi if test $elf = yes -a $gnu_ld = yes; then echo $ac_n "checking whether cc puts quotes around section names""... $ac_c" 1>&6 -echo "configure:2949: checking whether cc puts quotes around section names" >&5 +echo "configure:2943: checking whether cc puts quotes around section names" >&5 if eval "test \"`echo '$''{'libc_cv_have_section_quotes'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -2982,19 +2976,19 @@ if test $elf = yes; then else if test $ac_cv_prog_cc_works = yes; then echo $ac_n "checking for _ prefix on C symbol names""... $ac_c" 1>&6 -echo "configure:2986: checking for _ prefix on C symbol names" >&5 +echo "configure:2980: checking for _ prefix on C symbol names" >&5 if eval "test \"`echo '$''{'libc_cv_asm_underscores'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <<EOF -#line 2991 "configure" +#line 2985 "configure" #include "confdefs.h" asm ("_glibc_foobar:"); int main() { glibc_foobar (); ; return 0; } EOF -if { (eval echo configure:2998: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:2992: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* libc_cv_asm_underscores=yes else @@ -3009,17 +3003,17 @@ fi echo "$ac_t""$libc_cv_asm_underscores" 1>&6 else echo $ac_n "checking for _ prefix on C symbol names""... $ac_c" 1>&6 -echo "configure:3013: checking for _ prefix on C symbol names" >&5 +echo "configure:3007: checking for _ prefix on C symbol names" >&5 if eval "test \"`echo '$''{'libc_cv_asm_underscores'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <<EOF -#line 3018 "configure" +#line 3012 "configure" #include "confdefs.h" void underscore_test(void) { return; } EOF -if { (eval echo configure:3023: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:3017: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then if grep _underscore_test conftest* >/dev/null; then rm -f conftest* libc_cv_asm_underscores=yes @@ -3051,7 +3045,7 @@ if test $elf = yes; then fi echo $ac_n "checking for assembler .weak directive""... $ac_c" 1>&6 -echo "configure:3055: checking for assembler .weak directive" >&5 +echo "configure:3049: checking for assembler .weak directive" >&5 if eval "test \"`echo '$''{'libc_cv_asm_weak_directive'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -3074,7 +3068,7 @@ echo "$ac_t""$libc_cv_asm_weak_directive" 1>&6 if test $libc_cv_asm_weak_directive = no; then echo $ac_n "checking for assembler .weakext directive""... $ac_c" 1>&6 -echo "configure:3078: checking for assembler .weakext directive" >&5 +echo "configure:3072: checking for assembler .weakext directive" >&5 if eval "test \"`echo '$''{'libc_cv_asm_weakext_directive'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -3121,14 +3115,14 @@ EOF ;; hppa*linux*) echo $ac_n "checking for assembler line separator""... $ac_c" 1>&6 -echo "configure:3125: checking for assembler line separator" >&5 +echo "configure:3119: checking for assembler line separator" >&5 if eval "test \"`echo '$''{'libc_cv_asm_line_sep'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.s <<EOF nop ; is_old_puffin EOF - if { ac_try='${CC-cc} -c $CFLAGS conftest.s 1>&5'; { (eval echo configure:3132: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; }; then + if { ac_try='${CC-cc} -c $CFLAGS conftest.s 1>&5'; { (eval echo configure:3126: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; }; then libc_cv_asm_line_sep='!' else if test -z "$enable_hacker_mode"; then @@ -3150,7 +3144,7 @@ EOF esac echo $ac_n "checking for ld --no-whole-archive""... $ac_c" 1>&6 -echo "configure:3154: checking for ld --no-whole-archive" >&5 +echo "configure:3148: checking for ld --no-whole-archive" >&5 if eval "test \"`echo '$''{'libc_cv_ld_no_whole_archive'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -3161,7 +3155,7 @@ __throw () {} EOF if { ac_try='${CC-cc} $CFLAGS -nostdlib -nostartfiles -Wl,--no-whole-archive - -o conftest conftest.c 1>&5'; { (eval echo configure:3165: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; }; then + -o conftest conftest.c 1>&5'; { (eval echo configure:3159: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; }; then libc_cv_ld_no_whole_archive=yes else libc_cv_ld_no_whole_archive=no @@ -3175,7 +3169,7 @@ if test $libc_cv_ld_no_whole_archive = yes; then fi echo $ac_n "checking for gcc -fexceptions""... $ac_c" 1>&6 -echo "configure:3179: checking for gcc -fexceptions" >&5 +echo "configure:3173: checking for gcc -fexceptions" >&5 if eval "test \"`echo '$''{'libc_cv_gcc_exceptions'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -3186,7 +3180,7 @@ __throw () {} EOF if { ac_try='${CC-cc} $CFLAGS -nostdlib -nostartfiles -fexceptions - -o conftest conftest.c 1>&5'; { (eval echo configure:3190: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; }; then + -o conftest conftest.c 1>&5'; { (eval echo configure:3184: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; }; then libc_cv_gcc_exceptions=yes else libc_cv_gcc_exceptions=no @@ -3201,14 +3195,14 @@ fi if test "$base_machine" = alpha ; then echo $ac_n "checking for function ..ng prefix""... $ac_c" 1>&6 -echo "configure:3205: checking for function ..ng prefix" >&5 +echo "configure:3199: checking for function ..ng prefix" >&5 if eval "test \"`echo '$''{'libc_cv_gcc_alpha_ng_prefix'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.c <<\EOF foo () { } EOF -if { ac_try='${CC-cc} -S conftest.c -o - | fgrep "\$foo..ng" > /dev/null'; { (eval echo configure:3212: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; }; +if { ac_try='${CC-cc} -S conftest.c -o - | fgrep "\$foo..ng" > /dev/null'; { (eval echo configure:3206: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; }; then libc_cv_gcc_alpha_ng_prefix=yes else @@ -3235,19 +3229,19 @@ if test "$host_cpu" = powerpc ; then # Check for a bug present in at least versions 2.8.x of GCC # and versions 1.0.x of EGCS. echo $ac_n "checking whether clobbering cr0 causes problems""... $ac_c" 1>&6 -echo "configure:3239: checking whether clobbering cr0 causes problems" >&5 +echo "configure:3233: checking whether clobbering cr0 causes problems" >&5 if eval "test \"`echo '$''{'libc_cv_c_asmcr0_bug'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <<EOF -#line 3244 "configure" +#line 3238 "configure" #include "confdefs.h" int tester(int x) { asm ("" : : : "cc"); return x & 123; } int main() { ; return 0; } EOF -if { (eval echo configure:3251: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:3245: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* libc_cv_c_asmcr0_bug='no' else @@ -3269,12 +3263,12 @@ fi fi echo $ac_n "checking for DWARF2 unwind info support""... $ac_c" 1>&6 -echo "configure:3273: checking for DWARF2 unwind info support" >&5 +echo "configure:3267: checking for DWARF2 unwind info support" >&5 if eval "test \"`echo '$''{'libc_cv_gcc_dwarf2_unwind_info'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.c <<EOF -#line 3278 "configure" +#line 3272 "configure" static char __EH_FRAME_BEGIN__; _start () { @@ -3301,7 +3295,7 @@ __bzero () {} EOF if { ac_try='${CC-cc} $CFLAGS -DCHECK__register_frame_info -nostdlib -nostartfiles - -o conftest conftest.c -lgcc >&5'; { (eval echo configure:3305: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; }; then + -o conftest conftest.c -lgcc >&5'; { (eval echo configure:3299: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; }; then libc_cv_gcc_dwarf2_unwind_info=static else libc_cv_gcc_dwarf2_unwind_info=no @@ -3309,7 +3303,7 @@ fi if test $libc_cv_gcc_dwarf2_unwind_info = no; then if { ac_try='${CC-cc} $CFLAGS -DCHECK__register_frame -nostdlib -nostartfiles - -o conftest conftest.c -lgcc >&5'; { (eval echo configure:3313: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; }; then + -o conftest conftest.c -lgcc >&5'; { (eval echo configure:3307: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; }; then libc_cv_gcc_dwarf2_unwind_info=yes else libc_cv_gcc_dwarf2_unwind_info=no @@ -3339,12 +3333,12 @@ EOF esac echo $ac_n "checking for __builtin_expect""... $ac_c" 1>&6 -echo "configure:3343: checking for __builtin_expect" >&5 +echo "configure:3337: checking for __builtin_expect" >&5 if eval "test \"`echo '$''{'libc_cv_gcc_builtin_expect'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.c <<EOF -#line 3348 "configure" +#line 3342 "configure" int foo (int a) { a = __builtin_expect (a, 10); @@ -3352,7 +3346,7 @@ int foo (int a) } EOF if { ac_try='${CC-cc} $CFLAGS -nostdlib -nostartfiles - -o conftest conftest.c -lgcc >&5'; { (eval echo configure:3356: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; }; then + -o conftest conftest.c -lgcc >&5'; { (eval echo configure:3350: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; }; then libc_cv_gcc_builtin_expect=yes else libc_cv_gcc_builtin_expect=no @@ -3369,12 +3363,12 @@ EOF fi echo $ac_n "checking for local label subtraction""... $ac_c" 1>&6 -echo "configure:3373: checking for local label subtraction" >&5 +echo "configure:3367: checking for local label subtraction" >&5 if eval "test \"`echo '$''{'libc_cv_gcc_subtract_local_labels'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.c <<EOF -#line 3378 "configure" +#line 3372 "configure" int foo (int a) { static const int ar[] = { &&l1 - &&l1, &&l2 - &&l1 }; @@ -3387,7 +3381,7 @@ int foo (int a) } EOF if { ac_try='${CC-cc} $CFLAGS -nostdlib -nostartfiles - -o conftest conftest.c -lgcc >&5'; { (eval echo configure:3391: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; }; then + -o conftest conftest.c -lgcc >&5'; { (eval echo configure:3385: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; }; then libc_cv_gcc_subtract_local_labels=yes else libc_cv_gcc_subtract_local_labels=no @@ -3404,7 +3398,7 @@ EOF fi echo $ac_n "checking for libgd""... $ac_c" 1>&6 -echo "configure:3408: checking for libgd" >&5 +echo "configure:3402: checking for libgd" >&5 if test "$with_gd" != "no"; then old_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS $libgd_include" @@ -3413,14 +3407,14 @@ if test "$with_gd" != "no"; then old_LIBS="$LIBS" LIBS="$LIBS -lgd -lpng -lz -lm" cat > conftest.$ac_ext <<EOF -#line 3417 "configure" +#line 3411 "configure" #include "confdefs.h" #include <gd.h> int main() { gdImagePng (0, 0) ; return 0; } EOF -if { (eval echo configure:3424: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:3418: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* LIBGD=yes else @@ -3440,7 +3434,7 @@ echo "$ac_t""$LIBGD" 1>&6 echo $ac_n "checking size of long double""... $ac_c" 1>&6 -echo "configure:3444: checking size of long double" >&5 +echo "configure:3438: checking size of long double" >&5 if eval "test \"`echo '$''{'ac_cv_sizeof_long_double'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -3448,7 +3442,7 @@ else ac_cv_sizeof_long_double=0 else cat > conftest.$ac_ext <<EOF -#line 3452 "configure" +#line 3446 "configure" #include "confdefs.h" #include <stdio.h> int main() @@ -3459,7 +3453,7 @@ int main() return(0); } EOF -if { (eval echo configure:3463: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null +if { (eval echo configure:3457: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null then ac_cv_sizeof_long_double=`cat conftestval` else @@ -3492,6 +3486,7 @@ libc_link_sources= use_ldconfig=no ldd_rewrite_script=no libc_cv_sysconfdir=$sysconfdir +libc_cv_gcc_unwind_find_fde=no # Iterate over all the sysdep directories we will use, running their # configure fragments, and looking for a uname implementation. @@ -3516,6 +3511,14 @@ for dir in $sysnames; do fi done +if test x$libc_cv_gcc_unwind_find_fde = xyes; then + cat >> confdefs.h <<\EOF +#define EXPORT_UNWIND_FIND_FDE 1 +EOF + +fi + + # If we will use the generic uname implementation, we must figure out what @@ -3528,7 +3531,7 @@ if test "$uname" = "sysdeps/generic"; then fi echo $ac_n "checking OS release for uname""... $ac_c" 1>&6 -echo "configure:3532: checking OS release for uname" >&5 +echo "configure:3535: checking OS release for uname" >&5 if eval "test \"`echo '$''{'libc_cv_uname_release'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -3550,7 +3553,7 @@ echo "$ac_t""$libc_cv_uname_release" 1>&6 uname_release="$libc_cv_uname_release" echo $ac_n "checking OS version for uname""... $ac_c" 1>&6 -echo "configure:3554: checking OS version for uname" >&5 +echo "configure:3557: checking OS version for uname" >&5 if eval "test \"`echo '$''{'libc_cv_uname_version'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -3572,7 +3575,7 @@ else fi echo $ac_n "checking stdio selection""... $ac_c" 1>&6 -echo "configure:3576: checking stdio selection" >&5 +echo "configure:3579: checking stdio selection" >&5 case $stdio in libio) cat >> confdefs.h <<\EOF @@ -3586,7 +3589,7 @@ echo "$ac_t""$stdio" 1>&6 # Test for old glibc 2.0.x headers so that they can be removed properly # Search only in includedir. echo $ac_n "checking for old glibc 2.0.x headers""... $ac_c" 1>&6 -echo "configure:3590: checking for old glibc 2.0.x headers" >&5 +echo "configure:3593: checking for old glibc 2.0.x headers" >&5 if eval test -f "${includedir}/elfclass.h" -a -f "${includedir}/fcntlbits.h" then old_glibc_headers=yes @@ -3647,7 +3650,7 @@ if test $shared = default; then fi echo $ac_n "checking whether -fPIC is default""... $ac_c" 1>&6 -echo "configure:3651: checking whether -fPIC is default" >&5 +echo "configure:3654: checking whether -fPIC is default" >&5 if eval "test \"`echo '$''{'pic_default'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -3860,6 +3863,7 @@ s%@RANLIB@%$RANLIB%g s%@MIG@%$MIG%g s%@CCVERSION@%$CCVERSION%g s%@SYSINCLUDES@%$SYSINCLUDES%g +s%@libc_cv_gcc_static_libgcc@%$libc_cv_gcc_static_libgcc%g s%@BASH@%$BASH%g s%@libc_cv_have_bash2@%$libc_cv_have_bash2%g s%@KSH@%$KSH%g @@ -3881,6 +3885,7 @@ s%@no_whole_archive@%$no_whole_archive%g s%@exceptions@%$exceptions%g s%@LIBGD@%$LIBGD%g s%@sizeof_long_double@%$sizeof_long_double%g +s%@libc_cv_gcc_unwind_find_fde@%$libc_cv_gcc_unwind_find_fde%g s%@uname_sysname@%$uname_sysname%g s%@uname_release@%$uname_release%g s%@uname_version@%$uname_version%g diff --git a/configure.in b/configure.in index 6cbcf0e046..8f0df5c7c1 100644 --- a/configure.in +++ b/configure.in @@ -636,27 +636,6 @@ test -n "$aux_missing" && AC_MSG_WARN([ CCVERSION=`$CC -v 2>&1 | sed -n 's/gcc version //p'` AC_SUBST(CCVERSION) -case $CCVERSION in - 3.*) gcc3=yes;; -esac - -if test x"$gcc3" = xyes; then - echo "\ -*** This version of GNU libc cannot be compiled by GCC 3.x. -*** GCC 3.x will generate a library that is binary incompatible to -*** older and future releases of GNU libc. -*** You should compile this GNU libc release by an older GCC version -*** or wait for the next GNU libc release." - if test $enable_sanity = yes; then - echo "\ -*** If you really mean to use GCC 3.x, run configure again -*** using the extra parameter \`--disable-sanity-checks'." - exit 1 - else - echo "\ -*** This configuration is not supported by the GNU libc developers." - fi -fi # if using special system headers, find out the compiler's sekrit # header directory and add that to the list. NOTE: Only does the right # thing on a system that doesn't need fixincludes. (Not presently a problem.) @@ -713,6 +692,14 @@ AC_MSG_ERROR([ *** and run configure again.]) fi +AC_CACHE_CHECK(whether GCC supports -static-libgcc, libc_cv_gcc_static_libgcc, [dnl +if $CC -v -static-libgcc 2>&1 | grep -q 'unrecognized option.*static-libgcc'; then + libc_cv_gcc_static_libgcc= +else + libc_cv_gcc_static_libgcc=-static-libgcc +fi]) +AC_SUBST(libc_cv_gcc_static_libgcc) + AC_PATH_PROG(BASH, bash, no) if test "$BASH" != no && $BASH -c 'test "$BASH_VERSINFO" \ @@ -1459,6 +1446,7 @@ libc_link_sources= use_ldconfig=no ldd_rewrite_script=no libc_cv_sysconfdir=$sysconfdir +libc_cv_gcc_unwind_find_fde=no # Iterate over all the sysdep directories we will use, running their # configure fragments, and looking for a uname implementation. @@ -1484,6 +1472,11 @@ for dir in $sysnames; do ]dnl done +if test x$libc_cv_gcc_unwind_find_fde = xyes; then + AC_DEFINE(EXPORT_UNWIND_FIND_FDE) +fi +AC_SUBST(libc_cv_gcc_unwind_find_fde) + AC_LINK_FILES(`echo $libc_link_sources`, `echo $libc_link_dests`) # If we will use the generic uname implementation, we must figure out what diff --git a/elf/Makefile b/elf/Makefile index 91d7e3a508..b39034c7bf 100644 --- a/elf/Makefile +++ b/elf/Makefile @@ -66,6 +66,11 @@ distribute := $(rtld-routines:=.c) dynamic-link.h do-rel.h dl-machine.h \ include ../Makeconfig +ifeq ($(unwind-find-fde),yes) +routines += unwind-dw2-fde +shared-only-routines = unwind-dw2-fde +endif + before-compile = $(objpfx)trusted-dirs.h generated := trusted-dirs.h trusted-dirs.st for-renamed/renamed.so generated-dirs := for-renamed diff --git a/elf/Versions b/elf/Versions index 2506d100a6..a0e691c0ac 100644 --- a/elf/Versions +++ b/elf/Versions @@ -2,6 +2,9 @@ libc { GLIBC_2.0 { # functions used in other libraries _dl_open; _dl_close; _dl_addr; +%ifdef EXPORT_UNWIND_FIND_FDE + __register_frame_info; __deregister_frame_info; +%endif } GLIBC_2.1 { # functions used in other libraries @@ -17,6 +20,12 @@ libc { GLIBC_2.2.4 { dl_iterate_phdr; } +%ifdef EXPORT_UNWIND_FIND_FDE + GLIBC_2.2.5 { + __register_frame_info_bases; __deregister_frame_info_bases; + __register_frame_info_table_bases; _Unwind_Find_FDE; + } +%endif } ld { diff --git a/elf/soinit.c b/elf/soinit.c index ff65af4a36..32ed4454b5 100644 --- a/elf/soinit.c +++ b/elf/soinit.c @@ -4,6 +4,7 @@ calling those lists of functions. */ #include <libc-internal.h> +#include <stdlib.h> #ifdef HAVE_DWARF2_UNWIND_INFO_STATIC # include <gccframe.h> @@ -29,7 +30,10 @@ static char __EH_FRAME_BEGIN__[] = { }; # ifdef HAVE_DWARF2_UNWIND_INFO_STATIC extern void __register_frame_info (const void *, struct object *); +extern void __register_frame_info_bases (const void *, struct object *, + void *, void *); extern void __deregister_frame_info (const void *); +extern void __deregister_frame_info_bases (const void *); # else extern void __register_frame (const void *); extern void __deregister_frame (const void *); @@ -47,7 +51,23 @@ __libc_global_ctors (void) # ifdef HAVE_DWARF2_UNWIND_INFO_STATIC { static struct object ob; +# if defined CRT_GET_RFIB_TEXT || defined CRT_GET_RFIB_DATA + void *tbase, *dbase; + +# ifdef CRT_GET_RFIB_TEXT + CRT_GET_RFIB_TEXT (tbase); +# else + tbase = NULL; +# endif +# ifdef CRT_GET_RFIB_DATA + CRT_GET_RFIB_DATA (dbase); +# else + dbase = NULL; +# endif + __register_frame_info_bases (__EH_FRAME_BEGIN__, &ob, tbase, dbase); +# else __register_frame_info (__EH_FRAME_BEGIN__, &ob); +# endif } # else __register_frame (__EH_FRAME_BEGIN__); @@ -66,7 +86,11 @@ _fini (void) run_hooks (__DTOR_LIST__); #ifdef HAVE_DWARF2_UNWIND_INFO # ifdef HAVE_DWARF2_UNWIND_INFO_STATIC +# if defined CRT_GET_RFIB_TEXT || defined CRT_GET_RFIB_DATA + __deregister_frame_info_bases (__EH_FRAME_BEGIN__); +# else __deregister_frame_info (__EH_FRAME_BEGIN__); +# endif # else __deregister_frame (__EH_FRAME_BEGIN__); # endif diff --git a/localedata/locales/se_NO b/localedata/locales/se_NO new file mode 100644 index 0000000000..2846da9ddd --- /dev/null +++ b/localedata/locales/se_NO @@ -0,0 +1,311 @@ +# $Id$ +comment_char % +escape_char / +% +% Northern Saami Language Locale for Norway +% Source: http://www.hum.uit.no/a/trond/loc.html +% Contact: Børre Gaup +% Email: boerre.gaup@pc.nu +% Language: se +% Territory: NO +% Revision: 0.1 +% Date: 2001-11-03 +% Application: general +% Users: general +% Charset: UTF-8 +% Distribution and use is free, also +% for commercial purposes. + +LC_IDENTIFICATION +title "Northern Saami language locale for Norway" +source "http://www.hum.uit.no/a/trond/loc.html" +address "" +contact "Børre Gaup" +email "boerre.gaup@pc.nu" +tel "" +fax "" +language "Northern Saami" +territory "Norway" +revision "0.1" +date "2001-11-09" + +category se_NO:2000;LC_IDENTIFICATION +category se_NO:2000;LC_CTYPE +category se_NO:2000;LC_COLLATE +category se_NO:2000;LC_TIME +category se_NO:2000;LC_NUMERIC +category se_NO:2000;LC_PAPER +category se_NO:2000;LC_TELEPHONE +category se_NO:2000;LC_MEASUREMENT +category se_NO:2000;LC_ADDRESS +category se_NO:2000;LC_MONETARY +category se_NO:2000;LC_MESSAGES + +END LC_IDENTIFICATION + + +LC_COLLATE +copy "iso14651_t1" + +collating-symbol <aring> +collating-symbol <atilde> +collating-symbol <acircumflex> +collating-symbol <agrave> +collating-symbol <aacute> +collating-symbol <noae> +collating-symbol <svae> +collating-symbol <ccedilla> +collating-symbol <ccaron> +collating-symbol <ezh> +collating-symbol <ezhcaron> +collating-symbol <dstroke> +collating-symbol <eth> +collating-symbol <fhook> +collating-symbol <gcaron> +collating-symbol <gstroke> +collating-symbol <kcaron> +collating-symbol <otilde> +collating-symbol <oe> +collating-symbol <ssharp> +collating-symbol <scaron> +collating-symbol <oumlaut> +collating-symbol <oslash> + +% +reorder-after <CAP> +<MIN> + +reorder-after <a> +<agrave> +<atilde> +<aacute> +<acircumflex> + + +reorder-after <c> +<ccaron> +<ccedilla> +<ezh> +<ezhcaron> + +reorder-after <d> +<dstroke> +<eth> + +reorder-after <f> +<fhook> + +reorder-after <g> +<gcaron> +<gstroke> + +reorder-after <k> +<kcaron> + +reorder-after <s> +<ssharp> +<scaron> + +reorder-after <th> +<noae> +<oslash> +<aring> +<svae> +<oumlaut> + +reorder-after <U0061> +<U00E0> <agrave>;<GRA>;<MIN>;IGNORE % 201 à +<U00E1> <aacute>;<ACA>;<MIN>;IGNORE % 200 á +<U00E2> <acircumflex>;<CIR>;<MIN>;IGNORE % 202 â +<U00E3> <atilde>;<TIL>;<MIN>;IGNORE % 203 ã + +reorder-after <U0041> +<U00C0> <agrave>;<GRA>;<CAP>;IGNORE % 321 À +<U00C1> <aacute>;<ACA>;<CAP>;IGNORE % 320 Á +<U00C2> <acircumflex>;<CIR>;<CAP>;IGNORE % 322 Â +<U00C3> <atilde>;<TIL>;<CAP>;IGNORE % 323 Ã + +reorder-after <U0063> +<U00E7> <ccedilla>;<CDI>;<MIN>;IGNORE % 212 ç +<U010D> <ccaron>;<CAR>;<MIN>;IGNORE % 215 <c<> + +reorder-after <U0043> +<U00C7> <ccedilla>;<CDI>;<CAP>;IGNORE % 332 Ç +<U010C> <ccaron>;<CAR>;<CAP>;IGNORE % 335 <C<> + +reorder-after <U010B> +<U0292> <ezh>;<BAS>;<MIN>;IGNORE % ezh +<U01EF> <ezhcaron>;<CAR>;<MIN>;IGNORE % ezh caron + +reorder-after <U010A> +<U01B7> <ezh>;<BAS>;<MIN>;IGNORE % EZH +<U01EE> <ezhcaron>;<CAR>;<CAP>;IGNORE % EZH caron + +reorder-after <U0064> +<U00F0> <eth>;<PCL>;<MIN>;IGNORE % 218 ð +<U0111> <dstroke>;<OBL>;<MIN>;IGNORE % 220 <d//> + +reorder-after <U0044> +<U00D0> <eth>;<PCL>;<CAP>;IGNORE % 338 Ð +<U0110> <dstroke>;<OBL>;<CAP>;IGNORE % 340 <D//> + +reorder-after <U0066> +<U0192> <fhook>;<BAS>;<MIN>;IGNORE % f WITH HOOK + +reorder-after <U0123> +<U01E7> <gcaron>;<CAR>;<MIN>;IGNORE % gcaron +<U01E5> <gstroke>;<OBL>;<MIN>;IGNORE % gstroke + +reorder-after <U0122> +<U01E6> <gcaron>;<CAR>;<MIN>;IGNORE % Gcaron +<U01E4> <gstroke>;<OBL>;<MIN>;IGNORE % Gstroke + +reorder-after <U0137> +<U01E9> <kcaron>;<CAR>;<MIN>;IGNORE % kcaron +reorder-after <U0136> +<U01E8> <kcaron>;<CAR>;<CAP>;IGNORE % Kcaron + +reorder-after <U0053> +<U00DF> <ssharp>;"<LIG><LIG>";"<MIN><MIN>";IGNORE % ß +<U0161> <scaron>;<CAR>;<MIN>;IGNORE % 288 <s<> +<U0160> <scaron>;<CAR>;<CAP>;IGNORE % 405 <S<> + + +reorder-after <U00E3> +<U00E4> <svae>;<REU>;<MIN>;IGNORE % ä +<U00E5> <aring>;<RNE>;<MIN>;IGNORE % å +<U00E6> <noae>;<LIG>;<MIN>;IGNORE % æ +reorder-after <U00F5> +<U00F6> <oumlaut>;<REU>;<MIN>;IGNORE % ö +<U00F8> <oslash>;<OBL>;<MIN>;IGNORE % ø + +reorder-after <U00C3> +<U00C4> <svae>;<REU>;<CAP>;IGNORE % Ä +<U00C5> <aring>;<RNE>;<CAP>;IGNORE % Å +<U00C6> <noae>;<LIG>;<CAP>;IGNORE % Æ +reorder-after <U00D5> +<U00D6> <oumlaut>;<REU>;<CAP>;IGNORE % Ö +<U00D8> <oslash>;<OBL>;<CAP>;IGNORE % Ø + +% ü/Ü is treated like y/Y but is sorted after the latter +reorder-after <U00FB> +<U00FC> <y>;<REU>;<MIN>;IGNORE % ü +reorder-after <U00DB> +<U00DC> <y>;<REU>;<CAP>;IGNORE % Ü +reorder-end + +END LC_COLLATE + +LC_CTYPE +copy "i18n" +END LC_CTYPE + +LC_MONETARY +int_curr_symbol "<U004E><U004F><U004B><U0020>" +currency_symbol "<U0020><U0072><U0075>" +mon_decimal_point "<U002C>" +mon_thousands_sep "<U002E>" +mon_grouping 3;3 +positive_sign "" +negative_sign "<U002D>" +int_frac_digits 2 +frac_digits 2 +p_cs_precedes 1 +p_sep_by_space 0 +n_cs_precedes 1 +n_sep_by_space 0 +p_sign_posn 4 +n_sign_posn 4 +END LC_MONETARY + +LC_NUMERIC +decimal_point "<U002C>" +thousands_sep "<U002E>" +grouping 3;3 +END LC_NUMERIC + + +LC_TIME +abday "<U0073><U006F><U0074><U006E>";"<U0076><U0075><U006F><U0073>";/ + "<U006D><U0061><U014B>";"<U0067><U0061><U0073><U006B>";/ + "<U0064><U0075><U006F><U0072>";"<U0062><U0065><U0061><U0072>";/ + "<U006C><U00E1><U0076>" +day "<U0073><U006F><U0074><U006E><U0061><U0062><U0065><U0061><U0069><U0076><U0069>";/ + "<U0076><U0075><U006F><U0073><U0073><U00E1><U0072><U0067><U0061>";/ + "<U006D><U0061><U014B><U014B><U0065><U0062><U0061><U0072><U0067><U0061>";/ + "<U0067><U0061><U0073><U006B><U0061><U0076><U0061><U0068><U006B><U006B><U0075>";/ + "<U0064><U0075><U006F><U0072><U0061><U0073><U0064><U0061><U0074>";/ + "<U0062><U0065><U0061><U0072><U006A><U0061><U0064><U0061><U0074>";/ + "<U006C><U00E1><U0076><U0076><U0061><U0072><U0064><U0061><U0074>" +abmon "<U006F><U0111><U0111><U006A>";"<U0067><U0075><U006F><U0076>";/ + "<U006E><U006A><U0075><U006B>";"<U0063><U0075><U006F><U014B>";/ + "<U006D><U0069><U0065><U0073>";"<U0067><U0065><U0061><U0073>";/ + "<U0073><U0075><U006F><U0069>";"<U0062><U006F><U0072><U0067>";/ + "<U010D><U0061><U006B><U010D>";"<U0067><U006F><U006C><U0067>";/ + "<U0073><U006B><U00E1><U0062>";"<U006A><U0075><U006F><U0076>" +mon "<U006F><U0111><U0111><U0061><U006A><U0061><U0067><U0065><U006D><U00E1><U006E><U0075>";/ + "<U0067><U0075><U006F><U0076><U0076><U0061><U006D><U00E1><U006E><U0075>";/ + "<U006E><U006A><U0075><U006B><U010D><U0061><U006D><U00E1><U006E><U0075>";/ + "<U0063><U0075><U006F><U014B><U006F><U006D><U00E1><U006E><U0075>";/ + "<U006D><U0069><U0065><U0073><U0073><U0065><U006D><U00E1><U006E><U0075>";/ + "<U0067><U0065><U0061><U0073><U0073><U0065><U006D><U00E1><U006E><U0075>";/ + "<U0073><U0075><U006F><U0069><U0064><U006E><U0065><U006D><U00E1><U006E><U0075>";/ + "<U0062><U006F><U0072><U0067><U0065><U006D><U00E1><U006E><U0075>";/ + "<U010D><U0061><U006B><U010D><U0061><U006D><U00E1><U006E><U0075>";/ + "<U0067><U006F><U006C><U0067><U0067><U006F><U0074><U006D><U00E1><U006E><U0075>";/ + "<U0073><U006B><U00E1><U0062><U006D><U0061><U006D><U00E1><U006E><U0075>";/ + "<U006A><U0075><U006F><U0076><U006C><U0061><U006D><U00E1><U006E><U0075>" +% usual date representation +% Linjen nedenfor er: %a, %b %e b. %Y %T %Z +% f.eks. bear, geas 14. b. 2001 21:15:11 CEST +d_t_fmt "<U0025><U0061><U002C><U0020><U0025><U0062><U0020><U0025><U0065><U002E><U0020><U0062><U002E><U0020><U0025><U0059><U0020><U0025><U0054><U0020><U0025><U005A>" +%Linjen nedenfor er: %Y-%m-%d +%f.eks 2001-04-26 +d_fmt "<U0025><U0059><U002D><U0025><U006D><U002D><U0025><U0064>" +t_fmt "<U0025><U0054>" +am_pm "";"" +t_fmt_ampm "" + +% Denne linjen vil gi f.eks.: +% duorasdat, borgem<U00E1>nu 23. b. 2001 00:47:57 CEST +date_fmt "<U0025><U0041><U002C><U0020><U0025><U0042><U0020><U0025><U0064><U002E>/ +<U0020><U0062><U002E><U0020><U0025><U0059><U0020><U0025><U0048><U003A><U0025><U004D><U003A><U0025><U0053>/ +<U0020><U0025><U005A>" + +% %a %b-%e %H:%M:%S %Z %Y søn jan-31 21:15:11 CET 2001 +END LC_TIME + +LC_MESSAGES +yesexpr "<U005E><U005B><U004A><U006A><U0059><U0079><U005D><U002E><U002A>" +noexpr "<U005E><U005B><U0049><U0069><U005D><U002E><U002A>" +END LC_MESSAGES + + +LC_PAPER +height 297 +width 210 +END LC_PAPER + +LC_TELEPHONE +tel_int_fmt "<U002B><U0025><U0063><U0020><U0025><U006C>" +tel_dom_fmt "<U0025><U006C>" +int_select "<U0030><U0030>" +int_prefix "<U0034><U0037>" +END LC_TELEPHONE + +LC_MEASUREMENT +measurement 1 +END LC_MEASUREMENT + +LC_NAME +name_fmt "<U0025><U0064><U0025><U0074><U0025><U0067><U0025><U0074>/ +<U0025><U006D><U0025><U0074><U0025><U0066>" +END LC_NAME + +LC_ADDRESS +postal_fmt "<U0025><U0066><U0025><U004E><U0025><U0061><U0025><U004E>/ +<U0025><U0064><U0025><U004E><U0025><U0062><U0025><U004E><U0025><U0073>/ +<U0020><U0025><U0068><U0020><U0025><U0065><U0020><U0025><U0072><U0025>/ +<U004E><U0025><U0025><U007A><U0020><U0025><U0054><U0025>/ +<U004E><U0025><U0063><U0025><U004E>" +END LC_ADDRESS diff --git a/sysdeps/alpha/gccframe.h b/sysdeps/alpha/gccframe.h new file mode 100644 index 0000000000..b67022548f --- /dev/null +++ b/sysdeps/alpha/gccframe.h @@ -0,0 +1,22 @@ +/* Definition of object in frame unwind info. alpha version. + Copyright (C) 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#define FIRST_PSEUDO_REGISTER 64 + +#include <sysdeps/generic/gccframe.h> diff --git a/sysdeps/arm/gccframe.h b/sysdeps/arm/gccframe.h new file mode 100644 index 0000000000..ef8df2630e --- /dev/null +++ b/sysdeps/arm/gccframe.h @@ -0,0 +1,22 @@ +/* Definition of object in frame unwind info. arm version. + Copyright (C) 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#define FIRST_PSEUDO_REGISTER 27 + +#include <sysdeps/generic/gccframe.h> diff --git a/sysdeps/generic/dwarf2.h b/sysdeps/generic/dwarf2.h new file mode 100644 index 0000000000..800bda2dc0 --- /dev/null +++ b/sysdeps/generic/dwarf2.h @@ -0,0 +1,585 @@ +/* Declarations and definitions of codes relating to the DWARF2 symbolic + debugging information format. + Copyright (C) 1992, 1993, 1995, 1996, 1997, 2000 + Free Software Foundation, Inc. + Contributed by Gary Funck (gary@intrepid.com). Derived from the + DWARF 1 implementation written by Ron Guilmette (rfg@monkeys.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. */ + +/* This file is derived from the DWARF specification (a public document) + Revision 2.0.0 (July 27, 1993) developed by the UNIX International + Programming Languages Special Interest Group (UI/PLSIG) and distributed + by UNIX International. Copies of this specification are available from + UNIX International, 20 Waterview Boulevard, Parsippany, NJ, 07054. */ + +/* This file is shared between GCC and GDB, and should not contain + prototypes. */ + +/* Tag names and codes. */ + +enum dwarf_tag + { + DW_TAG_padding = 0x00, + DW_TAG_array_type = 0x01, + DW_TAG_class_type = 0x02, + DW_TAG_entry_point = 0x03, + DW_TAG_enumeration_type = 0x04, + DW_TAG_formal_parameter = 0x05, + DW_TAG_imported_declaration = 0x08, + DW_TAG_label = 0x0a, + DW_TAG_lexical_block = 0x0b, + DW_TAG_member = 0x0d, + DW_TAG_pointer_type = 0x0f, + DW_TAG_reference_type = 0x10, + DW_TAG_compile_unit = 0x11, + DW_TAG_string_type = 0x12, + DW_TAG_structure_type = 0x13, + DW_TAG_subroutine_type = 0x15, + DW_TAG_typedef = 0x16, + DW_TAG_union_type = 0x17, + DW_TAG_unspecified_parameters = 0x18, + DW_TAG_variant = 0x19, + DW_TAG_common_block = 0x1a, + DW_TAG_common_inclusion = 0x1b, + DW_TAG_inheritance = 0x1c, + DW_TAG_inlined_subroutine = 0x1d, + DW_TAG_module = 0x1e, + DW_TAG_ptr_to_member_type = 0x1f, + DW_TAG_set_type = 0x20, + DW_TAG_subrange_type = 0x21, + DW_TAG_with_stmt = 0x22, + DW_TAG_access_declaration = 0x23, + DW_TAG_base_type = 0x24, + DW_TAG_catch_block = 0x25, + DW_TAG_const_type = 0x26, + DW_TAG_constant = 0x27, + DW_TAG_enumerator = 0x28, + DW_TAG_file_type = 0x29, + DW_TAG_friend = 0x2a, + DW_TAG_namelist = 0x2b, + DW_TAG_namelist_item = 0x2c, + DW_TAG_packed_type = 0x2d, + DW_TAG_subprogram = 0x2e, + DW_TAG_template_type_param = 0x2f, + DW_TAG_template_value_param = 0x30, + DW_TAG_thrown_type = 0x31, + DW_TAG_try_block = 0x32, + DW_TAG_variant_part = 0x33, + DW_TAG_variable = 0x34, + DW_TAG_volatile_type = 0x35, + /* SGI/MIPS Extensions */ + DW_TAG_MIPS_loop = 0x4081, + /* GNU extensions */ + DW_TAG_format_label = 0x4101, /* for FORTRAN 77 and Fortran 90 */ + DW_TAG_function_template = 0x4102, /* for C++ */ + DW_TAG_class_template = 0x4103, /* for C++ */ + DW_TAG_GNU_BINCL = 0x4104, + DW_TAG_GNU_EINCL = 0x4105 + }; + +#define DW_TAG_lo_user 0x4080 +#define DW_TAG_hi_user 0xffff + +/* flag that tells whether entry has a child or not */ +#define DW_children_no 0 +#define DW_children_yes 1 + +/* Form names and codes. */ +enum dwarf_form + { + DW_FORM_addr = 0x01, + DW_FORM_block2 = 0x03, + DW_FORM_block4 = 0x04, + DW_FORM_data2 = 0x05, + DW_FORM_data4 = 0x06, + DW_FORM_data8 = 0x07, + DW_FORM_string = 0x08, + DW_FORM_block = 0x09, + DW_FORM_block1 = 0x0a, + DW_FORM_data1 = 0x0b, + DW_FORM_flag = 0x0c, + DW_FORM_sdata = 0x0d, + DW_FORM_strp = 0x0e, + DW_FORM_udata = 0x0f, + DW_FORM_ref_addr = 0x10, + DW_FORM_ref1 = 0x11, + DW_FORM_ref2 = 0x12, + DW_FORM_ref4 = 0x13, + DW_FORM_ref8 = 0x14, + DW_FORM_ref_udata = 0x15, + DW_FORM_indirect = 0x16 + }; + +/* Attribute names and codes. */ + +enum dwarf_attribute + { + DW_AT_sibling = 0x01, + DW_AT_location = 0x02, + DW_AT_name = 0x03, + DW_AT_ordering = 0x09, + DW_AT_subscr_data = 0x0a, + DW_AT_byte_size = 0x0b, + DW_AT_bit_offset = 0x0c, + DW_AT_bit_size = 0x0d, + DW_AT_element_list = 0x0f, + DW_AT_stmt_list = 0x10, + DW_AT_low_pc = 0x11, + DW_AT_high_pc = 0x12, + DW_AT_language = 0x13, + DW_AT_member = 0x14, + DW_AT_discr = 0x15, + DW_AT_discr_value = 0x16, + DW_AT_visibility = 0x17, + DW_AT_import = 0x18, + DW_AT_string_length = 0x19, + DW_AT_common_reference = 0x1a, + DW_AT_comp_dir = 0x1b, + DW_AT_const_value = 0x1c, + DW_AT_containing_type = 0x1d, + DW_AT_default_value = 0x1e, + DW_AT_inline = 0x20, + DW_AT_is_optional = 0x21, + DW_AT_lower_bound = 0x22, + DW_AT_producer = 0x25, + DW_AT_prototyped = 0x27, + DW_AT_return_addr = 0x2a, + DW_AT_start_scope = 0x2c, + DW_AT_stride_size = 0x2e, + DW_AT_upper_bound = 0x2f, + DW_AT_abstract_origin = 0x31, + DW_AT_accessibility = 0x32, + DW_AT_address_class = 0x33, + DW_AT_artificial = 0x34, + DW_AT_base_types = 0x35, + DW_AT_calling_convention = 0x36, + DW_AT_count = 0x37, + DW_AT_data_member_location = 0x38, + DW_AT_decl_column = 0x39, + DW_AT_decl_file = 0x3a, + DW_AT_decl_line = 0x3b, + DW_AT_declaration = 0x3c, + DW_AT_discr_list = 0x3d, + DW_AT_encoding = 0x3e, + DW_AT_external = 0x3f, + DW_AT_frame_base = 0x40, + DW_AT_friend = 0x41, + DW_AT_identifier_case = 0x42, + DW_AT_macro_info = 0x43, + DW_AT_namelist_items = 0x44, + DW_AT_priority = 0x45, + DW_AT_segment = 0x46, + DW_AT_specification = 0x47, + DW_AT_static_link = 0x48, + DW_AT_type = 0x49, + DW_AT_use_location = 0x4a, + DW_AT_variable_parameter = 0x4b, + DW_AT_virtuality = 0x4c, + DW_AT_vtable_elem_location = 0x4d, + /* SGI/MIPS Extensions */ + DW_AT_MIPS_fde = 0x2001, + DW_AT_MIPS_loop_begin = 0x2002, + DW_AT_MIPS_tail_loop_begin = 0x2003, + DW_AT_MIPS_epilog_begin = 0x2004, + DW_AT_MIPS_loop_unroll_factor = 0x2005, + DW_AT_MIPS_software_pipeline_depth = 0x2006, + DW_AT_MIPS_linkage_name = 0x2007, + DW_AT_MIPS_stride = 0x2008, + DW_AT_MIPS_abstract_name = 0x2009, + DW_AT_MIPS_clone_origin = 0x200a, + DW_AT_MIPS_has_inlines = 0x200b, + /* GNU extensions. */ + DW_AT_sf_names = 0x2101, + DW_AT_src_info = 0x2102, + DW_AT_mac_info = 0x2103, + DW_AT_src_coords = 0x2104, + DW_AT_body_begin = 0x2105, + DW_AT_body_end = 0x2106 + }; + +#define DW_AT_lo_user 0x2000 /* implementation-defined range start */ +#define DW_AT_hi_user 0x3ff0 /* implementation-defined range end */ + +/* Location atom names and codes. */ + +enum dwarf_location_atom + { + DW_OP_addr = 0x03, + DW_OP_deref = 0x06, + DW_OP_const1u = 0x08, + DW_OP_const1s = 0x09, + DW_OP_const2u = 0x0a, + DW_OP_const2s = 0x0b, + DW_OP_const4u = 0x0c, + DW_OP_const4s = 0x0d, + DW_OP_const8u = 0x0e, + DW_OP_const8s = 0x0f, + DW_OP_constu = 0x10, + DW_OP_consts = 0x11, + DW_OP_dup = 0x12, + DW_OP_drop = 0x13, + DW_OP_over = 0x14, + DW_OP_pick = 0x15, + DW_OP_swap = 0x16, + DW_OP_rot = 0x17, + DW_OP_xderef = 0x18, + DW_OP_abs = 0x19, + DW_OP_and = 0x1a, + DW_OP_div = 0x1b, + DW_OP_minus = 0x1c, + DW_OP_mod = 0x1d, + DW_OP_mul = 0x1e, + DW_OP_neg = 0x1f, + DW_OP_not = 0x20, + DW_OP_or = 0x21, + DW_OP_plus = 0x22, + DW_OP_plus_uconst = 0x23, + DW_OP_shl = 0x24, + DW_OP_shr = 0x25, + DW_OP_shra = 0x26, + DW_OP_xor = 0x27, + DW_OP_bra = 0x28, + DW_OP_eq = 0x29, + DW_OP_ge = 0x2a, + DW_OP_gt = 0x2b, + DW_OP_le = 0x2c, + DW_OP_lt = 0x2d, + DW_OP_ne = 0x2e, + DW_OP_skip = 0x2f, + DW_OP_lit0 = 0x30, + DW_OP_lit1 = 0x31, + DW_OP_lit2 = 0x32, + DW_OP_lit3 = 0x33, + DW_OP_lit4 = 0x34, + DW_OP_lit5 = 0x35, + DW_OP_lit6 = 0x36, + DW_OP_lit7 = 0x37, + DW_OP_lit8 = 0x38, + DW_OP_lit9 = 0x39, + DW_OP_lit10 = 0x3a, + DW_OP_lit11 = 0x3b, + DW_OP_lit12 = 0x3c, + DW_OP_lit13 = 0x3d, + DW_OP_lit14 = 0x3e, + DW_OP_lit15 = 0x3f, + DW_OP_lit16 = 0x40, + DW_OP_lit17 = 0x41, + DW_OP_lit18 = 0x42, + DW_OP_lit19 = 0x43, + DW_OP_lit20 = 0x44, + DW_OP_lit21 = 0x45, + DW_OP_lit22 = 0x46, + DW_OP_lit23 = 0x47, + DW_OP_lit24 = 0x48, + DW_OP_lit25 = 0x49, + DW_OP_lit26 = 0x4a, + DW_OP_lit27 = 0x4b, + DW_OP_lit28 = 0x4c, + DW_OP_lit29 = 0x4d, + DW_OP_lit30 = 0x4e, + DW_OP_lit31 = 0x4f, + DW_OP_reg0 = 0x50, + DW_OP_reg1 = 0x51, + DW_OP_reg2 = 0x52, + DW_OP_reg3 = 0x53, + DW_OP_reg4 = 0x54, + DW_OP_reg5 = 0x55, + DW_OP_reg6 = 0x56, + DW_OP_reg7 = 0x57, + DW_OP_reg8 = 0x58, + DW_OP_reg9 = 0x59, + DW_OP_reg10 = 0x5a, + DW_OP_reg11 = 0x5b, + DW_OP_reg12 = 0x5c, + DW_OP_reg13 = 0x5d, + DW_OP_reg14 = 0x5e, + DW_OP_reg15 = 0x5f, + DW_OP_reg16 = 0x60, + DW_OP_reg17 = 0x61, + DW_OP_reg18 = 0x62, + DW_OP_reg19 = 0x63, + DW_OP_reg20 = 0x64, + DW_OP_reg21 = 0x65, + DW_OP_reg22 = 0x66, + DW_OP_reg23 = 0x67, + DW_OP_reg24 = 0x68, + DW_OP_reg25 = 0x69, + DW_OP_reg26 = 0x6a, + DW_OP_reg27 = 0x6b, + DW_OP_reg28 = 0x6c, + DW_OP_reg29 = 0x6d, + DW_OP_reg30 = 0x6e, + DW_OP_reg31 = 0x6f, + DW_OP_breg0 = 0x70, + DW_OP_breg1 = 0x71, + DW_OP_breg2 = 0x72, + DW_OP_breg3 = 0x73, + DW_OP_breg4 = 0x74, + DW_OP_breg5 = 0x75, + DW_OP_breg6 = 0x76, + DW_OP_breg7 = 0x77, + DW_OP_breg8 = 0x78, + DW_OP_breg9 = 0x79, + DW_OP_breg10 = 0x7a, + DW_OP_breg11 = 0x7b, + DW_OP_breg12 = 0x7c, + DW_OP_breg13 = 0x7d, + DW_OP_breg14 = 0x7e, + DW_OP_breg15 = 0x7f, + DW_OP_breg16 = 0x80, + DW_OP_breg17 = 0x81, + DW_OP_breg18 = 0x82, + DW_OP_breg19 = 0x83, + DW_OP_breg20 = 0x84, + DW_OP_breg21 = 0x85, + DW_OP_breg22 = 0x86, + DW_OP_breg23 = 0x87, + DW_OP_breg24 = 0x88, + DW_OP_breg25 = 0x89, + DW_OP_breg26 = 0x8a, + DW_OP_breg27 = 0x8b, + DW_OP_breg28 = 0x8c, + DW_OP_breg29 = 0x8d, + DW_OP_breg30 = 0x8e, + DW_OP_breg31 = 0x8f, + DW_OP_regx = 0x90, + DW_OP_fbreg = 0x91, + DW_OP_bregx = 0x92, + DW_OP_piece = 0x93, + DW_OP_deref_size = 0x94, + DW_OP_xderef_size = 0x95, + DW_OP_nop = 0x96 + }; + +#define DW_OP_lo_user 0x80 /* implementation-defined range start */ +#define DW_OP_hi_user 0xff /* implementation-defined range end */ + +/* Type encodings. */ + +enum dwarf_type + { + DW_ATE_void = 0x0, + DW_ATE_address = 0x1, + DW_ATE_boolean = 0x2, + DW_ATE_complex_float = 0x3, + DW_ATE_float = 0x4, + DW_ATE_signed = 0x5, + DW_ATE_signed_char = 0x6, + DW_ATE_unsigned = 0x7, + DW_ATE_unsigned_char = 0x8 + }; + +#define DW_ATE_lo_user 0x80 +#define DW_ATE_hi_user 0xff + +/* Array ordering names and codes. */ +enum dwarf_array_dim_ordering + { + DW_ORD_row_major = 0, + DW_ORD_col_major = 1 + }; + +/* access attribute */ +enum dwarf_access_attribute + { + DW_ACCESS_public = 1, + DW_ACCESS_protected = 2, + DW_ACCESS_private = 3 + }; + +/* visibility */ +enum dwarf_visibility_attribute + { + DW_VIS_local = 1, + DW_VIS_exported = 2, + DW_VIS_qualified = 3 + }; + +/* virtuality */ +enum dwarf_virtuality_attribute + { + DW_VIRTUALITY_none = 0, + DW_VIRTUALITY_virtual = 1, + DW_VIRTUALITY_pure_virtual = 2 + }; + +/* case sensitivity */ +enum dwarf_id_case + { + DW_ID_case_sensitive = 0, + DW_ID_up_case = 1, + DW_ID_down_case = 2, + DW_ID_case_insensitive = 3 + }; + +/* calling convention */ +enum dwarf_calling_convention + { + DW_CC_normal = 0x1, + DW_CC_program = 0x2, + DW_CC_nocall = 0x3 + }; + +#define DW_CC_lo_user 0x40 +#define DW_CC_hi_user 0xff + +/* inline attribute */ +enum dwarf_inline_attribute + { + DW_INL_not_inlined = 0, + DW_INL_inlined = 1, + DW_INL_declared_not_inlined = 2, + DW_INL_declared_inlined = 3 + }; + +/* discriminant lists */ +enum dwarf_discrim_list + { + DW_DSC_label = 0, + DW_DSC_range = 1 + }; + +/* line number opcodes */ +enum dwarf_line_number_ops + { + DW_LNS_extended_op = 0, + DW_LNS_copy = 1, + DW_LNS_advance_pc = 2, + DW_LNS_advance_line = 3, + DW_LNS_set_file = 4, + DW_LNS_set_column = 5, + DW_LNS_negate_stmt = 6, + DW_LNS_set_basic_block = 7, + DW_LNS_const_add_pc = 8, + DW_LNS_fixed_advance_pc = 9 + }; + +/* line number extended opcodes */ +enum dwarf_line_number_x_ops + { + DW_LNE_end_sequence = 1, + DW_LNE_set_address = 2, + DW_LNE_define_file = 3 + }; + +/* call frame information */ +enum dwarf_call_frame_info + { + DW_CFA_advance_loc = 0x40, + DW_CFA_offset = 0x80, + DW_CFA_restore = 0xc0, + DW_CFA_nop = 0x00, + DW_CFA_set_loc = 0x01, + DW_CFA_advance_loc1 = 0x02, + DW_CFA_advance_loc2 = 0x03, + DW_CFA_advance_loc4 = 0x04, + DW_CFA_offset_extended = 0x05, + DW_CFA_restore_extended = 0x06, + DW_CFA_undefined = 0x07, + DW_CFA_same_value = 0x08, + DW_CFA_register = 0x09, + DW_CFA_remember_state = 0x0a, + DW_CFA_restore_state = 0x0b, + DW_CFA_def_cfa = 0x0c, + DW_CFA_def_cfa_register = 0x0d, + DW_CFA_def_cfa_offset = 0x0e, + DW_CFA_def_cfa_expression = 0x0f, + DW_CFA_expression = 0x10, + /* Dwarf 2.1 */ + DW_CFA_offset_extended_sf = 0x11, + DW_CFA_def_cfa_sf = 0x12, + DW_CFA_def_cfa_offset_sf = 0x13, + + /* SGI/MIPS specific */ + DW_CFA_MIPS_advance_loc8 = 0x1d, + + /* GNU extensions */ + DW_CFA_GNU_window_save = 0x2d, + DW_CFA_GNU_args_size = 0x2e, + DW_CFA_GNU_negative_offset_extended = 0x2f + }; + +#define DW_CIE_ID 0xffffffff +#define DW_CIE_VERSION 1 + +#define DW_CFA_extended 0 +#define DW_CFA_low_user 0x1c +#define DW_CFA_high_user 0x3f + +#define DW_CHILDREN_no 0x00 +#define DW_CHILDREN_yes 0x01 + +#define DW_ADDR_none 0 + +/* Source language names and codes. */ + +enum dwarf_source_language + { + DW_LANG_C89 = 0x0001, + DW_LANG_C = 0x0002, + DW_LANG_Ada83 = 0x0003, + DW_LANG_C_plus_plus = 0x0004, + DW_LANG_Cobol74 = 0x0005, + DW_LANG_Cobol85 = 0x0006, + DW_LANG_Fortran77 = 0x0007, + DW_LANG_Fortran90 = 0x0008, + DW_LANG_Pascal83 = 0x0009, + DW_LANG_Modula2 = 0x000a, + DW_LANG_Java = 0x000b, + DW_LANG_Mips_Assembler = 0x8001 + }; + + +#define DW_LANG_lo_user 0x8000 /* implementation-defined range start */ +#define DW_LANG_hi_user 0xffff /* implementation-defined range start */ + +/* Names and codes for macro information. */ + +enum dwarf_macinfo_record_type + { + DW_MACINFO_define = 1, + DW_MACINFO_undef = 2, + DW_MACINFO_start_file = 3, + DW_MACINFO_end_file = 4, + DW_MACINFO_vendor_ext = 255 + }; + + +/* @@@ For use with GNU frame unwind information. */ + +#define DW_EH_PE_absptr 0x00 +#define DW_EH_PE_omit 0xff + +#define DW_EH_PE_uleb128 0x01 +#define DW_EH_PE_udata2 0x02 +#define DW_EH_PE_udata4 0x03 +#define DW_EH_PE_udata8 0x04 +#define DW_EH_PE_sleb128 0x09 +#define DW_EH_PE_sdata2 0x0A +#define DW_EH_PE_sdata4 0x0B +#define DW_EH_PE_sdata8 0x0C +#define DW_EH_PE_signed 0x08 + +#define DW_EH_PE_pcrel 0x10 +#define DW_EH_PE_textrel 0x20 +#define DW_EH_PE_datarel 0x30 +#define DW_EH_PE_funcrel 0x40 +#define DW_EH_PE_aligned 0x50 + +#define DW_EH_PE_indirect 0x80 diff --git a/sysdeps/generic/framestate.c b/sysdeps/generic/framestate.c new file mode 100644 index 0000000000..5cb3e6ca85 --- /dev/null +++ b/sysdeps/generic/framestate.c @@ -0,0 +1,47 @@ +/* __frame_state_for unwinder helper function wrapper. + Copyright (C) 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Jakub Jelinek <jakub@redhat.com>, 2001. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <dlfcn.h> +#include <stdlib.h> +#define __frame_state_for fallback_frame_state_for +#include <unwind-dw2.c> +#undef __frame_state_for + +typedef struct frame_state * (*framesf)(void *pc, struct frame_state *); +struct frame_state *__frame_state_for (void *pc, + struct frame_state *frame_state); + +struct frame_state * +__frame_state_for (void *pc, struct frame_state *frame_state) +{ + static framesf frame_state_for; + + if (frame_state_for == NULL) + { + void *handle = __libc_dlopen ("libgcc_s.so.1"); + + if (handle == NULL + || (frame_state_for + = (framesf) __libc_dlsym (handle, "__frame_state_for")) == NULL) + frame_state_for = fallback_frame_state_for; + } + + return frame_state_for (pc, frame_state); +} diff --git a/sysdeps/generic/gccframe.h b/sysdeps/generic/gccframe.h index c694877605..1df7d713c0 100644 --- a/sysdeps/generic/gccframe.h +++ b/sysdeps/generic/gccframe.h @@ -1,5 +1,5 @@ /* Definition of object in frame unwind info. Generic version. - Copyright (C) 2000 Free Software Foundation, Inc. + Copyright (C) 2000, 2001 Free Software Foundation, Inc. This file is part of the GNU C Library. The GNU C Library is free software; you can redistribute it and/or @@ -17,14 +17,34 @@ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -/* This must match what's in frame.h in gcc. */ +#include <sys/types.h> + +struct dwarf_fde; +struct fde_vector; struct object { void *pc_begin; - void *pc_end; - void *fde_begin; - void *fde_array; - __SIZE_TYPE__ count; + void *tbase; + void *dbase; + union { + struct dwarf_fde *single; + struct dwarf_fde **array; + struct fde_vector *sort; + } u; + + union { + struct { + unsigned long sorted : 1; + unsigned long from_array : 1; + unsigned long mixed_encoding : 1; + unsigned long encoding : 8; + /* ??? Wish there was an easy way to detect a 64-bit host here; + we've got 32 bits left to play with... */ + unsigned long count : 21; + } b; + size_t i; + } s; + struct object *next; }; diff --git a/sysdeps/generic/unwind-dw2-fde.c b/sysdeps/generic/unwind-dw2-fde.c new file mode 100644 index 0000000000..b6bbc2bc73 --- /dev/null +++ b/sysdeps/generic/unwind-dw2-fde.c @@ -0,0 +1,1021 @@ +/* Subroutines needed for unwinding stack frames for exception handling. */ +/* Copyright (C) 1997, 1998, 1999, 2000, 2001 Free Software Foundation, Inc. + Contributed by Jason Merrill <jason@cygnus.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. + +In addition to the permissions in the GNU General Public License, the +Free Software Foundation gives you unlimited permission to link the +compiled version of this file into combinations with other programs, +and to distribute those combinations without any restriction coming +from the use of this file. (The General Public License restrictions +do apply in other respects; for example, they cover modification of +the file, and distribution when not linked into a combine +executable.) + +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. */ + +#ifdef _LIBC +# include <shlib-compat.h> +#endif + +#if !defined _LIBC || SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_2_5) + +#ifdef _LIBC +#include <stdlib.h> +#include <string.h> +#include <bits/libc-lock.h> +#include <dwarf2.h> +#include <unwind.h> +#define NO_BASE_OF_ENCODED_VALUE +#include <unwind-pe.h> +#include <unwind-dw2-fde.h> +#else +#include "tconfig.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" +#endif + +/* The unseen_objects list contains objects that have been registered + but not yet categorized in any way. The seen_objects list has had + it's pc_begin and count fields initialized at minimum, and is sorted + by decreasing value of pc_begin. */ +static struct object *unseen_objects; +static struct object *seen_objects; + +#ifdef _LIBC + +__libc_lock_define_initialized_recursive (static, object_mutex) +#define init_object_mutex_once() +#define __gthread_mutex_lock(m) __libc_lock_lock_recursive (*(m)) +#define __gthread_mutex_unlock(m) __libc_lock_unlock_recursive (*(m)) + +#else + +#ifdef __GTHREAD_MUTEX_INIT +static __gthread_mutex_t object_mutex = __GTHREAD_MUTEX_INIT; +#else +static __gthread_mutex_t object_mutex; +#endif + +#ifdef __GTHREAD_MUTEX_INIT_FUNCTION +static void +init_object_mutex (void) +{ + __GTHREAD_MUTEX_INIT_FUNCTION (&object_mutex); +} + +static void +init_object_mutex_once (void) +{ + static __gthread_once_t once = __GTHREAD_ONCE_INIT; + __gthread_once (&once, init_object_mutex); +} +#else +#define init_object_mutex_once() +#endif + +#endif /* _LIBC */ + +/* Called from crtbegin.o to register the unwind info for an object. */ + +void +__register_frame_info_bases (void *begin, struct object *ob, + void *tbase, void *dbase) +{ + ob->pc_begin = (void *)-1; + ob->tbase = tbase; + ob->dbase = dbase; + ob->u.single = begin; + ob->s.i = 0; + ob->s.b.encoding = DW_EH_PE_omit; + + init_object_mutex_once (); + __gthread_mutex_lock (&object_mutex); + + ob->next = unseen_objects; + unseen_objects = ob; + + __gthread_mutex_unlock (&object_mutex); +} + +void +__register_frame_info (void *begin, struct object *ob) +{ + __register_frame_info_bases (begin, ob, 0, 0); +} + +void +__register_frame (void *begin) +{ + struct object *ob = (struct object *) malloc (sizeof (struct object)); + __register_frame_info (begin, ob); +} + +/* Similar, but BEGIN is actually a pointer to a table of unwind entries + for different translation units. Called from the file generated by + collect2. */ + +void +__register_frame_info_table_bases (void *begin, struct object *ob, + void *tbase, void *dbase) +{ + ob->pc_begin = (void *)-1; + ob->tbase = tbase; + ob->dbase = dbase; + ob->u.array = begin; + ob->s.i = 0; + ob->s.b.from_array = 1; + ob->s.b.encoding = DW_EH_PE_omit; + + init_object_mutex_once (); + __gthread_mutex_lock (&object_mutex); + + ob->next = unseen_objects; + unseen_objects = ob; + + __gthread_mutex_unlock (&object_mutex); +} + +void +__register_frame_info_table (void *begin, struct object *ob) +{ + __register_frame_info_table_bases (begin, ob, 0, 0); +} + +void +__register_frame_table (void *begin) +{ + struct object *ob = (struct object *) malloc (sizeof (struct object)); + __register_frame_info_table (begin, ob); +} + +/* Called from crtbegin.o to deregister the unwind info for an object. */ +/* ??? Glibc has for a while now exported __register_frame_info and + __deregister_frame_info. If we call __register_frame_info_bases + from crtbegin (wherein it is declared weak), and this object does + not get pulled from libgcc.a for other reasons, then the + invocation of __deregister_frame_info will be resolved from glibc. + Since the registration did not happen there, we'll abort. + + Therefore, declare a new deregistration entry point that does the + exact same thing, but will resolve to the same library as + implements __register_frame_info_bases. */ + +void * +__deregister_frame_info_bases (void *begin) +{ + struct object **p; + struct object *ob = 0; + + init_object_mutex_once (); + __gthread_mutex_lock (&object_mutex); + + for (p = &unseen_objects; *p ; p = &(*p)->next) + if ((*p)->u.single == begin) + { + ob = *p; + *p = ob->next; + goto out; + } + + for (p = &seen_objects; *p ; p = &(*p)->next) + if ((*p)->s.b.sorted) + { + if ((*p)->u.sort->orig_data == begin) + { + ob = *p; + *p = ob->next; + free (ob->u.sort); + goto out; + } + } + else + { + if ((*p)->u.single == begin) + { + ob = *p; + *p = ob->next; + goto out; + } + } + + __gthread_mutex_unlock (&object_mutex); + abort (); + + out: + __gthread_mutex_unlock (&object_mutex); + return (void *) ob; +} + +void * +__deregister_frame_info (void *begin) +{ + return __deregister_frame_info_bases (begin); +} + +void +__deregister_frame (void *begin) +{ + free (__deregister_frame_info (begin)); +} + + +/* Like base_of_encoded_value, but take the base from a struct object + instead of an _Unwind_Context. */ + +static _Unwind_Ptr +base_from_object (unsigned char encoding, struct object *ob) +{ + 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) ob->tbase; + case DW_EH_PE_datarel: + return (_Unwind_Ptr) ob->dbase; + } + abort (); +} + +/* Return the FDE pointer encoding from the CIE. */ +/* ??? This is a subset of extract_cie_info from unwind-dw2.c. */ + +static int +get_cie_encoding (struct dwarf_cie *cie) +{ + const unsigned char *aug, *p; + _Unwind_Ptr dummy; + + aug = cie->augmentation; + if (aug[0] != 'z') + return DW_EH_PE_absptr; + + p = aug + strlen (aug) + 1; /* Skip the augmentation string. */ + p = read_uleb128 (p, &dummy); /* Skip code alignment. */ + p = read_sleb128 (p, &dummy); /* Skip data alignment. */ + p++; /* Skip return address column. */ + + aug++; /* Skip 'z' */ + p = read_uleb128 (p, &dummy); /* Skip augmentation length. */ + while (1) + { + /* This is what we're looking for. */ + if (*aug == 'R') + return *p; + /* Personality encoding and pointer. */ + else if (*aug == 'P') + { + /* ??? Avoid dereferencing indirect pointers, since we're + faking the base address. Gotta keep DW_EH_PE_aligned + intact, however. */ + p = read_encoded_value_with_base (*p & 0x7F, 0, p + 1, &dummy); + } + /* LSDA encoding. */ + else if (*aug == 'L') + p++; + /* Otherwise end of string, or unknown augmentation. */ + else + return DW_EH_PE_absptr; + aug++; + } +} + +static inline int +get_fde_encoding (struct dwarf_fde *f) +{ + return get_cie_encoding (get_cie (f)); +} + + +/* Sorting an array of FDEs by address. + (Ideally we would have the linker sort the FDEs so we don't have to do + it at run time. But the linkers are not yet prepared for this.) */ + +/* Comparison routines. Three variants of increasing complexity. */ + +static saddr +fde_unencoded_compare (struct object *ob __attribute__((unused)), + fde *x, fde *y) +{ + return *(saddr *)x->pc_begin - *(saddr *)y->pc_begin; +} + +static saddr +fde_single_encoding_compare (struct object *ob, fde *x, fde *y) +{ + _Unwind_Ptr base, x_ptr, y_ptr; + + base = base_from_object (ob->s.b.encoding, ob); + read_encoded_value_with_base (ob->s.b.encoding, base, x->pc_begin, &x_ptr); + read_encoded_value_with_base (ob->s.b.encoding, base, y->pc_begin, &y_ptr); + + return x_ptr - y_ptr; +} + +static saddr +fde_mixed_encoding_compare (struct object *ob, fde *x, fde *y) +{ + int x_encoding, y_encoding; + _Unwind_Ptr x_ptr, y_ptr; + + x_encoding = get_fde_encoding (x); + read_encoded_value_with_base (x_encoding, base_from_object (x_encoding, ob), + x->pc_begin, &x_ptr); + + y_encoding = get_fde_encoding (y); + read_encoded_value_with_base (y_encoding, base_from_object (y_encoding, ob), + y->pc_begin, &y_ptr); + + return x_ptr - y_ptr; +} + +typedef saddr (*fde_compare_t) (struct object *, fde *, fde *); + + +/* This is a special mix of insertion sort and heap sort, optimized for + the data sets that actually occur. They look like + 101 102 103 127 128 105 108 110 190 111 115 119 125 160 126 129 130. + I.e. a linearly increasing sequence (coming from functions in the text + section), with additionally a few unordered elements (coming from functions + in gnu_linkonce sections) whose values are higher than the values in the + surrounding linear sequence (but not necessarily higher than the values + at the end of the linear sequence!). + The worst-case total run time is O(N) + O(n log (n)), where N is the + total number of FDEs and n is the number of erratic ones. */ + +struct fde_accumulator +{ + struct fde_vector *linear; + struct fde_vector *erratic; +}; + +static inline int +start_fde_sort (struct fde_accumulator *accu, size_t count) +{ + size_t size; + if (! count) + return 0; + + size = sizeof (struct fde_vector) + sizeof (fde *) * count; + if ((accu->linear = (struct fde_vector *) malloc (size))) + { + accu->linear->count = 0; + if ((accu->erratic = (struct fde_vector *) malloc (size))) + accu->erratic->count = 0; + return 1; + } + else + return 0; +} + +static inline void +fde_insert (struct fde_accumulator *accu, fde *this_fde) +{ + if (accu->linear) + accu->linear->array[accu->linear->count++] = this_fde; +} + +/* Split LINEAR into a linear sequence with low values and an erratic + sequence with high values, put the linear one (of longest possible + length) into LINEAR and the erratic one into ERRATIC. This is O(N). + + Because the longest linear sequence we are trying to locate within the + incoming LINEAR array can be interspersed with (high valued) erratic + entries. We construct a chain indicating the sequenced entries. + To avoid having to allocate this chain, we overlay it onto the space of + the ERRATIC array during construction. A final pass iterates over the + chain to determine what should be placed in the ERRATIC array, and + what is the linear sequence. This overlay is safe from aliasing. */ + +static inline void +fde_split (struct object *ob, fde_compare_t fde_compare, + struct fde_vector *linear, struct fde_vector *erratic) +{ + static fde *marker; + size_t count = linear->count; + fde **chain_end = ▮ + size_t i, j, k; + + /* This should optimize out, but it is wise to make sure this assumption + is correct. Should these have different sizes, we cannot cast between + them and the overlaying onto ERRATIC will not work. */ + if (sizeof (fde *) != sizeof (fde **)) + abort (); + + for (i = 0; i < count; i++) + { + fde **probe; + + for (probe = chain_end; + probe != &marker && fde_compare (ob, linear->array[i], *probe) < 0; + probe = chain_end) + { + chain_end = (fde **)erratic->array[probe - linear->array]; + erratic->array[probe - linear->array] = NULL; + } + erratic->array[i] = (fde *)chain_end; + chain_end = &linear->array[i]; + } + + /* Each entry in LINEAR which is part of the linear sequence we have + discovered will correspond to a non-NULL entry in the chain we built in + the ERRATIC array. */ + for (i = j = k = 0; i < count; i++) + if (erratic->array[i]) + linear->array[j++] = linear->array[i]; + else + erratic->array[k++] = linear->array[i]; + linear->count = j; + erratic->count = k; +} + +/* This is O(n log(n)). BSD/OS defines heapsort in stdlib.h, so we must + use a name that does not conflict. */ + +static void +frame_heapsort (struct object *ob, fde_compare_t fde_compare, + struct fde_vector *erratic) +{ + /* For a description of this algorithm, see: + Samuel P. Harbison, Guy L. Steele Jr.: C, a reference manual, 2nd ed., + p. 60-61. */ + fde ** a = erratic->array; + /* A portion of the array is called a "heap" if for all i>=0: + If i and 2i+1 are valid indices, then a[i] >= a[2i+1]. + If i and 2i+2 are valid indices, then a[i] >= a[2i+2]. */ +#define SWAP(x,y) do { fde * tmp = x; x = y; y = tmp; } while (0) + size_t n = erratic->count; + size_t m = n; + size_t i; + + while (m > 0) + { + /* Invariant: a[m..n-1] is a heap. */ + m--; + for (i = m; 2*i+1 < n; ) + { + if (2*i+2 < n + && fde_compare (ob, a[2*i+2], a[2*i+1]) > 0 + && fde_compare (ob, a[2*i+2], a[i]) > 0) + { + SWAP (a[i], a[2*i+2]); + i = 2*i+2; + } + else if (fde_compare (ob, a[2*i+1], a[i]) > 0) + { + SWAP (a[i], a[2*i+1]); + i = 2*i+1; + } + else + break; + } + } + while (n > 1) + { + /* Invariant: a[0..n-1] is a heap. */ + n--; + SWAP (a[0], a[n]); + for (i = 0; 2*i+1 < n; ) + { + if (2*i+2 < n + && fde_compare (ob, a[2*i+2], a[2*i+1]) > 0 + && fde_compare (ob, a[2*i+2], a[i]) > 0) + { + SWAP (a[i], a[2*i+2]); + i = 2*i+2; + } + else if (fde_compare (ob, a[2*i+1], a[i]) > 0) + { + SWAP (a[i], a[2*i+1]); + i = 2*i+1; + } + else + break; + } + } +#undef SWAP +} + +/* Merge V1 and V2, both sorted, and put the result into V1. */ +static inline void +fde_merge (struct object *ob, fde_compare_t fde_compare, + struct fde_vector *v1, struct fde_vector *v2) +{ + size_t i1, i2; + fde * fde2; + + i2 = v2->count; + if (i2 > 0) + { + i1 = v1->count; + do { + i2--; + fde2 = v2->array[i2]; + while (i1 > 0 && fde_compare (ob, v1->array[i1-1], fde2) > 0) + { + v1->array[i1+i2] = v1->array[i1-1]; + i1--; + } + v1->array[i1+i2] = fde2; + } while (i2 > 0); + v1->count += v2->count; + } +} + +static inline void +end_fde_sort (struct object *ob, struct fde_accumulator *accu, size_t count) +{ + fde_compare_t fde_compare; + + if (accu->linear && accu->linear->count != count) + abort (); + + if (ob->s.b.mixed_encoding) + fde_compare = fde_mixed_encoding_compare; + else if (ob->s.b.encoding == DW_EH_PE_absptr) + fde_compare = fde_unencoded_compare; + else + fde_compare = fde_single_encoding_compare; + + if (accu->erratic) + { + fde_split (ob, fde_compare, accu->linear, accu->erratic); + if (accu->linear->count + accu->erratic->count != count) + abort (); + frame_heapsort (ob, fde_compare, accu->erratic); + fde_merge (ob, fde_compare, accu->linear, accu->erratic); + free (accu->erratic); + } + else + { + /* We've not managed to malloc an erratic array, + so heap sort in the linear one. */ + frame_heapsort (ob, fde_compare, accu->linear); + } +} + + +/* Update encoding, mixed_encoding, and pc_begin for OB for the + fde array beginning at THIS_FDE. Return the number of fdes + encountered along the way. */ + +static size_t +classify_object_over_fdes (struct object *ob, fde *this_fde) +{ + struct dwarf_cie *last_cie = 0; + size_t count = 0; + int encoding = DW_EH_PE_absptr; + _Unwind_Ptr base = 0; + + for (; this_fde->length != 0; this_fde = next_fde (this_fde)) + { + struct dwarf_cie *this_cie; + _Unwind_Ptr mask, pc_begin; + + /* Skip CIEs. */ + if (this_fde->CIE_delta == 0) + continue; + + /* Determine the encoding for this FDE. Note mixed encoded + objects for later. */ + this_cie = get_cie (this_fde); + if (this_cie != last_cie) + { + last_cie = this_cie; + encoding = get_cie_encoding (this_cie); + base = base_from_object (encoding, ob); + if (ob->s.b.encoding == DW_EH_PE_omit) + ob->s.b.encoding = encoding; + else if (ob->s.b.encoding != encoding) + ob->s.b.mixed_encoding = 1; + } + + read_encoded_value_with_base (encoding, base, this_fde->pc_begin, + &pc_begin); + + /* Take care to ignore link-once functions that were removed. + In these cases, the function address will be NULL, but if + the encoding is smaller than a pointer a true NULL may not + be representable. Assume 0 in the representable bits is NULL. */ + mask = size_of_encoded_value (encoding); + if (mask < sizeof (void *)) + mask = (1L << (mask << 3)) - 1; + else + mask = -1; + + if ((pc_begin & mask) == 0) + continue; + + count += 1; + if ((void *)pc_begin < ob->pc_begin) + ob->pc_begin = (void *)pc_begin; + } + + return count; +} + +static void +add_fdes (struct object *ob, struct fde_accumulator *accu, fde *this_fde) +{ + struct dwarf_cie *last_cie = 0; + int encoding = ob->s.b.encoding; + _Unwind_Ptr base = base_from_object (ob->s.b.encoding, ob); + + for (; this_fde->length != 0; this_fde = next_fde (this_fde)) + { + struct dwarf_cie *this_cie; + + /* Skip CIEs. */ + if (this_fde->CIE_delta == 0) + continue; + + if (ob->s.b.mixed_encoding) + { + /* Determine the encoding for this FDE. Note mixed encoded + objects for later. */ + this_cie = get_cie (this_fde); + if (this_cie != last_cie) + { + last_cie = this_cie; + encoding = get_cie_encoding (this_cie); + base = base_from_object (encoding, ob); + } + } + + if (encoding == DW_EH_PE_absptr) + { + if (*(_Unwind_Ptr *)this_fde->pc_begin == 0) + continue; + } + else + { + _Unwind_Ptr pc_begin, mask; + + read_encoded_value_with_base (encoding, base, this_fde->pc_begin, + &pc_begin); + + /* Take care to ignore link-once functions that were removed. + In these cases, the function address will be NULL, but if + the encoding is smaller than a pointer a true NULL may not + be representable. Assume 0 in the representable bits is NULL. */ + mask = size_of_encoded_value (encoding); + if (mask < sizeof (void *)) + mask = (1L << (mask << 3)) - 1; + else + mask = -1; + + if ((pc_begin & mask) == 0) + continue; + } + + fde_insert (accu, this_fde); + } +} + +/* Set up a sorted array of pointers to FDEs for a loaded object. We + count up the entries before allocating the array because it's likely to + be faster. We can be called multiple times, should we have failed to + allocate a sorted fde array on a previous occasion. */ + +static inline void +init_object (struct object* ob) +{ + struct fde_accumulator accu; + size_t count; + + count = ob->s.b.count; + if (count == 0) + { + if (ob->s.b.from_array) + { + fde **p = ob->u.array; + for (count = 0; *p; ++p) + count += classify_object_over_fdes (ob, *p); + } + else + count = classify_object_over_fdes (ob, ob->u.single); + + /* The count field we have in the main struct object is somewhat + limited, but should suffice for virtually all cases. If the + counted value doesn't fit, re-write a zero. The worst that + happens is that we re-count next time -- admittedly non-trivial + in that this implies some 2M fdes, but at least we function. */ + ob->s.b.count = count; + if (ob->s.b.count != count) + ob->s.b.count = 0; + } + + if (!start_fde_sort (&accu, count)) + return; + + if (ob->s.b.from_array) + { + fde **p; + for (p = ob->u.array; *p; ++p) + add_fdes (ob, &accu, *p); + } + else + add_fdes (ob, &accu, ob->u.single); + + end_fde_sort (ob, &accu, count); + + /* Save the original fde pointer, since this is the key by which the + DSO will deregister the object. */ + accu.linear->orig_data = ob->u.single; + ob->u.sort = accu.linear; + + ob->s.b.sorted = 1; +} + +/* A linear search through a set of FDEs for the given PC. This is + used when there was insufficient memory to allocate and sort an + array. */ + +static fde * +linear_search_fdes (struct object *ob, fde *this_fde, void *pc) +{ + struct dwarf_cie *last_cie = 0; + int encoding = ob->s.b.encoding; + _Unwind_Ptr base = base_from_object (ob->s.b.encoding, ob); + + for (; this_fde->length != 0; this_fde = next_fde (this_fde)) + { + struct dwarf_cie *this_cie; + _Unwind_Ptr pc_begin, pc_range; + + /* Skip CIEs. */ + if (this_fde->CIE_delta == 0) + continue; + + if (ob->s.b.mixed_encoding) + { + /* Determine the encoding for this FDE. Note mixed encoded + objects for later. */ + this_cie = get_cie (this_fde); + if (this_cie != last_cie) + { + last_cie = this_cie; + encoding = get_cie_encoding (this_cie); + base = base_from_object (encoding, ob); + } + } + + if (encoding == DW_EH_PE_absptr) + { + pc_begin = ((_Unwind_Ptr *)this_fde->pc_begin)[0]; + pc_range = ((_Unwind_Ptr *)this_fde->pc_begin)[1]; + if (pc_begin == 0) + continue; + } + else + { + _Unwind_Ptr mask; + const char *p; + + p = read_encoded_value_with_base (encoding, base, + this_fde->pc_begin, &pc_begin); + read_encoded_value_with_base (encoding & 0x0F, 0, p, &pc_range); + + /* Take care to ignore link-once functions that were removed. + In these cases, the function address will be NULL, but if + the encoding is smaller than a pointer a true NULL may not + be representable. Assume 0 in the representable bits is NULL. */ + mask = size_of_encoded_value (encoding); + if (mask < sizeof (void *)) + mask = (1L << (mask << 3)) - 1; + else + mask = -1; + + if ((pc_begin & mask) == 0) + continue; + } + + if ((_Unwind_Ptr)pc - pc_begin < pc_range) + return this_fde; + } + + return NULL; +} + +/* Binary search for an FDE containing the given PC. Here are three + implementations of increasing complexity. */ + +static inline fde * +binary_search_unencoded_fdes (struct object *ob, void *pc) +{ + struct fde_vector *vec = ob->u.sort; + size_t lo, hi; + + for (lo = 0, hi = vec->count; lo < hi; ) + { + size_t i = (lo + hi) / 2; + fde *f = vec->array[i]; + void *pc_begin; + uaddr pc_range; + + pc_begin = ((void **)f->pc_begin)[0]; + pc_range = ((uaddr *)f->pc_begin)[1]; + + if (pc < pc_begin) + hi = i; + else if (pc >= pc_begin + pc_range) + lo = i + 1; + else + return f; + } + + return NULL; +} + +static inline fde * +binary_search_single_encoding_fdes (struct object *ob, void *pc) +{ + struct fde_vector *vec = ob->u.sort; + int encoding = ob->s.b.encoding; + _Unwind_Ptr base = base_from_object (encoding, ob); + size_t lo, hi; + + for (lo = 0, hi = vec->count; lo < hi; ) + { + size_t i = (lo + hi) / 2; + fde *f = vec->array[i]; + _Unwind_Ptr pc_begin, pc_range; + const char *p; + + p = read_encoded_value_with_base (encoding, base, f->pc_begin, + &pc_begin); + read_encoded_value_with_base (encoding & 0x0F, 0, p, &pc_range); + + if ((_Unwind_Ptr)pc < pc_begin) + hi = i; + else if ((_Unwind_Ptr)pc >= pc_begin + pc_range) + lo = i + 1; + else + return f; + } + + return NULL; +} + +static inline fde * +binary_search_mixed_encoding_fdes (struct object *ob, void *pc) +{ + struct fde_vector *vec = ob->u.sort; + size_t lo, hi; + + for (lo = 0, hi = vec->count; lo < hi; ) + { + size_t i = (lo + hi) / 2; + fde *f = vec->array[i]; + _Unwind_Ptr pc_begin, pc_range; + const char *p; + int encoding; + + encoding = get_fde_encoding (f); + p = read_encoded_value_with_base (encoding, + base_from_object (encoding, ob), + f->pc_begin, &pc_begin); + read_encoded_value_with_base (encoding & 0x0F, 0, p, &pc_range); + + if ((_Unwind_Ptr)pc < pc_begin) + hi = i; + else if ((_Unwind_Ptr)pc >= pc_begin + pc_range) + lo = i + 1; + else + return f; + } + + return NULL; +} + +static fde * +search_object (struct object* ob, void *pc) +{ + /* If the data hasn't been sorted, try to do this now. We may have + more memory available than last time we tried. */ + if (! ob->s.b.sorted) + { + init_object (ob); + + /* Despite the above comment, the normal reason to get here is + that we've not processed this object before. A quick range + check is in order. */ + if (pc < ob->pc_begin) + return NULL; + } + + if (ob->s.b.sorted) + { + if (ob->s.b.mixed_encoding) + return binary_search_mixed_encoding_fdes (ob, pc); + else if (ob->s.b.encoding == DW_EH_PE_absptr) + return binary_search_unencoded_fdes (ob, pc); + else + return binary_search_single_encoding_fdes (ob, pc); + } + else + { + /* Long slow labourious linear search, cos we've no memory. */ + if (ob->s.b.from_array) + { + fde **p; + for (p = ob->u.array; *p ; p++) + { + fde *f = linear_search_fdes (ob, *p, pc); + if (f) + return f; + } + return NULL; + } + else + return linear_search_fdes (ob, ob->u.single, pc); + } +} + +fde * +_Unwind_Find_FDE (void *pc, struct dwarf_eh_bases *bases) +{ + struct object *ob; + fde *f = NULL; + + init_object_mutex_once (); + __gthread_mutex_lock (&object_mutex); + + /* Linear search through the classified objects, to find the one + containing the pc. Note that pc_begin is sorted decending, and + we expect objects to be non-overlapping. */ + for (ob = seen_objects; ob; ob = ob->next) + if (pc >= ob->pc_begin) + { + f = search_object (ob, pc); + if (f) + goto fini; + break; + } + + /* Classify and search the objects we've not yet processed. */ + while ((ob = unseen_objects)) + { + struct object **p; + + unseen_objects = ob->next; + f = search_object (ob, pc); + + /* Insert the object into the classified list. */ + for (p = &seen_objects; *p ; p = &(*p)->next) + if ((*p)->pc_begin < ob->pc_begin) + break; + ob->next = *p; + *p = ob; + + if (f) + goto fini; + } + + fini: + __gthread_mutex_unlock (&object_mutex); + + if (f) + { + int encoding; + + bases->tbase = ob->tbase; + bases->dbase = ob->dbase; + + encoding = ob->s.b.encoding; + if (ob->s.b.mixed_encoding) + encoding = get_fde_encoding (f); + read_encoded_value_with_base (encoding, base_from_object (encoding, ob), + f->pc_begin, (_Unwind_Ptr *)&bases->func); + } + + return f; +} + +#endif diff --git a/sysdeps/generic/unwind-dw2-fde.h b/sysdeps/generic/unwind-dw2-fde.h new file mode 100644 index 0000000000..83b4470ce5 --- /dev/null +++ b/sysdeps/generic/unwind-dw2-fde.h @@ -0,0 +1,165 @@ +/* Subroutines needed for unwinding stack frames for exception handling. */ +/* Copyright (C) 1997, 1998, 1999, 2000, 2001 Free Software Foundation, Inc. + Contributed by Jason Merrill <jason@cygnus.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. + +In addition to the permissions in the GNU General Public License, the +Free Software Foundation gives you unlimited permission to link the +compiled version of this file into combinations with other programs, +and to distribute those combinations without any restriction coming +from the use of this file. (The General Public License restrictions +do apply in other respects; for example, they cover modification of +the file, and distribution when not linked into a combine +executable.) + +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. */ + + +struct fde_vector +{ + void *orig_data; + size_t count; + struct dwarf_fde *array __flexarr; +}; + +#ifdef _LIBC +#include <gccframe.h> +#else +struct object +{ + void *pc_begin; + void *tbase; + void *dbase; + union { + struct dwarf_fde *single; + struct dwarf_fde **array; + struct fde_vector *sort; + } u; + + union { + struct { + unsigned long sorted : 1; + unsigned long from_array : 1; + unsigned long mixed_encoding : 1; + unsigned long encoding : 8; + /* ??? Wish there was an easy way to detect a 64-bit host here; + we've got 32 bits left to play with... */ + unsigned long count : 21; + } b; + size_t i; + } s; + + struct object *next; +}; +#endif + +/* This is the original definition of struct object. While the struct + itself was opaque to users, they did know how large it was, and + allocate one statically in crtbegin for each DSO. Keep this around + so that we're aware of the static size limitations for the new struct. */ +struct old_object +{ + void *pc_begin; + void *pc_end; + struct dwarf_fde *fde_begin; + struct dwarf_fde **fde_array; + size_t count; + struct old_object *next; +}; + +struct dwarf_eh_bases +{ + void *tbase; + void *dbase; + void *func; +}; + + +extern void __register_frame_info_bases (void *, struct object *, + void *, void *); +extern void __register_frame_info (void *, struct object *); +extern void __register_frame (void *); +extern void __register_frame_info_table_bases (void *, struct object *, + void *, void *); +extern void __register_frame_info_table (void *, struct object *); +extern void __register_frame_table (void *); +extern void *__deregister_frame_info (void *); +extern void *__deregister_frame_info_bases (void *); +extern void __deregister_frame (void *); + + +typedef int sword __attribute__ ((mode (SI))); +typedef unsigned int uword __attribute__ ((mode (SI))); +typedef unsigned int uaddr __attribute__ ((mode (pointer))); +typedef int saddr __attribute__ ((mode (pointer))); +typedef unsigned char ubyte; + +/* Terminology: + CIE - Common Information Element + FDE - Frame Descriptor Element + + There is one per function, and it describes where the function code + is located, and what the register lifetimes and stack layout are + within the function. + + The data structures are defined in the DWARF specfication, although + not in a very readable way (see LITERATURE). + + Every time an exception is thrown, the code needs to locate the FDE + for the current function, and starts to look for exception regions + from that FDE. This works in a two-level search: + a) in a linear search, find the shared image (i.e. DLL) containing + the PC + b) using the FDE table for that shared object, locate the FDE using + binary search (which requires the sorting). */ + +/* The first few fields of a CIE. The CIE_id field is 0 for a CIE, + to distinguish it from a valid FDE. FDEs are aligned to an addressing + unit boundary, but the fields within are unaligned. */ +struct dwarf_cie +{ + uword length; + sword CIE_id; + ubyte version; + unsigned char augmentation __flexarr; +} __attribute__ ((packed, aligned (__alignof__ (void *)))); + +/* The first few fields of an FDE. */ +struct dwarf_fde +{ + uword length; + sword CIE_delta; + unsigned char pc_begin __flexarr; +} __attribute__ ((packed, aligned (__alignof__ (void *)))); + +typedef struct dwarf_fde fde; + +/* Locate the CIE for a given FDE. */ + +static inline struct dwarf_cie * +get_cie (struct dwarf_fde *f) +{ + return (void *)&f->CIE_delta - f->CIE_delta; +} + +static inline fde * +next_fde (fde *f) +{ + return (fde *)((char *)f + f->length + sizeof (f->length)); +} + +extern fde * _Unwind_Find_FDE (void *, struct dwarf_eh_bases *); diff --git a/sysdeps/generic/unwind-dw2.c b/sysdeps/generic/unwind-dw2.c new file mode 100644 index 0000000000..ac56e7c35c --- /dev/null +++ b/sysdeps/generic/unwind-dw2.c @@ -0,0 +1,1207 @@ +/* DWARF2 exception handling and frame unwind runtime interface routines. + Copyright (C) 1997, 1998, 1999, 2000, 2001 Free Software Foundation, Inc. + + 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. */ + +#ifdef _LIBC +#include <stdlib.h> +#include <string.h> +#include <error.h> +#include <libintl.h> +#include <dwarf2.h> +#include <unwind.h> +#include <unwind-pe.h> +#include <unwind-dw2-fde.h> +#else +#include "tconfig.h" +#include "tsystem.h" +#include "dwarf2.h" +#include "unwind.h" +#include "unwind-pe.h" +#include "unwind-dw2-fde.h" +#include "gthr.h" +#endif + +#if !USING_SJLJ_EXCEPTIONS + +#ifndef STACK_GROWS_DOWNWARD +#define STACK_GROWS_DOWNWARD 0 +#else +#undef STACK_GROWS_DOWNWARD +#define STACK_GROWS_DOWNWARD 1 +#endif + +/* A target can override (perhaps for backward compatibility) how + many dwarf2 columns are unwound. */ +#ifndef DWARF_FRAME_REGISTERS +#define DWARF_FRAME_REGISTERS FIRST_PSEUDO_REGISTER +#endif + +/* This is the register and unwind state for a particular frame. */ +struct _Unwind_Context +{ + void *reg[DWARF_FRAME_REGISTERS+1]; + void *cfa; + void *ra; + void *lsda; + struct dwarf_eh_bases bases; + _Unwind_Word args_size; +}; + +#ifndef _LIBC +/* Byte size of every register managed by these routines. */ +static unsigned char dwarf_reg_size_table[DWARF_FRAME_REGISTERS]; +#endif + + +/* The result of interpreting the frame unwind info for a frame. + This is all symbolic at this point, as none of the values can + be resolved until the target pc is located. */ +typedef struct +{ + /* Each register save state can be described in terms of a CFA slot, + another register, or a location expression. */ + struct frame_state_reg_info + { + struct { + union { + unsigned int reg; + _Unwind_Sword offset; + const unsigned char *exp; + } loc; + enum { + REG_UNSAVED, + REG_SAVED_OFFSET, + REG_SAVED_REG, + REG_SAVED_EXP, + } how; + } reg[DWARF_FRAME_REGISTERS+1]; + + /* Used to implement DW_CFA_remember_state. */ + struct frame_state_reg_info *prev; + } regs; + + /* The CFA can be described in terms of a reg+offset or a + location expression. */ + _Unwind_Sword cfa_offset; + _Unwind_Word cfa_reg; + const unsigned char *cfa_exp; + enum { + CFA_UNSET, + CFA_REG_OFFSET, + CFA_EXP, + } cfa_how; + + /* The PC described by the current frame state. */ + void *pc; + + /* The information we care about from the CIE/FDE. */ + _Unwind_Personality_Fn personality; + signed int data_align; + unsigned int code_align; + unsigned char retaddr_column; + unsigned char fde_encoding; + unsigned char lsda_encoding; + unsigned char saw_z; + void *eh_ptr; +} _Unwind_FrameState; + +/* Read unaligned data from the instruction buffer. */ + +union unaligned +{ + void *p; + unsigned u2 __attribute__ ((mode (HI))); + unsigned u4 __attribute__ ((mode (SI))); + unsigned u8 __attribute__ ((mode (DI))); + signed s2 __attribute__ ((mode (HI))); + signed s4 __attribute__ ((mode (SI))); + signed s8 __attribute__ ((mode (DI))); +} __attribute__ ((packed)); + +static inline void * +read_pointer (const void *p) { const union unaligned *up = p; return up->p; } + +static inline int +read_1u (const void *p) { return *(const unsigned char *)p; } + +static inline int +read_1s (const void *p) { return *(const signed char *)p; } + +static inline int +read_2u (const void *p) { const union unaligned *up = p; return up->u2; } + +static inline int +read_2s (const void *p) { const union unaligned *up = p; return up->s2; } + +static inline unsigned int +read_4u (const void *p) { const union unaligned *up = p; return up->u4; } + +static inline int +read_4s (const void *p) { const union unaligned *up = p; return up->s4; } + +static inline unsigned long +read_8u (const void *p) { const union unaligned *up = p; return up->u8; } + +static inline unsigned long +read_8s (const void *p) { const union unaligned *up = p; return up->s8; } + +/* Get the value of register REG as saved in CONTEXT. */ + +inline _Unwind_Word +_Unwind_GetGR (struct _Unwind_Context *context, int index) +{ + /* This will segfault if the register hasn't been saved. */ + return * (_Unwind_Word *) context->reg[index]; +} + +/* Overwrite the saved value for register REG in CONTEXT with VAL. */ + +inline void +_Unwind_SetGR (struct _Unwind_Context *context, int index, _Unwind_Word val) +{ + * (_Unwind_Word *) context->reg[index] = val; +} + +/* Retrieve the return address for CONTEXT. */ + +inline _Unwind_Ptr +_Unwind_GetIP (struct _Unwind_Context *context) +{ + return (_Unwind_Ptr) context->ra; +} + +/* Overwrite the return address for CONTEXT with VAL. */ + +inline void +_Unwind_SetIP (struct _Unwind_Context *context, _Unwind_Ptr val) +{ + context->ra = (void *) val; +} + +void * +_Unwind_GetLanguageSpecificData (struct _Unwind_Context *context) +{ + return context->lsda; +} + +_Unwind_Ptr +_Unwind_GetRegionStart (struct _Unwind_Context *context) +{ + return (_Unwind_Ptr) context->bases.func; +} + +#ifndef __ia64__ +_Unwind_Ptr +_Unwind_GetDataRelBase (struct _Unwind_Context *context) +{ + return (_Unwind_Ptr) context->bases.dbase; +} + +_Unwind_Ptr +_Unwind_GetTextRelBase (struct _Unwind_Context *context) +{ + return (_Unwind_Ptr) context->bases.tbase; +} +#endif + +/* Extract any interesting information from the CIE for the translation + unit F belongs to. Return a pointer to the byte after the augmentation, + or NULL if we encountered an undecipherable augmentation. */ + +static const unsigned char * +extract_cie_info (struct dwarf_cie *cie, struct _Unwind_Context *context, + _Unwind_FrameState *fs) +{ + const unsigned char *aug = cie->augmentation; + const unsigned char *p = aug + strlen (aug) + 1; + const unsigned char *ret = NULL; + _Unwind_Ptr tmp; + + /* g++ v2 "eh" has pointer immediately following augmentation string, + so it must be handled first. */ + if (aug[0] == 'e' && aug[1] == 'h') + { + fs->eh_ptr = read_pointer (p); + p += sizeof (void *); + aug += 2; + } + + /* Immediately following the augmentation are the code and + data alignment and return address column. */ + p = read_uleb128 (p, &tmp); fs->code_align = tmp; + p = read_sleb128 (p, &tmp); fs->data_align = (saddr) tmp; + fs->retaddr_column = *p++; + fs->lsda_encoding = DW_EH_PE_omit; + + /* If the augmentation starts with 'z', then a uleb128 immediately + follows containing the length of the augmentation field following + the size. */ + if (*aug == 'z') + { + p = read_uleb128 (p, &tmp); + ret = p + tmp; + + fs->saw_z = 1; + ++aug; + } + + /* Iterate over recognized augmentation subsequences. */ + while (*aug != '\0') + { + /* "L" indicates a byte showing how the LSDA pointer is encoded. */ + if (aug[0] == 'L') + { + fs->lsda_encoding = *p++; + aug += 1; + } + + /* "R" indicates a byte indicating how FDE addresses are encoded. */ + else if (aug[0] == 'R') + { + fs->fde_encoding = *p++; + aug += 1; + } + + /* "P" indicates a personality routine in the CIE augmentation. */ + else if (aug[0] == 'P') + { + p = read_encoded_value (context, *p, p + 1, + (_Unwind_Ptr *) &fs->personality); + aug += 1; + } + + /* Otherwise we have an unknown augmentation string. + Bail unless we saw a 'z' prefix. */ + else + return ret; + } + + return ret ? ret : p; +} + +#ifndef _LIBC +/* Decode a DW_OP stack program. Return the top of stack. Push INITIAL + onto the stack to start. */ + +static _Unwind_Word +execute_stack_op (const unsigned char *op_ptr, const unsigned char *op_end, + struct _Unwind_Context *context, _Unwind_Word initial) +{ + _Unwind_Word stack[64]; /* ??? Assume this is enough. */ + int stack_elt; + + stack[0] = initial; + stack_elt = 1; + + while (op_ptr < op_end) + { + enum dwarf_location_atom op = *op_ptr++; + _Unwind_Word result = 0, reg; + _Unwind_Sword offset; + _Unwind_Ptr ptrtmp; + + switch (op) + { + case DW_OP_lit0: + case DW_OP_lit1: + case DW_OP_lit2: + case DW_OP_lit3: + case DW_OP_lit4: + case DW_OP_lit5: + case DW_OP_lit6: + case DW_OP_lit7: + case DW_OP_lit8: + case DW_OP_lit9: + case DW_OP_lit10: + case DW_OP_lit11: + case DW_OP_lit12: + case DW_OP_lit13: + case DW_OP_lit14: + case DW_OP_lit15: + case DW_OP_lit16: + case DW_OP_lit17: + case DW_OP_lit18: + case DW_OP_lit19: + case DW_OP_lit20: + case DW_OP_lit21: + case DW_OP_lit22: + case DW_OP_lit23: + case DW_OP_lit24: + case DW_OP_lit25: + case DW_OP_lit26: + case DW_OP_lit27: + case DW_OP_lit28: + case DW_OP_lit29: + case DW_OP_lit30: + case DW_OP_lit31: + result = op - DW_OP_lit0; + break; + + case DW_OP_addr: + result = (_Unwind_Word) (_Unwind_Ptr) read_pointer (op_ptr); + op_ptr += sizeof (void *); + break; + + case DW_OP_const1u: + result = read_1u (op_ptr); + op_ptr += 1; + break; + case DW_OP_const1s: + result = read_1s (op_ptr); + op_ptr += 1; + break; + case DW_OP_const2u: + result = read_2u (op_ptr); + op_ptr += 2; + break; + case DW_OP_const2s: + result = read_2s (op_ptr); + op_ptr += 2; + break; + case DW_OP_const4u: + result = read_4u (op_ptr); + op_ptr += 4; + break; + case DW_OP_const4s: + result = read_4s (op_ptr); + op_ptr += 4; + break; + case DW_OP_const8u: + result = read_8u (op_ptr); + op_ptr += 8; + break; + case DW_OP_const8s: + result = read_8s (op_ptr); + op_ptr += 8; + break; + case DW_OP_constu: + op_ptr = read_uleb128 (op_ptr, &ptrtmp); + result = ptrtmp; + break; + case DW_OP_consts: + op_ptr = read_sleb128 (op_ptr, &ptrtmp); + result = (saddr)ptrtmp; + break; + + case DW_OP_reg0: + case DW_OP_reg1: + case DW_OP_reg2: + case DW_OP_reg3: + case DW_OP_reg4: + case DW_OP_reg5: + case DW_OP_reg6: + case DW_OP_reg7: + case DW_OP_reg8: + case DW_OP_reg9: + case DW_OP_reg10: + case DW_OP_reg11: + case DW_OP_reg12: + case DW_OP_reg13: + case DW_OP_reg14: + case DW_OP_reg15: + case DW_OP_reg16: + case DW_OP_reg17: + case DW_OP_reg18: + case DW_OP_reg19: + case DW_OP_reg20: + case DW_OP_reg21: + case DW_OP_reg22: + case DW_OP_reg23: + case DW_OP_reg24: + case DW_OP_reg25: + case DW_OP_reg26: + case DW_OP_reg27: + case DW_OP_reg28: + case DW_OP_reg29: + case DW_OP_reg30: + case DW_OP_reg31: + result = _Unwind_GetGR (context, op - DW_OP_reg0); + break; + case DW_OP_regx: + op_ptr = read_uleb128 (op_ptr, &ptrtmp); reg = ptrtmp; + result = _Unwind_GetGR (context, reg); + break; + + case DW_OP_breg0: + case DW_OP_breg1: + case DW_OP_breg2: + case DW_OP_breg3: + case DW_OP_breg4: + case DW_OP_breg5: + case DW_OP_breg6: + case DW_OP_breg7: + case DW_OP_breg8: + case DW_OP_breg9: + case DW_OP_breg10: + case DW_OP_breg11: + case DW_OP_breg12: + case DW_OP_breg13: + case DW_OP_breg14: + case DW_OP_breg15: + case DW_OP_breg16: + case DW_OP_breg17: + case DW_OP_breg18: + case DW_OP_breg19: + case DW_OP_breg20: + case DW_OP_breg21: + case DW_OP_breg22: + case DW_OP_breg23: + case DW_OP_breg24: + case DW_OP_breg25: + case DW_OP_breg26: + case DW_OP_breg27: + case DW_OP_breg28: + case DW_OP_breg29: + case DW_OP_breg30: + case DW_OP_breg31: + op_ptr = read_sleb128 (op_ptr, &ptrtmp); offset = (saddr)ptrtmp; + result = _Unwind_GetGR (context, op - DW_OP_breg0) + offset; + break; + case DW_OP_bregx: + op_ptr = read_uleb128 (op_ptr, &ptrtmp); reg = ptrtmp; + op_ptr = read_sleb128 (op_ptr, &ptrtmp); offset = (saddr)ptrtmp; + result = _Unwind_GetGR (context, reg) + offset; + break; + + case DW_OP_dup: + if (stack_elt < 1) + abort (); + result = stack[stack_elt - 1]; + break; + + case DW_OP_drop: + if (--stack_elt < 0) + abort (); + goto no_push; + + case DW_OP_pick: + offset = *op_ptr++; + if (offset >= stack_elt - 1) + abort (); + result = stack[stack_elt - 1 - offset]; + break; + + case DW_OP_over: + if (stack_elt < 2) + abort (); + result = stack[stack_elt - 2]; + break; + + case DW_OP_rot: + { + _Unwind_Word t1, t2, t3; + + if (stack_elt < 3) + abort (); + t1 = stack[stack_elt - 1]; + t2 = stack[stack_elt - 2]; + t3 = stack[stack_elt - 3]; + stack[stack_elt - 1] = t2; + stack[stack_elt - 2] = t3; + stack[stack_elt - 3] = t1; + goto no_push; + } + + case DW_OP_deref: + case DW_OP_deref_size: + case DW_OP_abs: + case DW_OP_neg: + case DW_OP_not: + case DW_OP_plus_uconst: + /* Unary operations. */ + if (--stack_elt < 0) + abort (); + result = stack[stack_elt]; + + switch (op) + { + case DW_OP_deref: + { + void *ptr = (void *)(_Unwind_Ptr) result; + result = (_Unwind_Ptr) read_pointer (ptr); + } + break; + + case DW_OP_deref_size: + { + void *ptr = (void *)(_Unwind_Ptr) result; + switch (*op_ptr++) + { + case 1: + result = read_1u (ptr); + break; + case 2: + result = read_2u (ptr); + break; + case 4: + result = read_4u (ptr); + break; + case 8: + result = read_8u (ptr); + break; + default: + abort (); + } + } + break; + + case DW_OP_abs: + if ((_Unwind_Sword) result < 0) + result = -result; + break; + case DW_OP_neg: + result = -result; + break; + case DW_OP_not: + result = ~result; + break; + case DW_OP_plus_uconst: + op_ptr = read_uleb128 (op_ptr, &ptrtmp); reg = ptrtmp; + result += reg; + break; + /* Avoid warnings. */ + default: + break; + } + break; + + case DW_OP_and: + case DW_OP_div: + case DW_OP_minus: + case DW_OP_mod: + case DW_OP_mul: + case DW_OP_or: + case DW_OP_plus: + case DW_OP_le: + case DW_OP_ge: + case DW_OP_eq: + case DW_OP_lt: + case DW_OP_gt: + case DW_OP_ne: + { + /* Binary operations. */ + _Unwind_Word first, second; + if ((stack_elt -= 2) < 0) + abort (); + second = stack[stack_elt]; + first = stack[stack_elt + 1]; + + switch (op) + { + case DW_OP_and: + result = second & first; + break; + case DW_OP_div: + result = (_Unwind_Sword)second / (_Unwind_Sword)first; + break; + case DW_OP_minus: + result = second - first; + break; + case DW_OP_mod: + result = (_Unwind_Sword)second % (_Unwind_Sword)first; + break; + case DW_OP_mul: + result = second * first; + break; + case DW_OP_or: + result = second | first; + break; + case DW_OP_plus: + result = second + first; + break; + case DW_OP_shl: + result = second << first; + break; + case DW_OP_shr: + result = second >> first; + break; + case DW_OP_shra: + result = (_Unwind_Sword)second >> first; + break; + case DW_OP_xor: + result = second ^ first; + break; + case DW_OP_le: + result = (_Unwind_Sword)first <= (_Unwind_Sword)second; + break; + case DW_OP_ge: + result = (_Unwind_Sword)first >= (_Unwind_Sword)second; + break; + case DW_OP_eq: + result = (_Unwind_Sword)first == (_Unwind_Sword)second; + break; + case DW_OP_lt: + result = (_Unwind_Sword)first < (_Unwind_Sword)second; + break; + case DW_OP_gt: + result = (_Unwind_Sword)first > (_Unwind_Sword)second; + break; + case DW_OP_ne: + result = (_Unwind_Sword)first != (_Unwind_Sword)second; + break; + default: + /* Avoid warnings. */ + break; + } + } + break; + + case DW_OP_skip: + offset = read_2s (op_ptr); + op_ptr += 2; + op_ptr += offset; + goto no_push; + + case DW_OP_bra: + if (--stack_elt < 0) + abort (); + offset = read_2s (op_ptr); + op_ptr += 2; + if (stack[stack_elt] != 0) + op_ptr += offset; + goto no_push; + + case DW_OP_nop: + goto no_push; + + default: + abort (); + } + + /* Most things push a result value. */ + if ((size_t) stack_elt >= sizeof(stack)/sizeof(*stack)) + abort (); + stack[++stack_elt] = result; + no_push:; + } + + /* We were executing this program to get a value. It should be + at top of stack. */ + if (--stack_elt < 0) + abort (); + return stack[stack_elt]; +} +#endif + +/* Decode DWARF 2 call frame information. Takes pointers the + instruction sequence to decode, current register information and + CIE info, and the PC range to evaluate. */ + +static void +execute_cfa_program (const unsigned char *insn_ptr, + const unsigned char *insn_end, + struct _Unwind_Context *context, + _Unwind_FrameState *fs) +{ + struct frame_state_reg_info *unused_rs = NULL; + + /* Don't allow remember/restore between CIE and FDE programs. */ + fs->regs.prev = NULL; + + while (insn_ptr < insn_end && fs->pc < context->ra) + { + unsigned char insn = *insn_ptr++; + _Unwind_Word reg; + _Unwind_Sword offset; + _Unwind_Ptr ptrtmp; + + if (insn & DW_CFA_advance_loc) + fs->pc += (insn & 0x3f) * fs->code_align; + else if (insn & DW_CFA_offset) + { + reg = insn & 0x3f; + insn_ptr = read_uleb128 (insn_ptr, &ptrtmp); + offset = ptrtmp * fs->data_align; + fs->regs.reg[reg].how = REG_SAVED_OFFSET; + fs->regs.reg[reg].loc.offset = offset; + } + else if (insn & DW_CFA_restore) + { + reg = insn & 0x3f; + fs->regs.reg[reg].how = REG_UNSAVED; + } + else switch (insn) + { + case DW_CFA_set_loc: + insn_ptr = read_encoded_value (context, fs->fde_encoding, + insn_ptr, (_Unwind_Ptr *) &fs->pc); + break; + + case DW_CFA_advance_loc1: + fs->pc += read_1u (insn_ptr) * fs->code_align; + insn_ptr += 1; + break; + case DW_CFA_advance_loc2: + fs->pc += read_2u (insn_ptr) * fs->code_align; + insn_ptr += 2; + break; + case DW_CFA_advance_loc4: + fs->pc += read_4u (insn_ptr) * fs->code_align; + insn_ptr += 4; + break; + + case DW_CFA_offset_extended: + insn_ptr = read_uleb128 (insn_ptr, &ptrtmp); reg = ptrtmp; + insn_ptr = read_uleb128 (insn_ptr, &ptrtmp); + offset = ptrtmp * fs->data_align; + fs->regs.reg[reg].how = REG_SAVED_OFFSET; + fs->regs.reg[reg].loc.offset = offset; + break; + + case DW_CFA_restore_extended: + insn_ptr = read_uleb128 (insn_ptr, &ptrtmp); reg = ptrtmp; + fs->regs.reg[reg].how = REG_UNSAVED; + break; + + case DW_CFA_undefined: + case DW_CFA_same_value: + case DW_CFA_nop: + break; + + case DW_CFA_register: + { + _Unwind_Word reg2; + insn_ptr = read_uleb128 (insn_ptr, &ptrtmp); reg = ptrtmp; + insn_ptr = read_uleb128 (insn_ptr, &ptrtmp); reg2 = ptrtmp; + fs->regs.reg[reg].how = REG_SAVED_REG; + fs->regs.reg[reg].loc.reg = reg2; + } + break; + + case DW_CFA_remember_state: + { + struct frame_state_reg_info *new_rs; + if (unused_rs) + { + new_rs = unused_rs; + unused_rs = unused_rs->prev; + } + else + new_rs = alloca (sizeof (struct frame_state_reg_info)); + + *new_rs = fs->regs; + fs->regs.prev = new_rs; + } + break; + + case DW_CFA_restore_state: + { + struct frame_state_reg_info *old_rs = fs->regs.prev; + fs->regs = *old_rs; + old_rs->prev = unused_rs; + unused_rs = old_rs; + } + break; + + case DW_CFA_def_cfa: + insn_ptr = read_uleb128 (insn_ptr, &ptrtmp); + fs->cfa_reg = ptrtmp; + insn_ptr = read_uleb128 (insn_ptr, &ptrtmp); + fs->cfa_offset = ptrtmp; + fs->cfa_how = CFA_REG_OFFSET; + break; + + case DW_CFA_def_cfa_register: + insn_ptr = read_uleb128 (insn_ptr, &ptrtmp); + fs->cfa_reg = ptrtmp; + fs->cfa_how = CFA_REG_OFFSET; + break; + + case DW_CFA_def_cfa_offset: + insn_ptr = read_uleb128 (insn_ptr, &ptrtmp); + fs->cfa_offset = ptrtmp; + /* cfa_how deliberately not set. */ + break; + + case DW_CFA_def_cfa_expression: + insn_ptr = read_uleb128 (insn_ptr, &ptrtmp); + fs->cfa_exp = insn_ptr; + fs->cfa_how = CFA_EXP; + insn_ptr += ptrtmp; + break; + + case DW_CFA_expression: + insn_ptr = read_uleb128 (insn_ptr, &ptrtmp); reg = ptrtmp; + insn_ptr = read_uleb128 (insn_ptr, &ptrtmp); + fs->regs.reg[reg].how = REG_SAVED_EXP; + fs->regs.reg[reg].loc.exp = insn_ptr; + insn_ptr += ptrtmp; + break; + + /* From the 2.1 draft. */ + case DW_CFA_offset_extended_sf: + insn_ptr = read_uleb128 (insn_ptr, &ptrtmp); reg = ptrtmp; + insn_ptr = read_sleb128 (insn_ptr, &ptrtmp); + offset = (saddr)ptrtmp * fs->data_align; + fs->regs.reg[reg].how = REG_SAVED_OFFSET; + fs->regs.reg[reg].loc.offset = offset; + break; + + case DW_CFA_def_cfa_sf: + insn_ptr = read_uleb128 (insn_ptr, &ptrtmp); + fs->cfa_reg = ptrtmp; + insn_ptr = read_sleb128 (insn_ptr, &ptrtmp); + fs->cfa_offset = (saddr)ptrtmp; + fs->cfa_how = CFA_REG_OFFSET; + break; + + case DW_CFA_def_cfa_offset_sf: + insn_ptr = read_uleb128 (insn_ptr, &ptrtmp); + fs->cfa_offset = ptrtmp; + /* cfa_how deliberately not set. */ + break; + + case DW_CFA_GNU_window_save: + /* ??? Hardcoded for SPARC register window configuration. */ + for (reg = 16; reg < 32; ++reg) + { + fs->regs.reg[reg].how = REG_SAVED_OFFSET; + fs->regs.reg[reg].loc.offset = (reg - 16) * sizeof (void *); + } + break; + + case DW_CFA_GNU_args_size: + insn_ptr = read_uleb128 (insn_ptr, &ptrtmp); + context->args_size = ptrtmp; + break; + + case DW_CFA_GNU_negative_offset_extended: + /* Obsoleted by DW_CFA_offset_extended_sf, but used by + older PowerPC code. */ + insn_ptr = read_uleb128 (insn_ptr, &ptrtmp); reg = ptrtmp; + insn_ptr = read_uleb128 (insn_ptr, &ptrtmp); + offset = ptrtmp * fs->data_align; + fs->regs.reg[reg].how = REG_SAVED_OFFSET; + fs->regs.reg[reg].loc.offset = -offset; + break; + + default: + abort (); + } + } +} + +static _Unwind_Reason_Code +uw_frame_state_for (struct _Unwind_Context *context, _Unwind_FrameState *fs) +{ + struct dwarf_fde *fde; + struct dwarf_cie *cie; + const unsigned char *aug, *insn, *end; + + memset (fs, 0, sizeof (*fs)); + context->args_size = 0; + context->lsda = 0; + + fde = _Unwind_Find_FDE (context->ra - 1, &context->bases); + if (fde == NULL) + { + /* Couldn't find frame unwind info for this function. Try a + target-specific fallback mechanism. This will necessarily + not profide a personality routine or LSDA. */ +#ifdef MD_FALLBACK_FRAME_STATE_FOR + MD_FALLBACK_FRAME_STATE_FOR (context, fs, success); + return _URC_END_OF_STACK; + success: + return _URC_NO_REASON; +#else + return _URC_END_OF_STACK; +#endif + } + + fs->pc = context->bases.func; + + cie = get_cie (fde); + insn = extract_cie_info (cie, context, fs); + if (insn == NULL) + /* CIE contained unknown augmentation. */ + return _URC_FATAL_PHASE1_ERROR; + + /* First decode all the insns in the CIE. */ + end = (unsigned char *) next_fde ((struct dwarf_fde *) cie); + execute_cfa_program (insn, end, context, fs); + + /* Locate augmentation for the fde. */ + aug = (unsigned char *)fde + sizeof (*fde); + aug += 2 * size_of_encoded_value (fs->fde_encoding); + insn = NULL; + if (fs->saw_z) + { + _Unwind_Ptr i; + aug = read_uleb128 (aug, &i); + insn = aug + i; + } + if (fs->lsda_encoding != DW_EH_PE_omit) + aug = read_encoded_value (context, fs->lsda_encoding, aug, + (_Unwind_Ptr *) &context->lsda); + + /* Then the insns in the FDE up to our target PC. */ + if (insn == NULL) + insn = aug; + end = (unsigned char *) next_fde (fde); + execute_cfa_program (insn, end, context, fs); + + return _URC_NO_REASON; +} + +typedef struct frame_state +{ + void *cfa; + void *eh_ptr; + long cfa_offset; + long args_size; + long reg_or_offset[DWARF_FRAME_REGISTERS+1]; + unsigned short cfa_reg; + unsigned short retaddr_column; + char saved[DWARF_FRAME_REGISTERS+1]; +} frame_state; + +struct frame_state * __frame_state_for (void *, struct frame_state *); + +/* Called from pre-G++ 3.0 __throw to find the registers to restore for + a given PC_TARGET. The caller should allocate a local variable of + `struct frame_state' and pass its address to STATE_IN. */ + +struct frame_state * +__frame_state_for (void *pc_target, struct frame_state *state_in) +{ + struct _Unwind_Context context; + _Unwind_FrameState fs; + int reg; + + memset (&context, 0, sizeof (struct _Unwind_Context)); + context.ra = pc_target + 1; + + if (uw_frame_state_for (&context, &fs) != _URC_NO_REASON) + return 0; + + /* We have no way to pass a location expression for the CFA to our + caller. It wouldn't understand it anyway. */ + if (fs.cfa_how == CFA_EXP) + return 0; + + for (reg = 0; reg < DWARF_FRAME_REGISTERS + 1; reg++) + { + state_in->saved[reg] = fs.regs.reg[reg].how; + switch (state_in->saved[reg]) + { + case REG_SAVED_REG: + state_in->reg_or_offset[reg] = fs.regs.reg[reg].loc.reg; + break; + case REG_SAVED_OFFSET: + state_in->reg_or_offset[reg] = fs.regs.reg[reg].loc.offset; + break; + default: + state_in->reg_or_offset[reg] = 0; + break; + } + } + + state_in->cfa_offset = fs.cfa_offset; + state_in->cfa_reg = fs.cfa_reg; + state_in->retaddr_column = fs.retaddr_column; + state_in->args_size = context.args_size; + state_in->eh_ptr = fs.eh_ptr; + + return state_in; +} + +#ifndef _LIBC + +static void +uw_update_context_1 (struct _Unwind_Context *context, _Unwind_FrameState *fs) +{ + struct _Unwind_Context orig_context = *context; + void *cfa; + long i; + + /* Compute this frame's CFA. */ + switch (fs->cfa_how) + { + case CFA_REG_OFFSET: + /* Special handling here: Many machines do not use a frame pointer, + and track the CFA only through offsets from the stack pointer from + one frame to the next. In this case, the stack pointer is never + stored, so it has no saved address in the context. What we do + have is the CFA from the previous stack frame. */ + if (context->reg[fs->cfa_reg] == NULL) + cfa = context->cfa; + else + cfa = (void *) (_Unwind_Ptr) _Unwind_GetGR (context, fs->cfa_reg); + cfa += fs->cfa_offset; + break; + + case CFA_EXP: + /* ??? No way of knowing what register number is the stack pointer + to do the same sort of handling as above. Assume that if the + CFA calculation is so complicated as to require a stack program + that this will not be a problem. */ + { + const unsigned char *exp = fs->cfa_exp; + _Unwind_Ptr len; + + exp = read_uleb128 (exp, &len); + cfa = (void *) (_Unwind_Ptr) + execute_stack_op (exp, exp + len, context, 0); + break; + } + + default: + abort (); + } + context->cfa = cfa; + + /* Compute the addresses of all registers saved in this frame. */ + for (i = 0; i < DWARF_FRAME_REGISTERS + 1; ++i) + switch (fs->regs.reg[i].how) + { + case REG_UNSAVED: + break; + case REG_SAVED_OFFSET: + context->reg[i] = cfa + fs->regs.reg[i].loc.offset; + break; + case REG_SAVED_REG: + context->reg[i] = orig_context.reg[fs->regs.reg[i].loc.reg]; + break; + case REG_SAVED_EXP: + { + const unsigned char *exp = fs->regs.reg[i].loc.exp; + _Unwind_Ptr len; + _Unwind_Ptr val; + + exp = read_uleb128 (exp, &len); + val = execute_stack_op (exp, exp + len, &orig_context, + (_Unwind_Ptr) cfa); + context->reg[i] = (void *) val; + } + break; + } +} + +static void +uw_update_context (struct _Unwind_Context *context, _Unwind_FrameState *fs) +{ + uw_update_context_1 (context, fs); + + /* Compute the return address now, since the return address column + can change from frame to frame. */ + context->ra = __builtin_extract_return_addr + ((void *) (_Unwind_Ptr) _Unwind_GetGR (context, fs->retaddr_column)); +} + +/* Fill in CONTEXT for top-of-stack. The only valid registers at this + level will be the return address and the CFA. */ + +#define uw_init_context(CONTEXT) \ +do { \ + /* Do any necessary initialization to access arbitrary stack frames. \ + On the SPARC, this means flushing the register windows. */ \ + __builtin_unwind_init (); \ + uw_init_context_1 (CONTEXT, __builtin_dwarf_cfa (), \ + __builtin_return_address (0)); \ +} while (0) + +static void +uw_init_context_1 (struct _Unwind_Context *context, + void *outer_cfa, void *outer_ra) +{ + void *ra = __builtin_extract_return_addr (__builtin_return_address (0)); + _Unwind_FrameState fs; + + memset (context, 0, sizeof (struct _Unwind_Context)); + context->ra = ra; + + if (uw_frame_state_for (context, &fs) != _URC_NO_REASON) + abort (); + + /* Force the frame state to use the known cfa value. */ + context->cfa = outer_cfa; + fs.cfa_how = CFA_REG_OFFSET; + fs.cfa_reg = 0; + fs.cfa_offset = 0; + + uw_update_context_1 (context, &fs); + + /* If the return address column was saved in a register in the + initialization context, then we can't see it in the given + call frame data. So have the initialization context tell us. */ + context->ra = __builtin_extract_return_addr (outer_ra); +} + + +/* Install TARGET into CURRENT so that we can return to it. This is a + macro because __builtin_eh_return must be invoked in the context of + our caller. */ + +#define uw_install_context(CURRENT, TARGET) \ +do { \ + long offset = uw_install_context_1 ((CURRENT), (TARGET)); \ + void *handler = __builtin_frob_return_addr ((TARGET)->ra); \ + __builtin_eh_return (offset, handler); \ +} while (0) + +static inline void +init_dwarf_reg_size_table (void) +{ + __builtin_init_dwarf_reg_size_table (dwarf_reg_size_table); +} + +static long +uw_install_context_1 (struct _Unwind_Context *current, + struct _Unwind_Context *target) +{ + long i; + +#if __GTHREADS + { + static __gthread_once_t once_regsizes = __GTHREAD_ONCE_INIT; + if (__gthread_once (&once_regsizes, init_dwarf_reg_size_table) != 0 + || dwarf_reg_size_table[0] == 0) + init_dwarf_reg_size_table (); + } +#else + if (dwarf_reg_size_table[0] == 0) + init_dwarf_reg_size_table (); +#endif + + for (i = 0; i < DWARF_FRAME_REGISTERS; ++i) + { + void *c = current->reg[i]; + void *t = target->reg[i]; + if (t && c && t != c) + memcpy (c, t, dwarf_reg_size_table[i]); + } + + /* We adjust SP by the difference between CURRENT and TARGET's CFA. */ + if (STACK_GROWS_DOWNWARD) + return target->cfa - current->cfa + target->args_size; + else + return current->cfa - target->cfa - target->args_size; +} + +static inline _Unwind_Ptr +uw_identify_context (struct _Unwind_Context *context) +{ + return _Unwind_GetIP (context); +} + + +#include "unwind.inc" + +#endif /* _LIBC */ +#endif /* !USING_SJLJ_EXCEPTIONS */ diff --git a/sysdeps/generic/unwind-pe.h b/sysdeps/generic/unwind-pe.h new file mode 100644 index 0000000000..e4a564e3e1 --- /dev/null +++ b/sysdeps/generic/unwind-pe.h @@ -0,0 +1,272 @@ +/* Exception handling and frame unwind runtime interface routines. + Copyright (C) 2001 Free Software Foundation, Inc. + + 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. */ + +/* @@@ Really this should be out of line, but this also causes link + compatibility problems with the base ABI. This is slightly better + than duplicating code, however. */ + +/* If using C++, references to abort have to be qualified with std::. */ +#if __cplusplus +#define __gxx_abort std::abort +#else +#define __gxx_abort abort +#endif + +/* Pointer encodings, from dwarf2.h. */ +#define DW_EH_PE_absptr 0x00 +#define DW_EH_PE_omit 0xff + +#define DW_EH_PE_uleb128 0x01 +#define DW_EH_PE_udata2 0x02 +#define DW_EH_PE_udata4 0x03 +#define DW_EH_PE_udata8 0x04 +#define DW_EH_PE_sleb128 0x09 +#define DW_EH_PE_sdata2 0x0A +#define DW_EH_PE_sdata4 0x0B +#define DW_EH_PE_sdata8 0x0C +#define DW_EH_PE_signed 0x08 + +#define DW_EH_PE_pcrel 0x10 +#define DW_EH_PE_textrel 0x20 +#define DW_EH_PE_datarel 0x30 +#define DW_EH_PE_funcrel 0x40 +#define DW_EH_PE_aligned 0x50 + +#define DW_EH_PE_indirect 0x80 + + +/* Given an encoding, return the number of bytes the format occupies. + This is only defined for fixed-size encodings, and so does not + include leb128. */ + +#ifndef _LIBC +static +#endif +unsigned int +size_of_encoded_value (unsigned char encoding) +#if defined(_LIBC) && !defined(NO_BASE_OF_ENCODED_VALUE) +; +#else +{ + if (encoding == DW_EH_PE_omit) + return 0; + + switch (encoding & 0x07) + { + case DW_EH_PE_absptr: + return sizeof (void *); + case DW_EH_PE_udata2: + return 2; + case DW_EH_PE_udata4: + return 4; + case DW_EH_PE_udata8: + return 8; + } + __gxx_abort (); +} +#endif + +#ifndef NO_BASE_OF_ENCODED_VALUE + +/* Given an encoding and an _Unwind_Context, return the base to which + the encoding is relative. This base may then be passed to + read_encoded_value_with_base for use when the _Unwind_Context is + not available. */ + +static _Unwind_Ptr +base_of_encoded_value (unsigned char encoding, struct _Unwind_Context *context) +{ + 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_GetTextRelBase (context); + case DW_EH_PE_datarel: + return _Unwind_GetDataRelBase (context); + case DW_EH_PE_funcrel: + return _Unwind_GetRegionStart (context); + } + __gxx_abort (); +} + +#endif + +/* Load an encoded value from memory at P. The value is returned in VAL; + The function returns P incremented past the value. BASE is as given + by base_of_encoded_value for this encoding in the appropriate context. */ + +#ifndef _LIBC +static +#endif +const unsigned char * +read_encoded_value_with_base (unsigned char encoding, _Unwind_Ptr base, + const unsigned char *p, _Unwind_Ptr *val) +#if defined(_LIBC) && !defined(NO_BASE_OF_ENCODED_VALUE) +; +#else +{ + union unaligned + { + void *ptr; + unsigned u2 __attribute__ ((mode (HI))); + unsigned u4 __attribute__ ((mode (SI))); + unsigned u8 __attribute__ ((mode (DI))); + signed s2 __attribute__ ((mode (HI))); + signed s4 __attribute__ ((mode (SI))); + signed s8 __attribute__ ((mode (DI))); + } __attribute__((__packed__)); + + union unaligned *u = (union unaligned *) p; + _Unwind_Ptr result; + + if (encoding == DW_EH_PE_aligned) + { + _Unwind_Ptr a = (_Unwind_Ptr)p; + a = (a + sizeof (void *) - 1) & - sizeof(void *); + result = *(_Unwind_Ptr *) a; + p = (const unsigned char *)(a + sizeof (void *)); + } + else + { + switch (encoding & 0x0f) + { + case DW_EH_PE_absptr: + result = (_Unwind_Ptr) u->ptr; + p += sizeof (void *); + break; + + case DW_EH_PE_uleb128: + { + unsigned int shift = 0; + unsigned char byte; + + result = 0; + do + { + byte = *p++; + result |= (_Unwind_Ptr)(byte & 0x7f) << shift; + shift += 7; + } + while (byte & 0x80); + } + break; + + case DW_EH_PE_sleb128: + { + unsigned int shift = 0; + unsigned char byte; + + result = 0; + do + { + byte = *p++; + result |= (_Unwind_Ptr)(byte & 0x7f) << shift; + shift += 7; + } + while (byte & 0x80); + + if (shift < 8 * sizeof(result) && (byte & 0x40) != 0) + result |= -(1L << shift); + } + break; + + case DW_EH_PE_udata2: + result = u->u2; + p += 2; + break; + case DW_EH_PE_udata4: + result = u->u4; + p += 4; + break; + case DW_EH_PE_udata8: + result = u->u8; + p += 8; + break; + + case DW_EH_PE_sdata2: + result = u->s2; + p += 2; + break; + case DW_EH_PE_sdata4: + result = u->s4; + p += 4; + break; + case DW_EH_PE_sdata8: + result = u->s8; + p += 8; + break; + + default: + __gxx_abort (); + } + + if (result != 0) + { + result += ((encoding & 0x70) == DW_EH_PE_pcrel + ? (_Unwind_Ptr)u : base); + if (encoding & DW_EH_PE_indirect) + result = *(_Unwind_Ptr *)result; + } + } + + *val = result; + return p; +} +#endif + +#ifndef NO_BASE_OF_ENCODED_VALUE + +/* Like read_encoded_value_with_base, but get the base from the context + rather than providing it directly. */ + +static inline const unsigned char * +read_encoded_value (struct _Unwind_Context *context, unsigned char encoding, + const unsigned char *p, _Unwind_Ptr *val) +{ + return read_encoded_value_with_base (encoding, + base_of_encoded_value (encoding, context), + p, val); +} + +#endif + +/* Read an unsigned leb128 value from P, store the value in VAL, return + P incremented past the value. */ + +static inline const unsigned char * +read_uleb128 (const unsigned char *p, _Unwind_Ptr *val) +{ + return read_encoded_value_with_base (DW_EH_PE_uleb128, 0, p, val); +} + +/* Similar, but read a signed leb128 value. */ + +static inline const unsigned char * +read_sleb128 (const unsigned char *p, _Unwind_Ptr *val) +{ + return read_encoded_value_with_base (DW_EH_PE_sleb128, 0, p, val); +} diff --git a/sysdeps/generic/unwind.h b/sysdeps/generic/unwind.h new file mode 100644 index 0000000000..ce43365a31 --- /dev/null +++ b/sysdeps/generic/unwind.h @@ -0,0 +1,191 @@ +/* Exception handling and frame unwind runtime interface routines. + Copyright (C) 2001 Free Software Foundation, Inc. + + 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. */ + +/* This is derived from the C++ ABI for IA-64. Where we diverge + for cross-architecture compatibility are noted with "@@@". */ + +#ifdef __cplusplus +extern "C" { +#endif + +/* Level 1: Base ABI */ + +/* @@@ The IA-64 ABI uses uint64 throughout. Most places this is + inefficient for 32-bit and smaller machines. */ +typedef unsigned _Unwind_Word __attribute__((__mode__(__word__))); +typedef signed _Unwind_Sword __attribute__((__mode__(__word__))); +typedef unsigned _Unwind_Ptr __attribute__((__mode__(__pointer__))); + +/* @@@ The IA-64 ABI uses a 64-bit word to identify the producer and + consumer of an exception. We'll go along with this for now even on + 32-bit machines. We'll need to provide some other option for + 16-bit machines and for machines with > 8 bits per byte. */ +typedef unsigned _Unwind_Exception_Class __attribute__((__mode__(__DI__))); + +/* The unwind interface uses reason codes in several contexts to + identify the reasons for failures or other actions. */ +typedef enum +{ + _URC_NO_REASON = 0, + _URC_FOREIGN_EXCEPTION_CAUGHT = 1, + _URC_FATAL_PHASE2_ERROR = 2, + _URC_FATAL_PHASE1_ERROR = 3, + _URC_NORMAL_STOP = 4, + _URC_END_OF_STACK = 5, + _URC_HANDLER_FOUND = 6, + _URC_INSTALL_CONTEXT = 7, + _URC_CONTINUE_UNWIND = 8 +} _Unwind_Reason_Code; + + +/* The unwind interface uses a pointer to an exception header object + as its representation of an exception being thrown. In general, the + full representation of an exception object is language- and + implementation-specific, but it will be prefixed by a header + understood by the unwind interface. */ + +struct _Unwind_Exception; + +typedef void (*_Unwind_Exception_Cleanup_Fn) (_Unwind_Reason_Code, + struct _Unwind_Exception *); + +struct _Unwind_Exception +{ + _Unwind_Exception_Class exception_class; + _Unwind_Exception_Cleanup_Fn exception_cleanup; + _Unwind_Word private_1; + _Unwind_Word private_2; + + /* @@@ The IA-64 ABI says that this structure must be double-word aligned. + Taking that literally does not make much sense generically. Instead we + provide the maximum alignment required by any type for the machine. */ +} __attribute__((__aligned__)); + + +/* The ACTIONS argument to the personality routine is a bitwise OR of one + or more of the following constants. */ +typedef int _Unwind_Action; + +#define _UA_SEARCH_PHASE 1 +#define _UA_CLEANUP_PHASE 2 +#define _UA_HANDLER_FRAME 4 +#define _UA_FORCE_UNWIND 8 + +/* This is an opaque type used to refer to a system-specific data + structure used by the system unwinder. This context is created and + destroyed by the system, and passed to the personality routine + during unwinding. */ +struct _Unwind_Context; + +/* Raise an exception, passing along the given exception object. */ +extern _Unwind_Reason_Code _Unwind_RaiseException (struct _Unwind_Exception *); + +/* Raise an exception for forced unwinding. */ + +typedef _Unwind_Reason_Code (*_Unwind_Stop_Fn) + (int, _Unwind_Action, _Unwind_Exception_Class, + struct _Unwind_Exception *, struct _Unwind_Context *, void *); + +extern _Unwind_Reason_Code _Unwind_ForcedUnwind (struct _Unwind_Exception *, + _Unwind_Stop_Fn, + void *); + +/* Helper to invoke the exception_cleanup routine. */ +extern void _Unwind_DeleteException (struct _Unwind_Exception *); + +/* Resume propagation of an existing exception. This is used after + e.g. executing cleanup code, and not to implement rethrowing. */ +extern void _Unwind_Resume (struct _Unwind_Exception *); + +/* These functions are used for communicating information about the unwind + context (i.e. the unwind descriptors and the user register state) between + the unwind library and the personality routine and landing pad. Only + selected registers maybe manipulated. */ + +extern _Unwind_Word _Unwind_GetGR (struct _Unwind_Context *, int); +extern void _Unwind_SetGR (struct _Unwind_Context *, int, _Unwind_Word); + +extern _Unwind_Ptr _Unwind_GetIP (struct _Unwind_Context *); +extern void _Unwind_SetIP (struct _Unwind_Context *, _Unwind_Ptr); + +extern void *_Unwind_GetLanguageSpecificData (struct _Unwind_Context *); + +extern _Unwind_Ptr _Unwind_GetRegionStart (struct _Unwind_Context *); + + +/* The personality routine is the function in the C++ (or other language) + runtime library which serves as an interface between the system unwind + library and language-specific exception handling semantics. It is + specific to the code fragment described by an unwind info block, and + it is always referenced via the pointer in the unwind info block, and + hence it has no ABI-specified name. + + Note that this implies that two different C++ implementations can + use different names, and have different contents in the language + specific data area. Moreover, that the language specific data + area contains no version info because name of the function invoked + provides more effective versioning by detecting at link time the + lack of code to handle the different data format. */ + +typedef _Unwind_Reason_Code (*_Unwind_Personality_Fn) + (int, _Unwind_Action, _Unwind_Exception_Class, + struct _Unwind_Exception *, struct _Unwind_Context *); + +/* @@@ The following alternate entry points are for setjmp/longjmp + based unwinding. */ + +struct SjLj_Function_Context; +extern void _Unwind_SjLj_Register (struct SjLj_Function_Context *); +extern void _Unwind_SjLj_Unregister (struct SjLj_Function_Context *); + +extern _Unwind_Reason_Code _Unwind_SjLj_RaiseException + (struct _Unwind_Exception *); +extern _Unwind_Reason_Code _Unwind_SjLj_ForcedUnwind + (struct _Unwind_Exception *, _Unwind_Stop_Fn, void *); +extern void _Unwind_SjLj_Resume (struct _Unwind_Exception *); + +/* @@@ The following provide access to the base addresses for text + and data-relative addressing in the LDSA. In order to stay link + compatible with the standard ABI for IA-64, we inline these. */ + +#ifdef __ia64__ +#include <stdlib.h> + +static inline _Unwind_Ptr +_Unwind_GetDataRelBase (struct _Unwind_Context *_C) +{ + /* The GP is stored in R1. */ + return _Unwind_GetGR (_C, 1); +} + +static inline _Unwind_Ptr +_Unwind_GetTextRelBase (struct _Unwind_Context *_C) +{ + abort (); + return 0; +} +#else +extern _Unwind_Ptr _Unwind_GetDataRelBase (struct _Unwind_Context *); +extern _Unwind_Ptr _Unwind_GetTextRelBase (struct _Unwind_Context *); +#endif + +#ifdef __cplusplus +} +#endif diff --git a/sysdeps/hppa/gccframe.h b/sysdeps/hppa/gccframe.h new file mode 100644 index 0000000000..65e44dfd73 --- /dev/null +++ b/sysdeps/hppa/gccframe.h @@ -0,0 +1,23 @@ +/* Definition of object in frame unwind info. hppa version. + Copyright (C) 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* Note: For hppa64 this is 61 */ +#define DWARF_FRAME_REGISTERS 89 + +#include <sysdeps/generic/gccframe.h> diff --git a/sysdeps/i386/gccframe.h b/sysdeps/i386/gccframe.h new file mode 100644 index 0000000000..412fa974de --- /dev/null +++ b/sysdeps/i386/gccframe.h @@ -0,0 +1,28 @@ +/* Definition of object in frame unwind info. i386 version. + Copyright (C) 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#define DWARF_FRAME_REGISTERS 17 + +#define CRT_GET_RFIB_DATA(BASE) \ + { \ + register void *__ebx __asm__("ebx");\ + BASE = __ebx; \ + } + +#include <sysdeps/generic/gccframe.h> diff --git a/sysdeps/m68k/gccframe.h b/sysdeps/m68k/gccframe.h new file mode 100644 index 0000000000..452f53f626 --- /dev/null +++ b/sysdeps/m68k/gccframe.h @@ -0,0 +1,22 @@ +/* Definition of object in frame unwind info. m68k version. + Copyright (C) 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#define FIRST_PSEUDO_REGISTER 24 + +#include <sysdeps/generic/gccframe.h> diff --git a/sysdeps/mach/hurd/configure b/sysdeps/mach/hurd/configure index fb91f88100..36d0c08b6a 100755 --- a/sysdeps/mach/hurd/configure +++ b/sysdeps/mach/hurd/configure @@ -9,3 +9,11 @@ inhibit_glue=yes if test "x$prefix" != x; then echo "configure: warning: --prefix= (empty) is required for GNU/Hurd to work normally" 1>&2 fi + +case "$machine" in + i386*) + if test -z "$oldest_abi" || test "$oldest_abi" < "2.2.5"; then + libc_cv_gcc_unwind_find_fde=yes + fi + ;; +esac diff --git a/sysdeps/mach/hurd/configure.in b/sysdeps/mach/hurd/configure.in index 7daa188713..b271d4a810 100644 --- a/sysdeps/mach/hurd/configure.in +++ b/sysdeps/mach/hurd/configure.in @@ -11,3 +11,11 @@ inhibit_glue=yes if test "x$prefix" != x; then AC_MSG_WARN([--prefix= (empty) is required for GNU/Hurd to work normally]) fi + +case "$machine" in + i386*) + if test -z "$oldest_abi" || test "$oldest_abi" < "2.2.5"; then + libc_cv_gcc_unwind_find_fde=yes + fi + ;; +esac diff --git a/sysdeps/mach/hurd/i386/Makefile b/sysdeps/mach/hurd/i386/Makefile new file mode 100644 index 0000000000..61fac29c9a --- /dev/null +++ b/sysdeps/mach/hurd/i386/Makefile @@ -0,0 +1,7 @@ +ifeq ($(subdir),elf) +ifeq (yes,$(build-shared)) +# This is needed to support g++ v2 and v3. +sysdep_routines += framestate +shared-only-routines += framestate +endif +endif diff --git a/sysdeps/mach/hurd/i386/Versions b/sysdeps/mach/hurd/i386/Versions index 2d3061bad5..5731d9e01e 100644 --- a/sysdeps/mach/hurd/i386/Versions +++ b/sysdeps/mach/hurd/i386/Versions @@ -2,7 +2,6 @@ libc { GLIBC_2.0 { # Exception handling support functions from libgcc __register_frame; __register_frame_table; __deregister_frame; - __register_frame_info; __deregister_frame_info; __frame_state_for; - __register_frame_info_table; + __frame_state_for; __register_frame_info_table; } } diff --git a/sysdeps/mips/gccframe.h b/sysdeps/mips/gccframe.h new file mode 100644 index 0000000000..ec9311caca --- /dev/null +++ b/sysdeps/mips/gccframe.h @@ -0,0 +1,22 @@ +/* Definition of object in frame unwind info. mips version. + Copyright (C) 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#define FIRST_PSEUDO_REGISTER 76 + +#include <sysdeps/generic/gccframe.h> diff --git a/sysdeps/powerpc/gccframe.h b/sysdeps/powerpc/gccframe.h new file mode 100644 index 0000000000..d08e80f18e --- /dev/null +++ b/sysdeps/powerpc/gccframe.h @@ -0,0 +1,22 @@ +/* Definition of object in frame unwind info. powerpc version. + Copyright (C) 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#define DWARF_FRAME_REGISTERS 77 + +#include <sysdeps/generic/gccframe.h> diff --git a/sysdeps/s390/gccframe.h b/sysdeps/s390/gccframe.h new file mode 100644 index 0000000000..2f624b8f5a --- /dev/null +++ b/sysdeps/s390/gccframe.h @@ -0,0 +1,22 @@ +/* Definition of object in frame unwind info. s390 version. + Copyright (C) 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#define FIRST_PSEUDO_REGISTER 34 + +#include <sysdeps/generic/gccframe.h> diff --git a/sysdeps/sh/gccframe.h b/sysdeps/sh/gccframe.h new file mode 100644 index 0000000000..ad392741c4 --- /dev/null +++ b/sysdeps/sh/gccframe.h @@ -0,0 +1,22 @@ +/* Definition of object in frame unwind info. sh version. + Copyright (C) 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#define DWARF_FRAME_REGISTERS 49 + +#include <sysdeps/generic/gccframe.h> diff --git a/sysdeps/sparc/gccframe.h b/sysdeps/sparc/gccframe.h new file mode 100644 index 0000000000..236baab14a --- /dev/null +++ b/sysdeps/sparc/gccframe.h @@ -0,0 +1,22 @@ +/* Definition of object in frame unwind info. sparc version. + Copyright (C) 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#define FIRST_PSEUDO_REGISTER 101 + +#include <sysdeps/generic/gccframe.h> diff --git a/sysdeps/unix/sysv/linux/alpha/Makefile b/sysdeps/unix/sysv/linux/alpha/Makefile index 62536ae1ae..5c04677086 100644 --- a/sysdeps/unix/sysv/linux/alpha/Makefile +++ b/sysdeps/unix/sysv/linux/alpha/Makefile @@ -23,3 +23,11 @@ ifeq ($(subdir),signal) sysdep_routines += rt_sigsuspend rt_sigprocmask rt_sigtimedwait \ rt_sigqueueinfo rt_sigaction rt_sigpending endif + +ifeq ($(subdir),elf) +ifeq (yes,$(build-shared)) +# This is needed to support g++ v2 and v3. +sysdep_routines += framestate +shared-only-routines += framestate +endif +endif diff --git a/sysdeps/unix/sysv/linux/alpha/Versions b/sysdeps/unix/sysv/linux/alpha/Versions index d89ef6a061..c18816ca6f 100644 --- a/sysdeps/unix/sysv/linux/alpha/Versions +++ b/sysdeps/unix/sysv/linux/alpha/Versions @@ -6,8 +6,7 @@ libc { # Exception handling support functions from libgcc __register_frame; __register_frame_table; __deregister_frame; - __register_frame_info; __deregister_frame_info; __frame_state_for; - __register_frame_info_table; + __frame_state_for; __register_frame_info_table; # b* bus_base; bus_base_sparse; diff --git a/sysdeps/unix/sysv/linux/arm/Makefile b/sysdeps/unix/sysv/linux/arm/Makefile index aeaaa39fce..66a93ba8f3 100644 --- a/sysdeps/unix/sysv/linux/arm/Makefile +++ b/sysdeps/unix/sysv/linux/arm/Makefile @@ -19,4 +19,10 @@ sysdep-dl-routines += dl-procinfo sysdep_routines += dl-procinfo # extra shared linker files to link only into dl-allobjs.so sysdep-rtld-routines += dl-procinfo + +ifeq (yes,$(build-shared)) +# This is needed to support g++ v2 and v3. +sysdep_routines += framestate +shared-only-routines += framestate +endif endif diff --git a/sysdeps/unix/sysv/linux/arm/Versions b/sysdeps/unix/sysv/linux/arm/Versions index aeda9fa5fb..32cb185505 100644 --- a/sysdeps/unix/sysv/linux/arm/Versions +++ b/sysdeps/unix/sysv/linux/arm/Versions @@ -2,8 +2,7 @@ libc { GLIBC_2.0 { # Exception handling support functions from libgcc __register_frame; __register_frame_table; __deregister_frame; - __register_frame_info; __deregister_frame_info; __frame_state_for; - __register_frame_info_table; + __frame_state_for; __register_frame_info_table; } GLIBC_2.1 { ioperm; iopl; diff --git a/sysdeps/unix/sysv/linux/configure b/sysdeps/unix/sysv/linux/configure index db1666d258..72fa8430ac 100644 --- a/sysdeps/unix/sysv/linux/configure +++ b/sysdeps/unix/sysv/linux/configure @@ -54,6 +54,11 @@ fi case "$machine" in alpha*) arch_minimum_kernel=2.1.100 + libc_cv_gcc_unwind_find_fde=yes + ;; + i386*) + libc_cv_gcc_unwind_find_fde=yes + arch_minimum_kernel=2.0.10 ;; ia64*) arch_minimum_kernel=2.4.0 @@ -63,9 +68,19 @@ case "$machine" in ;; mips*) arch_minimum_kernel=2.2.15 + libc_cv_gcc_unwind_find_fde=yes + ;; + powerpc) + libc_cv_gcc_unwind_find_fde=yes + arch_minimum_kernel=2.0.10 ;; sh*) arch_minimum_kernel=2.3.99 + libc_cv_gcc_unwind_find_fde=yes + ;; + sparc*) + libc_cv_gcc_unwind_find_fde=yes + arch_minimum_kernel=2.0.10 ;; x86_64*) arch_minimum_kernel=2.4.0 @@ -91,11 +106,11 @@ fi if test -n "$minimum_kernel"; then echo $ac_n "checking for kernel header at least $minimum_kernel""... $ac_c" 1>&6 -echo "configure:95: checking for kernel header at least $minimum_kernel" >&5 +echo "configure:110: checking for kernel header at least $minimum_kernel" >&5 decnum=`echo "$minimum_kernel.0.0.0" | sed 's/\([0-9]*\)\.\([0-9]*\)\.\([0-9]*\).*/(\1 * 65536 + \2 * 256 + \3)/'`; abinum=`echo "$minimum_kernel.0.0.0" | sed 's/\([0-9]*\)\.\([0-9]*\)\.\([0-9]*\).*/\1,\2,\3/'`; cat > conftest.$ac_ext <<EOF -#line 99 "configure" +#line 114 "configure" #include "confdefs.h" #include <linux/version.h> #if LINUX_VERSION_CODE < $decnum @@ -128,6 +143,12 @@ EOF fi fi +# The result of the above test for the use of the FDE code is invalid if +# the user overrides the decision about the minimum ABI. +if test "$oldest_abi" != default && test "2.2.4" \< "$oldest_abi"; then + libc_cv_gcc_unwind_find_fde=no +fi + if test -n "$sysheaders"; then CPPFLAGS=$OLD_CPPFLAGS fi @@ -219,7 +240,7 @@ if test $host = $build; then ac_prefix=$ac_default_prefix fi echo $ac_n "checking for symlinks in ${ac_prefix}/include""... $ac_c" 1>&6 -echo "configure:223: checking for symlinks in ${ac_prefix}/include" >&5 +echo "configure:244: checking for symlinks in ${ac_prefix}/include" >&5 ac_message= if test -L ${ac_prefix}/include/net; then ac_message="$ac_message diff --git a/sysdeps/unix/sysv/linux/configure.in b/sysdeps/unix/sysv/linux/configure.in index dfae5a1de3..709d8e913f 100644 --- a/sysdeps/unix/sysv/linux/configure.in +++ b/sysdeps/unix/sysv/linux/configure.in @@ -41,6 +41,11 @@ fi case "$machine" in alpha*) arch_minimum_kernel=2.1.100 + libc_cv_gcc_unwind_find_fde=yes + ;; + i386*) + libc_cv_gcc_unwind_find_fde=yes + arch_minimum_kernel=2.0.10 ;; ia64*) arch_minimum_kernel=2.4.0 @@ -50,9 +55,19 @@ case "$machine" in ;; mips*) arch_minimum_kernel=2.2.15 + libc_cv_gcc_unwind_find_fde=yes + ;; + powerpc) + libc_cv_gcc_unwind_find_fde=yes + arch_minimum_kernel=2.0.10 ;; sh*) arch_minimum_kernel=2.3.99 + libc_cv_gcc_unwind_find_fde=yes + ;; + sparc*) + libc_cv_gcc_unwind_find_fde=yes + arch_minimum_kernel=2.0.10 ;; x86_64*) arch_minimum_kernel=2.4.0 @@ -96,6 +111,12 @@ eat flaming death fi fi +# The result of the above test for the use of the FDE code is invalid if +# the user overrides the decision about the minimum ABI. +if test "$oldest_abi" != default && test "2.2.4" \< "$oldest_abi"; then + libc_cv_gcc_unwind_find_fde=no +fi + if test -n "$sysheaders"; then CPPFLAGS=$OLD_CPPFLAGS fi diff --git a/sysdeps/unix/sysv/linux/i386/Makefile b/sysdeps/unix/sysv/linux/i386/Makefile index 4a219b89e4..4fc9434074 100644 --- a/sysdeps/unix/sysv/linux/i386/Makefile +++ b/sysdeps/unix/sysv/linux/i386/Makefile @@ -12,6 +12,12 @@ sysdep-dl-routines += dl-procinfo sysdep_routines += dl-procinfo # extra shared linker files to link only into dl-allobjs.so sysdep-rtld-routines += dl-procinfo + +ifeq (yes,$(build-shared)) +# This is needed to support g++ v2 and v3. +sysdep_routines += framestate +shared-only-routines += framestate +endif endif ifeq ($(subdir),resource) diff --git a/sysdeps/unix/sysv/linux/i386/Versions b/sysdeps/unix/sysv/linux/i386/Versions index 3015c41451..83445a1715 100644 --- a/sysdeps/unix/sysv/linux/i386/Versions +++ b/sysdeps/unix/sysv/linux/i386/Versions @@ -2,8 +2,7 @@ libc { GLIBC_2.0 { # Exception handling support functions from libgcc __register_frame; __register_frame_table; __deregister_frame; - __register_frame_info; __deregister_frame_info; __frame_state_for; - __register_frame_info_table; + __frame_state_for; __register_frame_info_table; ioperm; iopl; diff --git a/sysdeps/unix/sysv/linux/ia64/unwind-dw2-fde.c b/sysdeps/unix/sysv/linux/ia64/unwind-dw2-fde.c new file mode 100644 index 0000000000..15d12abfce --- /dev/null +++ b/sysdeps/unix/sysv/linux/ia64/unwind-dw2-fde.c @@ -0,0 +1 @@ +/* Linux/ia64 does not need unwind table registry. */ diff --git a/sysdeps/unix/sysv/linux/m68k/Makefile b/sysdeps/unix/sysv/linux/m68k/Makefile index 55eeeabe10..83ea370afa 100644 --- a/sysdeps/unix/sysv/linux/m68k/Makefile +++ b/sysdeps/unix/sysv/linux/m68k/Makefile @@ -10,6 +10,12 @@ endif ifeq ($(subdir),elf) sysdep-others += lddlibc4 install-bin += lddlibc4 + +ifeq (yes,$(build-shared)) +# This is needed to support g++ v2 and v3. +sysdep_routines += framestate +shared-only-routines += framestate +endif endif ifeq ($(subdir),resource) diff --git a/sysdeps/unix/sysv/linux/m68k/Versions b/sysdeps/unix/sysv/linux/m68k/Versions index 6c650e2ce2..0799bf310e 100644 --- a/sysdeps/unix/sysv/linux/m68k/Versions +++ b/sysdeps/unix/sysv/linux/m68k/Versions @@ -2,8 +2,7 @@ libc { GLIBC_2.0 { # Exception handling support functions from libgcc __register_frame; __register_frame_table; __deregister_frame; - __register_frame_info; __deregister_frame_info; __frame_state_for; - __register_frame_info_table; + __frame_state_for; __register_frame_info_table; # c* cacheflush; diff --git a/sysdeps/unix/sysv/linux/mips/Makefile b/sysdeps/unix/sysv/linux/mips/Makefile index 1f9fc2dd03..e46cfef7a5 100644 --- a/sysdeps/unix/sysv/linux/mips/Makefile +++ b/sysdeps/unix/sysv/linux/mips/Makefile @@ -9,3 +9,11 @@ sysdep_routines += cachectl cacheflush sysmips _test_and_set sysdep_headers += sys/cachectl.h sys/sysmips.h sys/tas.h endif + +ifeq ($(subdir),elf) +ifeq (yes,$(build-shared)) +# This is needed to support g++ v2 and v3. +sysdep_routines += framestate +shared-only-routines += framestate +endif +endif diff --git a/sysdeps/unix/sysv/linux/mips/Versions b/sysdeps/unix/sysv/linux/mips/Versions index d65bf18cb0..f71d9b5d88 100644 --- a/sysdeps/unix/sysv/linux/mips/Versions +++ b/sysdeps/unix/sysv/linux/mips/Versions @@ -2,8 +2,7 @@ libc { GLIBC_2.0 { # Exception handling support functions from libgcc __register_frame; __register_frame_table; __deregister_frame; - __register_frame_info; __deregister_frame_info; __frame_state_for; - __register_frame_info_table; + __frame_state_for; __register_frame_info_table; # Needed by gcc: _flush_cache; diff --git a/sysdeps/unix/sysv/linux/powerpc/Makefile b/sysdeps/unix/sysv/linux/powerpc/Makefile index 931611f4db..889df40fe8 100644 --- a/sysdeps/unix/sysv/linux/powerpc/Makefile +++ b/sysdeps/unix/sysv/linux/powerpc/Makefile @@ -6,3 +6,11 @@ endif ifeq ($(subdir),resource) sysdep_routines += oldgetrlimit64 endif + +ifeq ($(subdir),elf) +ifeq (yes,$(build-shared)) +# This is needed to support g++ v2 and v3. +sysdep_routines += framestate +shared-only-routines += framestate +endif +endif diff --git a/sysdeps/unix/sysv/linux/powerpc/Versions b/sysdeps/unix/sysv/linux/powerpc/Versions index a2296a968a..d0bf4a89c0 100644 --- a/sysdeps/unix/sysv/linux/powerpc/Versions +++ b/sysdeps/unix/sysv/linux/powerpc/Versions @@ -2,8 +2,7 @@ libc { GLIBC_2.0 { # Exception handling support functions from libgcc __register_frame; __register_frame_table; __deregister_frame; - __register_frame_info; __deregister_frame_info; __frame_state_for; - __register_frame_info_table; + __frame_state_for; __register_frame_info_table; } GLIBC_2.2 { # functions used in other libraries diff --git a/sysdeps/unix/sysv/linux/s390/s390-32/Makefile b/sysdeps/unix/sysv/linux/s390/s390-32/Makefile index bac110a28b..75844f455b 100644 --- a/sysdeps/unix/sysv/linux/s390/s390-32/Makefile +++ b/sysdeps/unix/sysv/linux/s390/s390-32/Makefile @@ -6,3 +6,11 @@ endif ifeq ($(subdir),resource) sysdep_routines += oldgetrlimit64 endif + +ifeq ($(subdir),elf) +ifeq (yes,$(build-shared)) +# This is needed to support g++ v2 and v3. +sysdep_routines += framestate +shared-only-routines += framestate +endif +endif diff --git a/sysdeps/unix/sysv/linux/s390/s390-32/Versions b/sysdeps/unix/sysv/linux/s390/s390-32/Versions index 5a56361b60..3c45a30778 100644 --- a/sysdeps/unix/sysv/linux/s390/s390-32/Versions +++ b/sysdeps/unix/sysv/linux/s390/s390-32/Versions @@ -2,8 +2,7 @@ libc { GLIBC_2.0 { # Exception handling support functions from libgcc __register_frame; __register_frame_table; __deregister_frame; - __register_frame_info; __deregister_frame_info; __frame_state_for; - __register_frame_info_table; + __frame_state_for; __register_frame_info_table; } GLIBC_2.2 { # functions used in other libraries diff --git a/sysdeps/unix/sysv/linux/sparc/Makefile b/sysdeps/unix/sysv/linux/sparc/Makefile index 9b46a7ea72..7059a1a31b 100644 --- a/sysdeps/unix/sysv/linux/sparc/Makefile +++ b/sysdeps/unix/sysv/linux/sparc/Makefile @@ -42,3 +42,11 @@ $(objpfx)syscall-%.h $(objpfx)syscall-%.d: ../sysdeps/unix/sysv/linux/sys/syscal mv -f $(@:.h=.d)-t2 $(@:.h=.d) endif + +ifeq ($(subdir),elf) +ifeq (yes,$(build-shared)) +# This is needed to support g++ v2 and v3. +sysdep_routines += framestate +shared-only-routines += framestate +endif +endif diff --git a/sysdeps/unix/sysv/linux/sparc/sparc32/Versions b/sysdeps/unix/sysv/linux/sparc/sparc32/Versions index d7a19f812a..4529e7fe6f 100644 --- a/sysdeps/unix/sysv/linux/sparc/sparc32/Versions +++ b/sysdeps/unix/sysv/linux/sparc/sparc32/Versions @@ -2,8 +2,7 @@ libc { GLIBC_2.0 { # Exception handling support functions from libgcc __register_frame; __register_frame_table; __deregister_frame; - __register_frame_info; __deregister_frame_info; __frame_state_for; - __register_frame_info_table; + __frame_state_for; __register_frame_info_table; } GLIBC_2.2 { # functions used in other libraries diff --git a/sysdeps/unix/sysv/linux/sparc/sparc64/Versions b/sysdeps/unix/sysv/linux/sparc/sparc64/Versions index 65349501fe..cfcc15b119 100644 --- a/sysdeps/unix/sysv/linux/sparc/sparc64/Versions +++ b/sysdeps/unix/sysv/linux/sparc/sparc64/Versions @@ -2,8 +2,7 @@ libc { GLIBC_2.0 { # Exception handling support functions from libgcc __register_frame; __register_frame_table; __deregister_frame; - __register_frame_info; __deregister_frame_info; __frame_state_for; - __register_frame_info_table; + __frame_state_for; __register_frame_info_table; } GLIBC_2.2.2 { # w* diff --git a/sysdeps/vax/gccframe.h b/sysdeps/vax/gccframe.h new file mode 100644 index 0000000000..323d5115d4 --- /dev/null +++ b/sysdeps/vax/gccframe.h @@ -0,0 +1,22 @@ +/* Definition of object in frame unwind info. vax version. + Copyright (C) 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#define DWARF_FRAME_REGISTERS 16 + +#include <sysdeps/generic/gccframe.h> |