Makefile.in (UNWIND_H): Remove.
authorRainer Orth <ro@gcc.gnu.org>
Fri, 5 Aug 2011 14:37:48 +0000 (14:37 +0000)
committerRainer Orth <ro@gcc.gnu.org>
Fri, 5 Aug 2011 14:37:48 +0000 (14:37 +0000)
gcc:
* Makefile.in (UNWIND_H): Remove.
(LIB2ADDEH, LIB2ADDEHSTATIC, LIB2ADDEHSHARED): Move to
../libgcc/Makefile.in.
(LIBUNWIND, SHLIBUNWIND_LINK, SHLIBUNWIND_INSTALL): Likewise.
(LIBUNWINDDEP): Remove.
(libgcc-support): Remove LIB2ADDEH, $(srcdir)/emutls.c dependencies.
(libgcc.mvars): Remove LIB2ADDEH, LIB2ADDEHSTATIC, LIB2ADDEHSHARED,
LIBUNWIND, SHLIBUNWIND_LINK, SHLIBUNWIND_INSTALL.
(stmp-int-hdrs): Remove $(UNWIND_H) dependency.
Don't copy $(UNWIND_H).
* config.gcc (ia64*-*-linux*): Remove with_system_libunwind
handling.
* configure.ac (GCC_CHECK_UNWIND_GETIPINFO): Remove.
* aclocal.m4: Regenerate.
* configure: Regenerate.
* emutls.c, unwind-c.c, unwind-compat.c, unwind-compat.h,
unwind-dw2-fde-compat.c, unwind-dw2-fde-glibc.c, unwind-dw2-fde.c,
unwind-dw2-fde.h, unwind-dw2.c, unwind-dw2.h, unwind-generic.h,
unwind-pe.h, unwind-sjlj.c, unwind.inc: Move to ../libgcc.
* unwind-dw2-fde-darwin.c: Move to ../libgcc/config.
* config/arm/libunwind.S, config/arm/pr-support.c,
config/arm/unwind-arm.c, config/arm/unwind-arm.h: Move to
../libgcc/config/arm.
* config/arm/t-bpabi (UNWIND_H, LIB2ADDEH): Remove.
* config/arm/t-symbian (UNWIND_H, LIB2ADDEH): Remove.
* config/frv/t-frv ($(T)frvbegin$(objext)): Use
$(srcdir)/../libgcc to refer to unwind-dw2-fde.h.
($(T)frvend$(objext)): Likewise.
* config/ia64/t-glibc (LIB2ADDEH): Remove.
* config/ia64/t-glibc-libunwind: Move to ../libgcc/config/ia64.
* config/ia64/fde-glibc.c, config/ia64/fde-vms.c,
config/ia64/unwind-ia64.c, config/ia64/unwind-ia64.h: Move to
../libgcc/config/ia64.
* config/ia64/t-hpux (LIB2ADDEH): Remove.
* config/ia64/t-ia64 (LIB2ADDEH): Remove.
* config/ia64/t-vms (LIB2ADDEH): Remove.
* config/ia64/vms.h (UNW_IVMS_MODE,
MD_UNW_COMPATIBLE_PERSONALITY_P): Remove.
* config/picochip/t-picochip (LIB2ADDEH): Remove.
* config/rs6000/aix.h (R_LR, MD_FROB_UPDATE_CONTEXT): Remove.
* config/rs6000/t-darwin (LIB2ADDEH): Remove.
* config/rs6000/darwin-fallback.c: Move to ../libgcc/config/rs6000.
* config/sh/t-sh ($(T)unwind-dw2-Os-4-200.o): Use
$(srcdir)/../libgcc to refer to unwinder sources.
* config/spu/t-spu-elf (LIB2ADDEH): Remove.
* config/t-darwin (LIB2ADDEH): Remove.
* config/t-freebsd (LIB2ADDEH): Remove.
* config/t-libunwind (LIB2ADDEH, LIB2ADDEHSTATIC): Remove.
* config/t-libunwind-elf: Move to ../libgcc/config.
* config/t-linux (LIB2ADDEH): Remove.
* config/t-sol2 (LIB2ADDEH): Remove.
* config/xtensa/t-xtensa (LIB2ADDEH): Remove.
* system.h (MD_FROB_UPDATE_CONTEXT): Poison.

gcc/po:
* EXCLUDES (unwind-c.c, unwind-dw2-fde-darwin.c)
(unwind-dw2-fde-glibc.c, unwind-dw2-fde.c, unwind-dw2-fde.h)
(unwind-dw2.c, unwind-pe.h, unwind-sjlj.c, unwind.h): Remove.

libgcc:
* Makefile.in (LIB2ADDEH, LIB2ADDEHSTATIC, LIB2ADDEHSHARED): New
variables.
(LIBUNWIND, SHLIBUNWIND_LINK, SHLIBUNWIND_INSTALL): New variables.
(LIB2ADDEH, LIB2ADDEHSTATIC, LIB2ADDEHSHARED): Add $(srcdir)/emutls.c.
(install-unwind_h): New target.
(all): Depend on it.
* config.host (unwind_header): New variable.
(*-*-freebsd*): Set tmake_file to t-eh-dw2-dip.
(*-*-linux*, frv-*-*linux*, *-*-kfreebsd*-gnu, *-*-knetbsd*-gnu,
*-*-gnu*): Likewise, also for *-*-kopensolaris*-gnu.
(*-*-solaris2*): Add t-eh-dw2-dip to tmake_file.
(arm*-*-linux*): Add arm/t-bpabi for arm*-*-linux-*eabi.
Set unwind_header.
(arm*-*-uclinux*): Add arm/t-bpabi for arm*-*-uclinux*eabi.
Set unwind_header.
(arm*-*-eabi*, arm*-*-symbianelf*): Add arm/t-bpabi for
arm*-*-eabi*.
Add arm/t-symbian to tmake_file for arm*-*-symbianelf*.
Set unwind_header.
(ia64*-*-elf*): Add ia64/t-eh-ia64 to tmake_file.
(ia64*-*-freebsd*): Likewise.
(ia64*-*-linux*): Add ia64/t-glibc, ia64/t-eh-ia64, t-libunwind to
tmake_file.
Add t-libunwind-elf, ia64/t-glibc-libunwind unless
$with_system_libunwind.
(ia64*-*-hpux*): Set tmake_file.
(ia64-hp-*vms*): Add ia64/t-eh-ia64 to tmake_file.
(picochip-*-*): Set tmake_file.
(rs6000-ibm-aix4.[3456789]*, powerpc-ibm-aix4.[3456789]*): Set
md_unwind_header.
(rs6000-ibm-aix5.1.*, powerpc-ibm-aix5.1.*): Likewise.
(rs6000-ibm-aix[56789].*, powerpc-ibm-aix[56789].*): Likewise.
(s390x-ibm-tpf*): Add t-eh-dw2-dip to tmake_file.
(xtensa*-*-elf*): Set tmake_file.
(xtensa*-*-linux*): Likewise.
* configure.ac: Include ../config/unwind_ipinfo.m4.
Call GCC_CHECK_UNWIND_GETIPINFO.
Link unwind.h to $unwind_header.
* configure: Regenerate.
* emutls.c, unwind-c.c, unwind-compat.c, unwind-compat.h,
unwind-dw2-fde-compat.c, unwind-dw2-fde-dip.c, unwind-dw2-fde.c,
unwind-dw2-fde.h, unwind-dw2.c, unwind-dw2.h, unwind-generic.h,
unwind-pe.h, unwind-sjlj.c, unwind.inc: New files.
* config/unwind-dw2-fde-darwin.c: New file.
* config/arm/libunwind.S, config/arm/pr-support.c,
config/arm/t-bpabi, config/arm/t-symbian, config/arm/unwind-arm.c,
config/arm/unwind-arm.h,: New files.
* config/ia64/fde-glibc.c, config/ia64/fde-vms.c,
config/ia64/t-eh-ia64, config/ia64/t-glibc,
config/ia64/t-glibc-libunwind, config/ia64/t-hpux,
config/ia64/t-vms, config/ia64/unwind-ia64.c,
config/ia64/unwind-ia64.h: New files.
* config/picochip/t-picochip: New file.
* config/rs6000/aix-unwind.h, config/rs6000/darwin-fallback.c: New
files.
* config/rs6000/t-darwin (LIB2ADDEH): Set.
* config/s390/t-tpf (LIB2ADDEH): Remove.
* config/t-darwin (LIB2ADDEH): Set.
* config/t-eh-dw2-dip: New file.
* config/t-libunwind, config/t-libunwind-elf: New files.
* config/t-sol2 (LIB2ADDEH): Remove.
* config/xtensa/t-xtensa: New file.

gcc/ada:
* gcc-interface/Makefile.in (raise-gcc.o): Search
$(srcdir)/../libgcc.

libgo:
* Makefile.am (AM_CFLAGS): Search $(srcdir)/../libgcc.
* Makefile.in: Regenerate.

libjava:
* configure.ac (GCC_UNWIND_INCLUDE): Rename to
LIBGCC_UNWIND_INCLUDE.
Point to $(multi_basedir)/./libjava/../libgcc.
* configure: Regenerate.
* Makefile.am (GCC_UNWIND_INCLUDE): Reflect this.
* Makefile.in: Regenerate.

libobjc:
* Makefile.in (INCLUDES): Search
$(srcdir)/$(MULTISRCTOP)../libgcc.

libstdc++-v3:
* acinclude.m4 (GLIBCXX_EXPORT_INCLUDES): Point TOPLEVEL_INCLUDES
to $(toplevel_srcdir)/libgcc.
* configure: Regenerate.

From-SVN: r177447

119 files changed:
gcc/ChangeLog
gcc/Makefile.in
gcc/aclocal.m4
gcc/ada/ChangeLog
gcc/ada/gcc-interface/Makefile.in
gcc/config.gcc
gcc/config/arm/libunwind.S [deleted file]
gcc/config/arm/pr-support.c [deleted file]
gcc/config/arm/t-bpabi
gcc/config/arm/t-symbian
gcc/config/arm/unwind-arm.c [deleted file]
gcc/config/arm/unwind-arm.h [deleted file]
gcc/config/frv/t-frv
gcc/config/ia64/fde-glibc.c [deleted file]
gcc/config/ia64/fde-vms.c [deleted file]
gcc/config/ia64/t-glibc
gcc/config/ia64/t-glibc-libunwind [deleted file]
gcc/config/ia64/t-hpux
gcc/config/ia64/t-ia64
gcc/config/ia64/t-vms
gcc/config/ia64/unwind-ia64.c [deleted file]
gcc/config/ia64/unwind-ia64.h [deleted file]
gcc/config/ia64/vms.h
gcc/config/picochip/t-picochip
gcc/config/rs6000/aix.h
gcc/config/rs6000/darwin-fallback.c [deleted file]
gcc/config/rs6000/t-darwin
gcc/config/sh/t-sh
gcc/config/spu/t-spu-elf
gcc/config/t-darwin
gcc/config/t-freebsd
gcc/config/t-libunwind
gcc/config/t-libunwind-elf [deleted file]
gcc/config/t-linux
gcc/config/t-sol2
gcc/config/xtensa/t-xtensa
gcc/config/xtensa/unwind-dw2-xtensa.c [deleted file]
gcc/config/xtensa/unwind-dw2-xtensa.h [deleted file]
gcc/configure
gcc/configure.ac
gcc/emutls.c [deleted file]
gcc/po/ChangeLog
gcc/po/EXCLUDES
gcc/system.h
gcc/unwind-c.c [deleted file]
gcc/unwind-compat.c [deleted file]
gcc/unwind-compat.h [deleted file]
gcc/unwind-dw2-fde-compat.c [deleted file]
gcc/unwind-dw2-fde-darwin.c [deleted file]
gcc/unwind-dw2-fde-glibc.c [deleted file]
gcc/unwind-dw2-fde.c [deleted file]
gcc/unwind-dw2-fde.h [deleted file]
gcc/unwind-dw2.c [deleted file]
gcc/unwind-dw2.h [deleted file]
gcc/unwind-generic.h [deleted file]
gcc/unwind-pe.h [deleted file]
gcc/unwind-sjlj.c [deleted file]
gcc/unwind.inc [deleted file]
libgcc/ChangeLog
libgcc/Makefile.in
libgcc/config.host
libgcc/config/arm/libunwind.S [new file with mode: 0644]
libgcc/config/arm/pr-support.c [new file with mode: 0644]
libgcc/config/arm/t-bpabi [new file with mode: 0644]
libgcc/config/arm/t-symbian [new file with mode: 0644]
libgcc/config/arm/unwind-arm.c [new file with mode: 0644]
libgcc/config/arm/unwind-arm.h [new file with mode: 0644]
libgcc/config/ia64/fde-glibc.c [new file with mode: 0644]
libgcc/config/ia64/fde-vms.c [new file with mode: 0644]
libgcc/config/ia64/t-eh-ia64 [new file with mode: 0644]
libgcc/config/ia64/t-glibc [new file with mode: 0644]
libgcc/config/ia64/t-glibc-libunwind [new file with mode: 0644]
libgcc/config/ia64/t-hpux [new file with mode: 0644]
libgcc/config/ia64/t-vms [new file with mode: 0644]
libgcc/config/ia64/unwind-ia64.c [new file with mode: 0644]
libgcc/config/ia64/unwind-ia64.h [new file with mode: 0644]
libgcc/config/ia64/vms-unwind.h
libgcc/config/picochip/t-picochip [new file with mode: 0644]
libgcc/config/rs6000/aix-unwind.h [new file with mode: 0644]
libgcc/config/rs6000/darwin-fallback.c [new file with mode: 0644]
libgcc/config/rs6000/t-darwin
libgcc/config/s390/t-tpf
libgcc/config/t-darwin
libgcc/config/t-eh-dw2-dip [new file with mode: 0644]
libgcc/config/t-libunwind [new file with mode: 0644]
libgcc/config/t-libunwind-elf [new file with mode: 0644]
libgcc/config/t-sol2
libgcc/config/unwind-dw2-fde-darwin.c [new file with mode: 0644]
libgcc/config/xtensa/t-xtensa [new file with mode: 0644]
libgcc/config/xtensa/unwind-dw2-xtensa.c [new file with mode: 0644]
libgcc/config/xtensa/unwind-dw2-xtensa.h [new file with mode: 0644]
libgcc/configure
libgcc/configure.ac
libgcc/emutls.c [new file with mode: 0644]
libgcc/unwind-c.c [new file with mode: 0644]
libgcc/unwind-compat.c [new file with mode: 0644]
libgcc/unwind-compat.h [new file with mode: 0644]
libgcc/unwind-dw2-fde-compat.c [new file with mode: 0644]
libgcc/unwind-dw2-fde-dip.c [new file with mode: 0644]
libgcc/unwind-dw2-fde.c [new file with mode: 0644]
libgcc/unwind-dw2-fde.h [new file with mode: 0644]
libgcc/unwind-dw2.c [new file with mode: 0644]
libgcc/unwind-dw2.h [new file with mode: 0644]
libgcc/unwind-generic.h [new file with mode: 0644]
libgcc/unwind-pe.h [new file with mode: 0644]
libgcc/unwind-sjlj.c [new file with mode: 0644]
libgcc/unwind.inc [new file with mode: 0644]
libgo/Makefile.am
libgo/Makefile.in
libjava/ChangeLog
libjava/Makefile.am
libjava/Makefile.in
libjava/configure
libjava/configure.ac
libobjc/ChangeLog
libobjc/Makefile.in
libstdc++-v3/ChangeLog
libstdc++-v3/acinclude.m4
libstdc++-v3/configure

index f269930732d155cf4cf6c11046c278265f671a20..438e8bb95f0c1950ef9b3ded9836a8637e9bf7cc 100644 (file)
@@ -1,3 +1,59 @@
+2011-08-05  Rainer Orth  <ro@CeBiTec.Uni-Bielefeld.DE>
+
+       * Makefile.in (UNWIND_H): Remove.
+       (LIB2ADDEH, LIB2ADDEHSTATIC, LIB2ADDEHSHARED): Move to
+       ../libgcc/Makefile.in.
+       (LIBUNWIND, SHLIBUNWIND_LINK, SHLIBUNWIND_INSTALL): Likewise.
+       (LIBUNWINDDEP): Remove.
+       (libgcc-support): Remove LIB2ADDEH, $(srcdir)/emutls.c dependencies.
+       (libgcc.mvars): Remove LIB2ADDEH, LIB2ADDEHSTATIC, LIB2ADDEHSHARED,
+       LIBUNWIND, SHLIBUNWIND_LINK, SHLIBUNWIND_INSTALL.
+       (stmp-int-hdrs): Remove $(UNWIND_H) dependency.
+       Don't copy $(UNWIND_H).
+       * config.gcc (ia64*-*-linux*): Remove with_system_libunwind
+       handling.
+       * configure.ac (GCC_CHECK_UNWIND_GETIPINFO): Remove.
+       * aclocal.m4: Regenerate.
+       * configure: Regenerate.
+       * emutls.c, unwind-c.c, unwind-compat.c, unwind-compat.h,
+       unwind-dw2-fde-compat.c, unwind-dw2-fde-glibc.c, unwind-dw2-fde.c,
+       unwind-dw2-fde.h, unwind-dw2.c, unwind-dw2.h, unwind-generic.h,
+       unwind-pe.h, unwind-sjlj.c, unwind.inc: Move to ../libgcc.
+       * unwind-dw2-fde-darwin.c: Move to ../libgcc/config.
+       * config/arm/libunwind.S, config/arm/pr-support.c,
+       config/arm/unwind-arm.c, config/arm/unwind-arm.h: Move to
+       ../libgcc/config/arm.
+       * config/arm/t-bpabi (UNWIND_H, LIB2ADDEH): Remove.
+       * config/arm/t-symbian (UNWIND_H, LIB2ADDEH): Remove.
+       * config/frv/t-frv ($(T)frvbegin$(objext)): Use
+       $(srcdir)/../libgcc to refer to unwind-dw2-fde.h.
+       ($(T)frvend$(objext)): Likewise.
+       * config/ia64/t-glibc (LIB2ADDEH): Remove.
+       * config/ia64/t-glibc-libunwind: Move to ../libgcc/config/ia64.
+       * config/ia64/fde-glibc.c, config/ia64/fde-vms.c,
+       config/ia64/unwind-ia64.c, config/ia64/unwind-ia64.h: Move to
+       ../libgcc/config/ia64.
+       * config/ia64/t-hpux (LIB2ADDEH): Remove.
+       * config/ia64/t-ia64 (LIB2ADDEH): Remove.
+       * config/ia64/t-vms (LIB2ADDEH): Remove.
+       * config/ia64/vms.h (UNW_IVMS_MODE,
+       MD_UNW_COMPATIBLE_PERSONALITY_P): Remove.
+       * config/picochip/t-picochip (LIB2ADDEH): Remove.
+       * config/rs6000/aix.h (R_LR, MD_FROB_UPDATE_CONTEXT): Remove.
+       * config/rs6000/t-darwin (LIB2ADDEH): Remove.
+       * config/rs6000/darwin-fallback.c: Move to ../libgcc/config/rs6000.
+       * config/sh/t-sh ($(T)unwind-dw2-Os-4-200.o): Use
+       $(srcdir)/../libgcc to refer to unwinder sources.
+       * config/spu/t-spu-elf (LIB2ADDEH): Remove.
+       * config/t-darwin (LIB2ADDEH): Remove.
+       * config/t-freebsd (LIB2ADDEH): Remove.
+       * config/t-libunwind (LIB2ADDEH, LIB2ADDEHSTATIC): Remove.
+       * config/t-libunwind-elf: Move to ../libgcc/config.
+       * config/t-linux (LIB2ADDEH): Remove.
+       * config/t-sol2 (LIB2ADDEH): Remove.
+       * config/xtensa/t-xtensa (LIB2ADDEH): Remove.
+       * system.h (MD_FROB_UPDATE_CONTEXT): Poison.
+
 2011-08-05  H.J. Lu  <hongjiu.lu@intel.com>
 
        * config/i386/i386.c (processor_alias_table): Add core-avx-i.
index 0204f93208a0c363eea166518b0d90b5806bdc4f..889deb16240ee0ab94817045270c4858eefc00bc 100644 (file)
@@ -378,8 +378,6 @@ USER_H = $(srcdir)/ginclude/float.h \
 USER_H_INC_NEXT_PRE = @user_headers_inc_next_pre@
 USER_H_INC_NEXT_POST = @user_headers_inc_next_post@
 
-UNWIND_H = $(srcdir)/unwind-generic.h
-
 # The GCC to use for compiling crt*.o.
 # Usually the one we just built.
 # Don't use this as a dependency--use $(GCC_PASSES).
@@ -693,18 +691,6 @@ CRTSTUFF_CFLAGS = -O2 $(GCC_CFLAGS) $(INCLUDES) $(MULTILIB_CFLAGS) -g0 \
   -fno-stack-protector \
   $(INHIBIT_LIBC_CFLAGS)
 
-# Additional sources to handle exceptions; overridden by targets as needed.
-LIB2ADDEH = $(srcdir)/unwind-dw2.c $(srcdir)/unwind-dw2-fde.c \
-   $(srcdir)/unwind-sjlj.c $(srcdir)/unwind-c.c
-LIB2ADDEHSTATIC = $(LIB2ADDEH)
-LIB2ADDEHSHARED = $(LIB2ADDEH)
-
-# Don't build libunwind by default.
-LIBUNWIND =
-LIBUNWINDDEP =
-SHLIBUNWIND_LINK =
-SHLIBUNWIND_INSTALL =
-
 # nm flags to list global symbols in libgcc object files.
 SHLIB_NM_FLAGS = -pg
 
@@ -1898,7 +1884,7 @@ GCC_EXTRA_PARTS := $(sort $(EXTRA_MULTILIB_PARTS) $(EXTRA_PARTS))
 
 libgcc-support: libgcc.mvars stmp-int-hdrs $(TCONFIG_H) \
        $(MACHMODE_H) $(FPBIT) $(DPBIT) $(TPBIT) $(LIB2ADD) \
-       $(LIB2ADD_ST) $(LIB2ADDEH) $(srcdir)/emutls.c gcov-iov.h $(SFP_MACHINE)
+       $(LIB2ADD_ST) gcov-iov.h $(SFP_MACHINE)
 
 libgcc.mvars: config.status Makefile $(LIB2ADD) $(LIB2ADD_ST) specs \
                xgcc$(exeext)
@@ -1909,13 +1895,7 @@ libgcc.mvars: config.status Makefile $(LIB2ADD) $(LIB2ADD_ST) specs \
        echo LIB2FUNCS_EXCLUDE = '$(LIB2FUNCS_EXCLUDE)' >> tmp-libgcc.mvars
        echo LIB2ADD = '$(call srcdirify,$(LIB2ADD))' >> tmp-libgcc.mvars
        echo LIB2ADD_ST = '$(call srcdirify,$(LIB2ADD_ST))' >> tmp-libgcc.mvars
-       echo LIB2ADDEH = '$(call srcdirify,$(LIB2ADDEH) $(srcdir)/emutls.c)' >> tmp-libgcc.mvars
-       echo LIB2ADDEHSTATIC = '$(call srcdirify,$(LIB2ADDEHSTATIC) $(srcdir)/emutls.c)' >> tmp-libgcc.mvars
-       echo LIB2ADDEHSHARED = '$(call srcdirify,$(LIB2ADDEHSHARED) $(srcdir)/emutls.c)' >> tmp-libgcc.mvars
        echo LIB2_SIDITI_CONV_FUNCS = '$(LIB2_SIDITI_CONV_FUNCS)' >> tmp-libgcc.mvars
-       echo LIBUNWIND = '$(call srcdirify,$(LIBUNWIND))' >> tmp-libgcc.mvars
-       echo SHLIBUNWIND_LINK = '$(SHLIBUNWIND_LINK)' >> tmp-libgcc.mvars
-       echo SHLIBUNWIND_INSTALL = '$(SHLIBUNWIND_INSTALL)' >> tmp-libgcc.mvars
        echo FPBIT = '$(FPBIT)' >> tmp-libgcc.mvars
        echo FPBIT_FUNCS = '$(FPBIT_FUNCS)' >> tmp-libgcc.mvars
        echo LIB2_DIVMOD_FUNCS = '$(LIB2_DIVMOD_FUNCS)' >> tmp-libgcc.mvars
@@ -4114,7 +4094,7 @@ gcov-dump$(exeext): $(GCOV_DUMP_OBJS) $(LIBDEPS)
 # be rebuilt.
 
 # Build the include directories.
-stmp-int-hdrs: $(STMP_FIXINC) $(USER_H) $(UNWIND_H) fixinc_list
+stmp-int-hdrs: $(STMP_FIXINC) $(USER_H) fixinc_list
 # Copy in the headers provided with gcc.
 # The sed command gets just the last file name component;
 # this is necessary because VPATH could add a dirname.
@@ -4146,9 +4126,6 @@ stmp-int-hdrs: $(STMP_FIXINC) $(USER_H) $(UNWIND_H) fixinc_list
            chmod a+r include/$$file; \
          fi; \
        done
-       rm -f include/unwind.h
-       cp $(UNWIND_H) include/unwind.h
-       chmod a+r include/unwind.h
        rm -f include/stdint.h
        if [ $(USE_GCC_STDINT) = wrap ]; then \
          rm -f include/stdint-gcc.h; \
index 73afd7fedee151d84e1c4d01bdb8c23197454dec..1b90b2f5ee6603b8cdfed2a2f58b4858542b872b 100644 (file)
@@ -116,6 +116,5 @@ m4_include([../config/lib-prefix.m4])
 m4_include([../config/override.m4])
 m4_include([../config/progtest.m4])
 m4_include([../config/stdint.m4])
-m4_include([../config/unwind_ipinfo.m4])
 m4_include([../config/warnings.m4])
 m4_include([acinclude.m4])
index ce02f4f2889adf7e20d42f48421aa0dfa18d407f..743fa0e57dca39535d6f8c9f73aee37e2782f3ec 100644 (file)
@@ -1,3 +1,8 @@
+2011-08-05  Rainer Orth  <ro@CeBiTec.Uni-Bielefeld.DE>
+
+       * gcc-interface/Makefile.in (raise-gcc.o): Search
+       $(srcdir)/../libgcc.
+
 2011-08-05  Bob Duff  <duff@adacore.com>
 
        * sinfo.ads, sinfo.adb (Subpool_Handle_Name): New attribute for
        necessary.
        * put_scos.adb: Code simplification based on above change.
 
+>>>>>>> .r177446
 2011-08-05  Robert Dewar  <dewar@adacore.com>
 
        * sem_ch3.adb, gnatcmd.adb, switch-c.adb, exp_attr.adb, make.adb,
index 1642cc8622bbd53f28c01f63036abd8147c0f655..1e7a392edf48caa47031952a22ea4089329fa7c6 100644 (file)
@@ -2773,7 +2773,7 @@ vx_stack_info.o : vx_stack_info.c
 
 raise-gcc.o : raise-gcc.c raise.h
        $(COMPILER) -c $(ALL_COMPILERFLAGS) $(ADA_CFLAGS) \
-               -iquote $(srcdir) \
+               -iquote $(srcdir)/../libgcc \
                $(ALL_CPPFLAGS) $(INCLUDES) $< $(OUTPUT_OPTION)
 
 cio.o     : cio.c
index 94f15d8706d946fdeacfff8db13c3592a4b362f0..673b768b7704d7abffebe5f3ca0f2b661e4622b9 100644 (file)
@@ -1604,9 +1604,6 @@ ia64*-*-freebsd*)
 ia64*-*-linux*)
        tm_file="${tm_file} dbxelf.h elfos.h gnu-user.h linux.h glibc-stdint.h ia64/sysv4.h ia64/linux.h"
        tmake_file="${tmake_file} ia64/t-ia64 t-libunwind ia64/t-glibc"
-       if test x$with_system_libunwind != xyes ; then
-               tmake_file="${tmake_file} t-libunwind-elf ia64/t-glibc-libunwind"
-       fi
        target_cpu_default="MASK_GNU_AS|MASK_GNU_LD"
        extra_parts="crtbegin.o crtend.o crtbeginS.o crtendS.o crtfastmath.o"
        ;;
diff --git a/gcc/config/arm/libunwind.S b/gcc/config/arm/libunwind.S
deleted file mode 100644 (file)
index 48eb592..0000000
+++ /dev/null
@@ -1,363 +0,0 @@
-/* Support functions for the unwinder.
-   Copyright (C) 2003, 2004, 2005, 2007, 2008, 2009, 2010
-   Free Software Foundation, Inc.
-   Contributed by Paul Brook
-
-   This file 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 3, or (at your option) any
-   later version.
-
-   This file 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.
-
-   Under Section 7 of GPL version 3, you are granted additional
-   permissions described in the GCC Runtime Library Exception, version
-   3.1, as published by the Free Software Foundation.
-
-   You should have received a copy of the GNU General Public License and
-   a copy of the GCC Runtime Library Exception along with this program;
-   see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
-   <http://www.gnu.org/licenses/>.  */
-
-/* An executable stack is *not* required for these functions.  */
-#if defined(__ELF__) && defined(__linux__)
-.section .note.GNU-stack,"",%progbits
-.previous
-#endif
-
-#ifdef __ARM_EABI__
-/* Some attributes that are common to all routines in this file.  */
-       /* Tag_ABI_align_needed: This code does not require 8-byte
-          alignment from the caller.  */
-       /* .eabi_attribute 24, 0  -- default setting.  */
-       /* Tag_ABI_align_preserved: This code preserves 8-byte
-          alignment in any callee.  */
-       .eabi_attribute 25, 1
-#endif /* __ARM_EABI__ */
-
-#ifndef __symbian__
-
-#include "lib1funcs.asm"
-
-.macro UNPREFIX name
-       .global SYM (\name)
-       EQUIV SYM (\name), SYM (__\name)
-.endm
-
-#if (__ARM_ARCH__ == 4)
-/* Some coprocessors require armv5.  We know this code will never be run on
-   other cpus.  Tell gas to allow armv5, but only mark the objects as armv4.
- */
-.arch armv5t
-#ifdef __ARM_ARCH_4T__
-.object_arch armv4t
-#else
-.object_arch armv4
-#endif
-#endif
-
-#ifdef __ARM_ARCH_6M__
-
-/* r0 points to a 16-word block.  Upload these values to the actual core
-   state.  */
-FUNC_START restore_core_regs
-       mov r1, r0
-       add r1, r1, #52
-       ldmia r1!, {r3, r4, r5}
-       sub r3, r3, #4
-       mov ip, r3
-       str r5, [r3]
-       mov lr, r4
-       /* Restore r8-r11.  */
-       mov r1, r0
-       add r1, r1, #32
-       ldmia r1!, {r2, r3, r4, r5}
-       mov r8, r2
-       mov r9, r3
-       mov sl, r4
-       mov fp, r5
-       mov r1, r0
-       add r1, r1, #8
-       ldmia r1!, {r2, r3, r4, r5, r6, r7}
-       ldr r1, [r0, #4]
-       ldr r0, [r0]
-       mov sp, ip
-       pop {pc}
-       FUNC_END restore_core_regs
-       UNPREFIX restore_core_regs
-
-/* ARMV6M does not have coprocessors, so these should never be used.  */
-FUNC_START gnu_Unwind_Restore_VFP
-       RET
-
-/* Store VFR regsters d0-d15 to the address in r0.  */
-FUNC_START gnu_Unwind_Save_VFP
-       RET
-
-/* Load VFP registers d0-d15 from the address in r0.
-   Use this to load from FSTMD format.  */
-FUNC_START gnu_Unwind_Restore_VFP_D
-       RET
-
-/* Store VFP registers d0-d15 to the address in r0.
-   Use this to store in FLDMD format.  */
-FUNC_START gnu_Unwind_Save_VFP_D
-       RET
-
-/* Load VFP registers d16-d31 from the address in r0.
-   Use this to load from FSTMD (=VSTM) format.  Needs VFPv3.  */
-FUNC_START gnu_Unwind_Restore_VFP_D_16_to_31
-       RET
-
-/* Store VFP registers d16-d31 to the address in r0.
-   Use this to store in FLDMD (=VLDM) format.  Needs VFPv3.  */
-FUNC_START gnu_Unwind_Save_VFP_D_16_to_31
-       RET
-
-FUNC_START gnu_Unwind_Restore_WMMXD
-       RET
-
-FUNC_START gnu_Unwind_Save_WMMXD
-       RET
-
-FUNC_START gnu_Unwind_Restore_WMMXC
-       RET
-
-FUNC_START gnu_Unwind_Save_WMMXC
-       RET
-
-.macro  UNWIND_WRAPPER name nargs
-       FUNC_START \name
-       /* Create a phase2_vrs structure.  */
-       /* Save r0 in the PC slot so we can use it as a scratch register.  */
-       push {r0}
-       add r0, sp, #4
-       push {r0, lr} /* Push original SP and LR.  */
-       /* Make space for r8-r12.  */
-       sub sp, sp, #20
-       /* Save low registers.  */
-       push {r0, r1, r2, r3, r4, r5, r6, r7}
-       /* Save high registers.  */
-       add r0, sp, #32
-       mov r1, r8
-       mov r2, r9
-       mov r3, sl
-       mov r4, fp
-       mov r5, ip
-       stmia r0!, {r1, r2, r3, r4, r5}
-       /* Restore original low register values.  */
-       add r0, sp, #4
-       ldmia r0!, {r1, r2, r3, r4, r5}
-       /* Restore orginial r0.  */
-       ldr r0, [sp, #60]
-       str r0, [sp]
-       /* Demand-save flags, plus an extra word for alignment.  */
-       mov r3, #0
-       push {r2, r3}
-       /* Point r1 at the block.  Pass r[0..nargs) unchanged.  */
-       add r\nargs, sp, #4
-
-       bl SYM (__gnu\name)
-
-       ldr r3, [sp, #64]
-       add sp, sp, #72
-       bx r3
-
-       FUNC_END \name
-       UNPREFIX \name
-.endm
-
-#else /* !__ARM_ARCH_6M__ */
-
-/* r0 points to a 16-word block.  Upload these values to the actual core
-   state.  */
-ARM_FUNC_START restore_core_regs
-       /* We must use sp as the base register when restoring sp.  Push the
-          last 3 registers onto the top of the current stack to achieve
-          this.  */
-       add r1, r0, #52
-       ldmia r1, {r3, r4, r5}  /* {sp, lr, pc}.  */
-#if defined(__thumb2__)
-       /* Thumb-2 doesn't allow sp in a load-multiple instruction, so push
-          the target address onto the target stack.  This is safe as
-          we're always returning to somewhere further up the call stack.  */
-       mov ip, r3
-       mov lr, r4
-       str r5, [ip, #-4]!
-#elif defined(__INTERWORKING__)
-       /* Restore pc into ip.  */
-       mov r2, r5
-       stmfd sp!, {r2, r3, r4}
-#else
-       stmfd sp!, {r3, r4, r5}
-#endif
-       /* Don't bother restoring ip.  */
-       ldmia r0, {r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, sl, fp}
-#if defined(__thumb2__)
-       /* Pop the return address off the target stack.  */
-       mov sp, ip
-       pop {pc}
-#elif defined(__INTERWORKING__)
-       /* Pop the three registers we pushed earlier.  */
-       ldmfd sp, {ip, sp, lr}
-       bx ip
-#else
-       ldmfd sp, {sp, lr, pc}
-#endif
-       FUNC_END restore_core_regs
-       UNPREFIX restore_core_regs
-
-/* Load VFP registers d0-d15 from the address in r0.
-   Use this to load from FSTMX format.  */
-ARM_FUNC_START gnu_Unwind_Restore_VFP
-       /* Use the generic coprocessor form so that gas doesn't complain
-          on soft-float targets.  */
-       ldc   p11,cr0,[r0],{0x21} /* fldmiax r0, {d0-d15} */
-       RET
-
-/* Store VFP registers d0-d15 to the address in r0.
-   Use this to store in FSTMX format.  */
-ARM_FUNC_START gnu_Unwind_Save_VFP
-       /* Use the generic coprocessor form so that gas doesn't complain
-          on soft-float targets.  */
-       stc   p11,cr0,[r0],{0x21} /* fstmiax r0, {d0-d15} */
-       RET
-
-/* Load VFP registers d0-d15 from the address in r0.
-   Use this to load from FSTMD format.  */
-ARM_FUNC_START gnu_Unwind_Restore_VFP_D
-       ldc   p11,cr0,[r0],{0x20} /* fldmiad r0, {d0-d15} */
-       RET
-
-/* Store VFP registers d0-d15 to the address in r0.
-   Use this to store in FLDMD format.  */
-ARM_FUNC_START gnu_Unwind_Save_VFP_D
-       stc   p11,cr0,[r0],{0x20} /* fstmiad r0, {d0-d15} */
-       RET
-
-/* Load VFP registers d16-d31 from the address in r0.
-   Use this to load from FSTMD (=VSTM) format.  Needs VFPv3.  */
-ARM_FUNC_START gnu_Unwind_Restore_VFP_D_16_to_31
-       ldcl  p11,cr0,[r0],{0x20} /* vldm r0, {d16-d31} */
-       RET
-
-/* Store VFP registers d16-d31 to the address in r0.
-   Use this to store in FLDMD (=VLDM) format.  Needs VFPv3.  */
-ARM_FUNC_START gnu_Unwind_Save_VFP_D_16_to_31
-       stcl  p11,cr0,[r0],{0x20} /* vstm r0, {d16-d31} */
-       RET
-
-ARM_FUNC_START gnu_Unwind_Restore_WMMXD
-       /* Use the generic coprocessor form so that gas doesn't complain
-          on non-iWMMXt targets.  */
-       ldcl  p1, cr0, [r0], #8 /* wldrd wr0, [r0], #8 */
-       ldcl  p1, cr1, [r0], #8 /* wldrd wr1, [r0], #8 */
-       ldcl  p1, cr2, [r0], #8 /* wldrd wr2, [r0], #8 */
-       ldcl  p1, cr3, [r0], #8 /* wldrd wr3, [r0], #8 */
-       ldcl  p1, cr4, [r0], #8 /* wldrd wr4, [r0], #8 */
-       ldcl  p1, cr5, [r0], #8 /* wldrd wr5, [r0], #8 */
-       ldcl  p1, cr6, [r0], #8 /* wldrd wr6, [r0], #8 */
-       ldcl  p1, cr7, [r0], #8 /* wldrd wr7, [r0], #8 */
-       ldcl  p1, cr8, [r0], #8 /* wldrd wr8, [r0], #8 */
-       ldcl  p1, cr9, [r0], #8 /* wldrd wr9, [r0], #8 */
-       ldcl  p1, cr10, [r0], #8 /* wldrd wr10, [r0], #8 */
-       ldcl  p1, cr11, [r0], #8 /* wldrd wr11, [r0], #8 */
-       ldcl  p1, cr12, [r0], #8 /* wldrd wr12, [r0], #8 */
-       ldcl  p1, cr13, [r0], #8 /* wldrd wr13, [r0], #8 */
-       ldcl  p1, cr14, [r0], #8 /* wldrd wr14, [r0], #8 */
-       ldcl  p1, cr15, [r0], #8 /* wldrd wr15, [r0], #8 */
-       RET
-
-ARM_FUNC_START gnu_Unwind_Save_WMMXD
-       /* Use the generic coprocessor form so that gas doesn't complain
-          on non-iWMMXt targets.  */
-       stcl  p1, cr0, [r0], #8 /* wstrd wr0, [r0], #8 */
-       stcl  p1, cr1, [r0], #8 /* wstrd wr1, [r0], #8 */
-       stcl  p1, cr2, [r0], #8 /* wstrd wr2, [r0], #8 */
-       stcl  p1, cr3, [r0], #8 /* wstrd wr3, [r0], #8 */
-       stcl  p1, cr4, [r0], #8 /* wstrd wr4, [r0], #8 */
-       stcl  p1, cr5, [r0], #8 /* wstrd wr5, [r0], #8 */
-       stcl  p1, cr6, [r0], #8 /* wstrd wr6, [r0], #8 */
-       stcl  p1, cr7, [r0], #8 /* wstrd wr7, [r0], #8 */
-       stcl  p1, cr8, [r0], #8 /* wstrd wr8, [r0], #8 */
-       stcl  p1, cr9, [r0], #8 /* wstrd wr9, [r0], #8 */
-       stcl  p1, cr10, [r0], #8 /* wstrd wr10, [r0], #8 */
-       stcl  p1, cr11, [r0], #8 /* wstrd wr11, [r0], #8 */
-       stcl  p1, cr12, [r0], #8 /* wstrd wr12, [r0], #8 */
-       stcl  p1, cr13, [r0], #8 /* wstrd wr13, [r0], #8 */
-       stcl  p1, cr14, [r0], #8 /* wstrd wr14, [r0], #8 */
-       stcl  p1, cr15, [r0], #8 /* wstrd wr15, [r0], #8 */
-       RET
-
-ARM_FUNC_START gnu_Unwind_Restore_WMMXC
-       /* Use the generic coprocessor form so that gas doesn't complain
-          on non-iWMMXt targets.  */
-       ldc2  p1, cr8, [r0], #4 /* wldrw wcgr0, [r0], #4 */
-       ldc2  p1, cr9, [r0], #4 /* wldrw wcgr1, [r0], #4 */
-       ldc2  p1, cr10, [r0], #4 /* wldrw wcgr2, [r0], #4 */
-       ldc2  p1, cr11, [r0], #4 /* wldrw wcgr3, [r0], #4 */
-       RET
-
-ARM_FUNC_START gnu_Unwind_Save_WMMXC
-       /* Use the generic coprocessor form so that gas doesn't complain
-          on non-iWMMXt targets.  */
-       stc2  p1, cr8, [r0], #4 /* wstrw wcgr0, [r0], #4 */
-       stc2  p1, cr9, [r0], #4 /* wstrw wcgr1, [r0], #4 */
-       stc2  p1, cr10, [r0], #4 /* wstrw wcgr2, [r0], #4 */
-       stc2  p1, cr11, [r0], #4 /* wstrw wcgr3, [r0], #4 */
-       RET
-
-/* Wrappers to save core registers, then call the real routine.   */
-
-.macro  UNWIND_WRAPPER name nargs
-       ARM_FUNC_START \name
-       /* Create a phase2_vrs structure.  */
-       /* Split reg push in two to ensure the correct value for sp.  */
-#if defined(__thumb2__)
-       mov ip, sp
-       push {lr} /* PC is ignored.  */
-       push {ip, lr} /* Push original SP and LR.  */
-#else
-       stmfd sp!, {sp, lr, pc}
-#endif
-       stmfd sp!, {r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, sl, fp, ip}
-       
-       /* Demand-save flags, plus an extra word for alignment.  */
-       mov r3, #0
-       stmfd sp!, {r2, r3}
-
-       /* Point r1 at the block.  Pass r[0..nargs) unchanged.  */
-       add r\nargs, sp, #4
-#if defined(__thumb__) && !defined(__thumb2__)
-       /* Switch back to thumb mode to avoid interworking hassle.  */
-       adr ip, .L1_\name
-       orr ip, ip, #1
-       bx ip
-       .thumb
-.L1_\name:
-       bl SYM (__gnu\name) __PLT__
-       ldr r3, [sp, #64]
-       add sp, #72
-       bx r3
-#else
-       bl SYM (__gnu\name) __PLT__
-       ldr lr, [sp, #64]
-       add sp, sp, #72
-       RET
-#endif
-       FUNC_END \name
-       UNPREFIX \name
-.endm
-
-#endif /* !__ARM_ARCH_6M__ */
-
-UNWIND_WRAPPER _Unwind_RaiseException 1
-UNWIND_WRAPPER _Unwind_Resume 1
-UNWIND_WRAPPER _Unwind_Resume_or_Rethrow 1
-UNWIND_WRAPPER _Unwind_ForcedUnwind 3
-UNWIND_WRAPPER _Unwind_Backtrace 2
-
-#endif  /* ndef __symbian__ */
diff --git a/gcc/config/arm/pr-support.c b/gcc/config/arm/pr-support.c
deleted file mode 100644 (file)
index deee661..0000000
+++ /dev/null
@@ -1,401 +0,0 @@
-/* ARM EABI compliant unwinding routines
-   Copyright (C) 2004, 2005, 2009 Free Software Foundation, Inc.
-   Contributed by Paul Brook
-   This file 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 3, or (at your option) any
-   later version.
-
-   This file 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.
-
-   Under Section 7 of GPL version 3, you are granted additional
-   permissions described in the GCC Runtime Library Exception, version
-   3.1, as published by the Free Software Foundation.
-
-   You should have received a copy of the GNU General Public License and
-   a copy of the GCC Runtime Library Exception along with this program;
-   see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
-   <http://www.gnu.org/licenses/>.  */
-
-#include "unwind.h"
-
-/* We add a prototype for abort here to avoid creating a dependency on
-   target headers.  */
-extern void abort (void);
-
-typedef struct _ZSt9type_info type_info; /* This names C++ type_info type */
-
-/* Misc constants.  */
-#define R_IP    12
-#define R_SP    13
-#define R_LR    14
-#define R_PC    15
-
-#define uint32_highbit (((_uw) 1) << 31)
-
-void __attribute__((weak)) __cxa_call_unexpected(_Unwind_Control_Block *ucbp);
-
-/* Unwind descriptors.  */
-
-typedef struct
-{
-  _uw16 length;
-  _uw16 offset;
-} EHT16;
-
-typedef struct
-{
-  _uw length;
-  _uw offset;
-} EHT32;
-
-/* Calculate the address encoded by a 31-bit self-relative offset at address
-   P.  Copy of routine in unwind-arm.c.  */
-
-static inline _uw
-selfrel_offset31 (const _uw *p)
-{
-  _uw offset;
-
-  offset = *p;
-  /* Sign extend to 32 bits.  */
-  if (offset & (1 << 30))
-    offset |= 1u << 31;
-
-  return offset + (_uw) p;
-}
-
-
-/* Personality routine helper functions.  */
-
-#define CODE_FINISH (0xb0)
-
-/* Return the next byte of unwinding information, or CODE_FINISH if there is
-   no data remaining.  */
-static inline _uw8
-next_unwind_byte (__gnu_unwind_state * uws)
-{
-  _uw8 b;
-
-  if (uws->bytes_left == 0)
-    {
-      /* Load another word */
-      if (uws->words_left == 0)
-       return CODE_FINISH; /* Nothing left.  */
-      uws->words_left--;
-      uws->data = *(uws->next++);
-      uws->bytes_left = 3;
-    }
-  else
-    uws->bytes_left--;
-
-  /* Extract the most significant byte.  */
-  b = (uws->data >> 24) & 0xff;
-  uws->data <<= 8;
-  return b;
-}
-
-/* Execute the unwinding instructions described by UWS.  */
-_Unwind_Reason_Code
-__gnu_unwind_execute (_Unwind_Context * context, __gnu_unwind_state * uws)
-{
-  _uw op;
-  int set_pc;
-  _uw reg;
-
-  set_pc = 0;
-  for (;;)
-    {
-      op = next_unwind_byte (uws);
-      if (op == CODE_FINISH)
-       {
-         /* If we haven't already set pc then copy it from lr.  */
-         if (!set_pc)
-           {
-             _Unwind_VRS_Get (context, _UVRSC_CORE, R_LR, _UVRSD_UINT32,
-                              &reg);
-             _Unwind_VRS_Set (context, _UVRSC_CORE, R_PC, _UVRSD_UINT32,
-                              &reg);
-             set_pc = 1;
-           }
-         /* Drop out of the loop.  */
-         break;
-       }
-      if ((op & 0x80) == 0)
-       {
-         /* vsp = vsp +- (imm6 << 2 + 4).  */
-         _uw offset;
-
-         offset = ((op & 0x3f) << 2) + 4;
-         _Unwind_VRS_Get (context, _UVRSC_CORE, R_SP, _UVRSD_UINT32, &reg);
-         if (op & 0x40)
-           reg -= offset;
-         else
-           reg += offset;
-         _Unwind_VRS_Set (context, _UVRSC_CORE, R_SP, _UVRSD_UINT32, &reg);
-         continue;
-       }
-      
-      if ((op & 0xf0) == 0x80)
-       {
-         op = (op << 8) | next_unwind_byte (uws);
-         if (op == 0x8000)
-           {
-             /* Refuse to unwind.  */
-             return _URC_FAILURE;
-           }
-         /* Pop r4-r15 under mask.  */
-         op = (op << 4) & 0xfff0;
-         if (_Unwind_VRS_Pop (context, _UVRSC_CORE, op, _UVRSD_UINT32)
-             != _UVRSR_OK)
-           return _URC_FAILURE;
-         if (op & (1 << R_PC))
-           set_pc = 1;
-         continue;
-       }
-      if ((op & 0xf0) == 0x90)
-       {
-         op &= 0xf;
-         if (op == 13 || op == 15)
-           /* Reserved.  */
-           return _URC_FAILURE;
-         /* vsp = r[nnnn].  */
-         _Unwind_VRS_Get (context, _UVRSC_CORE, op, _UVRSD_UINT32, &reg);
-         _Unwind_VRS_Set (context, _UVRSC_CORE, R_SP, _UVRSD_UINT32, &reg);
-         continue;
-       }
-      if ((op & 0xf0) == 0xa0)
-       {
-         /* Pop r4-r[4+nnn], [lr].  */
-         _uw mask;
-         
-         mask = (0xff0 >> (7 - (op & 7))) & 0xff0;
-         if (op & 8)
-           mask |= (1 << R_LR);
-         if (_Unwind_VRS_Pop (context, _UVRSC_CORE, mask, _UVRSD_UINT32)
-             != _UVRSR_OK)
-           return _URC_FAILURE;
-         continue;
-       }
-      if ((op & 0xf0) == 0xb0)
-       {
-         /* op == 0xb0 already handled.  */
-         if (op == 0xb1)
-           {
-             op = next_unwind_byte (uws);
-             if (op == 0 || ((op & 0xf0) != 0))
-               /* Spare.  */
-               return _URC_FAILURE;
-             /* Pop r0-r4 under mask.  */
-             if (_Unwind_VRS_Pop (context, _UVRSC_CORE, op, _UVRSD_UINT32)
-                 != _UVRSR_OK)
-               return _URC_FAILURE;
-             continue;
-           }
-         if (op == 0xb2)
-           {
-             /* vsp = vsp + 0x204 + (uleb128 << 2).  */
-             int shift;
-
-             _Unwind_VRS_Get (context, _UVRSC_CORE, R_SP, _UVRSD_UINT32,
-                              &reg);
-             op = next_unwind_byte (uws);
-             shift = 2;
-             while (op & 0x80)
-               {
-                 reg += ((op & 0x7f) << shift);
-                 shift += 7;
-                 op = next_unwind_byte (uws);
-               }
-             reg += ((op & 0x7f) << shift) + 0x204;
-             _Unwind_VRS_Set (context, _UVRSC_CORE, R_SP, _UVRSD_UINT32,
-                              &reg);
-             continue;
-           }
-         if (op == 0xb3)
-           {
-             /* Pop VFP registers with fldmx.  */
-             op = next_unwind_byte (uws);
-             op = ((op & 0xf0) << 12) | ((op & 0xf) + 1);
-             if (_Unwind_VRS_Pop (context, _UVRSC_VFP, op, _UVRSD_VFPX)
-                 != _UVRSR_OK)
-               return _URC_FAILURE;
-             continue;
-           }
-         if ((op & 0xfc) == 0xb4)
-           {
-             /* Pop FPA E[4]-E[4+nn].  */
-             op = 0x40000 | ((op & 3) + 1);
-             if (_Unwind_VRS_Pop (context, _UVRSC_FPA, op, _UVRSD_FPAX)
-                 != _UVRSR_OK)
-               return _URC_FAILURE;
-             continue;
-           }
-         /* op & 0xf8 == 0xb8.  */
-         /* Pop VFP D[8]-D[8+nnn] with fldmx.  */
-         op = 0x80000 | ((op & 7) + 1);
-         if (_Unwind_VRS_Pop (context, _UVRSC_VFP, op, _UVRSD_VFPX)
-             != _UVRSR_OK)
-           return _URC_FAILURE;
-         continue;
-       }
-      if ((op & 0xf0) == 0xc0)
-       {
-         if (op == 0xc6)
-           {
-             /* Pop iWMMXt D registers.  */
-             op = next_unwind_byte (uws);
-             op = ((op & 0xf0) << 12) | ((op & 0xf) + 1);
-             if (_Unwind_VRS_Pop (context, _UVRSC_WMMXD, op, _UVRSD_UINT64)
-                 != _UVRSR_OK)
-               return _URC_FAILURE;
-             continue;
-           }
-         if (op == 0xc7)
-           {
-             op = next_unwind_byte (uws);
-             if (op == 0 || (op & 0xf0) != 0)
-               /* Spare.  */
-               return _URC_FAILURE;
-             /* Pop iWMMXt wCGR{3,2,1,0} under mask.  */
-             if (_Unwind_VRS_Pop (context, _UVRSC_WMMXC, op, _UVRSD_UINT32)
-                 != _UVRSR_OK)
-               return _URC_FAILURE;
-             continue;
-           }
-         if ((op & 0xf8) == 0xc0)
-           {
-             /* Pop iWMMXt wR[10]-wR[10+nnn].  */
-             op = 0xa0000 | ((op & 0xf) + 1);
-             if (_Unwind_VRS_Pop (context, _UVRSC_WMMXD, op, _UVRSD_UINT64)
-                 != _UVRSR_OK)
-               return _URC_FAILURE;
-             continue;
-           }
-         if (op == 0xc8)
-           {
-#ifndef __VFP_FP__
-             /* Pop FPA registers.  */
-             op = next_unwind_byte (uws);
-             op = ((op & 0xf0) << 12) | ((op & 0xf) + 1);
-             if (_Unwind_VRS_Pop (context, _UVRSC_FPA, op, _UVRSD_FPAX)
-                 != _UVRSR_OK)
-               return _URC_FAILURE;
-             continue;
-#else
-              /* Pop VFPv3 registers D[16+ssss]-D[16+ssss+cccc] with vldm.  */
-              op = next_unwind_byte (uws);
-              op = (((op & 0xf0) + 16) << 12) | ((op & 0xf) + 1);
-              if (_Unwind_VRS_Pop (context, _UVRSC_VFP, op, _UVRSD_DOUBLE)
-                  != _UVRSR_OK)
-                return _URC_FAILURE;
-              continue;
-#endif
-           }
-         if (op == 0xc9)
-           {
-             /* Pop VFP registers with fldmd.  */
-             op = next_unwind_byte (uws);
-             op = ((op & 0xf0) << 12) | ((op & 0xf) + 1);
-             if (_Unwind_VRS_Pop (context, _UVRSC_VFP, op, _UVRSD_DOUBLE)
-                 != _UVRSR_OK)
-               return _URC_FAILURE;
-             continue;
-           }
-         /* Spare.  */
-         return _URC_FAILURE;
-       }
-      if ((op & 0xf8) == 0xd0)
-       {
-         /* Pop VFP D[8]-D[8+nnn] with fldmd.  */
-         op = 0x80000 | ((op & 7) + 1);
-         if (_Unwind_VRS_Pop (context, _UVRSC_VFP, op, _UVRSD_DOUBLE)
-             != _UVRSR_OK)
-           return _URC_FAILURE;
-         continue;
-       }
-      /* Spare.  */
-      return _URC_FAILURE;
-    }
-  return _URC_OK;
-}
-
-
-/* Execute the unwinding instructions associated with a frame.  UCBP and
-   CONTEXT are the current exception object and virtual CPU state
-   respectively.  */
-
-_Unwind_Reason_Code
-__gnu_unwind_frame (_Unwind_Control_Block * ucbp, _Unwind_Context * context)
-{
-  _uw *ptr;
-  __gnu_unwind_state uws;
-
-  ptr = (_uw *) ucbp->pr_cache.ehtp;
-  /* Skip over the personality routine address.  */
-  ptr++;
-  /* Setup the unwinder state.  */
-  uws.data = (*ptr) << 8;
-  uws.next = ptr + 1;
-  uws.bytes_left = 3;
-  uws.words_left = ((*ptr) >> 24) & 0xff;
-
-  return __gnu_unwind_execute (context, &uws);
-}
-
-/* Get the _Unwind_Control_Block from an _Unwind_Context.  */
-
-static inline _Unwind_Control_Block *
-unwind_UCB_from_context (_Unwind_Context * context)
-{
-  return (_Unwind_Control_Block *) _Unwind_GetGR (context, R_IP);
-}
-
-/* Get the start address of the function being unwound.  */
-
-_Unwind_Ptr
-_Unwind_GetRegionStart (_Unwind_Context * context)
-{
-  _Unwind_Control_Block *ucbp;
-
-  ucbp = unwind_UCB_from_context (context);
-  return (_Unwind_Ptr) ucbp->pr_cache.fnstart;
-}
-
-/* Find the Language specific exception data.  */
-
-void *
-_Unwind_GetLanguageSpecificData (_Unwind_Context * context)
-{
-  _Unwind_Control_Block *ucbp;
-  _uw *ptr;
-
-  /* Get a pointer to the exception table entry.  */
-  ucbp = unwind_UCB_from_context (context);
-  ptr = (_uw *) ucbp->pr_cache.ehtp;
-  /* Skip the personality routine address.  */
-  ptr++;
-  /* Skip the unwind opcodes.  */
-  ptr += (((*ptr) >> 24) & 0xff) + 1;
-
-  return ptr;
-}
-
-
-/* These two should never be used.  */
-
-_Unwind_Ptr
-_Unwind_GetDataRelBase (_Unwind_Context *context __attribute__ ((unused)))
-{
-  abort ();
-}
-
-_Unwind_Ptr
-_Unwind_GetTextRelBase (_Unwind_Context *context __attribute__ ((unused)))
-{
-  abort ();
-}
index 78812b35bd8f8f2e3d75fbc37c5aa43a62373c5f..b6b5f40d7231022efa2e18fe58cd7a3ea7214f72 100644 (file)
@@ -25,11 +25,6 @@ LIB2FUNCS_EXTRA = $(srcdir)/config/arm/bpabi.c \
 
 LIB2FUNCS_STATIC_EXTRA = $(srcdir)/config/arm/fp16.c
 
-UNWIND_H = $(srcdir)/config/arm/unwind-arm.h
-LIB2ADDEH = $(srcdir)/config/arm/unwind-arm.c \
-  $(srcdir)/config/arm/libunwind.S \
-  $(srcdir)/config/arm/pr-support.c $(srcdir)/unwind-c.c
-
 # Add the BPABI names.
 SHLIB_MAPFILES += $(srcdir)/config/arm/libgcc-bpabi.ver
 
index 3be83f445aa14fcb5a03e3eaec0b04717b721c22..f074591acbe3eb4e3c059fe50d14eb26d00a9a81 100644 (file)
@@ -30,10 +30,6 @@ LIB1ASMFUNCS += \
        _truncdfsf2 _negsf2 _addsubsf3 _muldivsf3 _cmpsf2 _unordsf2 \
        _fixsfsi _fixunssfsi
 
-# Include the gcc personality routine
-UNWIND_H = $(srcdir)/config/arm/unwind-arm.h
-LIB2ADDEH = $(srcdir)/unwind-c.c $(srcdir)/config/arm/pr-support.c
-
 # Include half-float helpers.
 LIB2FUNCS_STATIC_EXTRA = $(srcdir)/config/arm/fp16.c
 
diff --git a/gcc/config/arm/unwind-arm.c b/gcc/config/arm/unwind-arm.c
deleted file mode 100644 (file)
index 90d258d..0000000
+++ /dev/null
@@ -1,1283 +0,0 @@
-/* ARM EABI compliant unwinding routines.
-   Copyright (C) 2004, 2005, 2009 Free Software Foundation, Inc.
-   Contributed by Paul Brook
-
-   This file 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 3, or (at your option) any
-   later version.
-
-   This file 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.
-
-   Under Section 7 of GPL version 3, you are granted additional
-   permissions described in the GCC Runtime Library Exception, version
-   3.1, as published by the Free Software Foundation.
-
-   You should have received a copy of the GNU General Public License and
-   a copy of the GCC Runtime Library Exception along with this program;
-   see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
-   <http://www.gnu.org/licenses/>.  */
-
-#include "unwind.h"
-
-/* We add a prototype for abort here to avoid creating a dependency on
-   target headers.  */
-extern void abort (void);
-
-/* Definitions for C++ runtime support routines.  We make these weak
-   declarations to avoid pulling in libsupc++ unnecessarily.  */
-typedef unsigned char bool;
-
-typedef struct _ZSt9type_info type_info; /* This names C++ type_info type */
-enum __cxa_type_match_result
-  {
-    ctm_failed = 0,
-    ctm_succeeded = 1,
-    ctm_succeeded_with_ptr_to_base = 2
-  };
-
-void __attribute__((weak)) __cxa_call_unexpected(_Unwind_Control_Block *ucbp);
-bool __attribute__((weak)) __cxa_begin_cleanup(_Unwind_Control_Block *ucbp);
-enum __cxa_type_match_result __attribute__((weak)) __cxa_type_match
-  (_Unwind_Control_Block *ucbp, const type_info *rttip,
-   bool is_reference, void **matched_object);
-
-_Unwind_Ptr __attribute__((weak))
-__gnu_Unwind_Find_exidx (_Unwind_Ptr, int *);
-
-/* Misc constants.  */
-#define R_IP   12
-#define R_SP   13
-#define R_LR   14
-#define R_PC   15
-
-#define EXIDX_CANTUNWIND 1
-#define uint32_highbit (((_uw) 1) << 31)
-
-#define UCB_FORCED_STOP_FN(ucbp) ((ucbp)->unwinder_cache.reserved1)
-#define UCB_PR_ADDR(ucbp) ((ucbp)->unwinder_cache.reserved2)
-#define UCB_SAVED_CALLSITE_ADDR(ucbp) ((ucbp)->unwinder_cache.reserved3)
-#define UCB_FORCED_STOP_ARG(ucbp) ((ucbp)->unwinder_cache.reserved4)
-
-struct core_regs
-{
-  _uw r[16];
-};
-
-/* We use normal integer types here to avoid the compiler generating
-   coprocessor instructions.  */
-struct vfp_regs
-{
-  _uw64 d[16];
-  _uw pad;
-};
-
-struct vfpv3_regs
-{
-  /* Always populated via VSTM, so no need for the "pad" field from
-     vfp_regs (which is used to store the format word for FSTMX).  */
-  _uw64 d[16];
-};
-
-struct fpa_reg
-{
-  _uw w[3];
-};
-
-struct fpa_regs
-{
-  struct fpa_reg f[8];
-};
-
-struct wmmxd_regs
-{
-  _uw64 wd[16];
-};
-
-struct wmmxc_regs
-{
-  _uw wc[4];
-};
-
-/* Unwind descriptors.  */
-
-typedef struct
-{
-  _uw16 length;
-  _uw16 offset;
-} EHT16;
-
-typedef struct
-{
-  _uw length;
-  _uw offset;
-} EHT32;
-
-/* The ABI specifies that the unwind routines may only use core registers,
-   except when actually manipulating coprocessor state.  This allows
-   us to write one implementation that works on all platforms by
-   demand-saving coprocessor registers.
-
-   During unwinding we hold the coprocessor state in the actual hardware
-   registers and allocate demand-save areas for use during phase1
-   unwinding.  */
-
-typedef struct
-{
-  /* The first fields must be the same as a phase2_vrs.  */
-  _uw demand_save_flags;
-  struct core_regs core;
-  _uw prev_sp; /* Only valid during forced unwinding.  */
-  struct vfp_regs vfp;
-  struct vfpv3_regs vfp_regs_16_to_31;
-  struct fpa_regs fpa;
-  struct wmmxd_regs wmmxd;
-  struct wmmxc_regs wmmxc;
-} phase1_vrs;
-
-#define DEMAND_SAVE_VFP 1      /* VFP state has been saved if not set */
-#define DEMAND_SAVE_VFP_D 2    /* VFP state is for FLDMD/FSTMD if set */
-#define DEMAND_SAVE_VFP_V3 4    /* VFPv3 state for regs 16 .. 31 has
-                                   been saved if not set */
-#define DEMAND_SAVE_WMMXD 8    /* iWMMXt data registers have been
-                                  saved if not set.  */
-#define DEMAND_SAVE_WMMXC 16   /* iWMMXt control registers have been
-                                  saved if not set.  */
-
-/* This must match the structure created by the assembly wrappers.  */
-typedef struct
-{
-  _uw demand_save_flags;
-  struct core_regs core;
-} phase2_vrs;
-
-
-/* An exception index table entry.  */
-
-typedef struct __EIT_entry
-{
-  _uw fnoffset;
-  _uw content;
-} __EIT_entry;
-
-/* Assembly helper functions.  */
-
-/* Restore core register state.  Never returns.  */
-void __attribute__((noreturn)) restore_core_regs (struct core_regs *);
-
-
-/* Coprocessor register state manipulation functions.  */
-
-/* Routines for FLDMX/FSTMX format...  */
-void __gnu_Unwind_Save_VFP (struct vfp_regs * p);
-void __gnu_Unwind_Restore_VFP (struct vfp_regs * p);
-void __gnu_Unwind_Save_WMMXD (struct wmmxd_regs * p);
-void __gnu_Unwind_Restore_WMMXD (struct wmmxd_regs * p);
-void __gnu_Unwind_Save_WMMXC (struct wmmxc_regs * p);
-void __gnu_Unwind_Restore_WMMXC (struct wmmxc_regs * p);
-
-/* ...and those for FLDMD/FSTMD format...  */
-void __gnu_Unwind_Save_VFP_D (struct vfp_regs * p);
-void __gnu_Unwind_Restore_VFP_D (struct vfp_regs * p);
-
-/* ...and those for VLDM/VSTM format, saving/restoring only registers
-   16 through 31.  */
-void __gnu_Unwind_Save_VFP_D_16_to_31 (struct vfpv3_regs * p);
-void __gnu_Unwind_Restore_VFP_D_16_to_31 (struct vfpv3_regs * p);
-
-/* Restore coprocessor state after phase1 unwinding.  */
-static void
-restore_non_core_regs (phase1_vrs * vrs)
-{
-  if ((vrs->demand_save_flags & DEMAND_SAVE_VFP) == 0)
-    {
-      if (vrs->demand_save_flags & DEMAND_SAVE_VFP_D)
-        __gnu_Unwind_Restore_VFP_D (&vrs->vfp);
-      else
-        __gnu_Unwind_Restore_VFP (&vrs->vfp);
-    }
-
-  if ((vrs->demand_save_flags & DEMAND_SAVE_VFP_V3) == 0)
-    __gnu_Unwind_Restore_VFP_D_16_to_31 (&vrs->vfp_regs_16_to_31);
-
-  if ((vrs->demand_save_flags & DEMAND_SAVE_WMMXD) == 0)
-    __gnu_Unwind_Restore_WMMXD (&vrs->wmmxd);
-  if ((vrs->demand_save_flags & DEMAND_SAVE_WMMXC) == 0)
-    __gnu_Unwind_Restore_WMMXC (&vrs->wmmxc);
-}
-
-/* A better way to do this would probably be to compare the absolute address
-   with a segment relative relocation of the same symbol.  */
-
-extern int __text_start;
-extern int __data_start;
-
-/* The exception index table location.  */
-extern __EIT_entry __exidx_start;
-extern __EIT_entry __exidx_end;
-
-/* ABI defined personality routines.  */
-extern _Unwind_Reason_Code __aeabi_unwind_cpp_pr0 (_Unwind_State,
-    _Unwind_Control_Block *, _Unwind_Context *);// __attribute__((weak));
-extern _Unwind_Reason_Code __aeabi_unwind_cpp_pr1 (_Unwind_State,
-    _Unwind_Control_Block *, _Unwind_Context *) __attribute__((weak));
-extern _Unwind_Reason_Code __aeabi_unwind_cpp_pr2 (_Unwind_State,
-    _Unwind_Control_Block *, _Unwind_Context *) __attribute__((weak));
-
-/* ABI defined routine to store a virtual register to memory.  */
-
-_Unwind_VRS_Result _Unwind_VRS_Get (_Unwind_Context *context,
-                                   _Unwind_VRS_RegClass regclass,
-                                   _uw regno,
-                                   _Unwind_VRS_DataRepresentation representation,
-                                   void *valuep)
-{
-  phase1_vrs *vrs = (phase1_vrs *) context;
-
-  switch (regclass)
-    {
-    case _UVRSC_CORE:
-      if (representation != _UVRSD_UINT32
-         || regno > 15)
-       return _UVRSR_FAILED;
-      *(_uw *) valuep = vrs->core.r[regno];
-      return _UVRSR_OK;
-
-    case _UVRSC_VFP:
-    case _UVRSC_FPA:
-    case _UVRSC_WMMXD:
-    case _UVRSC_WMMXC:
-      return _UVRSR_NOT_IMPLEMENTED;
-
-    default:
-      return _UVRSR_FAILED;
-    }
-}
-
-
-/* ABI defined function to load a virtual register from memory.  */
-
-_Unwind_VRS_Result _Unwind_VRS_Set (_Unwind_Context *context,
-                                   _Unwind_VRS_RegClass regclass,
-                                   _uw regno,
-                                   _Unwind_VRS_DataRepresentation representation,
-                                   void *valuep)
-{
-  phase1_vrs *vrs = (phase1_vrs *) context;
-
-  switch (regclass)
-    {
-    case _UVRSC_CORE:
-      if (representation != _UVRSD_UINT32
-         || regno > 15)
-       return _UVRSR_FAILED;
-
-      vrs->core.r[regno] = *(_uw *) valuep;
-      return _UVRSR_OK;
-
-    case _UVRSC_VFP:
-    case _UVRSC_FPA:
-    case _UVRSC_WMMXD:
-    case _UVRSC_WMMXC:
-      return _UVRSR_NOT_IMPLEMENTED;
-
-    default:
-      return _UVRSR_FAILED;
-    }
-}
-
-
-/* ABI defined function to pop registers off the stack.  */
-
-_Unwind_VRS_Result _Unwind_VRS_Pop (_Unwind_Context *context,
-                                   _Unwind_VRS_RegClass regclass,
-                                   _uw discriminator,
-                                   _Unwind_VRS_DataRepresentation representation)
-{
-  phase1_vrs *vrs = (phase1_vrs *) context;
-
-  switch (regclass)
-    {
-    case _UVRSC_CORE:
-      {
-       _uw *ptr;
-       _uw mask;
-       int i;
-
-       if (representation != _UVRSD_UINT32)
-         return _UVRSR_FAILED;
-
-       mask = discriminator & 0xffff;
-       ptr = (_uw *) vrs->core.r[R_SP];
-       /* Pop the requested registers.  */
-       for (i = 0; i < 16; i++)
-         {
-           if (mask & (1 << i))
-             vrs->core.r[i] = *(ptr++);
-         }
-       /* Writeback the stack pointer value if it wasn't restored.  */
-       if ((mask & (1 << R_SP)) == 0)
-         vrs->core.r[R_SP] = (_uw) ptr;
-      }
-      return _UVRSR_OK;
-
-    case _UVRSC_VFP:
-      {
-       _uw start = discriminator >> 16;
-       _uw count = discriminator & 0xffff;
-       struct vfp_regs tmp;
-       struct vfpv3_regs tmp_16_to_31;
-       int tmp_count;
-       _uw *sp;
-       _uw *dest;
-        int num_vfpv3_regs = 0;
-
-        /* We use an approximation here by bounding _UVRSD_DOUBLE
-           register numbers at 32 always, since we can't detect if
-           VFPv3 isn't present (in such a case the upper limit is 16).  */
-       if ((representation != _UVRSD_VFPX && representation != _UVRSD_DOUBLE)
-            || start + count > (representation == _UVRSD_VFPX ? 16 : 32)
-            || (representation == _UVRSD_VFPX && start >= 16))
-         return _UVRSR_FAILED;
-
-        /* Check if we're being asked to pop VFPv3-only registers
-           (numbers 16 through 31).  */
-       if (start >= 16)
-          num_vfpv3_regs = count;
-        else if (start + count > 16)
-          num_vfpv3_regs = start + count - 16;
-
-        if (num_vfpv3_regs && representation != _UVRSD_DOUBLE)
-          return _UVRSR_FAILED;
-
-       /* Demand-save coprocessor registers for stage1.  */
-       if (start < 16 && (vrs->demand_save_flags & DEMAND_SAVE_VFP))
-         {
-           vrs->demand_save_flags &= ~DEMAND_SAVE_VFP;
-
-            if (representation == _UVRSD_DOUBLE)
-              {
-                /* Save in FLDMD/FSTMD format.  */
-               vrs->demand_save_flags |= DEMAND_SAVE_VFP_D;
-               __gnu_Unwind_Save_VFP_D (&vrs->vfp);
-              }
-            else
-              {
-                /* Save in FLDMX/FSTMX format.  */
-               vrs->demand_save_flags &= ~DEMAND_SAVE_VFP_D;
-               __gnu_Unwind_Save_VFP (&vrs->vfp);
-              }
-         }
-
-        if (num_vfpv3_regs > 0
-            && (vrs->demand_save_flags & DEMAND_SAVE_VFP_V3))
-         {
-           vrs->demand_save_flags &= ~DEMAND_SAVE_VFP_V3;
-            __gnu_Unwind_Save_VFP_D_16_to_31 (&vrs->vfp_regs_16_to_31);
-         }
-
-       /* Restore the registers from the stack.  Do this by saving the
-          current VFP registers to a memory area, moving the in-memory
-          values into that area, and restoring from the whole area.
-          For _UVRSD_VFPX we assume FSTMX standard format 1.  */
-        if (representation == _UVRSD_VFPX)
-         __gnu_Unwind_Save_VFP (&tmp);
-        else
-          {
-           /* Save registers 0 .. 15 if required.  */
-            if (start < 16)
-              __gnu_Unwind_Save_VFP_D (&tmp);
-
-           /* Save VFPv3 registers 16 .. 31 if required.  */
-            if (num_vfpv3_regs)
-             __gnu_Unwind_Save_VFP_D_16_to_31 (&tmp_16_to_31);
-          }
-
-       /* Work out how many registers below register 16 need popping.  */
-       tmp_count = num_vfpv3_regs > 0 ? 16 - start : count;
-
-       /* Copy registers below 16, if needed.
-          The stack address is only guaranteed to be word aligned, so
-          we can't use doubleword copies.  */
-       sp = (_uw *) vrs->core.r[R_SP];
-        if (tmp_count > 0)
-          {
-           tmp_count *= 2;
-           dest = (_uw *) &tmp.d[start];
-           while (tmp_count--)
-             *(dest++) = *(sp++);
-          }
-
-       /* Copy VFPv3 registers numbered >= 16, if needed.  */
-        if (num_vfpv3_regs > 0)
-          {
-            /* num_vfpv3_regs is needed below, so copy it.  */
-            int tmp_count_2 = num_vfpv3_regs * 2;
-            int vfpv3_start = start < 16 ? 16 : start;
-
-           dest = (_uw *) &tmp_16_to_31.d[vfpv3_start - 16];
-           while (tmp_count_2--)
-             *(dest++) = *(sp++);
-          }
-
-       /* Skip the format word space if using FLDMX/FSTMX format.  */
-       if (representation == _UVRSD_VFPX)
-         sp++;
-
-       /* Set the new stack pointer.  */
-       vrs->core.r[R_SP] = (_uw) sp;
-
-       /* Reload the registers.  */
-        if (representation == _UVRSD_VFPX)
-         __gnu_Unwind_Restore_VFP (&tmp);
-        else
-          {
-           /* Restore registers 0 .. 15 if required.  */
-            if (start < 16)
-              __gnu_Unwind_Restore_VFP_D (&tmp);
-
-           /* Restore VFPv3 registers 16 .. 31 if required.  */
-            if (num_vfpv3_regs > 0)
-             __gnu_Unwind_Restore_VFP_D_16_to_31 (&tmp_16_to_31);
-          }
-      }
-      return _UVRSR_OK;
-
-    case _UVRSC_FPA:
-      return _UVRSR_NOT_IMPLEMENTED;
-
-    case _UVRSC_WMMXD:
-      {
-       _uw start = discriminator >> 16;
-       _uw count = discriminator & 0xffff;
-       struct wmmxd_regs tmp;
-       _uw *sp;
-       _uw *dest;
-
-       if ((representation != _UVRSD_UINT64) || start + count > 16)
-         return _UVRSR_FAILED;
-
-       if (vrs->demand_save_flags & DEMAND_SAVE_WMMXD)
-         {
-           /* Demand-save resisters for stage1.  */
-           vrs->demand_save_flags &= ~DEMAND_SAVE_WMMXD;
-           __gnu_Unwind_Save_WMMXD (&vrs->wmmxd);
-         }
-
-       /* Restore the registers from the stack.  Do this by saving the
-          current WMMXD registers to a memory area, moving the in-memory
-          values into that area, and restoring from the whole area.  */
-       __gnu_Unwind_Save_WMMXD (&tmp);
-
-       /* The stack address is only guaranteed to be word aligned, so
-          we can't use doubleword copies.  */
-       sp = (_uw *) vrs->core.r[R_SP];
-       dest = (_uw *) &tmp.wd[start];
-       count *= 2;
-       while (count--)
-         *(dest++) = *(sp++);
-
-       /* Set the new stack pointer.  */
-       vrs->core.r[R_SP] = (_uw) sp;
-
-       /* Reload the registers.  */
-       __gnu_Unwind_Restore_WMMXD (&tmp);
-      }
-      return _UVRSR_OK;
-
-    case _UVRSC_WMMXC:
-      {
-       int i;
-       struct wmmxc_regs tmp;
-       _uw *sp;
-
-       if ((representation != _UVRSD_UINT32) || discriminator > 16)
-         return _UVRSR_FAILED;
-
-       if (vrs->demand_save_flags & DEMAND_SAVE_WMMXC)
-         {
-           /* Demand-save resisters for stage1.  */
-           vrs->demand_save_flags &= ~DEMAND_SAVE_WMMXC;
-           __gnu_Unwind_Save_WMMXC (&vrs->wmmxc);
-         }
-
-       /* Restore the registers from the stack.  Do this by saving the
-          current WMMXC registers to a memory area, moving the in-memory
-          values into that area, and restoring from the whole area.  */
-       __gnu_Unwind_Save_WMMXC (&tmp);
-
-       sp = (_uw *) vrs->core.r[R_SP];
-       for (i = 0; i < 4; i++)
-         if (discriminator & (1 << i))
-           tmp.wc[i] = *(sp++);
-
-       /* Set the new stack pointer.  */
-       vrs->core.r[R_SP] = (_uw) sp;
-
-       /* Reload the registers.  */
-       __gnu_Unwind_Restore_WMMXC (&tmp);
-      }
-      return _UVRSR_OK;
-
-    default:
-      return _UVRSR_FAILED;
-    }
-}
-
-
-/* Core unwinding functions.  */
-
-/* Calculate the address encoded by a 31-bit self-relative offset at address
-   P.  */
-static inline _uw
-selfrel_offset31 (const _uw *p)
-{
-  _uw offset;
-
-  offset = *p;
-  /* Sign extend to 32 bits.  */
-  if (offset & (1 << 30))
-    offset |= 1u << 31;
-  else
-    offset &= ~(1u << 31);
-
-  return offset + (_uw) p;
-}
-
-
-/* Perform a binary search for RETURN_ADDRESS in TABLE.  The table contains
-   NREC entries.  */
-
-static const __EIT_entry *
-search_EIT_table (const __EIT_entry * table, int nrec, _uw return_address)
-{
-  _uw next_fn;
-  _uw this_fn;
-  int n, left, right;
-
-  if (nrec == 0)
-    return (__EIT_entry *) 0;
-
-  left = 0;
-  right = nrec - 1;
-
-  while (1)
-    {
-      n = (left + right) / 2;
-      this_fn = selfrel_offset31 (&table[n].fnoffset);
-      if (n != nrec - 1)
-       next_fn = selfrel_offset31 (&table[n + 1].fnoffset) - 1;
-      else
-       next_fn = (_uw)0 - 1;
-
-      if (return_address < this_fn)
-       {
-         if (n == left)
-           return (__EIT_entry *) 0;
-         right = n - 1;
-       }
-      else if (return_address <= next_fn)
-       return &table[n];
-      else
-       left = n + 1;
-    }
-}
-
-/* Find the exception index table eintry for the given address.
-   Fill in the relevant fields of the UCB.
-   Returns _URC_FAILURE if an error occurred, _URC_OK on success.  */
-
-static _Unwind_Reason_Code
-get_eit_entry (_Unwind_Control_Block *ucbp, _uw return_address)
-{
-  const __EIT_entry * eitp;
-  int nrec;
-  
-  /* The return address is the address of the instruction following the
-     call instruction (plus one in thumb mode).  If this was the last
-     instruction in the function the address will lie in the following
-     function.  Subtract 2 from the address so that it points within the call
-     instruction itself.  */
-  return_address -= 2;
-
-  if (__gnu_Unwind_Find_exidx)
-    {
-      eitp = (const __EIT_entry *) __gnu_Unwind_Find_exidx (return_address,
-                                                           &nrec);
-      if (!eitp)
-       {
-         UCB_PR_ADDR (ucbp) = 0;
-         return _URC_FAILURE;
-       }
-    }
-  else
-    {
-      eitp = &__exidx_start;
-      nrec = &__exidx_end - &__exidx_start;
-    }
-
-  eitp = search_EIT_table (eitp, nrec, return_address);
-
-  if (!eitp)
-    {
-      UCB_PR_ADDR (ucbp) = 0;
-      return _URC_FAILURE;
-    }
-  ucbp->pr_cache.fnstart = selfrel_offset31 (&eitp->fnoffset);
-
-  /* Can this frame be unwound at all?  */
-  if (eitp->content == EXIDX_CANTUNWIND)
-    {
-      UCB_PR_ADDR (ucbp) = 0;
-      return _URC_END_OF_STACK;
-    }
-
-  /* Obtain the address of the "real" __EHT_Header word.  */
-
-  if (eitp->content & uint32_highbit)
-    {
-      /* It is immediate data.  */
-      ucbp->pr_cache.ehtp = (_Unwind_EHT_Header *)&eitp->content;
-      ucbp->pr_cache.additional = 1;
-    }
-  else
-    {
-      /* The low 31 bits of the content field are a self-relative
-        offset to an _Unwind_EHT_Entry structure.  */
-      ucbp->pr_cache.ehtp =
-       (_Unwind_EHT_Header *) selfrel_offset31 (&eitp->content);
-      ucbp->pr_cache.additional = 0;
-    }
-
-  /* Discover the personality routine address.  */
-  if (*ucbp->pr_cache.ehtp & (1u << 31))
-    {
-      /* One of the predefined standard routines.  */
-      _uw idx = (*(_uw *) ucbp->pr_cache.ehtp >> 24) & 0xf;
-      if (idx == 0)
-       UCB_PR_ADDR (ucbp) = (_uw) &__aeabi_unwind_cpp_pr0;
-      else if (idx == 1)
-       UCB_PR_ADDR (ucbp) = (_uw) &__aeabi_unwind_cpp_pr1;
-      else if (idx == 2)
-       UCB_PR_ADDR (ucbp) = (_uw) &__aeabi_unwind_cpp_pr2;
-      else
-       { /* Failed */
-         UCB_PR_ADDR (ucbp) = 0;
-         return _URC_FAILURE;
-       }
-    } 
-  else
-    {
-      /* Execute region offset to PR */
-      UCB_PR_ADDR (ucbp) = selfrel_offset31 (ucbp->pr_cache.ehtp);
-    }
-  return _URC_OK;
-}
-
-
-/* Perform phase2 unwinding.  VRS is the initial virtual register state.  */
-
-static void __attribute__((noreturn))
-unwind_phase2 (_Unwind_Control_Block * ucbp, phase2_vrs * vrs)
-{
-  _Unwind_Reason_Code pr_result;
-
-  do
-    {
-      /* Find the entry for this routine.  */
-      if (get_eit_entry (ucbp, vrs->core.r[R_PC]) != _URC_OK)
-       abort ();
-
-      UCB_SAVED_CALLSITE_ADDR (ucbp) = vrs->core.r[R_PC];
-
-      /* Call the pr to decide what to do.  */
-      pr_result = ((personality_routine) UCB_PR_ADDR (ucbp))
-       (_US_UNWIND_FRAME_STARTING, ucbp, (_Unwind_Context *) vrs);
-    }
-  while (pr_result == _URC_CONTINUE_UNWIND);
-  
-  if (pr_result != _URC_INSTALL_CONTEXT)
-    abort();
-  
-  restore_core_regs (&vrs->core);
-}
-
-/* Perform phase2 forced unwinding.  */
-
-static _Unwind_Reason_Code
-unwind_phase2_forced (_Unwind_Control_Block *ucbp, phase2_vrs *entry_vrs,
-                     int resuming)
-{
-  _Unwind_Stop_Fn stop_fn = (_Unwind_Stop_Fn) UCB_FORCED_STOP_FN (ucbp);
-  void *stop_arg = (void *)UCB_FORCED_STOP_ARG (ucbp);
-  _Unwind_Reason_Code pr_result = 0;
-  /* We use phase1_vrs here even though we do not demand save, for the
-     prev_sp field.  */
-  phase1_vrs saved_vrs, next_vrs;
-
-  /* Save the core registers.  */
-  saved_vrs.core = entry_vrs->core;
-  /* We don't need to demand-save the non-core registers, because we
-     unwind in a single pass.  */
-  saved_vrs.demand_save_flags = 0;
-
-  /* Unwind until we reach a propagation barrier.  */
-  do
-    {
-      _Unwind_State action;
-      _Unwind_Reason_Code entry_code;
-      _Unwind_Reason_Code stop_code;
-
-      /* Find the entry for this routine.  */
-      entry_code = get_eit_entry (ucbp, saved_vrs.core.r[R_PC]);
-
-      if (resuming)
-       {
-         action = _US_UNWIND_FRAME_RESUME | _US_FORCE_UNWIND;
-         resuming = 0;
-       }
-      else
-       action = _US_UNWIND_FRAME_STARTING | _US_FORCE_UNWIND;
-
-      if (entry_code == _URC_OK)
-       {
-         UCB_SAVED_CALLSITE_ADDR (ucbp) = saved_vrs.core.r[R_PC];
-
-         next_vrs = saved_vrs;
-
-         /* Call the pr to decide what to do.  */
-         pr_result = ((personality_routine) UCB_PR_ADDR (ucbp))
-           (action, ucbp, (void *) &next_vrs);
-
-         saved_vrs.prev_sp = next_vrs.core.r[R_SP];
-       }
-      else
-       {
-         /* Treat any failure as the end of unwinding, to cope more
-            gracefully with missing EH information.  Mixed EH and
-            non-EH within one object will usually result in failure,
-            because the .ARM.exidx tables do not indicate the end
-            of the code to which they apply; but mixed EH and non-EH
-            shared objects should return an unwind failure at the
-            entry of a non-EH shared object.  */
-         action |= _US_END_OF_STACK;
-
-         saved_vrs.prev_sp = saved_vrs.core.r[R_SP];
-       }
-
-      stop_code = stop_fn (1, action, ucbp->exception_class, ucbp,
-                          (void *)&saved_vrs, stop_arg);
-      if (stop_code != _URC_NO_REASON)
-       return _URC_FAILURE;
-
-      if (entry_code != _URC_OK)
-       return entry_code;
-
-      saved_vrs = next_vrs;
-    }
-  while (pr_result == _URC_CONTINUE_UNWIND);
-
-  if (pr_result != _URC_INSTALL_CONTEXT)
-    {
-      /* Some sort of failure has occurred in the pr and probably the
-        pr returned _URC_FAILURE.  */
-      return _URC_FAILURE;
-    }
-
-  restore_core_regs (&saved_vrs.core);
-}
-
-/* This is a very limited implementation of _Unwind_GetCFA.  It returns
-   the stack pointer as it is about to be unwound, and is only valid
-   while calling the stop function during forced unwinding.  If the
-   current personality routine result is going to run a cleanup, this
-   will not be the CFA; but when the frame is really unwound, it will
-   be.  */
-
-_Unwind_Word
-_Unwind_GetCFA (_Unwind_Context *context)
-{
-  return ((phase1_vrs *) context)->prev_sp;
-}
-
-/* Perform phase1 unwinding.  UCBP is the exception being thrown, and
-   entry_VRS is the register state on entry to _Unwind_RaiseException.  */
-
-_Unwind_Reason_Code
-__gnu_Unwind_RaiseException (_Unwind_Control_Block *, phase2_vrs *);
-
-_Unwind_Reason_Code
-__gnu_Unwind_RaiseException (_Unwind_Control_Block * ucbp,
-                            phase2_vrs * entry_vrs)
-{
-  phase1_vrs saved_vrs;
-  _Unwind_Reason_Code pr_result;
-
-  /* Set the pc to the call site.  */
-  entry_vrs->core.r[R_PC] = entry_vrs->core.r[R_LR];
-
-  /* Save the core registers.  */
-  saved_vrs.core = entry_vrs->core;
-  /* Set demand-save flags.  */
-  saved_vrs.demand_save_flags = ~(_uw) 0;
-  
-  /* Unwind until we reach a propagation barrier.  */
-  do
-    {
-      /* Find the entry for this routine.  */
-      if (get_eit_entry (ucbp, saved_vrs.core.r[R_PC]) != _URC_OK)
-       return _URC_FAILURE;
-
-      /* Call the pr to decide what to do.  */
-      pr_result = ((personality_routine) UCB_PR_ADDR (ucbp))
-       (_US_VIRTUAL_UNWIND_FRAME, ucbp, (void *) &saved_vrs);
-    }
-  while (pr_result == _URC_CONTINUE_UNWIND);
-
-  /* We've unwound as far as we want to go, so restore the original
-     register state.  */
-  restore_non_core_regs (&saved_vrs);
-  if (pr_result != _URC_HANDLER_FOUND)
-    {
-      /* Some sort of failure has occurred in the pr and probably the
-        pr returned _URC_FAILURE.  */
-      return _URC_FAILURE;
-    }
-  
-  unwind_phase2 (ucbp, entry_vrs);
-}
-
-/* Resume unwinding after a cleanup has been run.  UCBP is the exception
-   being thrown and ENTRY_VRS is the register state on entry to
-   _Unwind_Resume.  */
-_Unwind_Reason_Code
-__gnu_Unwind_ForcedUnwind (_Unwind_Control_Block *,
-                          _Unwind_Stop_Fn, void *, phase2_vrs *);
-
-_Unwind_Reason_Code
-__gnu_Unwind_ForcedUnwind (_Unwind_Control_Block *ucbp,
-                          _Unwind_Stop_Fn stop_fn, void *stop_arg,
-                          phase2_vrs *entry_vrs)
-{
-  UCB_FORCED_STOP_FN (ucbp) = (_uw) stop_fn;
-  UCB_FORCED_STOP_ARG (ucbp) = (_uw) stop_arg;
-
-  /* Set the pc to the call site.  */
-  entry_vrs->core.r[R_PC] = entry_vrs->core.r[R_LR];
-
-  return unwind_phase2_forced (ucbp, entry_vrs, 0);
-}
-
-_Unwind_Reason_Code
-__gnu_Unwind_Resume (_Unwind_Control_Block *, phase2_vrs *);
-
-_Unwind_Reason_Code
-__gnu_Unwind_Resume (_Unwind_Control_Block * ucbp, phase2_vrs * entry_vrs)
-{
-  _Unwind_Reason_Code pr_result;
-
-  /* Recover the saved address.  */
-  entry_vrs->core.r[R_PC] = UCB_SAVED_CALLSITE_ADDR (ucbp);
-
-  if (UCB_FORCED_STOP_FN (ucbp))
-    {
-      unwind_phase2_forced (ucbp, entry_vrs, 1);
-
-      /* We can't return failure at this point.  */
-      abort ();
-    }
-
-  /* Call the cached PR.  */
-  pr_result = ((personality_routine) UCB_PR_ADDR (ucbp))
-       (_US_UNWIND_FRAME_RESUME, ucbp, (_Unwind_Context *) entry_vrs);
-
-  switch (pr_result)
-    {
-    case _URC_INSTALL_CONTEXT:
-      /* Upload the registers to enter the landing pad.  */
-      restore_core_regs (&entry_vrs->core);
-
-    case _URC_CONTINUE_UNWIND:
-      /* Continue unwinding the next frame.  */
-      unwind_phase2 (ucbp, entry_vrs);
-
-    default:
-      abort ();
-    }
-}
-
-_Unwind_Reason_Code
-__gnu_Unwind_Resume_or_Rethrow (_Unwind_Control_Block *, phase2_vrs *);
-
-_Unwind_Reason_Code
-__gnu_Unwind_Resume_or_Rethrow (_Unwind_Control_Block * ucbp,
-                               phase2_vrs * entry_vrs)
-{
-  if (!UCB_FORCED_STOP_FN (ucbp))
-    return __gnu_Unwind_RaiseException (ucbp, entry_vrs);
-
-  /* Set the pc to the call site.  */
-  entry_vrs->core.r[R_PC] = entry_vrs->core.r[R_LR];
-  /* Continue unwinding the next frame.  */
-  return unwind_phase2_forced (ucbp, entry_vrs, 0);
-}
-
-/* Clean up an exception object when unwinding is complete.  */
-void
-_Unwind_Complete (_Unwind_Control_Block * ucbp __attribute__((unused)))
-{
-}
-
-
-/* Get the _Unwind_Control_Block from an _Unwind_Context.  */
-
-static inline _Unwind_Control_Block *
-unwind_UCB_from_context (_Unwind_Context * context)
-{
-  return (_Unwind_Control_Block *) _Unwind_GetGR (context, R_IP);
-}
-
-
-/* Free an exception.  */
-
-void
-_Unwind_DeleteException (_Unwind_Exception * exc)
-{
-  if (exc->exception_cleanup)
-    (*exc->exception_cleanup) (_URC_FOREIGN_EXCEPTION_CAUGHT, exc);
-}
-
-
-/* Perform stack backtrace through unwind data.  */
-_Unwind_Reason_Code
-__gnu_Unwind_Backtrace(_Unwind_Trace_Fn trace, void * trace_argument,
-                      phase2_vrs * entry_vrs);
-_Unwind_Reason_Code
-__gnu_Unwind_Backtrace(_Unwind_Trace_Fn trace, void * trace_argument,
-                      phase2_vrs * entry_vrs)
-{
-  phase1_vrs saved_vrs;
-  _Unwind_Reason_Code code;
-
-  _Unwind_Control_Block ucb;
-  _Unwind_Control_Block *ucbp = &ucb;
-
-  /* Set the pc to the call site.  */
-  entry_vrs->core.r[R_PC] = entry_vrs->core.r[R_LR];
-
-  /* Save the core registers.  */
-  saved_vrs.core = entry_vrs->core;
-  /* Set demand-save flags.  */
-  saved_vrs.demand_save_flags = ~(_uw) 0;
-  
-  do
-    {
-      /* Find the entry for this routine.  */
-      if (get_eit_entry (ucbp, saved_vrs.core.r[R_PC]) != _URC_OK)
-       {
-         code = _URC_FAILURE;
-         break;
-       }
-
-      /* The dwarf unwinder assumes the context structure holds things
-        like the function and LSDA pointers.  The ARM implementation
-        caches these in the exception header (UCB).  To avoid
-        rewriting everything we make the virtual IP register point at
-        the UCB.  */
-      _Unwind_SetGR((_Unwind_Context *)&saved_vrs, 12, (_Unwind_Ptr) ucbp);
-
-      /* Call trace function.  */
-      if ((*trace) ((_Unwind_Context *) &saved_vrs, trace_argument) 
-         != _URC_NO_REASON)
-       {
-         code = _URC_FAILURE;
-         break;
-       }
-
-      /* Call the pr to decide what to do.  */
-      code = ((personality_routine) UCB_PR_ADDR (ucbp))
-       (_US_VIRTUAL_UNWIND_FRAME | _US_FORCE_UNWIND, 
-        ucbp, (void *) &saved_vrs);
-    }
-  while (code != _URC_END_OF_STACK
-        && code != _URC_FAILURE);
-
-  restore_non_core_regs (&saved_vrs);
-  return code;
-}
-
-
-/* Common implementation for ARM ABI defined personality routines.
-   ID is the index of the personality routine, other arguments are as defined
-   by __aeabi_unwind_cpp_pr{0,1,2}.  */
-
-static _Unwind_Reason_Code
-__gnu_unwind_pr_common (_Unwind_State state,
-                       _Unwind_Control_Block *ucbp,
-                       _Unwind_Context *context,
-                       int id)
-{
-  __gnu_unwind_state uws;
-  _uw *data;
-  _uw offset;
-  _uw len;
-  _uw rtti_count;
-  int phase2_call_unexpected_after_unwind = 0;
-  int in_range = 0;
-  int forced_unwind = state & _US_FORCE_UNWIND;
-
-  state &= _US_ACTION_MASK;
-
-  data = (_uw *) ucbp->pr_cache.ehtp;
-  uws.data = *(data++);
-  uws.next = data;
-  if (id == 0)
-    {
-      uws.data <<= 8;
-      uws.words_left = 0;
-      uws.bytes_left = 3;
-    }
-  else
-    {
-      uws.words_left = (uws.data >> 16) & 0xff;
-      uws.data <<= 16;
-      uws.bytes_left = 2;
-      data += uws.words_left;
-    }
-
-  /* Restore the saved pointer.  */
-  if (state == _US_UNWIND_FRAME_RESUME)
-    data = (_uw *) ucbp->cleanup_cache.bitpattern[0];
-
-  if ((ucbp->pr_cache.additional & 1) == 0)
-    {
-      /* Process descriptors.  */
-      while (*data)
-       {
-         _uw addr;
-         _uw fnstart;
-
-         if (id == 2)
-           {
-             len = ((EHT32 *) data)->length;
-             offset = ((EHT32 *) data)->offset;
-             data += 2;
-           }
-         else
-           {
-             len = ((EHT16 *) data)->length;
-             offset = ((EHT16 *) data)->offset;
-             data++;
-           }
-
-         fnstart = ucbp->pr_cache.fnstart + (offset & ~1);
-         addr = _Unwind_GetGR (context, R_PC);
-         in_range = (fnstart <= addr && addr < fnstart + (len & ~1));
-
-         switch (((offset & 1) << 1) | (len & 1))
-           {
-           case 0:
-             /* Cleanup.  */
-             if (state != _US_VIRTUAL_UNWIND_FRAME
-                 && in_range)
-               {
-                 /* Cleanup in range, and we are running cleanups.  */
-                 _uw lp;
-
-                 /* Landing pad address is 31-bit pc-relative offset.  */
-                 lp = selfrel_offset31 (data);
-                 data++;
-                 /* Save the exception data pointer.  */
-                 ucbp->cleanup_cache.bitpattern[0] = (_uw) data;
-                 if (!__cxa_begin_cleanup (ucbp))
-                   return _URC_FAILURE;
-                 /* Setup the VRS to enter the landing pad.  */
-                 _Unwind_SetGR (context, R_PC, lp);
-                 return _URC_INSTALL_CONTEXT;
-               }
-             /* Cleanup not in range, or we are in stage 1.  */
-             data++;
-             break;
-
-           case 1:
-             /* Catch handler.  */
-             if (state == _US_VIRTUAL_UNWIND_FRAME)
-               {
-                 if (in_range)
-                   {
-                     /* Check for a barrier.  */
-                     _uw rtti;
-                     bool is_reference = (data[0] & uint32_highbit) != 0;
-                     void *matched;
-                     enum __cxa_type_match_result match_type;
-
-                     /* Check for no-throw areas.  */
-                     if (data[1] == (_uw) -2)
-                       return _URC_FAILURE;
-
-                     /* The thrown object immediately follows the ECB.  */
-                     matched = (void *)(ucbp + 1);
-                     if (data[1] != (_uw) -1)
-                       {
-                         /* Match a catch specification.  */
-                         rtti = _Unwind_decode_target2 ((_uw) &data[1]);
-                         match_type = __cxa_type_match (ucbp,
-                                                        (type_info *) rtti,
-                                                        is_reference,
-                                                        &matched);
-                       }
-                     else
-                       match_type = ctm_succeeded;
-
-                     if (match_type)
-                       {
-                         ucbp->barrier_cache.sp =
-                           _Unwind_GetGR (context, R_SP);
-                         // ctm_succeeded_with_ptr_to_base really
-                         // means _c_t_m indirected the pointer
-                         // object.  We have to reconstruct the
-                         // additional pointer layer by using a temporary.
-                         if (match_type == ctm_succeeded_with_ptr_to_base)
-                           {
-                             ucbp->barrier_cache.bitpattern[2]
-                               = (_uw) matched;
-                             ucbp->barrier_cache.bitpattern[0]
-                               = (_uw) &ucbp->barrier_cache.bitpattern[2];
-                           }
-                         else
-                           ucbp->barrier_cache.bitpattern[0] = (_uw) matched;
-                         ucbp->barrier_cache.bitpattern[1] = (_uw) data;
-                         return _URC_HANDLER_FOUND;
-                       }
-                   }
-                 /* Handler out of range, or not matched.  */
-               }
-             else if (ucbp->barrier_cache.sp == _Unwind_GetGR (context, R_SP)
-                      && ucbp->barrier_cache.bitpattern[1] == (_uw) data)
-               {
-                 /* Matched a previous propagation barrier.  */
-                 _uw lp;
-
-                 /* Setup for entry to the handler.  */
-                 lp = selfrel_offset31 (data);
-                 _Unwind_SetGR (context, R_PC, lp);
-                 _Unwind_SetGR (context, 0, (_uw) ucbp);
-                 return _URC_INSTALL_CONTEXT;
-               }
-             /* Catch handler not matched.  Advance to the next descriptor.  */
-             data += 2;
-             break;
-
-           case 2:
-             rtti_count = data[0] & 0x7fffffff;
-             /* Exception specification.  */
-             if (state == _US_VIRTUAL_UNWIND_FRAME)
-               {
-                 if (in_range && (!forced_unwind || !rtti_count))
-                   {
-                     /* Match against the exception specification.  */
-                     _uw i;
-                     _uw rtti;
-                     void *matched;
-
-                     for (i = 0; i < rtti_count; i++)
-                       {
-                         matched = (void *)(ucbp + 1);
-                         rtti = _Unwind_decode_target2 ((_uw) &data[i + 1]);
-                         if (__cxa_type_match (ucbp, (type_info *) rtti, 0,
-                                               &matched))
-                           break;
-                       }
-
-                     if (i == rtti_count)
-                       {
-                         /* Exception does not match the spec.  */
-                         ucbp->barrier_cache.sp =
-                           _Unwind_GetGR (context, R_SP);
-                         ucbp->barrier_cache.bitpattern[0] = (_uw) matched;
-                         ucbp->barrier_cache.bitpattern[1] = (_uw) data;
-                         return _URC_HANDLER_FOUND;
-                       }
-                   }
-                 /* Handler out of range, or exception is permitted.  */
-               }
-             else if (ucbp->barrier_cache.sp == _Unwind_GetGR (context, R_SP)
-                      && ucbp->barrier_cache.bitpattern[1] == (_uw) data)
-               {
-                 /* Matched a previous propagation barrier.  */
-                 _uw lp;
-                 /* Record the RTTI list for __cxa_call_unexpected.  */
-                 ucbp->barrier_cache.bitpattern[1] = rtti_count;
-                 ucbp->barrier_cache.bitpattern[2] = 0;
-                 ucbp->barrier_cache.bitpattern[3] = 4;
-                 ucbp->barrier_cache.bitpattern[4] = (_uw) &data[1];
-
-                 if (data[0] & uint32_highbit)
-                   {
-                     data += rtti_count + 1;
-                     /* Setup for entry to the handler.  */
-                     lp = selfrel_offset31 (data);
-                     data++;
-                     _Unwind_SetGR (context, R_PC, lp);
-                     _Unwind_SetGR (context, 0, (_uw) ucbp);
-                     return _URC_INSTALL_CONTEXT;
-                   }
-                 else
-                   phase2_call_unexpected_after_unwind = 1;
-               }
-             if (data[0] & uint32_highbit)
-               data++;
-             data += rtti_count + 1;
-             break;
-
-           default:
-             /* Should never happen.  */
-             return _URC_FAILURE;
-           }
-         /* Finished processing this descriptor.  */
-       }
-    }
-
-  if (__gnu_unwind_execute (context, &uws) != _URC_OK)
-    return _URC_FAILURE;
-
-  if (phase2_call_unexpected_after_unwind)
-    {
-      /* Enter __cxa_unexpected as if called from the call site.  */
-      _Unwind_SetGR (context, R_LR, _Unwind_GetGR (context, R_PC));
-      _Unwind_SetGR (context, R_PC, (_uw) &__cxa_call_unexpected);
-      return _URC_INSTALL_CONTEXT;
-    }
-
-  return _URC_CONTINUE_UNWIND;
-}
-
-
-/* ABI defined personality routine entry points.  */
-
-_Unwind_Reason_Code
-__aeabi_unwind_cpp_pr0 (_Unwind_State state,
-                       _Unwind_Control_Block *ucbp,
-                       _Unwind_Context *context)
-{
-  return __gnu_unwind_pr_common (state, ucbp, context, 0);
-}
-
-_Unwind_Reason_Code
-__aeabi_unwind_cpp_pr1 (_Unwind_State state,
-                       _Unwind_Control_Block *ucbp,
-                       _Unwind_Context *context)
-{
-  return __gnu_unwind_pr_common (state, ucbp, context, 1);
-}
-
-_Unwind_Reason_Code
-__aeabi_unwind_cpp_pr2 (_Unwind_State state,
-                       _Unwind_Control_Block *ucbp,
-                       _Unwind_Context *context)
-{
-  return __gnu_unwind_pr_common (state, ucbp, context, 2);
-}
diff --git a/gcc/config/arm/unwind-arm.h b/gcc/config/arm/unwind-arm.h
deleted file mode 100644 (file)
index 1a51d8d..0000000
+++ /dev/null
@@ -1,281 +0,0 @@
-/* Header file for the ARM EABI unwinder
-   Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2011
-   Free Software Foundation, Inc.
-   Contributed by Paul Brook
-
-   This file 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 3, or (at your option) any
-   later version.
-
-   This file 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.
-
-   Under Section 7 of GPL version 3, you are granted additional
-   permissions described in the GCC Runtime Library Exception, version
-   3.1, as published by the Free Software Foundation.
-
-   You should have received a copy of the GNU General Public License and
-   a copy of the GCC Runtime Library Exception along with this program;
-   see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
-   <http://www.gnu.org/licenses/>.  */
-
-/* Language-independent unwinder header public defines.  This contains both
-   ABI defined objects, and GNU support routines.  */
-
-#ifndef UNWIND_ARM_H
-#define UNWIND_ARM_H
-
-#define __ARM_EABI_UNWINDER__ 1
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-  typedef unsigned _Unwind_Word __attribute__((__mode__(__word__)));
-  typedef signed _Unwind_Sword __attribute__((__mode__(__word__)));
-  typedef unsigned _Unwind_Ptr __attribute__((__mode__(__pointer__)));
-  typedef unsigned _Unwind_Internal_Ptr __attribute__((__mode__(__pointer__)));
-  typedef _Unwind_Word _uw;
-  typedef unsigned _uw64 __attribute__((mode(__DI__)));
-  typedef unsigned _uw16 __attribute__((mode(__HI__)));
-  typedef unsigned _uw8 __attribute__((mode(__QI__)));
-
-  typedef enum
-    {
-      _URC_OK = 0,       /* operation completed successfully */
-      _URC_FOREIGN_EXCEPTION_CAUGHT = 1,
-      _URC_END_OF_STACK = 5,
-      _URC_HANDLER_FOUND = 6,
-      _URC_INSTALL_CONTEXT = 7,
-      _URC_CONTINUE_UNWIND = 8,
-      _URC_FAILURE = 9   /* unspecified failure of some kind */
-    }
-  _Unwind_Reason_Code;
-
-  typedef enum
-    {
-      _US_VIRTUAL_UNWIND_FRAME = 0,
-      _US_UNWIND_FRAME_STARTING = 1,
-      _US_UNWIND_FRAME_RESUME = 2,
-      _US_ACTION_MASK = 3,
-      _US_FORCE_UNWIND = 8,
-      _US_END_OF_STACK = 16
-    }
-  _Unwind_State;
-
-  /* Provided only for compatibility with existing code.  */
-  typedef int _Unwind_Action;
-#define _UA_SEARCH_PHASE       1
-#define _UA_CLEANUP_PHASE      2
-#define _UA_HANDLER_FRAME      4
-#define _UA_FORCE_UNWIND       8
-#define _UA_END_OF_STACK       16
-#define _URC_NO_REASON         _URC_OK
-
-  typedef struct _Unwind_Control_Block _Unwind_Control_Block;
-  typedef struct _Unwind_Context _Unwind_Context;
-  typedef _uw _Unwind_EHT_Header;
-
-
-  /* UCB: */
-
-  struct _Unwind_Control_Block
-    {
-      char exception_class[8];
-      void (*exception_cleanup)(_Unwind_Reason_Code, _Unwind_Control_Block *);
-      /* Unwinder cache, private fields for the unwinder's use */
-      struct
-       {
-         _uw reserved1;  /* Forced unwind stop fn, 0 if not forced */
-         _uw reserved2;  /* Personality routine address */
-         _uw reserved3;  /* Saved callsite address */
-         _uw reserved4;  /* Forced unwind stop arg */
-         _uw reserved5;
-       }
-      unwinder_cache;
-      /* Propagation barrier cache (valid after phase 1): */
-      struct
-       {
-         _uw sp;
-         _uw bitpattern[5];
-       }
-      barrier_cache;
-      /* Cleanup cache (preserved over cleanup): */
-      struct
-       {
-         _uw bitpattern[4];
-       }
-      cleanup_cache;
-      /* Pr cache (for pr's benefit): */
-      struct
-       {
-         _uw fnstart;                  /* function start address */
-         _Unwind_EHT_Header *ehtp;     /* pointer to EHT entry header word */
-         _uw additional;               /* additional data */
-         _uw reserved1;
-       }
-      pr_cache;
-      long long int :0;        /* Force alignment to 8-byte boundary */
-    };
-
-  /* Virtual Register Set*/
-
-  typedef enum
-    {
-      _UVRSC_CORE = 0,      /* integer register */
-      _UVRSC_VFP = 1,       /* vfp */
-      _UVRSC_FPA = 2,       /* fpa */
-      _UVRSC_WMMXD = 3,     /* Intel WMMX data register */
-      _UVRSC_WMMXC = 4      /* Intel WMMX control register */
-    }
-  _Unwind_VRS_RegClass;
-
-  typedef enum
-    {
-      _UVRSD_UINT32 = 0,
-      _UVRSD_VFPX = 1,
-      _UVRSD_FPAX = 2,
-      _UVRSD_UINT64 = 3,
-      _UVRSD_FLOAT = 4,
-      _UVRSD_DOUBLE = 5
-    }
-  _Unwind_VRS_DataRepresentation;
-
-  typedef enum
-    {
-      _UVRSR_OK = 0,
-      _UVRSR_NOT_IMPLEMENTED = 1,
-      _UVRSR_FAILED = 2
-    }
-  _Unwind_VRS_Result;
-
-  /* Frame unwinding state.  */
-  typedef struct
-    {
-      /* The current word (bytes packed msb first).  */
-      _uw data;
-      /* Pointer to the next word of data.  */
-      _uw *next;
-      /* The number of bytes left in this word.  */
-      _uw8 bytes_left;
-      /* The number of words pointed to by ptr.  */
-      _uw8 words_left;
-    }
-  __gnu_unwind_state;
-
-  typedef _Unwind_Reason_Code (*personality_routine) (_Unwind_State,
-      _Unwind_Control_Block *, _Unwind_Context *);
-
-  _Unwind_VRS_Result _Unwind_VRS_Set(_Unwind_Context *, _Unwind_VRS_RegClass,
-                                     _uw, _Unwind_VRS_DataRepresentation,
-                                     void *);
-
-  _Unwind_VRS_Result _Unwind_VRS_Get(_Unwind_Context *, _Unwind_VRS_RegClass,
-                                     _uw, _Unwind_VRS_DataRepresentation,
-                                     void *);
-
-  _Unwind_VRS_Result _Unwind_VRS_Pop(_Unwind_Context *, _Unwind_VRS_RegClass,
-                                     _uw, _Unwind_VRS_DataRepresentation);
-
-
-  /* Support functions for the PR.  */
-#define _Unwind_Exception _Unwind_Control_Block
-  typedef char _Unwind_Exception_Class[8];
-
-  void * _Unwind_GetLanguageSpecificData (_Unwind_Context *);
-  _Unwind_Ptr _Unwind_GetRegionStart (_Unwind_Context *);
-
-  /* These two should never be used.  */
-  _Unwind_Ptr _Unwind_GetDataRelBase (_Unwind_Context *);
-  _Unwind_Ptr _Unwind_GetTextRelBase (_Unwind_Context *);
-
-  /* Interface functions: */
-  _Unwind_Reason_Code _Unwind_RaiseException(_Unwind_Control_Block *ucbp);
-  void __attribute__((noreturn)) _Unwind_Resume(_Unwind_Control_Block *ucbp);
-  _Unwind_Reason_Code _Unwind_Resume_or_Rethrow (_Unwind_Control_Block *ucbp);
-
-  typedef _Unwind_Reason_Code (*_Unwind_Stop_Fn)
-       (int, _Unwind_Action, _Unwind_Exception_Class,
-       _Unwind_Control_Block *, struct _Unwind_Context *, void *);
-  _Unwind_Reason_Code _Unwind_ForcedUnwind (_Unwind_Control_Block *,
-                                           _Unwind_Stop_Fn, void *);
-  /* @@@ Use unwind data to perform a stack backtrace.  The trace callback
-     is called for every stack frame in the call chain, but no cleanup
-     actions are performed.  */
-  typedef _Unwind_Reason_Code (*_Unwind_Trace_Fn) (_Unwind_Context *, void *);
-  _Unwind_Reason_Code _Unwind_Backtrace(_Unwind_Trace_Fn,
-                                       void*);
-
-  _Unwind_Word _Unwind_GetCFA (struct _Unwind_Context *);
-  void _Unwind_Complete(_Unwind_Control_Block *ucbp);
-  void _Unwind_DeleteException (_Unwind_Exception *);
-
-  _Unwind_Reason_Code __gnu_unwind_frame (_Unwind_Control_Block *,
-                                         _Unwind_Context *);
-  _Unwind_Reason_Code __gnu_unwind_execute (_Unwind_Context *,
-                                           __gnu_unwind_state *);
-
-  /* Decode an R_ARM_TARGET2 relocation.  */
-  static inline _Unwind_Word
-  _Unwind_decode_target2 (_Unwind_Word ptr)
-    {
-      _Unwind_Word tmp;
-
-      tmp = *(_Unwind_Word *) ptr;
-      /* Zero values are always NULL.  */
-      if (!tmp)
-       return 0;
-
-#if (defined(linux) && !defined(__uClinux__)) || defined(__NetBSD__)
-      /* Pc-relative indirect.  */
-      tmp += ptr;
-      tmp = *(_Unwind_Word *) tmp;
-#elif defined(__symbian__) || defined(__uClinux__)
-      /* Absolute pointer.  Nothing more to do.  */
-#else
-      /* Pc-relative pointer.  */
-      tmp += ptr;
-#endif
-      return tmp;
-    }
-
-  static inline _Unwind_Word
-  _Unwind_GetGR (_Unwind_Context *context, int regno)
-    {
-      _uw val;
-      _Unwind_VRS_Get (context, _UVRSC_CORE, regno, _UVRSD_UINT32, &val);
-      return val;
-    }
-
-  /* Return the address of the instruction, not the actual IP value.  */
-#define _Unwind_GetIP(context) \
-  (_Unwind_GetGR (context, 15) & ~(_Unwind_Word)1)
-
-#define _Unwind_GetIPInfo(context, ip_before_insn) \
-  (*ip_before_insn = 0, _Unwind_GetGR (context, 15) & ~(_Unwind_Word)1)
-
-  static inline void
-  _Unwind_SetGR (_Unwind_Context *context, int regno, _Unwind_Word val)
-    {
-      _Unwind_VRS_Set (context, _UVRSC_CORE, regno, _UVRSD_UINT32, &val);
-    }
-
-  /* The dwarf unwinder doesn't understand arm/thumb state.  We assume the
-     landing pad uses the same instruction set as the call site.  */
-#define _Unwind_SetIP(context, val) \
-  _Unwind_SetGR (context, 15, val | (_Unwind_GetGR (context, 15) & 1))
-
-/* leb128 type numbers have a potentially unlimited size.
-   The target of the following definitions of _sleb128_t and _uleb128_t
-   is to have efficient data types large enough to hold the leb128 type
-   numbers used in the unwind code.  */
-typedef long _sleb128_t;
-typedef unsigned long _uleb128_t;
-
-#ifdef __cplusplus
-}   /* extern "C" */
-#endif
-
-#endif /* defined UNWIND_ARM_H */
index 0c58bb1671343c3e6b9846ca5663b5330eb6252d..2729008879c482f5019349810b8863c1c7a0fa07 100644 (file)
@@ -1,4 +1,4 @@
-# Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc.
+# Copyright (C) 2002, 2003, 2004, 2011 Free Software Foundation, Inc.
 #
 # This file is part of GCC.
 #
@@ -81,12 +81,12 @@ EXTRA_MULTILIB_PARTS=frvbegin.o frvend.o
 FRVSTUFF_CFLAGS = $(TARGET_LIBGCC2_CFLAGS)
 
 $(T)frvbegin$(objext): $(srcdir)/config/frv/frvbegin.c $(GCC_PASSES) \
-  $(CONFIG_H) defaults.h unwind-dw2-fde.h gbl-ctors.h
+  $(CONFIG_H) defaults.h $(srcdir)/../libgcc/unwind-dw2-fde.h gbl-ctors.h
        $(GCC_FOR_TARGET) $(GCC_CFLAGS) $(INCLUDES) $(MULTILIB_CFLAGS) $(FRVSTUFF_CFLAGS) \
          -c $(srcdir)/config/frv/frvbegin.c -o $(T)frvbegin$(objext)
 
 $(T)frvend$(objext): $(srcdir)/config/frv/frvend.c $(GCC_PASSES) \
-  $(CONFIG_H) defaults.h unwind-dw2-fde.h gbl-ctors.h
+  $(CONFIG_H) defaults.h $(srcdir)/../libgcc/unwind-dw2-fde.h gbl-ctors.h
        $(GCC_FOR_TARGET) $(GCC_CFLAGS) $(INCLUDES) $(MULTILIB_CFLAGS) $(FRVSTUFF_CFLAGS) \
          -c $(srcdir)/config/frv/frvend.c -o $(T)frvend$(objext)
 
diff --git a/gcc/config/ia64/fde-glibc.c b/gcc/config/ia64/fde-glibc.c
deleted file mode 100644 (file)
index 12760b9..0000000
+++ /dev/null
@@ -1,162 +0,0 @@
-/* Copyright (C) 2000, 2001, 2003, 2009 Free Software Foundation, Inc.
-   Contributed by Richard Henderson <rth@cygnus.com>.
-
-   This file is part of GCC.
-
-   GCC 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 3, or (at your option)
-   any later version.
-
-   GCC 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.
-
-   Under Section 7 of GPL version 3, you are granted additional
-   permissions described in the GCC Runtime Library Exception, version
-   3.1, as published by the Free Software Foundation.
-
-   You should have received a copy of the GNU General Public License and
-   a copy of the GCC Runtime Library Exception along with this program;
-   see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
-   <http://www.gnu.org/licenses/>.  */
-
-/* Locate the FDE entry for a given address, using glibc ld.so routines
-   to avoid register/deregister calls at DSO load/unload.  */
-
-#ifndef _GNU_SOURCE
-#define _GNU_SOURCE 1
-#endif
-#include "config.h"
-#include <stddef.h>
-#include <stdlib.h>
-#include <link.h>
-#include "unwind-ia64.h"
-
-#if __GLIBC__ < 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ < 2) \
-    || (__GLIBC__ == 2 && __GLIBC_MINOR__ == 2 && !defined(DT_CONFIG))
-# error You need GLIBC 2.2.4 or later on IA-64 Linux
-#endif
-
-struct unw_ia64_callback_data
-{
-  Elf64_Addr pc;
-  unsigned long *segment_base;
-  unsigned long *gp;
-  struct unw_table_entry *ret;
-};
-
-static int
-_Unwind_IteratePhdrCallback (struct dl_phdr_info *info, size_t size, void *ptr)
-{
-  struct unw_ia64_callback_data *data = (struct unw_ia64_callback_data *) ptr;
-  const Elf64_Phdr *phdr, *p_unwind, *p_dynamic;
-  long n, match;
-  Elf64_Addr load_base, seg_base;
-  struct unw_table_entry *f_base, *f;
-  size_t lo, hi;
-
-  /* Make sure struct dl_phdr_info is at least as big as we need.  */
-  if (size < offsetof (struct dl_phdr_info, dlpi_phnum)
-            + sizeof (info->dlpi_phnum))
-    return -1;
-
-  match = 0;
-  phdr = info->dlpi_phdr;
-  load_base = info->dlpi_addr;
-  p_unwind = NULL;
-  p_dynamic = NULL;
-  seg_base = ~(Elf64_Addr) 0;
-
-  /* See if PC falls into one of the loaded segments.  Find the unwind
-     segment at the same time.  */
-  for (n = info->dlpi_phnum; --n >= 0; phdr++)
-    {
-      if (phdr->p_type == PT_LOAD)
-       {
-         Elf64_Addr vaddr = phdr->p_vaddr + load_base;
-         if (data->pc >= vaddr && data->pc < vaddr + phdr->p_memsz)
-           match = 1;
-         if (vaddr < seg_base)
-           seg_base = vaddr;
-       }
-      else if (phdr->p_type == PT_IA_64_UNWIND)
-       p_unwind = phdr;
-      else if (phdr->p_type == PT_DYNAMIC)
-       p_dynamic = phdr;
-    }
-  if (!match || !p_unwind)
-    return 0;
-
-  /* Search for the FDE within the unwind segment.  */
-
-  f_base = (struct unw_table_entry *) (p_unwind->p_vaddr + load_base);
-  lo = 0;
-  hi = p_unwind->p_memsz / sizeof (struct unw_table_entry);
-
-  while (lo < hi)
-    {
-      size_t mid = (lo + hi) / 2;
-
-      f = f_base + mid;
-      if (data->pc < f->start_offset + seg_base)
-       hi = mid;
-      else if (data->pc >= f->end_offset + seg_base)
-       lo = mid + 1;
-      else
-        goto found;
-    }
-  /* No need to search for further libraries when we know pc is contained
-     in this library.  */
-  return 1;
-
- found:
-  *data->segment_base = seg_base;
-  *data->gp = 0;
-  data->ret = f;
-
-  if (p_dynamic)
-    {
-      /* For dynamically linked executables and shared libraries,
-        DT_PLTGOT is the gp value for that object.  */
-      Elf64_Dyn *dyn = (Elf64_Dyn *)(p_dynamic->p_vaddr + load_base);
-      for (; dyn->d_tag != DT_NULL ; dyn++)
-       if (dyn->d_tag == DT_PLTGOT)
-         {
-           /* On IA-64, _DYNAMIC is writable and GLIBC has relocated it.  */
-           *data->gp = dyn->d_un.d_ptr;
-           break;
-         }
-    }
-  else
-    {
-      /* Otherwise this is a static executable with no _DYNAMIC.
-        The gp is constant program-wide.  */
-      register unsigned long gp __asm__("gp");
-      *data->gp = gp;
-    }
-
-  return 1;
-}
-
-/* Return a pointer to the unwind table entry for the function
-   containing PC.  */
-
-struct unw_table_entry *
-_Unwind_FindTableEntry (void *pc, unsigned long *segment_base,
-                        unsigned long *gp,
-                        struct unw_table_entry *ent ATTRIBUTE_UNUSED)
-{
-  struct unw_ia64_callback_data data;
-
-  data.pc = (Elf64_Addr) pc;
-  data.segment_base = segment_base;
-  data.gp = gp;
-  data.ret = NULL;
-
-  if (dl_iterate_phdr (_Unwind_IteratePhdrCallback, &data) < 0)
-    return NULL;
-
-  return data.ret;
-}
diff --git a/gcc/config/ia64/fde-vms.c b/gcc/config/ia64/fde-vms.c
deleted file mode 100644 (file)
index b310f0d..0000000
+++ /dev/null
@@ -1,157 +0,0 @@
-/* Copyright (C) 2004, 2009 Free Software Foundation, Inc.
-   Contributed by Douglas B Rupp <rupp@gnat.com>
-
-   This file is part of GCC.
-
-   GCC 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 3, or (at your option)
-   any later version.
-
-   GCC 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.
-
-   Under Section 7 of GPL version 3, you are granted additional
-   permissions described in the GCC Runtime Library Exception, version
-   3.1, as published by the Free Software Foundation.
-
-   You should have received a copy of the GNU General Public License and
-   a copy of the GCC Runtime Library Exception along with this program;
-   see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
-   <http://www.gnu.org/licenses/>.  */
-
-/* Locate the FDE entry for a given address, using VMS Starlet routines
-   to avoid register/deregister calls at DSO load/unload.  */
-
-#include "tconfig.h"
-#include "tsystem.h"
-#include "coretypes.h"
-#include "tm.h"
-#include <stddef.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include "unwind-ia64.h"
-
-#define __int64 long
-#include <vms/ossddef.h>
-#ifndef SS$_NORMAL
-#define SS$_NORMAL 1
-#endif
-
-typedef struct
-{
-  unsigned long start_offset;
-  unsigned long end_offset;
-  unsigned long info_offset;
-  unsigned long gp_value;
-}  vms_unw_table_entry;
-
-typedef unsigned long long uqword;
-
-/* ENTRY is the unwind table entry found for a PC part of call chain we're
-   unwinding through.  Return whether we should force the generic unwinder
-   to resort to "fallback" processing.  */
-   
-static int
-force_fallback_processing_for (void * pc, vms_unw_table_entry * entry)
-{
-  static int eh_debug = -1;
-
-  uqword * unw_info_block = (uqword *)entry->info_offset;
-  uqword header = *unw_info_block;
-
-  /* We need to force fallback processing in two cases:
-
-     1/ The exception dispatch frame, since only our fallback
-        processing knows how to properly unwind through it, and
-
-     2/ A bottom of stack frame, since only our fallback processing
-        will ensure we don't try to unwind further past it, which
-        would get us into unknown territory and likely cause a severe
-        crash along the way.
-
-     The two cases are indicated by non-default values for specific
-     bits in the OS Specific Data (OSSD) General Information block
-     associated with such frames.  */
-
-  ossddef * ossd;
-
-  if (eh_debug == -1)
-    {
-      char * EH_DEBUG = getenv ("EH_DEBUG");
-      eh_debug = EH_DEBUG ? atoi (EH_DEBUG) : 0;
-    }
-
-  if (eh_debug)
-    {
-      printf ("pc @ 0x%p, block @ 0x%p, header = 0x%016llx\n",
-             pc, unw_info_block, header);
-      printf ("mode = %d, length = %ld, handler = %d\n",
-             (int)UNW_IVMS_MODE (header), UNW_LENGTH (header),
-             UNW_FLAG_EHANDLER (header) || UNW_FLAG_EHANDLER (header));
-    }
-
-  /* An OSSD block is there for IVMS_MODE == 3 only.  */
-  if (UNW_IVMS_MODE (header) != 3)
-    return 0;
-
-  /* The OSSD block is found past the header, unwind descriptor area
-     and condition handler pointer, if any.  */  
-  ossd = (ossddef *)
-    /* Beware: uqword pointer arithmetic below.  */
-    (unw_info_block
-     + 1
-     + UNW_LENGTH (header)
-     + (UNW_FLAG_EHANDLER (header) || UNW_FLAG_EHANDLER (header)));
-
-  /* "A General Information segment may be omitted if all of its fields
-      would have their default values.  If a General Information segment
-      is present, it must be the first in the OSSD area."  So ...  */
-  
-  if (eh_debug)
-    printf ("ossd @ 0x%p\n", ossd);
-      
-  if (eh_debug && ossd->ossd$v_type == OSSD$K_GENERAL_INFO)
-    printf ("exc_frame = %d - bot_frame = %d - base_frame = %d\n",
-           ossd->ossd$v_exception_frame, 
-           ossd->ossd$v_bottom_of_stack,
-           ossd->ossd$v_base_frame);
-                               
-  return
-    ossd->ossd$v_type == OSSD$K_GENERAL_INFO
-    && (ossd->ossd$v_exception_frame
-       || ossd->ossd$v_bottom_of_stack || ossd->ossd$v_base_frame);
-}
-
-/* Return a pointer to the unwind table entry for the function
-   containing PC, 0 if we cannot find an entry or if the one we find
-   calls for fallback processing.  */
-
-struct unw_table_entry *
-_Unwind_FindTableEntry (void *pc, unsigned long *segment_base,
-                        unsigned long *gp, struct unw_table_entry *ent)
-{
-  vms_unw_table_entry vueblock;
-
-  if (SYS$GET_UNWIND_ENTRY_INFO (pc, &vueblock, 0) != SS$_NORMAL)
-    return 0;
-
-  /* If there is no unwind information, use fallback.  */
-  if (vueblock.info_offset == 0)
-    return 0;
-
-  /* If we need to force fallback processing, just pretend there is
-     no entry.  */
-  if (force_fallback_processing_for (pc, &vueblock))
-    return 0;
-
-  *segment_base = 0; /* ??? Fixme. ??? */
-  *gp = vueblock.gp_value;
-  ent->start_offset = vueblock.start_offset;
-  ent->end_offset = vueblock.end_offset;
-  ent->info_offset = vueblock.info_offset;
-
-  return ent;
-}
index e6d72b94a871469a94600edb54608bf3a96e2e3b..ce18a92e27582aba97aefaf0e6eaf53f67337485 100644 (file)
@@ -1,5 +1 @@
-# Use system libunwind library on IA-64 GLIBC based system.
-LIB2ADDEH = $(srcdir)/unwind-sjlj.c $(srcdir)/unwind-c.c \
-  $(srcdir)/unwind-compat.c
-
 SHLIB_MAPFILES += $(srcdir)/config/ia64/libgcc-glibc.ver
diff --git a/gcc/config/ia64/t-glibc-libunwind b/gcc/config/ia64/t-glibc-libunwind
deleted file mode 100644 (file)
index df78f1d..0000000
+++ /dev/null
@@ -1,4 +0,0 @@
-# Build libunwind for IA-64 GLIBC based system.
-LIBUNWIND = $(srcdir)/config/ia64/fde-glibc.c \
-  $(srcdir)/config/ia64/unwind-ia64.c
-LIBUNWINDDEP = unwind.inc
index a97ab5c4478ff686cb10241af76a4981c03a0623..4aa661441b2b0ba034d2a9a97675353daa689b07 100644 (file)
@@ -1,5 +1,5 @@
 # Copyright (C) 2001, 2002, 2003, 2004, 2005,
-# 2006 Free Software Foundation, Inc.
+# 2006, 2011 Free Software Foundation, Inc.
 #
 # This file is part of GCC.
 #
@@ -50,8 +50,6 @@ LIBGCC1_TEST =
 
 T_CFLAGS += -DUSE_LIBUNWIND_EXCEPTIONS
 
-LIB2ADDEH = $(srcdir)/unwind-c.c
-
 SHLIB_EXT = .so
 # Must include -lunwind in the link, so that libgcc_s.so has the necessary
 # DT_NEEDED entry for libunwind.
index 4f013e2d591ae0b2541b2989fbb95ee73c1ebddc..f130f7c09d13c8c0db5452c291caa417f1bd1542 100644 (file)
@@ -43,9 +43,6 @@ SHLIB_MAPFILES += $(srcdir)/config/ia64/libgcc-ia64.ver
 # Effectively disable the crtbegin/end rules using crtstuff.c
 T = disable
 
-LIB2ADDEH = $(srcdir)/config/ia64/unwind-ia64.c $(srcdir)/unwind-sjlj.c \
-  $(srcdir)/unwind-c.c
-
 ia64-c.o: $(srcdir)/config/ia64/ia64-c.c $(CONFIG_H) $(SYSTEM_H) \
     coretypes.h $(TM_H) $(TREE_H) $(CPPLIB_H) $(C_COMMON_H) $(C_PRAGMA_H)
        $(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \
index bcd753401f1d6ce205349a196a1b44f9429092fa..094d53483ee50cbd1ef70d6bb8cba405be159e32 100644 (file)
@@ -32,8 +32,6 @@ $(T)crtinitS.o: $(srcdir)/config/ia64/vms-crtinit.asm $(GCC_PASSES)
        $(GCC_FOR_TARGET) -I. -c -o $(T)crtinitS.o -x assembler-with-cpp \
                $(srcdir)/config/ia64/vms-crtinit.asm
 
-LIB2ADDEH += $(srcdir)/config/ia64/fde-vms.c
-
 # Shared library macros
 shlib_version:=$(shell echo $(BASEVER_c) | sed -e 's/\./,/' -e 's/\.//g')
 SHLIB_EXT = .exe
diff --git a/gcc/config/ia64/unwind-ia64.c b/gcc/config/ia64/unwind-ia64.c
deleted file mode 100644 (file)
index 061bd4b..0000000
+++ /dev/null
@@ -1,2458 +0,0 @@
-/* Subroutines needed for unwinding IA-64 standard format stack frame
-   info for exception handling.
-   Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2004, 2005, 2006,
-   2009, 2011  Free Software Foundation, Inc.
-   Contributed by Andrew MacLeod  <amacleod@cygnus.com>
-                 Andrew Haley  <aph@cygnus.com>
-                 David Mosberger-Tang <davidm@hpl.hp.com>
-
-   This file is part of GCC.
-
-   GCC 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 3, or (at your option)
-   any later version.
-
-   GCC 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.
-
-   Under Section 7 of GPL version 3, you are granted additional
-   permissions described in the GCC Runtime Library Exception, version
-   3.1, as published by the Free Software Foundation.
-
-   You should have received a copy of the GNU General Public License and
-   a copy of the GCC Runtime Library Exception along with this program;
-   see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
-   <http://www.gnu.org/licenses/>.  */
-
-#include "tconfig.h"
-#include "tsystem.h"
-#include "coretypes.h"
-#include "tm.h"
-#include "unwind.h"
-#include "unwind-ia64.h"
-#include "unwind-compat.h"
-#include "ia64intrin.h"
-
-/* This isn't thread safe, but nice for occasional tests.  */
-#undef ENABLE_MALLOC_CHECKING
-
-#ifndef __USING_SJLJ_EXCEPTIONS__
-
-
-/* By default, assume personality routine interface compatibility with
-   our expectations.  */
-#ifndef MD_UNW_COMPATIBLE_PERSONALITY_P
-#define MD_UNW_COMPATIBLE_PERSONALITY_P(HEADER) 1
-#endif
-
-enum unw_application_register
-{
-  UNW_AR_BSP,
-  UNW_AR_BSPSTORE,
-  UNW_AR_PFS,
-  UNW_AR_RNAT,
-  UNW_AR_UNAT,
-  UNW_AR_LC,
-  UNW_AR_EC,
-  UNW_AR_FPSR,
-  UNW_AR_RSC,
-  UNW_AR_CCV
-};
-
-enum unw_register_index
-{
-  /* Primary UNAT.  */
-  UNW_REG_PRI_UNAT_GR,
-  UNW_REG_PRI_UNAT_MEM,
-
-  /* Memory Stack.  */
-  UNW_REG_PSP,                 /* previous memory stack pointer */
-
-  /* Register Stack.  */
-  UNW_REG_BSP,                 /* register stack pointer */
-  UNW_REG_BSPSTORE,
-  UNW_REG_PFS,                 /* previous function state */
-  UNW_REG_RNAT,
-  /* Return Pointer.  */
-  UNW_REG_RP,
-
-  /* Special preserved registers.  */
-  UNW_REG_UNAT, UNW_REG_PR, UNW_REG_LC, UNW_REG_FPSR,
-
-  /* Non-stacked general registers.  */
-  UNW_REG_R2,
-  UNW_REG_R4 = UNW_REG_R2 + 2,
-  UNW_REG_R7 = UNW_REG_R2 + 5,
-  UNW_REG_R31 = UNW_REG_R2 + 29,
-
-  /* Non-stacked floating point registers.  */
-  UNW_REG_F2,
-  UNW_REG_F5 = UNW_REG_F2 + 3,
-  UNW_REG_F16 = UNW_REG_F2 + 14,
-  UNW_REG_F31 = UNW_REG_F2 + 29,
-
-  /* Branch registers.  */
-  UNW_REG_B0, UNW_REG_B1,
-  UNW_REG_B5 = UNW_REG_B1 + 4,
-
-  UNW_NUM_REGS
-};
-
-enum unw_where
-{
-  UNW_WHERE_NONE,      /* register isn't saved at all */
-  UNW_WHERE_GR,                /* register is saved in a general register */
-  UNW_WHERE_FR,                /* register is saved in a floating-point register */
-  UNW_WHERE_BR,                /* register is saved in a branch register */
-  UNW_WHERE_SPREL,     /* register is saved on memstack (sp-relative) */
-  UNW_WHERE_PSPREL,    /* register is saved on memstack (psp-relative) */
- /* At the end of each prologue these locations get resolved to
-     UNW_WHERE_PSPREL and UNW_WHERE_GR, respectively.  */
-  UNW_WHERE_SPILL_HOME,        /* register is saved in its spill home */
-  UNW_WHERE_GR_SAVE    /* register is saved in next general register */
-};
-
-#define UNW_WHEN_NEVER  0x7fffffff
-
-struct unw_reg_info
-{
-  unsigned long val;           /* save location: register number or offset */
-  enum unw_where where;                /* where the register gets saved */
-  int when;                    /* when the register gets saved */
-};
-
-struct unw_reg_state {
-       struct unw_reg_state *next;     /* next (outer) element on state stack */
-       struct unw_reg_info reg[UNW_NUM_REGS];  /* register save locations */
-};
-
-struct unw_labeled_state {
-       struct unw_labeled_state *next;         /* next labeled state (or NULL) */
-       unsigned long label;                    /* label for this state */
-       struct unw_reg_state saved_state;
-};
-
-typedef struct unw_state_record
-{
-  unsigned int first_region : 1;       /* is this the first region? */
-  unsigned int done : 1;               /* are we done scanning descriptors? */
-  unsigned int any_spills : 1;         /* got any register spills? */
-  unsigned int in_body : 1;    /* are we inside a body? */
-  unsigned int no_reg_stack_frame : 1; /* Don't adjust bsp for i&l regs */
-  unsigned char *imask;                /* imask of spill_mask record or NULL */
-  unsigned long pr_val;                /* predicate values */
-  unsigned long pr_mask;       /* predicate mask */
-  long spill_offset;           /* psp-relative offset for spill base */
-  int region_start;
-  int region_len;
-  int epilogue_start;
-  int epilogue_count;
-  int when_target;
-
-  unsigned char gr_save_loc;   /* next general register to use for saving */
-  unsigned char return_link_reg; /* branch register for return link */
-  unsigned short unwabi;
-
-  struct unw_labeled_state *labeled_states;    /* list of all labeled states */
-  struct unw_reg_state curr;   /* current state */
-
-  _Unwind_Personality_Fn personality;
-  
-} _Unwind_FrameState;
-
-enum unw_nat_type
-{
-  UNW_NAT_NONE,                        /* NaT not represented */
-  UNW_NAT_VAL,                 /* NaT represented by NaT value (fp reg) */
-  UNW_NAT_MEMSTK,              /* NaT value is in unat word at offset OFF  */
-  UNW_NAT_REGSTK               /* NaT is in rnat */
-};
-
-struct unw_stack
-{
-  unsigned long limit;
-  unsigned long top;
-};
-
-struct _Unwind_Context
-{
-  /* Initial frame info.  */
-  unsigned long rnat;          /* rse nat collection */
-  unsigned long regstk_top;    /* lowest address of rbs stored register
-                                  which uses context->rnat collection */
-
-  /* Current frame info.  */
-  unsigned long bsp;           /* backing store pointer value
-                                  corresponding to psp.  */
-  unsigned long sp;            /* stack pointer value */
-  unsigned long psp;           /* previous sp value */
-  unsigned long rp;            /* return pointer */
-  unsigned long pr;            /* predicate collection */
-
-  unsigned long region_start;  /* start of unwind region */
-  unsigned long gp;            /* global pointer value */
-  void *lsda;                  /* language specific data area */
-
-  /* Preserved state.  */
-  unsigned long *bsp_loc;      /* previous bsp save location
-                                  Appears to be write-only?    */
-  unsigned long *bspstore_loc;
-  unsigned long *pfs_loc;      /* Save location for pfs in current
-                                  (corr. to sp) frame.  Target
-                                  contains cfm for caller.     */
-  unsigned long *signal_pfs_loc;/* Save location for pfs in current
-                                  signal frame.  Target contains
-                                  pfs for caller.  */
-  unsigned long *pri_unat_loc;
-  unsigned long *unat_loc;
-  unsigned long *lc_loc;
-  unsigned long *fpsr_loc;
-
-  unsigned long eh_data[4];
-
-  struct unw_ireg
-  {
-    unsigned long *loc;
-    struct unw_ireg_nat
-    {
-      enum unw_nat_type type : 3;
-      signed long off : 61;            /* NaT word is at loc+nat.off */
-    } nat;
-  } ireg[32 - 2];      /* Indexed by <register number> - 2 */
-
-  unsigned long *br_loc[8];
-  void *fr_loc[32 - 2];
-
-  /* ??? We initially point pri_unat_loc here.  The entire NAT bit
-     logic needs work.  */
-  unsigned long initial_unat;
-};
-
-typedef unsigned long unw_word;
-
-/* Implicit register save order.  See section 11.4.2.3 Rules for Using
-   Unwind Descriptors, rule 3.  */
-
-static unsigned char const save_order[] =
-{
-  UNW_REG_RP, UNW_REG_PFS, UNW_REG_PSP, UNW_REG_PR,
-  UNW_REG_UNAT, UNW_REG_LC, UNW_REG_FPSR, UNW_REG_PRI_UNAT_GR
-};
-
-\f
-#define MIN(X, Y) ((X) < (Y) ? (X) : (Y))
-
-/* MASK is a bitmap describing the allocation state of emergency buffers,
-   with bit set indicating free. Return >= 0 if allocation is successful;
-   < 0 if failure.  */
-
-static inline int
-atomic_alloc (unsigned int *mask)
-{
-  unsigned int old = *mask, ret, new;
-
-  while (1)
-    {
-      if (old == 0)
-       return -1;
-      ret = old & -old;
-      new = old & ~ret;
-      new = __sync_val_compare_and_swap (mask, old, new);
-      if (old == new)
-       break;
-      old = new;
-    }
-
-  return __builtin_ffs (ret) - 1;
-}
-
-/* Similarly, free an emergency buffer.  */
-
-static inline void
-atomic_free (unsigned int *mask, int bit)
-{
-  __sync_xor_and_fetch (mask, 1 << bit);
-}
-
-
-#define SIZE(X)                (sizeof(X) / sizeof(*(X)))
-#define MASK_FOR(X)    ((2U << (SIZE (X) - 1)) - 1)
-#define PTR_IN(X, P)   ((P) >= (X) && (P) < (X) + SIZE (X))
-
-static struct unw_reg_state emergency_reg_state[32];
-static unsigned int emergency_reg_state_free = MASK_FOR (emergency_reg_state);
-
-static struct unw_labeled_state emergency_labeled_state[8];
-static unsigned int emergency_labeled_state_free = MASK_FOR (emergency_labeled_state);
-
-#ifdef ENABLE_MALLOC_CHECKING
-static int reg_state_alloced;
-static int labeled_state_alloced;
-#endif
-
-/* Allocation and deallocation of structures.  */
-
-static struct unw_reg_state *
-alloc_reg_state (void)
-{
-  struct unw_reg_state *rs;
-
-#ifdef ENABLE_MALLOC_CHECKING
-  reg_state_alloced++;
-#endif
-
-  rs = malloc (sizeof (struct unw_reg_state));
-  if (!rs)
-    {
-      int n = atomic_alloc (&emergency_reg_state_free);
-      if (n >= 0)
-       rs = &emergency_reg_state[n];
-    }
-
-  return rs;
-}
-
-static void
-free_reg_state (struct unw_reg_state *rs)
-{
-#ifdef ENABLE_MALLOC_CHECKING
-  reg_state_alloced--;
-#endif
-
-  if (PTR_IN (emergency_reg_state, rs))
-    atomic_free (&emergency_reg_state_free, rs - emergency_reg_state);
-  else
-    free (rs);
-}
-
-static struct unw_labeled_state *
-alloc_label_state (void)
-{
-  struct unw_labeled_state *ls;
-
-#ifdef ENABLE_MALLOC_CHECKING
-  labeled_state_alloced++;
-#endif
-
-  ls = malloc(sizeof(struct unw_labeled_state));
-  if (!ls)
-    {
-      int n = atomic_alloc (&emergency_labeled_state_free);
-      if (n >= 0)
-       ls = &emergency_labeled_state[n];
-    }
-
-  return ls;
-}
-
-static void
-free_label_state (struct unw_labeled_state *ls)
-{
-#ifdef ENABLE_MALLOC_CHECKING
-  labeled_state_alloced--;
-#endif
-
-  if (PTR_IN (emergency_labeled_state, ls))
-    atomic_free (&emergency_labeled_state_free, emergency_labeled_state - ls);
-  else
-    free (ls);
-}
-
-/* Routines to manipulate the state stack.  */
-
-static void
-push (struct unw_state_record *sr)
-{
-  struct unw_reg_state *rs = alloc_reg_state ();
-  memcpy (rs, &sr->curr, sizeof (*rs));
-  sr->curr.next = rs;
-}
-
-static void
-pop (struct unw_state_record *sr)
-{
-  struct unw_reg_state *rs = sr->curr.next;
-
-  if (!rs)
-    abort ();
-  memcpy (&sr->curr, rs, sizeof(*rs));
-  free_reg_state (rs);
-}
-
-/* Make a copy of the state stack.  Non-recursive to avoid stack overflows.  */
-
-static struct unw_reg_state *
-dup_state_stack (struct unw_reg_state *rs)
-{
-  struct unw_reg_state *copy, *prev = NULL, *first = NULL;
-
-  while (rs)
-    {
-      copy = alloc_reg_state ();
-      memcpy (copy, rs, sizeof(*copy));
-      if (first)
-       prev->next = copy;
-      else
-       first = copy;
-      rs = rs->next;
-      prev = copy;
-    }
-
-  return first;
-}
-
-/* Free all stacked register states (but not RS itself).  */
-static void
-free_state_stack (struct unw_reg_state *rs)
-{
-  struct unw_reg_state *p, *next;
-
-  for (p = rs->next; p != NULL; p = next)
-    {
-      next = p->next;
-      free_reg_state (p);
-    }
-  rs->next = NULL;
-}
-
-/* Free all labeled states.  */
-
-static void
-free_label_states (struct unw_labeled_state *ls)
-{
-  struct unw_labeled_state *next;
-
-  for (; ls ; ls = next)
-    {
-      next = ls->next;
-
-      free_state_stack (&ls->saved_state);
-      free_label_state (ls);
-    }
-}
-\f
-/* Unwind decoder routines */
-
-static enum unw_register_index __attribute__((const))
-decode_abreg (unsigned char abreg, int memory)
-{
-  switch (abreg)
-    {
-#if TARGET_ABI_OPEN_VMS
-    /* OpenVMS Calling Standard specifies R3 - R31.  */
-    case 0x03 ... 0x1f: return UNW_REG_R2 + (abreg - 0x02);
-#else
-    /* Standard Intel ABI specifies GR 4 - 7.  */
-    case 0x04 ... 0x07: return UNW_REG_R4 + (abreg - 0x04);
-#endif
-    case 0x22 ... 0x25: return UNW_REG_F2 + (abreg - 0x22);
-    case 0x30 ... 0x3f: return UNW_REG_F16 + (abreg - 0x30);
-    case 0x41 ... 0x45: return UNW_REG_B1 + (abreg - 0x41);
-    case 0x60: return UNW_REG_PR;
-    case 0x61: return UNW_REG_PSP;
-    case 0x62: return memory ? UNW_REG_PRI_UNAT_MEM : UNW_REG_PRI_UNAT_GR;
-    case 0x63: return UNW_REG_RP;
-    case 0x64: return UNW_REG_BSP;
-    case 0x65: return UNW_REG_BSPSTORE;
-    case 0x66: return UNW_REG_RNAT;
-    case 0x67: return UNW_REG_UNAT;
-    case 0x68: return UNW_REG_FPSR;
-    case 0x69: return UNW_REG_PFS;
-    case 0x6a: return UNW_REG_LC;
-    default:
-      abort ();
-  }
-}
-
-static void
-set_reg (struct unw_reg_info *reg, enum unw_where where,
-        int when, unsigned long val)
-{
-  reg->val = val;
-  reg->where = where;
-  if (reg->when == UNW_WHEN_NEVER)
-    reg->when = when;
-}
-
-static void
-alloc_spill_area (unsigned long *offp, unsigned long regsize,
-                 struct unw_reg_info *lo, struct unw_reg_info *hi)
-{
-  struct unw_reg_info *reg;
-
-  for (reg = hi; reg >= lo; --reg)
-    {
-      if (reg->where == UNW_WHERE_SPILL_HOME)
-       {
-         reg->where = UNW_WHERE_PSPREL;
-         *offp -= regsize;
-         reg->val = *offp;
-       }
-    }
-}
-
-static inline void
-spill_next_when (struct unw_reg_info **regp, struct unw_reg_info *lim,
-                unw_word t)
-{
-  struct unw_reg_info *reg;
-
-  for (reg = *regp; reg <= lim; ++reg)
-    {
-      if (reg->where == UNW_WHERE_SPILL_HOME)
-       {
-         reg->when = t;
-         *regp = reg + 1;
-         return;
-       }
-    }
-  /* Excess spill.  */
-  abort ();
-}
-
-static void
-finish_prologue (struct unw_state_record *sr)
-{
-  struct unw_reg_info *reg;
-  unsigned long off;
-  int i;
-
-  /* First, resolve implicit register save locations
-     (see Section "11.4.2.3 Rules for Using Unwind Descriptors", rule 3).  */
-
-  for (i = 0; i < (int) sizeof (save_order); ++i)
-    {
-      reg = sr->curr.reg + save_order[i];
-      if (reg->where == UNW_WHERE_GR_SAVE)
-       {
-         reg->where = UNW_WHERE_GR;
-         reg->val = sr->gr_save_loc++;
-       }
-    }
-
-  /* Next, compute when the fp, general, and branch registers get saved.
-     This must come before alloc_spill_area() because we need to know
-     which registers are spilled to their home locations.  */
-  if (sr->imask)
-    {
-      static unsigned char const limit[3] = {
-       UNW_REG_F31, UNW_REG_R7, UNW_REG_B5
-      };
-
-      unsigned char kind, mask = 0, *cp = sr->imask;
-      int t;
-      struct unw_reg_info *(regs[3]);
-
-      regs[0] = sr->curr.reg + UNW_REG_F2;
-      regs[1] = sr->curr.reg + UNW_REG_R4;
-      regs[2] = sr->curr.reg + UNW_REG_B1;
-
-      for (t = 0; t < sr->region_len; ++t)
-       {
-         if ((t & 3) == 0)
-           mask = *cp++;
-         kind = (mask >> 2*(3-(t & 3))) & 3;
-         if (kind > 0)
-           spill_next_when (&regs[kind - 1], sr->curr.reg + limit[kind - 1],
-                            sr->region_start + t);
-       }
-    }
-
-  /* Next, lay out the memory stack spill area.  */
-  if (sr->any_spills)
-    {
-      off = sr->spill_offset;
-      alloc_spill_area (&off, 16, sr->curr.reg + UNW_REG_F2,
-                       sr->curr.reg + UNW_REG_F31); 
-      alloc_spill_area (&off,  8, sr->curr.reg + UNW_REG_B1,
-                       sr->curr.reg + UNW_REG_B5);
-      alloc_spill_area (&off,  8, sr->curr.reg + UNW_REG_R4,
-                       sr->curr.reg + UNW_REG_R7);
-    }
-}
-
-/*
- * Region header descriptors.
- */
-
-static void
-desc_prologue (int body, unw_word rlen, unsigned char mask,
-              unsigned char grsave, struct unw_state_record *sr)
-{
-  int i;
-
-  if (!(sr->in_body || sr->first_region))
-    finish_prologue (sr);
-  sr->first_region = 0;
-
-  /* Check if we're done.  */
-  if (sr->when_target < sr->region_start + sr->region_len) 
-    {
-      sr->done = 1;
-      return;
-    }
-
-  for (i = 0; i < sr->epilogue_count; ++i)
-    pop (sr);
-
-  sr->epilogue_count = 0;
-  sr->epilogue_start = UNW_WHEN_NEVER;
-
-  if (!body)
-    push (sr);
-
-  sr->region_start += sr->region_len;
-  sr->region_len = rlen;
-  sr->in_body = body;
-
-  if (!body)
-    {
-      for (i = 0; i < 4; ++i)
-       {
-         if (mask & 0x8)
-           set_reg (sr->curr.reg + save_order[i], UNW_WHERE_GR,
-                    sr->region_start + sr->region_len - 1, grsave++);
-         mask <<= 1;
-       }
-      sr->gr_save_loc = grsave;
-      sr->any_spills = 0;
-      sr->imask = 0;
-      sr->spill_offset = 0x10; /* default to psp+16 */
-    }
-}
-
-/*
- * Prologue descriptors.
- */
-
-static inline void
-desc_abi (unsigned char abi,
-         unsigned char context,
-         struct unw_state_record *sr)
-{
-  sr->unwabi = (abi << 8) | context;
-}
-
-static inline void
-desc_br_gr (unsigned char brmask, unsigned char gr,
-           struct unw_state_record *sr)
-{
-  int i;
-
-  for (i = 0; i < 5; ++i)
-    {
-      if (brmask & 1)
-       set_reg (sr->curr.reg + UNW_REG_B1 + i, UNW_WHERE_GR,
-                sr->region_start + sr->region_len - 1, gr++);
-      brmask >>= 1;
-    }
-}
-
-static inline void
-desc_br_mem (unsigned char brmask, struct unw_state_record *sr)
-{
-  int i;
-
-  for (i = 0; i < 5; ++i)
-    {
-      if (brmask & 1)
-       {
-         set_reg (sr->curr.reg + UNW_REG_B1 + i, UNW_WHERE_SPILL_HOME,
-                  sr->region_start + sr->region_len - 1, 0);
-         sr->any_spills = 1;
-       }
-      brmask >>= 1;
-    }
-}
-
-static inline void
-desc_frgr_mem (unsigned char grmask, unw_word frmask,
-              struct unw_state_record *sr)
-{
-  int i;
-
-  for (i = 0; i < 4; ++i)
-    {
-      if ((grmask & 1) != 0)
-       {
-         set_reg (sr->curr.reg + UNW_REG_R4 + i, UNW_WHERE_SPILL_HOME,
-                  sr->region_start + sr->region_len - 1, 0);
-         sr->any_spills = 1;
-       }
-      grmask >>= 1;
-    }
-  for (i = 0; i < 20; ++i)
-    {
-      if ((frmask & 1) != 0)
-       {
-         enum unw_register_index base = i < 4 ? UNW_REG_F2 : UNW_REG_F16 - 4;
-         set_reg (sr->curr.reg + base + i, UNW_WHERE_SPILL_HOME,
-                  sr->region_start + sr->region_len - 1, 0);
-         sr->any_spills = 1;
-       }
-      frmask >>= 1;
-    }
-}
-
-static inline void
-desc_fr_mem (unsigned char frmask, struct unw_state_record *sr)
-{
-  int i;
-
-  for (i = 0; i < 4; ++i)
-    {
-      if ((frmask & 1) != 0)
-       {
-         set_reg (sr->curr.reg + UNW_REG_F2 + i, UNW_WHERE_SPILL_HOME,
-                  sr->region_start + sr->region_len - 1, 0);
-         sr->any_spills = 1;
-       }
-      frmask >>= 1;
-    }
-}
-
-static inline void
-desc_gr_gr (unsigned char grmask, unsigned char gr,
-           struct unw_state_record *sr)
-{
-  int i;
-
-  for (i = 0; i < 4; ++i)
-    {
-      if ((grmask & 1) != 0)
-       set_reg (sr->curr.reg + UNW_REG_R4 + i, UNW_WHERE_GR,
-                sr->region_start + sr->region_len - 1, gr++);
-      grmask >>= 1;
-    }
-}
-
-static inline void
-desc_gr_mem (unsigned char grmask, struct unw_state_record *sr)
-{
-  int i;
-
-  for (i = 0; i < 4; ++i)
-    {
-      if ((grmask & 1) != 0)
-       {
-         set_reg (sr->curr.reg + UNW_REG_R4 + i, UNW_WHERE_SPILL_HOME,
-                  sr->region_start + sr->region_len - 1, 0);
-         sr->any_spills = 1;
-       }
-      grmask >>= 1;
-    }
-}
-
-static inline void
-desc_mem_stack_f (unw_word t, unw_word size, struct unw_state_record *sr)
-{
-  set_reg (sr->curr.reg + UNW_REG_PSP, UNW_WHERE_NONE,
-          sr->region_start + MIN ((int)t, sr->region_len - 1), 16*size);
-}
-
-static inline void
-desc_mem_stack_v (unw_word t, struct unw_state_record *sr)
-{
-  sr->curr.reg[UNW_REG_PSP].when
-    = sr->region_start + MIN ((int)t, sr->region_len - 1);
-}
-
-static inline void
-desc_reg_gr (unsigned char reg, unsigned char dst, struct unw_state_record *sr)
-{
-  set_reg (sr->curr.reg + reg, UNW_WHERE_GR,
-          sr->region_start + sr->region_len - 1, dst);
-}
-
-static inline void
-desc_reg_psprel (unsigned char reg, unw_word pspoff,
-                struct unw_state_record *sr)
-{
-  set_reg (sr->curr.reg + reg, UNW_WHERE_PSPREL,
-          sr->region_start + sr->region_len - 1,
-          0x10 - 4*pspoff);
-}
-
-static inline void
-desc_reg_sprel (unsigned char reg, unw_word spoff, struct unw_state_record *sr)
-{
-  set_reg (sr->curr.reg + reg, UNW_WHERE_SPREL,
-          sr->region_start + sr->region_len - 1,
-          4*spoff);
-}
-
-static inline void
-desc_rp_br (unsigned char dst, struct unw_state_record *sr)
-{
-  sr->return_link_reg = dst;
-}
-
-static inline void
-desc_reg_when (unsigned char regnum, unw_word t, struct unw_state_record *sr)
-{
-  struct unw_reg_info *reg = sr->curr.reg + regnum;
-
-  if (reg->where == UNW_WHERE_NONE)
-    reg->where = UNW_WHERE_GR_SAVE;
-  reg->when = sr->region_start + MIN ((int)t, sr->region_len - 1);
-}
-
-static inline void
-desc_spill_base (unw_word pspoff, struct unw_state_record *sr)
-{
-  sr->spill_offset = 0x10 - 4*pspoff;
-}
-
-static inline unsigned char *
-desc_spill_mask (unsigned char *imaskp, struct unw_state_record *sr)
-{
-  sr->imask = imaskp;
-  return imaskp + (2*sr->region_len + 7)/8;
-}
-
-/*
- * Body descriptors.
- */
-static inline void
-desc_epilogue (unw_word t, unw_word ecount, struct unw_state_record *sr)
-{
-  sr->epilogue_start = sr->region_start + sr->region_len - 1 - t;
-  sr->epilogue_count = ecount + 1;
-}
-
-static inline void
-desc_copy_state (unw_word label, struct unw_state_record *sr)
-{
-  struct unw_labeled_state *ls;
-
-  for (ls = sr->labeled_states; ls; ls = ls->next)
-    {
-      if (ls->label == label)
-        {
-         free_state_stack (&sr->curr);
-         memcpy (&sr->curr, &ls->saved_state, sizeof (sr->curr));
-         sr->curr.next = dup_state_stack (ls->saved_state.next);
-         return;
-       }
-    }
-  abort ();
-}
-
-static inline void
-desc_label_state (unw_word label, struct unw_state_record *sr)
-{
-  struct unw_labeled_state *ls = alloc_label_state ();
-
-  ls->label = label;
-  memcpy (&ls->saved_state, &sr->curr, sizeof (ls->saved_state));
-  ls->saved_state.next = dup_state_stack (sr->curr.next);
-
-  /* Insert into list of labeled states.  */
-  ls->next = sr->labeled_states;
-  sr->labeled_states = ls;
-}
-
-/*
- * General descriptors.
- */
-
-static inline int
-desc_is_active (unsigned char qp, unw_word t, struct unw_state_record *sr)
-{
-  if (sr->when_target <= sr->region_start + MIN ((int)t, sr->region_len - 1))
-    return 0;
-  if (qp > 0)
-    {
-      if ((sr->pr_val & (1UL << qp)) == 0) 
-       return 0;
-      sr->pr_mask |= (1UL << qp);
-    }
-  return 1;
-}
-
-static inline void
-desc_restore_p (unsigned char qp, unw_word t, unsigned char abreg,
-               struct unw_state_record *sr)
-{
-  struct unw_reg_info *r;
-
-  if (! desc_is_active (qp, t, sr))
-    return;
-
-  r = sr->curr.reg + decode_abreg (abreg, 0);
-  r->where = UNW_WHERE_NONE;
-  r->when = sr->region_start + MIN ((int)t, sr->region_len - 1);
-  r->val = 0;
-}
-
-static inline void
-desc_spill_reg_p (unsigned char qp, unw_word t, unsigned char abreg,
-                 unsigned char x, unsigned char ytreg,
-                 struct unw_state_record *sr)
-{
-  enum unw_where where = UNW_WHERE_GR;
-  struct unw_reg_info *r;
-
-  if (! desc_is_active (qp, t, sr))
-    return;
-
-  if (x)
-    where = UNW_WHERE_BR;
-  else if (ytreg & 0x80)
-    where = UNW_WHERE_FR;
-
-  r = sr->curr.reg + decode_abreg (abreg, 0);
-  r->where = where;
-  r->when = sr->region_start + MIN ((int)t, sr->region_len - 1);
-  r->val = ytreg & 0x7f;
-}
-
-static inline void
-desc_spill_psprel_p (unsigned char qp, unw_word t, unsigned char abreg,
-                    unw_word pspoff, struct unw_state_record *sr)
-{
-  struct unw_reg_info *r;
-
-  if (! desc_is_active (qp, t, sr))
-    return;
-
-  r = sr->curr.reg + decode_abreg (abreg, 1);
-  r->where = UNW_WHERE_PSPREL;
-  r->when = sr->region_start + MIN((int)t, sr->region_len - 1);
-  r->val = 0x10 - 4*pspoff;
-}
-
-static inline void
-desc_spill_sprel_p (unsigned char qp, unw_word t, unsigned char abreg,
-                   unw_word spoff, struct unw_state_record *sr)
-{
-  struct unw_reg_info *r;
-
-  if (! desc_is_active (qp, t, sr))
-    return;
-
-  r = sr->curr.reg + decode_abreg (abreg, 1);
-  r->where = UNW_WHERE_SPREL;
-  r->when = sr->region_start + MIN ((int)t, sr->region_len - 1);
-  r->val = 4*spoff;
-}
-
-\f
-#define UNW_DEC_BAD_CODE(code)                 abort ();
-
-/* Region headers.  */
-#define UNW_DEC_PROLOGUE_GR(fmt,r,m,gr,arg)    desc_prologue(0,r,m,gr,arg)
-#define UNW_DEC_PROLOGUE(fmt,b,r,arg)          desc_prologue(b,r,0,32,arg)
-
-/* Prologue descriptors.  */
-#define UNW_DEC_ABI(fmt,a,c,arg)               desc_abi(a,c,arg)
-#define UNW_DEC_BR_GR(fmt,b,g,arg)             desc_br_gr(b,g,arg)
-#define UNW_DEC_BR_MEM(fmt,b,arg)              desc_br_mem(b,arg)
-#define UNW_DEC_FRGR_MEM(fmt,g,f,arg)          desc_frgr_mem(g,f,arg)
-#define UNW_DEC_FR_MEM(fmt,f,arg)              desc_fr_mem(f,arg)
-#define UNW_DEC_GR_GR(fmt,m,g,arg)             desc_gr_gr(m,g,arg)
-#define UNW_DEC_GR_MEM(fmt,m,arg)              desc_gr_mem(m,arg)
-#define UNW_DEC_MEM_STACK_F(fmt,t,s,arg)       desc_mem_stack_f(t,s,arg)
-#define UNW_DEC_MEM_STACK_V(fmt,t,arg)         desc_mem_stack_v(t,arg)
-#define UNW_DEC_REG_GR(fmt,r,d,arg)            desc_reg_gr(r,d,arg)
-#define UNW_DEC_REG_PSPREL(fmt,r,o,arg)                desc_reg_psprel(r,o,arg)
-#define UNW_DEC_REG_SPREL(fmt,r,o,arg)         desc_reg_sprel(r,o,arg)
-#define UNW_DEC_REG_WHEN(fmt,r,t,arg)          desc_reg_when(r,t,arg)
-#define UNW_DEC_PRIUNAT_WHEN_GR(fmt,t,arg)     desc_reg_when(UNW_REG_PRI_UNAT_GR,t,arg)
-#define UNW_DEC_PRIUNAT_WHEN_MEM(fmt,t,arg)    desc_reg_when(UNW_REG_PRI_UNAT_MEM,t,arg)
-#define UNW_DEC_PRIUNAT_GR(fmt,r,arg)          desc_reg_gr(UNW_REG_PRI_UNAT_GR,r,arg)
-#define UNW_DEC_PRIUNAT_PSPREL(fmt,o,arg)      desc_reg_psprel(UNW_REG_PRI_UNAT_MEM,o,arg)
-#define UNW_DEC_PRIUNAT_SPREL(fmt,o,arg)       desc_reg_sprel(UNW_REG_PRI_UNAT_MEM,o,arg)
-#define UNW_DEC_RP_BR(fmt,d,arg)               desc_rp_br(d,arg)
-#define UNW_DEC_SPILL_BASE(fmt,o,arg)          desc_spill_base(o,arg)
-#define UNW_DEC_SPILL_MASK(fmt,m,arg)          (m = desc_spill_mask(m,arg))
-
-/* Body descriptors.  */
-#define UNW_DEC_EPILOGUE(fmt,t,c,arg)          desc_epilogue(t,c,arg)
-#define UNW_DEC_COPY_STATE(fmt,l,arg)          desc_copy_state(l,arg)
-#define UNW_DEC_LABEL_STATE(fmt,l,arg)         desc_label_state(l,arg)
-
-/* General unwind descriptors.  */
-#define UNW_DEC_SPILL_REG_P(f,p,t,a,x,y,arg)   desc_spill_reg_p(p,t,a,x,y,arg)
-#define UNW_DEC_SPILL_REG(f,t,a,x,y,arg)       desc_spill_reg_p(0,t,a,x,y,arg)
-#define UNW_DEC_SPILL_PSPREL_P(f,p,t,a,o,arg)  desc_spill_psprel_p(p,t,a,o,arg)
-#define UNW_DEC_SPILL_PSPREL(f,t,a,o,arg)      desc_spill_psprel_p(0,t,a,o,arg)
-#define UNW_DEC_SPILL_SPREL_P(f,p,t,a,o,arg)   desc_spill_sprel_p(p,t,a,o,arg)
-#define UNW_DEC_SPILL_SPREL(f,t,a,o,arg)       desc_spill_sprel_p(0,t,a,o,arg)
-#define UNW_DEC_RESTORE_P(f,p,t,a,arg)         desc_restore_p(p,t,a,arg)
-#define UNW_DEC_RESTORE(f,t,a,arg)             desc_restore_p(0,t,a,arg)
-
-\f
-/*
- * Generic IA-64 unwind info decoder.
- *
- * This file is used both by the Linux kernel and objdump.  Please keep
- * the copies of this file in sync.
- *
- * You need to customize the decoder by defining the following
- * macros/constants before including this file:
- *
- *  Types:
- *     unw_word        Unsigned integer type with at least 64 bits 
- *
- *  Register names:
- *     UNW_REG_BSP
- *     UNW_REG_BSPSTORE
- *     UNW_REG_FPSR
- *     UNW_REG_LC
- *     UNW_REG_PFS
- *     UNW_REG_PR
- *     UNW_REG_RNAT
- *     UNW_REG_PSP
- *     UNW_REG_RP
- *     UNW_REG_UNAT
- *
- *  Decoder action macros:
- *     UNW_DEC_BAD_CODE(code)
- *     UNW_DEC_ABI(fmt,abi,context,arg)
- *     UNW_DEC_BR_GR(fmt,brmask,gr,arg)
- *     UNW_DEC_BR_MEM(fmt,brmask,arg)
- *     UNW_DEC_COPY_STATE(fmt,label,arg)
- *     UNW_DEC_EPILOGUE(fmt,t,ecount,arg)
- *     UNW_DEC_FRGR_MEM(fmt,grmask,frmask,arg)
- *     UNW_DEC_FR_MEM(fmt,frmask,arg)
- *     UNW_DEC_GR_GR(fmt,grmask,gr,arg)
- *     UNW_DEC_GR_MEM(fmt,grmask,arg)
- *     UNW_DEC_LABEL_STATE(fmt,label,arg)
- *     UNW_DEC_MEM_STACK_F(fmt,t,size,arg)
- *     UNW_DEC_MEM_STACK_V(fmt,t,arg)
- *     UNW_DEC_PRIUNAT_GR(fmt,r,arg)
- *     UNW_DEC_PRIUNAT_WHEN_GR(fmt,t,arg)
- *     UNW_DEC_PRIUNAT_WHEN_MEM(fmt,t,arg)
- *     UNW_DEC_PRIUNAT_WHEN_PSPREL(fmt,pspoff,arg)
- *     UNW_DEC_PRIUNAT_WHEN_SPREL(fmt,spoff,arg)
- *     UNW_DEC_PROLOGUE(fmt,body,rlen,arg)
- *     UNW_DEC_PROLOGUE_GR(fmt,rlen,mask,grsave,arg)
- *     UNW_DEC_REG_PSPREL(fmt,reg,pspoff,arg)
- *     UNW_DEC_REG_REG(fmt,src,dst,arg)
- *     UNW_DEC_REG_SPREL(fmt,reg,spoff,arg)
- *     UNW_DEC_REG_WHEN(fmt,reg,t,arg)
- *     UNW_DEC_RESTORE(fmt,t,abreg,arg)
- *     UNW_DEC_RESTORE_P(fmt,qp,t,abreg,arg)
- *     UNW_DEC_SPILL_BASE(fmt,pspoff,arg)
- *     UNW_DEC_SPILL_MASK(fmt,imaskp,arg)
- *     UNW_DEC_SPILL_PSPREL(fmt,t,abreg,pspoff,arg)
- *     UNW_DEC_SPILL_PSPREL_P(fmt,qp,t,abreg,pspoff,arg)
- *     UNW_DEC_SPILL_REG(fmt,t,abreg,x,ytreg,arg)
- *     UNW_DEC_SPILL_REG_P(fmt,qp,t,abreg,x,ytreg,arg)
- *     UNW_DEC_SPILL_SPREL(fmt,t,abreg,spoff,arg)
- *     UNW_DEC_SPILL_SPREL_P(fmt,qp,t,abreg,pspoff,arg)
- */
-
-static unw_word
-unw_decode_uleb128 (unsigned char **dpp)
-{
-  unsigned shift = 0;
-  unw_word byte, result = 0;
-  unsigned char *bp = *dpp;
-
-  while (1)
-    {
-      byte = *bp++;
-      result |= (byte & 0x7f) << shift;
-      if ((byte & 0x80) == 0)
-       break;
-      shift += 7;
-    }
-  *dpp = bp;
-  return result;
-}
-
-static unsigned char *
-unw_decode_x1 (unsigned char *dp,
-              unsigned char code __attribute__((unused)),
-              void *arg)
-{
-  unsigned char byte1, abreg;
-  unw_word t, off;
-
-  byte1 = *dp++;
-  t = unw_decode_uleb128 (&dp);
-  off = unw_decode_uleb128 (&dp);
-  abreg = (byte1 & 0x7f);
-  if (byte1 & 0x80)
-         UNW_DEC_SPILL_SPREL(X1, t, abreg, off, arg);
-  else
-         UNW_DEC_SPILL_PSPREL(X1, t, abreg, off, arg);
-  return dp;
-}
-
-static unsigned char *
-unw_decode_x2 (unsigned char *dp,
-              unsigned char code __attribute__((unused)),
-              void *arg)
-{
-  unsigned char byte1, byte2, abreg, x, ytreg;
-  unw_word t;
-
-  byte1 = *dp++; byte2 = *dp++;
-  t = unw_decode_uleb128 (&dp);
-  abreg = (byte1 & 0x7f);
-  ytreg = byte2;
-  x = (byte1 >> 7) & 1;
-  if ((byte1 & 0x80) == 0 && ytreg == 0)
-    UNW_DEC_RESTORE(X2, t, abreg, arg);
-  else
-    UNW_DEC_SPILL_REG(X2, t, abreg, x, ytreg, arg);
-  return dp;
-}
-
-static unsigned char *
-unw_decode_x3 (unsigned char *dp,
-              unsigned char code __attribute__((unused)),
-              void *arg)
-{
-  unsigned char byte1, byte2, abreg, qp;
-  unw_word t, off;
-
-  byte1 = *dp++; byte2 = *dp++;
-  t = unw_decode_uleb128 (&dp);
-  off = unw_decode_uleb128 (&dp);
-
-  qp = (byte1 & 0x3f);
-  abreg = (byte2 & 0x7f);
-
-  if (byte1 & 0x80)
-    UNW_DEC_SPILL_SPREL_P(X3, qp, t, abreg, off, arg);
-  else
-    UNW_DEC_SPILL_PSPREL_P(X3, qp, t, abreg, off, arg);
-  return dp;
-}
-
-static unsigned char *
-unw_decode_x4 (unsigned char *dp,
-              unsigned char code __attribute__((unused)),
-              void *arg)
-{
-  unsigned char byte1, byte2, byte3, qp, abreg, x, ytreg;
-  unw_word t;
-
-  byte1 = *dp++; byte2 = *dp++; byte3 = *dp++;
-  t = unw_decode_uleb128 (&dp);
-
-  qp = (byte1 & 0x3f);
-  abreg = (byte2 & 0x7f);
-  x = (byte2 >> 7) & 1;
-  ytreg = byte3;
-
-  if ((byte2 & 0x80) == 0 && byte3 == 0)
-    UNW_DEC_RESTORE_P(X4, qp, t, abreg, arg);
-  else
-    UNW_DEC_SPILL_REG_P(X4, qp, t, abreg, x, ytreg, arg);
-  return dp;
-}
-
-static unsigned char *
-unw_decode_r1 (unsigned char *dp, unsigned char code, void *arg)
-{
-  int body = (code & 0x20) != 0;
-  unw_word rlen;
-
-  rlen = (code & 0x1f);
-  UNW_DEC_PROLOGUE(R1, body, rlen, arg);
-  return dp;
-}
-
-static unsigned char *
-unw_decode_r2 (unsigned char *dp, unsigned char code, void *arg)
-{
-  unsigned char byte1, mask, grsave;
-  unw_word rlen;
-
-  byte1 = *dp++;
-
-  mask = ((code & 0x7) << 1) | ((byte1 >> 7) & 1);
-  grsave = (byte1 & 0x7f);
-  rlen = unw_decode_uleb128 (&dp);
-  UNW_DEC_PROLOGUE_GR(R2, rlen, mask, grsave, arg);
-  return dp;
-}
-
-static unsigned char *
-unw_decode_r3 (unsigned char *dp, unsigned char code, void *arg)
-{
-  unw_word rlen;
-
-  rlen = unw_decode_uleb128 (&dp);
-  UNW_DEC_PROLOGUE(R3, ((code & 0x3) == 1), rlen, arg);
-  return dp;
-}
-
-static unsigned char *
-unw_decode_p1 (unsigned char *dp, unsigned char code, void *arg)
-{
-  unsigned char brmask = (code & 0x1f);
-
-  UNW_DEC_BR_MEM(P1, brmask, arg);
-  return dp;
-}
-
-static unsigned char *
-unw_decode_p2_p5 (unsigned char *dp, unsigned char code, void *arg)
-{
-  if ((code & 0x10) == 0)
-    {
-      unsigned char byte1 = *dp++;
-
-      UNW_DEC_BR_GR(P2, ((code & 0xf) << 1) | ((byte1 >> 7) & 1),
-                   (byte1 & 0x7f), arg);
-    }
-  else if ((code & 0x08) == 0)
-    {
-      unsigned char byte1 = *dp++, r, dst;
-
-      r = ((code & 0x7) << 1) | ((byte1 >> 7) & 1);
-      dst = (byte1 & 0x7f);
-      switch (r)
-       {
-       case 0: UNW_DEC_REG_GR(P3, UNW_REG_PSP, dst, arg); break;
-       case 1: UNW_DEC_REG_GR(P3, UNW_REG_RP, dst, arg); break;
-       case 2: UNW_DEC_REG_GR(P3, UNW_REG_PFS, dst, arg); break;
-       case 3: UNW_DEC_REG_GR(P3, UNW_REG_PR, dst, arg); break;
-       case 4: UNW_DEC_REG_GR(P3, UNW_REG_UNAT, dst, arg); break;
-       case 5: UNW_DEC_REG_GR(P3, UNW_REG_LC, dst, arg); break;
-       case 6: UNW_DEC_RP_BR(P3, dst, arg); break;
-       case 7: UNW_DEC_REG_GR(P3, UNW_REG_RNAT, dst, arg); break;
-       case 8: UNW_DEC_REG_GR(P3, UNW_REG_BSP, dst, arg); break;
-       case 9: UNW_DEC_REG_GR(P3, UNW_REG_BSPSTORE, dst, arg); break;
-       case 10: UNW_DEC_REG_GR(P3, UNW_REG_FPSR, dst, arg); break;
-       case 11: UNW_DEC_PRIUNAT_GR(P3, dst, arg); break;
-       default: UNW_DEC_BAD_CODE(r); break;
-       }
-    }
-  else if ((code & 0x7) == 0)
-    UNW_DEC_SPILL_MASK(P4, dp, arg);
-  else if ((code & 0x7) == 1)
-    {
-      unw_word grmask, frmask, byte1, byte2, byte3;
-
-      byte1 = *dp++; byte2 = *dp++; byte3 = *dp++;
-      grmask = ((byte1 >> 4) & 0xf);
-      frmask = ((byte1 & 0xf) << 16) | (byte2 << 8) | byte3;
-      UNW_DEC_FRGR_MEM(P5, grmask, frmask, arg);
-    }
-  else
-    UNW_DEC_BAD_CODE(code);
-  return dp;
-}
-
-static unsigned char *
-unw_decode_p6 (unsigned char *dp, unsigned char code, void *arg)
-{
-  int gregs = (code & 0x10) != 0;
-  unsigned char mask = (code & 0x0f);
-
-  if (gregs)
-    UNW_DEC_GR_MEM(P6, mask, arg);
-  else
-    UNW_DEC_FR_MEM(P6, mask, arg);
-  return dp;
-}
-
-static unsigned char *
-unw_decode_p7_p10 (unsigned char *dp, unsigned char code, void *arg)
-{
-  unsigned char r, byte1, byte2;
-  unw_word t, size;
-
-  if ((code & 0x10) == 0)
-    {
-      r = (code & 0xf);
-      t = unw_decode_uleb128 (&dp);
-      switch (r)
-       {
-       case 0:
-         size = unw_decode_uleb128 (&dp);
-         UNW_DEC_MEM_STACK_F(P7, t, size, arg);
-         break;
-
-       case 1: UNW_DEC_MEM_STACK_V(P7, t, arg); break;
-       case 2: UNW_DEC_SPILL_BASE(P7, t, arg); break;
-       case 3: UNW_DEC_REG_SPREL(P7, UNW_REG_PSP, t, arg); break;
-       case 4: UNW_DEC_REG_WHEN(P7, UNW_REG_RP, t, arg); break;
-       case 5: UNW_DEC_REG_PSPREL(P7, UNW_REG_RP, t, arg); break;
-       case 6: UNW_DEC_REG_WHEN(P7, UNW_REG_PFS, t, arg); break;
-       case 7: UNW_DEC_REG_PSPREL(P7, UNW_REG_PFS, t, arg); break;
-       case 8: UNW_DEC_REG_WHEN(P7, UNW_REG_PR, t, arg); break;
-       case 9: UNW_DEC_REG_PSPREL(P7, UNW_REG_PR, t, arg); break;
-       case 10: UNW_DEC_REG_WHEN(P7, UNW_REG_LC, t, arg); break;
-       case 11: UNW_DEC_REG_PSPREL(P7, UNW_REG_LC, t, arg); break;
-       case 12: UNW_DEC_REG_WHEN(P7, UNW_REG_UNAT, t, arg); break;
-       case 13: UNW_DEC_REG_PSPREL(P7, UNW_REG_UNAT, t, arg); break;
-       case 14: UNW_DEC_REG_WHEN(P7, UNW_REG_FPSR, t, arg); break;
-       case 15: UNW_DEC_REG_PSPREL(P7, UNW_REG_FPSR, t, arg); break;
-       default: UNW_DEC_BAD_CODE(r); break;
-       }
-    }
-  else
-    {
-      switch (code & 0xf)
-       {
-       case 0x0: /* p8 */
-         {
-           r = *dp++;
-           t = unw_decode_uleb128 (&dp);
-           switch (r)
-             {
-             case  1: UNW_DEC_REG_SPREL(P8, UNW_REG_RP, t, arg); break;
-             case  2: UNW_DEC_REG_SPREL(P8, UNW_REG_PFS, t, arg); break;
-             case  3: UNW_DEC_REG_SPREL(P8, UNW_REG_PR, t, arg); break;
-             case  4: UNW_DEC_REG_SPREL(P8, UNW_REG_LC, t, arg); break;
-             case  5: UNW_DEC_REG_SPREL(P8, UNW_REG_UNAT, t, arg); break;
-             case  6: UNW_DEC_REG_SPREL(P8, UNW_REG_FPSR, t, arg); break;
-             case  7: UNW_DEC_REG_WHEN(P8, UNW_REG_BSP, t, arg); break;
-             case  8: UNW_DEC_REG_PSPREL(P8, UNW_REG_BSP, t, arg); break;
-             case  9: UNW_DEC_REG_SPREL(P8, UNW_REG_BSP, t, arg); break;
-             case 10: UNW_DEC_REG_WHEN(P8, UNW_REG_BSPSTORE, t, arg); break;
-             case 11: UNW_DEC_REG_PSPREL(P8, UNW_REG_BSPSTORE, t, arg); break;
-             case 12: UNW_DEC_REG_SPREL(P8, UNW_REG_BSPSTORE, t, arg); break;
-             case 13: UNW_DEC_REG_WHEN(P8, UNW_REG_RNAT, t, arg); break;
-             case 14: UNW_DEC_REG_PSPREL(P8, UNW_REG_RNAT, t, arg); break;
-             case 15: UNW_DEC_REG_SPREL(P8, UNW_REG_RNAT, t, arg); break;
-             case 16: UNW_DEC_PRIUNAT_WHEN_GR(P8, t, arg); break;
-             case 17: UNW_DEC_PRIUNAT_PSPREL(P8, t, arg); break;
-             case 18: UNW_DEC_PRIUNAT_SPREL(P8, t, arg); break;
-             case 19: UNW_DEC_PRIUNAT_WHEN_MEM(P8, t, arg); break;
-             default: UNW_DEC_BAD_CODE(r); break;
-           }
-         }
-         break;
-
-       case 0x1:
-         byte1 = *dp++; byte2 = *dp++;
-         UNW_DEC_GR_GR(P9, (byte1 & 0xf), (byte2 & 0x7f), arg);
-         break;
-
-       case 0xf: /* p10 */
-         byte1 = *dp++; byte2 = *dp++;
-         UNW_DEC_ABI(P10, byte1, byte2, arg);
-         break;
-
-       case 0x9:
-         return unw_decode_x1 (dp, code, arg);
-
-       case 0xa:
-         return unw_decode_x2 (dp, code, arg);
-
-       case 0xb:
-         return unw_decode_x3 (dp, code, arg);
-
-       case 0xc:
-         return unw_decode_x4 (dp, code, arg);
-
-       default:
-         UNW_DEC_BAD_CODE(code);
-         break;
-       }
-    }
-  return dp;
-}
-
-static unsigned char *
-unw_decode_b1 (unsigned char *dp, unsigned char code, void *arg)
-{
-  unw_word label = (code & 0x1f);
-
-  if ((code & 0x20) != 0)
-    UNW_DEC_COPY_STATE(B1, label, arg);
-  else
-    UNW_DEC_LABEL_STATE(B1, label, arg);
-  return dp;
-}
-
-static unsigned char *
-unw_decode_b2 (unsigned char *dp, unsigned char code, void *arg)
-{
-  unw_word t;
-
-  t = unw_decode_uleb128 (&dp);
-  UNW_DEC_EPILOGUE(B2, t, (code & 0x1f), arg);
-  return dp;
-}
-
-static unsigned char *
-unw_decode_b3_x4 (unsigned char *dp, unsigned char code, void *arg)
-{
-  unw_word t, ecount, label;
-
-  if ((code & 0x10) == 0)
-    {
-      t = unw_decode_uleb128 (&dp);
-      ecount = unw_decode_uleb128 (&dp);
-      UNW_DEC_EPILOGUE(B3, t, ecount, arg);
-    }
-  else if ((code & 0x07) == 0)
-    {
-      label = unw_decode_uleb128 (&dp);
-      if ((code & 0x08) != 0)
-       UNW_DEC_COPY_STATE(B4, label, arg);
-      else
-       UNW_DEC_LABEL_STATE(B4, label, arg);
-    }
-  else
-    switch (code & 0x7)
-      {
-      case 1: return unw_decode_x1 (dp, code, arg);
-      case 2: return unw_decode_x2 (dp, code, arg);
-      case 3: return unw_decode_x3 (dp, code, arg);
-      case 4: return unw_decode_x4 (dp, code, arg);
-      default: UNW_DEC_BAD_CODE(code); break;
-      }
-  return dp;
-}
-
-typedef unsigned char *(*unw_decoder) (unsigned char *, unsigned char, void *);
-
-static const unw_decoder unw_decode_table[2][8] =
-{
-  /* prologue table: */
-  {
-    unw_decode_r1,     /* 0 */
-    unw_decode_r1,
-    unw_decode_r2,
-    unw_decode_r3,
-    unw_decode_p1,     /* 4 */
-    unw_decode_p2_p5,
-    unw_decode_p6,
-    unw_decode_p7_p10
-  },
-  {
-    unw_decode_r1,     /* 0 */
-    unw_decode_r1,
-    unw_decode_r2,
-    unw_decode_r3,
-    unw_decode_b1,     /* 4 */
-    unw_decode_b1,
-    unw_decode_b2,
-    unw_decode_b3_x4
-  }
-};
-
-/*
- * Decode one descriptor and return address of next descriptor.
- */
-static inline unsigned char *
-unw_decode (unsigned char *dp, int inside_body, void *arg)
-{
-  unw_decoder decoder;
-  unsigned char code;
-
-  code = *dp++;
-  decoder = unw_decode_table[inside_body][code >> 5];
-  dp = (*decoder) (dp, code, arg);
-  return dp;
-}
-
-\f
-/* RSE helper functions.  */
-
-static inline unsigned long
-ia64_rse_slot_num (unsigned long *addr)
-{
-  return (((unsigned long) addr) >> 3) & 0x3f;
-}
-
-/* Return TRUE if ADDR is the address of an RNAT slot.  */
-static inline unsigned long
-ia64_rse_is_rnat_slot (unsigned long *addr)
-{
-  return ia64_rse_slot_num (addr) == 0x3f;
-}
-
-/* Returns the address of the RNAT slot that covers the slot at
-   address SLOT_ADDR.  */
-static inline unsigned long *
-ia64_rse_rnat_addr (unsigned long *slot_addr)
-{
-  return (unsigned long *) ((unsigned long) slot_addr | (0x3f << 3));
-}
-
-/* Calculate the number of registers in the dirty partition starting at
-   BSPSTORE with a size of DIRTY bytes.  This isn't simply DIRTY
-   divided by eight because the 64th slot is used to store ar.rnat.  */
-static inline unsigned long
-ia64_rse_num_regs (unsigned long *bspstore, unsigned long *bsp)
-{
-  unsigned long slots = (bsp - bspstore);
-
-  return slots - (ia64_rse_slot_num (bspstore) + slots)/0x40;
-}
-
-/* The inverse of the above: given bspstore and the number of
-   registers, calculate ar.bsp.  */
-static inline unsigned long *
-ia64_rse_skip_regs (unsigned long *addr, long num_regs)
-{
-  long delta = ia64_rse_slot_num (addr) + num_regs;
-
-  if (num_regs < 0)
-    delta -= 0x3e;
-  return addr + num_regs + delta/0x3f;
-}
-
-\f
-/* Copy register backing store from SRC to DST, LEN words
-   (which include both saved registers and nat collections).
-   DST_RNAT is a partial nat collection for DST.  SRC and DST
-   don't have to be equal modulo 64 slots, so it cannot be
-   done with a simple memcpy as the nat collections will be
-   at different relative offsets and need to be combined together.  */
-static void
-ia64_copy_rbs (struct _Unwind_Context *info, unsigned long dst,
-               unsigned long src, long len, unsigned long dst_rnat)
-{
-  long count;
-  unsigned long src_rnat;
-  unsigned long shift1, shift2;
-
-  len <<= 3;
-  dst_rnat &= (1UL << ((dst >> 3) & 0x3f)) - 1;
-  src_rnat = src >= info->regstk_top
-            ? info->rnat : *(unsigned long *) (src | 0x1f8);
-  src_rnat &= ~((1UL << ((src >> 3) & 0x3f)) - 1);
-  /* Just to make sure.  */
-  src_rnat &= ~(1UL << 63);
-  shift1 = ((dst - src) >> 3) & 0x3f;
-  if ((dst & 0x1f8) < (src & 0x1f8))
-    shift1--;
-  shift2 = 0x3f - shift1;
-  if ((dst & 0x1f8) >= (src & 0x1f8))
-    {
-      count = ~dst & 0x1f8;
-      goto first;
-    }
-  count = ~src & 0x1f8;
-  goto second;
-  while (len > 0)
-    {
-      src_rnat = src >= info->regstk_top
-                ? info->rnat : *(unsigned long *) (src | 0x1f8);
-      /* Just to make sure.  */
-      src_rnat &= ~(1UL << 63);
-      count = shift2 << 3;
-first:
-      if (count > len)
-        count = len;
-      memcpy ((char *) dst, (char *) src, count);
-      dst += count;
-      src += count;
-      len -= count;
-      dst_rnat |= (src_rnat << shift1) & ~(1UL << 63);
-      if (len <= 0)
-        break;
-      *(long *) dst = dst_rnat;
-      dst += 8;
-      dst_rnat = 0;
-      count = shift1 << 3;
-second:
-      if (count > len)
-        count = len;
-      memcpy ((char *) dst, (char *) src, count);
-      dst += count;
-      src += count + 8;
-      len -= count + 8;
-      dst_rnat |= (src_rnat >> shift2);
-    }
-  if ((dst & 0x1f8) == 0x1f8)
-    {
-      *(long *) dst = dst_rnat;
-      dst += 8;
-      dst_rnat = 0;
-    }
-  /* Set info->regstk_top to lowest rbs address which will use
-     info->rnat collection.  */
-  info->regstk_top = dst & ~0x1ffUL;
-  info->rnat = dst_rnat;
-}
-
-/* Unwind accessors.  */
-
-static void
-unw_access_gr (struct _Unwind_Context *info, int regnum,
-              unsigned long *val, char *nat, int write)
-{
-  unsigned long *addr, *nat_addr = 0, nat_mask = 0, dummy_nat;
-  struct unw_ireg *ireg;
-
-  if ((unsigned) regnum - 1 >= 127)
-    abort ();
-
-  if (regnum < 1)
-    {
-      nat_addr = addr = &dummy_nat;
-      dummy_nat = 0;
-    }
-  else if (regnum < 32)
-    {
-      /* Access a non-stacked register.  */
-      ireg = &info->ireg[regnum - 2];
-      addr = ireg->loc;
-      if (addr)
-       {
-         nat_addr = addr + ireg->nat.off;
-         switch (ireg->nat.type)
-           {
-           case UNW_NAT_VAL:
-             /* Simulate getf.sig/setf.sig.  */
-             if (write)
-               {
-                 if (*nat)
-                   {
-                     /* Write NaTVal and be done with it.  */
-                     addr[0] = 0;
-                     addr[1] = 0x1fffe;
-                     return;
-                   }
-                 addr[1] = 0x1003e;
-               }
-             else if (addr[0] == 0 && addr[1] == 0x1ffe)
-               {
-                 /* Return NaT and be done with it.  */
-                 *val = 0;
-                 *nat = 1;
-                 return;
-               }
-             /* FALLTHRU */
-
-           case UNW_NAT_NONE:
-             dummy_nat = 0;
-             nat_addr = &dummy_nat;
-             break;
-
-           case UNW_NAT_MEMSTK:
-             nat_mask = 1UL << ((long) addr & 0x1f8)/8;
-             break;
-
-           case UNW_NAT_REGSTK:
-             if ((unsigned long) addr >= info->regstk_top)
-               nat_addr = &info->rnat;
-             else
-               nat_addr = ia64_rse_rnat_addr (addr);
-             nat_mask = 1UL << ia64_rse_slot_num (addr);
-             break;
-           }
-       }
-    }
-  else
-    {
-      /* Access a stacked register.  */
-      addr = ia64_rse_skip_regs ((unsigned long *) info->bsp, regnum - 32);
-      if ((unsigned long) addr >= info->regstk_top)
-       nat_addr = &info->rnat;
-      else
-       nat_addr = ia64_rse_rnat_addr (addr);
-      nat_mask = 1UL << ia64_rse_slot_num (addr);
-    }
-
-  if (write)
-    {
-      *addr = *val;
-      if (*nat)
-       *nat_addr |= nat_mask;
-      else
-       *nat_addr &= ~nat_mask;
-    }
-  else
-    {
-      *val = *addr;
-      *nat = (*nat_addr & nat_mask) != 0;
-    }
-}
-\f
-/* Get the value of register REG as saved in CONTEXT.  */
-
-_Unwind_Word
-_Unwind_GetGR (struct _Unwind_Context *context, int index)
-{
-  _Unwind_Word ret;
-  char nat;
-
-  if (index == 1)
-    return context->gp;
-  else if (index >= 15 && index <= 18)
-    return context->eh_data[index - 15];
-  else
-    unw_access_gr (context, index, &ret, &nat, 0);
-
-  return ret;
-}
-
-/* Overwrite the saved value for register REG in CONTEXT with VAL.  */
-
-void
-_Unwind_SetGR (struct _Unwind_Context *context, int index, _Unwind_Word val)
-{
-  char nat = 0;
-
-  if (index == 1)
-    context->gp = val;
-  else if (index >= 15 && index <= 18)
-    context->eh_data[index - 15] = val;
-  else
-    unw_access_gr (context, index, &val, &nat, 1);
-}
-
-/* Retrieve the return address for CONTEXT.  */
-
-inline _Unwind_Ptr
-_Unwind_GetIP (struct _Unwind_Context *context)
-{
-  return context->rp;
-}
-
-inline _Unwind_Ptr
-_Unwind_GetIPInfo (struct _Unwind_Context *context, int *ip_before_insn)
-{
-  *ip_before_insn = 0;
-  return context->rp;
-}
-
-/* Overwrite the return address for CONTEXT with VAL.  */
-
-inline void
-_Unwind_SetIP (struct _Unwind_Context *context, _Unwind_Ptr val)
-{
-  context->rp = val;
-}
-
-void *
-_Unwind_GetLanguageSpecificData (struct _Unwind_Context *context)
-{
-  return context->lsda;
-}
-
-_Unwind_Ptr
-_Unwind_GetRegionStart (struct _Unwind_Context *context)
-{
-  return context->region_start;
-}
-
-void *
-_Unwind_FindEnclosingFunction (void *pc)
-{
-  struct unw_table_entry *entp, ent;
-  unsigned long segment_base, gp;
-
-  entp = _Unwind_FindTableEntry (pc, &segment_base, &gp, &ent);
-  if (entp == NULL)
-    return NULL;
-  else
-    return (void *)(segment_base + entp->start_offset);
-}
-
-/* Get the value of the CFA as saved in CONTEXT.  In GCC/Dwarf2 parlance,
-   the CFA is the value of the stack pointer on entry; In IA-64 unwind
-   parlance, this is the PSP.  */
-
-_Unwind_Word
-_Unwind_GetCFA (struct _Unwind_Context *context)
-{
-  return (_Unwind_Ptr) context->psp;
-}
-
-/* Get the value of the Backing Store Pointer as saved in CONTEXT.  */
-
-_Unwind_Word
-_Unwind_GetBSP (struct _Unwind_Context *context)
-{
-  return (_Unwind_Ptr) context->bsp;
-}
-
-#include "md-unwind-support.h"
-\f
-static _Unwind_Reason_Code
-uw_frame_state_for (struct _Unwind_Context *context, _Unwind_FrameState *fs)
-{
-  struct unw_table_entry *entp, ent;
-  unsigned long *unw, header, length;
-  unsigned char *insn, *insn_end;
-  unsigned long segment_base;
-  struct unw_reg_info *r;
-
-  memset (fs, 0, sizeof (*fs));
-  for (r = fs->curr.reg; r < fs->curr.reg + UNW_NUM_REGS; ++r)
-    r->when = UNW_WHEN_NEVER;
-  context->lsda = 0;
-
-  entp = _Unwind_FindTableEntry ((void *) context->rp,
-                               &segment_base, &context->gp, &ent);
-  if (entp == NULL)
-    {
-      /* Couldn't find unwind info for this function.  Try an
-        os-specific fallback mechanism.  This will necessarily
-        not provide a personality routine or LSDA.  */
-#ifdef MD_FALLBACK_FRAME_STATE_FOR
-      if (MD_FALLBACK_FRAME_STATE_FOR (context, fs) == _URC_NO_REASON)
-       return _URC_NO_REASON;
-#endif
-
-      /* [SCRA 11.4.1] A leaf function with no memory stack, no exception
-        handlers, and which keeps the return value in B0 does not need
-        an unwind table entry.
-
-        This can only happen in the frame after unwinding through a signal
-        handler.  Avoid infinite looping by requiring that B0 != RP.
-        RP == 0 terminates the chain.  */
-      if (context->br_loc[0]
-         && *context->br_loc[0] != context->rp
-         && context->rp != 0)
-       goto skip_unwind_info;
-
-      return _URC_END_OF_STACK;
-    }
-
-  context->region_start = entp->start_offset + segment_base;
-  fs->when_target = ((context->rp & -16) - context->region_start) / 16 * 3
-                   + (context->rp & 15);
-
-  unw = (unsigned long *) (entp->info_offset + segment_base);
-  header = *unw;
-  length = UNW_LENGTH (header);
-
-  /* Some operating systems use the personality routine slot in way not
-     compatible with what we expect.  For instance, OpenVMS uses this slot to
-     designate "condition handlers" with very different arguments than what we
-     would be providing.  Such cases are typically identified from OS specific
-     bits in the unwind information block header, and checked by the target
-     MD_UNW_COMPATIBLE_PERSONALITY_P macro. 
-
-     We just pretend there is no personality from our standpoint in such
-     situations, and expect GCC not to set the identifying bits itself so that
-     compatible personalities for GCC compiled code are called.
-
-     Of course, this raises the question of what combinations of native/GCC
-     calls can be expected to behave properly exception handling-wise.  We are
-     not to provide a magic answer here, merely to prevent crashes assuming
-     users know what they are doing.
-
-     ??? Perhaps check UNW_VER / UNW_FLAG_OSMASK as well.  */
-
-  if (MD_UNW_COMPATIBLE_PERSONALITY_P (header)
-      && (UNW_FLAG_EHANDLER (header) | UNW_FLAG_UHANDLER (header)))
-    {
-      fs->personality =
-       *(_Unwind_Personality_Fn *) (unw[length + 1] + context->gp);
-      context->lsda = unw + length + 2;
-    }
-
-  insn = (unsigned char *) (unw + 1);
-  insn_end = (unsigned char *) (unw + 1 + length);
-  while (!fs->done && insn < insn_end)
-    insn = unw_decode (insn, fs->in_body, fs);
-
-  free_label_states (fs->labeled_states);
-  free_state_stack (&fs->curr);
-
-#ifdef ENABLE_MALLOC_CHECKING
-  if (reg_state_alloced || labeled_state_alloced)
-    abort ();
-#endif
-
-  /* If we're in the epilogue, sp has been restored and all values
-     on the memory stack below psp also have been restored.  */
-  if (fs->when_target > fs->epilogue_start)
-    {
-      struct unw_reg_info *r;
-
-      fs->curr.reg[UNW_REG_PSP].where = UNW_WHERE_NONE;
-      fs->curr.reg[UNW_REG_PSP].val = 0;
-      for (r = fs->curr.reg; r < fs->curr.reg + UNW_NUM_REGS; ++r)
-       if ((r->where == UNW_WHERE_PSPREL && r->val <= 0x10)
-           || r->where == UNW_WHERE_SPREL)
-         r->where = UNW_WHERE_NONE;
-    }
-
-skip_unwind_info:
-  /* If RP didn't get saved, generate entry for the return link register.  */
-  if (fs->curr.reg[UNW_REG_RP].when >= fs->when_target)
-    {
-      fs->curr.reg[UNW_REG_RP].where = UNW_WHERE_BR;
-      fs->curr.reg[UNW_REG_RP].when = -1;
-      fs->curr.reg[UNW_REG_RP].val = fs->return_link_reg;
-    }
-
-  /* There is a subtlety for the frame after unwinding through a signal
-     handler: should we restore the cfm as usual or the pfs?  We can't
-     restore both because we use br.ret to resume execution of user code.
-     For other frames the procedure is by definition non-leaf so the pfs
-     is saved and restored and thus effectively dead in the body; only
-     the cfm need therefore be restored.
-     
-     Here we have 2 cases:
-       - either the pfs is saved and restored and thus effectively dead
-        like in regular frames; then we do nothing special and restore
-        the cfm.
-       - or the pfs is not saved and thus live; but in that case the
-        procedure is necessarily leaf so the cfm is effectively dead
-        and we restore the pfs.  */
-  if (context->signal_pfs_loc)
-    {
-      if (fs->curr.reg[UNW_REG_PFS].when >= fs->when_target)
-       context->pfs_loc = context->signal_pfs_loc;
-      context->signal_pfs_loc = NULL;
-    }
-
-  return _URC_NO_REASON;
-}
-
-static void
-uw_update_reg_address (struct _Unwind_Context *context,
-                      _Unwind_FrameState *fs,
-                      enum unw_register_index regno)
-{
-  struct unw_reg_info *r = fs->curr.reg + regno;
-  void *addr;
-  unsigned long rval;
-
-  if (r->where == UNW_WHERE_NONE || r->when >= fs->when_target)
-    return;
-
-  rval = r->val;
-  switch (r->where)
-    {
-    case UNW_WHERE_GR:
-      if (rval >= 32)
-       addr = ia64_rse_skip_regs ((unsigned long *) context->bsp, rval - 32);
-      else if (rval >= 2)
-       addr = context->ireg[rval - 2].loc;
-      else if (rval == 0)
-       {
-         static const unsigned long dummy;
-         addr = (void *) &dummy;
-       }
-      else
-       abort ();
-      break;
-
-    case UNW_WHERE_FR:
-      if (rval >= 2 && rval < 32)
-       addr = context->fr_loc[rval - 2];
-      else
-       abort ();
-      break;
-
-    case UNW_WHERE_BR:
-      /* Note that while RVAL can only be 1-5 from normal descriptors,
-        we can want to look at B0, B6 and B7 due to having manually unwound a
-        signal frame.  */
-      if (rval < 8)
-       addr = context->br_loc[rval];
-      else
-       abort ();
-      break;
-
-    case UNW_WHERE_SPREL:
-      addr = (void *)(context->sp + rval);
-      break;
-
-    case UNW_WHERE_PSPREL:
-      addr = (void *)(context->psp + rval);
-      break;
-
-    default:
-      abort ();
-    }
-
-  switch (regno)
-    {
-    case UNW_REG_R2 ... UNW_REG_R31:
-      context->ireg[regno - UNW_REG_R2].loc = addr;
-      switch (r->where)
-      {
-      case UNW_WHERE_GR:
-       if (rval >= 32)
-         {
-           context->ireg[regno - UNW_REG_R2].nat.type = UNW_NAT_MEMSTK;
-           context->ireg[regno - UNW_REG_R2].nat.off
-             = context->pri_unat_loc - (unsigned long *) addr;
-         }
-       else if (rval >= 2)
-         {
-           context->ireg[regno - UNW_REG_R2].nat
-             = context->ireg[rval - 2].nat;
-         }
-       else if (rval == 0)
-         {
-           context->ireg[regno - UNW_REG_R2].nat.type = UNW_NAT_NONE;
-           context->ireg[regno - UNW_REG_R2].nat.off = 0;
-         }
-       else
-         abort ();
-       break;
-
-      case UNW_WHERE_FR:
-       context->ireg[regno - UNW_REG_R2].nat.type = UNW_NAT_VAL;
-       context->ireg[regno - UNW_REG_R2].nat.off = 0;
-       break;
-
-      case UNW_WHERE_BR:
-       context->ireg[regno - UNW_REG_R2].nat.type = UNW_NAT_NONE;
-       context->ireg[regno - UNW_REG_R2].nat.off = 0;
-       break;
-
-      case UNW_WHERE_PSPREL:
-      case UNW_WHERE_SPREL:
-       context->ireg[regno - UNW_REG_R2].nat.type = UNW_NAT_MEMSTK;
-       context->ireg[regno - UNW_REG_R2].nat.off
-         = context->pri_unat_loc - (unsigned long *) addr;
-       break;
-
-      default:
-       abort ();
-      }
-      break;
-
-    case UNW_REG_F2 ... UNW_REG_F31:
-      context->fr_loc[regno - UNW_REG_F2] = addr;
-      break;
-
-    case UNW_REG_B1 ... UNW_REG_B5:
-      context->br_loc[regno - UNW_REG_B0] = addr;
-      break;
-
-    case UNW_REG_BSP:
-      context->bsp_loc = addr;
-      break;
-    case UNW_REG_BSPSTORE:
-      context->bspstore_loc = addr;
-      break;
-    case UNW_REG_PFS:
-      context->pfs_loc = addr;
-      break;
-    case UNW_REG_RP:
-      context->rp = *(unsigned long *)addr;
-      break;
-    case UNW_REG_UNAT:
-      context->unat_loc = addr;
-      break;
-    case UNW_REG_PR:
-      context->pr = *(unsigned long *) addr;
-      break;
-    case UNW_REG_LC:
-      context->lc_loc = addr;
-      break;
-    case UNW_REG_FPSR:
-      context->fpsr_loc = addr;
-      break;
-
-    case UNW_REG_PSP:
-      context->psp = *(unsigned long *)addr;
-      break;
-
-    default:
-      abort ();
-    }
-}
-
-static void
-uw_update_context (struct _Unwind_Context *context, _Unwind_FrameState *fs)
-{
-  long i;
-
-#ifdef MD_HANDLE_UNWABI
-  MD_HANDLE_UNWABI (context, fs);
-#endif
-
-  context->sp = context->psp;
-
-  /* First, set PSP.  Subsequent instructions may depend on this value.  */
-  if (fs->when_target > fs->curr.reg[UNW_REG_PSP].when)
-    {
-      if (fs->curr.reg[UNW_REG_PSP].where == UNW_WHERE_NONE)
-       context->psp = context->psp + fs->curr.reg[UNW_REG_PSP].val;
-      else
-       uw_update_reg_address (context, fs, UNW_REG_PSP);
-    }
-
-  /* Determine the location of the primary UNaT.  */
-  {
-    int i;
-    if (fs->when_target < fs->curr.reg[UNW_REG_PRI_UNAT_GR].when)
-      i = UNW_REG_PRI_UNAT_MEM;
-    else if (fs->when_target < fs->curr.reg[UNW_REG_PRI_UNAT_MEM].when)
-      i = UNW_REG_PRI_UNAT_GR;
-    else if (fs->curr.reg[UNW_REG_PRI_UNAT_MEM].when
-            > fs->curr.reg[UNW_REG_PRI_UNAT_GR].when)
-      i = UNW_REG_PRI_UNAT_MEM;
-    else
-      i = UNW_REG_PRI_UNAT_GR;
-    uw_update_reg_address (context, fs, i);
-  }
-
-  /* Compute the addresses of all registers saved in this frame.  */
-  for (i = UNW_REG_BSP; i < UNW_NUM_REGS; ++i)
-    uw_update_reg_address (context, fs, i);
-
-  /* Unwind BSP for the local registers allocated this frame.  */
-  /* ??? What to do with stored BSP or BSPSTORE registers.  */
-  /* We assert that we are either at a call site, or we have
-     just unwound through a signal frame.  In either case
-     pfs_loc is valid. */
-  if (!(fs -> no_reg_stack_frame))
-    {
-      unsigned long pfs = *context->pfs_loc;
-      unsigned long sol = (pfs >> 7) & 0x7f;
-      context->bsp = (unsigned long)
-       ia64_rse_skip_regs ((unsigned long *) context->bsp, -sol);
-    }
-}
-
-static void
-uw_advance_context (struct _Unwind_Context *context, _Unwind_FrameState *fs)
-{
-  uw_update_context (context, fs);
-}
-
-/* Fill in CONTEXT for top-of-stack.  The only valid registers at this
-   level will be the return address and the CFA.  Note that CFA = SP+16.  */
-   
-#define uw_init_context(CONTEXT)                                       \
-  do {                                                                 \
-    /* ??? There is a whole lot o code in uw_install_context that      \
-       tries to avoid spilling the entire machine state here.  We      \
-       should try to make that work again.  */                         \
-    __builtin_unwind_init();                                           \
-    uw_init_context_1 (CONTEXT, __builtin_ia64_bsp ());                        \
-  } while (0)
-
-static void __attribute__((noinline))
-uw_init_context_1 (struct _Unwind_Context *context, void *bsp)
-{
-  void *rp = __builtin_extract_return_addr (__builtin_return_address (0));
-  /* Set psp to the caller's stack pointer.  */
-  void *psp = __builtin_dwarf_cfa () - 16;
-  _Unwind_FrameState fs;
-  unsigned long rnat, tmp1, tmp2;
-
-  /* Flush the register stack to memory so that we can access it.
-     Get rse nat collection for the last incomplete rbs chunk of
-     registers at the same time.  For this RSE needs to be turned
-     into the mandatory only mode.  */
-  asm ("mov.m %1 = ar.rsc;;\n\t"
-       "and %2 = 0x1c, %1;;\n\t"
-       "mov.m ar.rsc = %2;;\n\t"
-       "flushrs;;\n\t"
-       "mov.m %0 = ar.rnat;;\n\t"
-       "mov.m ar.rsc = %1\n\t"
-       : "=r" (rnat), "=r" (tmp1), "=r" (tmp2));
-
-  memset (context, 0, sizeof (struct _Unwind_Context));
-  context->bsp = (unsigned long) bsp;
-  /* Set context->regstk_top to lowest rbs address which will use
-     context->rnat collection.  */
-  context->regstk_top = context->bsp & ~0x1ffULL;
-  context->rnat = rnat;
-  context->psp = (unsigned long) psp;
-  context->rp = (unsigned long) rp;
-  asm ("mov %0 = sp" : "=r" (context->sp));
-  asm ("mov %0 = pr" : "=r" (context->pr));
-  context->pri_unat_loc = &context->initial_unat;      /* ??? */
-
-  if (uw_frame_state_for (context, &fs) != _URC_NO_REASON)
-    abort ();
-
-  uw_update_context (context, &fs);
-}
-
-/* Install (i.e. longjmp to) the contents of TARGET.  */
-
-static void __attribute__((noreturn))
-uw_install_context (struct _Unwind_Context *current __attribute__((unused)),
-                   struct _Unwind_Context *target)
-{
-  unsigned long ireg_buf[4], ireg_nat = 0, ireg_pr = 0;
-  long i;
-
-  /* Copy integer register data from the target context to a
-     temporary buffer.  Do this so that we can frob AR.UNAT
-     to get the NaT bits for these registers set properly.  */
-  for (i = 4; i <= 7; ++i)
-    {
-      char nat;
-      void *t = target->ireg[i - 2].loc;
-      if (t)
-       {
-         unw_access_gr (target, i, &ireg_buf[i - 4], &nat, 0);
-          ireg_nat |= (long)nat << (((size_t)&ireg_buf[i - 4] >> 3) & 0x3f);
-         /* Set p6 - p9.  */
-         ireg_pr |= 4L << i;
-       }
-    }
-
-  /* The value in uc_bsp that we've computed is that for the 
-     target function.  The value that we install below will be
-     adjusted by the BR.RET instruction based on the contents
-     of AR.PFS.  So we must unadjust that here.  */
-  target->bsp = (unsigned long)
-    ia64_rse_skip_regs ((unsigned long *)target->bsp,
-                       (*target->pfs_loc >> 7) & 0x7f);
-
-  if (target->bsp < target->regstk_top)
-    target->rnat = *ia64_rse_rnat_addr ((unsigned long *) target->bsp);
-
-  /* Provide assembly with the offsets into the _Unwind_Context.  */
-  asm volatile ("uc_rnat = %0"
-               : : "i"(offsetof (struct _Unwind_Context, rnat)));
-  asm volatile ("uc_bsp = %0"
-               : : "i"(offsetof (struct _Unwind_Context, bsp)));
-  asm volatile ("uc_psp = %0"
-               : : "i"(offsetof (struct _Unwind_Context, psp)));
-  asm volatile ("uc_rp = %0"
-               : : "i"(offsetof (struct _Unwind_Context, rp)));
-  asm volatile ("uc_pr = %0"
-               : : "i"(offsetof (struct _Unwind_Context, pr)));
-  asm volatile ("uc_gp = %0"
-               : : "i"(offsetof (struct _Unwind_Context, gp)));
-  asm volatile ("uc_pfs_loc = %0"
-               : : "i"(offsetof (struct _Unwind_Context, pfs_loc)));
-  asm volatile ("uc_unat_loc = %0"
-               : : "i"(offsetof (struct _Unwind_Context, unat_loc)));
-  asm volatile ("uc_lc_loc = %0"
-               : : "i"(offsetof (struct _Unwind_Context, lc_loc)));
-  asm volatile ("uc_fpsr_loc = %0"
-               : : "i"(offsetof (struct _Unwind_Context, fpsr_loc)));
-  asm volatile ("uc_eh_data = %0"
-               : : "i"(offsetof (struct _Unwind_Context, eh_data)));
-  asm volatile ("uc_br_loc = %0"
-               : : "i"(offsetof (struct _Unwind_Context, br_loc)));
-  asm volatile ("uc_fr_loc = %0"
-               : : "i"(offsetof (struct _Unwind_Context, fr_loc)));
-
-  asm volatile (
-       /* Load up call-saved non-window integer registers from ireg_buf.  */
-       "add r20 = 8, %1                        \n\t"
-       "mov ar.unat = %2                       \n\t"
-       "mov pr = %3, 0x3c0                     \n\t"
-       ";;                                     \n\t"
-       "(p6) ld8.fill r4 = [%1]                \n\t"
-       "(p7) ld8.fill r5 = [r20]               \n\t"
-       "add r21 = uc_br_loc + 16, %0           \n\t"
-       "adds %1 = 16, %1                       \n\t"
-       "adds r20 = 16, r20                     \n\t"
-       ";;                                     \n\t"
-       "(p8) ld8.fill r6 = [%1]                \n\t"
-       "(p9) ld8.fill r7 = [r20]               \n\t"
-       "add r20 = uc_br_loc + 8, %0            \n\t"
-       ";;                                     \n\t"
-       /* Load up call-saved branch registers.  */
-       "ld8 r22 = [r20], 16                    \n\t"
-       "ld8 r23 = [r21], 16                    \n\t"
-       ";;                                     \n\t"
-       "ld8 r24 = [r20], 16                    \n\t"
-       "ld8 r25 = [r21], uc_fr_loc - (uc_br_loc + 32)\n\t"
-       ";;                                     \n\t"
-       "ld8 r26 = [r20], uc_fr_loc + 8 - (uc_br_loc + 40)\n\t"
-       "ld8 r27 = [r21], 24                    \n\t"
-       "cmp.ne p6, p0 = r0, r22                \n\t"
-       ";;                                     \n\t"
-       "ld8 r28 = [r20], 8                     \n\t"
-       "(p6) ld8 r22 = [r22]                   \n\t"
-       "cmp.ne p7, p0 = r0, r23                \n\t"
-       ";;                                     \n\t"
-       "(p7) ld8 r23 = [r23]                   \n\t"
-       "cmp.ne p8, p0 = r0, r24                \n\t"
-       ";;                                     \n\t"
-       "(p8) ld8 r24 = [r24]                   \n\t"
-       "(p6) mov b1 = r22                      \n\t"
-       "cmp.ne p9, p0 = r0, r25                \n\t"
-       ";;                                     \n\t"
-       "(p9) ld8 r25 = [r25]                   \n\t"
-       "(p7) mov b2 = r23                      \n\t"
-       "cmp.ne p6, p0 = r0, r26                \n\t"
-       ";;                                     \n\t"
-       "(p6) ld8 r26 = [r26]                   \n\t"
-       "(p8) mov b3 = r24                      \n\t"
-       "cmp.ne p7, p0 = r0, r27                \n\t"
-       ";;                                     \n\t"
-       /* Load up call-saved fp registers.  */
-       "(p7) ldf.fill f2 = [r27]               \n\t"
-       "(p9) mov b4 = r25                      \n\t"
-       "cmp.ne p8, p0 = r0, r28                \n\t"
-       ";;                                     \n\t"
-       "(p8) ldf.fill f3 = [r28]               \n\t"
-       "(p6) mov b5 = r26                      \n\t"
-       ";;                                     \n\t"
-       "ld8 r29 = [r20], 16*8 - 4*8            \n\t"
-       "ld8 r30 = [r21], 17*8 - 5*8            \n\t"
-       ";;                                     \n\t"
-       "ld8 r22 = [r20], 16                    \n\t"
-       "ld8 r23 = [r21], 16                    \n\t"
-       ";;                                     \n\t"
-       "ld8 r24 = [r20], 16                    \n\t"
-       "ld8 r25 = [r21]                        \n\t"
-       "cmp.ne p6, p0 = r0, r29                \n\t"
-       ";;                                     \n\t"
-       "ld8 r26 = [r20], 8                     \n\t"
-       "(p6) ldf.fill f4 = [r29]               \n\t"
-       "cmp.ne p7, p0 = r0, r30                \n\t"
-       ";;                                     \n\t"
-       "ld8 r27 = [r20], 8                     \n\t"
-       "(p7) ldf.fill f5 = [r30]               \n\t"
-       "cmp.ne p6, p0 = r0, r22                \n\t"
-       ";;                                     \n\t"
-       "ld8 r28 = [r20], 8                     \n\t"
-       "(p6) ldf.fill f16 = [r22]              \n\t"
-       "cmp.ne p7, p0 = r0, r23                \n\t"
-       ";;                                     \n\t"
-       "ld8 r29 = [r20], 8                     \n\t"
-       "(p7) ldf.fill f17 = [r23]              \n\t"
-       "cmp.ne p6, p0 = r0, r24                \n\t"
-       ";;                                     \n\t"
-       "ld8 r22 = [r20], 8                     \n\t"
-       "(p6) ldf.fill f18 = [r24]              \n\t"
-       "cmp.ne p7, p0 = r0, r25                \n\t"
-       ";;                                     \n\t"
-       "ld8 r23 = [r20], 8                     \n\t"
-       "(p7) ldf.fill f19 = [r25]              \n\t"
-       "cmp.ne p6, p0 = r0, r26                \n\t"
-       ";;                                     \n\t"
-       "ld8 r24 = [r20], 8                     \n\t"
-       "(p6) ldf.fill f20 = [r26]              \n\t"
-       "cmp.ne p7, p0 = r0, r27                \n\t"
-       ";;                                     \n\t"
-       "ld8 r25 = [r20], 8                     \n\t"
-       "(p7) ldf.fill f21 = [r27]              \n\t"
-       "cmp.ne p6, p0 = r0, r28                \n\t"
-       ";;                                     \n\t"
-       "ld8 r26 = [r20], 8                     \n\t"
-       "(p6) ldf.fill f22 = [r28]              \n\t"
-       "cmp.ne p7, p0 = r0, r29                \n\t"
-       ";;                                     \n\t"
-       "ld8 r27 = [r20], 8                     \n\t"
-       ";;                                     \n\t"
-       "ld8 r28 = [r20], 8                     \n\t"
-       "(p7) ldf.fill f23 = [r29]              \n\t"
-       "cmp.ne p6, p0 = r0, r22                \n\t"
-       ";;                                     \n\t"
-       "ld8 r29 = [r20], 8                     \n\t"
-       "(p6) ldf.fill f24 = [r22]              \n\t"
-       "cmp.ne p7, p0 = r0, r23                \n\t"
-       ";;                                     \n\t"
-       "(p7) ldf.fill f25 = [r23]              \n\t"
-       "cmp.ne p6, p0 = r0, r24                \n\t"
-       "cmp.ne p7, p0 = r0, r25                \n\t"
-       ";;                                     \n\t"
-       "(p6) ldf.fill f26 = [r24]              \n\t"
-       "(p7) ldf.fill f27 = [r25]              \n\t"
-       "cmp.ne p6, p0 = r0, r26                \n\t"
-       ";;                                     \n\t"
-       "(p6) ldf.fill f28 = [r26]              \n\t"
-       "cmp.ne p7, p0 = r0, r27                \n\t"
-       "cmp.ne p6, p0 = r0, r28                \n\t"
-       ";;                                     \n\t"
-       "(p7) ldf.fill f29 = [r27]              \n\t"
-       "(p6) ldf.fill f30 = [r28]              \n\t"
-       "cmp.ne p7, p0 = r0, r29                \n\t"
-       ";;                                     \n\t"
-       "(p7) ldf.fill f31 = [r29]              \n\t"
-       "add r20 = uc_rnat, %0                  \n\t"
-       "add r21 = uc_bsp, %0                   \n\t"
-       ";;                                     \n\t"
-       /* Load the balance of the thread state from the context.  */
-       "ld8 r22 = [r20], uc_psp - uc_rnat      \n\t"
-       "ld8 r23 = [r21], uc_gp - uc_bsp        \n\t"
-       ";;                                     \n\t"
-       "ld8 r24 = [r20], uc_pfs_loc - uc_psp   \n\t"
-       "ld8 r1 = [r21], uc_rp - uc_gp          \n\t"
-       ";;                                     \n\t"
-       "ld8 r25 = [r20], uc_unat_loc - uc_pfs_loc\n\t"
-       "ld8 r26 = [r21], uc_pr - uc_rp         \n\t"
-       ";;                                     \n\t"
-       "ld8 r27 = [r20], uc_lc_loc - uc_unat_loc\n\t"
-       "ld8 r28 = [r21], uc_fpsr_loc - uc_pr   \n\t"
-       ";;                                     \n\t"
-       "ld8 r29 = [r20], uc_eh_data - uc_lc_loc\n\t"
-       "ld8 r30 = [r21], uc_eh_data + 8 - uc_fpsr_loc\n\t"
-       ";;                                     \n\t"
-       /* Load data for the exception handler.  */
-       "ld8 r15 = [r20], 16                    \n\t"
-       "ld8 r16 = [r21], 16                    \n\t"
-       ";;                                     \n\t"
-       "ld8 r17 = [r20]                        \n\t"
-       "ld8 r18 = [r21]                        \n\t"
-       ";;                                     \n\t"
-       /* Install the balance of the thread state loaded above.  */
-       "cmp.ne p6, p0 = r0, r25                \n\t"
-       "cmp.ne p7, p0 = r0, r27                \n\t"
-       ";;                                     \n\t"
-       "(p6) ld8 r25 = [r25]                   \n\t"
-       "(p7) ld8 r27 = [r27]                   \n\t"
-       ";;                                     \n\t"
-       "(p7) mov.m ar.unat = r27               \n\t"
-       "(p6) mov.i ar.pfs = r25                \n\t"
-       "cmp.ne p9, p0 = r0, r29                \n\t"
-       ";;                                     \n\t"
-       "(p9) ld8 r29 = [r29]                   \n\t"
-       "cmp.ne p6, p0 = r0, r30                \n\t"
-       ";;                                     \n\t"
-       "(p6) ld8 r30 = [r30]                   \n\t"
-       /* Don't clobber p6-p9, which are in use at present.  */
-       "mov pr = r28, ~0x3c0                   \n\t"
-       "(p9) mov.i ar.lc = r29                 \n\t"
-       ";;                                     \n\t"
-       "mov.m r25 = ar.rsc                     \n\t"
-       "(p6) mov.m ar.fpsr = r30               \n\t"
-       ";;                                     \n\t"
-       "and r29 = 0x1c, r25                    \n\t"
-       "mov b0 = r26                           \n\t"
-       ";;                                     \n\t"
-       "mov.m ar.rsc = r29                     \n\t"
-       ";;                                     \n\t"
-       /* This must be done before setting AR.BSPSTORE, otherwise 
-          AR.BSP will be initialized with a random displacement
-          below the value we want, based on the current number of
-          dirty stacked registers.  */
-       "loadrs                                 \n\t"
-       "invala                                 \n\t"
-       ";;                                     \n\t"
-       "mov.m ar.bspstore = r23                \n\t"
-       ";;                                     \n\t"
-       "mov.m ar.rnat = r22                    \n\t"
-       ";;                                     \n\t"
-       "mov.m ar.rsc = r25                     \n\t"
-       "mov sp = r24                           \n\t"
-       "br.ret.sptk.few b0"
-       : : "r"(target), "r"(ireg_buf), "r"(ireg_nat), "r"(ireg_pr)
-       : "r15", "r16", "r17", "r18", "r20", "r21", "r22",
-         "r23", "r24", "r25", "r26", "r27", "r28", "r29",
-         "r30", "r31");
-  /* NOTREACHED */
-  while (1);
-}
-
-static inline _Unwind_Ptr
-uw_identify_context (struct _Unwind_Context *context)
-{
-  return _Unwind_GetIP (context);
-}
-
-#include "unwind.inc"
-
-#if defined (USE_GAS_SYMVER) && defined (SHARED) && defined (USE_LIBUNWIND_EXCEPTIONS)
-alias (_Unwind_Backtrace);
-alias (_Unwind_DeleteException);
-alias (_Unwind_FindEnclosingFunction);
-alias (_Unwind_ForcedUnwind);
-alias (_Unwind_GetBSP);
-alias (_Unwind_GetCFA);
-alias (_Unwind_GetGR);
-alias (_Unwind_GetIP);
-alias (_Unwind_GetLanguageSpecificData);
-alias (_Unwind_GetRegionStart);
-alias (_Unwind_RaiseException);
-alias (_Unwind_Resume);
-alias (_Unwind_Resume_or_Rethrow);
-alias (_Unwind_SetGR);
-alias (_Unwind_SetIP);
-#endif
-
-#endif
diff --git a/gcc/config/ia64/unwind-ia64.h b/gcc/config/ia64/unwind-ia64.h
deleted file mode 100644 (file)
index b98f048..0000000
+++ /dev/null
@@ -1,43 +0,0 @@
-/* Copyright (C) 1999, 2000, 2001, 2007, 2009 Free Software Foundation, Inc.
-   Contributed by Andrew MacLeod  <amacleod@cygnus.com>
-                  Andrew Haley  <aph@cygnus.com>
-
-   This file is part of GCC.
-
-   GCC 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 3, or (at your option)
-   any later version.
-
-   GCC 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 GCC; see the file COPYING3.  If not see
-   <http://www.gnu.org/licenses/>.  */
-
-struct unw_table_entry
-{
-  unsigned long start_offset;
-  unsigned long end_offset;
-  unsigned long info_offset;
-};
-
-/* Accessors to fields of an unwind info block header.  In this common file to
-   be visible from all the units involved in a target implementation.  */
-   
-#ifndef __USING_SJLJ_EXCEPTIONS__
-#define UNW_VER(x)             ((x) >> 48)
-#define UNW_FLAG_MASK          0x0000ffff00000000
-#define UNW_FLAG_OSMASK                0x0000f00000000000
-#define UNW_FLAG_EHANDLER(x)   ((x) & 0x0000000100000000L)
-#define UNW_FLAG_UHANDLER(x)   ((x) & 0x0000000200000000L)
-#define UNW_LENGTH(x)          ((x) & 0x00000000ffffffffL)
-#endif
-
-extern struct unw_table_entry *
-_Unwind_FindTableEntry (void *pc, unsigned long *segment_base,
-                       unsigned long *gp, struct unw_table_entry *ent)
-                       __attribute__ ((__visibility__ ("hidden")));
index 847d79afa1d5adcb9b2364078223073fe2ea220b..853e0239d3b52dd265970fa5d5d38b1f45800cd7 100644 (file)
@@ -139,9 +139,6 @@ STATIC func_ptr __CTOR_LIST__[1]                                             \
 /* Define this to be nonzero if static stack checking is supported.  */
 #define STACK_CHECK_STATIC_BUILTIN 1
 
-#define UNW_IVMS_MODE(HEADER) (((HEADER) >> 44) & 0x3L)
-#define MD_UNW_COMPATIBLE_PERSONALITY_P(HEADER) (!UNW_IVMS_MODE (HEADER))
-
 /* Minimum amount of stack required to recover from an anticipated stack
    overflow detection.  The default value conveys an estimate of the amount
    of stack required to propagate an exception.  */
index ba4394eceebcc1e7bef9dd17d2d20f123196a1e8..4df74a01fc6b1fe661b9aa286cdb4254c12de9b8 100644 (file)
@@ -43,9 +43,6 @@ LIB2FUNCS_EXTRA = \
 LIB1ASMFUNCS = _mulsc3 _divsc3
 LIB1ASMSRC = picochip/libgccExtras/fake_libgcc.asm
 
-# Turn off the building of exception handling libraries.
-LIB2ADDEH =
-
 # Turn off ranlib on target libraries.
 RANLIB_FOR_TARGET = cat
 
index 13d317f508a9f377d5a00c618f5d4657ce607ee0..2c678a3a247921427a2b5e233ecdea13a31645c3 100644 (file)
 /* And similarly for general purpose registers.  */
 #define GP_SAVE_INLINE(FIRST_REG) ((FIRST_REG) < 32)
 
-/* If the current unwind info (FS) does not contain explicit info
-   saving R2, then we have to do a minor amount of code reading to
-   figure out if it was saved.  The big problem here is that the
-   code that does the save/restore is generated by the linker, so
-   we have no good way to determine at compile time what to do.  */
-
-#define R_LR 65
-
-#ifdef __64BIT__
-#define MD_FROB_UPDATE_CONTEXT(CTX, FS)                                        \
-  do {                                                                 \
-    if ((FS)->regs.reg[2].how == REG_UNSAVED)                          \
-      {                                                                        \
-       unsigned int *insn                                              \
-         = (unsigned int *)                                            \
-           _Unwind_GetGR ((CTX), R_LR);                                \
-       if (*insn == 0xE8410028)                                        \
-         _Unwind_SetGRPtr ((CTX), 2, (CTX)->cfa + 40);                 \
-      }                                                                        \
-  } while (0)
-#else
-#define MD_FROB_UPDATE_CONTEXT(CTX, FS)                                        \
-  do {                                                                 \
-    if ((FS)->regs.reg[2].how == REG_UNSAVED)                          \
-      {                                                                        \
-       unsigned int *insn                                              \
-         = (unsigned int *)                                            \
-           _Unwind_GetGR ((CTX), R_LR);                                \
-       if (*insn == 0x80410014)                                        \
-         _Unwind_SetGRPtr ((CTX), 2, (CTX)->cfa + 20);                 \
-      }                                                                        \
-  } while (0)
-#endif
-
 #define PROFILE_HOOK(LABEL)   output_profile_hook (LABEL)
 
 /* No version of AIX fully supports AltiVec or 64-bit instructions in
diff --git a/gcc/config/rs6000/darwin-fallback.c b/gcc/config/rs6000/darwin-fallback.c
deleted file mode 100644 (file)
index 4591071..0000000
+++ /dev/null
@@ -1,487 +0,0 @@
-/* Fallback frame-state unwinder for Darwin.
-   Copyright (C) 2004, 2005, 2007, 2009 Free Software Foundation, Inc.
-
-   This file is part of GCC.
-
-   GCC 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 3, or (at your option)
-   any later version.
-
-   GCC 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.
-
-   Under Section 7 of GPL version 3, you are granted additional
-   permissions described in the GCC Runtime Library Exception, version
-   3.1, as published by the Free Software Foundation.
-
-   You should have received a copy of the GNU General Public License and
-   a copy of the GCC Runtime Library Exception along with this program;
-   see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
-   <http://www.gnu.org/licenses/>.  */
-
-#ifdef __ppc__
-
-#include "tconfig.h"
-#include "tsystem.h"
-#include "coretypes.h"
-#include "tm.h"
-#include "dwarf2.h"
-#include "unwind.h"
-#include "unwind-dw2.h"
-#include <stdint.h>
-#include <stdbool.h>
-#include <sys/types.h>
-#include <signal.h>
-
-#define R_LR           65
-#define R_CTR          66
-#define R_CR2          70
-#define R_XER          76
-#define R_VR0          77
-#define R_VRSAVE       109
-#define R_VSCR         110
-#define R_SPEFSCR      112
-
-typedef unsigned long reg_unit;
-
-/* Place in GPRS the parameters to the first 'sc' instruction that would
-   have been executed if we were returning from this CONTEXT, or
-   return false if an unexpected instruction is encountered.  */
-
-static bool
-interpret_libc (reg_unit gprs[32], struct _Unwind_Context *context)
-{
-  uint32_t *pc = (uint32_t *)_Unwind_GetIP (context);
-  uint32_t cr;
-  reg_unit lr = (reg_unit) pc;
-  reg_unit ctr = 0;
-  uint32_t *invalid_address = NULL;
-
-  int i;
-
-  for (i = 0; i < 13; i++)
-    gprs[i] = 1;
-  gprs[1] = _Unwind_GetCFA (context);
-  for (; i < 32; i++)
-    gprs[i] = _Unwind_GetGR (context, i);
-  cr = _Unwind_GetGR (context, R_CR2);
-
-  /* For each supported Libc, we have to track the code flow
-     all the way back into the kernel.
-  
-     This code is believed to support all released Libc/Libsystem builds since
-     Jaguar 6C115, including all the security updates.  To be precise,
-
-     Libc      Libsystem       Build(s)
-     262~1     60~37           6C115
-     262~1     60.2~4          6D52
-     262~1     61~3            6F21-6F22
-     262~1     63~24           6G30-6G37
-     262~1     63~32           6I34-6I35
-     262~1     63~64           6L29-6L60
-     262.4.1~1 63~84           6L123-6R172
-     
-     320~1     71~101          7B85-7D28
-     320~1     71~266          7F54-7F56
-     320~1     71~288          7F112
-     320~1     71~289          7F113
-     320.1.3~1 71.1.1~29       7H60-7H105
-     320.1.3~1 71.1.1~30       7H110-7H113
-     320.1.3~1 71.1.1~31       7H114
-     
-     That's a big table!  It would be insane to try to keep track of
-     every little detail, so we just read the code itself and do what
-     it would do.
-  */
-
-  for (;;)
-    {
-      uint32_t ins = *pc++;
-      
-      if ((ins & 0xFC000003) == 0x48000000)  /* b instruction */
-       {
-         pc += ((((int32_t) ins & 0x3FFFFFC) ^ 0x2000000) - 0x2000004) / 4;
-         continue;
-       }
-      if ((ins & 0xFC600000) == 0x2C000000)  /* cmpwi */
-       {
-         int32_t val1 = (int16_t) ins;
-         int32_t val2 = gprs[ins >> 16 & 0x1F];
-         /* Only beq and bne instructions are supported, so we only
-            need to set the EQ bit.  */
-         uint32_t mask = 0xF << ((ins >> 21 & 0x1C) ^ 0x1C);
-         if (val1 == val2)
-           cr |= mask;
-         else
-           cr &= ~mask;
-         continue;
-       }
-      if ((ins & 0xFEC38003) == 0x40820000)  /* forwards beq/bne */
-       {
-         if ((cr >> ((ins >> 16 & 0x1F) ^ 0x1F) & 1) == (ins >> 24 & 1))
-           pc += (ins & 0x7FFC) / 4 - 1;
-         continue;
-       }
-      if ((ins & 0xFC0007FF) == 0x7C000378) /* or, including mr */
-       {
-         gprs [ins >> 16 & 0x1F] = (gprs [ins >> 11 & 0x1F] 
-                                    | gprs [ins >> 21 & 0x1F]);
-         continue;
-       }
-      if (ins >> 26 == 0x0E)  /* addi, including li */
-       {
-         reg_unit src = (ins >> 16 & 0x1F) == 0 ? 0 : gprs [ins >> 16 & 0x1F];
-         gprs [ins >> 21 & 0x1F] = src + (int16_t) ins;
-         continue;
-       }
-      if (ins >> 26 == 0x0F)  /* addis, including lis */
-       {
-         reg_unit src = (ins >> 16 & 0x1F) == 0 ? 0 : gprs [ins >> 16 & 0x1F];
-         gprs [ins >> 21 & 0x1F] = src + ((int16_t) ins << 16);
-         continue;
-       }
-      if (ins >> 26 == 0x20)  /* lwz */
-       {
-         reg_unit src = (ins >> 16 & 0x1F) == 0 ? 0 : gprs [ins >> 16 & 0x1F];
-         uint32_t *p = (uint32_t *)(src + (int16_t) ins);
-         if (p == invalid_address)
-           return false;
-         gprs [ins >> 21 & 0x1F] = *p;
-         continue;
-       }
-      if (ins >> 26 == 0x21)  /* lwzu */
-       {
-         uint32_t *p = (uint32_t *)(gprs [ins >> 16 & 0x1F] += (int16_t) ins);
-         if (p == invalid_address)
-           return false;
-         gprs [ins >> 21 & 0x1F] = *p;
-         continue;
-       }
-      if (ins >> 26 == 0x24)  /* stw */
-       /* What we hope this is doing is '--in_sigtramp'.  We don't want
-          to actually store to memory, so just make a note of the
-          address and refuse to load from it.  */
-       {
-         reg_unit src = (ins >> 16 & 0x1F) == 0 ? 0 : gprs [ins >> 16 & 0x1F];
-         uint32_t *p = (uint32_t *)(src + (int16_t) ins);
-         if (p == NULL || invalid_address != NULL)
-           return false;
-         invalid_address = p;
-         continue;
-       }
-      if (ins >> 26 == 0x2E) /* lmw */
-       {
-         reg_unit src = (ins >> 16 & 0x1F) == 0 ? 0 : gprs [ins >> 16 & 0x1F];
-         uint32_t *p = (uint32_t *)(src + (int16_t) ins);
-         int i;
-
-         for (i = (ins >> 21 & 0x1F); i < 32; i++)
-           {
-             if (p == invalid_address)
-               return false;
-             gprs[i] = *p++;
-           }
-         continue;
-       }
-      if ((ins & 0xFC1FFFFF) == 0x7c0803a6)  /* mtlr */
-       {
-         lr = gprs [ins >> 21 & 0x1F];
-         continue;
-       }
-      if ((ins & 0xFC1FFFFF) == 0x7c0802a6)  /* mflr */
-       {
-         gprs [ins >> 21 & 0x1F] = lr;
-         continue;
-       }
-      if ((ins & 0xFC1FFFFF) == 0x7c0903a6)  /* mtctr */
-       {
-         ctr = gprs [ins >> 21 & 0x1F];
-         continue;
-       }
-      /* The PowerPC User's Manual says that bit 11 of the mtcrf
-        instruction is reserved and should be set to zero, but it
-        looks like the Darwin assembler doesn't do that... */
-      if ((ins & 0xFC000FFF) == 0x7c000120) /* mtcrf */
-       {
-         int i;
-         uint32_t mask = 0;
-         for (i = 0; i < 8; i++)
-           mask |= ((-(ins >> (12 + i) & 1)) & 0xF) << 4 * i;
-         cr = (cr & ~mask) | (gprs [ins >> 21 & 0x1F] & mask);
-         continue;
-       }
-      if (ins == 0x429f0005)  /* bcl- 20,4*cr7+so,.+4, loads pc into LR */
-       {
-         lr = (reg_unit) pc;
-         continue;
-       }
-      if (ins == 0x4e800420) /* bctr */
-       {
-         pc = (uint32_t *) ctr;
-         continue;
-       }
-      if (ins == 0x44000002) /* sc */
-       return true;
-
-      return false;
-    }
-}
-
-/* We used to include <ucontext.h> and <mach/thread_status.h>,
-   but they change so much between different Darwin system versions
-   that it's much easier to just write the structures involved here
-   directly.  */
-
-/* These defines are from the kernel's bsd/dev/ppc/unix_signal.c.  */
-#define UC_TRAD                 1
-#define UC_TRAD_VEC             6
-#define UC_TRAD64               20
-#define UC_TRAD64_VEC           25
-#define UC_FLAVOR               30
-#define UC_FLAVOR_VEC           35
-#define UC_FLAVOR64             40
-#define UC_FLAVOR64_VEC         45
-#define UC_DUAL                 50
-#define UC_DUAL_VEC             55
-
-struct gcc_ucontext 
-{
-  int onstack;
-  sigset_t sigmask;
-  void * stack_sp;
-  size_t stack_sz;
-  int stack_flags;
-  struct gcc_ucontext *link;
-  size_t mcsize;
-  struct gcc_mcontext32 *mcontext;
-};
-
-struct gcc_float_vector_state 
-{
-  double fpregs[32];
-  uint32_t fpscr_pad;
-  uint32_t fpscr;
-  uint32_t save_vr[32][4];
-  uint32_t save_vscr[4];
-};
-
-struct gcc_mcontext32 {
-  uint32_t dar;
-  uint32_t dsisr;
-  uint32_t exception;
-  uint32_t padding1[5];
-  uint32_t srr0;
-  uint32_t srr1;
-  uint32_t gpr[32];
-  uint32_t cr;
-  uint32_t xer;
-  uint32_t lr;
-  uint32_t ctr;
-  uint32_t mq;
-  uint32_t vrsave;
-  struct gcc_float_vector_state fvs;
-};
-
-/* These are based on /usr/include/ppc/ucontext.h and
-   /usr/include/mach/ppc/thread_status.h, but rewritten to be more
-   convenient, to compile on Jaguar, and to work around Radar 3712064
-   on Panther, which is that the 'es' field of 'struct mcontext64' has
-   the wrong type (doh!).  */
-
-struct gcc_mcontext64 {
-  uint64_t dar;
-  uint32_t dsisr;
-  uint32_t exception;
-  uint32_t padding1[4];
-  uint64_t srr0;
-  uint64_t srr1;
-  uint32_t gpr[32][2];
-  uint32_t cr;
-  uint32_t xer[2];  /* These are arrays because the original structure has them misaligned.  */
-  uint32_t lr[2];
-  uint32_t ctr[2];
-  uint32_t vrsave;
-  struct gcc_float_vector_state fvs;
-};
-
-#define UC_FLAVOR_SIZE \
-  (sizeof (struct gcc_mcontext32) - 33*16)
-
-#define UC_FLAVOR_VEC_SIZE (sizeof (struct gcc_mcontext32))
-
-#define UC_FLAVOR64_SIZE \
-  (sizeof (struct gcc_mcontext64) - 33*16)
-
-#define UC_FLAVOR64_VEC_SIZE (sizeof (struct gcc_mcontext64))
-
-/* Given GPRS as input to a 'sc' instruction, and OLD_CFA, update FS
-   to represent the execution of a signal return; or, if not a signal
-   return, return false.  */
-
-static bool
-handle_syscall (_Unwind_FrameState *fs, const reg_unit gprs[32],
-               _Unwind_Ptr old_cfa)
-{
-  struct gcc_ucontext *uctx;
-  bool is_64, is_vector;
-  struct gcc_float_vector_state * float_vector_state;
-  _Unwind_Ptr new_cfa;
-  int i;
-  static _Unwind_Ptr return_addr;
-  
-  /* Yay!  We're in a Libc that we understand, and it's made a
-     system call.  In Jaguar, this is a direct system call with value 103;
-     in Panther and Tiger it is a SYS_syscall call for system call number 184,
-     and in Leopard it is a direct syscall with number 184.  */
-  
-  if (gprs[0] == 0x67 /* SYS_SIGRETURN */)
-    {
-      uctx = (struct gcc_ucontext *) gprs[3];
-      is_vector = (uctx->mcsize == UC_FLAVOR64_VEC_SIZE
-                  || uctx->mcsize == UC_FLAVOR_VEC_SIZE);
-      is_64 = (uctx->mcsize == UC_FLAVOR64_VEC_SIZE
-              || uctx->mcsize == UC_FLAVOR64_SIZE);
-    }
-  else if (gprs[0] == 0 /* SYS_syscall */ && gprs[3] == 184)
-    {
-      int ctxstyle = gprs[5];
-      uctx = (struct gcc_ucontext *) gprs[4];
-      is_vector = (ctxstyle == UC_FLAVOR_VEC || ctxstyle == UC_FLAVOR64_VEC
-                  || ctxstyle == UC_TRAD_VEC || ctxstyle == UC_TRAD64_VEC);
-      is_64 = (ctxstyle == UC_FLAVOR64_VEC || ctxstyle == UC_TRAD64_VEC
-              || ctxstyle == UC_FLAVOR64 || ctxstyle == UC_TRAD64);
-    }
-  else if (gprs[0] == 184 /* SYS_sigreturn */)
-    {
-      int ctxstyle = gprs[4];
-      uctx = (struct gcc_ucontext *) gprs[3];
-      is_vector = (ctxstyle == UC_FLAVOR_VEC || ctxstyle == UC_FLAVOR64_VEC
-                  || ctxstyle == UC_TRAD_VEC || ctxstyle == UC_TRAD64_VEC);
-      is_64 = (ctxstyle == UC_FLAVOR64_VEC || ctxstyle == UC_TRAD64_VEC
-              || ctxstyle == UC_FLAVOR64 || ctxstyle == UC_TRAD64);
-    }
-  else
-    return false;
-
-#define set_offset(r, addr)                                    \
-  (fs->regs.reg[r].how = REG_SAVED_OFFSET,                     \
-   fs->regs.reg[r].loc.offset = (_Unwind_Ptr)(addr) - new_cfa)
-
-  /* Restore even the registers that are not call-saved, since they
-     might be being used in the prologue to save other registers,
-     for instance GPR0 is sometimes used to save LR.  */
-
-  /* Handle the GPRs, and produce the information needed to do the rest.  */
-  if (is_64)
-    {
-      /* The context is 64-bit, but it doesn't carry any extra information
-        for us because only the low 32 bits of the registers are
-        call-saved.  */
-      struct gcc_mcontext64 *m64 = (struct gcc_mcontext64 *)uctx->mcontext;
-      int i;
-
-      float_vector_state = &m64->fvs;
-
-      new_cfa = m64->gpr[1][1];
-      
-      set_offset (R_CR2, &m64->cr);
-      for (i = 0; i < 32; i++)
-       set_offset (i, m64->gpr[i] + 1);
-      set_offset (R_XER, m64->xer + 1);
-      set_offset (R_LR, m64->lr + 1);
-      set_offset (R_CTR, m64->ctr + 1);
-      if (is_vector)
-       set_offset (R_VRSAVE, &m64->vrsave);
-      
-      /* Sometimes, srr0 points to the instruction that caused the exception,
-        and sometimes to the next instruction to be executed; we want
-        the latter.  */
-      if (m64->exception == 3 || m64->exception == 4
-         || m64->exception == 6
-         || (m64->exception == 7 && !(m64->srr1 & 0x10000)))
-       return_addr = m64->srr0 + 4;
-      else
-       return_addr = m64->srr0;
-    }
-  else
-    {
-      struct gcc_mcontext32 *m = uctx->mcontext;
-      int i;
-
-      float_vector_state = &m->fvs;
-      
-      new_cfa = m->gpr[1];
-
-      set_offset (R_CR2, &m->cr);
-      for (i = 0; i < 32; i++)
-       set_offset (i, m->gpr + i);
-      set_offset (R_XER, &m->xer);
-      set_offset (R_LR, &m->lr);
-      set_offset (R_CTR, &m->ctr);
-
-      if (is_vector)
-       set_offset (R_VRSAVE, &m->vrsave);
-
-      /* Sometimes, srr0 points to the instruction that caused the exception,
-        and sometimes to the next instruction to be executed; we want
-        the latter.  */
-      if (m->exception == 3 || m->exception == 4
-         || m->exception == 6
-         || (m->exception == 7 && !(m->srr1 & 0x10000)))
-       return_addr = m->srr0 + 4;
-      else
-       return_addr = m->srr0;
-    }
-
-  fs->regs.cfa_how = CFA_REG_OFFSET;
-  fs->regs.cfa_reg = STACK_POINTER_REGNUM;
-  fs->regs.cfa_offset = new_cfa - old_cfa;;
-  
-  /* The choice of column for the return address is somewhat tricky.
-     Fortunately, the actual choice is private to this file, and
-     the space it's reserved from is the GCC register space, not the
-     DWARF2 numbering.  So any free element of the right size is an OK
-     choice.  Thus: */
-  fs->retaddr_column = ARG_POINTER_REGNUM;
-  /* FIXME: this should really be done using a DWARF2 location expression,
-     not using a static variable.  In fact, this entire file should
-     be implemented in DWARF2 expressions.  */
-  set_offset (ARG_POINTER_REGNUM, &return_addr);
-
-  for (i = 0; i < 32; i++)
-    set_offset (32 + i, float_vector_state->fpregs + i);
-  set_offset (R_SPEFSCR, &float_vector_state->fpscr);
-  
-  if (is_vector)
-    {
-      for (i = 0; i < 32; i++)
-       set_offset (R_VR0 + i, float_vector_state->save_vr + i);
-      set_offset (R_VSCR, float_vector_state->save_vscr);
-    }
-
-  return true;
-}
-
-/* This is also prototyped in rs6000/darwin.h, inside the
-   MD_FALLBACK_FRAME_STATE_FOR macro.  */
-extern bool _Unwind_fallback_frame_state_for (struct _Unwind_Context *context,
-                                             _Unwind_FrameState *fs);
-
-/* Implement the MD_FALLBACK_FRAME_STATE_FOR macro,
-   returning true iff the frame was a sigreturn() frame that we
-   can understand.  */
-
-bool
-_Unwind_fallback_frame_state_for (struct _Unwind_Context *context,
-                                 _Unwind_FrameState *fs)
-{
-  reg_unit gprs[32];
-
-  if (!interpret_libc (gprs, context))
-    return false;
-  return handle_syscall (fs, gprs, _Unwind_GetCFA (context));
-}
-#endif
index 8113b9ecbcb4f0aab63bc1a3d9dc9f8a35ebb979..27fc07b69b38234213e6c2b68a624b905e0736ef 100644 (file)
@@ -1,5 +1,5 @@
 # Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006,
-# 2007 Free Software Foundation, Inc.
+# 2007, 2011 Free Software Foundation, Inc.
 #
 # This file is part of GCC.
 #
@@ -40,7 +40,5 @@ TARGET_LIBGCC2_CFLAGS = -Wa,-force_cpusubtype_ALL -pipe -mmacosx-version-min=10.
 # Export the _xlq* symbols from darwin-ldouble.c.
 SHLIB_MAPFILES += $(srcdir)/config/rs6000/libgcc-ppc64.ver
 
-LIB2ADDEH += $(srcdir)/config/rs6000/darwin-fallback.c
-
 darwin-fpsave.o:       $(srcdir)/config/rs6000/darwin-asm.h
 darwin-tramp.o:                $(srcdir)/config/rs6000/darwin-asm.h
index a897bfffb47f6571a53c310f530bb32c24bc61f4..27cbd3d3e88d8e2b1b35d9152878dc84defd25f0 100644 (file)
@@ -1,5 +1,5 @@
 # Copyright (C) 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
-# 2003, 2004, 2006, 2008, 2009 Free Software Foundation, Inc.
+# 2003, 2004, 2006, 2008, 2009, 2011 Free Software Foundation, Inc.
 #
 # This file is part of GCC.
 #
@@ -149,7 +149,7 @@ $(T)sdivsi3_i4i-Os-4-200.o: $(srcdir)/config/sh/lib1funcs-Os-4-200.asm $(GCC_PAS
        $(GCC_FOR_TARGET) $(MULTILIB_CFLAGS) -c -o $@ -DL_sdivsi3_i4i -x assembler-with-cpp $<
 $(T)udivsi3_i4i-Os-4-200.o: $(srcdir)/config/sh/lib1funcs-Os-4-200.asm $(GCC_PASSES)
        $(GCC_FOR_TARGET) $(MULTILIB_CFLAGS) -c -o $@ -DL_udivsi3_i4i -x assembler-with-cpp $<
-$(T)unwind-dw2-Os-4-200.o: $(srcdir)/unwind-dw2.c $(srcdir)/unwind-generic.h unwind-pe.h unwind.inc unwind-dw2-fde.h unwind-dw2.h $(CONFIG_H) coretypes.h $(TM_H) $(MACHMODE_H) longlong.h config.status stmp-int-hdrs tsystem.h $(GCC_PASSES)
+$(T)unwind-dw2-Os-4-200.o: $(srcdir)/../libgcc/unwind-dw2.c $(srcdir)/../libgcc/unwind-generic.h $(srcdir)/../libgcc/unwind-pe.h $(srcdir)/../libgcc/unwind.inc $(srcdir)/../libgcc/unwind-dw2-fde.h $(srcdir)/../libgcc/unwind-dw2.h $(CONFIG_H) coretypes.h $(TM_H) $(MACHMODE_H) longlong.h config.status stmp-int-hdrs tsystem.h $(GCC_PASSES)
        $(GCC_FOR_TARGET) $(MULTILIB_CFLAGS) $(LIBGCC2_CFLAGS) $(INCLUDES) $(vis_hide) -fexceptions -Os -c -o $@ $<
 OBJS_Os_4_200=$(T)sdivsi3_i4i-Os-4-200.o $(T)udivsi3_i4i-Os-4-200.o $(T)unwind-dw2-Os-4-200.o
 $(T)libgcc-Os-4-200.a: $(OBJS_Os_4_200) $(GCC_PASSES)
index 5189f28584da3a2bcc1836891ceda916a7d747bd..ab680f5be881621a7ccc98de071043f85df33e32 100644 (file)
@@ -47,9 +47,6 @@ LIB2FUNCS_STATIC_EXTRA = $(srcdir)/config/spu/float_unssidf.c \
                         $(srcdir)/config/spu/divmodti4.c \
                         $(srcdir)/config/spu/divv2df3.c
 
-LIB2ADDEH = $(srcdir)/unwind-dw2.c $(srcdir)/unwind-dw2-fde.c \
-   $(srcdir)/unwind-sjlj.c $(srcdir)/unwind-c.c
-
 # We want fine grained libraries, so use the new code to build the
 # floating point emulation libraries.
 FPBIT = fp-bit.c
index 9e77395998d8f80d7fd42e6e1cfac69057d7222d..d952bd39273e3047589c70b1890437c92a2e3da0 100644 (file)
@@ -42,10 +42,6 @@ darwin-driver.o: $(srcdir)/config/darwin-driver.c \
        $(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \
          $(srcdir)/config/darwin-driver.c
 
-# Use unwind-dw2-fde-darwin
-LIB2ADDEH = $(srcdir)/unwind-dw2.c $(srcdir)/unwind-dw2-fde-darwin.c \
-  $(srcdir)/unwind-sjlj.c $(srcdir)/unwind-c.c
-
 # -pipe because there's an assembler bug, 4077127, which causes
 # it to not properly process the first # directive, causing temporary
 # file names to appear in stabs, causing the bootstrap to fail.  Using -pipe
index af2df24f1054696b7f5f01fd535d0c86b2f764f7..0680618a6ec703efec0d50f05def28eda7ce1458 100644 (file)
@@ -3,7 +3,3 @@ CRTSTUFF_T_CFLAGS_S = $(CRTSTUFF_T_CFLAGS) -fPIC
 
 # Compile libgcc.a with pic.
 TARGET_LIBGCC2_CFLAGS += -fPIC
-
-# Use unwind-dw2-fde-glibc
-LIB2ADDEH = $(srcdir)/unwind-dw2.c $(srcdir)/unwind-dw2-fde-glibc.c \
-  $(srcdir)/unwind-sjlj.c $(srcdir)/unwind-c.c
index 6fdaf676b37b4d1df32b06e7340079169b4f839e..6b8d2dd1292c19a077a0cd2f07535a3a72ad7b08 100644 (file)
@@ -1,4 +1,4 @@
-# Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc.
+# Copyright (C) 2002, 2003, 2004, 2011 Free Software Foundation, Inc.
 #
 # This file is part of GCC.
 #
@@ -22,9 +22,6 @@
 # so that the resulting libgcc_s.so has the necessary DT_NEEDED entry for
 # libunwind.
 SHLIB_LC = -lunwind -lc
-LIB2ADDEH = $(srcdir)/unwind-sjlj.c $(srcdir)/unwind-c.c \
-  $(srcdir)/unwind-compat.c $(srcdir)/unwind-dw2-fde-compat.c
-LIB2ADDEHSTATIC = $(srcdir)/unwind-sjlj.c $(srcdir)/unwind-c.c
 
 T_CFLAGS += -DUSE_LIBUNWIND_EXCEPTIONS
 TARGET_LIBGCC2_CFLAGS += -DUSE_GAS_SYMVER
diff --git a/gcc/config/t-libunwind-elf b/gcc/config/t-libunwind-elf
deleted file mode 100644 (file)
index 5ae0d62..0000000
+++ /dev/null
@@ -1,49 +0,0 @@
-# Copyright (C) 2004, 2005 Free Software Foundation, Inc.
-#
-# This file is part of GCC.
-#
-# GCC 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 3, or (at your option)
-# any later version.
-#
-# GCC 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 GCC; see the file COPYING3.  If not see
-# <http://www.gnu.org/licenses/>.
-
-# Build libunwind for ELF with the GNU linker.
-
-# Use unwind-dw2-fde-glibc
-LIBUNWIND = $(srcdir)/unwind-dw2.c $(srcdir)/unwind-dw2-fde-glibc.c
-LIBUNWINDDEP = unwind.inc unwind-dw2-fde.h unwind-dw2-fde.c
-
-SHLIBUNWIND_SOVERSION = 7
-SHLIBUNWIND_SONAME = @shlib_base_name@.so.$(SHLIBUNWIND_SOVERSION)
-
-SHLIBUNWIND_LINK = $(GCC_FOR_TARGET) $(LIBGCC2_CFLAGS) -shared \
-       -nodefaultlibs -Wl,-h,$(SHLIBUNWIND_SONAME) \
-       -Wl,-z,text -Wl,-z,defs -o $(SHLIB_DIR)/$(SHLIBUNWIND_SONAME).tmp \
-       @multilib_flags@ $(SHLIB_OBJS) -lc && \
-       rm -f $(SHLIB_DIR)/$(SHLIB_SOLINK) && \
-       if [ -f $(SHLIB_DIR)/$(SHLIBUNWIND_SONAME) ]; then \
-         mv -f $(SHLIB_DIR)/$(SHLIBUNWIND_SONAME) \
-               $(SHLIB_DIR)/$(SHLIBUNWIND_SONAME).backup; \
-       else true; fi && \
-       mv $(SHLIB_DIR)/$(SHLIBUNWIND_SONAME).tmp \
-          $(SHLIB_DIR)/$(SHLIBUNWIND_SONAME) && \
-       $(LN_S) $(SHLIBUNWIND_SONAME) $(SHLIB_DIR)/$(SHLIB_SOLINK)
-
-# $(slibdir) double quoted to protect it from expansion while building
-# libgcc.mk.  We want this delayed until actual install time.
-SHLIBUNWIND_INSTALL = \
-       $$(SHELL) $$(srcdir)/mkinstalldirs $$(DESTDIR)$$(slibdir)$(SHLIB_SLIBDIR_QUAL); \
-       $(INSTALL_DATA) $(SHLIB_DIR)/$(SHLIBUNWIND_SONAME) \
-         $$(DESTDIR)$$(slibdir)$(SHLIB_SLIBDIR_QUAL)/$(SHLIBUNWIND_SONAME); \
-       rm -f $$(DESTDIR)$$(slibdir)$(SHLIB_SLIBDIR_QUAL)/$(SHLIB_SOLINK); \
-       $(LN_S) $(SHLIBUNWIND_SONAME) \
-         $$(DESTDIR)$$(slibdir)$(SHLIB_SLIBDIR_QUAL)/$(SHLIB_SOLINK)
index 039fa27ae82fbdd080b292b328b7ab846f915a74..64d19ca8dd77ff1c0b62a8d2da18396de2668a71 100644 (file)
@@ -25,7 +25,3 @@ TARGET_LIBGCC2_CFLAGS = -fPIC
 # Override t-slibgcc-elf-ver to export some libgcc symbols with
 # the symbol versions that glibc used.
 SHLIB_MAPFILES += $(srcdir)/config/libgcc-glibc.ver
-
-# Use unwind-dw2-fde-glibc
-LIB2ADDEH = $(srcdir)/unwind-dw2.c $(srcdir)/unwind-dw2-fde-glibc.c \
-  $(srcdir)/unwind-sjlj.c $(srcdir)/unwind-c.c
index 73fd8eb3667d97e249e223a879d17749f8576945..f53da4d3ca6617d8c42feff142a58efc9068e76f 100644 (file)
@@ -31,8 +31,3 @@ sol2.o: $(srcdir)/config/sol2.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
 
 # This is required by gcc/ada/gcc-interface/Makefile.in.
 TARGET_LIBGCC2_CFLAGS = -fPIC
-
-# Use unwind-dw2-fde-glibc.c.  Unless linker support and dl_iterate_phdr
-# are present, automatically falls back to unwind-dw2-fde.c.
-LIB2ADDEH = $(srcdir)/unwind-dw2.c $(srcdir)/unwind-dw2-fde-glibc.c \
-  $(srcdir)/unwind-sjlj.c $(srcdir)/unwind-c.c
index c3d98ae30b5a4c17ac1cacc7d1574361555e7f97..641e6fe76201e011cdceaf87b8eba58951068c1d 100644 (file)
@@ -1,4 +1,5 @@
-# Copyright (C) 2002, 2003, 2006, 2007, 2008 Free Software Foundation, Inc.
+# Copyright (C) 2002, 2003, 2006, 2007, 2008, 2011
+# Free Software Foundation, Inc.
 #
 # This file is part of GCC.
 #
@@ -29,8 +30,6 @@ LIB1ASMFUNCS = _mulsi3 _divsi3 _modsi3 _udivsi3 _umodsi3 \
        _truncdfsf2 _extendsfdf2
 
 LIB2FUNCS_EXTRA = $(srcdir)/config/xtensa/lib2funcs.S
-LIB2ADDEH = $(srcdir)/config/xtensa/unwind-dw2-xtensa.c \
-   $(srcdir)/unwind-dw2-fde.c $(srcdir)/unwind-sjlj.c $(srcdir)/unwind-c.c
 
 $(T)crti.o: $(srcdir)/config/xtensa/crti.asm $(GCC_PASSES)
        $(GCC_FOR_TARGET) $(GCC_CFLAGS) $(MULTILIB_CFLAGS) $(INCLUDES) \
diff --git a/gcc/config/xtensa/unwind-dw2-xtensa.c b/gcc/config/xtensa/unwind-dw2-xtensa.c
deleted file mode 100644 (file)
index 54daf76..0000000
+++ /dev/null
@@ -1,544 +0,0 @@
-/* DWARF2 exception handling and frame unwinding for Xtensa.
-   Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006,
-   2007, 2008, 2009, 2011
-   Free Software Foundation, Inc.
-
-   This file is part of GCC.
-
-   GCC 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 3, or (at your option)
-   any later version.
-
-   GCC 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.
-
-   Under Section 7 of GPL version 3, you are granted additional
-   permissions described in the GCC Runtime Library Exception, version
-   3.1, as published by the Free Software Foundation.
-
-   You should have received a copy of the GNU General Public License and
-   a copy of the GCC Runtime Library Exception along with this program;
-   see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
-   <http://www.gnu.org/licenses/>.  */
-
-#include "tconfig.h"
-#include "tsystem.h"
-#include "coretypes.h"
-#include "tm.h"
-#include "dwarf2.h"
-#include "unwind.h"
-#ifdef __USING_SJLJ_EXCEPTIONS__
-# define NO_SIZE_OF_ENCODED_VALUE
-#endif
-#include "unwind-pe.h"
-#include "unwind-dw2-fde.h"
-#include "unwind-dw2-xtensa.h"
-
-#ifndef __USING_SJLJ_EXCEPTIONS__
-
-/* The standard CIE and FDE structures work fine for Xtensa but the
-   variable-size register window save areas are not a good fit for the rest
-   of the standard DWARF unwinding mechanism.  Nor is that mechanism
-   necessary, since the register save areas are always in fixed locations
-   in each stack frame.  This file is a stripped down and customized version
-   of the standard DWARF unwinding code.  It needs to be customized to have
-   builtin logic for finding the save areas and also to track the stack
-   pointer value (besides the CFA) while unwinding since the primary save
-   area is located below the stack pointer.  It is stripped down to reduce
-   code size and ease the maintenance burden of tracking changes in the
-   standard version of the code.  */
-
-#ifndef DWARF_REG_TO_UNWIND_COLUMN
-#define DWARF_REG_TO_UNWIND_COLUMN(REGNO) (REGNO)
-#endif
-
-#define XTENSA_RA_FIELD_MASK 0x3FFFFFFF
-
-/* This is the register and unwind state for a particular frame.  This
-   provides the information necessary to unwind up past a frame and return
-   to its caller.  */
-struct _Unwind_Context
-{
-  /* Track register window save areas of 4 registers each, instead of
-     keeping separate addresses for the individual registers.  */
-  _Unwind_Word *reg[4];
-
-  void *cfa;
-  void *sp;
-  void *ra;
-
-  /* Cache the 2 high bits to replace the window size in return addresses.  */
-  _Unwind_Word ra_high_bits;
-
-  void *lsda;
-  struct dwarf_eh_bases bases;
-  /* Signal frame context.  */
-#define SIGNAL_FRAME_BIT ((~(_Unwind_Word) 0 >> 1) + 1)
-  _Unwind_Word flags;
-  /* 0 for now, can be increased when further fields are added to
-     struct _Unwind_Context.  */
-  _Unwind_Word version;
-};
-
-\f
-/* Read unaligned data from the instruction buffer.  */
-
-union unaligned
-{
-  void *p;
-} __attribute__ ((packed));
-
-static void uw_update_context (struct _Unwind_Context *, _Unwind_FrameState *);
-static _Unwind_Reason_Code uw_frame_state_for (struct _Unwind_Context *,
-                                              _Unwind_FrameState *);
-
-static inline void *
-read_pointer (const void *p) { const union unaligned *up = p; return up->p; }
-\f
-static inline _Unwind_Word
-_Unwind_IsSignalFrame (struct _Unwind_Context *context)
-{
-  return (context->flags & SIGNAL_FRAME_BIT) ? 1 : 0;
-}
-
-static inline void
-_Unwind_SetSignalFrame (struct _Unwind_Context *context, int val)
-{
-  if (val)
-    context->flags |= SIGNAL_FRAME_BIT;
-  else
-    context->flags &= ~SIGNAL_FRAME_BIT;
-}
-\f
-/* Get the value of register INDEX as saved in CONTEXT.  */
-
-inline _Unwind_Word
-_Unwind_GetGR (struct _Unwind_Context *context, int index)
-{
-  _Unwind_Word *ptr;
-
-  index = DWARF_REG_TO_UNWIND_COLUMN (index);
-  ptr = context->reg[index >> 2] + (index & 3);
-
-  return *ptr;
-}
-
-/* Get the value of the CFA as saved in CONTEXT.  */
-
-_Unwind_Word
-_Unwind_GetCFA (struct _Unwind_Context *context)
-{
-  return (_Unwind_Ptr) context->cfa;
-}
-
-/* Overwrite the saved value for register INDEX in CONTEXT with VAL.  */
-
-inline void
-_Unwind_SetGR (struct _Unwind_Context *context, int index, _Unwind_Word val)
-{
-  _Unwind_Word *ptr;
-
-  index = DWARF_REG_TO_UNWIND_COLUMN (index);
-  ptr = context->reg[index >> 2] + (index & 3);
-
-  *ptr = val;
-}
-
-/* Retrieve the return address for CONTEXT.  */
-
-inline _Unwind_Ptr
-_Unwind_GetIP (struct _Unwind_Context *context)
-{
-  return (_Unwind_Ptr) context->ra;
-}
-
-/* Retrieve the return address and flag whether that IP is before
-   or after first not yet fully executed instruction.  */
-
-inline _Unwind_Ptr
-_Unwind_GetIPInfo (struct _Unwind_Context *context, int *ip_before_insn)
-{
-  *ip_before_insn = _Unwind_IsSignalFrame (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;
-}
-
-void *
-_Unwind_FindEnclosingFunction (void *pc)
-{
-  struct dwarf_eh_bases bases;
-  const struct dwarf_fde *fde = _Unwind_Find_FDE (pc-1, &bases);
-  if (fde)
-    return bases.func;
-  else
-    return NULL;
-}
-
-_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;
-}
-
-#include "md-unwind-support.h"
-\f
-/* 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 (const struct dwarf_cie *cie, struct _Unwind_Context *context,
-                 _Unwind_FrameState *fs)
-{
-  const unsigned char *aug = cie->augmentation;
-  const unsigned char *p = aug + strlen ((const char *)aug) + 1;
-  const unsigned char *ret = NULL;
-  _uleb128_t utmp;
-  _sleb128_t stmp;
-
-  /* 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, &utmp);
-  p = read_sleb128 (p, &stmp);
-  if (cie->version == 1)
-    fs->retaddr_column = *p++;
-  else
-    {
-      p = read_uleb128 (p, &utmp);
-      fs->retaddr_column = (_Unwind_Word)utmp;
-    }
-  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, &utmp);
-      ret = p + utmp;
-
-      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')
-       {
-         _Unwind_Ptr personality;
-         
-         p = read_encoded_value (context, *p, p + 1, &personality);
-         fs->personality = (_Unwind_Personality_Fn) personality;
-         aug += 1;
-       }
-
-      /* "S" indicates a signal frame.  */
-      else if (aug[0] == 'S')
-       {
-         fs->signal_frame = 1;
-         aug += 1;
-       }
-
-      /* Otherwise we have an unknown augmentation string.
-        Bail unless we saw a 'z' prefix.  */
-      else
-       return ret;
-    }
-
-  return ret ? ret : p;
-}
-\f
-/* Given the _Unwind_Context CONTEXT for a stack frame, look up the FDE for
-   its caller and decode it into FS.  This function also sets the
-   lsda member of CONTEXT, as it is really information
-   about the caller's frame.  */
-
-static _Unwind_Reason_Code
-uw_frame_state_for (struct _Unwind_Context *context, _Unwind_FrameState *fs)
-{
-  const struct dwarf_fde *fde;
-  const struct dwarf_cie *cie;
-  const unsigned char *aug;
-  int window_size;
-  _Unwind_Word *ra_ptr;
-
-  memset (fs, 0, sizeof (*fs));
-  context->lsda = 0;
-
-  fde = _Unwind_Find_FDE (context->ra + _Unwind_IsSignalFrame (context) - 1,
-                         &context->bases);
-  if (fde == NULL)
-    {
-#ifdef MD_FALLBACK_FRAME_STATE_FOR
-      _Unwind_Reason_Code reason;
-      /* Couldn't find frame unwind info for this function.  Try a
-        target-specific fallback mechanism.  This will necessarily
-        not provide a personality routine or LSDA.  */
-      reason = MD_FALLBACK_FRAME_STATE_FOR (context, fs);
-      if (reason != _URC_END_OF_STACK)
-       return reason;
-#endif
-      /* The frame was not recognized and handled by the fallback function,
-        but it is not really the end of the stack.  Fall through here and
-        unwind it anyway.  */
-    }
-  else
-    {
-      cie = get_cie (fde);
-      if (extract_cie_info (cie, context, fs) == NULL)
-       /* CIE contained unknown augmentation.  */
-       return _URC_FATAL_PHASE1_ERROR;
-
-      /* Locate augmentation for the fde.  */
-      aug = (const unsigned char *) fde + sizeof (*fde);
-      aug += 2 * size_of_encoded_value (fs->fde_encoding);
-      if (fs->saw_z)
-       {
-         _uleb128_t i;
-         aug = read_uleb128 (aug, &i);
-       }
-      if (fs->lsda_encoding != DW_EH_PE_omit)
-       {
-         _Unwind_Ptr lsda;
-
-         aug = read_encoded_value (context, fs->lsda_encoding, aug, &lsda);
-         context->lsda = (void *) lsda;
-       }
-    }
-
-  /* Check for the end of the stack.  This needs to be checked after
-     the MD_FALLBACK_FRAME_STATE_FOR check for signal frames because
-     the contents of context->reg[0] are undefined at a signal frame,
-     and register a0 may appear to be zero.  (The return address in
-     context->ra comes from register a4 or a8).  */
-  ra_ptr = context->reg[0];
-  if (ra_ptr && *ra_ptr == 0)
-    return _URC_END_OF_STACK;
-
-  /* Find the window size from the high bits of the return address.  */
-  if (ra_ptr)
-    window_size = (*ra_ptr >> 30) * 4;
-  else
-    window_size = 8;
-
-  fs->retaddr_column = window_size;
-
-  return _URC_NO_REASON;
-}
-\f
-static void
-uw_update_context_1 (struct _Unwind_Context *context, _Unwind_FrameState *fs)
-{
-  struct _Unwind_Context orig_context = *context;
-  _Unwind_Word *sp, *cfa, *next_cfa;
-  int i;
-
-  if (fs->signal_regs)
-    {
-      cfa = (_Unwind_Word *) fs->signal_regs[1];
-      next_cfa = (_Unwind_Word *) cfa[-3];
-
-      for (i = 0; i < 4; i++)
-       context->reg[i] = fs->signal_regs + (i << 2);
-    }
-  else
-    {
-      int window_size = fs->retaddr_column >> 2;
-
-      sp = (_Unwind_Word *) orig_context.sp;
-      cfa = (_Unwind_Word *) orig_context.cfa;
-      next_cfa = (_Unwind_Word *) cfa[-3];
-
-      /* Registers a0-a3 are in the save area below sp.  */
-      context->reg[0] = sp - 4;
-
-      /* Find the extra save area below next_cfa.  */
-      for (i = 1; i < window_size; i++)
-       context->reg[i] = next_cfa - 4 * (1 + window_size - i);
-
-      /* Remaining registers rotate from previous save areas.  */
-      for (i = window_size; i < 4; i++)
-       context->reg[i] = orig_context.reg[i - window_size];
-    }
-
-  context->sp = cfa;
-  context->cfa = next_cfa;
-
-  _Unwind_SetSignalFrame (context, fs->signal_frame);
-}
-
-/* CONTEXT describes the unwind state for a frame, and FS describes the FDE
-   of its caller.  Update CONTEXT to refer to the caller as well.  Note
-   that the lsda member is not updated here, but later in
-   uw_frame_state_for.  */
-
-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.  */
-  if (fs->signal_ra != 0)
-    context->ra = (void *) fs->signal_ra;
-  else
-    context->ra = (void *) ((_Unwind_GetGR (context, fs->retaddr_column)
-                            & XTENSA_RA_FIELD_MASK) | context->ra_high_bits);
-}
-
-static void
-uw_advance_context (struct _Unwind_Context *context, _Unwind_FrameState *fs)
-{
-  uw_update_context (context, fs);
-}
-\f
-/* 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                                                                      \
-    {                                                                     \
-      __builtin_unwind_init ();                                                   \
-      uw_init_context_1 (CONTEXT, __builtin_dwarf_cfa (),                 \
-                        __builtin_return_address (0));                    \
-    }                                                                     \
-  while (0)
-
-static void __attribute__((noinline))
-uw_init_context_1 (struct _Unwind_Context *context, void *outer_cfa,
-                  void *outer_ra)
-{
-  void *ra = __builtin_return_address (0);
-  void *cfa = __builtin_dwarf_cfa ();
-  _Unwind_FrameState fs;
-
-  memset (context, 0, sizeof (struct _Unwind_Context));
-  context->ra = ra;
-
-  memset (&fs, 0, sizeof (fs));
-  fs.retaddr_column = 8;
-  context->sp = cfa;
-  context->cfa = outer_cfa;
-  context->ra_high_bits =
-    ((_Unwind_Word) uw_init_context_1) & ~XTENSA_RA_FIELD_MASK;
-  uw_update_context_1 (context, &fs);
-
-  context->ra = 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 long
-uw_install_context_1 (struct _Unwind_Context *current,
-                     struct _Unwind_Context *target)
-{
-  long i;
-
-  /* The eh_return insn assumes a window size of 8, so don't bother copying
-     the save areas for registers a8-a15 since they won't be reloaded.  */
-  for (i = 0; i < 2; ++i)
-    {
-      void *c = current->reg[i];
-      void *t = target->reg[i];
-
-      if (t && c && t != c)
-       memcpy (c, t, 4 * sizeof (_Unwind_Word));
-    }
-
-  return 0;
-}
-
-static inline _Unwind_Ptr
-uw_identify_context (struct _Unwind_Context *context)
-{
-  return _Unwind_GetCFA (context);
-}
-
-
-#include "unwind.inc"
-
-#if defined (USE_GAS_SYMVER) && defined (SHARED) && defined (USE_LIBUNWIND_EXCEPTIONS)
-alias (_Unwind_Backtrace);
-alias (_Unwind_DeleteException);
-alias (_Unwind_FindEnclosingFunction);
-alias (_Unwind_ForcedUnwind);
-alias (_Unwind_GetDataRelBase);
-alias (_Unwind_GetTextRelBase);
-alias (_Unwind_GetCFA);
-alias (_Unwind_GetGR);
-alias (_Unwind_GetIP);
-alias (_Unwind_GetLanguageSpecificData);
-alias (_Unwind_GetRegionStart);
-alias (_Unwind_RaiseException);
-alias (_Unwind_Resume);
-alias (_Unwind_Resume_or_Rethrow);
-alias (_Unwind_SetGR);
-alias (_Unwind_SetIP);
-#endif
-
-#endif /* !USING_SJLJ_EXCEPTIONS */
diff --git a/gcc/config/xtensa/unwind-dw2-xtensa.h b/gcc/config/xtensa/unwind-dw2-xtensa.h
deleted file mode 100644 (file)
index d13b326..0000000
+++ /dev/null
@@ -1,50 +0,0 @@
-/* DWARF2 frame unwind data structure for Xtensa.
-   Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2007, 2008,
-   2009  Free Software Foundation, Inc.
-
-   This file is part of GCC.
-
-   GCC 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 3, or (at your option)
-   any later version.
-
-   GCC 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.
-
-   Under Section 7 of GPL version 3, you are granted additional
-   permissions described in the GCC Runtime Library Exception, version
-   3.1, as published by the Free Software Foundation.
-
-   You should have received a copy of the GNU General Public License and
-   a copy of the GCC Runtime Library Exception along with this program;
-   see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
-   <http://www.gnu.org/licenses/>.  */
-
-/* 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
-
-/* Xtensa's variable-size register window save areas can be unwound without
-   any unwind info.  This is a stripped down version of the standard DWARF
-   _Unwind_FrameState.  */
-typedef struct
-{
-  /* The information we care about from the CIE/FDE.  */
-  _Unwind_Personality_Fn personality;
-  _Unwind_Word retaddr_column;
-  unsigned char fde_encoding;
-  unsigned char lsda_encoding;
-  unsigned char saw_z;
-  unsigned char signal_frame;
-  void *eh_ptr;
-
-  /* Saved registers for a signal frame.  */
-  _Unwind_Word *signal_regs;
-  _Unwind_Word signal_ra;
-} _Unwind_FrameState;
-
index 63e44c5e43df3ddfa5cbeca93c3c13ac1f670d8a..88bb116dc1f8ec7d68dbe918ea46eaaded4c6f46 100755 (executable)
@@ -894,7 +894,6 @@ enable_rpath
 with_libiconv_prefix
 enable_initfini_array
 enable_sjlj_exceptions
-with_system_libunwind
 enable_secureplt
 enable_leading_mingw64_underscores
 enable_cld
@@ -1659,7 +1658,6 @@ Optional Packages:
   --with-gnu-ld           assume the C compiler uses GNU ld default=no
   --with-libiconv-prefix[=DIR]  search for libiconv in DIR/include and DIR/lib
   --without-libiconv-prefix     don't search for libiconv in includedir and libdir
-  --with-system-libunwind use installed libunwind
   --with-pic              try to use only PIC/non-PIC objects [default=use
                           both]
   --with-gnu-ld           assume the C compiler uses GNU ld [default=no]
@@ -10855,46 +10853,6 @@ _ACEOF
 
 fi
 
-# For platforms with the unwind ABI which includes an unwind library,
-# libunwind, we can choose to use the system libunwind.
-# config.gcc also contains tests of with_system_libunwind.
-
-
-# Check whether --with-system-libunwind was given.
-if test "${with_system_libunwind+set}" = set; then :
-  withval=$with_system_libunwind;
-fi
-
-  # If system-libunwind was not specifically set, pick a default setting.
-  if test x$with_system_libunwind = x; then
-    case ${target} in
-      ia64-*-hpux*) with_system_libunwind=yes ;;
-      *) with_system_libunwind=no ;;
-    esac
-  fi
-  # Based on system-libunwind and target, do we have ipinfo?
-  if  test x$with_system_libunwind = xyes; then
-    case ${target} in
-      ia64-*-*) have_unwind_getipinfo=no ;;
-      *) have_unwind_getipinfo=yes ;;
-    esac
-  else
-    # Darwin before version 9 does not have _Unwind_GetIPInfo.
-
-    case ${target} in
-      *-*-darwin[3-8]|*-*-darwin[3-8].*) have_unwind_getipinfo=no ;;
-      *) have_unwind_getipinfo=yes ;;
-    esac
-
-  fi
-
-  if test x$have_unwind_getipinfo = xyes; then
-
-$as_echo "#define HAVE_GETIPINFO 1" >>confdefs.h
-
-  fi
-
-
 # --------------------------------------------------------
 # Build, host, and target specific configuration fragments
 # --------------------------------------------------------
@@ -17805,7 +17763,7 @@ else
   lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
   lt_status=$lt_dlunknown
   cat > conftest.$ac_ext <<_LT_EOF
-#line 17808 "configure"
+#line 17766 "configure"
 #include "confdefs.h"
 
 #if HAVE_DLFCN_H
@@ -17911,7 +17869,7 @@ else
   lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
   lt_status=$lt_dlunknown
   cat > conftest.$ac_ext <<_LT_EOF
-#line 17914 "configure"
+#line 17872 "configure"
 #include "confdefs.h"
 
 #if HAVE_DLFCN_H
index c71281cbeb2e28b774bcae2c41156cca78fc4e06..81345d6f32876f7733d9249654c127a0c05ceb3f 100644 (file)
@@ -1184,11 +1184,6 @@ if test $force_sjlj_exceptions = yes; then
     [Define 0/1 to force the choice for exception handling model.])
 fi
 
-# For platforms with the unwind ABI which includes an unwind library,
-# libunwind, we can choose to use the system libunwind.
-# config.gcc also contains tests of with_system_libunwind.
-GCC_CHECK_UNWIND_GETIPINFO
-
 # --------------------------------------------------------
 # Build, host, and target specific configuration fragments
 # --------------------------------------------------------
diff --git a/gcc/emutls.c b/gcc/emutls.c
deleted file mode 100644 (file)
index b7ee3bd..0000000
+++ /dev/null
@@ -1,202 +0,0 @@
-/* TLS emulation.
-   Copyright (C) 2006, 2008, 2009 Free Software Foundation, Inc.
-   Contributed by Jakub Jelinek <jakub@redhat.com>.
-
-This file is part of GCC.
-
-GCC 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 3, or (at your option) any later
-version.
-
-GCC 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.
-
-Under Section 7 of GPL version 3, you are granted additional
-permissions described in the GCC Runtime Library Exception, version
-3.1, as published by the Free Software Foundation.
-
-You should have received a copy of the GNU General Public License and
-a copy of the GCC Runtime Library Exception along with this program;
-see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
-<http://www.gnu.org/licenses/>.  */
-
-#include "tconfig.h"
-#include "tsystem.h"
-#include "coretypes.h"
-#include "tm.h"
-#include "gthr.h"
-
-typedef unsigned int word __attribute__((mode(word)));
-typedef unsigned int pointer __attribute__((mode(pointer)));
-
-struct __emutls_object
-{
-  word size;
-  word align;
-  union {
-    pointer offset;
-    void *ptr;
-  } loc;
-  void *templ;
-};
-
-struct __emutls_array
-{
-  pointer size;
-  void **data[];
-};
-
-void *__emutls_get_address (struct __emutls_object *);
-void __emutls_register_common (struct __emutls_object *, word, word, void *);
-
-#ifdef __GTHREADS
-#ifdef __GTHREAD_MUTEX_INIT
-static __gthread_mutex_t emutls_mutex = __GTHREAD_MUTEX_INIT;
-#else
-static __gthread_mutex_t emutls_mutex;
-#endif
-static __gthread_key_t emutls_key;
-static pointer emutls_size;
-
-static void
-emutls_destroy (void *ptr)
-{
-  struct __emutls_array *arr = ptr;
-  pointer size = arr->size;
-  pointer i;
-
-  for (i = 0; i < size; ++i)
-    {
-      if (arr->data[i])
-       free (arr->data[i][-1]);
-    }
-
-  free (ptr);
-}
-
-static void
-emutls_init (void)
-{
-#ifndef __GTHREAD_MUTEX_INIT
-  __GTHREAD_MUTEX_INIT_FUNCTION (&emutls_mutex);
-#endif
-  if (__gthread_key_create (&emutls_key, emutls_destroy) != 0)
-    abort ();
-}
-#endif
-
-static void *
-emutls_alloc (struct __emutls_object *obj)
-{
-  void *ptr;
-  void *ret;
-
-  /* We could use here posix_memalign if available and adjust
-     emutls_destroy accordingly.  */
-  if (obj->align <= sizeof (void *))
-    {
-      ptr = malloc (obj->size + sizeof (void *));
-      if (ptr == NULL)
-       abort ();
-      ((void **) ptr)[0] = ptr;
-      ret = ptr + sizeof (void *);
-    }
-  else
-    {
-      ptr = malloc (obj->size + sizeof (void *) + obj->align - 1);
-      if (ptr == NULL)
-       abort ();
-      ret = (void *) (((pointer) (ptr + sizeof (void *) + obj->align - 1))
-                     & ~(pointer)(obj->align - 1));
-      ((void **) ret)[-1] = ptr;
-    }
-
-  if (obj->templ)
-    memcpy (ret, obj->templ, obj->size);
-  else
-    memset (ret, 0, obj->size);
-
-  return ret;
-}
-
-void *
-__emutls_get_address (struct __emutls_object *obj)
-{
-  if (! __gthread_active_p ())
-    {
-      if (__builtin_expect (obj->loc.ptr == NULL, 0))
-       obj->loc.ptr = emutls_alloc (obj);
-      return obj->loc.ptr;
-    }
-
-#ifndef __GTHREADS
-  abort ();
-#else
-  pointer offset = obj->loc.offset;
-
-  if (__builtin_expect (offset == 0, 0))
-    {
-      static __gthread_once_t once = __GTHREAD_ONCE_INIT;
-      __gthread_once (&once, emutls_init);
-      __gthread_mutex_lock (&emutls_mutex);
-      offset = obj->loc.offset;
-      if (offset == 0)
-       {
-         offset = ++emutls_size;
-         obj->loc.offset = offset;
-       }
-      __gthread_mutex_unlock (&emutls_mutex);
-    }
-
-  struct __emutls_array *arr = __gthread_getspecific (emutls_key);
-  if (__builtin_expect (arr == NULL, 0))
-    {
-      pointer size = offset + 32;
-      arr = calloc (size + 1, sizeof (void *));
-      if (arr == NULL)
-       abort ();
-      arr->size = size;
-      __gthread_setspecific (emutls_key, (void *) arr);
-    }
-  else if (__builtin_expect (offset > arr->size, 0))
-    {
-      pointer orig_size = arr->size;
-      pointer size = orig_size * 2;
-      if (offset > size)
-       size = offset + 32;
-      arr = realloc (arr, (size + 1) * sizeof (void *));
-      if (arr == NULL)
-       abort ();
-      arr->size = size;
-      memset (arr->data + orig_size, 0,
-             (size - orig_size) * sizeof (void *));
-      __gthread_setspecific (emutls_key, (void *) arr);
-    }
-
-  void *ret = arr->data[offset - 1];
-  if (__builtin_expect (ret == NULL, 0))
-    {
-      ret = emutls_alloc (obj);
-      arr->data[offset - 1] = ret;
-    }
-  return ret;
-#endif
-}
-
-void
-__emutls_register_common (struct __emutls_object *obj,
-                         word size, word align, void *templ)
-{
-  if (obj->size < size)
-    {
-      obj->size = size;
-      obj->templ = NULL;
-    }
-  if (obj->align < align)
-    obj->align = align;
-  if (templ && size == obj->size)
-    obj->templ = templ;
-}
index 1123a00424d7fee7c1fbced210ac0a2e9e84fe0e..610ca9ba7d0581365ac9be9933ba4f2edc97750e 100644 (file)
@@ -1,3 +1,9 @@
+2011-08-05  Rainer Orth  <ro@CeBiTec.Uni-Bielefeld.DE>
+
+       * EXCLUDES (unwind-c.c, unwind-dw2-fde-darwin.c)
+       (unwind-dw2-fde-glibc.c, unwind-dw2-fde.c, unwind-dw2-fde.h)
+       (unwind-dw2.c, unwind-pe.h, unwind-sjlj.c, unwind.h): Remove.
+
 2011-07-31  Joseph Myers  <joseph@codesourcery.com>
 
        * de.po: Update.
index cc29a2bd1ac7d0de397a7d6447d6885445ab5f7a..12fced15f72f7dcb092cdd30e9856056a17492d0 100644 (file)
@@ -44,15 +44,6 @@ libgcc2.h
 limitx.h
 limity.h
 longlong.h
-unwind-c.c
-unwind-dw2-fde-darwin.c
-unwind-dw2-fde-glibc.c
-unwind-dw2-fde.c
-unwind-dw2-fde.h
-unwind-dw2.c
-unwind-pe.h
-unwind-sjlj.c
-unwind.h
 
 #   These programs are meant to be executed only by GCC maintainers or
 #   installers.  Such files do not need to be translated, as these
index 7ac98596bc750c53bf51126327708ef32d5be704..a7db6f58f851bad9cc8356540e805a7b803aac5e 100644 (file)
@@ -802,7 +802,7 @@ extern void fancy_abort (const char *, int, const char *) ATTRIBUTE_NORETURN;
 /* Target macros only used for code built for the target, that have
    moved to libgcc-tm.h or have never been present elsewhere.  */
  #pragma GCC poison DECLARE_LIBRARY_RENAMES LIBGCC2_GNU_PREFIX         \
-       MD_UNWIND_SUPPORT ENABLE_EXECUTE_STACK
+       MD_UNWIND_SUPPORT MD_FROB_UPDATE_CONTEXT ENABLE_EXECUTE_STACK
 
 /* Other obsolete target macros, or macros that used to be in target
    headers and were not used, and may be obsolete or may never have
diff --git a/gcc/unwind-c.c b/gcc/unwind-c.c
deleted file mode 100644 (file)
index 86b9f55..0000000
+++ /dev/null
@@ -1,229 +0,0 @@
-/* Supporting functions for C exception handling.
-   Copyright (C) 2002, 2003, 2009 Free Software Foundation, Inc.
-   Contributed by Aldy Hernandez <aldy@quesejoda.com>.
-   Shamelessly stolen from the Java front end.
-
-This file is part of GCC.
-
-GCC 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 3, or (at your option) any later
-version.
-
-GCC 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.
-
-Under Section 7 of GPL version 3, you are granted additional
-permissions described in the GCC Runtime Library Exception, version
-3.1, as published by the Free Software Foundation.
-
-You should have received a copy of the GNU General Public License and
-a copy of the GCC Runtime Library Exception along with this program;
-see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
-<http://www.gnu.org/licenses/>.  */
-
-#include "tconfig.h"
-#include "tsystem.h"
-#include "unwind.h"
-#define NO_SIZE_OF_ENCODED_VALUE
-#include "unwind-pe.h"
-
-typedef struct
-{
-  _Unwind_Ptr Start;
-  _Unwind_Ptr LPStart;
-  _Unwind_Ptr ttype_base;
-  const unsigned char *TType;
-  const unsigned char *action_table;
-  unsigned char ttype_encoding;
-  unsigned char call_site_encoding;
-} lsda_header_info;
-
-static const unsigned char *
-parse_lsda_header (struct _Unwind_Context *context, const unsigned char *p,
-                  lsda_header_info *info)
-{
-  _uleb128_t tmp;
-  unsigned char lpstart_encoding;
-
-  info->Start = (context ? _Unwind_GetRegionStart (context) : 0);
-
-  /* Find @LPStart, the base to which landing pad offsets are relative.  */
-  lpstart_encoding = *p++;
-  if (lpstart_encoding != DW_EH_PE_omit)
-    p = read_encoded_value (context, lpstart_encoding, p, &info->LPStart);
-  else
-    info->LPStart = info->Start;
-
-  /* Find @TType, the base of the handler and exception spec type data.  */
-  info->ttype_encoding = *p++;
-  if (info->ttype_encoding != DW_EH_PE_omit)
-    {
-      p = read_uleb128 (p, &tmp);
-      info->TType = p + tmp;
-    }
-  else
-    info->TType = 0;
-
-  /* The encoding and length of the call-site table; the action table
-     immediately follows.  */
-  info->call_site_encoding = *p++;
-  p = read_uleb128 (p, &tmp);
-  info->action_table = p + tmp;
-
-  return p;
-}
-
-#ifdef __ARM_EABI_UNWINDER__
-/* ARM EABI personality routines must also unwind the stack.  */
-#define CONTINUE_UNWINDING \
-  do                                                           \
-    {                                                          \
-      if (__gnu_unwind_frame (ue_header, context) != _URC_OK)  \
-       return _URC_FAILURE;                                    \
-      return _URC_CONTINUE_UNWIND;                             \
-    }                                                          \
-  while (0)
-#else
-#define CONTINUE_UNWINDING return _URC_CONTINUE_UNWIND
-#endif
-
-#ifdef __USING_SJLJ_EXCEPTIONS__
-#define PERSONALITY_FUNCTION    __gcc_personality_sj0
-#define __builtin_eh_return_data_regno(x) x
-#else
-#define PERSONALITY_FUNCTION    __gcc_personality_v0
-#endif
-
-#ifdef __ARM_EABI_UNWINDER__
-_Unwind_Reason_Code
-PERSONALITY_FUNCTION (_Unwind_State, struct _Unwind_Exception *,
-                     struct _Unwind_Context *);
-
-_Unwind_Reason_Code
-PERSONALITY_FUNCTION (_Unwind_State state,
-                     struct _Unwind_Exception * ue_header,
-                     struct _Unwind_Context * context)
-#else
-_Unwind_Reason_Code
-PERSONALITY_FUNCTION (int, _Unwind_Action, _Unwind_Exception_Class,
-                     struct _Unwind_Exception *, struct _Unwind_Context *);
-
-_Unwind_Reason_Code
-PERSONALITY_FUNCTION (int version,
-                     _Unwind_Action actions,
-                     _Unwind_Exception_Class exception_class ATTRIBUTE_UNUSED,
-                     struct _Unwind_Exception *ue_header,
-                     struct _Unwind_Context *context)
-#endif
-{
-  lsda_header_info info;
-  const unsigned char *language_specific_data, *p;
-  _Unwind_Ptr landing_pad, ip;
-  int ip_before_insn = 0;
-
-#ifdef __ARM_EABI_UNWINDER__
-  if ((state & _US_ACTION_MASK) != _US_UNWIND_FRAME_STARTING)
-    CONTINUE_UNWINDING;
-
-  /* The dwarf unwinder assumes the context structure holds things like the
-     function and LSDA pointers.  The ARM implementation caches these in
-     the exception header (UCB).  To avoid rewriting everything we make the
-     virtual IP register point at the UCB.  */
-  ip = (_Unwind_Ptr) ue_header;
-  _Unwind_SetGR (context, 12, ip);
-#else
-  if (version != 1)
-    return _URC_FATAL_PHASE1_ERROR;
-
-  /* Currently we only support cleanups for C.  */
-  if ((actions & _UA_CLEANUP_PHASE) == 0)
-    CONTINUE_UNWINDING;
-#endif
-
-  language_specific_data = (const unsigned char *)
-    _Unwind_GetLanguageSpecificData (context);
-
-  /* If no LSDA, then there are no handlers or cleanups.  */
-  if (! language_specific_data)
-    CONTINUE_UNWINDING;
-
-  /* Parse the LSDA header.  */
-  p = parse_lsda_header (context, language_specific_data, &info);
-#ifdef HAVE_GETIPINFO
-  ip = _Unwind_GetIPInfo (context, &ip_before_insn);
-#else
-  ip = _Unwind_GetIP (context);
-#endif
-  if (! ip_before_insn)
-    --ip;
-  landing_pad = 0;
-
-#ifdef __USING_SJLJ_EXCEPTIONS__
-  /* The given "IP" is an index into the call-site table, with two
-     exceptions -- -1 means no-action, and 0 means terminate.  But
-     since we're using uleb128 values, we've not got random access
-     to the array.  */
-  if ((int) ip <= 0)
-    return _URC_CONTINUE_UNWIND;
-  else
-    {
-      _uleb128_t cs_lp, cs_action;
-      do
-       {
-         p = read_uleb128 (p, &cs_lp);
-         p = read_uleb128 (p, &cs_action);
-       }
-      while (--ip);
-
-      /* Can never have null landing pad for sjlj -- that would have
-        been indicated by a -1 call site index.  */
-      landing_pad = (_Unwind_Ptr)cs_lp + 1;
-      goto found_something;
-    }
-#else
-  /* Search the call-site table for the action associated with this IP.  */
-  while (p < info.action_table)
-    {
-      _Unwind_Ptr cs_start, cs_len, cs_lp;
-      _uleb128_t cs_action;
-
-      /* Note that all call-site encodings are "absolute" displacements.  */
-      p = read_encoded_value (0, info.call_site_encoding, p, &cs_start);
-      p = read_encoded_value (0, info.call_site_encoding, p, &cs_len);
-      p = read_encoded_value (0, info.call_site_encoding, p, &cs_lp);
-      p = read_uleb128 (p, &cs_action);
-
-      /* The table is sorted, so if we've passed the ip, stop.  */
-      if (ip < info.Start + cs_start)
-       p = info.action_table;
-      else if (ip < info.Start + cs_start + cs_len)
-       {
-         if (cs_lp)
-           landing_pad = info.LPStart + cs_lp;
-         goto found_something;
-       }
-    }
-#endif
-
-  /* IP is not in table.  No associated cleanups.  */
-  /* ??? This is where C++ calls std::terminate to catch throw
-     from a destructor.  */
-  CONTINUE_UNWINDING;
-
- found_something:
-  if (landing_pad == 0)
-    {
-      /* IP is present, but has a null landing pad.
-        No handler to be run.  */
-      CONTINUE_UNWINDING;
-    }
-
-  _Unwind_SetGR (context, __builtin_eh_return_data_regno (0),
-                (_Unwind_Ptr) ue_header);
-  _Unwind_SetGR (context, __builtin_eh_return_data_regno (1), 0);
-  _Unwind_SetIP (context, landing_pad);
-  return _URC_INSTALL_CONTEXT;
-}
diff --git a/gcc/unwind-compat.c b/gcc/unwind-compat.c
deleted file mode 100644 (file)
index 5b41f24..0000000
+++ /dev/null
@@ -1,210 +0,0 @@
-/* Backward compatibility unwind routines.
-   Copyright (C) 2004, 2005, 2006, 2009
-   Free Software Foundation, Inc.
-
-   This file is part of GCC.
-
-   GCC 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 3, or (at your option)
-   any later version.
-
-   GCC 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.
-
-   Under Section 7 of GPL version 3, you are granted additional
-   permissions described in the GCC Runtime Library Exception, version
-   3.1, as published by the Free Software Foundation.
-
-   You should have received a copy of the GNU General Public License and
-   a copy of the GCC Runtime Library Exception along with this program;
-   see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
-   <http://www.gnu.org/licenses/>.  */
-
-#if defined (USE_GAS_SYMVER) && defined (USE_LIBUNWIND_EXCEPTIONS)
-#include "tconfig.h"
-#include "tsystem.h"
-#include "unwind.h"
-#include "unwind-dw2-fde.h"
-#include "unwind-compat.h"
-
-extern _Unwind_Reason_Code __libunwind_Unwind_Backtrace
-  (_Unwind_Trace_Fn, void *);
-
-_Unwind_Reason_Code LIBGCC2_UNWIND_ATTRIBUTE
-_Unwind_Backtrace (_Unwind_Trace_Fn trace, void *trace_argument)
-{
-  return __libunwind_Unwind_Backtrace (trace, trace_argument);
-}
-symver (_Unwind_Backtrace, GCC_3.3);
-
-extern void __libunwind_Unwind_DeleteException
-  (struct _Unwind_Exception *);
-
-void
-_Unwind_DeleteException (struct _Unwind_Exception *exc)
-{
-  return __libunwind_Unwind_DeleteException (exc);
-}
-symver (_Unwind_DeleteException, GCC_3.0);
-
-extern void * __libunwind_Unwind_FindEnclosingFunction (void *);
-
-void *
-_Unwind_FindEnclosingFunction (void *pc)
-{
-  return __libunwind_Unwind_FindEnclosingFunction (pc);
-}
-symver (_Unwind_FindEnclosingFunction, GCC_3.3);
-
-extern _Unwind_Reason_Code __libunwind_Unwind_ForcedUnwind
-  (struct _Unwind_Exception *, _Unwind_Stop_Fn, void *);
-
-_Unwind_Reason_Code LIBGCC2_UNWIND_ATTRIBUTE
-_Unwind_ForcedUnwind (struct _Unwind_Exception *exc,
-                     _Unwind_Stop_Fn stop, void * stop_argument)
-{
-  return __libunwind_Unwind_ForcedUnwind (exc, stop, stop_argument);
-}
-symver (_Unwind_ForcedUnwind, GCC_3.0);
-
-extern _Unwind_Word __libunwind_Unwind_GetCFA
-  (struct _Unwind_Context *);
-
-_Unwind_Word
-_Unwind_GetCFA (struct _Unwind_Context *context)
-{
-  return __libunwind_Unwind_GetCFA (context);
-}
-symver (_Unwind_GetCFA, GCC_3.3);
-
-#ifdef __ia64__
-extern _Unwind_Word __libunwind_Unwind_GetBSP
-  (struct _Unwind_Context *);
-
-_Unwind_Word
-_Unwind_GetBSP (struct _Unwind_Context * context)
-{
-  return __libunwind_Unwind_GetBSP (context);
-}
-symver (_Unwind_GetBSP, GCC_3.3.2);
-#else
-extern _Unwind_Ptr __libunwind_Unwind_GetDataRelBase
-  (struct _Unwind_Context *);
-
-_Unwind_Ptr
-_Unwind_GetDataRelBase (struct _Unwind_Context *context)
-{
-  return __libunwind_Unwind_GetDataRelBase (context);
-}
-symver (_Unwind_GetDataRelBase, GCC_3.0);
-
-extern _Unwind_Ptr __libunwind_Unwind_GetTextRelBase
-  (struct _Unwind_Context *);
-
-_Unwind_Ptr
-_Unwind_GetTextRelBase (struct _Unwind_Context *context)
-{
-  return __libunwind_Unwind_GetTextRelBase (context);
-}
-symver (_Unwind_GetTextRelBase, GCC_3.0);
-#endif
-
-extern _Unwind_Word __libunwind_Unwind_GetGR
-  (struct _Unwind_Context *, int );
-
-_Unwind_Word
-_Unwind_GetGR (struct _Unwind_Context *context, int index)
-{
-  return __libunwind_Unwind_GetGR (context, index);
-}
-symver (_Unwind_GetGR, GCC_3.0);
-
-extern _Unwind_Ptr __libunwind_Unwind_GetIP (struct _Unwind_Context *);
-
-_Unwind_Ptr
-_Unwind_GetIP (struct _Unwind_Context *context)
-{
-  return __libunwind_Unwind_GetIP (context);
-}
-symver (_Unwind_GetIP, GCC_3.0);
-
-_Unwind_Ptr
-_Unwind_GetIPInfo (struct _Unwind_Context *context, int *ip_before_insn)
-{
-  *ip_before_insn = 0;
-  return __libunwind_Unwind_GetIP (context);
-}
-
-extern void *__libunwind_Unwind_GetLanguageSpecificData
-  (struct _Unwind_Context *);
-
-void *
-_Unwind_GetLanguageSpecificData (struct _Unwind_Context *context)
-{
-  return __libunwind_Unwind_GetLanguageSpecificData (context);
-}
-symver (_Unwind_GetLanguageSpecificData, GCC_3.0);
-
-extern _Unwind_Ptr __libunwind_Unwind_GetRegionStart
-  (struct _Unwind_Context *);
-
-_Unwind_Ptr
-_Unwind_GetRegionStart (struct _Unwind_Context *context)
-{
-  return __libunwind_Unwind_GetRegionStart (context);
-}
-symver (_Unwind_GetRegionStart, GCC_3.0);
-
-extern _Unwind_Reason_Code __libunwind_Unwind_RaiseException
-  (struct _Unwind_Exception *);
-
-_Unwind_Reason_Code LIBGCC2_UNWIND_ATTRIBUTE
-_Unwind_RaiseException(struct _Unwind_Exception *exc)
-{
-  return __libunwind_Unwind_RaiseException (exc);
-}
-symver (_Unwind_RaiseException, GCC_3.0);
-
-extern void __libunwind_Unwind_Resume (struct _Unwind_Exception *);
-
-void LIBGCC2_UNWIND_ATTRIBUTE
-_Unwind_Resume (struct _Unwind_Exception *exc)
-{
-  __libunwind_Unwind_Resume (exc);
-}
-symver (_Unwind_Resume, GCC_3.0);
-
-extern _Unwind_Reason_Code __libunwind_Unwind_Resume_or_Rethrow
-   (struct _Unwind_Exception *);
-
-_Unwind_Reason_Code LIBGCC2_UNWIND_ATTRIBUTE
-_Unwind_Resume_or_Rethrow (struct _Unwind_Exception *exc)
-{
-  return __libunwind_Unwind_Resume_or_Rethrow (exc);
-}
-symver (_Unwind_Resume_or_Rethrow, GCC_3.3);
-
-extern void __libunwind_Unwind_SetGR
-  (struct _Unwind_Context *, int, _Unwind_Word);
-
-void
-_Unwind_SetGR (struct _Unwind_Context *context, int index,
-              _Unwind_Word val)
-{
-  __libunwind_Unwind_SetGR (context, index, val);
-}
-symver (_Unwind_SetGR, GCC_3.0);
-
-extern void __libunwind_Unwind_SetIP
-  (struct _Unwind_Context *, _Unwind_Ptr);
-
-void
-_Unwind_SetIP (struct _Unwind_Context *context, _Unwind_Ptr val)
-{
-  return __libunwind_Unwind_SetIP (context, val);
-}
-symver (_Unwind_SetIP, GCC_3.0);
-#endif
diff --git a/gcc/unwind-compat.h b/gcc/unwind-compat.h
deleted file mode 100644 (file)
index 24c8de1..0000000
+++ /dev/null
@@ -1,30 +0,0 @@
-/* Backward compatibility unwind routines.
-   Copyright (C) 2004, 2009
-   Free Software Foundation, Inc.
-
-   This file is part of GCC.
-
-   GCC 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 3, or (at your option)
-   any later version.
-
-   GCC 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.
-
-   Under Section 7 of GPL version 3, you are granted additional
-   permissions described in the GCC Runtime Library Exception, version
-   3.1, as published by the Free Software Foundation.
-
-   You should have received a copy of the GNU General Public License and
-   a copy of the GCC Runtime Library Exception along with this program;
-   see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
-   <http://www.gnu.org/licenses/>.  */
-
-#define symver(name, version) \
-  __asm__ (".symver " #name"," #name "@" #version)
-
-#define alias(name) \
-  __typeof(name) __libunwind##name __attribute__ ((alias (#name)))
diff --git a/gcc/unwind-dw2-fde-compat.c b/gcc/unwind-dw2-fde-compat.c
deleted file mode 100644 (file)
index f305a55..0000000
+++ /dev/null
@@ -1,43 +0,0 @@
-/* Backward compatibility unwind routines.
-   Copyright (C) 2004, 2005, 2009
-   Free Software Foundation, Inc.
-
-   This file is part of GCC.
-
-   GCC 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 3, or (at your option)
-   any later version.
-
-   GCC 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.
-
-   Under Section 7 of GPL version 3, you are granted additional
-   permissions described in the GCC Runtime Library Exception, version
-   3.1, as published by the Free Software Foundation.
-
-   You should have received a copy of the GNU General Public License and
-   a copy of the GCC Runtime Library Exception along with this program;
-   see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
-   <http://www.gnu.org/licenses/>.  */
-
-#if defined (USE_GAS_SYMVER) && defined (USE_LIBUNWIND_EXCEPTIONS)
-#include "tconfig.h"
-#include "tsystem.h"
-#include "unwind.h"
-#include "unwind-dw2-fde.h"
-#include "unwind-compat.h"
-
-extern const fde * __libunwind__Unwind_Find_FDE
-  (void *, struct dwarf_eh_bases *);
-
-const fde *
-_Unwind_Find_FDE (void *pc, struct dwarf_eh_bases *bases)
-{
-  __libunwind__Unwind_Find_FDE (pc, bases);
-}
-
-symver (_Unwind_Find_FDE, GCC_3.0);
-#endif
diff --git a/gcc/unwind-dw2-fde-darwin.c b/gcc/unwind-dw2-fde-darwin.c
deleted file mode 100644 (file)
index 75b404e..0000000
+++ /dev/null
@@ -1,289 +0,0 @@
-/* Copyright (C) 2001, 2002, 2003, 2005, 2009, 2010
-   Free Software Foundation, Inc.
-
-   This file is part of GCC.
-
-   GCC 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 3, or (at your option)
-   any later version.
-
-   GCC 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.
-
-   Under Section 7 of GPL version 3, you are granted additional
-   permissions described in the GCC Runtime Library Exception, version
-   3.1, as published by the Free Software Foundation.
-
-   You should have received a copy of the GNU General Public License and
-   a copy of the GCC Runtime Library Exception along with this program;
-   see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
-   <http://www.gnu.org/licenses/>.  */
-
-/* Locate the FDE entry for a given address, using Darwin's keymgr support.  */
-
-#include "tconfig.h"
-#include "tsystem.h"
-#include <string.h>
-#include <stdlib.h>
-#include "dwarf2.h"
-#include "unwind.h"
-#define NO_BASE_OF_ENCODED_VALUE
-#define DWARF2_OBJECT_END_PTR_EXTENSION
-#include "unwind-pe.h"
-#include "unwind-dw2-fde.h"
-/* Carefully don't include gthr.h.  */
-
-typedef int __gthread_mutex_t;
-#define __gthread_mutex_lock(x)  (void)(x)
-#define __gthread_mutex_unlock(x) (void)(x)
-
-static const fde * _Unwind_Find_registered_FDE (void *pc,
-                                               struct dwarf_eh_bases *bases);
-
-#define _Unwind_Find_FDE _Unwind_Find_registered_FDE
-#include "unwind-dw2-fde.c"
-#undef _Unwind_Find_FDE
-
-/* KeyMgr stuff.  */
-#define KEYMGR_GCC3_LIVE_IMAGE_LIST     301     /* loaded images  */
-#define KEYMGR_GCC3_DW2_OBJ_LIST        302     /* Dwarf2 object list  */
-
-extern void *_keymgr_get_and_lock_processwide_ptr (int);
-extern void _keymgr_set_and_unlock_processwide_ptr (int, void *);
-extern void _keymgr_unlock_processwide_ptr (int);
-
-struct mach_header;
-struct mach_header_64;
-extern char *getsectdatafromheader (struct mach_header*, const char*,
-                                   const char *, unsigned long *);
-extern char *getsectdatafromheader_64 (struct mach_header_64*, const char*,
-                                      const char *, unsigned long *);
-
-/* This is referenced from KEYMGR_GCC3_DW2_OBJ_LIST.  */
-struct km_object_info {
-  struct object *seen_objects;
-  struct object *unseen_objects;
-  unsigned spare[2];
-};
-
-/* Node of KEYMGR_GCC3_LIVE_IMAGE_LIST.  Info about each resident image.  */
-struct live_images {
-  unsigned long this_size;                      /* sizeof (live_images)  */
-  struct mach_header *mh;                       /* the image info  */
-  unsigned long vm_slide;
-  void (*destructor)(struct live_images *);     /* destructor for this  */
-  struct live_images *next;
-  unsigned int examined_p;
-  void *fde;
-  void *object_info;
-  unsigned long info[2];                        /* Future use.  */
-};
-
-/* Bits in the examined_p field of struct live_images.  */
-enum {
-  EXAMINED_IMAGE_MASK = 1,     /* We've seen this one.  */
-  ALLOCED_IMAGE_MASK = 2,      /* The FDE entries were allocated by
-                                  malloc, and must be freed.  This isn't
-                                  used by newer libgcc versions.  */
-  IMAGE_IS_TEXT_MASK = 4,      /* This image is in the TEXT segment.  */
-  DESTRUCTOR_MAY_BE_CALLED_LIVE = 8  /* The destructor may be called on an
-                                       object that's part of the live
-                                       image list.  */
-};
-\f
-/* Delete any data we allocated on a live_images structure.  Either
-   IMAGE has already been removed from the
-   KEYMGR_GCC3_LIVE_IMAGE_LIST and the struct will be deleted
-   after we return, or that list is locked and we're being called
-   because this object might be about to be unloaded.  Called by
-   KeyMgr.  */
-
-static void
-live_image_destructor (struct live_images *image)
-{
-  if (image->object_info)
-    {
-      struct km_object_info *the_obj_info;
-
-      the_obj_info =
-       _keymgr_get_and_lock_processwide_ptr (KEYMGR_GCC3_DW2_OBJ_LIST);
-      if (the_obj_info)
-       {
-         seen_objects = the_obj_info->seen_objects;
-         unseen_objects = the_obj_info->unseen_objects;
-
-         /* Free any sorted arrays.  */
-         __deregister_frame_info_bases (image->fde);
-
-         the_obj_info->seen_objects = seen_objects;
-         the_obj_info->unseen_objects = unseen_objects;
-       }
-      _keymgr_set_and_unlock_processwide_ptr (KEYMGR_GCC3_DW2_OBJ_LIST,
-                                             the_obj_info);
-
-      free (image->object_info);
-      image->object_info = NULL;
-      if (image->examined_p & ALLOCED_IMAGE_MASK)
-       free (image->fde);
-      image->fde = NULL;
-    }
-  image->examined_p = 0;
-  image->destructor = NULL;
-}
-
-/* Run through the list of live images.  If we can allocate memory,
-   give each unseen image a new `struct object'.  Even if we can't,
-   check whether the PC is inside the FDE of each unseen image.
- */
-
-static inline const fde *
-examine_objects (void *pc, struct dwarf_eh_bases *bases, int dont_alloc)
-{
-  const fde *result = NULL;
-  struct live_images *image;
-
-  image = _keymgr_get_and_lock_processwide_ptr (KEYMGR_GCC3_LIVE_IMAGE_LIST);
-
-  for (; image != NULL; image = image->next)
-    if ((image->examined_p & EXAMINED_IMAGE_MASK) == 0)
-      {
-       char *fde = NULL;
-       unsigned long sz;
-
-       /* For ppc only check whether or not we have __DATA eh frames.  */
-#ifdef __ppc__
-       fde = getsectdatafromheader (image->mh, "__DATA", "__eh_frame", &sz);
-#endif
-
-       if (fde == NULL)
-         {
-#if __LP64__
-           fde = getsectdatafromheader_64 ((struct mach_header_64 *) image->mh,
-                                           "__TEXT", "__eh_frame", &sz);
-#else
-           fde = getsectdatafromheader (image->mh, "__TEXT",
-                                        "__eh_frame", &sz);
-#endif
-           if (fde != NULL)
-             image->examined_p |= IMAGE_IS_TEXT_MASK;
-         }
-
-       /* If .eh_frame is empty, don't register at all.  */
-       if (fde != NULL && sz > 0)
-         {
-           char *real_fde = (fde + image->vm_slide);
-           struct object *ob = NULL;
-           struct object panicob;
-
-           if (! dont_alloc)
-             ob = calloc (1, sizeof (struct object));
-           dont_alloc |= ob == NULL;
-           if (dont_alloc)
-             ob = &panicob;
-
-           ob->pc_begin = (void *)-1;
-           ob->tbase = 0;
-           ob->dbase = 0;
-           ob->u.single = (struct dwarf_fde *)real_fde;
-           ob->s.i = 0;
-           ob->s.b.encoding = DW_EH_PE_omit;
-           ob->fde_end = real_fde + sz;
-
-           image->fde = real_fde;
-
-           result = search_object (ob, pc);
-
-           if (! dont_alloc)
-             {
-               struct object **p;
-
-               image->destructor = live_image_destructor;
-               image->object_info = ob;
-
-               image->examined_p |= (EXAMINED_IMAGE_MASK
-                                     | DESTRUCTOR_MAY_BE_CALLED_LIVE);
-
-               /* 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 (result)
-             {
-               int encoding;
-               _Unwind_Ptr func;
-
-               bases->tbase = ob->tbase;
-               bases->dbase = ob->dbase;
-
-               encoding = ob->s.b.encoding;
-               if (ob->s.b.mixed_encoding)
-                 encoding = get_fde_encoding (result);
-               read_encoded_value_with_base (encoding,
-                                             base_from_object (encoding, ob),
-                                             result->pc_begin, &func);
-               bases->func = (void *) func;
-               break;
-             }
-         }
-       else
-         image->examined_p |= EXAMINED_IMAGE_MASK;
-      }
-
-  _keymgr_unlock_processwide_ptr (KEYMGR_GCC3_LIVE_IMAGE_LIST);
-
-  return result;
-}
-
-const fde *
-_Unwind_Find_FDE (void *pc, struct dwarf_eh_bases *bases)
-{
-  struct km_object_info *the_obj_info;
-  const fde *ret = NULL;
-
-  the_obj_info =
-    _keymgr_get_and_lock_processwide_ptr (KEYMGR_GCC3_DW2_OBJ_LIST);
-  if (! the_obj_info)
-    the_obj_info = calloc (1, sizeof (*the_obj_info));
-
-  if (the_obj_info != NULL)
-    {
-      seen_objects = the_obj_info->seen_objects;
-      unseen_objects = the_obj_info->unseen_objects;
-
-      ret = _Unwind_Find_registered_FDE (pc, bases);
-    }
-
-  /* OK, didn't find it in the list of FDEs we've seen before,
-     so go through and look at the new ones.  */
-  if (ret == NULL)
-    ret = examine_objects (pc, bases, the_obj_info == NULL);
-
-  if (the_obj_info != NULL)
-    {
-      the_obj_info->seen_objects = seen_objects;
-      the_obj_info->unseen_objects = unseen_objects;
-    }
-  _keymgr_set_and_unlock_processwide_ptr (KEYMGR_GCC3_DW2_OBJ_LIST,
-                                         the_obj_info);
-  return ret;
-}
-
-void *
-_darwin10_Unwind_FindEnclosingFunction (void *pc ATTRIBUTE_UNUSED)
-{
-#if __MACH__ && (__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ >= 1060)
-  struct dwarf_eh_bases bases;
-  const struct dwarf_fde *fde = _Unwind_Find_FDE (pc-1, &bases);
-  if (fde)
-    return bases.func;
-#endif
-  return NULL;
-}
-
diff --git a/gcc/unwind-dw2-fde-glibc.c b/gcc/unwind-dw2-fde-glibc.c
deleted file mode 100644 (file)
index d8e3c0e..0000000
+++ /dev/null
@@ -1,470 +0,0 @@
-/* Copyright (C) 2001, 2002, 2003, 2004, 2005, 2009, 2010
-   Free Software Foundation, Inc.
-   Contributed by Jakub Jelinek <jakub@redhat.com>.
-
-   This file is part of GCC.
-
-   GCC 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 3, or (at your option)
-   any later version.
-
-   GCC 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.
-
-   Under Section 7 of GPL version 3, you are granted additional
-   permissions described in the GCC Runtime Library Exception, version
-   3.1, as published by the Free Software Foundation.
-
-   You should have received a copy of the GNU General Public License and
-   a copy of the GCC Runtime Library Exception along with this program;
-   see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
-   <http://www.gnu.org/licenses/>.  */
-
-/* Locate the FDE entry for a given address, using PT_GNU_EH_FRAME ELF
-   segment and dl_iterate_phdr to avoid register/deregister calls at
-   DSO load/unload.  */
-
-#ifndef _GNU_SOURCE
-#define _GNU_SOURCE 1
-#endif
-
-#include "tconfig.h"
-#include "tsystem.h"
-#ifndef inhibit_libc
-#include <elf.h>               /* Get DT_CONFIG.  */
-#endif
-#include "coretypes.h"
-#include "tm.h"
-#include "dwarf2.h"
-#include "unwind.h"
-#define NO_BASE_OF_ENCODED_VALUE
-#include "unwind-pe.h"
-#include "unwind-dw2-fde.h"
-#include "unwind-compat.h"
-#include "gthr.h"
-
-#if !defined(inhibit_libc) && defined(HAVE_LD_EH_FRAME_HDR) \
-    && (__GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ > 2) \
-       || (__GLIBC__ == 2 && __GLIBC_MINOR__ == 2 && defined(DT_CONFIG)))
-# define USE_PT_GNU_EH_FRAME
-#endif
-
-#if !defined(inhibit_libc) && defined(HAVE_LD_EH_FRAME_HDR) \
-    && defined(__FreeBSD__) && __FreeBSD__ >= 7
-# define ElfW __ElfN
-# define USE_PT_GNU_EH_FRAME
-#endif
-
-#if !defined(inhibit_libc) && defined(HAVE_LD_EH_FRAME_HDR) \
-    && defined(TARGET_DL_ITERATE_PHDR) \
-    && defined(__sun__) && defined(__svr4__)
-# define USE_PT_GNU_EH_FRAME
-#endif
-
-#if defined(USE_PT_GNU_EH_FRAME)
-
-#include <link.h>
-
-#ifndef __RELOC_POINTER
-# define __RELOC_POINTER(ptr, base) ((ptr) + (base))
-#endif
-
-static const fde * _Unwind_Find_registered_FDE (void *pc, struct dwarf_eh_bases *bases);
-
-#define _Unwind_Find_FDE _Unwind_Find_registered_FDE
-#include "unwind-dw2-fde.c"
-#undef _Unwind_Find_FDE
-
-#ifndef PT_GNU_EH_FRAME
-#define PT_GNU_EH_FRAME (PT_LOOS + 0x474e550)
-#endif
-
-struct unw_eh_callback_data
-{
-  _Unwind_Ptr pc;
-  void *tbase;
-  void *dbase;
-  void *func;
-  const fde *ret;
-  int check_cache;
-};
-
-struct unw_eh_frame_hdr
-{
-  unsigned char version;
-  unsigned char eh_frame_ptr_enc;
-  unsigned char fde_count_enc;
-  unsigned char table_enc;
-};
-
-#define FRAME_HDR_CACHE_SIZE 8
-
-static struct frame_hdr_cache_element
-{
-  _Unwind_Ptr pc_low;
-  _Unwind_Ptr pc_high;
-  _Unwind_Ptr load_base;
-  const ElfW(Phdr) *p_eh_frame_hdr;
-  const ElfW(Phdr) *p_dynamic;
-  struct frame_hdr_cache_element *link;
-} frame_hdr_cache[FRAME_HDR_CACHE_SIZE];
-
-static struct frame_hdr_cache_element *frame_hdr_cache_head;
-
-/* Like base_of_encoded_value, but take the base from a struct
-   unw_eh_callback_data instead of an _Unwind_Context.  */
-
-static _Unwind_Ptr
-base_from_cb_data (unsigned char encoding, struct unw_eh_callback_data *data)
-{
-  if (encoding == DW_EH_PE_omit)
-    return 0;
-
-  switch (encoding & 0x70)
-    {
-    case DW_EH_PE_absptr:
-    case DW_EH_PE_pcrel:
-    case DW_EH_PE_aligned:
-      return 0;
-
-    case DW_EH_PE_textrel:
-      return (_Unwind_Ptr) data->tbase;
-    case DW_EH_PE_datarel:
-      return (_Unwind_Ptr) data->dbase;
-    default:
-      gcc_unreachable ();
-    }
-}
-
-static int
-_Unwind_IteratePhdrCallback (struct dl_phdr_info *info, size_t size, void *ptr)
-{
-  struct unw_eh_callback_data *data = (struct unw_eh_callback_data *) ptr;
-  const ElfW(Phdr) *phdr, *p_eh_frame_hdr, *p_dynamic;
-  long n, match;
-#ifdef __FRV_FDPIC__
-  struct elf32_fdpic_loadaddr load_base;
-#else
-  _Unwind_Ptr load_base;
-#endif
-  const unsigned char *p;
-  const struct unw_eh_frame_hdr *hdr;
-  _Unwind_Ptr eh_frame;
-  struct object ob;
-  _Unwind_Ptr pc_low = 0, pc_high = 0;
-
-  struct ext_dl_phdr_info
-    {
-      ElfW(Addr) dlpi_addr;
-      const char *dlpi_name;
-      const ElfW(Phdr) *dlpi_phdr;
-      ElfW(Half) dlpi_phnum;
-      unsigned long long int dlpi_adds;
-      unsigned long long int dlpi_subs;
-    };
-
-  match = 0;
-  phdr = info->dlpi_phdr;
-  load_base = info->dlpi_addr;
-  p_eh_frame_hdr = NULL;
-  p_dynamic = NULL;
-
-  struct frame_hdr_cache_element *prev_cache_entry = NULL,
-    *last_cache_entry = NULL;
-
-  if (data->check_cache && size >= sizeof (struct ext_dl_phdr_info))
-    {
-      static unsigned long long adds = -1ULL, subs;
-      struct ext_dl_phdr_info *einfo = (struct ext_dl_phdr_info *) info;
-
-      /* We use a least recently used cache replacement policy.  Also,
-        the most recently used cache entries are placed at the head
-        of the search chain.  */
-
-      if (einfo->dlpi_adds == adds && einfo->dlpi_subs == subs)
-       {
-         /* Find data->pc in shared library cache.
-            Set load_base, p_eh_frame_hdr and p_dynamic
-            plus match from the cache and goto
-            "Read .eh_frame_hdr header." below.  */
-
-         struct frame_hdr_cache_element *cache_entry;
-
-         for (cache_entry = frame_hdr_cache_head;
-              cache_entry;
-              cache_entry = cache_entry->link)
-           {
-             if (data->pc >= cache_entry->pc_low
-                 && data->pc < cache_entry->pc_high)
-               {
-                 load_base = cache_entry->load_base;
-                 p_eh_frame_hdr = cache_entry->p_eh_frame_hdr;
-                 p_dynamic = cache_entry->p_dynamic;
-
-                 /* And move the entry we're using to the head.  */
-                 if (cache_entry != frame_hdr_cache_head)
-                   {
-                     prev_cache_entry->link = cache_entry->link;
-                     cache_entry->link = frame_hdr_cache_head;
-                     frame_hdr_cache_head = cache_entry;
-                   }
-                 goto found;
-               }
-
-             last_cache_entry = cache_entry;
-             /* Exit early if we found an unused entry.  */
-             if ((cache_entry->pc_low | cache_entry->pc_high) == 0)
-               break;
-             if (cache_entry->link != NULL)
-               prev_cache_entry = cache_entry;
-           }
-       }
-      else
-       {
-         adds = einfo->dlpi_adds;
-         subs = einfo->dlpi_subs;
-         /* Initialize the cache.  Create a chain of cache entries,
-            with the final one terminated by a NULL link.  */
-         int i;
-         for (i = 0; i < FRAME_HDR_CACHE_SIZE; i++)
-           {
-             frame_hdr_cache[i].pc_low = 0;
-             frame_hdr_cache[i].pc_high = 0;
-             frame_hdr_cache[i].link = &frame_hdr_cache[i+1];
-           }
-         frame_hdr_cache[i-1].link = NULL;
-         frame_hdr_cache_head = &frame_hdr_cache[0];
-         data->check_cache = 0;
-       }
-    }
-
-  /* Make sure struct dl_phdr_info is at least as big as we need.  */
-  if (size < offsetof (struct dl_phdr_info, dlpi_phnum)
-            + sizeof (info->dlpi_phnum))
-    return -1;
-
-  /* See if PC falls into one of the loaded segments.  Find the eh_frame
-     segment at the same time.  */
-  for (n = info->dlpi_phnum; --n >= 0; phdr++)
-    {
-      if (phdr->p_type == PT_LOAD)
-       {
-         _Unwind_Ptr vaddr = (_Unwind_Ptr)
-           __RELOC_POINTER (phdr->p_vaddr, load_base);
-         if (data->pc >= vaddr && data->pc < vaddr + phdr->p_memsz)
-           {
-             match = 1;
-             pc_low = vaddr;
-             pc_high =  vaddr + phdr->p_memsz;
-           }
-       }
-      else if (phdr->p_type == PT_GNU_EH_FRAME)
-       p_eh_frame_hdr = phdr;
-#ifdef PT_SUNW_UNWIND
-      /* Sun ld emits PT_SUNW_UNWIND .eh_frame_hdr sections instead of
-        PT_SUNW_EH_FRAME/PT_GNU_EH_FRAME, so accept them as well.  */
-      else if (phdr->p_type == PT_SUNW_UNWIND)
-       p_eh_frame_hdr = phdr;
-#endif
-      else if (phdr->p_type == PT_DYNAMIC)
-       p_dynamic = phdr;
-    }
-
-  if (!match)
-    return 0;
-
-  if (size >= sizeof (struct ext_dl_phdr_info))
-    {
-      /* Move the cache entry we're about to overwrite to the head of
-        the list.  If either last_cache_entry or prev_cache_entry are
-        NULL, that cache entry is already at the head.  */
-      if (last_cache_entry != NULL && prev_cache_entry != NULL)
-       {
-         prev_cache_entry->link = last_cache_entry->link;
-         last_cache_entry->link = frame_hdr_cache_head;
-         frame_hdr_cache_head = last_cache_entry;
-       }
-
-      frame_hdr_cache_head->load_base = load_base;
-      frame_hdr_cache_head->p_eh_frame_hdr = p_eh_frame_hdr;
-      frame_hdr_cache_head->p_dynamic = p_dynamic;
-      frame_hdr_cache_head->pc_low = pc_low;
-      frame_hdr_cache_head->pc_high = pc_high;
-    }
-
- found:
-
-  if (!p_eh_frame_hdr)
-    return 0;
-
-  /* Read .eh_frame_hdr header.  */
-  hdr = (const struct unw_eh_frame_hdr *)
-    __RELOC_POINTER (p_eh_frame_hdr->p_vaddr, load_base);
-  if (hdr->version != 1)
-    return 1;
-
-#ifdef CRT_GET_RFIB_DATA
-# ifdef __i386__
-  data->dbase = NULL;
-  if (p_dynamic)
-    {
-      /* For dynamically linked executables and shared libraries,
-        DT_PLTGOT is the gp value for that object.  */
-      ElfW(Dyn) *dyn = (ElfW(Dyn) *)
-       __RELOC_POINTER (p_dynamic->p_vaddr, load_base);
-      for (; dyn->d_tag != DT_NULL ; dyn++)
-       if (dyn->d_tag == DT_PLTGOT)
-         {
-           data->dbase = (void *) dyn->d_un.d_ptr;
-#if defined __linux__
-           /* On IA-32 Linux, _DYNAMIC is writable and GLIBC has
-              relocated it.  */
-#elif defined __sun__ && defined __svr4__
-           /* On Solaris 2/x86, we need to do this ourselves.  */
-           data->dbase += load_base;
-#endif
-           break;
-         }
-    }
-# elif defined __FRV_FDPIC__ && defined __linux__
-  data->dbase = load_base.got_value;
-# elif defined __x86_64__ && defined __sun__ && defined __svr4__
-  /* While CRT_GET_RFIB_DATA is also defined for 64-bit Solaris 10+/x86, it
-     doesn't apply since it uses DW_EH_PE_pcrel encoding.  */
-# else
-#  error What is DW_EH_PE_datarel base on this platform?
-# endif
-#endif
-
-  p = read_encoded_value_with_base (hdr->eh_frame_ptr_enc,
-                                   base_from_cb_data (hdr->eh_frame_ptr_enc,
-                                                      data),
-                                   (const unsigned char *) (hdr + 1),
-                                   &eh_frame);
-
-  /* We require here specific table encoding to speed things up.
-     Also, DW_EH_PE_datarel here means using PT_GNU_EH_FRAME start
-     as base, not the processor specific DW_EH_PE_datarel.  */
-  if (hdr->fde_count_enc != DW_EH_PE_omit
-      && hdr->table_enc == (DW_EH_PE_datarel | DW_EH_PE_sdata4))
-    {
-      _Unwind_Ptr fde_count;
-
-      p = read_encoded_value_with_base (hdr->fde_count_enc,
-                                       base_from_cb_data (hdr->fde_count_enc,
-                                                          data),
-                                       p, &fde_count);
-      /* Shouldn't happen.  */
-      if (fde_count == 0)
-       return 1;
-      if ((((_Unwind_Ptr) p) & 3) == 0)
-       {
-         struct fde_table {
-           signed initial_loc __attribute__ ((mode (SI)));
-           signed fde __attribute__ ((mode (SI)));
-         };
-         const struct fde_table *table = (const struct fde_table *) p;
-         size_t lo, hi, mid;
-         _Unwind_Ptr data_base = (_Unwind_Ptr) hdr;
-         fde *f;
-         unsigned int f_enc, f_enc_size;
-         _Unwind_Ptr range;
-
-         mid = fde_count - 1;
-         if (data->pc < table[0].initial_loc + data_base)
-           return 1;
-         else if (data->pc < table[mid].initial_loc + data_base)
-           {
-             lo = 0;
-             hi = mid;
-
-             while (lo < hi)
-               {
-                 mid = (lo + hi) / 2;
-                 if (data->pc < table[mid].initial_loc + data_base)
-                   hi = mid;
-                 else if (data->pc >= table[mid + 1].initial_loc + data_base)
-                   lo = mid + 1;
-                 else
-                   break;
-               }
-
-             gcc_assert (lo < hi);
-           }
-
-         f = (fde *) (table[mid].fde + data_base);
-         f_enc = get_fde_encoding (f);
-         f_enc_size = size_of_encoded_value (f_enc);
-         read_encoded_value_with_base (f_enc & 0x0f, 0,
-                                       &f->pc_begin[f_enc_size], &range);
-         if (data->pc < table[mid].initial_loc + data_base + range)
-           data->ret = f;
-         data->func = (void *) (table[mid].initial_loc + data_base);
-         return 1;
-       }
-    }
-
-  /* We have no sorted search table, so need to go the slow way.
-     As soon as GLIBC will provide API so to notify that a library has been
-     removed, we could cache this (and thus use search_object).  */
-  ob.pc_begin = NULL;
-  ob.tbase = data->tbase;
-  ob.dbase = data->dbase;
-  ob.u.single = (fde *) eh_frame;
-  ob.s.i = 0;
-  ob.s.b.mixed_encoding = 1;  /* Need to assume worst case.  */
-  data->ret = linear_search_fdes (&ob, (fde *) eh_frame, (void *) data->pc);
-  if (data->ret != NULL)
-    {
-      _Unwind_Ptr func;
-      unsigned int encoding = get_fde_encoding (data->ret);
-
-      read_encoded_value_with_base (encoding,
-                                   base_from_cb_data (encoding, data),
-                                   data->ret->pc_begin, &func);
-      data->func = (void *) func;
-    }
-  return 1;
-}
-
-const fde *
-_Unwind_Find_FDE (void *pc, struct dwarf_eh_bases *bases)
-{
-  struct unw_eh_callback_data data;
-  const fde *ret;
-
-  ret = _Unwind_Find_registered_FDE (pc, bases);
-  if (ret != NULL)
-    return ret;
-
-  data.pc = (_Unwind_Ptr) pc;
-  data.tbase = NULL;
-  data.dbase = NULL;
-  data.func = NULL;
-  data.ret = NULL;
-  data.check_cache = 1;
-
-  if (dl_iterate_phdr (_Unwind_IteratePhdrCallback, &data) < 0)
-    return NULL;
-
-  if (data.ret)
-    {
-      bases->tbase = data.tbase;
-      bases->dbase = data.dbase;
-      bases->func = data.func;
-    }
-  return data.ret;
-}
-
-#else
-/* Prevent multiple include of header files.  */
-#define _Unwind_Find_FDE _Unwind_Find_FDE
-#include "unwind-dw2-fde.c"
-#endif
-
-#if defined (USE_GAS_SYMVER) && defined (SHARED) && defined (USE_LIBUNWIND_EXCEPTIONS)
-alias (_Unwind_Find_FDE);
-#endif
diff --git a/gcc/unwind-dw2-fde.c b/gcc/unwind-dw2-fde.c
deleted file mode 100644 (file)
index 93d4271..0000000
+++ /dev/null
@@ -1,1054 +0,0 @@
-/* Subroutines needed for unwinding stack frames for exception handling.  */
-/* Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2008,
-   2009, 2010  Free Software Foundation, Inc.
-   Contributed by Jason Merrill <jason@cygnus.com>.
-
-This file is part of GCC.
-
-GCC 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 3, or (at your option) any later
-version.
-
-GCC 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.
-
-Under Section 7 of GPL version 3, you are granted additional
-permissions described in the GCC Runtime Library Exception, version
-3.1, as published by the Free Software Foundation.
-
-You should have received a copy of the GNU General Public License and
-a copy of the GCC Runtime Library Exception along with this program;
-see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
-<http://www.gnu.org/licenses/>.  */
-
-#ifndef _Unwind_Find_FDE
-#include "tconfig.h"
-#include "tsystem.h"
-#include "coretypes.h"
-#include "tm.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
-   its 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 __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
-
-/* Called from crtbegin.o to register the unwind info for an object.  */
-
-void
-__register_frame_info_bases (const void *begin, struct object *ob,
-                            void *tbase, void *dbase)
-{
-  /* If .eh_frame is empty, don't register at all.  */
-  if ((const uword *) begin == 0 || *(const uword *) begin == 0)
-    return;
-
-  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;
-#ifdef DWARF2_OBJECT_END_PTR_EXTENSION
-  ob->fde_end = NULL;
-#endif
-
-  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 (const void *begin, struct object *ob)
-{
-  __register_frame_info_bases (begin, ob, 0, 0);
-}
-
-void
-__register_frame (void *begin)
-{
-  struct object *ob;
-
-  /* If .eh_frame is empty, don't register at all.  */
-  if (*(uword *) begin == 0)
-    return;
-
-  ob = 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 = 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 die.
-
-   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 (const void *begin)
-{
-  struct object **p;
-  struct object *ob = 0;
-
-  /* If .eh_frame is empty, we haven't registered.  */
-  if ((const uword *) begin == 0 || *(const uword *) begin == 0)
-    return ob;
-
-  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;
-         }
-      }
-
- out:
-  __gthread_mutex_unlock (&object_mutex);
-  gcc_assert (ob);
-  return (void *) ob;
-}
-
-void *
-__deregister_frame_info (const void *begin)
-{
-  return __deregister_frame_info_bases (begin);
-}
-
-void
-__deregister_frame (void *begin)
-{
-  /* If .eh_frame is empty, we haven't registered.  */
-  if (*(uword *) begin != 0)
-    free (__deregister_frame_info (begin));
-}
-
-\f
-/* 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;
-    default:
-      gcc_unreachable ();
-    }
-}
-
-/* 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 (const struct dwarf_cie *cie)
-{
-  const unsigned char *aug, *p;
-  _Unwind_Ptr dummy;
-  _uleb128_t utmp;
-  _sleb128_t stmp;
-
-  aug = cie->augmentation;
-  p = aug + strlen ((const char *)aug) + 1; /* Skip the augmentation string.  */
-  if (__builtin_expect (cie->version >= 4, 0))
-    {
-      if (p[0] != sizeof (void *) || p[1] != 0)
-       return DW_EH_PE_omit;           /* We are not prepared to handle unexpected
-                                          address sizes or segment selectors.  */
-      p += 2;                          /* Skip address size and segment size.  */
-    }
-
-  if (aug[0] != 'z')
-    return DW_EH_PE_absptr;
-
-  p = read_uleb128 (p, &utmp);         /* Skip code alignment.  */
-  p = read_sleb128 (p, &stmp);         /* Skip data alignment.  */
-  if (cie->version == 1)               /* Skip return address column.  */
-    p++;
-  else
-    p = read_uleb128 (p, &utmp);
-
-  aug++;                               /* Skip 'z' */
-  p = read_uleb128 (p, &utmp);         /* 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 (const struct dwarf_fde *f)
-{
-  return get_cie_encoding (get_cie (f));
-}
-
-\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 int
-fde_unencoded_compare (struct object *ob __attribute__((unused)),
-                      const fde *x, const fde *y)
-{
-  _Unwind_Ptr x_ptr, y_ptr;
-  memcpy (&x_ptr, x->pc_begin, sizeof (_Unwind_Ptr));
-  memcpy (&y_ptr, y->pc_begin, sizeof (_Unwind_Ptr));
-
-  if (x_ptr > y_ptr)
-    return 1;
-  if (x_ptr < y_ptr)
-    return -1;
-  return 0;
-}
-
-static int
-fde_single_encoding_compare (struct object *ob, const fde *x, const 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);
-
-  if (x_ptr > y_ptr)
-    return 1;
-  if (x_ptr < y_ptr)
-    return -1;
-  return 0;
-}
-
-static int
-fde_mixed_encoding_compare (struct object *ob, const fde *x, const 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);
-
-  if (x_ptr > y_ptr)
-    return 1;
-  if (x_ptr < y_ptr)
-    return -1;
-  return 0;
-}
-
-typedef int (*fde_compare_t) (struct object *, const fde *, const 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 (const fde *) * count;
-  if ((accu->linear = malloc (size)))
-    {
-      accu->linear->count = 0;
-      if ((accu->erratic = malloc (size)))
-       accu->erratic->count = 0;
-      return 1;
-    }
-  else
-    return 0;
-}
-
-static inline void
-fde_insert (struct fde_accumulator *accu, const 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 const fde *marker;
-  size_t count = linear->count;
-  const fde *const *chain_end = &marker;
-  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.  */
-  gcc_assert (sizeof (const fde *) == sizeof (const fde **));
-
-  for (i = 0; i < count; i++)
-    {
-      const fde *const *probe;
-
-      for (probe = chain_end;
-          probe != &marker && fde_compare (ob, linear->array[i], *probe) < 0;
-          probe = chain_end)
-       {
-         chain_end = (const fde *const*) erratic->array[probe - linear->array];
-         erratic->array[probe - linear->array] = NULL;
-       }
-      erratic->array[i] = (const 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;
-}
-
-#define SWAP(x,y) do { const fde * tmp = x; x = y; y = tmp; } while (0)
-
-/* Convert a semi-heap to a heap.  A semi-heap is a heap except possibly
-   for the first (root) node; push it down to its rightful place.  */
-
-static void
-frame_downheap (struct object *ob, fde_compare_t fde_compare, const fde **a,
-               int lo, int hi)
-{
-  int i, j;
-
-  for (i = lo, j = 2*i+1;
-       j < hi;
-       j = 2*i+1)
-    {
-      if (j+1 < hi && fde_compare (ob, a[j], a[j+1]) < 0)
-       ++j;
-
-      if (fde_compare (ob, a[i], a[j]) < 0)
-       {
-         SWAP (a[i], a[j]);
-         i = j;
-       }
-      else
-       break;
-    }
-}
-
-/* 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.  */
-  const 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].  */
-  size_t n = erratic->count;
-  int m;
-
-  /* Expand our heap incrementally from the end of the array, heapifying
-     each resulting semi-heap as we go.  After each step, a[m] is the top
-     of a heap.  */
-  for (m = n/2-1; m >= 0; --m)
-    frame_downheap (ob, fde_compare, a, m, n);
-
-  /* Shrink our heap incrementally from the end of the array, first
-     swapping out the largest element a[0] and then re-heapifying the
-     resulting semi-heap.  After each step, a[0..m) is a heap.  */
-  for (m = n-1; m >= 1; --m)
-    {
-      SWAP (a[0], a[m]);
-      frame_downheap (ob, fde_compare, a, 0, m);
-    }
-#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;
-  const 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;
-
-  gcc_assert (!accu->linear || accu->linear->count == count);
-
-  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);
-      gcc_assert (accu->linear->count + accu->erratic->count == count);
-      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);
-    }
-}
-
-\f
-/* 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, const fde *this_fde)
-{
-  const struct dwarf_cie *last_cie = 0;
-  size_t count = 0;
-  int encoding = DW_EH_PE_absptr;
-  _Unwind_Ptr base = 0;
-
-  for (; ! last_fde (ob, this_fde); this_fde = next_fde (this_fde))
-    {
-      const 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);
-         if (encoding == DW_EH_PE_omit)
-           return -1;
-         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 = (((_Unwind_Ptr) 1) << (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, const fde *this_fde)
-{
-  const struct dwarf_cie *last_cie = 0;
-  int encoding = ob->s.b.encoding;
-  _Unwind_Ptr base = base_from_object (ob->s.b.encoding, ob);
-
-  for (; ! last_fde (ob, this_fde); this_fde = next_fde (this_fde))
-    {
-      const 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)
-       {
-         _Unwind_Ptr ptr;
-         memcpy (&ptr, this_fde->pc_begin, sizeof (_Unwind_Ptr));
-         if (ptr == 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 = (((_Unwind_Ptr) 1) << (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)
-           {
-             size_t cur_count = classify_object_over_fdes (ob, *p);
-             if (cur_count == (size_t) -1)
-               goto unhandled_fdes;
-             count += cur_count;
-           }
-       }
-      else
-       {
-         count = classify_object_over_fdes (ob, ob->u.single);
-         if (count == (size_t) -1)
-           {
-             static const fde terminator;
-           unhandled_fdes:
-             ob->s.i = 0;
-             ob->s.b.encoding = DW_EH_PE_omit;
-             ob->u.single = &terminator;
-             return;
-           }
-       }
-
-      /* 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 const fde *
-linear_search_fdes (struct object *ob, const fde *this_fde, void *pc)
-{
-  const struct dwarf_cie *last_cie = 0;
-  int encoding = ob->s.b.encoding;
-  _Unwind_Ptr base = base_from_object (ob->s.b.encoding, ob);
-
-  for (; ! last_fde (ob, this_fde); this_fde = next_fde (this_fde))
-    {
-      const 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)
-       {
-         const _Unwind_Ptr *pc_array = (const _Unwind_Ptr *) this_fde->pc_begin;
-         pc_begin = pc_array[0];
-         pc_range = pc_array[1];
-         if (pc_begin == 0)
-           continue;
-       }
-      else
-       {
-         _Unwind_Ptr mask;
-         const unsigned 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 = (((_Unwind_Ptr) 1) << (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 const 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;
-      const fde *const f = vec->array[i];
-      void *pc_begin;
-      uaddr pc_range;
-      memcpy (&pc_begin, (const void * const *) f->pc_begin, sizeof (void *));
-      memcpy (&pc_range, (const uaddr *) f->pc_begin + 1, sizeof (uaddr));
-
-      if (pc < pc_begin)
-       hi = i;
-      else if (pc >= pc_begin + pc_range)
-       lo = i + 1;
-      else
-       return f;
-    }
-
-  return NULL;
-}
-
-static inline const 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;
-      const fde *f = vec->array[i];
-      _Unwind_Ptr pc_begin, pc_range;
-      const unsigned 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 const 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;
-      const fde *f = vec->array[i];
-      _Unwind_Ptr pc_begin, pc_range;
-      const unsigned 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 const 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 laborious linear search, cos we've no memory.  */
-      if (ob->s.b.from_array)
-       {
-         fde **p;
-         for (p = ob->u.array; *p ; p++)
-           {
-             const fde *f = linear_search_fdes (ob, *p, pc);
-             if (f)
-               return f;
-           }
-         return NULL;
-       }
-      else
-       return linear_search_fdes (ob, ob->u.single, pc);
-    }
-}
-
-const fde *
-_Unwind_Find_FDE (void *pc, struct dwarf_eh_bases *bases)
-{
-  struct object *ob;
-  const 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 descending, 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;
-      _Unwind_Ptr func;
-
-      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, &func);
-      bases->func = (void *) func;
-    }
-
-  return f;
-}
diff --git a/gcc/unwind-dw2-fde.h b/gcc/unwind-dw2-fde.h
deleted file mode 100644 (file)
index 6d7a8de..0000000
+++ /dev/null
@@ -1,183 +0,0 @@
-/* Subroutines needed for unwinding stack frames for exception handling.  */
-/* Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2004, 2009
-   Free Software Foundation, Inc.
-   Contributed by Jason Merrill <jason@cygnus.com>.
-
-This file is part of GCC.
-
-GCC 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 3, or (at your option) any later
-version.
-
-GCC 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.
-
-Under Section 7 of GPL version 3, you are granted additional
-permissions described in the GCC Runtime Library Exception, version
-3.1, as published by the Free Software Foundation.
-
-You should have received a copy of the GNU General Public License and
-a copy of the GCC Runtime Library Exception along with this program;
-see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
-<http://www.gnu.org/licenses/>.  */
-
-#ifndef GCC_UNWIND_DW2_FDE_H
-#define GCC_UNWIND_DW2_FDE_H
-
-#ifndef HIDE_EXPORTS
-#pragma GCC visibility push(default)
-#endif
-
-struct fde_vector
-{
-  const void *orig_data;
-  size_t count;
-  const struct dwarf_fde *array[];
-};
-
-struct object
-{
-  void *pc_begin;
-  void *tbase;
-  void *dbase;
-  union {
-    const 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;
-
-#ifdef DWARF2_OBJECT_END_PTR_EXTENSION
-  char *fde_end;
-#endif
-
-  struct object *next;
-};
-
-/* 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 (const void *, struct object *,
-                                        void *, void *);
-extern void __register_frame_info (const 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 (const void *);
-extern void *__deregister_frame_info_bases (const void *);
-extern void __deregister_frame (void *);
-
-\f
-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 specification, 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[];
-} __attribute__ ((packed, aligned (__alignof__ (void *))));
-
-/* The first few fields of an FDE.  */
-struct dwarf_fde
-{
-  uword length;
-  sword CIE_delta;
-  unsigned char pc_begin[];
-} __attribute__ ((packed, aligned (__alignof__ (void *))));
-
-typedef struct dwarf_fde fde;
-
-/* Locate the CIE for a given FDE.  */
-
-static inline const struct dwarf_cie *
-get_cie (const struct dwarf_fde *f)
-{
-  return (const void *)&f->CIE_delta - f->CIE_delta;
-}
-
-static inline const fde *
-next_fde (const fde *f)
-{
-  return (const fde *) ((const char *) f + f->length + sizeof (f->length));
-}
-
-extern const fde * _Unwind_Find_FDE (void *, struct dwarf_eh_bases *);
-
-static inline int
-last_fde (struct object *obj __attribute__ ((__unused__)), const fde *f)
-{
-#ifdef DWARF2_OBJECT_END_PTR_EXTENSION
-  return (char *)f == obj->fde_end || f->length == 0;
-#else
-  return f->length == 0;
-#endif
-}
-
-#ifndef HIDE_EXPORTS
-#pragma GCC visibility pop
-#endif
-
-#endif /* unwind-dw2-fde.h */
diff --git a/gcc/unwind-dw2.c b/gcc/unwind-dw2.c
deleted file mode 100644 (file)
index 19da299..0000000
+++ /dev/null
@@ -1,1611 +0,0 @@
-/* DWARF2 exception handling and frame unwind runtime interface routines.
-   Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006,
-   2008, 2009, 2010, 2011  Free Software Foundation, Inc.
-
-   This file is part of GCC.
-
-   GCC 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 3, or (at your option)
-   any later version.
-
-   GCC 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.
-
-   Under Section 7 of GPL version 3, you are granted additional
-   permissions described in the GCC Runtime Library Exception, version
-   3.1, as published by the Free Software Foundation.
-
-   You should have received a copy of the GNU General Public License and
-   a copy of the GCC Runtime Library Exception along with this program;
-   see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
-   <http://www.gnu.org/licenses/>.  */
-
-#include "tconfig.h"
-#include "tsystem.h"
-#include "coretypes.h"
-#include "tm.h"
-#include "dwarf2.h"
-#include "unwind.h"
-#ifdef __USING_SJLJ_EXCEPTIONS__
-# define NO_SIZE_OF_ENCODED_VALUE
-#endif
-#include "unwind-pe.h"
-#include "unwind-dw2-fde.h"
-#include "gthr.h"
-#include "unwind-dw2.h"
-
-#ifdef HAVE_SYS_SDT_H
-#include <sys/sdt.h>
-#endif
-
-#ifndef __USING_SJLJ_EXCEPTIONS__
-
-#ifndef STACK_GROWS_DOWNWARD
-#define STACK_GROWS_DOWNWARD 0
-#else
-#undef STACK_GROWS_DOWNWARD
-#define STACK_GROWS_DOWNWARD 1
-#endif
-
-/* Dwarf frame registers used for pre gcc 3.0 compiled glibc.  */
-#ifndef PRE_GCC3_DWARF_FRAME_REGISTERS
-#define PRE_GCC3_DWARF_FRAME_REGISTERS DWARF_FRAME_REGISTERS
-#endif
-
-#ifndef DWARF_REG_TO_UNWIND_COLUMN
-#define DWARF_REG_TO_UNWIND_COLUMN(REGNO) (REGNO)
-#endif
-
-/* This is the register and unwind state for a particular frame.  This
-   provides the information necessary to unwind up past a frame and return
-   to its caller.  */
-struct _Unwind_Context
-{
-  void *reg[DWARF_FRAME_REGISTERS+1];
-  void *cfa;
-  void *ra;
-  void *lsda;
-  struct dwarf_eh_bases bases;
-  /* Signal frame context.  */
-#define SIGNAL_FRAME_BIT ((~(_Unwind_Word) 0 >> 1) + 1)
-  /* Context which has version/args_size/by_value fields.  */
-#define EXTENDED_CONTEXT_BIT ((~(_Unwind_Word) 0 >> 2) + 1)
-  _Unwind_Word flags;
-  /* 0 for now, can be increased when further fields are added to
-     struct _Unwind_Context.  */
-  _Unwind_Word version;
-  _Unwind_Word args_size;
-  char by_value[DWARF_FRAME_REGISTERS+1];
-};
-
-/* Byte size of every register managed by these routines.  */
-static unsigned char dwarf_reg_size_table[DWARF_FRAME_REGISTERS+1];
-
-\f
-/* 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 void uw_update_context (struct _Unwind_Context *, _Unwind_FrameState *);
-static _Unwind_Reason_Code uw_frame_state_for (struct _Unwind_Context *,
-                                              _Unwind_FrameState *);
-
-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; }
-\f
-static inline _Unwind_Word
-_Unwind_IsSignalFrame (struct _Unwind_Context *context)
-{
-  return (context->flags & SIGNAL_FRAME_BIT) ? 1 : 0;
-}
-
-static inline void
-_Unwind_SetSignalFrame (struct _Unwind_Context *context, int val)
-{
-  if (val)
-    context->flags |= SIGNAL_FRAME_BIT;
-  else
-    context->flags &= ~SIGNAL_FRAME_BIT;
-}
-
-static inline _Unwind_Word
-_Unwind_IsExtendedContext (struct _Unwind_Context *context)
-{
-  return context->flags & EXTENDED_CONTEXT_BIT;
-}
-\f
-/* Get the value of register INDEX as saved in CONTEXT.  */
-
-inline _Unwind_Word
-_Unwind_GetGR (struct _Unwind_Context *context, int index)
-{
-  int size;
-  void *ptr;
-
-#ifdef DWARF_ZERO_REG
-  if (index == DWARF_ZERO_REG)
-    return 0;
-#endif
-
-  index = DWARF_REG_TO_UNWIND_COLUMN (index);
-  gcc_assert (index < (int) sizeof(dwarf_reg_size_table));
-  size = dwarf_reg_size_table[index];
-  ptr = context->reg[index];
-
-  if (_Unwind_IsExtendedContext (context) && context->by_value[index])
-    return (_Unwind_Word) (_Unwind_Internal_Ptr) ptr;
-
-  /* This will segfault if the register hasn't been saved.  */
-  if (size == sizeof(_Unwind_Ptr))
-    return * (_Unwind_Ptr *) ptr;
-  else
-    {
-      gcc_assert (size == sizeof(_Unwind_Word));
-      return * (_Unwind_Word *) ptr;
-    }
-}
-
-static inline void *
-_Unwind_GetPtr (struct _Unwind_Context *context, int index)
-{
-  return (void *)(_Unwind_Ptr) _Unwind_GetGR (context, index);
-}
-
-/* Get the value of the CFA as saved in CONTEXT.  */
-
-_Unwind_Word
-_Unwind_GetCFA (struct _Unwind_Context *context)
-{
-  return (_Unwind_Ptr) context->cfa;
-}
-
-/* Overwrite the saved value for register INDEX in CONTEXT with VAL.  */
-
-inline void
-_Unwind_SetGR (struct _Unwind_Context *context, int index, _Unwind_Word val)
-{
-  int size;
-  void *ptr;
-
-  index = DWARF_REG_TO_UNWIND_COLUMN (index);
-  gcc_assert (index < (int) sizeof(dwarf_reg_size_table));
-  size = dwarf_reg_size_table[index];
-
-  if (_Unwind_IsExtendedContext (context) && context->by_value[index])
-    {
-      context->reg[index] = (void *) (_Unwind_Internal_Ptr) val;
-      return;
-    }
-
-  ptr = context->reg[index];
-
-  if (size == sizeof(_Unwind_Ptr))
-    * (_Unwind_Ptr *) ptr = val;
-  else
-    {
-      gcc_assert (size == sizeof(_Unwind_Word));
-      * (_Unwind_Word *) ptr = val;
-    }
-}
-
-/* Get the pointer to a register INDEX as saved in CONTEXT.  */
-
-static inline void *
-_Unwind_GetGRPtr (struct _Unwind_Context *context, int index)
-{
-  index = DWARF_REG_TO_UNWIND_COLUMN (index);
-  if (_Unwind_IsExtendedContext (context) && context->by_value[index])
-    return &context->reg[index];
-  return context->reg[index];
-}
-
-/* Set the pointer to a register INDEX as saved in CONTEXT.  */
-
-static inline void
-_Unwind_SetGRPtr (struct _Unwind_Context *context, int index, void *p)
-{
-  index = DWARF_REG_TO_UNWIND_COLUMN (index);
-  if (_Unwind_IsExtendedContext (context))
-    context->by_value[index] = 0;
-  context->reg[index] = p;
-}
-
-/* Overwrite the saved value for register INDEX in CONTEXT with VAL.  */
-
-static inline void
-_Unwind_SetGRValue (struct _Unwind_Context *context, int index,
-                   _Unwind_Word val)
-{
-  index = DWARF_REG_TO_UNWIND_COLUMN (index);
-  gcc_assert (index < (int) sizeof(dwarf_reg_size_table));
-  gcc_assert (dwarf_reg_size_table[index] == sizeof (_Unwind_Ptr));
-
-  context->by_value[index] = 1;
-  context->reg[index] = (void *) (_Unwind_Internal_Ptr) val;
-}
-
-/* Return nonzero if register INDEX is stored by value rather than
-   by reference.  */
-
-static inline int
-_Unwind_GRByValue (struct _Unwind_Context *context, int index)
-{
-  index = DWARF_REG_TO_UNWIND_COLUMN (index);
-  return context->by_value[index];
-}
-
-/* Retrieve the return address for CONTEXT.  */
-
-inline _Unwind_Ptr
-_Unwind_GetIP (struct _Unwind_Context *context)
-{
-  return (_Unwind_Ptr) context->ra;
-}
-
-/* Retrieve the return address and flag whether that IP is before
-   or after first not yet fully executed instruction.  */
-
-inline _Unwind_Ptr
-_Unwind_GetIPInfo (struct _Unwind_Context *context, int *ip_before_insn)
-{
-  *ip_before_insn = _Unwind_IsSignalFrame (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;
-}
-
-void *
-_Unwind_FindEnclosingFunction (void *pc)
-{
-  struct dwarf_eh_bases bases;
-  const struct dwarf_fde *fde = _Unwind_Find_FDE (pc-1, &bases);
-  if (fde)
-    return bases.func;
-  else
-    return NULL;
-}
-
-#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
-
-#include "md-unwind-support.h"
-\f
-/* 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 (const struct dwarf_cie *cie, struct _Unwind_Context *context,
-                 _Unwind_FrameState *fs)
-{
-  const unsigned char *aug = cie->augmentation;
-  const unsigned char *p = aug + strlen ((const char *)aug) + 1;
-  const unsigned char *ret = NULL;
-  _uleb128_t utmp;
-  _sleb128_t stmp;
-
-  /* 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;
-    }
-
-  /* After the augmentation resp. pointer for "eh" augmentation
-     follows for CIE version >= 4 address size byte and
-     segment size byte.  */
-  if (__builtin_expect (cie->version >= 4, 0))
-    {
-      if (p[0] != sizeof (void *) || p[1] != 0)
-       return NULL;
-      p += 2;
-    }
-  /* Immediately following this are the code and
-     data alignment and return address column.  */
-  p = read_uleb128 (p, &utmp);
-  fs->code_align = (_Unwind_Word)utmp;
-  p = read_sleb128 (p, &stmp);
-  fs->data_align = (_Unwind_Sword)stmp;
-  if (cie->version == 1)
-    fs->retaddr_column = *p++;
-  else
-    {
-      p = read_uleb128 (p, &utmp);
-      fs->retaddr_column = (_Unwind_Word)utmp;
-    }
-  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, &utmp);
-      ret = p + utmp;
-
-      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')
-       {
-         _Unwind_Ptr personality;
-
-         p = read_encoded_value (context, *p, p + 1, &personality);
-         fs->personality = (_Unwind_Personality_Fn) personality;
-         aug += 1;
-       }
-
-      /* "S" indicates a signal frame.  */
-      else if (aug[0] == 'S')
-       {
-         fs->signal_frame = 1;
-         aug += 1;
-       }
-
-      /* Otherwise we have an unknown augmentation string.
-        Bail unless we saw a 'z' prefix.  */
-      else
-       return ret;
-    }
-
-  return ret ? ret : p;
-}
-
-
-/* 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;
-      _uleb128_t reg, utmp;
-      _sleb128_t offset, stmp;
-
-      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_GNU_encoded_addr:
-         {
-           _Unwind_Ptr presult;
-           op_ptr = read_encoded_value (context, *op_ptr, op_ptr+1, &presult);
-           result = presult;
-         }
-         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, &utmp);
-         result = (_Unwind_Word)utmp;
-         break;
-       case DW_OP_consts:
-         op_ptr = read_sleb128 (op_ptr, &stmp);
-         result = (_Unwind_Sword)stmp;
-         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, &reg);
-         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, &offset);
-         result = _Unwind_GetGR (context, op - DW_OP_breg0) + offset;
-         break;
-       case DW_OP_bregx:
-         op_ptr = read_uleb128 (op_ptr, &reg);
-         op_ptr = read_sleb128 (op_ptr, &offset);
-         result = _Unwind_GetGR (context, reg) + (_Unwind_Word)offset;
-         break;
-
-       case DW_OP_dup:
-         gcc_assert (stack_elt);
-         result = stack[stack_elt - 1];
-         break;
-
-       case DW_OP_drop:
-         gcc_assert (stack_elt);
-         stack_elt -= 1;
-         goto no_push;
-
-       case DW_OP_pick:
-         offset = *op_ptr++;
-         gcc_assert (offset < stack_elt - 1);
-         result = stack[stack_elt - 1 - offset];
-         break;
-
-       case DW_OP_over:
-         gcc_assert (stack_elt >= 2);
-         result = stack[stack_elt - 2];
-         break;
-
-       case DW_OP_swap:
-         {
-           _Unwind_Word t;
-           gcc_assert (stack_elt >= 2);
-           t = stack[stack_elt - 1];
-           stack[stack_elt - 1] = stack[stack_elt - 2];
-           stack[stack_elt - 2] = t;
-           goto no_push;
-         }
-
-       case DW_OP_rot:
-         {
-           _Unwind_Word t1, t2, t3;
-
-           gcc_assert (stack_elt >= 3);
-           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.  */
-         gcc_assert (stack_elt);
-         stack_elt -= 1;
-
-         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:
-                   gcc_unreachable ();
-                 }
-             }
-             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, &utmp);
-             result += (_Unwind_Word)utmp;
-             break;
-
-           default:
-             gcc_unreachable ();
-           }
-         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_shl:
-       case DW_OP_shr:
-       case DW_OP_shra:
-       case DW_OP_xor:
-       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;
-           gcc_assert (stack_elt >= 2);
-           stack_elt -= 2;
-
-           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 = second % 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) second <= (_Unwind_Sword) first;
-               break;
-             case DW_OP_ge:
-               result = (_Unwind_Sword) second >= (_Unwind_Sword) first;
-               break;
-             case DW_OP_eq:
-               result = (_Unwind_Sword) second == (_Unwind_Sword) first;
-               break;
-             case DW_OP_lt:
-               result = (_Unwind_Sword) second < (_Unwind_Sword) first;
-               break;
-             case DW_OP_gt:
-               result = (_Unwind_Sword) second > (_Unwind_Sword) first;
-               break;
-             case DW_OP_ne:
-               result = (_Unwind_Sword) second != (_Unwind_Sword) first;
-               break;
-
-             default:
-               gcc_unreachable ();
-             }
-         }
-         break;
-
-       case DW_OP_skip:
-         offset = read_2s (op_ptr);
-         op_ptr += 2;
-         op_ptr += offset;
-         goto no_push;
-
-       case DW_OP_bra:
-         gcc_assert (stack_elt);
-         stack_elt -= 1;
-
-         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:
-         gcc_unreachable ();
-       }
-
-      /* Most things push a result value.  */
-      gcc_assert ((size_t) stack_elt < sizeof(stack)/sizeof(*stack));
-      stack[stack_elt++] = result;
-    no_push:;
-    }
-
-  /* We were executing this program to get a value.  It should be
-     at top of stack.  */
-  gcc_assert (stack_elt);
-  stack_elt -= 1;
-  return stack[stack_elt];
-}
-
-
-/* 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;
-
-  /* The comparison with the return address uses < rather than <= because
-     we are only interested in the effects of code before the call; for a
-     noreturn function, the return address may point to unrelated code with
-     a different stack configuration that we are not interested in.  We
-     assume that the call itself is unwind info-neutral; if not, or if
-     there are delay instructions that adjust the stack, these must be
-     reflected at the point immediately before the call insn.
-     In signal frames, return address is after last completed instruction,
-     so we add 1 to return address to make the comparison <=.  */
-  while (insn_ptr < insn_end
-        && fs->pc < context->ra + _Unwind_IsSignalFrame (context))
-    {
-      unsigned char insn = *insn_ptr++;
-      _uleb128_t reg, utmp;
-      _sleb128_t offset, stmp;
-
-      if ((insn & 0xc0) == DW_CFA_advance_loc)
-       fs->pc += (insn & 0x3f) * fs->code_align;
-      else if ((insn & 0xc0) == DW_CFA_offset)
-       {
-         reg = insn & 0x3f;
-         insn_ptr = read_uleb128 (insn_ptr, &utmp);
-         offset = (_Unwind_Sword) utmp * fs->data_align;
-         fs->regs.reg[DWARF_REG_TO_UNWIND_COLUMN (reg)].how
-           = REG_SAVED_OFFSET;
-         fs->regs.reg[DWARF_REG_TO_UNWIND_COLUMN (reg)].loc.offset = offset;
-       }
-      else if ((insn & 0xc0) == DW_CFA_restore)
-       {
-         reg = insn & 0x3f;
-         fs->regs.reg[DWARF_REG_TO_UNWIND_COLUMN (reg)].how = REG_UNSAVED;
-       }
-      else switch (insn)
-       {
-       case DW_CFA_set_loc:
-         {
-           _Unwind_Ptr pc;
-
-           insn_ptr = read_encoded_value (context, fs->fde_encoding,
-                                          insn_ptr, &pc);
-           fs->pc = (void *) 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, &reg);
-         insn_ptr = read_uleb128 (insn_ptr, &utmp);
-         offset = (_Unwind_Sword) utmp * fs->data_align;
-         fs->regs.reg[DWARF_REG_TO_UNWIND_COLUMN (reg)].how
-           = REG_SAVED_OFFSET;
-         fs->regs.reg[DWARF_REG_TO_UNWIND_COLUMN (reg)].loc.offset = offset;
-         break;
-
-       case DW_CFA_restore_extended:
-         insn_ptr = read_uleb128 (insn_ptr, &reg);
-         /* FIXME, this is wrong; the CIE might have said that the
-            register was saved somewhere.  */
-         fs->regs.reg[DWARF_REG_TO_UNWIND_COLUMN(reg)].how = REG_UNSAVED;
-         break;
-
-       case DW_CFA_same_value:
-         insn_ptr = read_uleb128 (insn_ptr, &reg);
-         fs->regs.reg[DWARF_REG_TO_UNWIND_COLUMN(reg)].how = REG_UNSAVED;
-         break;
-
-       case DW_CFA_undefined:
-         insn_ptr = read_uleb128 (insn_ptr, &reg);
-         fs->regs.reg[DWARF_REG_TO_UNWIND_COLUMN(reg)].how = REG_UNDEFINED;
-         break;
-
-       case DW_CFA_nop:
-         break;
-
-       case DW_CFA_register:
-         {
-           _uleb128_t reg2;
-           insn_ptr = read_uleb128 (insn_ptr, &reg);
-           insn_ptr = read_uleb128 (insn_ptr, &reg2);
-           fs->regs.reg[DWARF_REG_TO_UNWIND_COLUMN (reg)].how = REG_SAVED_REG;
-           fs->regs.reg[DWARF_REG_TO_UNWIND_COLUMN (reg)].loc.reg =
-             (_Unwind_Word)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, &utmp);
-         fs->regs.cfa_reg = (_Unwind_Word)utmp;
-         insn_ptr = read_uleb128 (insn_ptr, &utmp);
-         fs->regs.cfa_offset = (_Unwind_Word)utmp;
-         fs->regs.cfa_how = CFA_REG_OFFSET;
-         break;
-
-       case DW_CFA_def_cfa_register:
-         insn_ptr = read_uleb128 (insn_ptr, &utmp);
-         fs->regs.cfa_reg = (_Unwind_Word)utmp;
-         fs->regs.cfa_how = CFA_REG_OFFSET;
-         break;
-
-       case DW_CFA_def_cfa_offset:
-         insn_ptr = read_uleb128 (insn_ptr, &utmp);
-         fs->regs.cfa_offset = utmp;
-         /* cfa_how deliberately not set.  */
-         break;
-
-       case DW_CFA_def_cfa_expression:
-         fs->regs.cfa_exp = insn_ptr;
-         fs->regs.cfa_how = CFA_EXP;
-         insn_ptr = read_uleb128 (insn_ptr, &utmp);
-         insn_ptr += utmp;
-         break;
-
-       case DW_CFA_expression:
-         insn_ptr = read_uleb128 (insn_ptr, &reg);
-         fs->regs.reg[DWARF_REG_TO_UNWIND_COLUMN (reg)].how = REG_SAVED_EXP;
-         fs->regs.reg[DWARF_REG_TO_UNWIND_COLUMN (reg)].loc.exp = insn_ptr;
-         insn_ptr = read_uleb128 (insn_ptr, &utmp);
-         insn_ptr += utmp;
-         break;
-
-         /* Dwarf3.  */
-       case DW_CFA_offset_extended_sf:
-         insn_ptr = read_uleb128 (insn_ptr, &reg);
-         insn_ptr = read_sleb128 (insn_ptr, &stmp);
-         offset = stmp * fs->data_align;
-         fs->regs.reg[DWARF_REG_TO_UNWIND_COLUMN (reg)].how
-           = REG_SAVED_OFFSET;
-         fs->regs.reg[DWARF_REG_TO_UNWIND_COLUMN (reg)].loc.offset = offset;
-         break;
-
-       case DW_CFA_def_cfa_sf:
-         insn_ptr = read_uleb128 (insn_ptr, &utmp);
-         fs->regs.cfa_reg = (_Unwind_Word)utmp;
-         insn_ptr = read_sleb128 (insn_ptr, &stmp);
-         fs->regs.cfa_offset = (_Unwind_Sword)stmp;
-         fs->regs.cfa_how = CFA_REG_OFFSET;
-         fs->regs.cfa_offset *= fs->data_align;
-         break;
-
-       case DW_CFA_def_cfa_offset_sf:
-         insn_ptr = read_sleb128 (insn_ptr, &stmp);
-         fs->regs.cfa_offset = (_Unwind_Sword)stmp;
-         fs->regs.cfa_offset *= fs->data_align;
-         /* cfa_how deliberately not set.  */
-         break;
-
-       case DW_CFA_val_offset:
-         insn_ptr = read_uleb128 (insn_ptr, &reg);
-         insn_ptr = read_uleb128 (insn_ptr, &utmp);
-         offset = (_Unwind_Sword) utmp * fs->data_align;
-         fs->regs.reg[DWARF_REG_TO_UNWIND_COLUMN (reg)].how
-           = REG_SAVED_VAL_OFFSET;
-         fs->regs.reg[DWARF_REG_TO_UNWIND_COLUMN (reg)].loc.offset = offset;
-         break;
-
-       case DW_CFA_val_offset_sf:
-         insn_ptr = read_uleb128 (insn_ptr, &reg);
-         insn_ptr = read_sleb128 (insn_ptr, &stmp);
-         offset = stmp * fs->data_align;
-         fs->regs.reg[DWARF_REG_TO_UNWIND_COLUMN (reg)].how
-           = REG_SAVED_VAL_OFFSET;
-         fs->regs.reg[DWARF_REG_TO_UNWIND_COLUMN (reg)].loc.offset = offset;
-         break;
-
-       case DW_CFA_val_expression:
-         insn_ptr = read_uleb128 (insn_ptr, &reg);
-         fs->regs.reg[DWARF_REG_TO_UNWIND_COLUMN (reg)].how
-           = REG_SAVED_VAL_EXP;
-         fs->regs.reg[DWARF_REG_TO_UNWIND_COLUMN (reg)].loc.exp = insn_ptr;
-         insn_ptr = read_uleb128 (insn_ptr, &utmp);
-         insn_ptr += utmp;
-         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, &utmp);
-         context->args_size = (_Unwind_Word)utmp;
-         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, &reg);
-         insn_ptr = read_uleb128 (insn_ptr, &utmp);
-         offset = (_Unwind_Word) utmp * fs->data_align;
-         fs->regs.reg[DWARF_REG_TO_UNWIND_COLUMN (reg)].how
-           = REG_SAVED_OFFSET;
-         fs->regs.reg[DWARF_REG_TO_UNWIND_COLUMN (reg)].loc.offset = -offset;
-         break;
-
-       default:
-         gcc_unreachable ();
-       }
-    }
-}
-\f
-/* Given the _Unwind_Context CONTEXT for a stack frame, look up the FDE for
-   its caller and decode it into FS.  This function also sets the
-   args_size and lsda members of CONTEXT, as they are really information
-   about the caller's frame.  */
-
-static _Unwind_Reason_Code
-uw_frame_state_for (struct _Unwind_Context *context, _Unwind_FrameState *fs)
-{
-  const struct dwarf_fde *fde;
-  const struct dwarf_cie *cie;
-  const unsigned char *aug, *insn, *end;
-
-  memset (fs, 0, sizeof (*fs));
-  context->args_size = 0;
-  context->lsda = 0;
-
-  if (context->ra == 0)
-    return _URC_END_OF_STACK;
-
-  fde = _Unwind_Find_FDE (context->ra + _Unwind_IsSignalFrame (context) - 1,
-                         &context->bases);
-  if (fde == NULL)
-    {
-#ifdef MD_FALLBACK_FRAME_STATE_FOR
-      /* Couldn't find frame unwind info for this function.  Try a
-        target-specific fallback mechanism.  This will necessarily
-        not provide a personality routine or LSDA.  */
-      return MD_FALLBACK_FRAME_STATE_FOR (context, fs);
-#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 = (const unsigned char *) next_fde ((const struct dwarf_fde *) cie);
-  execute_cfa_program (insn, end, context, fs);
-
-  /* Locate augmentation for the fde.  */
-  aug = (const unsigned char *) fde + sizeof (*fde);
-  aug += 2 * size_of_encoded_value (fs->fde_encoding);
-  insn = NULL;
-  if (fs->saw_z)
-    {
-      _uleb128_t i;
-      aug = read_uleb128 (aug, &i);
-      insn = aug + i;
-    }
-  if (fs->lsda_encoding != DW_EH_PE_omit)
-    {
-      _Unwind_Ptr lsda;
-
-      aug = read_encoded_value (context, fs->lsda_encoding, aug, &lsda);
-      context->lsda = (void *) lsda;
-    }
-
-  /* Then the insns in the FDE up to our target PC.  */
-  if (insn == NULL)
-    insn = aug;
-  end = (const unsigned char *) next_fde (fde);
-  execute_cfa_program (insn, end, context, fs);
-
-  return _URC_NO_REASON;
-}
-\f
-typedef struct frame_state
-{
-  void *cfa;
-  void *eh_ptr;
-  long cfa_offset;
-  long args_size;
-  long reg_or_offset[PRE_GCC3_DWARF_FRAME_REGISTERS+1];
-  unsigned short cfa_reg;
-  unsigned short retaddr_column;
-  char saved[PRE_GCC3_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.flags = EXTENDED_CONTEXT_BIT;
-  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.regs.cfa_how == CFA_EXP)
-    return 0;
-
-  for (reg = 0; reg < PRE_GCC3_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.regs.cfa_offset;
-  state_in->cfa_reg = fs.regs.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;
-}
-\f
-typedef union { _Unwind_Ptr ptr; _Unwind_Word word; } _Unwind_SpTmp;
-
-static inline void
-_Unwind_SetSpColumn (struct _Unwind_Context *context, void *cfa,
-                    _Unwind_SpTmp *tmp_sp)
-{
-  int size = dwarf_reg_size_table[__builtin_dwarf_sp_column ()];
-
-  if (size == sizeof(_Unwind_Ptr))
-    tmp_sp->ptr = (_Unwind_Ptr) cfa;
-  else
-    {
-      gcc_assert (size == sizeof(_Unwind_Word));
-      tmp_sp->word = (_Unwind_Ptr) cfa;
-    }
-  _Unwind_SetGRPtr (context, __builtin_dwarf_sp_column (), tmp_sp);
-}
-
-static void
-uw_update_context_1 (struct _Unwind_Context *context, _Unwind_FrameState *fs)
-{
-  struct _Unwind_Context orig_context = *context;
-  void *cfa;
-  long i;
-
-#ifdef EH_RETURN_STACKADJ_RTX
-  /* 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.
-
-     In very special situations (such as unwind info for signal return),
-     there may be location expressions that use the stack pointer as well.
-
-     Do this conditionally for one frame.  This allows the unwind info
-     for one frame to save a copy of the stack pointer from the previous
-     frame, and be able to use much easier CFA mechanisms to do it.
-     Always zap the saved stack pointer value for the next frame; carrying
-     the value over from one frame to another doesn't make sense.  */
-
-  _Unwind_SpTmp tmp_sp;
-
-  if (!_Unwind_GetGRPtr (&orig_context, __builtin_dwarf_sp_column ()))
-    _Unwind_SetSpColumn (&orig_context, context->cfa, &tmp_sp);
-  _Unwind_SetGRPtr (context, __builtin_dwarf_sp_column (), NULL);
-#endif
-
-  /* Compute this frame's CFA.  */
-  switch (fs->regs.cfa_how)
-    {
-    case CFA_REG_OFFSET:
-      cfa = _Unwind_GetPtr (&orig_context, fs->regs.cfa_reg);
-      cfa += fs->regs.cfa_offset;
-      break;
-
-    case CFA_EXP:
-      {
-       const unsigned char *exp = fs->regs.cfa_exp;
-       _uleb128_t len;
-
-       exp = read_uleb128 (exp, &len);
-       cfa = (void *) (_Unwind_Ptr)
-         execute_stack_op (exp, exp + len, &orig_context, 0);
-       break;
-      }
-
-    default:
-      gcc_unreachable ();
-    }
-  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:
-      case REG_UNDEFINED:
-       break;
-
-      case REG_SAVED_OFFSET:
-       _Unwind_SetGRPtr (context, i,
-                         (void *) (cfa + fs->regs.reg[i].loc.offset));
-       break;
-
-      case REG_SAVED_REG:
-       if (_Unwind_GRByValue (&orig_context, fs->regs.reg[i].loc.reg))
-         _Unwind_SetGRValue (context, i,
-                             _Unwind_GetGR (&orig_context,
-                                            fs->regs.reg[i].loc.reg));
-       else
-         _Unwind_SetGRPtr (context, i,
-                           _Unwind_GetGRPtr (&orig_context,
-                                             fs->regs.reg[i].loc.reg));
-       break;
-
-      case REG_SAVED_EXP:
-       {
-         const unsigned char *exp = fs->regs.reg[i].loc.exp;
-         _uleb128_t len;
-         _Unwind_Ptr val;
-
-         exp = read_uleb128 (exp, &len);
-         val = execute_stack_op (exp, exp + len, &orig_context,
-                                 (_Unwind_Ptr) cfa);
-         _Unwind_SetGRPtr (context, i, (void *) val);
-       }
-       break;
-
-      case REG_SAVED_VAL_OFFSET:
-       _Unwind_SetGRValue (context, i,
-                           (_Unwind_Internal_Ptr)
-                           (cfa + fs->regs.reg[i].loc.offset));
-       break;
-
-      case REG_SAVED_VAL_EXP:
-       {
-         const unsigned char *exp = fs->regs.reg[i].loc.exp;
-         _uleb128_t len;
-         _Unwind_Ptr val;
-
-         exp = read_uleb128 (exp, &len);
-         val = execute_stack_op (exp, exp + len, &orig_context,
-                                 (_Unwind_Ptr) cfa);
-         _Unwind_SetGRValue (context, i, val);
-       }
-       break;
-      }
-
-  _Unwind_SetSignalFrame (context, fs->signal_frame);
-
-#ifdef MD_FROB_UPDATE_CONTEXT
-  MD_FROB_UPDATE_CONTEXT (context, fs);
-#endif
-}
-
-/* CONTEXT describes the unwind state for a frame, and FS describes the FDE
-   of its caller.  Update CONTEXT to refer to the caller as well.  Note
-   that the args_size and lsda members are not updated here, but later in
-   uw_frame_state_for.  */
-
-static void
-uw_update_context (struct _Unwind_Context *context, _Unwind_FrameState *fs)
-{
-  uw_update_context_1 (context, fs);
-
-  /* In general this unwinder doesn't make any distinction between
-     undefined and same_value rule.  Call-saved registers are assumed
-     to have same_value rule by default and explicit undefined
-     rule is handled like same_value.  The only exception is
-     DW_CFA_undefined on retaddr_column which is supposed to
-     mark outermost frame in DWARF 3.  */
-  if (fs->regs.reg[DWARF_REG_TO_UNWIND_COLUMN (fs->retaddr_column)].how
-      == REG_UNDEFINED)
-    /* uw_frame_state_for uses context->ra == 0 check to find outermost
-       stack frame.  */
-    context->ra = 0;
-  else
-    /* Compute the return address now, since the return address column
-       can change from frame to frame.  */
-    context->ra = __builtin_extract_return_addr
-      (_Unwind_GetPtr (context, fs->retaddr_column));
-}
-
-static void
-uw_advance_context (struct _Unwind_Context *context, _Unwind_FrameState *fs)
-{
-  uw_update_context (context, fs);
-}
-\f
-/* 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 inline void
-init_dwarf_reg_size_table (void)
-{
-  __builtin_init_dwarf_reg_size_table (dwarf_reg_size_table);
-}
-
-static void __attribute__((noinline))
-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;
-  _Unwind_SpTmp sp_slot;
-  _Unwind_Reason_Code code;
-
-  memset (context, 0, sizeof (struct _Unwind_Context));
-  context->ra = ra;
-  context->flags = EXTENDED_CONTEXT_BIT;
-
-  code = uw_frame_state_for (context, &fs);
-  gcc_assert (code == _URC_NO_REASON);
-
-#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
-
-  /* Force the frame state to use the known cfa value.  */
-  _Unwind_SetSpColumn (context, outer_cfa, &sp_slot);
-  fs.regs.cfa_how = CFA_REG_OFFSET;
-  fs.regs.cfa_reg = __builtin_dwarf_sp_column ();
-  fs.regs.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);
-}
-
-static void _Unwind_DebugHook (void *, void *)
-  __attribute__ ((__noinline__, __used__, __noclone__));
-
-/* This function is called during unwinding.  It is intended as a hook
-   for a debugger to intercept exceptions.  CFA is the CFA of the
-   target frame.  HANDLER is the PC to which control will be
-   transferred.  */
-static void
-_Unwind_DebugHook (void *cfa __attribute__ ((__unused__)),
-                  void *handler __attribute__ ((__unused__)))
-{
-  /* We only want to use stap probes starting with v3.  Earlier
-     versions added too much startup cost.  */
-#if defined (HAVE_SYS_SDT_H) && defined (STAP_PROBE2) && _SDT_NOTE_TYPE >= 3
-  STAP_PROBE2 (libgcc, unwind, cfa, handler);
-#else
-  asm ("");
-#endif
-}
-
-/* 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);       \
-      _Unwind_DebugHook ((TARGET)->cfa, handler);                      \
-      __builtin_eh_return (offset, handler);                           \
-    }                                                                  \
-  while (0)
-
-static long
-uw_install_context_1 (struct _Unwind_Context *current,
-                     struct _Unwind_Context *target)
-{
-  long i;
-  _Unwind_SpTmp sp_slot;
-
-  /* If the target frame does not have a saved stack pointer,
-     then set up the target's CFA.  */
-  if (!_Unwind_GetGRPtr (target, __builtin_dwarf_sp_column ()))
-    _Unwind_SetSpColumn (target, target->cfa, &sp_slot);
-
-  for (i = 0; i < DWARF_FRAME_REGISTERS; ++i)
-    {
-      void *c = current->reg[i];
-      void *t = target->reg[i];
-
-      gcc_assert (current->by_value[i] == 0);
-      if (target->by_value[i] && c)
-       {
-         _Unwind_Word w;
-         _Unwind_Ptr p;
-         if (dwarf_reg_size_table[i] == sizeof (_Unwind_Word))
-           {
-             w = (_Unwind_Internal_Ptr) t;
-             memcpy (c, &w, sizeof (_Unwind_Word));
-           }
-         else
-           {
-             gcc_assert (dwarf_reg_size_table[i] == sizeof (_Unwind_Ptr));
-             p = (_Unwind_Internal_Ptr) t;
-             memcpy (c, &p, sizeof (_Unwind_Ptr));
-           }
-       }
-      else if (t && c && t != c)
-       memcpy (c, t, dwarf_reg_size_table[i]);
-    }
-
-  /* If the current frame doesn't have a saved stack pointer, then we
-     need to rely on EH_RETURN_STACKADJ_RTX to get our target stack
-     pointer value reloaded.  */
-  if (!_Unwind_GetGRPtr (current, __builtin_dwarf_sp_column ()))
-    {
-      void *target_cfa;
-
-      target_cfa = _Unwind_GetPtr (target, __builtin_dwarf_sp_column ());
-
-      /* 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;
-    }
-  return 0;
-}
-
-static inline _Unwind_Ptr
-uw_identify_context (struct _Unwind_Context *context)
-{
-  /* The CFA is not sufficient to disambiguate the context of a function
-     interrupted by a signal before establishing its frame and the context
-     of the signal itself.  */
-  if (STACK_GROWS_DOWNWARD)
-    return _Unwind_GetCFA (context) - _Unwind_IsSignalFrame (context);
-  else
-    return _Unwind_GetCFA (context) + _Unwind_IsSignalFrame (context);
-}
-
-
-#include "unwind.inc"
-
-#if defined (USE_GAS_SYMVER) && defined (SHARED) && defined (USE_LIBUNWIND_EXCEPTIONS)
-alias (_Unwind_Backtrace);
-alias (_Unwind_DeleteException);
-alias (_Unwind_FindEnclosingFunction);
-alias (_Unwind_ForcedUnwind);
-alias (_Unwind_GetDataRelBase);
-alias (_Unwind_GetTextRelBase);
-alias (_Unwind_GetCFA);
-alias (_Unwind_GetGR);
-alias (_Unwind_GetIP);
-alias (_Unwind_GetLanguageSpecificData);
-alias (_Unwind_GetRegionStart);
-alias (_Unwind_RaiseException);
-alias (_Unwind_Resume);
-alias (_Unwind_Resume_or_Rethrow);
-alias (_Unwind_SetGR);
-alias (_Unwind_SetIP);
-#endif
-
-#endif /* !USING_SJLJ_EXCEPTIONS */
diff --git a/gcc/unwind-dw2.h b/gcc/unwind-dw2.h
deleted file mode 100644 (file)
index 2c558b4..0000000
+++ /dev/null
@@ -1,87 +0,0 @@
-/* DWARF2 frame unwind data structure.
-   Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2009
-   Free Software Foundation, Inc.
-
-   This file is part of GCC.
-
-   GCC 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 3, or (at your option)
-   any later version.
-
-   GCC 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.
-
-   Under Section 7 of GPL version 3, you are granted additional
-   permissions described in the GCC Runtime Library Exception, version
-   3.1, as published by the Free Software Foundation.
-
-   You should have received a copy of the GNU General Public License and
-   a copy of the GCC Runtime Library Exception along with this program;
-   see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
-   <http://www.gnu.org/licenses/>.  */
-
-/* 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
-
-/* 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 {
-       _Unwind_Word reg;
-       _Unwind_Sword offset;
-       const unsigned char *exp;
-      } loc;
-      enum {
-       REG_UNSAVED,
-       REG_SAVED_OFFSET,
-       REG_SAVED_REG,
-       REG_SAVED_EXP,
-       REG_SAVED_VAL_OFFSET,
-       REG_SAVED_VAL_EXP,
-       REG_UNDEFINED
-      } how;
-    } reg[DWARF_FRAME_REGISTERS+1];
-
-    /* Used to implement DW_CFA_remember_state.  */
-    struct frame_state_reg_info *prev;
-
-    /* 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;
-  } regs;
-
-  /* The PC described by the current frame state.  */
-  void *pc;
-
-  /* The information we care about from the CIE/FDE.  */
-  _Unwind_Personality_Fn personality;
-  _Unwind_Sword data_align;
-  _Unwind_Word code_align;
-  _Unwind_Word retaddr_column;
-  unsigned char fde_encoding;
-  unsigned char lsda_encoding;
-  unsigned char saw_z;
-  unsigned char signal_frame;
-  void *eh_ptr;
-} _Unwind_FrameState;
-
diff --git a/gcc/unwind-generic.h b/gcc/unwind-generic.h
deleted file mode 100644 (file)
index 4ff9017..0000000
+++ /dev/null
@@ -1,276 +0,0 @@
-/* Exception handling and frame unwind runtime interface routines.
-   Copyright (C) 2001, 2003, 2004, 2006, 2008, 2009 Free Software Foundation, Inc.
-
-   This file is part of GCC.
-
-   GCC 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 3, or (at your option)
-   any later version.
-
-   GCC 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.
-
-   Under Section 7 of GPL version 3, you are granted additional
-   permissions described in the GCC Runtime Library Exception, version
-   3.1, as published by the Free Software Foundation.
-
-   You should have received a copy of the GNU General Public License and
-   a copy of the GCC Runtime Library Exception along with this program;
-   see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
-   <http://www.gnu.org/licenses/>.  */
-
-/* This is derived from the C++ ABI for IA-64.  Where we diverge
-   for cross-architecture compatibility are noted with "@@@".  */
-
-#ifndef _UNWIND_H
-#define _UNWIND_H
-
-#ifndef HIDE_EXPORTS
-#pragma GCC visibility push(default)
-#endif
-
-#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__(__unwind_word__)));
-typedef signed _Unwind_Sword __attribute__((__mode__(__unwind_word__)));
-#if defined(__ia64__) && defined(__hpux__)
-typedef unsigned _Unwind_Ptr __attribute__((__mode__(__word__)));
-#else
-typedef unsigned _Unwind_Ptr __attribute__((__mode__(__pointer__)));
-#endif
-typedef unsigned _Unwind_Internal_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
-#define _UA_END_OF_STACK       16
-
-/* The target can override this macro to define any back-end-specific
-   attributes required for the lowest-level stack frame.  */
-#ifndef LIBGCC2_UNWIND_ATTRIBUTE
-#define LIBGCC2_UNWIND_ATTRIBUTE
-#endif
-
-/* 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 LIBGCC2_UNWIND_ATTRIBUTE
-_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 LIBGCC2_UNWIND_ATTRIBUTE
-_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 LIBGCC2_UNWIND_ATTRIBUTE
-_Unwind_Resume (struct _Unwind_Exception *);
-
-/* @@@ Resume propagation of a FORCE_UNWIND exception, or to rethrow
-   a normal exception that was handled.  */
-extern _Unwind_Reason_Code LIBGCC2_UNWIND_ATTRIBUTE
-_Unwind_Resume_or_Rethrow (struct _Unwind_Exception *);
-
-/* @@@ Use unwind data to perform a stack backtrace.  The trace callback
-   is called for every stack frame in the call chain, but no cleanup
-   actions are performed.  */
-typedef _Unwind_Reason_Code (*_Unwind_Trace_Fn)
-     (struct _Unwind_Context *, void *);
-
-extern _Unwind_Reason_Code LIBGCC2_UNWIND_ATTRIBUTE
-_Unwind_Backtrace (_Unwind_Trace_Fn, void *);
-
-/* 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 may be 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 _Unwind_Ptr _Unwind_GetIPInfo (struct _Unwind_Context *, int *);
-extern void _Unwind_SetIP (struct _Unwind_Context *, _Unwind_Ptr);
-
-/* @@@ Retrieve the CFA of the given context.  */
-extern _Unwind_Word _Unwind_GetCFA (struct _Unwind_Context *);
-
-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 LIBGCC2_UNWIND_ATTRIBUTE
-_Unwind_SjLj_RaiseException (struct _Unwind_Exception *);
-extern _Unwind_Reason_Code LIBGCC2_UNWIND_ATTRIBUTE
-_Unwind_SjLj_ForcedUnwind (struct _Unwind_Exception *, _Unwind_Stop_Fn, void *);
-extern void LIBGCC2_UNWIND_ATTRIBUTE
-_Unwind_SjLj_Resume (struct _Unwind_Exception *);
-extern _Unwind_Reason_Code LIBGCC2_UNWIND_ATTRIBUTE
-_Unwind_SjLj_Resume_or_Rethrow (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 __attribute__ ((__unused__)))
-{
-  abort ();
-  return 0;
-}
-
-/* @@@ Retrieve the Backing Store Pointer of the given context.  */
-extern _Unwind_Word _Unwind_GetBSP (struct _Unwind_Context *);
-#else
-extern _Unwind_Ptr _Unwind_GetDataRelBase (struct _Unwind_Context *);
-extern _Unwind_Ptr _Unwind_GetTextRelBase (struct _Unwind_Context *);
-#endif
-
-/* @@@ Given an address, return the entry point of the function that
-   contains it.  */
-extern void * _Unwind_FindEnclosingFunction (void *pc);
-
-#ifndef __SIZEOF_LONG__
-  #error "__SIZEOF_LONG__ macro not defined"
-#endif
-
-#ifndef __SIZEOF_POINTER__
-  #error "__SIZEOF_POINTER__ macro not defined"
-#endif
-
-
-/* leb128 type numbers have a potentially unlimited size.
-   The target of the following definitions of _sleb128_t and _uleb128_t
-   is to have efficient data types large enough to hold the leb128 type
-   numbers used in the unwind code.
-   Mostly these types will simply be defined to long and unsigned long
-   except when a unsigned long data type on the target machine is not
-   capable of storing a pointer.  */
-
-#if __SIZEOF_LONG__ >= __SIZEOF_POINTER__
-  typedef long _sleb128_t;
-  typedef unsigned long _uleb128_t;
-#elif __SIZEOF_LONG_LONG__ >= __SIZEOF_POINTER__
-  typedef long long _sleb128_t;
-  typedef unsigned long long _uleb128_t;
-#else
-# error "What type shall we use for _sleb128_t?"
-#endif
-
-#ifdef __cplusplus
-}
-#endif
-
-#ifndef HIDE_EXPORTS
-#pragma GCC visibility pop
-#endif
-
-#endif /* unwind.h */
diff --git a/gcc/unwind-pe.h b/gcc/unwind-pe.h
deleted file mode 100644 (file)
index 121f877..0000000
+++ /dev/null
@@ -1,289 +0,0 @@
-/* Exception handling and frame unwind runtime interface routines.
-   Copyright (C) 2001, 2002, 2003, 2004, 2008, 2009 Free Software Foundation, Inc.
-
-   This file is part of GCC.
-
-   GCC 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 3, or (at your option)
-   any later version.
-
-   GCC 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.
-
-   Under Section 7 of GPL version 3, you are granted additional
-   permissions described in the GCC Runtime Library Exception, version
-   3.1, as published by the Free Software Foundation.
-
-   You should have received a copy of the GNU General Public License and
-   a copy of the GCC Runtime Library Exception along with this program;
-   see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
-   <http://www.gnu.org/licenses/>.  */
-
-/* @@@ 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.  */
-
-#ifndef GCC_UNWIND_PE_H
-#define GCC_UNWIND_PE_H
-
-/* 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
-\f
-
-#ifndef NO_SIZE_OF_ENCODED_VALUE
-
-/* 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.  */
-
-static unsigned int
-size_of_encoded_value (unsigned char encoding) __attribute__ ((unused));
-
-static unsigned int
-size_of_encoded_value (unsigned char encoding)
-{
-  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
-
-/* Read an unsigned leb128 value from P, store the value in VAL, return
-   P incremented past the value.  We assume that a word is large enough to
-   hold any value so encoded; if it is smaller than a pointer on some target,
-   pointers should not be leb128 encoded on that target.  */
-
-static const unsigned char *
-read_uleb128 (const unsigned char *p, _uleb128_t *val)
-{
-  unsigned int shift = 0;
-  unsigned char byte;
-  _uleb128_t result;
-
-  result = 0;
-  do
-    {
-      byte = *p++;
-      result |= ((_uleb128_t)byte & 0x7f) << shift;
-      shift += 7;
-    }
-  while (byte & 0x80);
-
-  *val = result;
-  return p;
-}
-
-/* Similar, but read a signed leb128 value.  */
-
-static const unsigned char *
-read_sleb128 (const unsigned char *p, _sleb128_t *val)
-{
-  unsigned int shift = 0;
-  unsigned char byte;
-  _uleb128_t result;
-
-  result = 0;
-  do
-    {
-      byte = *p++;
-      result |= ((_uleb128_t)byte & 0x7f) << shift;
-      shift += 7;
-    }
-  while (byte & 0x80);
-
-  /* Sign-extend a negative value.  */
-  if (shift < 8 * sizeof(result) && (byte & 0x40) != 0)
-    result |= -(((_uleb128_t)1L) << shift);
-
-  *val = (_sleb128_t) result;
-  return p;
-}
-
-/* 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.  */
-
-static const unsigned char *
-read_encoded_value_with_base (unsigned char encoding, _Unwind_Ptr base,
-                             const unsigned char *p, _Unwind_Ptr *val)
-{
-  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__));
-
-  const union unaligned *u = (const union unaligned *) p;
-  _Unwind_Internal_Ptr result;
-
-  if (encoding == DW_EH_PE_aligned)
-    {
-      _Unwind_Internal_Ptr a = (_Unwind_Internal_Ptr) p;
-      a = (a + sizeof (void *) - 1) & - sizeof(void *);
-      result = *(_Unwind_Internal_Ptr *) a;
-      p = (const unsigned char *) (_Unwind_Internal_Ptr) (a + sizeof (void *));
-    }
-  else
-    {
-      switch (encoding & 0x0f)
-       {
-       case DW_EH_PE_absptr:
-         result = (_Unwind_Internal_Ptr) u->ptr;
-         p += sizeof (void *);
-         break;
-
-       case DW_EH_PE_uleb128:
-         {
-           _uleb128_t tmp;
-           p = read_uleb128 (p, &tmp);
-           result = (_Unwind_Internal_Ptr) tmp;
-         }
-         break;
-
-       case DW_EH_PE_sleb128:
-         {
-           _sleb128_t tmp;
-           p = read_sleb128 (p, &tmp);
-           result = (_Unwind_Internal_Ptr) tmp;
-         }
-         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_Internal_Ptr) u : base);
-         if (encoding & DW_EH_PE_indirect)
-           result = *(_Unwind_Internal_Ptr *) result;
-       }
-    }
-
-  *val = result;
-  return p;
-}
-
-#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
-
-#endif /* unwind-pe.h */
diff --git a/gcc/unwind-sjlj.c b/gcc/unwind-sjlj.c
deleted file mode 100644 (file)
index c71e798..0000000
+++ /dev/null
@@ -1,326 +0,0 @@
-/* SJLJ exception handling and frame unwind runtime interface routines.
-   Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2006,
-   2009  Free Software Foundation, Inc.
-
-   This file is part of GCC.
-
-   GCC 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 3, or (at your option)
-   any later version.
-
-   GCC 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.
-
-   Under Section 7 of GPL version 3, you are granted additional
-   permissions described in the GCC Runtime Library Exception, version
-   3.1, as published by the Free Software Foundation.
-
-   You should have received a copy of the GNU General Public License and
-   a copy of the GCC Runtime Library Exception along with this program;
-   see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
-   <http://www.gnu.org/licenses/>.  */
-
-#include "tconfig.h"
-#include "tsystem.h"
-#include "coretypes.h"
-#include "tm.h"
-#include "unwind.h"
-#include "gthr.h"
-
-#ifdef __USING_SJLJ_EXCEPTIONS__
-
-#ifdef DONT_USE_BUILTIN_SETJMP
-#ifndef inhibit_libc
-#include <setjmp.h>
-#else
-typedef void *jmp_buf[JMP_BUF_SIZE];
-extern void longjmp(jmp_buf, int) __attribute__((noreturn));
-#endif
-#else
-#define longjmp __builtin_longjmp
-#endif
-
-/* The setjmp side is dealt with in the except.c file.  */
-#undef setjmp
-#define setjmp setjmp_should_not_be_used_in_this_file
-
-
-/* This structure is allocated on the stack of the target function.
-   This must match the definition created in except.c:init_eh.  */
-struct SjLj_Function_Context
-{
-  /* This is the chain through all registered contexts.  It is
-     filled in by _Unwind_SjLj_Register.  */
-  struct SjLj_Function_Context *prev;
-
-  /* This is assigned in by the target function before every call
-     to the index of the call site in the lsda.  It is assigned by
-     the personality routine to the landing pad index.  */
-  int call_site;
-
-  /* This is how data is returned from the personality routine to
-     the target function's handler.  */
-  _Unwind_Word data[4];
-
-  /* These are filled in once by the target function before any
-     exceptions are expected to be handled.  */
-  _Unwind_Personality_Fn personality;
-  void *lsda;
-
-#ifdef DONT_USE_BUILTIN_SETJMP
-  /* We don't know what sort of alignment requirements the system
-     jmp_buf has.  We over estimated in except.c, and now we have
-     to match that here just in case the system *didn't* have more
-     restrictive requirements.  */
-  jmp_buf jbuf __attribute__((aligned));
-#else
-  void *jbuf[];
-#endif
-};
-
-struct _Unwind_Context
-{
-  struct SjLj_Function_Context *fc;
-};
-
-typedef struct
-{
-  _Unwind_Personality_Fn personality;
-} _Unwind_FrameState;
-
-\f
-/* Manage the chain of registered function contexts.  */
-
-/* Single threaded fallback chain.  */
-static struct SjLj_Function_Context *fc_static;
-
-#if __GTHREADS
-static __gthread_key_t fc_key;
-static int use_fc_key = -1;
-
-static void
-fc_key_init (void)
-{
-  use_fc_key = __gthread_key_create (&fc_key, 0) == 0;
-}
-
-static void
-fc_key_init_once (void)
-{
-  static __gthread_once_t once = __GTHREAD_ONCE_INIT;
-  if (__gthread_once (&once, fc_key_init) != 0 || use_fc_key < 0)
-    use_fc_key = 0;
-}
-#endif
-
-void
-_Unwind_SjLj_Register (struct SjLj_Function_Context *fc)
-{
-#if __GTHREADS
-  if (use_fc_key < 0)
-    fc_key_init_once ();
-
-  if (use_fc_key)
-    {
-      fc->prev = __gthread_getspecific (fc_key);
-      __gthread_setspecific (fc_key, fc);
-    }
-  else
-#endif
-    {
-      fc->prev = fc_static;
-      fc_static = fc;
-    }
-}
-
-static inline struct SjLj_Function_Context *
-_Unwind_SjLj_GetContext (void)
-{
-#if __GTHREADS
-  if (use_fc_key < 0)
-    fc_key_init_once ();
-
-  if (use_fc_key)
-    return __gthread_getspecific (fc_key);
-#endif
-  return fc_static;
-}
-
-static inline void
-_Unwind_SjLj_SetContext (struct SjLj_Function_Context *fc)
-{
-#if __GTHREADS
-  if (use_fc_key < 0)
-    fc_key_init_once ();
-
-  if (use_fc_key)
-    __gthread_setspecific (fc_key, fc);
-  else
-#endif
-    fc_static = fc;
-}
-
-void
-_Unwind_SjLj_Unregister (struct SjLj_Function_Context *fc)
-{
-  _Unwind_SjLj_SetContext (fc->prev);
-}
-
-\f
-/* Get/set the return data value at INDEX in CONTEXT.  */
-
-_Unwind_Word
-_Unwind_GetGR (struct _Unwind_Context *context, int index)
-{
-  return context->fc->data[index];
-}
-
-/* Get the value of the CFA as saved in CONTEXT.  */
-
-_Unwind_Word
-_Unwind_GetCFA (struct _Unwind_Context *context __attribute__((unused)))
-{
-  /* ??? Ideally __builtin_setjmp places the CFA in the jmpbuf.  */
-
-#ifndef DONT_USE_BUILTIN_SETJMP
-  /* This is a crude imitation of the CFA: the saved stack pointer.
-     This is roughly the CFA of the frame before CONTEXT.  When using the
-     DWARF-2 unwinder _Unwind_GetCFA returns the CFA of the frame described
-     by CONTEXT instead; but for DWARF-2 the cleanups associated with
-     CONTEXT have already been run, and for SJLJ they have not yet been.  */
-  if (context->fc != NULL)
-    return (_Unwind_Word) context->fc->jbuf[2];
-#endif
-
-  /* Otherwise we're out of luck for now.  */
-  return (_Unwind_Word) 0;
-}
-
-void
-_Unwind_SetGR (struct _Unwind_Context *context, int index, _Unwind_Word val)
-{
-  context->fc->data[index] = val;
-}
-
-/* Get the call-site index as saved in CONTEXT.  */
-
-_Unwind_Ptr
-_Unwind_GetIP (struct _Unwind_Context *context)
-{
-  return context->fc->call_site + 1;
-}
-
-_Unwind_Ptr
-_Unwind_GetIPInfo (struct _Unwind_Context *context, int *ip_before_insn)
-{
-  *ip_before_insn = 0;
-  if (context->fc != NULL)
-    return context->fc->call_site + 1;
-  else
-    return 0;
-}
-
-/* Set the return landing pad index in CONTEXT.  */
-
-void
-_Unwind_SetIP (struct _Unwind_Context *context, _Unwind_Ptr val)
-{
-  context->fc->call_site = val - 1;
-}
-
-void *
-_Unwind_GetLanguageSpecificData (struct _Unwind_Context *context)
-{
-  return context->fc->lsda;
-}
-
-_Unwind_Ptr
-_Unwind_GetRegionStart (struct _Unwind_Context *context __attribute__((unused)) )
-{
-  return 0;
-}
-
-void *
-_Unwind_FindEnclosingFunction (void *pc __attribute__((unused)))
-{
-  return NULL;
-}
-
-#ifndef __ia64__
-_Unwind_Ptr
-_Unwind_GetDataRelBase (struct _Unwind_Context *context __attribute__((unused)) )
-{
-  return 0;
-}
-
-_Unwind_Ptr
-_Unwind_GetTextRelBase (struct _Unwind_Context *context __attribute__((unused)) )
-{
-  return 0;
-}
-#endif
-\f
-static inline _Unwind_Reason_Code
-uw_frame_state_for (struct _Unwind_Context *context, _Unwind_FrameState *fs)
-{
-  if (context->fc == NULL)
-    {
-      fs->personality = NULL;
-      return _URC_END_OF_STACK;
-    }
-  else
-    {
-      fs->personality = context->fc->personality;
-      return _URC_NO_REASON;
-    }
-}
-
-static inline void
-uw_update_context (struct _Unwind_Context *context,
-                  _Unwind_FrameState *fs __attribute__((unused)) )
-{
-  context->fc = context->fc->prev;
-}
-
-static void
-uw_advance_context (struct _Unwind_Context *context, _Unwind_FrameState *fs)
-{
-  _Unwind_SjLj_Unregister (context->fc);
-  uw_update_context (context, fs);
-}
-
-static inline void
-uw_init_context (struct _Unwind_Context *context)
-{
-  context->fc = _Unwind_SjLj_GetContext ();
-}
-
-static void __attribute__((noreturn))
-uw_install_context (struct _Unwind_Context *current __attribute__((unused)),
-                    struct _Unwind_Context *target)
-{
-  _Unwind_SjLj_SetContext (target->fc);
-  longjmp (target->fc->jbuf, 1);
-}
-
-static inline _Unwind_Ptr
-uw_identify_context (struct _Unwind_Context *context)
-{
-  return (_Unwind_Ptr) context->fc;
-}
-
-
-/* Play games with unwind symbols so that we can have call frame
-   and sjlj symbols in the same shared library.  Not that you can
-   use them simultaneously...  */
-#define _Unwind_RaiseException         _Unwind_SjLj_RaiseException
-#define _Unwind_ForcedUnwind           _Unwind_SjLj_ForcedUnwind
-#define _Unwind_Resume                 _Unwind_SjLj_Resume
-#define _Unwind_Resume_or_Rethrow      _Unwind_SjLj_Resume_or_Rethrow
-
-#include "unwind.inc"
-
-#endif /* USING_SJLJ_EXCEPTIONS */
diff --git a/gcc/unwind.inc b/gcc/unwind.inc
deleted file mode 100644 (file)
index 5e2ec29..0000000
+++ /dev/null
@@ -1,307 +0,0 @@
-/* Exception handling and frame unwind runtime interface routines. -*- C -*-
-   Copyright (C) 2001, 2003, 2008, 2009 Free Software Foundation, Inc.
-
-   This file is part of GCC.
-
-   GCC 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 3, or (at your option)
-   any later version.
-
-   GCC 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.
-
-   Under Section 7 of GPL version 3, you are granted additional
-   permissions described in the GCC Runtime Library Exception, version
-   3.1, as published by the Free Software Foundation.
-
-   You should have received a copy of the GNU General Public License and
-   a copy of the GCC Runtime Library Exception along with this program;
-   see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
-   <http://www.gnu.org/licenses/>.  */
-
-/* This is derived from the C++ ABI for IA-64.  Where we diverge
-   for cross-architecture compatibility are noted with "@@@".  
-   This file is included from unwind-dw2.c, unwind-sjlj.c or
-   unwind-ia64.c.  */
-
-/* Subroutine of _Unwind_RaiseException also invoked from _Unwind_Resume. 
-
-   Unwind the stack calling the personality routine to find both the
-   exception handler and intermediary cleanup code.  We'll only locate
-   the first such frame here.  Cleanup code will call back into
-   _Unwind_Resume and we'll continue Phase 2 there.  */
-
-static _Unwind_Reason_Code
-_Unwind_RaiseException_Phase2(struct _Unwind_Exception *exc,
-                             struct _Unwind_Context *context)
-{
-  _Unwind_Reason_Code code;
-
-  while (1)
-    {
-      _Unwind_FrameState fs;
-      int match_handler;
-
-      code = uw_frame_state_for (context, &fs);
-
-      /* Identify when we've reached the designated handler context.  */
-      match_handler = (uw_identify_context (context) == exc->private_2
-                      ? _UA_HANDLER_FRAME : 0);
-
-      if (code != _URC_NO_REASON)
-       /* Some error encountered.  Usually the unwinder doesn't
-          diagnose these and merely crashes.  */
-       return _URC_FATAL_PHASE2_ERROR;
-
-      /* Unwind successful.  Run the personality routine, if any.  */
-      if (fs.personality)
-       {
-         code = (*fs.personality) (1, _UA_CLEANUP_PHASE | match_handler,
-                                   exc->exception_class, exc, context);
-         if (code == _URC_INSTALL_CONTEXT)
-           break;
-         if (code != _URC_CONTINUE_UNWIND) 
-           return _URC_FATAL_PHASE2_ERROR;
-       }
-
-      /* Don't let us unwind past the handler context.  */
-      gcc_assert (!match_handler);
-
-      uw_update_context (context, &fs);
-    }
-
-  return code;
-}
-
-/* Raise an exception, passing along the given exception object.  */
-
-_Unwind_Reason_Code LIBGCC2_UNWIND_ATTRIBUTE
-_Unwind_RaiseException(struct _Unwind_Exception *exc)
-{
-  struct _Unwind_Context this_context, cur_context;
-  _Unwind_Reason_Code code;
-
-  /* Set up this_context to describe the current stack frame.  */
-  uw_init_context (&this_context);
-  cur_context = this_context;
-
-  /* Phase 1: Search.  Unwind the stack, calling the personality routine
-     with the _UA_SEARCH_PHASE flag set.  Do not modify the stack yet.  */
-  while (1)
-    {
-      _Unwind_FrameState fs;
-
-      /* Set up fs to describe the FDE for the caller of cur_context.  The
-        first time through the loop, that means __cxa_throw.  */
-      code = uw_frame_state_for (&cur_context, &fs);
-
-      if (code == _URC_END_OF_STACK)
-       /* Hit end of stack with no handler found.  */
-       return _URC_END_OF_STACK;
-
-      if (code != _URC_NO_REASON)
-       /* Some error encountered.  Usually the unwinder doesn't
-          diagnose these and merely crashes.  */
-       return _URC_FATAL_PHASE1_ERROR;
-
-      /* Unwind successful.  Run the personality routine, if any.  */
-      if (fs.personality)
-       {
-         code = (*fs.personality) (1, _UA_SEARCH_PHASE, exc->exception_class,
-                                   exc, &cur_context);
-         if (code == _URC_HANDLER_FOUND)
-           break;
-         else if (code != _URC_CONTINUE_UNWIND)
-           return _URC_FATAL_PHASE1_ERROR;
-       }
-
-      /* Update cur_context to describe the same frame as fs.  */
-      uw_update_context (&cur_context, &fs);
-    }
-
-  /* Indicate to _Unwind_Resume and associated subroutines that this
-     is not a forced unwind.  Further, note where we found a handler.  */
-  exc->private_1 = 0;
-  exc->private_2 = uw_identify_context (&cur_context);
-
-  cur_context = this_context;
-  code = _Unwind_RaiseException_Phase2 (exc, &cur_context);
-  if (code != _URC_INSTALL_CONTEXT)
-    return code;
-
-  uw_install_context (&this_context, &cur_context);
-}
-
-
-/* Subroutine of _Unwind_ForcedUnwind also invoked from _Unwind_Resume.  */
-
-static _Unwind_Reason_Code
-_Unwind_ForcedUnwind_Phase2 (struct _Unwind_Exception *exc,
-                            struct _Unwind_Context *context)
-{
-  _Unwind_Stop_Fn stop = (_Unwind_Stop_Fn) (_Unwind_Ptr) exc->private_1;
-  void *stop_argument = (void *) (_Unwind_Ptr) exc->private_2;
-  _Unwind_Reason_Code code, stop_code;
-
-  while (1)
-    {
-      _Unwind_FrameState fs;
-      int action;
-
-      /* Set up fs to describe the FDE for the caller of cur_context.  */
-      code = uw_frame_state_for (context, &fs);
-      if (code != _URC_NO_REASON && code != _URC_END_OF_STACK)
-       return _URC_FATAL_PHASE2_ERROR;
-
-      /* Unwind successful.  */
-      action = _UA_FORCE_UNWIND | _UA_CLEANUP_PHASE;
-      if (code == _URC_END_OF_STACK)
-       action |= _UA_END_OF_STACK;
-      stop_code = (*stop) (1, action, exc->exception_class, exc,
-                          context, stop_argument);
-      if (stop_code != _URC_NO_REASON)
-       return _URC_FATAL_PHASE2_ERROR;
-
-      /* Stop didn't want to do anything.  Invoke the personality
-        handler, if applicable, to run cleanups.  */
-      if (code == _URC_END_OF_STACK)
-       break;
-       
-      if (fs.personality)
-       {
-         code = (*fs.personality) (1, _UA_FORCE_UNWIND | _UA_CLEANUP_PHASE,
-                                   exc->exception_class, exc, context);
-         if (code == _URC_INSTALL_CONTEXT)
-           break;
-         if (code != _URC_CONTINUE_UNWIND) 
-           return _URC_FATAL_PHASE2_ERROR;
-       }
-
-      /* Update cur_context to describe the same frame as fs, and discard
-        the previous context if necessary.  */
-      uw_advance_context (context, &fs);
-    }
-
-  return code;
-}
-
-
-/* Raise an exception for forced unwinding.  */
-
-_Unwind_Reason_Code LIBGCC2_UNWIND_ATTRIBUTE
-_Unwind_ForcedUnwind (struct _Unwind_Exception *exc,
-                     _Unwind_Stop_Fn stop, void * stop_argument)
-{
-  struct _Unwind_Context this_context, cur_context;
-  _Unwind_Reason_Code code;
-
-  uw_init_context (&this_context);
-  cur_context = this_context;
-
-  exc->private_1 = (_Unwind_Ptr) stop;
-  exc->private_2 = (_Unwind_Ptr) stop_argument;
-
-  code = _Unwind_ForcedUnwind_Phase2 (exc, &cur_context);
-  if (code != _URC_INSTALL_CONTEXT)
-    return code;
-
-  uw_install_context (&this_context, &cur_context);
-}
-
-
-/* Resume propagation of an existing exception.  This is used after
-   e.g. executing cleanup code, and not to implement rethrowing.  */
-
-void LIBGCC2_UNWIND_ATTRIBUTE
-_Unwind_Resume (struct _Unwind_Exception *exc)
-{
-  struct _Unwind_Context this_context, cur_context;
-  _Unwind_Reason_Code code;
-
-  uw_init_context (&this_context);
-  cur_context = this_context;
-
-  /* Choose between continuing to process _Unwind_RaiseException
-     or _Unwind_ForcedUnwind.  */
-  if (exc->private_1 == 0)
-    code = _Unwind_RaiseException_Phase2 (exc, &cur_context);
-  else
-    code = _Unwind_ForcedUnwind_Phase2 (exc, &cur_context);
-
-  gcc_assert (code == _URC_INSTALL_CONTEXT);
-
-  uw_install_context (&this_context, &cur_context);
-}
-
-
-/* Resume propagation of an FORCE_UNWIND exception, or to rethrow
-   a normal exception that was handled.  */
-
-_Unwind_Reason_Code LIBGCC2_UNWIND_ATTRIBUTE
-_Unwind_Resume_or_Rethrow (struct _Unwind_Exception *exc)
-{
-  struct _Unwind_Context this_context, cur_context;
-  _Unwind_Reason_Code code;
-
-  /* Choose between continuing to process _Unwind_RaiseException
-     or _Unwind_ForcedUnwind.  */
-  if (exc->private_1 == 0)
-    return _Unwind_RaiseException (exc);
-
-  uw_init_context (&this_context);
-  cur_context = this_context;
-
-  code = _Unwind_ForcedUnwind_Phase2 (exc, &cur_context);
-
-  gcc_assert (code == _URC_INSTALL_CONTEXT);
-
-  uw_install_context (&this_context, &cur_context);
-}
-
-
-/* A convenience function that calls the exception_cleanup field.  */
-
-void
-_Unwind_DeleteException (struct _Unwind_Exception *exc)
-{
-  if (exc->exception_cleanup)
-    (*exc->exception_cleanup) (_URC_FOREIGN_EXCEPTION_CAUGHT, exc);
-}
-
-
-/* Perform stack backtrace through unwind data.  */
-
-_Unwind_Reason_Code LIBGCC2_UNWIND_ATTRIBUTE
-_Unwind_Backtrace(_Unwind_Trace_Fn trace, void * trace_argument)
-{
-  struct _Unwind_Context context;
-  _Unwind_Reason_Code code;
-
-  uw_init_context (&context);
-
-  while (1)
-    {
-      _Unwind_FrameState fs;
-
-      /* Set up fs to describe the FDE for the caller of context.  */
-      code = uw_frame_state_for (&context, &fs);
-      if (code != _URC_NO_REASON && code != _URC_END_OF_STACK)
-       return _URC_FATAL_PHASE1_ERROR;
-
-      /* Call trace function.  */
-      if ((*trace) (&context, trace_argument) != _URC_NO_REASON)
-       return _URC_FATAL_PHASE1_ERROR;
-
-      /* We're done at end of stack.  */       
-      if (code == _URC_END_OF_STACK)
-       break;
-
-      /* Update context to describe the same frame as fs.  */
-      uw_update_context (&context, &fs);
-    }
-
-  return code;
-}
index 322b93ec861f3db688e7818b6d2119c775e87111..65d47a80278e9766a35a39d63d279cd3f7a78f37 100644 (file)
@@ -1,3 +1,68 @@
+2011-08-05  Rainer Orth  <ro@CeBiTec.Uni-Bielefeld.DE>
+
+       * Makefile.in (LIB2ADDEH, LIB2ADDEHSTATIC, LIB2ADDEHSHARED): New
+       variables.
+       (LIBUNWIND, SHLIBUNWIND_LINK, SHLIBUNWIND_INSTALL): New variables.
+       (LIB2ADDEH, LIB2ADDEHSTATIC, LIB2ADDEHSHARED): Add $(srcdir)/emutls.c.
+       (install-unwind_h): New target.
+       (all): Depend on it.
+       * config.host (unwind_header): New variable.
+       (*-*-freebsd*): Set tmake_file to t-eh-dw2-dip.
+       (*-*-linux*, frv-*-*linux*, *-*-kfreebsd*-gnu, *-*-knetbsd*-gnu,
+       *-*-gnu*): Likewise, also for *-*-kopensolaris*-gnu.
+       (*-*-solaris2*): Add t-eh-dw2-dip to tmake_file.
+       (arm*-*-linux*): Add arm/t-bpabi for arm*-*-linux-*eabi.
+       Set unwind_header.
+       (arm*-*-uclinux*): Add arm/t-bpabi for arm*-*-uclinux*eabi.
+       Set unwind_header.
+       (arm*-*-eabi*, arm*-*-symbianelf*): Add arm/t-bpabi for
+       arm*-*-eabi*.
+       Add arm/t-symbian to tmake_file for arm*-*-symbianelf*.
+       Set unwind_header.
+       (ia64*-*-elf*): Add ia64/t-eh-ia64 to tmake_file.
+       (ia64*-*-freebsd*): Likewise.
+       (ia64*-*-linux*): Add ia64/t-glibc, ia64/t-eh-ia64, t-libunwind to
+       tmake_file.
+       Add t-libunwind-elf, ia64/t-glibc-libunwind unless
+       $with_system_libunwind.
+       (ia64*-*-hpux*): Set tmake_file.
+       (ia64-hp-*vms*): Add ia64/t-eh-ia64 to tmake_file.
+       (picochip-*-*): Set tmake_file.
+       (rs6000-ibm-aix4.[3456789]*, powerpc-ibm-aix4.[3456789]*): Set
+       md_unwind_header.
+       (rs6000-ibm-aix5.1.*, powerpc-ibm-aix5.1.*): Likewise.
+       (rs6000-ibm-aix[56789].*, powerpc-ibm-aix[56789].*): Likewise.
+       (s390x-ibm-tpf*): Add t-eh-dw2-dip to tmake_file.
+       (xtensa*-*-elf*): Set tmake_file.
+       (xtensa*-*-linux*): Likewise.
+       * configure.ac: Include ../config/unwind_ipinfo.m4.
+       Call GCC_CHECK_UNWIND_GETIPINFO.
+       Link unwind.h to $unwind_header.
+       * configure: Regenerate.
+       * emutls.c, unwind-c.c, unwind-compat.c, unwind-compat.h,
+       unwind-dw2-fde-compat.c, unwind-dw2-fde-dip.c, unwind-dw2-fde.c,
+       unwind-dw2-fde.h, unwind-dw2.c, unwind-dw2.h, unwind-generic.h,
+       unwind-pe.h, unwind-sjlj.c, unwind.inc: New files.
+       * config/unwind-dw2-fde-darwin.c: New file.
+       * config/arm/libunwind.S, config/arm/pr-support.c,
+       config/arm/t-bpabi, config/arm/t-symbian, config/arm/unwind-arm.c,
+       config/arm/unwind-arm.h,: New files.
+       * config/ia64/fde-glibc.c, config/ia64/fde-vms.c,
+       config/ia64/t-eh-ia64, config/ia64/t-glibc,
+       config/ia64/t-glibc-libunwind, config/ia64/t-hpux,
+       config/ia64/t-vms, config/ia64/unwind-ia64.c,
+       config/ia64/unwind-ia64.h: New files.
+       * config/picochip/t-picochip: New file.
+       * config/rs6000/aix-unwind.h, config/rs6000/darwin-fallback.c: New
+       files.
+       * config/rs6000/t-darwin (LIB2ADDEH): Set.
+       * config/s390/t-tpf (LIB2ADDEH): Remove.
+       * config/t-darwin (LIB2ADDEH): Set.
+       * config/t-eh-dw2-dip: New file.
+       * config/t-libunwind, config/t-libunwind-elf: New files.
+       * config/t-sol2 (LIB2ADDEH): Remove.
+       * config/xtensa/t-xtensa: New file.
+
 2011-08-02  H.J. Lu  <hongjiu.lu@intel.com>
 
        * config/i386/linux-unwind.h (RT_SIGRETURN_SYSCALL): New.
index 5f7cd629fc2791393eed9e05a59fe2a16b784c3d..c252d9a2217c3b069a355cd1f562e232cb5471e7 100644 (file)
@@ -256,6 +256,17 @@ LIBGCC_VER_GNU_PREFIX = __
 LIBGCC_VER_FIXEDPOINT_GNU_PREFIX = __
 LIBGCC_VER_SYMBOLS_PREFIX =
 
+# Additional sources to handle exceptions; overridden by targets as needed.
+LIB2ADDEH = $(srcdir)/unwind-dw2.c $(srcdir)/unwind-dw2-fde.c \
+  $(srcdir)/unwind-sjlj.c $(srcdir)/unwind-c.c
+LIB2ADDEHSTATIC = $(LIB2ADDEH)
+LIB2ADDEHSHARED = $(LIB2ADDEH)
+
+# Don't build libunwind by default.
+LIBUNWIND =
+SHLIBUNWIND_LINK =
+SHLIBUNWIND_INSTALL =
+
 tmake_file = @tmake_file@
 include $(srcdir)/empty.mk $(tmake_file)
 
@@ -316,6 +327,10 @@ endif
 
 LIB2ADD += enable-execute-stack.c
 
+LIB2ADDEH += $(srcdir)/emutls.c
+LIB2ADDEHSTATIC += $(srcdir)/emutls.c
+LIB2ADDEHSHARED += $(srcdir)/emutls.c
+
 # Library members defined in libgcc2.c.
 lib2funcs = _muldi3 _negdi2 _lshrdi3 _ashldi3 _ashrdi3 _cmpdi2 _ucmpdi2           \
            _clear_cache _trampoline __main _absvsi2 \
@@ -967,6 +982,12 @@ gcc-extra-parts:
 
 all: $(extra-parts)
 
+install-unwind_h:
+       cp unwind.h $(gcc_objdir)/include/unwind.h
+       chmod a+r $(gcc_objdir)/include/unwind.h
+
+all: install-unwind_h
+
 # Documentation targets (empty).
 .PHONY: info html dvi pdf install-info install-html install-pdf
 
index f7c1b3bd0351ff47d65b431950953bfecde74f46..db00c4c2d8c76f818b84581dfef241be79b799dc 100644 (file)
 #  tmake_file          A list of machine-description-specific
 #                      makefile-fragments, if different from
 #                      "$cpu_type/t-$cpu_type".
+#  unwind_header       The name of the header file declaring the unwind
+#                      runtime interface routines.
 
 asm_hidden_op=.hidden
 enable_execute_stack=
 extra_parts=
 tmake_file=
 md_unwind_header=no-unwind.h
+unwind_header=unwind-generic.h
 
 # Set default cpu_type so it can be updated in each machine entry.
 cpu_type=`echo ${host} | sed 's/-.*$//'`
@@ -171,8 +174,10 @@ case ${host} in
   # This is the generic ELF configuration of FreeBSD.  Later
   # machine-specific sections may refine and add to this
   # configuration.
+  tmake_file=t-eh-dw2-dip
   ;;
-*-*-linux* | frv-*-*linux* | *-*-kfreebsd*-gnu | *-*-knetbsd*-gnu | *-*-gnu*)
+*-*-linux* | frv-*-*linux* | *-*-kfreebsd*-gnu | *-*-knetbsd*-gnu | *-*-gnu* | *-*-kopensolaris*-gnu)
+  tmake_file=t-eh-dw2-dip
   extra_parts="crtbegin.o crtbeginS.o crtbeginT.o crtend.o crtendS.o"
   ;;
 *-*-netbsd*)
@@ -182,7 +187,9 @@ case ${host} in
 *-*-rtems*)
   ;;
 *-*-solaris2*)
-  tmake_file="$tmake_file t-sol2 t-slibgcc t-slibgcc-elf-ver"
+  # Unless linker support and dl_iterate_phdr are present,
+  # unwind-dw2-fde-dip.c automatically falls back to unwind-dw2-fde.c.
+  tmake_file="$tmake_file t-sol2 t-eh-dw2-dip t-slibgcc t-slibgcc-elf-ver"
   if test $with_gnu_ld = yes; then
     tmake_file="$tmake_file t-slibgcc-gld"
   else
@@ -265,14 +272,35 @@ arm*-*-netbsdelf*)
        ;;
 arm*-*-linux*)                 # ARM GNU/Linux with ELF
        tmake_file="${tmake_file} t-fixedpoint-gnu-prefix"
+       case ${host} in
+       arm*-*-linux-*eabi)
+         tmake_file="${tmake_file} arm/t-bpabi"
+         unwind_header=config/arm/unwind-arm.h
+         ;;
+       esac
        ;;
 arm*-*-uclinux*)               # ARM ucLinux
        tmake_file="${tmake_file} t-fixedpoint-gnu-prefix"
+       case ${host} in
+       arm*-*-uclinux*eabi)
+         tmake_file="${tmake_file} arm/t-bpabi"
+         unwind_header=config/arm/unwind-arm.h
+         ;;
+       esac
        ;;
 arm*-*-ecos-elf)
        ;;
 arm*-*-eabi* | arm*-*-symbianelf* )
        tmake_file="${tmake_file} t-fixedpoint-gnu-prefix"
+       case ${host} in
+       arm*-*-eabi*)
+         tmake_file="${tmake_file} arm/t-bpabi"
+         ;;
+       arm*-*-symbianelf*)
+         tmake_file="${tmake_file} arm/t-symbian"
+         ;;
+       esac
+       unwind_header=config/arm/unwind-arm.h
        ;;
 arm*-*-rtems*)
        ;;
@@ -408,21 +436,25 @@ i[34567]86-*-interix3*)
        ;;
 ia64*-*-elf*)
        extra_parts="crtbegin.o crtend.o crtbeginS.o crtendS.o crtfastmath.o"
-       tmake_file="ia64/t-ia64 t-crtfm"
+       tmake_file="ia64/t-ia64 ia64/t-eh-ia64 t-crtfm"
        ;;
 ia64*-*-freebsd*)
        extra_parts="crtbegin.o crtend.o crtbeginS.o crtendS.o crtfastmath.o"
-       tmake_file="ia64/t-ia64 t-crtfm"
+       tmake_file="ia64/t-ia64 ia64/t-eh-ia64 t-crtfm"
        ;;
 ia64*-*-linux*)
        extra_parts="crtbegin.o crtend.o crtbeginS.o crtendS.o crtfastmath.o"
-       tmake_file="ia64/t-ia64 t-crtfm t-softfp ia64/t-fprules-softfp ia64/t-softfp-compat"
+       tmake_file="ia64/t-ia64 t-crtfm t-softfp ia64/t-fprules-softfp ia64/t-softfp-compat ia64/t-glibc ia64/t-eh-ia64 t-libunwind"
+       if test x$with_system_libunwind != xyes ; then
+               tmake_file="${tmake_file} t-libunwind-elf ia64/t-glibc-libunwind"
+       fi
        md_unwind_header=ia64/linux-unwind.h
        ;;
 ia64*-*-hpux*)
+       tmake_file="ia64/t-hpux"
        ;;
 ia64-hp-*vms*)
-       tmake_file="vms/t-vms vms/t-vms64 ia64/t-vms"
+       tmake_file="vms/t-vms vms/t-vms64 ia64/t-eh-ia64 ia64/t-vms"
        md_unwind_header=ia64/vms-unwind.h
        ;;
 iq2000*-*-elf*)
@@ -522,6 +554,7 @@ moxie-*-*)
 pdp11-*-*)
        ;;
 picochip-*-*)
+       tmake_file=picochip/t-picochip
         ;;
 powerpc-*-darwin*)
        case ${host} in
@@ -574,10 +607,13 @@ powerpcle-*-eabisim*)
 powerpcle-*-eabi*)
        ;;
 rs6000-ibm-aix4.[3456789]* | powerpc-ibm-aix4.[3456789]*)
+       md_unwind_header=rs6000/aix-unwind.h
        ;;
 rs6000-ibm-aix5.1.* | powerpc-ibm-aix5.1.*)
+       md_unwind_header=rs6000/aix-unwind.h
        ;;
 rs6000-ibm-aix[56789].* | powerpc-ibm-aix[56789].*)
+       md_unwind_header=rs6000/aix-unwind.h
        ;;
 rx-*-elf)
        extra_parts="crtbegin.o crtend.o"
@@ -592,7 +628,7 @@ s390x-*-linux*)
        md_unwind_header=s390/linux-unwind.h
        ;;
 s390x-ibm-tpf*)
-       tmake_file="${tmake_file} s390/t-crtstuff s390/t-tpf"
+       tmake_file="${tmake_file} s390/t-crtstuff s390/t-tpf t-eh-dw2-dip"
        md_unwind_header=s390/tpf-unwind.h
        ;;
 score-*-elf)
@@ -674,8 +710,10 @@ vax-*-openbsd*)
 xstormy16-*-elf)
        ;;
 xtensa*-*-elf*)
+       tmake_file=xtensa/t-xtensa
        ;;
 xtensa*-*-linux*)
+       tmake_file=xtensa/t-xtensa
        md_unwind_header=xtensa/linux-unwind.h
        ;;
 am33_2.0-*-linux*)
diff --git a/libgcc/config/arm/libunwind.S b/libgcc/config/arm/libunwind.S
new file mode 100644 (file)
index 0000000..a3a19da
--- /dev/null
@@ -0,0 +1,363 @@
+/* Support functions for the unwinder.
+   Copyright (C) 2003, 2004, 2005, 2007, 2008, 2009, 2010, 2011
+   Free Software Foundation, Inc.
+   Contributed by Paul Brook
+
+   This file 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 3, or (at your option) any
+   later version.
+
+   This file 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.
+
+   Under Section 7 of GPL version 3, you are granted additional
+   permissions described in the GCC Runtime Library Exception, version
+   3.1, as published by the Free Software Foundation.
+
+   You should have received a copy of the GNU General Public License and
+   a copy of the GCC Runtime Library Exception along with this program;
+   see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+   <http://www.gnu.org/licenses/>.  */
+
+/* An executable stack is *not* required for these functions.  */
+#if defined(__ELF__) && defined(__linux__)
+.section .note.GNU-stack,"",%progbits
+.previous
+#endif
+
+#ifdef __ARM_EABI__
+/* Some attributes that are common to all routines in this file.  */
+       /* Tag_ABI_align_needed: This code does not require 8-byte
+          alignment from the caller.  */
+       /* .eabi_attribute 24, 0  -- default setting.  */
+       /* Tag_ABI_align_preserved: This code preserves 8-byte
+          alignment in any callee.  */
+       .eabi_attribute 25, 1
+#endif /* __ARM_EABI__ */
+
+#ifndef __symbian__
+
+#include "config/arm/lib1funcs.asm"
+
+.macro UNPREFIX name
+       .global SYM (\name)
+       EQUIV SYM (\name), SYM (__\name)
+.endm
+
+#if (__ARM_ARCH__ == 4)
+/* Some coprocessors require armv5.  We know this code will never be run on
+   other cpus.  Tell gas to allow armv5, but only mark the objects as armv4.
+ */
+.arch armv5t
+#ifdef __ARM_ARCH_4T__
+.object_arch armv4t
+#else
+.object_arch armv4
+#endif
+#endif
+
+#ifdef __ARM_ARCH_6M__
+
+/* r0 points to a 16-word block.  Upload these values to the actual core
+   state.  */
+FUNC_START restore_core_regs
+       mov r1, r0
+       add r1, r1, #52
+       ldmia r1!, {r3, r4, r5}
+       sub r3, r3, #4
+       mov ip, r3
+       str r5, [r3]
+       mov lr, r4
+       /* Restore r8-r11.  */
+       mov r1, r0
+       add r1, r1, #32
+       ldmia r1!, {r2, r3, r4, r5}
+       mov r8, r2
+       mov r9, r3
+       mov sl, r4
+       mov fp, r5
+       mov r1, r0
+       add r1, r1, #8
+       ldmia r1!, {r2, r3, r4, r5, r6, r7}
+       ldr r1, [r0, #4]
+       ldr r0, [r0]
+       mov sp, ip
+       pop {pc}
+       FUNC_END restore_core_regs
+       UNPREFIX restore_core_regs
+
+/* ARMV6M does not have coprocessors, so these should never be used.  */
+FUNC_START gnu_Unwind_Restore_VFP
+       RET
+
+/* Store VFR regsters d0-d15 to the address in r0.  */
+FUNC_START gnu_Unwind_Save_VFP
+       RET
+
+/* Load VFP registers d0-d15 from the address in r0.
+   Use this to load from FSTMD format.  */
+FUNC_START gnu_Unwind_Restore_VFP_D
+       RET
+
+/* Store VFP registers d0-d15 to the address in r0.
+   Use this to store in FLDMD format.  */
+FUNC_START gnu_Unwind_Save_VFP_D
+       RET
+
+/* Load VFP registers d16-d31 from the address in r0.
+   Use this to load from FSTMD (=VSTM) format.  Needs VFPv3.  */
+FUNC_START gnu_Unwind_Restore_VFP_D_16_to_31
+       RET
+
+/* Store VFP registers d16-d31 to the address in r0.
+   Use this to store in FLDMD (=VLDM) format.  Needs VFPv3.  */
+FUNC_START gnu_Unwind_Save_VFP_D_16_to_31
+       RET
+
+FUNC_START gnu_Unwind_Restore_WMMXD
+       RET
+
+FUNC_START gnu_Unwind_Save_WMMXD
+       RET
+
+FUNC_START gnu_Unwind_Restore_WMMXC
+       RET
+
+FUNC_START gnu_Unwind_Save_WMMXC
+       RET
+
+.macro  UNWIND_WRAPPER name nargs
+       FUNC_START \name
+       /* Create a phase2_vrs structure.  */
+       /* Save r0 in the PC slot so we can use it as a scratch register.  */
+       push {r0}
+       add r0, sp, #4
+       push {r0, lr} /* Push original SP and LR.  */
+       /* Make space for r8-r12.  */
+       sub sp, sp, #20
+       /* Save low registers.  */
+       push {r0, r1, r2, r3, r4, r5, r6, r7}
+       /* Save high registers.  */
+       add r0, sp, #32
+       mov r1, r8
+       mov r2, r9
+       mov r3, sl
+       mov r4, fp
+       mov r5, ip
+       stmia r0!, {r1, r2, r3, r4, r5}
+       /* Restore original low register values.  */
+       add r0, sp, #4
+       ldmia r0!, {r1, r2, r3, r4, r5}
+       /* Restore orginial r0.  */
+       ldr r0, [sp, #60]
+       str r0, [sp]
+       /* Demand-save flags, plus an extra word for alignment.  */
+       mov r3, #0
+       push {r2, r3}
+       /* Point r1 at the block.  Pass r[0..nargs) unchanged.  */
+       add r\nargs, sp, #4
+
+       bl SYM (__gnu\name)
+
+       ldr r3, [sp, #64]
+       add sp, sp, #72
+       bx r3
+
+       FUNC_END \name
+       UNPREFIX \name
+.endm
+
+#else /* !__ARM_ARCH_6M__ */
+
+/* r0 points to a 16-word block.  Upload these values to the actual core
+   state.  */
+ARM_FUNC_START restore_core_regs
+       /* We must use sp as the base register when restoring sp.  Push the
+          last 3 registers onto the top of the current stack to achieve
+          this.  */
+       add r1, r0, #52
+       ldmia r1, {r3, r4, r5}  /* {sp, lr, pc}.  */
+#if defined(__thumb2__)
+       /* Thumb-2 doesn't allow sp in a load-multiple instruction, so push
+          the target address onto the target stack.  This is safe as
+          we're always returning to somewhere further up the call stack.  */
+       mov ip, r3
+       mov lr, r4
+       str r5, [ip, #-4]!
+#elif defined(__INTERWORKING__)
+       /* Restore pc into ip.  */
+       mov r2, r5
+       stmfd sp!, {r2, r3, r4}
+#else
+       stmfd sp!, {r3, r4, r5}
+#endif
+       /* Don't bother restoring ip.  */
+       ldmia r0, {r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, sl, fp}
+#if defined(__thumb2__)
+       /* Pop the return address off the target stack.  */
+       mov sp, ip
+       pop {pc}
+#elif defined(__INTERWORKING__)
+       /* Pop the three registers we pushed earlier.  */
+       ldmfd sp, {ip, sp, lr}
+       bx ip
+#else
+       ldmfd sp, {sp, lr, pc}
+#endif
+       FUNC_END restore_core_regs
+       UNPREFIX restore_core_regs
+
+/* Load VFP registers d0-d15 from the address in r0.
+   Use this to load from FSTMX format.  */
+ARM_FUNC_START gnu_Unwind_Restore_VFP
+       /* Use the generic coprocessor form so that gas doesn't complain
+          on soft-float targets.  */
+       ldc   p11,cr0,[r0],{0x21} /* fldmiax r0, {d0-d15} */
+       RET
+
+/* Store VFP registers d0-d15 to the address in r0.
+   Use this to store in FSTMX format.  */
+ARM_FUNC_START gnu_Unwind_Save_VFP
+       /* Use the generic coprocessor form so that gas doesn't complain
+          on soft-float targets.  */
+       stc   p11,cr0,[r0],{0x21} /* fstmiax r0, {d0-d15} */
+       RET
+
+/* Load VFP registers d0-d15 from the address in r0.
+   Use this to load from FSTMD format.  */
+ARM_FUNC_START gnu_Unwind_Restore_VFP_D
+       ldc   p11,cr0,[r0],{0x20} /* fldmiad r0, {d0-d15} */
+       RET
+
+/* Store VFP registers d0-d15 to the address in r0.
+   Use this to store in FLDMD format.  */
+ARM_FUNC_START gnu_Unwind_Save_VFP_D
+       stc   p11,cr0,[r0],{0x20} /* fstmiad r0, {d0-d15} */
+       RET
+
+/* Load VFP registers d16-d31 from the address in r0.
+   Use this to load from FSTMD (=VSTM) format.  Needs VFPv3.  */
+ARM_FUNC_START gnu_Unwind_Restore_VFP_D_16_to_31
+       ldcl  p11,cr0,[r0],{0x20} /* vldm r0, {d16-d31} */
+       RET
+
+/* Store VFP registers d16-d31 to the address in r0.
+   Use this to store in FLDMD (=VLDM) format.  Needs VFPv3.  */
+ARM_FUNC_START gnu_Unwind_Save_VFP_D_16_to_31
+       stcl  p11,cr0,[r0],{0x20} /* vstm r0, {d16-d31} */
+       RET
+
+ARM_FUNC_START gnu_Unwind_Restore_WMMXD
+       /* Use the generic coprocessor form so that gas doesn't complain
+          on non-iWMMXt targets.  */
+       ldcl  p1, cr0, [r0], #8 /* wldrd wr0, [r0], #8 */
+       ldcl  p1, cr1, [r0], #8 /* wldrd wr1, [r0], #8 */
+       ldcl  p1, cr2, [r0], #8 /* wldrd wr2, [r0], #8 */
+       ldcl  p1, cr3, [r0], #8 /* wldrd wr3, [r0], #8 */
+       ldcl  p1, cr4, [r0], #8 /* wldrd wr4, [r0], #8 */
+       ldcl  p1, cr5, [r0], #8 /* wldrd wr5, [r0], #8 */
+       ldcl  p1, cr6, [r0], #8 /* wldrd wr6, [r0], #8 */
+       ldcl  p1, cr7, [r0], #8 /* wldrd wr7, [r0], #8 */
+       ldcl  p1, cr8, [r0], #8 /* wldrd wr8, [r0], #8 */
+       ldcl  p1, cr9, [r0], #8 /* wldrd wr9, [r0], #8 */
+       ldcl  p1, cr10, [r0], #8 /* wldrd wr10, [r0], #8 */
+       ldcl  p1, cr11, [r0], #8 /* wldrd wr11, [r0], #8 */
+       ldcl  p1, cr12, [r0], #8 /* wldrd wr12, [r0], #8 */
+       ldcl  p1, cr13, [r0], #8 /* wldrd wr13, [r0], #8 */
+       ldcl  p1, cr14, [r0], #8 /* wldrd wr14, [r0], #8 */
+       ldcl  p1, cr15, [r0], #8 /* wldrd wr15, [r0], #8 */
+       RET
+
+ARM_FUNC_START gnu_Unwind_Save_WMMXD
+       /* Use the generic coprocessor form so that gas doesn't complain
+          on non-iWMMXt targets.  */
+       stcl  p1, cr0, [r0], #8 /* wstrd wr0, [r0], #8 */
+       stcl  p1, cr1, [r0], #8 /* wstrd wr1, [r0], #8 */
+       stcl  p1, cr2, [r0], #8 /* wstrd wr2, [r0], #8 */
+       stcl  p1, cr3, [r0], #8 /* wstrd wr3, [r0], #8 */
+       stcl  p1, cr4, [r0], #8 /* wstrd wr4, [r0], #8 */
+       stcl  p1, cr5, [r0], #8 /* wstrd wr5, [r0], #8 */
+       stcl  p1, cr6, [r0], #8 /* wstrd wr6, [r0], #8 */
+       stcl  p1, cr7, [r0], #8 /* wstrd wr7, [r0], #8 */
+       stcl  p1, cr8, [r0], #8 /* wstrd wr8, [r0], #8 */
+       stcl  p1, cr9, [r0], #8 /* wstrd wr9, [r0], #8 */
+       stcl  p1, cr10, [r0], #8 /* wstrd wr10, [r0], #8 */
+       stcl  p1, cr11, [r0], #8 /* wstrd wr11, [r0], #8 */
+       stcl  p1, cr12, [r0], #8 /* wstrd wr12, [r0], #8 */
+       stcl  p1, cr13, [r0], #8 /* wstrd wr13, [r0], #8 */
+       stcl  p1, cr14, [r0], #8 /* wstrd wr14, [r0], #8 */
+       stcl  p1, cr15, [r0], #8 /* wstrd wr15, [r0], #8 */
+       RET
+
+ARM_FUNC_START gnu_Unwind_Restore_WMMXC
+       /* Use the generic coprocessor form so that gas doesn't complain
+          on non-iWMMXt targets.  */
+       ldc2  p1, cr8, [r0], #4 /* wldrw wcgr0, [r0], #4 */
+       ldc2  p1, cr9, [r0], #4 /* wldrw wcgr1, [r0], #4 */
+       ldc2  p1, cr10, [r0], #4 /* wldrw wcgr2, [r0], #4 */
+       ldc2  p1, cr11, [r0], #4 /* wldrw wcgr3, [r0], #4 */
+       RET
+
+ARM_FUNC_START gnu_Unwind_Save_WMMXC
+       /* Use the generic coprocessor form so that gas doesn't complain
+          on non-iWMMXt targets.  */
+       stc2  p1, cr8, [r0], #4 /* wstrw wcgr0, [r0], #4 */
+       stc2  p1, cr9, [r0], #4 /* wstrw wcgr1, [r0], #4 */
+       stc2  p1, cr10, [r0], #4 /* wstrw wcgr2, [r0], #4 */
+       stc2  p1, cr11, [r0], #4 /* wstrw wcgr3, [r0], #4 */
+       RET
+
+/* Wrappers to save core registers, then call the real routine.   */
+
+.macro  UNWIND_WRAPPER name nargs
+       ARM_FUNC_START \name
+       /* Create a phase2_vrs structure.  */
+       /* Split reg push in two to ensure the correct value for sp.  */
+#if defined(__thumb2__)
+       mov ip, sp
+       push {lr} /* PC is ignored.  */
+       push {ip, lr} /* Push original SP and LR.  */
+#else
+       stmfd sp!, {sp, lr, pc}
+#endif
+       stmfd sp!, {r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, sl, fp, ip}
+       
+       /* Demand-save flags, plus an extra word for alignment.  */
+       mov r3, #0
+       stmfd sp!, {r2, r3}
+
+       /* Point r1 at the block.  Pass r[0..nargs) unchanged.  */
+       add r\nargs, sp, #4
+#if defined(__thumb__) && !defined(__thumb2__)
+       /* Switch back to thumb mode to avoid interworking hassle.  */
+       adr ip, .L1_\name
+       orr ip, ip, #1
+       bx ip
+       .thumb
+.L1_\name:
+       bl SYM (__gnu\name) __PLT__
+       ldr r3, [sp, #64]
+       add sp, #72
+       bx r3
+#else
+       bl SYM (__gnu\name) __PLT__
+       ldr lr, [sp, #64]
+       add sp, sp, #72
+       RET
+#endif
+       FUNC_END \name
+       UNPREFIX \name
+.endm
+
+#endif /* !__ARM_ARCH_6M__ */
+
+UNWIND_WRAPPER _Unwind_RaiseException 1
+UNWIND_WRAPPER _Unwind_Resume 1
+UNWIND_WRAPPER _Unwind_Resume_or_Rethrow 1
+UNWIND_WRAPPER _Unwind_ForcedUnwind 3
+UNWIND_WRAPPER _Unwind_Backtrace 2
+
+#endif  /* ndef __symbian__ */
diff --git a/libgcc/config/arm/pr-support.c b/libgcc/config/arm/pr-support.c
new file mode 100644 (file)
index 0000000..deee661
--- /dev/null
@@ -0,0 +1,401 @@
+/* ARM EABI compliant unwinding routines
+   Copyright (C) 2004, 2005, 2009 Free Software Foundation, Inc.
+   Contributed by Paul Brook
+   This file 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 3, or (at your option) any
+   later version.
+
+   This file 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.
+
+   Under Section 7 of GPL version 3, you are granted additional
+   permissions described in the GCC Runtime Library Exception, version
+   3.1, as published by the Free Software Foundation.
+
+   You should have received a copy of the GNU General Public License and
+   a copy of the GCC Runtime Library Exception along with this program;
+   see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include "unwind.h"
+
+/* We add a prototype for abort here to avoid creating a dependency on
+   target headers.  */
+extern void abort (void);
+
+typedef struct _ZSt9type_info type_info; /* This names C++ type_info type */
+
+/* Misc constants.  */
+#define R_IP    12
+#define R_SP    13
+#define R_LR    14
+#define R_PC    15
+
+#define uint32_highbit (((_uw) 1) << 31)
+
+void __attribute__((weak)) __cxa_call_unexpected(_Unwind_Control_Block *ucbp);
+
+/* Unwind descriptors.  */
+
+typedef struct
+{
+  _uw16 length;
+  _uw16 offset;
+} EHT16;
+
+typedef struct
+{
+  _uw length;
+  _uw offset;
+} EHT32;
+
+/* Calculate the address encoded by a 31-bit self-relative offset at address
+   P.  Copy of routine in unwind-arm.c.  */
+
+static inline _uw
+selfrel_offset31 (const _uw *p)
+{
+  _uw offset;
+
+  offset = *p;
+  /* Sign extend to 32 bits.  */
+  if (offset & (1 << 30))
+    offset |= 1u << 31;
+
+  return offset + (_uw) p;
+}
+
+
+/* Personality routine helper functions.  */
+
+#define CODE_FINISH (0xb0)
+
+/* Return the next byte of unwinding information, or CODE_FINISH if there is
+   no data remaining.  */
+static inline _uw8
+next_unwind_byte (__gnu_unwind_state * uws)
+{
+  _uw8 b;
+
+  if (uws->bytes_left == 0)
+    {
+      /* Load another word */
+      if (uws->words_left == 0)
+       return CODE_FINISH; /* Nothing left.  */
+      uws->words_left--;
+      uws->data = *(uws->next++);
+      uws->bytes_left = 3;
+    }
+  else
+    uws->bytes_left--;
+
+  /* Extract the most significant byte.  */
+  b = (uws->data >> 24) & 0xff;
+  uws->data <<= 8;
+  return b;
+}
+
+/* Execute the unwinding instructions described by UWS.  */
+_Unwind_Reason_Code
+__gnu_unwind_execute (_Unwind_Context * context, __gnu_unwind_state * uws)
+{
+  _uw op;
+  int set_pc;
+  _uw reg;
+
+  set_pc = 0;
+  for (;;)
+    {
+      op = next_unwind_byte (uws);
+      if (op == CODE_FINISH)
+       {
+         /* If we haven't already set pc then copy it from lr.  */
+         if (!set_pc)
+           {
+             _Unwind_VRS_Get (context, _UVRSC_CORE, R_LR, _UVRSD_UINT32,
+                              &reg);
+             _Unwind_VRS_Set (context, _UVRSC_CORE, R_PC, _UVRSD_UINT32,
+                              &reg);
+             set_pc = 1;
+           }
+         /* Drop out of the loop.  */
+         break;
+       }
+      if ((op & 0x80) == 0)
+       {
+         /* vsp = vsp +- (imm6 << 2 + 4).  */
+         _uw offset;
+
+         offset = ((op & 0x3f) << 2) + 4;
+         _Unwind_VRS_Get (context, _UVRSC_CORE, R_SP, _UVRSD_UINT32, &reg);
+         if (op & 0x40)
+           reg -= offset;
+         else
+           reg += offset;
+         _Unwind_VRS_Set (context, _UVRSC_CORE, R_SP, _UVRSD_UINT32, &reg);
+         continue;
+       }
+      
+      if ((op & 0xf0) == 0x80)
+       {
+         op = (op << 8) | next_unwind_byte (uws);
+         if (op == 0x8000)
+           {
+             /* Refuse to unwind.  */
+             return _URC_FAILURE;
+           }
+         /* Pop r4-r15 under mask.  */
+         op = (op << 4) & 0xfff0;
+         if (_Unwind_VRS_Pop (context, _UVRSC_CORE, op, _UVRSD_UINT32)
+             != _UVRSR_OK)
+           return _URC_FAILURE;
+         if (op & (1 << R_PC))
+           set_pc = 1;
+         continue;
+       }
+      if ((op & 0xf0) == 0x90)
+       {
+         op &= 0xf;
+         if (op == 13 || op == 15)
+           /* Reserved.  */
+           return _URC_FAILURE;
+         /* vsp = r[nnnn].  */
+         _Unwind_VRS_Get (context, _UVRSC_CORE, op, _UVRSD_UINT32, &reg);
+         _Unwind_VRS_Set (context, _UVRSC_CORE, R_SP, _UVRSD_UINT32, &reg);
+         continue;
+       }
+      if ((op & 0xf0) == 0xa0)
+       {
+         /* Pop r4-r[4+nnn], [lr].  */
+         _uw mask;
+         
+         mask = (0xff0 >> (7 - (op & 7))) & 0xff0;
+         if (op & 8)
+           mask |= (1 << R_LR);
+         if (_Unwind_VRS_Pop (context, _UVRSC_CORE, mask, _UVRSD_UINT32)
+             != _UVRSR_OK)
+           return _URC_FAILURE;
+         continue;
+       }
+      if ((op & 0xf0) == 0xb0)
+       {
+         /* op == 0xb0 already handled.  */
+         if (op == 0xb1)
+           {
+             op = next_unwind_byte (uws);
+             if (op == 0 || ((op & 0xf0) != 0))
+               /* Spare.  */
+               return _URC_FAILURE;
+             /* Pop r0-r4 under mask.  */
+             if (_Unwind_VRS_Pop (context, _UVRSC_CORE, op, _UVRSD_UINT32)
+                 != _UVRSR_OK)
+               return _URC_FAILURE;
+             continue;
+           }
+         if (op == 0xb2)
+           {
+             /* vsp = vsp + 0x204 + (uleb128 << 2).  */
+             int shift;
+
+             _Unwind_VRS_Get (context, _UVRSC_CORE, R_SP, _UVRSD_UINT32,
+                              &reg);
+             op = next_unwind_byte (uws);
+             shift = 2;
+             while (op & 0x80)
+               {
+                 reg += ((op & 0x7f) << shift);
+                 shift += 7;
+                 op = next_unwind_byte (uws);
+               }
+             reg += ((op & 0x7f) << shift) + 0x204;
+             _Unwind_VRS_Set (context, _UVRSC_CORE, R_SP, _UVRSD_UINT32,
+                              &reg);
+             continue;
+           }
+         if (op == 0xb3)
+           {
+             /* Pop VFP registers with fldmx.  */
+             op = next_unwind_byte (uws);
+             op = ((op & 0xf0) << 12) | ((op & 0xf) + 1);
+             if (_Unwind_VRS_Pop (context, _UVRSC_VFP, op, _UVRSD_VFPX)
+                 != _UVRSR_OK)
+               return _URC_FAILURE;
+             continue;
+           }
+         if ((op & 0xfc) == 0xb4)
+           {
+             /* Pop FPA E[4]-E[4+nn].  */
+             op = 0x40000 | ((op & 3) + 1);
+             if (_Unwind_VRS_Pop (context, _UVRSC_FPA, op, _UVRSD_FPAX)
+                 != _UVRSR_OK)
+               return _URC_FAILURE;
+             continue;
+           }
+         /* op & 0xf8 == 0xb8.  */
+         /* Pop VFP D[8]-D[8+nnn] with fldmx.  */
+         op = 0x80000 | ((op & 7) + 1);
+         if (_Unwind_VRS_Pop (context, _UVRSC_VFP, op, _UVRSD_VFPX)
+             != _UVRSR_OK)
+           return _URC_FAILURE;
+         continue;
+       }
+      if ((op & 0xf0) == 0xc0)
+       {
+         if (op == 0xc6)
+           {
+             /* Pop iWMMXt D registers.  */
+             op = next_unwind_byte (uws);
+             op = ((op & 0xf0) << 12) | ((op & 0xf) + 1);
+             if (_Unwind_VRS_Pop (context, _UVRSC_WMMXD, op, _UVRSD_UINT64)
+                 != _UVRSR_OK)
+               return _URC_FAILURE;
+             continue;
+           }
+         if (op == 0xc7)
+           {
+             op = next_unwind_byte (uws);
+             if (op == 0 || (op & 0xf0) != 0)
+               /* Spare.  */
+               return _URC_FAILURE;
+             /* Pop iWMMXt wCGR{3,2,1,0} under mask.  */
+             if (_Unwind_VRS_Pop (context, _UVRSC_WMMXC, op, _UVRSD_UINT32)
+                 != _UVRSR_OK)
+               return _URC_FAILURE;
+             continue;
+           }
+         if ((op & 0xf8) == 0xc0)
+           {
+             /* Pop iWMMXt wR[10]-wR[10+nnn].  */
+             op = 0xa0000 | ((op & 0xf) + 1);
+             if (_Unwind_VRS_Pop (context, _UVRSC_WMMXD, op, _UVRSD_UINT64)
+                 != _UVRSR_OK)
+               return _URC_FAILURE;
+             continue;
+           }
+         if (op == 0xc8)
+           {
+#ifndef __VFP_FP__
+             /* Pop FPA registers.  */
+             op = next_unwind_byte (uws);
+             op = ((op & 0xf0) << 12) | ((op & 0xf) + 1);
+             if (_Unwind_VRS_Pop (context, _UVRSC_FPA, op, _UVRSD_FPAX)
+                 != _UVRSR_OK)
+               return _URC_FAILURE;
+             continue;
+#else
+              /* Pop VFPv3 registers D[16+ssss]-D[16+ssss+cccc] with vldm.  */
+              op = next_unwind_byte (uws);
+              op = (((op & 0xf0) + 16) << 12) | ((op & 0xf) + 1);
+              if (_Unwind_VRS_Pop (context, _UVRSC_VFP, op, _UVRSD_DOUBLE)
+                  != _UVRSR_OK)
+                return _URC_FAILURE;
+              continue;
+#endif
+           }
+         if (op == 0xc9)
+           {
+             /* Pop VFP registers with fldmd.  */
+             op = next_unwind_byte (uws);
+             op = ((op & 0xf0) << 12) | ((op & 0xf) + 1);
+             if (_Unwind_VRS_Pop (context, _UVRSC_VFP, op, _UVRSD_DOUBLE)
+                 != _UVRSR_OK)
+               return _URC_FAILURE;
+             continue;
+           }
+         /* Spare.  */
+         return _URC_FAILURE;
+       }
+      if ((op & 0xf8) == 0xd0)
+       {
+         /* Pop VFP D[8]-D[8+nnn] with fldmd.  */
+         op = 0x80000 | ((op & 7) + 1);
+         if (_Unwind_VRS_Pop (context, _UVRSC_VFP, op, _UVRSD_DOUBLE)
+             != _UVRSR_OK)
+           return _URC_FAILURE;
+         continue;
+       }
+      /* Spare.  */
+      return _URC_FAILURE;
+    }
+  return _URC_OK;
+}
+
+
+/* Execute the unwinding instructions associated with a frame.  UCBP and
+   CONTEXT are the current exception object and virtual CPU state
+   respectively.  */
+
+_Unwind_Reason_Code
+__gnu_unwind_frame (_Unwind_Control_Block * ucbp, _Unwind_Context * context)
+{
+  _uw *ptr;
+  __gnu_unwind_state uws;
+
+  ptr = (_uw *) ucbp->pr_cache.ehtp;
+  /* Skip over the personality routine address.  */
+  ptr++;
+  /* Setup the unwinder state.  */
+  uws.data = (*ptr) << 8;
+  uws.next = ptr + 1;
+  uws.bytes_left = 3;
+  uws.words_left = ((*ptr) >> 24) & 0xff;
+
+  return __gnu_unwind_execute (context, &uws);
+}
+
+/* Get the _Unwind_Control_Block from an _Unwind_Context.  */
+
+static inline _Unwind_Control_Block *
+unwind_UCB_from_context (_Unwind_Context * context)
+{
+  return (_Unwind_Control_Block *) _Unwind_GetGR (context, R_IP);
+}
+
+/* Get the start address of the function being unwound.  */
+
+_Unwind_Ptr
+_Unwind_GetRegionStart (_Unwind_Context * context)
+{
+  _Unwind_Control_Block *ucbp;
+
+  ucbp = unwind_UCB_from_context (context);
+  return (_Unwind_Ptr) ucbp->pr_cache.fnstart;
+}
+
+/* Find the Language specific exception data.  */
+
+void *
+_Unwind_GetLanguageSpecificData (_Unwind_Context * context)
+{
+  _Unwind_Control_Block *ucbp;
+  _uw *ptr;
+
+  /* Get a pointer to the exception table entry.  */
+  ucbp = unwind_UCB_from_context (context);
+  ptr = (_uw *) ucbp->pr_cache.ehtp;
+  /* Skip the personality routine address.  */
+  ptr++;
+  /* Skip the unwind opcodes.  */
+  ptr += (((*ptr) >> 24) & 0xff) + 1;
+
+  return ptr;
+}
+
+
+/* These two should never be used.  */
+
+_Unwind_Ptr
+_Unwind_GetDataRelBase (_Unwind_Context *context __attribute__ ((unused)))
+{
+  abort ();
+}
+
+_Unwind_Ptr
+_Unwind_GetTextRelBase (_Unwind_Context *context __attribute__ ((unused)))
+{
+  abort ();
+}
diff --git a/libgcc/config/arm/t-bpabi b/libgcc/config/arm/t-bpabi
new file mode 100644 (file)
index 0000000..a3b23dc
--- /dev/null
@@ -0,0 +1,3 @@
+LIB2ADDEH = $(srcdir)/config/arm/unwind-arm.c \
+  $(srcdir)/config/arm/libunwind.S \
+  $(srcdir)/config/arm/pr-support.c $(srcdir)/unwind-c.c
diff --git a/libgcc/config/arm/t-symbian b/libgcc/config/arm/t-symbian
new file mode 100644 (file)
index 0000000..6788d5f
--- /dev/null
@@ -0,0 +1,2 @@
+# Include the gcc personality routine
+LIB2ADDEH = $(srcdir)/unwind-c.c $(srcdir)/config/arm/pr-support.c
diff --git a/libgcc/config/arm/unwind-arm.c b/libgcc/config/arm/unwind-arm.c
new file mode 100644 (file)
index 0000000..90d258d
--- /dev/null
@@ -0,0 +1,1283 @@
+/* ARM EABI compliant unwinding routines.
+   Copyright (C) 2004, 2005, 2009 Free Software Foundation, Inc.
+   Contributed by Paul Brook
+
+   This file 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 3, or (at your option) any
+   later version.
+
+   This file 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.
+
+   Under Section 7 of GPL version 3, you are granted additional
+   permissions described in the GCC Runtime Library Exception, version
+   3.1, as published by the Free Software Foundation.
+
+   You should have received a copy of the GNU General Public License and
+   a copy of the GCC Runtime Library Exception along with this program;
+   see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include "unwind.h"
+
+/* We add a prototype for abort here to avoid creating a dependency on
+   target headers.  */
+extern void abort (void);
+
+/* Definitions for C++ runtime support routines.  We make these weak
+   declarations to avoid pulling in libsupc++ unnecessarily.  */
+typedef unsigned char bool;
+
+typedef struct _ZSt9type_info type_info; /* This names C++ type_info type */
+enum __cxa_type_match_result
+  {
+    ctm_failed = 0,
+    ctm_succeeded = 1,
+    ctm_succeeded_with_ptr_to_base = 2
+  };
+
+void __attribute__((weak)) __cxa_call_unexpected(_Unwind_Control_Block *ucbp);
+bool __attribute__((weak)) __cxa_begin_cleanup(_Unwind_Control_Block *ucbp);
+enum __cxa_type_match_result __attribute__((weak)) __cxa_type_match
+  (_Unwind_Control_Block *ucbp, const type_info *rttip,
+   bool is_reference, void **matched_object);
+
+_Unwind_Ptr __attribute__((weak))
+__gnu_Unwind_Find_exidx (_Unwind_Ptr, int *);
+
+/* Misc constants.  */
+#define R_IP   12
+#define R_SP   13
+#define R_LR   14
+#define R_PC   15
+
+#define EXIDX_CANTUNWIND 1
+#define uint32_highbit (((_uw) 1) << 31)
+
+#define UCB_FORCED_STOP_FN(ucbp) ((ucbp)->unwinder_cache.reserved1)
+#define UCB_PR_ADDR(ucbp) ((ucbp)->unwinder_cache.reserved2)
+#define UCB_SAVED_CALLSITE_ADDR(ucbp) ((ucbp)->unwinder_cache.reserved3)
+#define UCB_FORCED_STOP_ARG(ucbp) ((ucbp)->unwinder_cache.reserved4)
+
+struct core_regs
+{
+  _uw r[16];
+};
+
+/* We use normal integer types here to avoid the compiler generating
+   coprocessor instructions.  */
+struct vfp_regs
+{
+  _uw64 d[16];
+  _uw pad;
+};
+
+struct vfpv3_regs
+{
+  /* Always populated via VSTM, so no need for the "pad" field from
+     vfp_regs (which is used to store the format word for FSTMX).  */
+  _uw64 d[16];
+};
+
+struct fpa_reg
+{
+  _uw w[3];
+};
+
+struct fpa_regs
+{
+  struct fpa_reg f[8];
+};
+
+struct wmmxd_regs
+{
+  _uw64 wd[16];
+};
+
+struct wmmxc_regs
+{
+  _uw wc[4];
+};
+
+/* Unwind descriptors.  */
+
+typedef struct
+{
+  _uw16 length;
+  _uw16 offset;
+} EHT16;
+
+typedef struct
+{
+  _uw length;
+  _uw offset;
+} EHT32;
+
+/* The ABI specifies that the unwind routines may only use core registers,
+   except when actually manipulating coprocessor state.  This allows
+   us to write one implementation that works on all platforms by
+   demand-saving coprocessor registers.
+
+   During unwinding we hold the coprocessor state in the actual hardware
+   registers and allocate demand-save areas for use during phase1
+   unwinding.  */
+
+typedef struct
+{
+  /* The first fields must be the same as a phase2_vrs.  */
+  _uw demand_save_flags;
+  struct core_regs core;
+  _uw prev_sp; /* Only valid during forced unwinding.  */
+  struct vfp_regs vfp;
+  struct vfpv3_regs vfp_regs_16_to_31;
+  struct fpa_regs fpa;
+  struct wmmxd_regs wmmxd;
+  struct wmmxc_regs wmmxc;
+} phase1_vrs;
+
+#define DEMAND_SAVE_VFP 1      /* VFP state has been saved if not set */
+#define DEMAND_SAVE_VFP_D 2    /* VFP state is for FLDMD/FSTMD if set */
+#define DEMAND_SAVE_VFP_V3 4    /* VFPv3 state for regs 16 .. 31 has
+                                   been saved if not set */
+#define DEMAND_SAVE_WMMXD 8    /* iWMMXt data registers have been
+                                  saved if not set.  */
+#define DEMAND_SAVE_WMMXC 16   /* iWMMXt control registers have been
+                                  saved if not set.  */
+
+/* This must match the structure created by the assembly wrappers.  */
+typedef struct
+{
+  _uw demand_save_flags;
+  struct core_regs core;
+} phase2_vrs;
+
+
+/* An exception index table entry.  */
+
+typedef struct __EIT_entry
+{
+  _uw fnoffset;
+  _uw content;
+} __EIT_entry;
+
+/* Assembly helper functions.  */
+
+/* Restore core register state.  Never returns.  */
+void __attribute__((noreturn)) restore_core_regs (struct core_regs *);
+
+
+/* Coprocessor register state manipulation functions.  */
+
+/* Routines for FLDMX/FSTMX format...  */
+void __gnu_Unwind_Save_VFP (struct vfp_regs * p);
+void __gnu_Unwind_Restore_VFP (struct vfp_regs * p);
+void __gnu_Unwind_Save_WMMXD (struct wmmxd_regs * p);
+void __gnu_Unwind_Restore_WMMXD (struct wmmxd_regs * p);
+void __gnu_Unwind_Save_WMMXC (struct wmmxc_regs * p);
+void __gnu_Unwind_Restore_WMMXC (struct wmmxc_regs * p);
+
+/* ...and those for FLDMD/FSTMD format...  */
+void __gnu_Unwind_Save_VFP_D (struct vfp_regs * p);
+void __gnu_Unwind_Restore_VFP_D (struct vfp_regs * p);
+
+/* ...and those for VLDM/VSTM format, saving/restoring only registers
+   16 through 31.  */
+void __gnu_Unwind_Save_VFP_D_16_to_31 (struct vfpv3_regs * p);
+void __gnu_Unwind_Restore_VFP_D_16_to_31 (struct vfpv3_regs * p);
+
+/* Restore coprocessor state after phase1 unwinding.  */
+static void
+restore_non_core_regs (phase1_vrs * vrs)
+{
+  if ((vrs->demand_save_flags & DEMAND_SAVE_VFP) == 0)
+    {
+      if (vrs->demand_save_flags & DEMAND_SAVE_VFP_D)
+        __gnu_Unwind_Restore_VFP_D (&vrs->vfp);
+      else
+        __gnu_Unwind_Restore_VFP (&vrs->vfp);
+    }
+
+  if ((vrs->demand_save_flags & DEMAND_SAVE_VFP_V3) == 0)
+    __gnu_Unwind_Restore_VFP_D_16_to_31 (&vrs->vfp_regs_16_to_31);
+
+  if ((vrs->demand_save_flags & DEMAND_SAVE_WMMXD) == 0)
+    __gnu_Unwind_Restore_WMMXD (&vrs->wmmxd);
+  if ((vrs->demand_save_flags & DEMAND_SAVE_WMMXC) == 0)
+    __gnu_Unwind_Restore_WMMXC (&vrs->wmmxc);
+}
+
+/* A better way to do this would probably be to compare the absolute address
+   with a segment relative relocation of the same symbol.  */
+
+extern int __text_start;
+extern int __data_start;
+
+/* The exception index table location.  */
+extern __EIT_entry __exidx_start;
+extern __EIT_entry __exidx_end;
+
+/* ABI defined personality routines.  */
+extern _Unwind_Reason_Code __aeabi_unwind_cpp_pr0 (_Unwind_State,
+    _Unwind_Control_Block *, _Unwind_Context *);// __attribute__((weak));
+extern _Unwind_Reason_Code __aeabi_unwind_cpp_pr1 (_Unwind_State,
+    _Unwind_Control_Block *, _Unwind_Context *) __attribute__((weak));
+extern _Unwind_Reason_Code __aeabi_unwind_cpp_pr2 (_Unwind_State,
+    _Unwind_Control_Block *, _Unwind_Context *) __attribute__((weak));
+
+/* ABI defined routine to store a virtual register to memory.  */
+
+_Unwind_VRS_Result _Unwind_VRS_Get (_Unwind_Context *context,
+                                   _Unwind_VRS_RegClass regclass,
+                                   _uw regno,
+                                   _Unwind_VRS_DataRepresentation representation,
+                                   void *valuep)
+{
+  phase1_vrs *vrs = (phase1_vrs *) context;
+
+  switch (regclass)
+    {
+    case _UVRSC_CORE:
+      if (representation != _UVRSD_UINT32
+         || regno > 15)
+       return _UVRSR_FAILED;
+      *(_uw *) valuep = vrs->core.r[regno];
+      return _UVRSR_OK;
+
+    case _UVRSC_VFP:
+    case _UVRSC_FPA:
+    case _UVRSC_WMMXD:
+    case _UVRSC_WMMXC:
+      return _UVRSR_NOT_IMPLEMENTED;
+
+    default:
+      return _UVRSR_FAILED;
+    }
+}
+
+
+/* ABI defined function to load a virtual register from memory.  */
+
+_Unwind_VRS_Result _Unwind_VRS_Set (_Unwind_Context *context,
+                                   _Unwind_VRS_RegClass regclass,
+                                   _uw regno,
+                                   _Unwind_VRS_DataRepresentation representation,
+                                   void *valuep)
+{
+  phase1_vrs *vrs = (phase1_vrs *) context;
+
+  switch (regclass)
+    {
+    case _UVRSC_CORE:
+      if (representation != _UVRSD_UINT32
+         || regno > 15)
+       return _UVRSR_FAILED;
+
+      vrs->core.r[regno] = *(_uw *) valuep;
+      return _UVRSR_OK;
+
+    case _UVRSC_VFP:
+    case _UVRSC_FPA:
+    case _UVRSC_WMMXD:
+    case _UVRSC_WMMXC:
+      return _UVRSR_NOT_IMPLEMENTED;
+
+    default:
+      return _UVRSR_FAILED;
+    }
+}
+
+
+/* ABI defined function to pop registers off the stack.  */
+
+_Unwind_VRS_Result _Unwind_VRS_Pop (_Unwind_Context *context,
+                                   _Unwind_VRS_RegClass regclass,
+                                   _uw discriminator,
+                                   _Unwind_VRS_DataRepresentation representation)
+{
+  phase1_vrs *vrs = (phase1_vrs *) context;
+
+  switch (regclass)
+    {
+    case _UVRSC_CORE:
+      {
+       _uw *ptr;
+       _uw mask;
+       int i;
+
+       if (representation != _UVRSD_UINT32)
+         return _UVRSR_FAILED;
+
+       mask = discriminator & 0xffff;
+       ptr = (_uw *) vrs->core.r[R_SP];
+       /* Pop the requested registers.  */
+       for (i = 0; i < 16; i++)
+         {
+           if (mask & (1 << i))
+             vrs->core.r[i] = *(ptr++);
+         }
+       /* Writeback the stack pointer value if it wasn't restored.  */
+       if ((mask & (1 << R_SP)) == 0)
+         vrs->core.r[R_SP] = (_uw) ptr;
+      }
+      return _UVRSR_OK;
+
+    case _UVRSC_VFP:
+      {
+       _uw start = discriminator >> 16;
+       _uw count = discriminator & 0xffff;
+       struct vfp_regs tmp;
+       struct vfpv3_regs tmp_16_to_31;
+       int tmp_count;
+       _uw *sp;
+       _uw *dest;
+        int num_vfpv3_regs = 0;
+
+        /* We use an approximation here by bounding _UVRSD_DOUBLE
+           register numbers at 32 always, since we can't detect if
+           VFPv3 isn't present (in such a case the upper limit is 16).  */
+       if ((representation != _UVRSD_VFPX && representation != _UVRSD_DOUBLE)
+            || start + count > (representation == _UVRSD_VFPX ? 16 : 32)
+            || (representation == _UVRSD_VFPX && start >= 16))
+         return _UVRSR_FAILED;
+
+        /* Check if we're being asked to pop VFPv3-only registers
+           (numbers 16 through 31).  */
+       if (start >= 16)
+          num_vfpv3_regs = count;
+        else if (start + count > 16)
+          num_vfpv3_regs = start + count - 16;
+
+        if (num_vfpv3_regs && representation != _UVRSD_DOUBLE)
+          return _UVRSR_FAILED;
+
+       /* Demand-save coprocessor registers for stage1.  */
+       if (start < 16 && (vrs->demand_save_flags & DEMAND_SAVE_VFP))
+         {
+           vrs->demand_save_flags &= ~DEMAND_SAVE_VFP;
+
+            if (representation == _UVRSD_DOUBLE)
+              {
+                /* Save in FLDMD/FSTMD format.  */
+               vrs->demand_save_flags |= DEMAND_SAVE_VFP_D;
+               __gnu_Unwind_Save_VFP_D (&vrs->vfp);
+              }
+            else
+              {
+                /* Save in FLDMX/FSTMX format.  */
+               vrs->demand_save_flags &= ~DEMAND_SAVE_VFP_D;
+               __gnu_Unwind_Save_VFP (&vrs->vfp);
+              }
+         }
+
+        if (num_vfpv3_regs > 0
+            && (vrs->demand_save_flags & DEMAND_SAVE_VFP_V3))
+         {
+           vrs->demand_save_flags &= ~DEMAND_SAVE_VFP_V3;
+            __gnu_Unwind_Save_VFP_D_16_to_31 (&vrs->vfp_regs_16_to_31);
+         }
+
+       /* Restore the registers from the stack.  Do this by saving the
+          current VFP registers to a memory area, moving the in-memory
+          values into that area, and restoring from the whole area.
+          For _UVRSD_VFPX we assume FSTMX standard format 1.  */
+        if (representation == _UVRSD_VFPX)
+         __gnu_Unwind_Save_VFP (&tmp);
+        else
+          {
+           /* Save registers 0 .. 15 if required.  */
+            if (start < 16)
+              __gnu_Unwind_Save_VFP_D (&tmp);
+
+           /* Save VFPv3 registers 16 .. 31 if required.  */
+            if (num_vfpv3_regs)
+             __gnu_Unwind_Save_VFP_D_16_to_31 (&tmp_16_to_31);
+          }
+
+       /* Work out how many registers below register 16 need popping.  */
+       tmp_count = num_vfpv3_regs > 0 ? 16 - start : count;
+
+       /* Copy registers below 16, if needed.
+          The stack address is only guaranteed to be word aligned, so
+          we can't use doubleword copies.  */
+       sp = (_uw *) vrs->core.r[R_SP];
+        if (tmp_count > 0)
+          {
+           tmp_count *= 2;
+           dest = (_uw *) &tmp.d[start];
+           while (tmp_count--)
+             *(dest++) = *(sp++);
+          }
+
+       /* Copy VFPv3 registers numbered >= 16, if needed.  */
+        if (num_vfpv3_regs > 0)
+          {
+            /* num_vfpv3_regs is needed below, so copy it.  */
+            int tmp_count_2 = num_vfpv3_regs * 2;
+            int vfpv3_start = start < 16 ? 16 : start;
+
+           dest = (_uw *) &tmp_16_to_31.d[vfpv3_start - 16];
+           while (tmp_count_2--)
+             *(dest++) = *(sp++);
+          }
+
+       /* Skip the format word space if using FLDMX/FSTMX format.  */
+       if (representation == _UVRSD_VFPX)
+         sp++;
+
+       /* Set the new stack pointer.  */
+       vrs->core.r[R_SP] = (_uw) sp;
+
+       /* Reload the registers.  */
+        if (representation == _UVRSD_VFPX)
+         __gnu_Unwind_Restore_VFP (&tmp);
+        else
+          {
+           /* Restore registers 0 .. 15 if required.  */
+            if (start < 16)
+              __gnu_Unwind_Restore_VFP_D (&tmp);
+
+           /* Restore VFPv3 registers 16 .. 31 if required.  */
+            if (num_vfpv3_regs > 0)
+             __gnu_Unwind_Restore_VFP_D_16_to_31 (&tmp_16_to_31);
+          }
+      }
+      return _UVRSR_OK;
+
+    case _UVRSC_FPA:
+      return _UVRSR_NOT_IMPLEMENTED;
+
+    case _UVRSC_WMMXD:
+      {
+       _uw start = discriminator >> 16;
+       _uw count = discriminator & 0xffff;
+       struct wmmxd_regs tmp;
+       _uw *sp;
+       _uw *dest;
+
+       if ((representation != _UVRSD_UINT64) || start + count > 16)
+         return _UVRSR_FAILED;
+
+       if (vrs->demand_save_flags & DEMAND_SAVE_WMMXD)
+         {
+           /* Demand-save resisters for stage1.  */
+           vrs->demand_save_flags &= ~DEMAND_SAVE_WMMXD;
+           __gnu_Unwind_Save_WMMXD (&vrs->wmmxd);
+         }
+
+       /* Restore the registers from the stack.  Do this by saving the
+          current WMMXD registers to a memory area, moving the in-memory
+          values into that area, and restoring from the whole area.  */
+       __gnu_Unwind_Save_WMMXD (&tmp);
+
+       /* The stack address is only guaranteed to be word aligned, so
+          we can't use doubleword copies.  */
+       sp = (_uw *) vrs->core.r[R_SP];
+       dest = (_uw *) &tmp.wd[start];
+       count *= 2;
+       while (count--)
+         *(dest++) = *(sp++);
+
+       /* Set the new stack pointer.  */
+       vrs->core.r[R_SP] = (_uw) sp;
+
+       /* Reload the registers.  */
+       __gnu_Unwind_Restore_WMMXD (&tmp);
+      }
+      return _UVRSR_OK;
+
+    case _UVRSC_WMMXC:
+      {
+       int i;
+       struct wmmxc_regs tmp;
+       _uw *sp;
+
+       if ((representation != _UVRSD_UINT32) || discriminator > 16)
+         return _UVRSR_FAILED;
+
+       if (vrs->demand_save_flags & DEMAND_SAVE_WMMXC)
+         {
+           /* Demand-save resisters for stage1.  */
+           vrs->demand_save_flags &= ~DEMAND_SAVE_WMMXC;
+           __gnu_Unwind_Save_WMMXC (&vrs->wmmxc);
+         }
+
+       /* Restore the registers from the stack.  Do this by saving the
+          current WMMXC registers to a memory area, moving the in-memory
+          values into that area, and restoring from the whole area.  */
+       __gnu_Unwind_Save_WMMXC (&tmp);
+
+       sp = (_uw *) vrs->core.r[R_SP];
+       for (i = 0; i < 4; i++)
+         if (discriminator & (1 << i))
+           tmp.wc[i] = *(sp++);
+
+       /* Set the new stack pointer.  */
+       vrs->core.r[R_SP] = (_uw) sp;
+
+       /* Reload the registers.  */
+       __gnu_Unwind_Restore_WMMXC (&tmp);
+      }
+      return _UVRSR_OK;
+
+    default:
+      return _UVRSR_FAILED;
+    }
+}
+
+
+/* Core unwinding functions.  */
+
+/* Calculate the address encoded by a 31-bit self-relative offset at address
+   P.  */
+static inline _uw
+selfrel_offset31 (const _uw *p)
+{
+  _uw offset;
+
+  offset = *p;
+  /* Sign extend to 32 bits.  */
+  if (offset & (1 << 30))
+    offset |= 1u << 31;
+  else
+    offset &= ~(1u << 31);
+
+  return offset + (_uw) p;
+}
+
+
+/* Perform a binary search for RETURN_ADDRESS in TABLE.  The table contains
+   NREC entries.  */
+
+static const __EIT_entry *
+search_EIT_table (const __EIT_entry * table, int nrec, _uw return_address)
+{
+  _uw next_fn;
+  _uw this_fn;
+  int n, left, right;
+
+  if (nrec == 0)
+    return (__EIT_entry *) 0;
+
+  left = 0;
+  right = nrec - 1;
+
+  while (1)
+    {
+      n = (left + right) / 2;
+      this_fn = selfrel_offset31 (&table[n].fnoffset);
+      if (n != nrec - 1)
+       next_fn = selfrel_offset31 (&table[n + 1].fnoffset) - 1;
+      else
+       next_fn = (_uw)0 - 1;
+
+      if (return_address < this_fn)
+       {
+         if (n == left)
+           return (__EIT_entry *) 0;
+         right = n - 1;
+       }
+      else if (return_address <= next_fn)
+       return &table[n];
+      else
+       left = n + 1;
+    }
+}
+
+/* Find the exception index table eintry for the given address.
+   Fill in the relevant fields of the UCB.
+   Returns _URC_FAILURE if an error occurred, _URC_OK on success.  */
+
+static _Unwind_Reason_Code
+get_eit_entry (_Unwind_Control_Block *ucbp, _uw return_address)
+{
+  const __EIT_entry * eitp;
+  int nrec;
+  
+  /* The return address is the address of the instruction following the
+     call instruction (plus one in thumb mode).  If this was the last
+     instruction in the function the address will lie in the following
+     function.  Subtract 2 from the address so that it points within the call
+     instruction itself.  */
+  return_address -= 2;
+
+  if (__gnu_Unwind_Find_exidx)
+    {
+      eitp = (const __EIT_entry *) __gnu_Unwind_Find_exidx (return_address,
+                                                           &nrec);
+      if (!eitp)
+       {
+         UCB_PR_ADDR (ucbp) = 0;
+         return _URC_FAILURE;
+       }
+    }
+  else
+    {
+      eitp = &__exidx_start;
+      nrec = &__exidx_end - &__exidx_start;
+    }
+
+  eitp = search_EIT_table (eitp, nrec, return_address);
+
+  if (!eitp)
+    {
+      UCB_PR_ADDR (ucbp) = 0;
+      return _URC_FAILURE;
+    }
+  ucbp->pr_cache.fnstart = selfrel_offset31 (&eitp->fnoffset);
+
+  /* Can this frame be unwound at all?  */
+  if (eitp->content == EXIDX_CANTUNWIND)
+    {
+      UCB_PR_ADDR (ucbp) = 0;
+      return _URC_END_OF_STACK;
+    }
+
+  /* Obtain the address of the "real" __EHT_Header word.  */
+
+  if (eitp->content & uint32_highbit)
+    {
+      /* It is immediate data.  */
+      ucbp->pr_cache.ehtp = (_Unwind_EHT_Header *)&eitp->content;
+      ucbp->pr_cache.additional = 1;
+    }
+  else
+    {
+      /* The low 31 bits of the content field are a self-relative
+        offset to an _Unwind_EHT_Entry structure.  */
+      ucbp->pr_cache.ehtp =
+       (_Unwind_EHT_Header *) selfrel_offset31 (&eitp->content);
+      ucbp->pr_cache.additional = 0;
+    }
+
+  /* Discover the personality routine address.  */
+  if (*ucbp->pr_cache.ehtp & (1u << 31))
+    {
+      /* One of the predefined standard routines.  */
+      _uw idx = (*(_uw *) ucbp->pr_cache.ehtp >> 24) & 0xf;
+      if (idx == 0)
+       UCB_PR_ADDR (ucbp) = (_uw) &__aeabi_unwind_cpp_pr0;
+      else if (idx == 1)
+       UCB_PR_ADDR (ucbp) = (_uw) &__aeabi_unwind_cpp_pr1;
+      else if (idx == 2)
+       UCB_PR_ADDR (ucbp) = (_uw) &__aeabi_unwind_cpp_pr2;
+      else
+       { /* Failed */
+         UCB_PR_ADDR (ucbp) = 0;
+         return _URC_FAILURE;
+       }
+    } 
+  else
+    {
+      /* Execute region offset to PR */
+      UCB_PR_ADDR (ucbp) = selfrel_offset31 (ucbp->pr_cache.ehtp);
+    }
+  return _URC_OK;
+}
+
+
+/* Perform phase2 unwinding.  VRS is the initial virtual register state.  */
+
+static void __attribute__((noreturn))
+unwind_phase2 (_Unwind_Control_Block * ucbp, phase2_vrs * vrs)
+{
+  _Unwind_Reason_Code pr_result;
+
+  do
+    {
+      /* Find the entry for this routine.  */
+      if (get_eit_entry (ucbp, vrs->core.r[R_PC]) != _URC_OK)
+       abort ();
+
+      UCB_SAVED_CALLSITE_ADDR (ucbp) = vrs->core.r[R_PC];
+
+      /* Call the pr to decide what to do.  */
+      pr_result = ((personality_routine) UCB_PR_ADDR (ucbp))
+       (_US_UNWIND_FRAME_STARTING, ucbp, (_Unwind_Context *) vrs);
+    }
+  while (pr_result == _URC_CONTINUE_UNWIND);
+  
+  if (pr_result != _URC_INSTALL_CONTEXT)
+    abort();
+  
+  restore_core_regs (&vrs->core);
+}
+
+/* Perform phase2 forced unwinding.  */
+
+static _Unwind_Reason_Code
+unwind_phase2_forced (_Unwind_Control_Block *ucbp, phase2_vrs *entry_vrs,
+                     int resuming)
+{
+  _Unwind_Stop_Fn stop_fn = (_Unwind_Stop_Fn) UCB_FORCED_STOP_FN (ucbp);
+  void *stop_arg = (void *)UCB_FORCED_STOP_ARG (ucbp);
+  _Unwind_Reason_Code pr_result = 0;
+  /* We use phase1_vrs here even though we do not demand save, for the
+     prev_sp field.  */
+  phase1_vrs saved_vrs, next_vrs;
+
+  /* Save the core registers.  */
+  saved_vrs.core = entry_vrs->core;
+  /* We don't need to demand-save the non-core registers, because we
+     unwind in a single pass.  */
+  saved_vrs.demand_save_flags = 0;
+
+  /* Unwind until we reach a propagation barrier.  */
+  do
+    {
+      _Unwind_State action;
+      _Unwind_Reason_Code entry_code;
+      _Unwind_Reason_Code stop_code;
+
+      /* Find the entry for this routine.  */
+      entry_code = get_eit_entry (ucbp, saved_vrs.core.r[R_PC]);
+
+      if (resuming)
+       {
+         action = _US_UNWIND_FRAME_RESUME | _US_FORCE_UNWIND;
+         resuming = 0;
+       }
+      else
+       action = _US_UNWIND_FRAME_STARTING | _US_FORCE_UNWIND;
+
+      if (entry_code == _URC_OK)
+       {
+         UCB_SAVED_CALLSITE_ADDR (ucbp) = saved_vrs.core.r[R_PC];
+
+         next_vrs = saved_vrs;
+
+         /* Call the pr to decide what to do.  */
+         pr_result = ((personality_routine) UCB_PR_ADDR (ucbp))
+           (action, ucbp, (void *) &next_vrs);
+
+         saved_vrs.prev_sp = next_vrs.core.r[R_SP];
+       }
+      else
+       {
+         /* Treat any failure as the end of unwinding, to cope more
+            gracefully with missing EH information.  Mixed EH and
+            non-EH within one object will usually result in failure,
+            because the .ARM.exidx tables do not indicate the end
+            of the code to which they apply; but mixed EH and non-EH
+            shared objects should return an unwind failure at the
+            entry of a non-EH shared object.  */
+         action |= _US_END_OF_STACK;
+
+         saved_vrs.prev_sp = saved_vrs.core.r[R_SP];
+       }
+
+      stop_code = stop_fn (1, action, ucbp->exception_class, ucbp,
+                          (void *)&saved_vrs, stop_arg);
+      if (stop_code != _URC_NO_REASON)
+       return _URC_FAILURE;
+
+      if (entry_code != _URC_OK)
+       return entry_code;
+
+      saved_vrs = next_vrs;
+    }
+  while (pr_result == _URC_CONTINUE_UNWIND);
+
+  if (pr_result != _URC_INSTALL_CONTEXT)
+    {
+      /* Some sort of failure has occurred in the pr and probably the
+        pr returned _URC_FAILURE.  */
+      return _URC_FAILURE;
+    }
+
+  restore_core_regs (&saved_vrs.core);
+}
+
+/* This is a very limited implementation of _Unwind_GetCFA.  It returns
+   the stack pointer as it is about to be unwound, and is only valid
+   while calling the stop function during forced unwinding.  If the
+   current personality routine result is going to run a cleanup, this
+   will not be the CFA; but when the frame is really unwound, it will
+   be.  */
+
+_Unwind_Word
+_Unwind_GetCFA (_Unwind_Context *context)
+{
+  return ((phase1_vrs *) context)->prev_sp;
+}
+
+/* Perform phase1 unwinding.  UCBP is the exception being thrown, and
+   entry_VRS is the register state on entry to _Unwind_RaiseException.  */
+
+_Unwind_Reason_Code
+__gnu_Unwind_RaiseException (_Unwind_Control_Block *, phase2_vrs *);
+
+_Unwind_Reason_Code
+__gnu_Unwind_RaiseException (_Unwind_Control_Block * ucbp,
+                            phase2_vrs * entry_vrs)
+{
+  phase1_vrs saved_vrs;
+  _Unwind_Reason_Code pr_result;
+
+  /* Set the pc to the call site.  */
+  entry_vrs->core.r[R_PC] = entry_vrs->core.r[R_LR];
+
+  /* Save the core registers.  */
+  saved_vrs.core = entry_vrs->core;
+  /* Set demand-save flags.  */
+  saved_vrs.demand_save_flags = ~(_uw) 0;
+  
+  /* Unwind until we reach a propagation barrier.  */
+  do
+    {
+      /* Find the entry for this routine.  */
+      if (get_eit_entry (ucbp, saved_vrs.core.r[R_PC]) != _URC_OK)
+       return _URC_FAILURE;
+
+      /* Call the pr to decide what to do.  */
+      pr_result = ((personality_routine) UCB_PR_ADDR (ucbp))
+       (_US_VIRTUAL_UNWIND_FRAME, ucbp, (void *) &saved_vrs);
+    }
+  while (pr_result == _URC_CONTINUE_UNWIND);
+
+  /* We've unwound as far as we want to go, so restore the original
+     register state.  */
+  restore_non_core_regs (&saved_vrs);
+  if (pr_result != _URC_HANDLER_FOUND)
+    {
+      /* Some sort of failure has occurred in the pr and probably the
+        pr returned _URC_FAILURE.  */
+      return _URC_FAILURE;
+    }
+  
+  unwind_phase2 (ucbp, entry_vrs);
+}
+
+/* Resume unwinding after a cleanup has been run.  UCBP is the exception
+   being thrown and ENTRY_VRS is the register state on entry to
+   _Unwind_Resume.  */
+_Unwind_Reason_Code
+__gnu_Unwind_ForcedUnwind (_Unwind_Control_Block *,
+                          _Unwind_Stop_Fn, void *, phase2_vrs *);
+
+_Unwind_Reason_Code
+__gnu_Unwind_ForcedUnwind (_Unwind_Control_Block *ucbp,
+                          _Unwind_Stop_Fn stop_fn, void *stop_arg,
+                          phase2_vrs *entry_vrs)
+{
+  UCB_FORCED_STOP_FN (ucbp) = (_uw) stop_fn;
+  UCB_FORCED_STOP_ARG (ucbp) = (_uw) stop_arg;
+
+  /* Set the pc to the call site.  */
+  entry_vrs->core.r[R_PC] = entry_vrs->core.r[R_LR];
+
+  return unwind_phase2_forced (ucbp, entry_vrs, 0);
+}
+
+_Unwind_Reason_Code
+__gnu_Unwind_Resume (_Unwind_Control_Block *, phase2_vrs *);
+
+_Unwind_Reason_Code
+__gnu_Unwind_Resume (_Unwind_Control_Block * ucbp, phase2_vrs * entry_vrs)
+{
+  _Unwind_Reason_Code pr_result;
+
+  /* Recover the saved address.  */
+  entry_vrs->core.r[R_PC] = UCB_SAVED_CALLSITE_ADDR (ucbp);
+
+  if (UCB_FORCED_STOP_FN (ucbp))
+    {
+      unwind_phase2_forced (ucbp, entry_vrs, 1);
+
+      /* We can't return failure at this point.  */
+      abort ();
+    }
+
+  /* Call the cached PR.  */
+  pr_result = ((personality_routine) UCB_PR_ADDR (ucbp))
+       (_US_UNWIND_FRAME_RESUME, ucbp, (_Unwind_Context *) entry_vrs);
+
+  switch (pr_result)
+    {
+    case _URC_INSTALL_CONTEXT:
+      /* Upload the registers to enter the landing pad.  */
+      restore_core_regs (&entry_vrs->core);
+
+    case _URC_CONTINUE_UNWIND:
+      /* Continue unwinding the next frame.  */
+      unwind_phase2 (ucbp, entry_vrs);
+
+    default:
+      abort ();
+    }
+}
+
+_Unwind_Reason_Code
+__gnu_Unwind_Resume_or_Rethrow (_Unwind_Control_Block *, phase2_vrs *);
+
+_Unwind_Reason_Code
+__gnu_Unwind_Resume_or_Rethrow (_Unwind_Control_Block * ucbp,
+                               phase2_vrs * entry_vrs)
+{
+  if (!UCB_FORCED_STOP_FN (ucbp))
+    return __gnu_Unwind_RaiseException (ucbp, entry_vrs);
+
+  /* Set the pc to the call site.  */
+  entry_vrs->core.r[R_PC] = entry_vrs->core.r[R_LR];
+  /* Continue unwinding the next frame.  */
+  return unwind_phase2_forced (ucbp, entry_vrs, 0);
+}
+
+/* Clean up an exception object when unwinding is complete.  */
+void
+_Unwind_Complete (_Unwind_Control_Block * ucbp __attribute__((unused)))
+{
+}
+
+
+/* Get the _Unwind_Control_Block from an _Unwind_Context.  */
+
+static inline _Unwind_Control_Block *
+unwind_UCB_from_context (_Unwind_Context * context)
+{
+  return (_Unwind_Control_Block *) _Unwind_GetGR (context, R_IP);
+}
+
+
+/* Free an exception.  */
+
+void
+_Unwind_DeleteException (_Unwind_Exception * exc)
+{
+  if (exc->exception_cleanup)
+    (*exc->exception_cleanup) (_URC_FOREIGN_EXCEPTION_CAUGHT, exc);
+}
+
+
+/* Perform stack backtrace through unwind data.  */
+_Unwind_Reason_Code
+__gnu_Unwind_Backtrace(_Unwind_Trace_Fn trace, void * trace_argument,
+                      phase2_vrs * entry_vrs);
+_Unwind_Reason_Code
+__gnu_Unwind_Backtrace(_Unwind_Trace_Fn trace, void * trace_argument,
+                      phase2_vrs * entry_vrs)
+{
+  phase1_vrs saved_vrs;
+  _Unwind_Reason_Code code;
+
+  _Unwind_Control_Block ucb;
+  _Unwind_Control_Block *ucbp = &ucb;
+
+  /* Set the pc to the call site.  */
+  entry_vrs->core.r[R_PC] = entry_vrs->core.r[R_LR];
+
+  /* Save the core registers.  */
+  saved_vrs.core = entry_vrs->core;
+  /* Set demand-save flags.  */
+  saved_vrs.demand_save_flags = ~(_uw) 0;
+  
+  do
+    {
+      /* Find the entry for this routine.  */
+      if (get_eit_entry (ucbp, saved_vrs.core.r[R_PC]) != _URC_OK)
+       {
+         code = _URC_FAILURE;
+         break;
+       }
+
+      /* The dwarf unwinder assumes the context structure holds things
+        like the function and LSDA pointers.  The ARM implementation
+        caches these in the exception header (UCB).  To avoid
+        rewriting everything we make the virtual IP register point at
+        the UCB.  */
+      _Unwind_SetGR((_Unwind_Context *)&saved_vrs, 12, (_Unwind_Ptr) ucbp);
+
+      /* Call trace function.  */
+      if ((*trace) ((_Unwind_Context *) &saved_vrs, trace_argument) 
+         != _URC_NO_REASON)
+       {
+         code = _URC_FAILURE;
+         break;
+       }
+
+      /* Call the pr to decide what to do.  */
+      code = ((personality_routine) UCB_PR_ADDR (ucbp))
+       (_US_VIRTUAL_UNWIND_FRAME | _US_FORCE_UNWIND, 
+        ucbp, (void *) &saved_vrs);
+    }
+  while (code != _URC_END_OF_STACK
+        && code != _URC_FAILURE);
+
+  restore_non_core_regs (&saved_vrs);
+  return code;
+}
+
+
+/* Common implementation for ARM ABI defined personality routines.
+   ID is the index of the personality routine, other arguments are as defined
+   by __aeabi_unwind_cpp_pr{0,1,2}.  */
+
+static _Unwind_Reason_Code
+__gnu_unwind_pr_common (_Unwind_State state,
+                       _Unwind_Control_Block *ucbp,
+                       _Unwind_Context *context,
+                       int id)
+{
+  __gnu_unwind_state uws;
+  _uw *data;
+  _uw offset;
+  _uw len;
+  _uw rtti_count;
+  int phase2_call_unexpected_after_unwind = 0;
+  int in_range = 0;
+  int forced_unwind = state & _US_FORCE_UNWIND;
+
+  state &= _US_ACTION_MASK;
+
+  data = (_uw *) ucbp->pr_cache.ehtp;
+  uws.data = *(data++);
+  uws.next = data;
+  if (id == 0)
+    {
+      uws.data <<= 8;
+      uws.words_left = 0;
+      uws.bytes_left = 3;
+    }
+  else
+    {
+      uws.words_left = (uws.data >> 16) & 0xff;
+      uws.data <<= 16;
+      uws.bytes_left = 2;
+      data += uws.words_left;
+    }
+
+  /* Restore the saved pointer.  */
+  if (state == _US_UNWIND_FRAME_RESUME)
+    data = (_uw *) ucbp->cleanup_cache.bitpattern[0];
+
+  if ((ucbp->pr_cache.additional & 1) == 0)
+    {
+      /* Process descriptors.  */
+      while (*data)
+       {
+         _uw addr;
+         _uw fnstart;
+
+         if (id == 2)
+           {
+             len = ((EHT32 *) data)->length;
+             offset = ((EHT32 *) data)->offset;
+             data += 2;
+           }
+         else
+           {
+             len = ((EHT16 *) data)->length;
+             offset = ((EHT16 *) data)->offset;
+             data++;
+           }
+
+         fnstart = ucbp->pr_cache.fnstart + (offset & ~1);
+         addr = _Unwind_GetGR (context, R_PC);
+         in_range = (fnstart <= addr && addr < fnstart + (len & ~1));
+
+         switch (((offset & 1) << 1) | (len & 1))
+           {
+           case 0:
+             /* Cleanup.  */
+             if (state != _US_VIRTUAL_UNWIND_FRAME
+                 && in_range)
+               {
+                 /* Cleanup in range, and we are running cleanups.  */
+                 _uw lp;
+
+                 /* Landing pad address is 31-bit pc-relative offset.  */
+                 lp = selfrel_offset31 (data);
+                 data++;
+                 /* Save the exception data pointer.  */
+                 ucbp->cleanup_cache.bitpattern[0] = (_uw) data;
+                 if (!__cxa_begin_cleanup (ucbp))
+                   return _URC_FAILURE;
+                 /* Setup the VRS to enter the landing pad.  */
+                 _Unwind_SetGR (context, R_PC, lp);
+                 return _URC_INSTALL_CONTEXT;
+               }
+             /* Cleanup not in range, or we are in stage 1.  */
+             data++;
+             break;
+
+           case 1:
+             /* Catch handler.  */
+             if (state == _US_VIRTUAL_UNWIND_FRAME)
+               {
+                 if (in_range)
+                   {
+                     /* Check for a barrier.  */
+                     _uw rtti;
+                     bool is_reference = (data[0] & uint32_highbit) != 0;
+                     void *matched;
+                     enum __cxa_type_match_result match_type;
+
+                     /* Check for no-throw areas.  */
+                     if (data[1] == (_uw) -2)
+                       return _URC_FAILURE;
+
+                     /* The thrown object immediately follows the ECB.  */
+                     matched = (void *)(ucbp + 1);
+                     if (data[1] != (_uw) -1)
+                       {
+                         /* Match a catch specification.  */
+                         rtti = _Unwind_decode_target2 ((_uw) &data[1]);
+                         match_type = __cxa_type_match (ucbp,
+                                                        (type_info *) rtti,
+                                                        is_reference,
+                                                        &matched);
+                       }
+                     else
+                       match_type = ctm_succeeded;
+
+                     if (match_type)
+                       {
+                         ucbp->barrier_cache.sp =
+                           _Unwind_GetGR (context, R_SP);
+                         // ctm_succeeded_with_ptr_to_base really
+                         // means _c_t_m indirected the pointer
+                         // object.  We have to reconstruct the
+                         // additional pointer layer by using a temporary.
+                         if (match_type == ctm_succeeded_with_ptr_to_base)
+                           {
+                             ucbp->barrier_cache.bitpattern[2]
+                               = (_uw) matched;
+                             ucbp->barrier_cache.bitpattern[0]
+                               = (_uw) &ucbp->barrier_cache.bitpattern[2];
+                           }
+                         else
+                           ucbp->barrier_cache.bitpattern[0] = (_uw) matched;
+                         ucbp->barrier_cache.bitpattern[1] = (_uw) data;
+                         return _URC_HANDLER_FOUND;
+                       }
+                   }
+                 /* Handler out of range, or not matched.  */
+               }
+             else if (ucbp->barrier_cache.sp == _Unwind_GetGR (context, R_SP)
+                      && ucbp->barrier_cache.bitpattern[1] == (_uw) data)
+               {
+                 /* Matched a previous propagation barrier.  */
+                 _uw lp;
+
+                 /* Setup for entry to the handler.  */
+                 lp = selfrel_offset31 (data);
+                 _Unwind_SetGR (context, R_PC, lp);
+                 _Unwind_SetGR (context, 0, (_uw) ucbp);
+                 return _URC_INSTALL_CONTEXT;
+               }
+             /* Catch handler not matched.  Advance to the next descriptor.  */
+             data += 2;
+             break;
+
+           case 2:
+             rtti_count = data[0] & 0x7fffffff;
+             /* Exception specification.  */
+             if (state == _US_VIRTUAL_UNWIND_FRAME)
+               {
+                 if (in_range && (!forced_unwind || !rtti_count))
+                   {
+                     /* Match against the exception specification.  */
+                     _uw i;
+                     _uw rtti;
+                     void *matched;
+
+                     for (i = 0; i < rtti_count; i++)
+                       {
+                         matched = (void *)(ucbp + 1);
+                         rtti = _Unwind_decode_target2 ((_uw) &data[i + 1]);
+                         if (__cxa_type_match (ucbp, (type_info *) rtti, 0,
+                                               &matched))
+                           break;
+                       }
+
+                     if (i == rtti_count)
+                       {
+                         /* Exception does not match the spec.  */
+                         ucbp->barrier_cache.sp =
+                           _Unwind_GetGR (context, R_SP);
+                         ucbp->barrier_cache.bitpattern[0] = (_uw) matched;
+                         ucbp->barrier_cache.bitpattern[1] = (_uw) data;
+                         return _URC_HANDLER_FOUND;
+                       }
+                   }
+                 /* Handler out of range, or exception is permitted.  */
+               }
+             else if (ucbp->barrier_cache.sp == _Unwind_GetGR (context, R_SP)
+                      && ucbp->barrier_cache.bitpattern[1] == (_uw) data)
+               {
+                 /* Matched a previous propagation barrier.  */
+                 _uw lp;
+                 /* Record the RTTI list for __cxa_call_unexpected.  */
+                 ucbp->barrier_cache.bitpattern[1] = rtti_count;
+                 ucbp->barrier_cache.bitpattern[2] = 0;
+                 ucbp->barrier_cache.bitpattern[3] = 4;
+                 ucbp->barrier_cache.bitpattern[4] = (_uw) &data[1];
+
+                 if (data[0] & uint32_highbit)
+                   {
+                     data += rtti_count + 1;
+                     /* Setup for entry to the handler.  */
+                     lp = selfrel_offset31 (data);
+                     data++;
+                     _Unwind_SetGR (context, R_PC, lp);
+                     _Unwind_SetGR (context, 0, (_uw) ucbp);
+                     return _URC_INSTALL_CONTEXT;
+                   }
+                 else
+                   phase2_call_unexpected_after_unwind = 1;
+               }
+             if (data[0] & uint32_highbit)
+               data++;
+             data += rtti_count + 1;
+             break;
+
+           default:
+             /* Should never happen.  */
+             return _URC_FAILURE;
+           }
+         /* Finished processing this descriptor.  */
+       }
+    }
+
+  if (__gnu_unwind_execute (context, &uws) != _URC_OK)
+    return _URC_FAILURE;
+
+  if (phase2_call_unexpected_after_unwind)
+    {
+      /* Enter __cxa_unexpected as if called from the call site.  */
+      _Unwind_SetGR (context, R_LR, _Unwind_GetGR (context, R_PC));
+      _Unwind_SetGR (context, R_PC, (_uw) &__cxa_call_unexpected);
+      return _URC_INSTALL_CONTEXT;
+    }
+
+  return _URC_CONTINUE_UNWIND;
+}
+
+
+/* ABI defined personality routine entry points.  */
+
+_Unwind_Reason_Code
+__aeabi_unwind_cpp_pr0 (_Unwind_State state,
+                       _Unwind_Control_Block *ucbp,
+                       _Unwind_Context *context)
+{
+  return __gnu_unwind_pr_common (state, ucbp, context, 0);
+}
+
+_Unwind_Reason_Code
+__aeabi_unwind_cpp_pr1 (_Unwind_State state,
+                       _Unwind_Control_Block *ucbp,
+                       _Unwind_Context *context)
+{
+  return __gnu_unwind_pr_common (state, ucbp, context, 1);
+}
+
+_Unwind_Reason_Code
+__aeabi_unwind_cpp_pr2 (_Unwind_State state,
+                       _Unwind_Control_Block *ucbp,
+                       _Unwind_Context *context)
+{
+  return __gnu_unwind_pr_common (state, ucbp, context, 2);
+}
diff --git a/libgcc/config/arm/unwind-arm.h b/libgcc/config/arm/unwind-arm.h
new file mode 100644 (file)
index 0000000..1a51d8d
--- /dev/null
@@ -0,0 +1,281 @@
+/* Header file for the ARM EABI unwinder
+   Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2011
+   Free Software Foundation, Inc.
+   Contributed by Paul Brook
+
+   This file 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 3, or (at your option) any
+   later version.
+
+   This file 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.
+
+   Under Section 7 of GPL version 3, you are granted additional
+   permissions described in the GCC Runtime Library Exception, version
+   3.1, as published by the Free Software Foundation.
+
+   You should have received a copy of the GNU General Public License and
+   a copy of the GCC Runtime Library Exception along with this program;
+   see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+   <http://www.gnu.org/licenses/>.  */
+
+/* Language-independent unwinder header public defines.  This contains both
+   ABI defined objects, and GNU support routines.  */
+
+#ifndef UNWIND_ARM_H
+#define UNWIND_ARM_H
+
+#define __ARM_EABI_UNWINDER__ 1
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+  typedef unsigned _Unwind_Word __attribute__((__mode__(__word__)));
+  typedef signed _Unwind_Sword __attribute__((__mode__(__word__)));
+  typedef unsigned _Unwind_Ptr __attribute__((__mode__(__pointer__)));
+  typedef unsigned _Unwind_Internal_Ptr __attribute__((__mode__(__pointer__)));
+  typedef _Unwind_Word _uw;
+  typedef unsigned _uw64 __attribute__((mode(__DI__)));
+  typedef unsigned _uw16 __attribute__((mode(__HI__)));
+  typedef unsigned _uw8 __attribute__((mode(__QI__)));
+
+  typedef enum
+    {
+      _URC_OK = 0,       /* operation completed successfully */
+      _URC_FOREIGN_EXCEPTION_CAUGHT = 1,
+      _URC_END_OF_STACK = 5,
+      _URC_HANDLER_FOUND = 6,
+      _URC_INSTALL_CONTEXT = 7,
+      _URC_CONTINUE_UNWIND = 8,
+      _URC_FAILURE = 9   /* unspecified failure of some kind */
+    }
+  _Unwind_Reason_Code;
+
+  typedef enum
+    {
+      _US_VIRTUAL_UNWIND_FRAME = 0,
+      _US_UNWIND_FRAME_STARTING = 1,
+      _US_UNWIND_FRAME_RESUME = 2,
+      _US_ACTION_MASK = 3,
+      _US_FORCE_UNWIND = 8,
+      _US_END_OF_STACK = 16
+    }
+  _Unwind_State;
+
+  /* Provided only for compatibility with existing code.  */
+  typedef int _Unwind_Action;
+#define _UA_SEARCH_PHASE       1
+#define _UA_CLEANUP_PHASE      2
+#define _UA_HANDLER_FRAME      4
+#define _UA_FORCE_UNWIND       8
+#define _UA_END_OF_STACK       16
+#define _URC_NO_REASON         _URC_OK
+
+  typedef struct _Unwind_Control_Block _Unwind_Control_Block;
+  typedef struct _Unwind_Context _Unwind_Context;
+  typedef _uw _Unwind_EHT_Header;
+
+
+  /* UCB: */
+
+  struct _Unwind_Control_Block
+    {
+      char exception_class[8];
+      void (*exception_cleanup)(_Unwind_Reason_Code, _Unwind_Control_Block *);
+      /* Unwinder cache, private fields for the unwinder's use */
+      struct
+       {
+         _uw reserved1;  /* Forced unwind stop fn, 0 if not forced */
+         _uw reserved2;  /* Personality routine address */
+         _uw reserved3;  /* Saved callsite address */
+         _uw reserved4;  /* Forced unwind stop arg */
+         _uw reserved5;
+       }
+      unwinder_cache;
+      /* Propagation barrier cache (valid after phase 1): */
+      struct
+       {
+         _uw sp;
+         _uw bitpattern[5];
+       }
+      barrier_cache;
+      /* Cleanup cache (preserved over cleanup): */
+      struct
+       {
+         _uw bitpattern[4];
+       }
+      cleanup_cache;
+      /* Pr cache (for pr's benefit): */
+      struct
+       {
+         _uw fnstart;                  /* function start address */
+         _Unwind_EHT_Header *ehtp;     /* pointer to EHT entry header word */
+         _uw additional;               /* additional data */
+         _uw reserved1;
+       }
+      pr_cache;
+      long long int :0;        /* Force alignment to 8-byte boundary */
+    };
+
+  /* Virtual Register Set*/
+
+  typedef enum
+    {
+      _UVRSC_CORE = 0,      /* integer register */
+      _UVRSC_VFP = 1,       /* vfp */
+      _UVRSC_FPA = 2,       /* fpa */
+      _UVRSC_WMMXD = 3,     /* Intel WMMX data register */
+      _UVRSC_WMMXC = 4      /* Intel WMMX control register */
+    }
+  _Unwind_VRS_RegClass;
+
+  typedef enum
+    {
+      _UVRSD_UINT32 = 0,
+      _UVRSD_VFPX = 1,
+      _UVRSD_FPAX = 2,
+      _UVRSD_UINT64 = 3,
+      _UVRSD_FLOAT = 4,
+      _UVRSD_DOUBLE = 5
+    }
+  _Unwind_VRS_DataRepresentation;
+
+  typedef enum
+    {
+      _UVRSR_OK = 0,
+      _UVRSR_NOT_IMPLEMENTED = 1,
+      _UVRSR_FAILED = 2
+    }
+  _Unwind_VRS_Result;
+
+  /* Frame unwinding state.  */
+  typedef struct
+    {
+      /* The current word (bytes packed msb first).  */
+      _uw data;
+      /* Pointer to the next word of data.  */
+      _uw *next;
+      /* The number of bytes left in this word.  */
+      _uw8 bytes_left;
+      /* The number of words pointed to by ptr.  */
+      _uw8 words_left;
+    }
+  __gnu_unwind_state;
+
+  typedef _Unwind_Reason_Code (*personality_routine) (_Unwind_State,
+      _Unwind_Control_Block *, _Unwind_Context *);
+
+  _Unwind_VRS_Result _Unwind_VRS_Set(_Unwind_Context *, _Unwind_VRS_RegClass,
+                                     _uw, _Unwind_VRS_DataRepresentation,
+                                     void *);
+
+  _Unwind_VRS_Result _Unwind_VRS_Get(_Unwind_Context *, _Unwind_VRS_RegClass,
+                                     _uw, _Unwind_VRS_DataRepresentation,
+                                     void *);
+
+  _Unwind_VRS_Result _Unwind_VRS_Pop(_Unwind_Context *, _Unwind_VRS_RegClass,
+                                     _uw, _Unwind_VRS_DataRepresentation);
+
+
+  /* Support functions for the PR.  */
+#define _Unwind_Exception _Unwind_Control_Block
+  typedef char _Unwind_Exception_Class[8];
+
+  void * _Unwind_GetLanguageSpecificData (_Unwind_Context *);
+  _Unwind_Ptr _Unwind_GetRegionStart (_Unwind_Context *);
+
+  /* These two should never be used.  */
+  _Unwind_Ptr _Unwind_GetDataRelBase (_Unwind_Context *);
+  _Unwind_Ptr _Unwind_GetTextRelBase (_Unwind_Context *);
+
+  /* Interface functions: */
+  _Unwind_Reason_Code _Unwind_RaiseException(_Unwind_Control_Block *ucbp);
+  void __attribute__((noreturn)) _Unwind_Resume(_Unwind_Control_Block *ucbp);
+  _Unwind_Reason_Code _Unwind_Resume_or_Rethrow (_Unwind_Control_Block *ucbp);
+
+  typedef _Unwind_Reason_Code (*_Unwind_Stop_Fn)
+       (int, _Unwind_Action, _Unwind_Exception_Class,
+       _Unwind_Control_Block *, struct _Unwind_Context *, void *);
+  _Unwind_Reason_Code _Unwind_ForcedUnwind (_Unwind_Control_Block *,
+                                           _Unwind_Stop_Fn, void *);
+  /* @@@ Use unwind data to perform a stack backtrace.  The trace callback
+     is called for every stack frame in the call chain, but no cleanup
+     actions are performed.  */
+  typedef _Unwind_Reason_Code (*_Unwind_Trace_Fn) (_Unwind_Context *, void *);
+  _Unwind_Reason_Code _Unwind_Backtrace(_Unwind_Trace_Fn,
+                                       void*);
+
+  _Unwind_Word _Unwind_GetCFA (struct _Unwind_Context *);
+  void _Unwind_Complete(_Unwind_Control_Block *ucbp);
+  void _Unwind_DeleteException (_Unwind_Exception *);
+
+  _Unwind_Reason_Code __gnu_unwind_frame (_Unwind_Control_Block *,
+                                         _Unwind_Context *);
+  _Unwind_Reason_Code __gnu_unwind_execute (_Unwind_Context *,
+                                           __gnu_unwind_state *);
+
+  /* Decode an R_ARM_TARGET2 relocation.  */
+  static inline _Unwind_Word
+  _Unwind_decode_target2 (_Unwind_Word ptr)
+    {
+      _Unwind_Word tmp;
+
+      tmp = *(_Unwind_Word *) ptr;
+      /* Zero values are always NULL.  */
+      if (!tmp)
+       return 0;
+
+#if (defined(linux) && !defined(__uClinux__)) || defined(__NetBSD__)
+      /* Pc-relative indirect.  */
+      tmp += ptr;
+      tmp = *(_Unwind_Word *) tmp;
+#elif defined(__symbian__) || defined(__uClinux__)
+      /* Absolute pointer.  Nothing more to do.  */
+#else
+      /* Pc-relative pointer.  */
+      tmp += ptr;
+#endif
+      return tmp;
+    }
+
+  static inline _Unwind_Word
+  _Unwind_GetGR (_Unwind_Context *context, int regno)
+    {
+      _uw val;
+      _Unwind_VRS_Get (context, _UVRSC_CORE, regno, _UVRSD_UINT32, &val);
+      return val;
+    }
+
+  /* Return the address of the instruction, not the actual IP value.  */
+#define _Unwind_GetIP(context) \
+  (_Unwind_GetGR (context, 15) & ~(_Unwind_Word)1)
+
+#define _Unwind_GetIPInfo(context, ip_before_insn) \
+  (*ip_before_insn = 0, _Unwind_GetGR (context, 15) & ~(_Unwind_Word)1)
+
+  static inline void
+  _Unwind_SetGR (_Unwind_Context *context, int regno, _Unwind_Word val)
+    {
+      _Unwind_VRS_Set (context, _UVRSC_CORE, regno, _UVRSD_UINT32, &val);
+    }
+
+  /* The dwarf unwinder doesn't understand arm/thumb state.  We assume the
+     landing pad uses the same instruction set as the call site.  */
+#define _Unwind_SetIP(context, val) \
+  _Unwind_SetGR (context, 15, val | (_Unwind_GetGR (context, 15) & 1))
+
+/* leb128 type numbers have a potentially unlimited size.
+   The target of the following definitions of _sleb128_t and _uleb128_t
+   is to have efficient data types large enough to hold the leb128 type
+   numbers used in the unwind code.  */
+typedef long _sleb128_t;
+typedef unsigned long _uleb128_t;
+
+#ifdef __cplusplus
+}   /* extern "C" */
+#endif
+
+#endif /* defined UNWIND_ARM_H */
diff --git a/libgcc/config/ia64/fde-glibc.c b/libgcc/config/ia64/fde-glibc.c
new file mode 100644 (file)
index 0000000..12760b9
--- /dev/null
@@ -0,0 +1,162 @@
+/* Copyright (C) 2000, 2001, 2003, 2009 Free Software Foundation, Inc.
+   Contributed by Richard Henderson <rth@cygnus.com>.
+
+   This file is part of GCC.
+
+   GCC 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 3, or (at your option)
+   any later version.
+
+   GCC 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.
+
+   Under Section 7 of GPL version 3, you are granted additional
+   permissions described in the GCC Runtime Library Exception, version
+   3.1, as published by the Free Software Foundation.
+
+   You should have received a copy of the GNU General Public License and
+   a copy of the GCC Runtime Library Exception along with this program;
+   see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+   <http://www.gnu.org/licenses/>.  */
+
+/* Locate the FDE entry for a given address, using glibc ld.so routines
+   to avoid register/deregister calls at DSO load/unload.  */
+
+#ifndef _GNU_SOURCE
+#define _GNU_SOURCE 1
+#endif
+#include "config.h"
+#include <stddef.h>
+#include <stdlib.h>
+#include <link.h>
+#include "unwind-ia64.h"
+
+#if __GLIBC__ < 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ < 2) \
+    || (__GLIBC__ == 2 && __GLIBC_MINOR__ == 2 && !defined(DT_CONFIG))
+# error You need GLIBC 2.2.4 or later on IA-64 Linux
+#endif
+
+struct unw_ia64_callback_data
+{
+  Elf64_Addr pc;
+  unsigned long *segment_base;
+  unsigned long *gp;
+  struct unw_table_entry *ret;
+};
+
+static int
+_Unwind_IteratePhdrCallback (struct dl_phdr_info *info, size_t size, void *ptr)
+{
+  struct unw_ia64_callback_data *data = (struct unw_ia64_callback_data *) ptr;
+  const Elf64_Phdr *phdr, *p_unwind, *p_dynamic;
+  long n, match;
+  Elf64_Addr load_base, seg_base;
+  struct unw_table_entry *f_base, *f;
+  size_t lo, hi;
+
+  /* Make sure struct dl_phdr_info is at least as big as we need.  */
+  if (size < offsetof (struct dl_phdr_info, dlpi_phnum)
+            + sizeof (info->dlpi_phnum))
+    return -1;
+
+  match = 0;
+  phdr = info->dlpi_phdr;
+  load_base = info->dlpi_addr;
+  p_unwind = NULL;
+  p_dynamic = NULL;
+  seg_base = ~(Elf64_Addr) 0;
+
+  /* See if PC falls into one of the loaded segments.  Find the unwind
+     segment at the same time.  */
+  for (n = info->dlpi_phnum; --n >= 0; phdr++)
+    {
+      if (phdr->p_type == PT_LOAD)
+       {
+         Elf64_Addr vaddr = phdr->p_vaddr + load_base;
+         if (data->pc >= vaddr && data->pc < vaddr + phdr->p_memsz)
+           match = 1;
+         if (vaddr < seg_base)
+           seg_base = vaddr;
+       }
+      else if (phdr->p_type == PT_IA_64_UNWIND)
+       p_unwind = phdr;
+      else if (phdr->p_type == PT_DYNAMIC)
+       p_dynamic = phdr;
+    }
+  if (!match || !p_unwind)
+    return 0;
+
+  /* Search for the FDE within the unwind segment.  */
+
+  f_base = (struct unw_table_entry *) (p_unwind->p_vaddr + load_base);
+  lo = 0;
+  hi = p_unwind->p_memsz / sizeof (struct unw_table_entry);
+
+  while (lo < hi)
+    {
+      size_t mid = (lo + hi) / 2;
+
+      f = f_base + mid;
+      if (data->pc < f->start_offset + seg_base)
+       hi = mid;
+      else if (data->pc >= f->end_offset + seg_base)
+       lo = mid + 1;
+      else
+        goto found;
+    }
+  /* No need to search for further libraries when we know pc is contained
+     in this library.  */
+  return 1;
+
+ found:
+  *data->segment_base = seg_base;
+  *data->gp = 0;
+  data->ret = f;
+
+  if (p_dynamic)
+    {
+      /* For dynamically linked executables and shared libraries,
+        DT_PLTGOT is the gp value for that object.  */
+      Elf64_Dyn *dyn = (Elf64_Dyn *)(p_dynamic->p_vaddr + load_base);
+      for (; dyn->d_tag != DT_NULL ; dyn++)
+       if (dyn->d_tag == DT_PLTGOT)
+         {
+           /* On IA-64, _DYNAMIC is writable and GLIBC has relocated it.  */
+           *data->gp = dyn->d_un.d_ptr;
+           break;
+         }
+    }
+  else
+    {
+      /* Otherwise this is a static executable with no _DYNAMIC.
+        The gp is constant program-wide.  */
+      register unsigned long gp __asm__("gp");
+      *data->gp = gp;
+    }
+
+  return 1;
+}
+
+/* Return a pointer to the unwind table entry for the function
+   containing PC.  */
+
+struct unw_table_entry *
+_Unwind_FindTableEntry (void *pc, unsigned long *segment_base,
+                        unsigned long *gp,
+                        struct unw_table_entry *ent ATTRIBUTE_UNUSED)
+{
+  struct unw_ia64_callback_data data;
+
+  data.pc = (Elf64_Addr) pc;
+  data.segment_base = segment_base;
+  data.gp = gp;
+  data.ret = NULL;
+
+  if (dl_iterate_phdr (_Unwind_IteratePhdrCallback, &data) < 0)
+    return NULL;
+
+  return data.ret;
+}
diff --git a/libgcc/config/ia64/fde-vms.c b/libgcc/config/ia64/fde-vms.c
new file mode 100644 (file)
index 0000000..c9ac5d2
--- /dev/null
@@ -0,0 +1,158 @@
+/* Copyright (C) 2004, 2009, 2011 Free Software Foundation, Inc.
+   Contributed by Douglas B Rupp <rupp@gnat.com>
+
+   This file is part of GCC.
+
+   GCC 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 3, or (at your option)
+   any later version.
+
+   GCC 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.
+
+   Under Section 7 of GPL version 3, you are granted additional
+   permissions described in the GCC Runtime Library Exception, version
+   3.1, as published by the Free Software Foundation.
+
+   You should have received a copy of the GNU General Public License and
+   a copy of the GCC Runtime Library Exception along with this program;
+   see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+   <http://www.gnu.org/licenses/>.  */
+
+/* Locate the FDE entry for a given address, using VMS Starlet routines
+   to avoid register/deregister calls at DSO load/unload.  */
+
+#include "tconfig.h"
+#include "tsystem.h"
+#include "coretypes.h"
+#include "tm.h"
+#include <stddef.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include "md-unwind-support.h"
+#include "unwind-ia64.h"
+
+#define __int64 long
+#include <vms/ossddef.h>
+#ifndef SS$_NORMAL
+#define SS$_NORMAL 1
+#endif
+
+typedef struct
+{
+  unsigned long start_offset;
+  unsigned long end_offset;
+  unsigned long info_offset;
+  unsigned long gp_value;
+}  vms_unw_table_entry;
+
+typedef unsigned long long uqword;
+
+/* ENTRY is the unwind table entry found for a PC part of call chain we're
+   unwinding through.  Return whether we should force the generic unwinder
+   to resort to "fallback" processing.  */
+   
+static int
+force_fallback_processing_for (void * pc, vms_unw_table_entry * entry)
+{
+  static int eh_debug = -1;
+
+  uqword * unw_info_block = (uqword *)entry->info_offset;
+  uqword header = *unw_info_block;
+
+  /* We need to force fallback processing in two cases:
+
+     1/ The exception dispatch frame, since only our fallback
+        processing knows how to properly unwind through it, and
+
+     2/ A bottom of stack frame, since only our fallback processing
+        will ensure we don't try to unwind further past it, which
+        would get us into unknown territory and likely cause a severe
+        crash along the way.
+
+     The two cases are indicated by non-default values for specific
+     bits in the OS Specific Data (OSSD) General Information block
+     associated with such frames.  */
+
+  ossddef * ossd;
+
+  if (eh_debug == -1)
+    {
+      char * EH_DEBUG = getenv ("EH_DEBUG");
+      eh_debug = EH_DEBUG ? atoi (EH_DEBUG) : 0;
+    }
+
+  if (eh_debug)
+    {
+      printf ("pc @ 0x%p, block @ 0x%p, header = 0x%016llx\n",
+             pc, unw_info_block, header);
+      printf ("mode = %d, length = %ld, handler = %d\n",
+             (int)UNW_IVMS_MODE (header), UNW_LENGTH (header),
+             UNW_FLAG_EHANDLER (header) || UNW_FLAG_EHANDLER (header));
+    }
+
+  /* An OSSD block is there for IVMS_MODE == 3 only.  */
+  if (UNW_IVMS_MODE (header) != 3)
+    return 0;
+
+  /* The OSSD block is found past the header, unwind descriptor area
+     and condition handler pointer, if any.  */  
+  ossd = (ossddef *)
+    /* Beware: uqword pointer arithmetic below.  */
+    (unw_info_block
+     + 1
+     + UNW_LENGTH (header)
+     + (UNW_FLAG_EHANDLER (header) || UNW_FLAG_EHANDLER (header)));
+
+  /* "A General Information segment may be omitted if all of its fields
+      would have their default values.  If a General Information segment
+      is present, it must be the first in the OSSD area."  So ...  */
+  
+  if (eh_debug)
+    printf ("ossd @ 0x%p\n", ossd);
+      
+  if (eh_debug && ossd->ossd$v_type == OSSD$K_GENERAL_INFO)
+    printf ("exc_frame = %d - bot_frame = %d - base_frame = %d\n",
+           ossd->ossd$v_exception_frame, 
+           ossd->ossd$v_bottom_of_stack,
+           ossd->ossd$v_base_frame);
+                               
+  return
+    ossd->ossd$v_type == OSSD$K_GENERAL_INFO
+    && (ossd->ossd$v_exception_frame
+       || ossd->ossd$v_bottom_of_stack || ossd->ossd$v_base_frame);
+}
+
+/* Return a pointer to the unwind table entry for the function
+   containing PC, 0 if we cannot find an entry or if the one we find
+   calls for fallback processing.  */
+
+struct unw_table_entry *
+_Unwind_FindTableEntry (void *pc, unsigned long *segment_base,
+                        unsigned long *gp, struct unw_table_entry *ent)
+{
+  vms_unw_table_entry vueblock;
+
+  if (SYS$GET_UNWIND_ENTRY_INFO (pc, &vueblock, 0) != SS$_NORMAL)
+    return 0;
+
+  /* If there is no unwind information, use fallback.  */
+  if (vueblock.info_offset == 0)
+    return 0;
+
+  /* If we need to force fallback processing, just pretend there is
+     no entry.  */
+  if (force_fallback_processing_for (pc, &vueblock))
+    return 0;
+
+  *segment_base = 0; /* ??? Fixme. ??? */
+  *gp = vueblock.gp_value;
+  ent->start_offset = vueblock.start_offset;
+  ent->end_offset = vueblock.end_offset;
+  ent->info_offset = vueblock.info_offset;
+
+  return ent;
+}
diff --git a/libgcc/config/ia64/t-eh-ia64 b/libgcc/config/ia64/t-eh-ia64
new file mode 100644 (file)
index 0000000..6aa4bb9
--- /dev/null
@@ -0,0 +1,2 @@
+LIB2ADDEH = $(srcdir)/config/ia64/unwind-ia64.c $(srcdir)/unwind-sjlj.c \
+  $(srcdir)/unwind-c.c
diff --git a/libgcc/config/ia64/t-glibc b/libgcc/config/ia64/t-glibc
new file mode 100644 (file)
index 0000000..df4fe9c
--- /dev/null
@@ -0,0 +1,3 @@
+# Use system libunwind library on IA-64 GLIBC based system.
+LIB2ADDEH = $(srcdir)/unwind-sjlj.c $(srcdir)/unwind-c.c \
+  $(srcdir)/unwind-compat.c
diff --git a/libgcc/config/ia64/t-glibc-libunwind b/libgcc/config/ia64/t-glibc-libunwind
new file mode 100644 (file)
index 0000000..8b1736a
--- /dev/null
@@ -0,0 +1,3 @@
+# Build libunwind for IA-64 GLIBC based system.
+LIBUNWIND = $(srcdir)/config/ia64/fde-glibc.c \
+  $(srcdir)/config/ia64/unwind-ia64.c
diff --git a/libgcc/config/ia64/t-hpux b/libgcc/config/ia64/t-hpux
new file mode 100644 (file)
index 0000000..ef3387e
--- /dev/null
@@ -0,0 +1 @@
+LIB2ADDEH = $(srcdir)/unwind-c.c
diff --git a/libgcc/config/ia64/t-vms b/libgcc/config/ia64/t-vms
new file mode 100644 (file)
index 0000000..9bc933a
--- /dev/null
@@ -0,0 +1 @@
+LIB2ADDEH += $(srcdir)/config/ia64/fde-vms.c
diff --git a/libgcc/config/ia64/unwind-ia64.c b/libgcc/config/ia64/unwind-ia64.c
new file mode 100644 (file)
index 0000000..e9ddfca
--- /dev/null
@@ -0,0 +1,2458 @@
+/* Subroutines needed for unwinding IA-64 standard format stack frame
+   info for exception handling.
+   Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2004, 2005, 2006,
+   2009, 2011  Free Software Foundation, Inc.
+   Contributed by Andrew MacLeod  <amacleod@cygnus.com>
+                 Andrew Haley  <aph@cygnus.com>
+                 David Mosberger-Tang <davidm@hpl.hp.com>
+
+   This file is part of GCC.
+
+   GCC 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 3, or (at your option)
+   any later version.
+
+   GCC 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.
+
+   Under Section 7 of GPL version 3, you are granted additional
+   permissions described in the GCC Runtime Library Exception, version
+   3.1, as published by the Free Software Foundation.
+
+   You should have received a copy of the GNU General Public License and
+   a copy of the GCC Runtime Library Exception along with this program;
+   see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include "tconfig.h"
+#include "tsystem.h"
+#include "coretypes.h"
+#include "tm.h"
+#include "unwind.h"
+#include "unwind-ia64.h"
+#include "unwind-compat.h"
+#include "ia64intrin.h"
+
+/* This isn't thread safe, but nice for occasional tests.  */
+#undef ENABLE_MALLOC_CHECKING
+
+#ifndef __USING_SJLJ_EXCEPTIONS__
+
+enum unw_application_register
+{
+  UNW_AR_BSP,
+  UNW_AR_BSPSTORE,
+  UNW_AR_PFS,
+  UNW_AR_RNAT,
+  UNW_AR_UNAT,
+  UNW_AR_LC,
+  UNW_AR_EC,
+  UNW_AR_FPSR,
+  UNW_AR_RSC,
+  UNW_AR_CCV
+};
+
+enum unw_register_index
+{
+  /* Primary UNAT.  */
+  UNW_REG_PRI_UNAT_GR,
+  UNW_REG_PRI_UNAT_MEM,
+
+  /* Memory Stack.  */
+  UNW_REG_PSP,                 /* previous memory stack pointer */
+
+  /* Register Stack.  */
+  UNW_REG_BSP,                 /* register stack pointer */
+  UNW_REG_BSPSTORE,
+  UNW_REG_PFS,                 /* previous function state */
+  UNW_REG_RNAT,
+  /* Return Pointer.  */
+  UNW_REG_RP,
+
+  /* Special preserved registers.  */
+  UNW_REG_UNAT, UNW_REG_PR, UNW_REG_LC, UNW_REG_FPSR,
+
+  /* Non-stacked general registers.  */
+  UNW_REG_R2,
+  UNW_REG_R4 = UNW_REG_R2 + 2,
+  UNW_REG_R7 = UNW_REG_R2 + 5,
+  UNW_REG_R31 = UNW_REG_R2 + 29,
+
+  /* Non-stacked floating point registers.  */
+  UNW_REG_F2,
+  UNW_REG_F5 = UNW_REG_F2 + 3,
+  UNW_REG_F16 = UNW_REG_F2 + 14,
+  UNW_REG_F31 = UNW_REG_F2 + 29,
+
+  /* Branch registers.  */
+  UNW_REG_B0, UNW_REG_B1,
+  UNW_REG_B5 = UNW_REG_B1 + 4,
+
+  UNW_NUM_REGS
+};
+
+enum unw_where
+{
+  UNW_WHERE_NONE,      /* register isn't saved at all */
+  UNW_WHERE_GR,                /* register is saved in a general register */
+  UNW_WHERE_FR,                /* register is saved in a floating-point register */
+  UNW_WHERE_BR,                /* register is saved in a branch register */
+  UNW_WHERE_SPREL,     /* register is saved on memstack (sp-relative) */
+  UNW_WHERE_PSPREL,    /* register is saved on memstack (psp-relative) */
+ /* At the end of each prologue these locations get resolved to
+     UNW_WHERE_PSPREL and UNW_WHERE_GR, respectively.  */
+  UNW_WHERE_SPILL_HOME,        /* register is saved in its spill home */
+  UNW_WHERE_GR_SAVE    /* register is saved in next general register */
+};
+
+#define UNW_WHEN_NEVER  0x7fffffff
+
+struct unw_reg_info
+{
+  unsigned long val;           /* save location: register number or offset */
+  enum unw_where where;                /* where the register gets saved */
+  int when;                    /* when the register gets saved */
+};
+
+struct unw_reg_state {
+       struct unw_reg_state *next;     /* next (outer) element on state stack */
+       struct unw_reg_info reg[UNW_NUM_REGS];  /* register save locations */
+};
+
+struct unw_labeled_state {
+       struct unw_labeled_state *next;         /* next labeled state (or NULL) */
+       unsigned long label;                    /* label for this state */
+       struct unw_reg_state saved_state;
+};
+
+typedef struct unw_state_record
+{
+  unsigned int first_region : 1;       /* is this the first region? */
+  unsigned int done : 1;               /* are we done scanning descriptors? */
+  unsigned int any_spills : 1;         /* got any register spills? */
+  unsigned int in_body : 1;    /* are we inside a body? */
+  unsigned int no_reg_stack_frame : 1; /* Don't adjust bsp for i&l regs */
+  unsigned char *imask;                /* imask of spill_mask record or NULL */
+  unsigned long pr_val;                /* predicate values */
+  unsigned long pr_mask;       /* predicate mask */
+  long spill_offset;           /* psp-relative offset for spill base */
+  int region_start;
+  int region_len;
+  int epilogue_start;
+  int epilogue_count;
+  int when_target;
+
+  unsigned char gr_save_loc;   /* next general register to use for saving */
+  unsigned char return_link_reg; /* branch register for return link */
+  unsigned short unwabi;
+
+  struct unw_labeled_state *labeled_states;    /* list of all labeled states */
+  struct unw_reg_state curr;   /* current state */
+
+  _Unwind_Personality_Fn personality;
+  
+} _Unwind_FrameState;
+
+enum unw_nat_type
+{
+  UNW_NAT_NONE,                        /* NaT not represented */
+  UNW_NAT_VAL,                 /* NaT represented by NaT value (fp reg) */
+  UNW_NAT_MEMSTK,              /* NaT value is in unat word at offset OFF  */
+  UNW_NAT_REGSTK               /* NaT is in rnat */
+};
+
+struct unw_stack
+{
+  unsigned long limit;
+  unsigned long top;
+};
+
+struct _Unwind_Context
+{
+  /* Initial frame info.  */
+  unsigned long rnat;          /* rse nat collection */
+  unsigned long regstk_top;    /* lowest address of rbs stored register
+                                  which uses context->rnat collection */
+
+  /* Current frame info.  */
+  unsigned long bsp;           /* backing store pointer value
+                                  corresponding to psp.  */
+  unsigned long sp;            /* stack pointer value */
+  unsigned long psp;           /* previous sp value */
+  unsigned long rp;            /* return pointer */
+  unsigned long pr;            /* predicate collection */
+
+  unsigned long region_start;  /* start of unwind region */
+  unsigned long gp;            /* global pointer value */
+  void *lsda;                  /* language specific data area */
+
+  /* Preserved state.  */
+  unsigned long *bsp_loc;      /* previous bsp save location
+                                  Appears to be write-only?    */
+  unsigned long *bspstore_loc;
+  unsigned long *pfs_loc;      /* Save location for pfs in current
+                                  (corr. to sp) frame.  Target
+                                  contains cfm for caller.     */
+  unsigned long *signal_pfs_loc;/* Save location for pfs in current
+                                  signal frame.  Target contains
+                                  pfs for caller.  */
+  unsigned long *pri_unat_loc;
+  unsigned long *unat_loc;
+  unsigned long *lc_loc;
+  unsigned long *fpsr_loc;
+
+  unsigned long eh_data[4];
+
+  struct unw_ireg
+  {
+    unsigned long *loc;
+    struct unw_ireg_nat
+    {
+      enum unw_nat_type type : 3;
+      signed long off : 61;            /* NaT word is at loc+nat.off */
+    } nat;
+  } ireg[32 - 2];      /* Indexed by <register number> - 2 */
+
+  unsigned long *br_loc[8];
+  void *fr_loc[32 - 2];
+
+  /* ??? We initially point pri_unat_loc here.  The entire NAT bit
+     logic needs work.  */
+  unsigned long initial_unat;
+};
+
+typedef unsigned long unw_word;
+
+/* Implicit register save order.  See section 11.4.2.3 Rules for Using
+   Unwind Descriptors, rule 3.  */
+
+static unsigned char const save_order[] =
+{
+  UNW_REG_RP, UNW_REG_PFS, UNW_REG_PSP, UNW_REG_PR,
+  UNW_REG_UNAT, UNW_REG_LC, UNW_REG_FPSR, UNW_REG_PRI_UNAT_GR
+};
+
+\f
+#define MIN(X, Y) ((X) < (Y) ? (X) : (Y))
+
+/* MASK is a bitmap describing the allocation state of emergency buffers,
+   with bit set indicating free. Return >= 0 if allocation is successful;
+   < 0 if failure.  */
+
+static inline int
+atomic_alloc (unsigned int *mask)
+{
+  unsigned int old = *mask, ret, new;
+
+  while (1)
+    {
+      if (old == 0)
+       return -1;
+      ret = old & -old;
+      new = old & ~ret;
+      new = __sync_val_compare_and_swap (mask, old, new);
+      if (old == new)
+       break;
+      old = new;
+    }
+
+  return __builtin_ffs (ret) - 1;
+}
+
+/* Similarly, free an emergency buffer.  */
+
+static inline void
+atomic_free (unsigned int *mask, int bit)
+{
+  __sync_xor_and_fetch (mask, 1 << bit);
+}
+
+
+#define SIZE(X)                (sizeof(X) / sizeof(*(X)))
+#define MASK_FOR(X)    ((2U << (SIZE (X) - 1)) - 1)
+#define PTR_IN(X, P)   ((P) >= (X) && (P) < (X) + SIZE (X))
+
+static struct unw_reg_state emergency_reg_state[32];
+static unsigned int emergency_reg_state_free = MASK_FOR (emergency_reg_state);
+
+static struct unw_labeled_state emergency_labeled_state[8];
+static unsigned int emergency_labeled_state_free = MASK_FOR (emergency_labeled_state);
+
+#ifdef ENABLE_MALLOC_CHECKING
+static int reg_state_alloced;
+static int labeled_state_alloced;
+#endif
+
+/* Allocation and deallocation of structures.  */
+
+static struct unw_reg_state *
+alloc_reg_state (void)
+{
+  struct unw_reg_state *rs;
+
+#ifdef ENABLE_MALLOC_CHECKING
+  reg_state_alloced++;
+#endif
+
+  rs = malloc (sizeof (struct unw_reg_state));
+  if (!rs)
+    {
+      int n = atomic_alloc (&emergency_reg_state_free);
+      if (n >= 0)
+       rs = &emergency_reg_state[n];
+    }
+
+  return rs;
+}
+
+static void
+free_reg_state (struct unw_reg_state *rs)
+{
+#ifdef ENABLE_MALLOC_CHECKING
+  reg_state_alloced--;
+#endif
+
+  if (PTR_IN (emergency_reg_state, rs))
+    atomic_free (&emergency_reg_state_free, rs - emergency_reg_state);
+  else
+    free (rs);
+}
+
+static struct unw_labeled_state *
+alloc_label_state (void)
+{
+  struct unw_labeled_state *ls;
+
+#ifdef ENABLE_MALLOC_CHECKING
+  labeled_state_alloced++;
+#endif
+
+  ls = malloc(sizeof(struct unw_labeled_state));
+  if (!ls)
+    {
+      int n = atomic_alloc (&emergency_labeled_state_free);
+      if (n >= 0)
+       ls = &emergency_labeled_state[n];
+    }
+
+  return ls;
+}
+
+static void
+free_label_state (struct unw_labeled_state *ls)
+{
+#ifdef ENABLE_MALLOC_CHECKING
+  labeled_state_alloced--;
+#endif
+
+  if (PTR_IN (emergency_labeled_state, ls))
+    atomic_free (&emergency_labeled_state_free, emergency_labeled_state - ls);
+  else
+    free (ls);
+}
+
+/* Routines to manipulate the state stack.  */
+
+static void
+push (struct unw_state_record *sr)
+{
+  struct unw_reg_state *rs = alloc_reg_state ();
+  memcpy (rs, &sr->curr, sizeof (*rs));
+  sr->curr.next = rs;
+}
+
+static void
+pop (struct unw_state_record *sr)
+{
+  struct unw_reg_state *rs = sr->curr.next;
+
+  if (!rs)
+    abort ();
+  memcpy (&sr->curr, rs, sizeof(*rs));
+  free_reg_state (rs);
+}
+
+/* Make a copy of the state stack.  Non-recursive to avoid stack overflows.  */
+
+static struct unw_reg_state *
+dup_state_stack (struct unw_reg_state *rs)
+{
+  struct unw_reg_state *copy, *prev = NULL, *first = NULL;
+
+  while (rs)
+    {
+      copy = alloc_reg_state ();
+      memcpy (copy, rs, sizeof(*copy));
+      if (first)
+       prev->next = copy;
+      else
+       first = copy;
+      rs = rs->next;
+      prev = copy;
+    }
+
+  return first;
+}
+
+/* Free all stacked register states (but not RS itself).  */
+static void
+free_state_stack (struct unw_reg_state *rs)
+{
+  struct unw_reg_state *p, *next;
+
+  for (p = rs->next; p != NULL; p = next)
+    {
+      next = p->next;
+      free_reg_state (p);
+    }
+  rs->next = NULL;
+}
+
+/* Free all labeled states.  */
+
+static void
+free_label_states (struct unw_labeled_state *ls)
+{
+  struct unw_labeled_state *next;
+
+  for (; ls ; ls = next)
+    {
+      next = ls->next;
+
+      free_state_stack (&ls->saved_state);
+      free_label_state (ls);
+    }
+}
+\f
+/* Unwind decoder routines */
+
+static enum unw_register_index __attribute__((const))
+decode_abreg (unsigned char abreg, int memory)
+{
+  switch (abreg)
+    {
+#if TARGET_ABI_OPEN_VMS
+    /* OpenVMS Calling Standard specifies R3 - R31.  */
+    case 0x03 ... 0x1f: return UNW_REG_R2 + (abreg - 0x02);
+#else
+    /* Standard Intel ABI specifies GR 4 - 7.  */
+    case 0x04 ... 0x07: return UNW_REG_R4 + (abreg - 0x04);
+#endif
+    case 0x22 ... 0x25: return UNW_REG_F2 + (abreg - 0x22);
+    case 0x30 ... 0x3f: return UNW_REG_F16 + (abreg - 0x30);
+    case 0x41 ... 0x45: return UNW_REG_B1 + (abreg - 0x41);
+    case 0x60: return UNW_REG_PR;
+    case 0x61: return UNW_REG_PSP;
+    case 0x62: return memory ? UNW_REG_PRI_UNAT_MEM : UNW_REG_PRI_UNAT_GR;
+    case 0x63: return UNW_REG_RP;
+    case 0x64: return UNW_REG_BSP;
+    case 0x65: return UNW_REG_BSPSTORE;
+    case 0x66: return UNW_REG_RNAT;
+    case 0x67: return UNW_REG_UNAT;
+    case 0x68: return UNW_REG_FPSR;
+    case 0x69: return UNW_REG_PFS;
+    case 0x6a: return UNW_REG_LC;
+    default:
+      abort ();
+  }
+}
+
+static void
+set_reg (struct unw_reg_info *reg, enum unw_where where,
+        int when, unsigned long val)
+{
+  reg->val = val;
+  reg->where = where;
+  if (reg->when == UNW_WHEN_NEVER)
+    reg->when = when;
+}
+
+static void
+alloc_spill_area (unsigned long *offp, unsigned long regsize,
+                 struct unw_reg_info *lo, struct unw_reg_info *hi)
+{
+  struct unw_reg_info *reg;
+
+  for (reg = hi; reg >= lo; --reg)
+    {
+      if (reg->where == UNW_WHERE_SPILL_HOME)
+       {
+         reg->where = UNW_WHERE_PSPREL;
+         *offp -= regsize;
+         reg->val = *offp;
+       }
+    }
+}
+
+static inline void
+spill_next_when (struct unw_reg_info **regp, struct unw_reg_info *lim,
+                unw_word t)
+{
+  struct unw_reg_info *reg;
+
+  for (reg = *regp; reg <= lim; ++reg)
+    {
+      if (reg->where == UNW_WHERE_SPILL_HOME)
+       {
+         reg->when = t;
+         *regp = reg + 1;
+         return;
+       }
+    }
+  /* Excess spill.  */
+  abort ();
+}
+
+static void
+finish_prologue (struct unw_state_record *sr)
+{
+  struct unw_reg_info *reg;
+  unsigned long off;
+  int i;
+
+  /* First, resolve implicit register save locations
+     (see Section "11.4.2.3 Rules for Using Unwind Descriptors", rule 3).  */
+
+  for (i = 0; i < (int) sizeof (save_order); ++i)
+    {
+      reg = sr->curr.reg + save_order[i];
+      if (reg->where == UNW_WHERE_GR_SAVE)
+       {
+         reg->where = UNW_WHERE_GR;
+         reg->val = sr->gr_save_loc++;
+       }
+    }
+
+  /* Next, compute when the fp, general, and branch registers get saved.
+     This must come before alloc_spill_area() because we need to know
+     which registers are spilled to their home locations.  */
+  if (sr->imask)
+    {
+      static unsigned char const limit[3] = {
+       UNW_REG_F31, UNW_REG_R7, UNW_REG_B5
+      };
+
+      unsigned char kind, mask = 0, *cp = sr->imask;
+      int t;
+      struct unw_reg_info *(regs[3]);
+
+      regs[0] = sr->curr.reg + UNW_REG_F2;
+      regs[1] = sr->curr.reg + UNW_REG_R4;
+      regs[2] = sr->curr.reg + UNW_REG_B1;
+
+      for (t = 0; t < sr->region_len; ++t)
+       {
+         if ((t & 3) == 0)
+           mask = *cp++;
+         kind = (mask >> 2*(3-(t & 3))) & 3;
+         if (kind > 0)
+           spill_next_when (&regs[kind - 1], sr->curr.reg + limit[kind - 1],
+                            sr->region_start + t);
+       }
+    }
+
+  /* Next, lay out the memory stack spill area.  */
+  if (sr->any_spills)
+    {
+      off = sr->spill_offset;
+      alloc_spill_area (&off, 16, sr->curr.reg + UNW_REG_F2,
+                       sr->curr.reg + UNW_REG_F31); 
+      alloc_spill_area (&off,  8, sr->curr.reg + UNW_REG_B1,
+                       sr->curr.reg + UNW_REG_B5);
+      alloc_spill_area (&off,  8, sr->curr.reg + UNW_REG_R4,
+                       sr->curr.reg + UNW_REG_R7);
+    }
+}
+
+/*
+ * Region header descriptors.
+ */
+
+static void
+desc_prologue (int body, unw_word rlen, unsigned char mask,
+              unsigned char grsave, struct unw_state_record *sr)
+{
+  int i;
+
+  if (!(sr->in_body || sr->first_region))
+    finish_prologue (sr);
+  sr->first_region = 0;
+
+  /* Check if we're done.  */
+  if (sr->when_target < sr->region_start + sr->region_len) 
+    {
+      sr->done = 1;
+      return;
+    }
+
+  for (i = 0; i < sr->epilogue_count; ++i)
+    pop (sr);
+
+  sr->epilogue_count = 0;
+  sr->epilogue_start = UNW_WHEN_NEVER;
+
+  if (!body)
+    push (sr);
+
+  sr->region_start += sr->region_len;
+  sr->region_len = rlen;
+  sr->in_body = body;
+
+  if (!body)
+    {
+      for (i = 0; i < 4; ++i)
+       {
+         if (mask & 0x8)
+           set_reg (sr->curr.reg + save_order[i], UNW_WHERE_GR,
+                    sr->region_start + sr->region_len - 1, grsave++);
+         mask <<= 1;
+       }
+      sr->gr_save_loc = grsave;
+      sr->any_spills = 0;
+      sr->imask = 0;
+      sr->spill_offset = 0x10; /* default to psp+16 */
+    }
+}
+
+/*
+ * Prologue descriptors.
+ */
+
+static inline void
+desc_abi (unsigned char abi,
+         unsigned char context,
+         struct unw_state_record *sr)
+{
+  sr->unwabi = (abi << 8) | context;
+}
+
+static inline void
+desc_br_gr (unsigned char brmask, unsigned char gr,
+           struct unw_state_record *sr)
+{
+  int i;
+
+  for (i = 0; i < 5; ++i)
+    {
+      if (brmask & 1)
+       set_reg (sr->curr.reg + UNW_REG_B1 + i, UNW_WHERE_GR,
+                sr->region_start + sr->region_len - 1, gr++);
+      brmask >>= 1;
+    }
+}
+
+static inline void
+desc_br_mem (unsigned char brmask, struct unw_state_record *sr)
+{
+  int i;
+
+  for (i = 0; i < 5; ++i)
+    {
+      if (brmask & 1)
+       {
+         set_reg (sr->curr.reg + UNW_REG_B1 + i, UNW_WHERE_SPILL_HOME,
+                  sr->region_start + sr->region_len - 1, 0);
+         sr->any_spills = 1;
+       }
+      brmask >>= 1;
+    }
+}
+
+static inline void
+desc_frgr_mem (unsigned char grmask, unw_word frmask,
+              struct unw_state_record *sr)
+{
+  int i;
+
+  for (i = 0; i < 4; ++i)
+    {
+      if ((grmask & 1) != 0)
+       {
+         set_reg (sr->curr.reg + UNW_REG_R4 + i, UNW_WHERE_SPILL_HOME,
+                  sr->region_start + sr->region_len - 1, 0);
+         sr->any_spills = 1;
+       }
+      grmask >>= 1;
+    }
+  for (i = 0; i < 20; ++i)
+    {
+      if ((frmask & 1) != 0)
+       {
+         enum unw_register_index base = i < 4 ? UNW_REG_F2 : UNW_REG_F16 - 4;
+         set_reg (sr->curr.reg + base + i, UNW_WHERE_SPILL_HOME,
+                  sr->region_start + sr->region_len - 1, 0);
+         sr->any_spills = 1;
+       }
+      frmask >>= 1;
+    }
+}
+
+static inline void
+desc_fr_mem (unsigned char frmask, struct unw_state_record *sr)
+{
+  int i;
+
+  for (i = 0; i < 4; ++i)
+    {
+      if ((frmask & 1) != 0)
+       {
+         set_reg (sr->curr.reg + UNW_REG_F2 + i, UNW_WHERE_SPILL_HOME,
+                  sr->region_start + sr->region_len - 1, 0);
+         sr->any_spills = 1;
+       }
+      frmask >>= 1;
+    }
+}
+
+static inline void
+desc_gr_gr (unsigned char grmask, unsigned char gr,
+           struct unw_state_record *sr)
+{
+  int i;
+
+  for (i = 0; i < 4; ++i)
+    {
+      if ((grmask & 1) != 0)
+       set_reg (sr->curr.reg + UNW_REG_R4 + i, UNW_WHERE_GR,
+                sr->region_start + sr->region_len - 1, gr++);
+      grmask >>= 1;
+    }
+}
+
+static inline void
+desc_gr_mem (unsigned char grmask, struct unw_state_record *sr)
+{
+  int i;
+
+  for (i = 0; i < 4; ++i)
+    {
+      if ((grmask & 1) != 0)
+       {
+         set_reg (sr->curr.reg + UNW_REG_R4 + i, UNW_WHERE_SPILL_HOME,
+                  sr->region_start + sr->region_len - 1, 0);
+         sr->any_spills = 1;
+       }
+      grmask >>= 1;
+    }
+}
+
+static inline void
+desc_mem_stack_f (unw_word t, unw_word size, struct unw_state_record *sr)
+{
+  set_reg (sr->curr.reg + UNW_REG_PSP, UNW_WHERE_NONE,
+          sr->region_start + MIN ((int)t, sr->region_len - 1), 16*size);
+}
+
+static inline void
+desc_mem_stack_v (unw_word t, struct unw_state_record *sr)
+{
+  sr->curr.reg[UNW_REG_PSP].when
+    = sr->region_start + MIN ((int)t, sr->region_len - 1);
+}
+
+static inline void
+desc_reg_gr (unsigned char reg, unsigned char dst, struct unw_state_record *sr)
+{
+  set_reg (sr->curr.reg + reg, UNW_WHERE_GR,
+          sr->region_start + sr->region_len - 1, dst);
+}
+
+static inline void
+desc_reg_psprel (unsigned char reg, unw_word pspoff,
+                struct unw_state_record *sr)
+{
+  set_reg (sr->curr.reg + reg, UNW_WHERE_PSPREL,
+          sr->region_start + sr->region_len - 1,
+          0x10 - 4*pspoff);
+}
+
+static inline void
+desc_reg_sprel (unsigned char reg, unw_word spoff, struct unw_state_record *sr)
+{
+  set_reg (sr->curr.reg + reg, UNW_WHERE_SPREL,
+          sr->region_start + sr->region_len - 1,
+          4*spoff);
+}
+
+static inline void
+desc_rp_br (unsigned char dst, struct unw_state_record *sr)
+{
+  sr->return_link_reg = dst;
+}
+
+static inline void
+desc_reg_when (unsigned char regnum, unw_word t, struct unw_state_record *sr)
+{
+  struct unw_reg_info *reg = sr->curr.reg + regnum;
+
+  if (reg->where == UNW_WHERE_NONE)
+    reg->where = UNW_WHERE_GR_SAVE;
+  reg->when = sr->region_start + MIN ((int)t, sr->region_len - 1);
+}
+
+static inline void
+desc_spill_base (unw_word pspoff, struct unw_state_record *sr)
+{
+  sr->spill_offset = 0x10 - 4*pspoff;
+}
+
+static inline unsigned char *
+desc_spill_mask (unsigned char *imaskp, struct unw_state_record *sr)
+{
+  sr->imask = imaskp;
+  return imaskp + (2*sr->region_len + 7)/8;
+}
+
+/*
+ * Body descriptors.
+ */
+static inline void
+desc_epilogue (unw_word t, unw_word ecount, struct unw_state_record *sr)
+{
+  sr->epilogue_start = sr->region_start + sr->region_len - 1 - t;
+  sr->epilogue_count = ecount + 1;
+}
+
+static inline void
+desc_copy_state (unw_word label, struct unw_state_record *sr)
+{
+  struct unw_labeled_state *ls;
+
+  for (ls = sr->labeled_states; ls; ls = ls->next)
+    {
+      if (ls->label == label)
+        {
+         free_state_stack (&sr->curr);
+         memcpy (&sr->curr, &ls->saved_state, sizeof (sr->curr));
+         sr->curr.next = dup_state_stack (ls->saved_state.next);
+         return;
+       }
+    }
+  abort ();
+}
+
+static inline void
+desc_label_state (unw_word label, struct unw_state_record *sr)
+{
+  struct unw_labeled_state *ls = alloc_label_state ();
+
+  ls->label = label;
+  memcpy (&ls->saved_state, &sr->curr, sizeof (ls->saved_state));
+  ls->saved_state.next = dup_state_stack (sr->curr.next);
+
+  /* Insert into list of labeled states.  */
+  ls->next = sr->labeled_states;
+  sr->labeled_states = ls;
+}
+
+/*
+ * General descriptors.
+ */
+
+static inline int
+desc_is_active (unsigned char qp, unw_word t, struct unw_state_record *sr)
+{
+  if (sr->when_target <= sr->region_start + MIN ((int)t, sr->region_len - 1))
+    return 0;
+  if (qp > 0)
+    {
+      if ((sr->pr_val & (1UL << qp)) == 0) 
+       return 0;
+      sr->pr_mask |= (1UL << qp);
+    }
+  return 1;
+}
+
+static inline void
+desc_restore_p (unsigned char qp, unw_word t, unsigned char abreg,
+               struct unw_state_record *sr)
+{
+  struct unw_reg_info *r;
+
+  if (! desc_is_active (qp, t, sr))
+    return;
+
+  r = sr->curr.reg + decode_abreg (abreg, 0);
+  r->where = UNW_WHERE_NONE;
+  r->when = sr->region_start + MIN ((int)t, sr->region_len - 1);
+  r->val = 0;
+}
+
+static inline void
+desc_spill_reg_p (unsigned char qp, unw_word t, unsigned char abreg,
+                 unsigned char x, unsigned char ytreg,
+                 struct unw_state_record *sr)
+{
+  enum unw_where where = UNW_WHERE_GR;
+  struct unw_reg_info *r;
+
+  if (! desc_is_active (qp, t, sr))
+    return;
+
+  if (x)
+    where = UNW_WHERE_BR;
+  else if (ytreg & 0x80)
+    where = UNW_WHERE_FR;
+
+  r = sr->curr.reg + decode_abreg (abreg, 0);
+  r->where = where;
+  r->when = sr->region_start + MIN ((int)t, sr->region_len - 1);
+  r->val = ytreg & 0x7f;
+}
+
+static inline void
+desc_spill_psprel_p (unsigned char qp, unw_word t, unsigned char abreg,
+                    unw_word pspoff, struct unw_state_record *sr)
+{
+  struct unw_reg_info *r;
+
+  if (! desc_is_active (qp, t, sr))
+    return;
+
+  r = sr->curr.reg + decode_abreg (abreg, 1);
+  r->where = UNW_WHERE_PSPREL;
+  r->when = sr->region_start + MIN((int)t, sr->region_len - 1);
+  r->val = 0x10 - 4*pspoff;
+}
+
+static inline void
+desc_spill_sprel_p (unsigned char qp, unw_word t, unsigned char abreg,
+                   unw_word spoff, struct unw_state_record *sr)
+{
+  struct unw_reg_info *r;
+
+  if (! desc_is_active (qp, t, sr))
+    return;
+
+  r = sr->curr.reg + decode_abreg (abreg, 1);
+  r->where = UNW_WHERE_SPREL;
+  r->when = sr->region_start + MIN ((int)t, sr->region_len - 1);
+  r->val = 4*spoff;
+}
+
+\f
+#define UNW_DEC_BAD_CODE(code)                 abort ();
+
+/* Region headers.  */
+#define UNW_DEC_PROLOGUE_GR(fmt,r,m,gr,arg)    desc_prologue(0,r,m,gr,arg)
+#define UNW_DEC_PROLOGUE(fmt,b,r,arg)          desc_prologue(b,r,0,32,arg)
+
+/* Prologue descriptors.  */
+#define UNW_DEC_ABI(fmt,a,c,arg)               desc_abi(a,c,arg)
+#define UNW_DEC_BR_GR(fmt,b,g,arg)             desc_br_gr(b,g,arg)
+#define UNW_DEC_BR_MEM(fmt,b,arg)              desc_br_mem(b,arg)
+#define UNW_DEC_FRGR_MEM(fmt,g,f,arg)          desc_frgr_mem(g,f,arg)
+#define UNW_DEC_FR_MEM(fmt,f,arg)              desc_fr_mem(f,arg)
+#define UNW_DEC_GR_GR(fmt,m,g,arg)             desc_gr_gr(m,g,arg)
+#define UNW_DEC_GR_MEM(fmt,m,arg)              desc_gr_mem(m,arg)
+#define UNW_DEC_MEM_STACK_F(fmt,t,s,arg)       desc_mem_stack_f(t,s,arg)
+#define UNW_DEC_MEM_STACK_V(fmt,t,arg)         desc_mem_stack_v(t,arg)
+#define UNW_DEC_REG_GR(fmt,r,d,arg)            desc_reg_gr(r,d,arg)
+#define UNW_DEC_REG_PSPREL(fmt,r,o,arg)                desc_reg_psprel(r,o,arg)
+#define UNW_DEC_REG_SPREL(fmt,r,o,arg)         desc_reg_sprel(r,o,arg)
+#define UNW_DEC_REG_WHEN(fmt,r,t,arg)          desc_reg_when(r,t,arg)
+#define UNW_DEC_PRIUNAT_WHEN_GR(fmt,t,arg)     desc_reg_when(UNW_REG_PRI_UNAT_GR,t,arg)
+#define UNW_DEC_PRIUNAT_WHEN_MEM(fmt,t,arg)    desc_reg_when(UNW_REG_PRI_UNAT_MEM,t,arg)
+#define UNW_DEC_PRIUNAT_GR(fmt,r,arg)          desc_reg_gr(UNW_REG_PRI_UNAT_GR,r,arg)
+#define UNW_DEC_PRIUNAT_PSPREL(fmt,o,arg)      desc_reg_psprel(UNW_REG_PRI_UNAT_MEM,o,arg)
+#define UNW_DEC_PRIUNAT_SPREL(fmt,o,arg)       desc_reg_sprel(UNW_REG_PRI_UNAT_MEM,o,arg)
+#define UNW_DEC_RP_BR(fmt,d,arg)               desc_rp_br(d,arg)
+#define UNW_DEC_SPILL_BASE(fmt,o,arg)          desc_spill_base(o,arg)
+#define UNW_DEC_SPILL_MASK(fmt,m,arg)          (m = desc_spill_mask(m,arg))
+
+/* Body descriptors.  */
+#define UNW_DEC_EPILOGUE(fmt,t,c,arg)          desc_epilogue(t,c,arg)
+#define UNW_DEC_COPY_STATE(fmt,l,arg)          desc_copy_state(l,arg)
+#define UNW_DEC_LABEL_STATE(fmt,l,arg)         desc_label_state(l,arg)
+
+/* General unwind descriptors.  */
+#define UNW_DEC_SPILL_REG_P(f,p,t,a,x,y,arg)   desc_spill_reg_p(p,t,a,x,y,arg)
+#define UNW_DEC_SPILL_REG(f,t,a,x,y,arg)       desc_spill_reg_p(0,t,a,x,y,arg)
+#define UNW_DEC_SPILL_PSPREL_P(f,p,t,a,o,arg)  desc_spill_psprel_p(p,t,a,o,arg)
+#define UNW_DEC_SPILL_PSPREL(f,t,a,o,arg)      desc_spill_psprel_p(0,t,a,o,arg)
+#define UNW_DEC_SPILL_SPREL_P(f,p,t,a,o,arg)   desc_spill_sprel_p(p,t,a,o,arg)
+#define UNW_DEC_SPILL_SPREL(f,t,a,o,arg)       desc_spill_sprel_p(0,t,a,o,arg)
+#define UNW_DEC_RESTORE_P(f,p,t,a,arg)         desc_restore_p(p,t,a,arg)
+#define UNW_DEC_RESTORE(f,t,a,arg)             desc_restore_p(0,t,a,arg)
+
+\f
+/*
+ * Generic IA-64 unwind info decoder.
+ *
+ * This file is used both by the Linux kernel and objdump.  Please keep
+ * the copies of this file in sync.
+ *
+ * You need to customize the decoder by defining the following
+ * macros/constants before including this file:
+ *
+ *  Types:
+ *     unw_word        Unsigned integer type with at least 64 bits 
+ *
+ *  Register names:
+ *     UNW_REG_BSP
+ *     UNW_REG_BSPSTORE
+ *     UNW_REG_FPSR
+ *     UNW_REG_LC
+ *     UNW_REG_PFS
+ *     UNW_REG_PR
+ *     UNW_REG_RNAT
+ *     UNW_REG_PSP
+ *     UNW_REG_RP
+ *     UNW_REG_UNAT
+ *
+ *  Decoder action macros:
+ *     UNW_DEC_BAD_CODE(code)
+ *     UNW_DEC_ABI(fmt,abi,context,arg)
+ *     UNW_DEC_BR_GR(fmt,brmask,gr,arg)
+ *     UNW_DEC_BR_MEM(fmt,brmask,arg)
+ *     UNW_DEC_COPY_STATE(fmt,label,arg)
+ *     UNW_DEC_EPILOGUE(fmt,t,ecount,arg)
+ *     UNW_DEC_FRGR_MEM(fmt,grmask,frmask,arg)
+ *     UNW_DEC_FR_MEM(fmt,frmask,arg)
+ *     UNW_DEC_GR_GR(fmt,grmask,gr,arg)
+ *     UNW_DEC_GR_MEM(fmt,grmask,arg)
+ *     UNW_DEC_LABEL_STATE(fmt,label,arg)
+ *     UNW_DEC_MEM_STACK_F(fmt,t,size,arg)
+ *     UNW_DEC_MEM_STACK_V(fmt,t,arg)
+ *     UNW_DEC_PRIUNAT_GR(fmt,r,arg)
+ *     UNW_DEC_PRIUNAT_WHEN_GR(fmt,t,arg)
+ *     UNW_DEC_PRIUNAT_WHEN_MEM(fmt,t,arg)
+ *     UNW_DEC_PRIUNAT_WHEN_PSPREL(fmt,pspoff,arg)
+ *     UNW_DEC_PRIUNAT_WHEN_SPREL(fmt,spoff,arg)
+ *     UNW_DEC_PROLOGUE(fmt,body,rlen,arg)
+ *     UNW_DEC_PROLOGUE_GR(fmt,rlen,mask,grsave,arg)
+ *     UNW_DEC_REG_PSPREL(fmt,reg,pspoff,arg)
+ *     UNW_DEC_REG_REG(fmt,src,dst,arg)
+ *     UNW_DEC_REG_SPREL(fmt,reg,spoff,arg)
+ *     UNW_DEC_REG_WHEN(fmt,reg,t,arg)
+ *     UNW_DEC_RESTORE(fmt,t,abreg,arg)
+ *     UNW_DEC_RESTORE_P(fmt,qp,t,abreg,arg)
+ *     UNW_DEC_SPILL_BASE(fmt,pspoff,arg)
+ *     UNW_DEC_SPILL_MASK(fmt,imaskp,arg)
+ *     UNW_DEC_SPILL_PSPREL(fmt,t,abreg,pspoff,arg)
+ *     UNW_DEC_SPILL_PSPREL_P(fmt,qp,t,abreg,pspoff,arg)
+ *     UNW_DEC_SPILL_REG(fmt,t,abreg,x,ytreg,arg)
+ *     UNW_DEC_SPILL_REG_P(fmt,qp,t,abreg,x,ytreg,arg)
+ *     UNW_DEC_SPILL_SPREL(fmt,t,abreg,spoff,arg)
+ *     UNW_DEC_SPILL_SPREL_P(fmt,qp,t,abreg,pspoff,arg)
+ */
+
+static unw_word
+unw_decode_uleb128 (unsigned char **dpp)
+{
+  unsigned shift = 0;
+  unw_word byte, result = 0;
+  unsigned char *bp = *dpp;
+
+  while (1)
+    {
+      byte = *bp++;
+      result |= (byte & 0x7f) << shift;
+      if ((byte & 0x80) == 0)
+       break;
+      shift += 7;
+    }
+  *dpp = bp;
+  return result;
+}
+
+static unsigned char *
+unw_decode_x1 (unsigned char *dp,
+              unsigned char code __attribute__((unused)),
+              void *arg)
+{
+  unsigned char byte1, abreg;
+  unw_word t, off;
+
+  byte1 = *dp++;
+  t = unw_decode_uleb128 (&dp);
+  off = unw_decode_uleb128 (&dp);
+  abreg = (byte1 & 0x7f);
+  if (byte1 & 0x80)
+         UNW_DEC_SPILL_SPREL(X1, t, abreg, off, arg);
+  else
+         UNW_DEC_SPILL_PSPREL(X1, t, abreg, off, arg);
+  return dp;
+}
+
+static unsigned char *
+unw_decode_x2 (unsigned char *dp,
+              unsigned char code __attribute__((unused)),
+              void *arg)
+{
+  unsigned char byte1, byte2, abreg, x, ytreg;
+  unw_word t;
+
+  byte1 = *dp++; byte2 = *dp++;
+  t = unw_decode_uleb128 (&dp);
+  abreg = (byte1 & 0x7f);
+  ytreg = byte2;
+  x = (byte1 >> 7) & 1;
+  if ((byte1 & 0x80) == 0 && ytreg == 0)
+    UNW_DEC_RESTORE(X2, t, abreg, arg);
+  else
+    UNW_DEC_SPILL_REG(X2, t, abreg, x, ytreg, arg);
+  return dp;
+}
+
+static unsigned char *
+unw_decode_x3 (unsigned char *dp,
+              unsigned char code __attribute__((unused)),
+              void *arg)
+{
+  unsigned char byte1, byte2, abreg, qp;
+  unw_word t, off;
+
+  byte1 = *dp++; byte2 = *dp++;
+  t = unw_decode_uleb128 (&dp);
+  off = unw_decode_uleb128 (&dp);
+
+  qp = (byte1 & 0x3f);
+  abreg = (byte2 & 0x7f);
+
+  if (byte1 & 0x80)
+    UNW_DEC_SPILL_SPREL_P(X3, qp, t, abreg, off, arg);
+  else
+    UNW_DEC_SPILL_PSPREL_P(X3, qp, t, abreg, off, arg);
+  return dp;
+}
+
+static unsigned char *
+unw_decode_x4 (unsigned char *dp,
+              unsigned char code __attribute__((unused)),
+              void *arg)
+{
+  unsigned char byte1, byte2, byte3, qp, abreg, x, ytreg;
+  unw_word t;
+
+  byte1 = *dp++; byte2 = *dp++; byte3 = *dp++;
+  t = unw_decode_uleb128 (&dp);
+
+  qp = (byte1 & 0x3f);
+  abreg = (byte2 & 0x7f);
+  x = (byte2 >> 7) & 1;
+  ytreg = byte3;
+
+  if ((byte2 & 0x80) == 0 && byte3 == 0)
+    UNW_DEC_RESTORE_P(X4, qp, t, abreg, arg);
+  else
+    UNW_DEC_SPILL_REG_P(X4, qp, t, abreg, x, ytreg, arg);
+  return dp;
+}
+
+static unsigned char *
+unw_decode_r1 (unsigned char *dp, unsigned char code, void *arg)
+{
+  int body = (code & 0x20) != 0;
+  unw_word rlen;
+
+  rlen = (code & 0x1f);
+  UNW_DEC_PROLOGUE(R1, body, rlen, arg);
+  return dp;
+}
+
+static unsigned char *
+unw_decode_r2 (unsigned char *dp, unsigned char code, void *arg)
+{
+  unsigned char byte1, mask, grsave;
+  unw_word rlen;
+
+  byte1 = *dp++;
+
+  mask = ((code & 0x7) << 1) | ((byte1 >> 7) & 1);
+  grsave = (byte1 & 0x7f);
+  rlen = unw_decode_uleb128 (&dp);
+  UNW_DEC_PROLOGUE_GR(R2, rlen, mask, grsave, arg);
+  return dp;
+}
+
+static unsigned char *
+unw_decode_r3 (unsigned char *dp, unsigned char code, void *arg)
+{
+  unw_word rlen;
+
+  rlen = unw_decode_uleb128 (&dp);
+  UNW_DEC_PROLOGUE(R3, ((code & 0x3) == 1), rlen, arg);
+  return dp;
+}
+
+static unsigned char *
+unw_decode_p1 (unsigned char *dp, unsigned char code, void *arg)
+{
+  unsigned char brmask = (code & 0x1f);
+
+  UNW_DEC_BR_MEM(P1, brmask, arg);
+  return dp;
+}
+
+static unsigned char *
+unw_decode_p2_p5 (unsigned char *dp, unsigned char code, void *arg)
+{
+  if ((code & 0x10) == 0)
+    {
+      unsigned char byte1 = *dp++;
+
+      UNW_DEC_BR_GR(P2, ((code & 0xf) << 1) | ((byte1 >> 7) & 1),
+                   (byte1 & 0x7f), arg);
+    }
+  else if ((code & 0x08) == 0)
+    {
+      unsigned char byte1 = *dp++, r, dst;
+
+      r = ((code & 0x7) << 1) | ((byte1 >> 7) & 1);
+      dst = (byte1 & 0x7f);
+      switch (r)
+       {
+       case 0: UNW_DEC_REG_GR(P3, UNW_REG_PSP, dst, arg); break;
+       case 1: UNW_DEC_REG_GR(P3, UNW_REG_RP, dst, arg); break;
+       case 2: UNW_DEC_REG_GR(P3, UNW_REG_PFS, dst, arg); break;
+       case 3: UNW_DEC_REG_GR(P3, UNW_REG_PR, dst, arg); break;
+       case 4: UNW_DEC_REG_GR(P3, UNW_REG_UNAT, dst, arg); break;
+       case 5: UNW_DEC_REG_GR(P3, UNW_REG_LC, dst, arg); break;
+       case 6: UNW_DEC_RP_BR(P3, dst, arg); break;
+       case 7: UNW_DEC_REG_GR(P3, UNW_REG_RNAT, dst, arg); break;
+       case 8: UNW_DEC_REG_GR(P3, UNW_REG_BSP, dst, arg); break;
+       case 9: UNW_DEC_REG_GR(P3, UNW_REG_BSPSTORE, dst, arg); break;
+       case 10: UNW_DEC_REG_GR(P3, UNW_REG_FPSR, dst, arg); break;
+       case 11: UNW_DEC_PRIUNAT_GR(P3, dst, arg); break;
+       default: UNW_DEC_BAD_CODE(r); break;
+       }
+    }
+  else if ((code & 0x7) == 0)
+    UNW_DEC_SPILL_MASK(P4, dp, arg);
+  else if ((code & 0x7) == 1)
+    {
+      unw_word grmask, frmask, byte1, byte2, byte3;
+
+      byte1 = *dp++; byte2 = *dp++; byte3 = *dp++;
+      grmask = ((byte1 >> 4) & 0xf);
+      frmask = ((byte1 & 0xf) << 16) | (byte2 << 8) | byte3;
+      UNW_DEC_FRGR_MEM(P5, grmask, frmask, arg);
+    }
+  else
+    UNW_DEC_BAD_CODE(code);
+  return dp;
+}
+
+static unsigned char *
+unw_decode_p6 (unsigned char *dp, unsigned char code, void *arg)
+{
+  int gregs = (code & 0x10) != 0;
+  unsigned char mask = (code & 0x0f);
+
+  if (gregs)
+    UNW_DEC_GR_MEM(P6, mask, arg);
+  else
+    UNW_DEC_FR_MEM(P6, mask, arg);
+  return dp;
+}
+
+static unsigned char *
+unw_decode_p7_p10 (unsigned char *dp, unsigned char code, void *arg)
+{
+  unsigned char r, byte1, byte2;
+  unw_word t, size;
+
+  if ((code & 0x10) == 0)
+    {
+      r = (code & 0xf);
+      t = unw_decode_uleb128 (&dp);
+      switch (r)
+       {
+       case 0:
+         size = unw_decode_uleb128 (&dp);
+         UNW_DEC_MEM_STACK_F(P7, t, size, arg);
+         break;
+
+       case 1: UNW_DEC_MEM_STACK_V(P7, t, arg); break;
+       case 2: UNW_DEC_SPILL_BASE(P7, t, arg); break;
+       case 3: UNW_DEC_REG_SPREL(P7, UNW_REG_PSP, t, arg); break;
+       case 4: UNW_DEC_REG_WHEN(P7, UNW_REG_RP, t, arg); break;
+       case 5: UNW_DEC_REG_PSPREL(P7, UNW_REG_RP, t, arg); break;
+       case 6: UNW_DEC_REG_WHEN(P7, UNW_REG_PFS, t, arg); break;
+       case 7: UNW_DEC_REG_PSPREL(P7, UNW_REG_PFS, t, arg); break;
+       case 8: UNW_DEC_REG_WHEN(P7, UNW_REG_PR, t, arg); break;
+       case 9: UNW_DEC_REG_PSPREL(P7, UNW_REG_PR, t, arg); break;
+       case 10: UNW_DEC_REG_WHEN(P7, UNW_REG_LC, t, arg); break;
+       case 11: UNW_DEC_REG_PSPREL(P7, UNW_REG_LC, t, arg); break;
+       case 12: UNW_DEC_REG_WHEN(P7, UNW_REG_UNAT, t, arg); break;
+       case 13: UNW_DEC_REG_PSPREL(P7, UNW_REG_UNAT, t, arg); break;
+       case 14: UNW_DEC_REG_WHEN(P7, UNW_REG_FPSR, t, arg); break;
+       case 15: UNW_DEC_REG_PSPREL(P7, UNW_REG_FPSR, t, arg); break;
+       default: UNW_DEC_BAD_CODE(r); break;
+       }
+    }
+  else
+    {
+      switch (code & 0xf)
+       {
+       case 0x0: /* p8 */
+         {
+           r = *dp++;
+           t = unw_decode_uleb128 (&dp);
+           switch (r)
+             {
+             case  1: UNW_DEC_REG_SPREL(P8, UNW_REG_RP, t, arg); break;
+             case  2: UNW_DEC_REG_SPREL(P8, UNW_REG_PFS, t, arg); break;
+             case  3: UNW_DEC_REG_SPREL(P8, UNW_REG_PR, t, arg); break;
+             case  4: UNW_DEC_REG_SPREL(P8, UNW_REG_LC, t, arg); break;
+             case  5: UNW_DEC_REG_SPREL(P8, UNW_REG_UNAT, t, arg); break;
+             case  6: UNW_DEC_REG_SPREL(P8, UNW_REG_FPSR, t, arg); break;
+             case  7: UNW_DEC_REG_WHEN(P8, UNW_REG_BSP, t, arg); break;
+             case  8: UNW_DEC_REG_PSPREL(P8, UNW_REG_BSP, t, arg); break;
+             case  9: UNW_DEC_REG_SPREL(P8, UNW_REG_BSP, t, arg); break;
+             case 10: UNW_DEC_REG_WHEN(P8, UNW_REG_BSPSTORE, t, arg); break;
+             case 11: UNW_DEC_REG_PSPREL(P8, UNW_REG_BSPSTORE, t, arg); break;
+             case 12: UNW_DEC_REG_SPREL(P8, UNW_REG_BSPSTORE, t, arg); break;
+             case 13: UNW_DEC_REG_WHEN(P8, UNW_REG_RNAT, t, arg); break;
+             case 14: UNW_DEC_REG_PSPREL(P8, UNW_REG_RNAT, t, arg); break;
+             case 15: UNW_DEC_REG_SPREL(P8, UNW_REG_RNAT, t, arg); break;
+             case 16: UNW_DEC_PRIUNAT_WHEN_GR(P8, t, arg); break;
+             case 17: UNW_DEC_PRIUNAT_PSPREL(P8, t, arg); break;
+             case 18: UNW_DEC_PRIUNAT_SPREL(P8, t, arg); break;
+             case 19: UNW_DEC_PRIUNAT_WHEN_MEM(P8, t, arg); break;
+             default: UNW_DEC_BAD_CODE(r); break;
+           }
+         }
+         break;
+
+       case 0x1:
+         byte1 = *dp++; byte2 = *dp++;
+         UNW_DEC_GR_GR(P9, (byte1 & 0xf), (byte2 & 0x7f), arg);
+         break;
+
+       case 0xf: /* p10 */
+         byte1 = *dp++; byte2 = *dp++;
+         UNW_DEC_ABI(P10, byte1, byte2, arg);
+         break;
+
+       case 0x9:
+         return unw_decode_x1 (dp, code, arg);
+
+       case 0xa:
+         return unw_decode_x2 (dp, code, arg);
+
+       case 0xb:
+         return unw_decode_x3 (dp, code, arg);
+
+       case 0xc:
+         return unw_decode_x4 (dp, code, arg);
+
+       default:
+         UNW_DEC_BAD_CODE(code);
+         break;
+       }
+    }
+  return dp;
+}
+
+static unsigned char *
+unw_decode_b1 (unsigned char *dp, unsigned char code, void *arg)
+{
+  unw_word label = (code & 0x1f);
+
+  if ((code & 0x20) != 0)
+    UNW_DEC_COPY_STATE(B1, label, arg);
+  else
+    UNW_DEC_LABEL_STATE(B1, label, arg);
+  return dp;
+}
+
+static unsigned char *
+unw_decode_b2 (unsigned char *dp, unsigned char code, void *arg)
+{
+  unw_word t;
+
+  t = unw_decode_uleb128 (&dp);
+  UNW_DEC_EPILOGUE(B2, t, (code & 0x1f), arg);
+  return dp;
+}
+
+static unsigned char *
+unw_decode_b3_x4 (unsigned char *dp, unsigned char code, void *arg)
+{
+  unw_word t, ecount, label;
+
+  if ((code & 0x10) == 0)
+    {
+      t = unw_decode_uleb128 (&dp);
+      ecount = unw_decode_uleb128 (&dp);
+      UNW_DEC_EPILOGUE(B3, t, ecount, arg);
+    }
+  else if ((code & 0x07) == 0)
+    {
+      label = unw_decode_uleb128 (&dp);
+      if ((code & 0x08) != 0)
+       UNW_DEC_COPY_STATE(B4, label, arg);
+      else
+       UNW_DEC_LABEL_STATE(B4, label, arg);
+    }
+  else
+    switch (code & 0x7)
+      {
+      case 1: return unw_decode_x1 (dp, code, arg);
+      case 2: return unw_decode_x2 (dp, code, arg);
+      case 3: return unw_decode_x3 (dp, code, arg);
+      case 4: return unw_decode_x4 (dp, code, arg);
+      default: UNW_DEC_BAD_CODE(code); break;
+      }
+  return dp;
+}
+
+typedef unsigned char *(*unw_decoder) (unsigned char *, unsigned char, void *);
+
+static const unw_decoder unw_decode_table[2][8] =
+{
+  /* prologue table: */
+  {
+    unw_decode_r1,     /* 0 */
+    unw_decode_r1,
+    unw_decode_r2,
+    unw_decode_r3,
+    unw_decode_p1,     /* 4 */
+    unw_decode_p2_p5,
+    unw_decode_p6,
+    unw_decode_p7_p10
+  },
+  {
+    unw_decode_r1,     /* 0 */
+    unw_decode_r1,
+    unw_decode_r2,
+    unw_decode_r3,
+    unw_decode_b1,     /* 4 */
+    unw_decode_b1,
+    unw_decode_b2,
+    unw_decode_b3_x4
+  }
+};
+
+/*
+ * Decode one descriptor and return address of next descriptor.
+ */
+static inline unsigned char *
+unw_decode (unsigned char *dp, int inside_body, void *arg)
+{
+  unw_decoder decoder;
+  unsigned char code;
+
+  code = *dp++;
+  decoder = unw_decode_table[inside_body][code >> 5];
+  dp = (*decoder) (dp, code, arg);
+  return dp;
+}
+
+\f
+/* RSE helper functions.  */
+
+static inline unsigned long
+ia64_rse_slot_num (unsigned long *addr)
+{
+  return (((unsigned long) addr) >> 3) & 0x3f;
+}
+
+/* Return TRUE if ADDR is the address of an RNAT slot.  */
+static inline unsigned long
+ia64_rse_is_rnat_slot (unsigned long *addr)
+{
+  return ia64_rse_slot_num (addr) == 0x3f;
+}
+
+/* Returns the address of the RNAT slot that covers the slot at
+   address SLOT_ADDR.  */
+static inline unsigned long *
+ia64_rse_rnat_addr (unsigned long *slot_addr)
+{
+  return (unsigned long *) ((unsigned long) slot_addr | (0x3f << 3));
+}
+
+/* Calculate the number of registers in the dirty partition starting at
+   BSPSTORE with a size of DIRTY bytes.  This isn't simply DIRTY
+   divided by eight because the 64th slot is used to store ar.rnat.  */
+static inline unsigned long
+ia64_rse_num_regs (unsigned long *bspstore, unsigned long *bsp)
+{
+  unsigned long slots = (bsp - bspstore);
+
+  return slots - (ia64_rse_slot_num (bspstore) + slots)/0x40;
+}
+
+/* The inverse of the above: given bspstore and the number of
+   registers, calculate ar.bsp.  */
+static inline unsigned long *
+ia64_rse_skip_regs (unsigned long *addr, long num_regs)
+{
+  long delta = ia64_rse_slot_num (addr) + num_regs;
+
+  if (num_regs < 0)
+    delta -= 0x3e;
+  return addr + num_regs + delta/0x3f;
+}
+
+\f
+/* Copy register backing store from SRC to DST, LEN words
+   (which include both saved registers and nat collections).
+   DST_RNAT is a partial nat collection for DST.  SRC and DST
+   don't have to be equal modulo 64 slots, so it cannot be
+   done with a simple memcpy as the nat collections will be
+   at different relative offsets and need to be combined together.  */
+static void
+ia64_copy_rbs (struct _Unwind_Context *info, unsigned long dst,
+               unsigned long src, long len, unsigned long dst_rnat)
+{
+  long count;
+  unsigned long src_rnat;
+  unsigned long shift1, shift2;
+
+  len <<= 3;
+  dst_rnat &= (1UL << ((dst >> 3) & 0x3f)) - 1;
+  src_rnat = src >= info->regstk_top
+            ? info->rnat : *(unsigned long *) (src | 0x1f8);
+  src_rnat &= ~((1UL << ((src >> 3) & 0x3f)) - 1);
+  /* Just to make sure.  */
+  src_rnat &= ~(1UL << 63);
+  shift1 = ((dst - src) >> 3) & 0x3f;
+  if ((dst & 0x1f8) < (src & 0x1f8))
+    shift1--;
+  shift2 = 0x3f - shift1;
+  if ((dst & 0x1f8) >= (src & 0x1f8))
+    {
+      count = ~dst & 0x1f8;
+      goto first;
+    }
+  count = ~src & 0x1f8;
+  goto second;
+  while (len > 0)
+    {
+      src_rnat = src >= info->regstk_top
+                ? info->rnat : *(unsigned long *) (src | 0x1f8);
+      /* Just to make sure.  */
+      src_rnat &= ~(1UL << 63);
+      count = shift2 << 3;
+first:
+      if (count > len)
+        count = len;
+      memcpy ((char *) dst, (char *) src, count);
+      dst += count;
+      src += count;
+      len -= count;
+      dst_rnat |= (src_rnat << shift1) & ~(1UL << 63);
+      if (len <= 0)
+        break;
+      *(long *) dst = dst_rnat;
+      dst += 8;
+      dst_rnat = 0;
+      count = shift1 << 3;
+second:
+      if (count > len)
+        count = len;
+      memcpy ((char *) dst, (char *) src, count);
+      dst += count;
+      src += count + 8;
+      len -= count + 8;
+      dst_rnat |= (src_rnat >> shift2);
+    }
+  if ((dst & 0x1f8) == 0x1f8)
+    {
+      *(long *) dst = dst_rnat;
+      dst += 8;
+      dst_rnat = 0;
+    }
+  /* Set info->regstk_top to lowest rbs address which will use
+     info->rnat collection.  */
+  info->regstk_top = dst & ~0x1ffUL;
+  info->rnat = dst_rnat;
+}
+
+/* Unwind accessors.  */
+
+static void
+unw_access_gr (struct _Unwind_Context *info, int regnum,
+              unsigned long *val, char *nat, int write)
+{
+  unsigned long *addr, *nat_addr = 0, nat_mask = 0, dummy_nat;
+  struct unw_ireg *ireg;
+
+  if ((unsigned) regnum - 1 >= 127)
+    abort ();
+
+  if (regnum < 1)
+    {
+      nat_addr = addr = &dummy_nat;
+      dummy_nat = 0;
+    }
+  else if (regnum < 32)
+    {
+      /* Access a non-stacked register.  */
+      ireg = &info->ireg[regnum - 2];
+      addr = ireg->loc;
+      if (addr)
+       {
+         nat_addr = addr + ireg->nat.off;
+         switch (ireg->nat.type)
+           {
+           case UNW_NAT_VAL:
+             /* Simulate getf.sig/setf.sig.  */
+             if (write)
+               {
+                 if (*nat)
+                   {
+                     /* Write NaTVal and be done with it.  */
+                     addr[0] = 0;
+                     addr[1] = 0x1fffe;
+                     return;
+                   }
+                 addr[1] = 0x1003e;
+               }
+             else if (addr[0] == 0 && addr[1] == 0x1ffe)
+               {
+                 /* Return NaT and be done with it.  */
+                 *val = 0;
+                 *nat = 1;
+                 return;
+               }
+             /* FALLTHRU */
+
+           case UNW_NAT_NONE:
+             dummy_nat = 0;
+             nat_addr = &dummy_nat;
+             break;
+
+           case UNW_NAT_MEMSTK:
+             nat_mask = 1UL << ((long) addr & 0x1f8)/8;
+             break;
+
+           case UNW_NAT_REGSTK:
+             if ((unsigned long) addr >= info->regstk_top)
+               nat_addr = &info->rnat;
+             else
+               nat_addr = ia64_rse_rnat_addr (addr);
+             nat_mask = 1UL << ia64_rse_slot_num (addr);
+             break;
+           }
+       }
+    }
+  else
+    {
+      /* Access a stacked register.  */
+      addr = ia64_rse_skip_regs ((unsigned long *) info->bsp, regnum - 32);
+      if ((unsigned long) addr >= info->regstk_top)
+       nat_addr = &info->rnat;
+      else
+       nat_addr = ia64_rse_rnat_addr (addr);
+      nat_mask = 1UL << ia64_rse_slot_num (addr);
+    }
+
+  if (write)
+    {
+      *addr = *val;
+      if (*nat)
+       *nat_addr |= nat_mask;
+      else
+       *nat_addr &= ~nat_mask;
+    }
+  else
+    {
+      *val = *addr;
+      *nat = (*nat_addr & nat_mask) != 0;
+    }
+}
+\f
+/* Get the value of register REG as saved in CONTEXT.  */
+
+_Unwind_Word
+_Unwind_GetGR (struct _Unwind_Context *context, int index)
+{
+  _Unwind_Word ret;
+  char nat;
+
+  if (index == 1)
+    return context->gp;
+  else if (index >= 15 && index <= 18)
+    return context->eh_data[index - 15];
+  else
+    unw_access_gr (context, index, &ret, &nat, 0);
+
+  return ret;
+}
+
+/* Overwrite the saved value for register REG in CONTEXT with VAL.  */
+
+void
+_Unwind_SetGR (struct _Unwind_Context *context, int index, _Unwind_Word val)
+{
+  char nat = 0;
+
+  if (index == 1)
+    context->gp = val;
+  else if (index >= 15 && index <= 18)
+    context->eh_data[index - 15] = val;
+  else
+    unw_access_gr (context, index, &val, &nat, 1);
+}
+
+/* Retrieve the return address for CONTEXT.  */
+
+inline _Unwind_Ptr
+_Unwind_GetIP (struct _Unwind_Context *context)
+{
+  return context->rp;
+}
+
+inline _Unwind_Ptr
+_Unwind_GetIPInfo (struct _Unwind_Context *context, int *ip_before_insn)
+{
+  *ip_before_insn = 0;
+  return context->rp;
+}
+
+/* Overwrite the return address for CONTEXT with VAL.  */
+
+inline void
+_Unwind_SetIP (struct _Unwind_Context *context, _Unwind_Ptr val)
+{
+  context->rp = val;
+}
+
+void *
+_Unwind_GetLanguageSpecificData (struct _Unwind_Context *context)
+{
+  return context->lsda;
+}
+
+_Unwind_Ptr
+_Unwind_GetRegionStart (struct _Unwind_Context *context)
+{
+  return context->region_start;
+}
+
+void *
+_Unwind_FindEnclosingFunction (void *pc)
+{
+  struct unw_table_entry *entp, ent;
+  unsigned long segment_base, gp;
+
+  entp = _Unwind_FindTableEntry (pc, &segment_base, &gp, &ent);
+  if (entp == NULL)
+    return NULL;
+  else
+    return (void *)(segment_base + entp->start_offset);
+}
+
+/* Get the value of the CFA as saved in CONTEXT.  In GCC/Dwarf2 parlance,
+   the CFA is the value of the stack pointer on entry; In IA-64 unwind
+   parlance, this is the PSP.  */
+
+_Unwind_Word
+_Unwind_GetCFA (struct _Unwind_Context *context)
+{
+  return (_Unwind_Ptr) context->psp;
+}
+
+/* Get the value of the Backing Store Pointer as saved in CONTEXT.  */
+
+_Unwind_Word
+_Unwind_GetBSP (struct _Unwind_Context *context)
+{
+  return (_Unwind_Ptr) context->bsp;
+}
+
+#include "md-unwind-support.h"
+
+/* By default, assume personality routine interface compatibility with
+   our expectations.  */
+#ifndef MD_UNW_COMPATIBLE_PERSONALITY_P
+#define MD_UNW_COMPATIBLE_PERSONALITY_P(HEADER) 1
+#endif
+
+\f
+static _Unwind_Reason_Code
+uw_frame_state_for (struct _Unwind_Context *context, _Unwind_FrameState *fs)
+{
+  struct unw_table_entry *entp, ent;
+  unsigned long *unw, header, length;
+  unsigned char *insn, *insn_end;
+  unsigned long segment_base;
+  struct unw_reg_info *r;
+
+  memset (fs, 0, sizeof (*fs));
+  for (r = fs->curr.reg; r < fs->curr.reg + UNW_NUM_REGS; ++r)
+    r->when = UNW_WHEN_NEVER;
+  context->lsda = 0;
+
+  entp = _Unwind_FindTableEntry ((void *) context->rp,
+                               &segment_base, &context->gp, &ent);
+  if (entp == NULL)
+    {
+      /* Couldn't find unwind info for this function.  Try an
+        os-specific fallback mechanism.  This will necessarily
+        not provide a personality routine or LSDA.  */
+#ifdef MD_FALLBACK_FRAME_STATE_FOR
+      if (MD_FALLBACK_FRAME_STATE_FOR (context, fs) == _URC_NO_REASON)
+       return _URC_NO_REASON;
+#endif
+
+      /* [SCRA 11.4.1] A leaf function with no memory stack, no exception
+        handlers, and which keeps the return value in B0 does not need
+        an unwind table entry.
+
+        This can only happen in the frame after unwinding through a signal
+        handler.  Avoid infinite looping by requiring that B0 != RP.
+        RP == 0 terminates the chain.  */
+      if (context->br_loc[0]
+         && *context->br_loc[0] != context->rp
+         && context->rp != 0)
+       goto skip_unwind_info;
+
+      return _URC_END_OF_STACK;
+    }
+
+  context->region_start = entp->start_offset + segment_base;
+  fs->when_target = ((context->rp & -16) - context->region_start) / 16 * 3
+                   + (context->rp & 15);
+
+  unw = (unsigned long *) (entp->info_offset + segment_base);
+  header = *unw;
+  length = UNW_LENGTH (header);
+
+  /* Some operating systems use the personality routine slot in way not
+     compatible with what we expect.  For instance, OpenVMS uses this slot to
+     designate "condition handlers" with very different arguments than what we
+     would be providing.  Such cases are typically identified from OS specific
+     bits in the unwind information block header, and checked by the target
+     MD_UNW_COMPATIBLE_PERSONALITY_P macro. 
+
+     We just pretend there is no personality from our standpoint in such
+     situations, and expect GCC not to set the identifying bits itself so that
+     compatible personalities for GCC compiled code are called.
+
+     Of course, this raises the question of what combinations of native/GCC
+     calls can be expected to behave properly exception handling-wise.  We are
+     not to provide a magic answer here, merely to prevent crashes assuming
+     users know what they are doing.
+
+     ??? Perhaps check UNW_VER / UNW_FLAG_OSMASK as well.  */
+
+  if (MD_UNW_COMPATIBLE_PERSONALITY_P (header)
+      && (UNW_FLAG_EHANDLER (header) | UNW_FLAG_UHANDLER (header)))
+    {
+      fs->personality =
+       *(_Unwind_Personality_Fn *) (unw[length + 1] + context->gp);
+      context->lsda = unw + length + 2;
+    }
+
+  insn = (unsigned char *) (unw + 1);
+  insn_end = (unsigned char *) (unw + 1 + length);
+  while (!fs->done && insn < insn_end)
+    insn = unw_decode (insn, fs->in_body, fs);
+
+  free_label_states (fs->labeled_states);
+  free_state_stack (&fs->curr);
+
+#ifdef ENABLE_MALLOC_CHECKING
+  if (reg_state_alloced || labeled_state_alloced)
+    abort ();
+#endif
+
+  /* If we're in the epilogue, sp has been restored and all values
+     on the memory stack below psp also have been restored.  */
+  if (fs->when_target > fs->epilogue_start)
+    {
+      struct unw_reg_info *r;
+
+      fs->curr.reg[UNW_REG_PSP].where = UNW_WHERE_NONE;
+      fs->curr.reg[UNW_REG_PSP].val = 0;
+      for (r = fs->curr.reg; r < fs->curr.reg + UNW_NUM_REGS; ++r)
+       if ((r->where == UNW_WHERE_PSPREL && r->val <= 0x10)
+           || r->where == UNW_WHERE_SPREL)
+         r->where = UNW_WHERE_NONE;
+    }
+
+skip_unwind_info:
+  /* If RP didn't get saved, generate entry for the return link register.  */
+  if (fs->curr.reg[UNW_REG_RP].when >= fs->when_target)
+    {
+      fs->curr.reg[UNW_REG_RP].where = UNW_WHERE_BR;
+      fs->curr.reg[UNW_REG_RP].when = -1;
+      fs->curr.reg[UNW_REG_RP].val = fs->return_link_reg;
+    }
+
+  /* There is a subtlety for the frame after unwinding through a signal
+     handler: should we restore the cfm as usual or the pfs?  We can't
+     restore both because we use br.ret to resume execution of user code.
+     For other frames the procedure is by definition non-leaf so the pfs
+     is saved and restored and thus effectively dead in the body; only
+     the cfm need therefore be restored.
+     
+     Here we have 2 cases:
+       - either the pfs is saved and restored and thus effectively dead
+        like in regular frames; then we do nothing special and restore
+        the cfm.
+       - or the pfs is not saved and thus live; but in that case the
+        procedure is necessarily leaf so the cfm is effectively dead
+        and we restore the pfs.  */
+  if (context->signal_pfs_loc)
+    {
+      if (fs->curr.reg[UNW_REG_PFS].when >= fs->when_target)
+       context->pfs_loc = context->signal_pfs_loc;
+      context->signal_pfs_loc = NULL;
+    }
+
+  return _URC_NO_REASON;
+}
+
+static void
+uw_update_reg_address (struct _Unwind_Context *context,
+                      _Unwind_FrameState *fs,
+                      enum unw_register_index regno)
+{
+  struct unw_reg_info *r = fs->curr.reg + regno;
+  void *addr;
+  unsigned long rval;
+
+  if (r->where == UNW_WHERE_NONE || r->when >= fs->when_target)
+    return;
+
+  rval = r->val;
+  switch (r->where)
+    {
+    case UNW_WHERE_GR:
+      if (rval >= 32)
+       addr = ia64_rse_skip_regs ((unsigned long *) context->bsp, rval - 32);
+      else if (rval >= 2)
+       addr = context->ireg[rval - 2].loc;
+      else if (rval == 0)
+       {
+         static const unsigned long dummy;
+         addr = (void *) &dummy;
+       }
+      else
+       abort ();
+      break;
+
+    case UNW_WHERE_FR:
+      if (rval >= 2 && rval < 32)
+       addr = context->fr_loc[rval - 2];
+      else
+       abort ();
+      break;
+
+    case UNW_WHERE_BR:
+      /* Note that while RVAL can only be 1-5 from normal descriptors,
+        we can want to look at B0, B6 and B7 due to having manually unwound a
+        signal frame.  */
+      if (rval < 8)
+       addr = context->br_loc[rval];
+      else
+       abort ();
+      break;
+
+    case UNW_WHERE_SPREL:
+      addr = (void *)(context->sp + rval);
+      break;
+
+    case UNW_WHERE_PSPREL:
+      addr = (void *)(context->psp + rval);
+      break;
+
+    default:
+      abort ();
+    }
+
+  switch (regno)
+    {
+    case UNW_REG_R2 ... UNW_REG_R31:
+      context->ireg[regno - UNW_REG_R2].loc = addr;
+      switch (r->where)
+      {
+      case UNW_WHERE_GR:
+       if (rval >= 32)
+         {
+           context->ireg[regno - UNW_REG_R2].nat.type = UNW_NAT_MEMSTK;
+           context->ireg[regno - UNW_REG_R2].nat.off
+             = context->pri_unat_loc - (unsigned long *) addr;
+         }
+       else if (rval >= 2)
+         {
+           context->ireg[regno - UNW_REG_R2].nat
+             = context->ireg[rval - 2].nat;
+         }
+       else if (rval == 0)
+         {
+           context->ireg[regno - UNW_REG_R2].nat.type = UNW_NAT_NONE;
+           context->ireg[regno - UNW_REG_R2].nat.off = 0;
+         }
+       else
+         abort ();
+       break;
+
+      case UNW_WHERE_FR:
+       context->ireg[regno - UNW_REG_R2].nat.type = UNW_NAT_VAL;
+       context->ireg[regno - UNW_REG_R2].nat.off = 0;
+       break;
+
+      case UNW_WHERE_BR:
+       context->ireg[regno - UNW_REG_R2].nat.type = UNW_NAT_NONE;
+       context->ireg[regno - UNW_REG_R2].nat.off = 0;
+       break;
+
+      case UNW_WHERE_PSPREL:
+      case UNW_WHERE_SPREL:
+       context->ireg[regno - UNW_REG_R2].nat.type = UNW_NAT_MEMSTK;
+       context->ireg[regno - UNW_REG_R2].nat.off
+         = context->pri_unat_loc - (unsigned long *) addr;
+       break;
+
+      default:
+       abort ();
+      }
+      break;
+
+    case UNW_REG_F2 ... UNW_REG_F31:
+      context->fr_loc[regno - UNW_REG_F2] = addr;
+      break;
+
+    case UNW_REG_B1 ... UNW_REG_B5:
+      context->br_loc[regno - UNW_REG_B0] = addr;
+      break;
+
+    case UNW_REG_BSP:
+      context->bsp_loc = addr;
+      break;
+    case UNW_REG_BSPSTORE:
+      context->bspstore_loc = addr;
+      break;
+    case UNW_REG_PFS:
+      context->pfs_loc = addr;
+      break;
+    case UNW_REG_RP:
+      context->rp = *(unsigned long *)addr;
+      break;
+    case UNW_REG_UNAT:
+      context->unat_loc = addr;
+      break;
+    case UNW_REG_PR:
+      context->pr = *(unsigned long *) addr;
+      break;
+    case UNW_REG_LC:
+      context->lc_loc = addr;
+      break;
+    case UNW_REG_FPSR:
+      context->fpsr_loc = addr;
+      break;
+
+    case UNW_REG_PSP:
+      context->psp = *(unsigned long *)addr;
+      break;
+
+    default:
+      abort ();
+    }
+}
+
+static void
+uw_update_context (struct _Unwind_Context *context, _Unwind_FrameState *fs)
+{
+  long i;
+
+#ifdef MD_HANDLE_UNWABI
+  MD_HANDLE_UNWABI (context, fs);
+#endif
+
+  context->sp = context->psp;
+
+  /* First, set PSP.  Subsequent instructions may depend on this value.  */
+  if (fs->when_target > fs->curr.reg[UNW_REG_PSP].when)
+    {
+      if (fs->curr.reg[UNW_REG_PSP].where == UNW_WHERE_NONE)
+       context->psp = context->psp + fs->curr.reg[UNW_REG_PSP].val;
+      else
+       uw_update_reg_address (context, fs, UNW_REG_PSP);
+    }
+
+  /* Determine the location of the primary UNaT.  */
+  {
+    int i;
+    if (fs->when_target < fs->curr.reg[UNW_REG_PRI_UNAT_GR].when)
+      i = UNW_REG_PRI_UNAT_MEM;
+    else if (fs->when_target < fs->curr.reg[UNW_REG_PRI_UNAT_MEM].when)
+      i = UNW_REG_PRI_UNAT_GR;
+    else if (fs->curr.reg[UNW_REG_PRI_UNAT_MEM].when
+            > fs->curr.reg[UNW_REG_PRI_UNAT_GR].when)
+      i = UNW_REG_PRI_UNAT_MEM;
+    else
+      i = UNW_REG_PRI_UNAT_GR;
+    uw_update_reg_address (context, fs, i);
+  }
+
+  /* Compute the addresses of all registers saved in this frame.  */
+  for (i = UNW_REG_BSP; i < UNW_NUM_REGS; ++i)
+    uw_update_reg_address (context, fs, i);
+
+  /* Unwind BSP for the local registers allocated this frame.  */
+  /* ??? What to do with stored BSP or BSPSTORE registers.  */
+  /* We assert that we are either at a call site, or we have
+     just unwound through a signal frame.  In either case
+     pfs_loc is valid. */
+  if (!(fs -> no_reg_stack_frame))
+    {
+      unsigned long pfs = *context->pfs_loc;
+      unsigned long sol = (pfs >> 7) & 0x7f;
+      context->bsp = (unsigned long)
+       ia64_rse_skip_regs ((unsigned long *) context->bsp, -sol);
+    }
+}
+
+static void
+uw_advance_context (struct _Unwind_Context *context, _Unwind_FrameState *fs)
+{
+  uw_update_context (context, fs);
+}
+
+/* Fill in CONTEXT for top-of-stack.  The only valid registers at this
+   level will be the return address and the CFA.  Note that CFA = SP+16.  */
+   
+#define uw_init_context(CONTEXT)                                       \
+  do {                                                                 \
+    /* ??? There is a whole lot o code in uw_install_context that      \
+       tries to avoid spilling the entire machine state here.  We      \
+       should try to make that work again.  */                         \
+    __builtin_unwind_init();                                           \
+    uw_init_context_1 (CONTEXT, __builtin_ia64_bsp ());                        \
+  } while (0)
+
+static void __attribute__((noinline))
+uw_init_context_1 (struct _Unwind_Context *context, void *bsp)
+{
+  void *rp = __builtin_extract_return_addr (__builtin_return_address (0));
+  /* Set psp to the caller's stack pointer.  */
+  void *psp = __builtin_dwarf_cfa () - 16;
+  _Unwind_FrameState fs;
+  unsigned long rnat, tmp1, tmp2;
+
+  /* Flush the register stack to memory so that we can access it.
+     Get rse nat collection for the last incomplete rbs chunk of
+     registers at the same time.  For this RSE needs to be turned
+     into the mandatory only mode.  */
+  asm ("mov.m %1 = ar.rsc;;\n\t"
+       "and %2 = 0x1c, %1;;\n\t"
+       "mov.m ar.rsc = %2;;\n\t"
+       "flushrs;;\n\t"
+       "mov.m %0 = ar.rnat;;\n\t"
+       "mov.m ar.rsc = %1\n\t"
+       : "=r" (rnat), "=r" (tmp1), "=r" (tmp2));
+
+  memset (context, 0, sizeof (struct _Unwind_Context));
+  context->bsp = (unsigned long) bsp;
+  /* Set context->regstk_top to lowest rbs address which will use
+     context->rnat collection.  */
+  context->regstk_top = context->bsp & ~0x1ffULL;
+  context->rnat = rnat;
+  context->psp = (unsigned long) psp;
+  context->rp = (unsigned long) rp;
+  asm ("mov %0 = sp" : "=r" (context->sp));
+  asm ("mov %0 = pr" : "=r" (context->pr));
+  context->pri_unat_loc = &context->initial_unat;      /* ??? */
+
+  if (uw_frame_state_for (context, &fs) != _URC_NO_REASON)
+    abort ();
+
+  uw_update_context (context, &fs);
+}
+
+/* Install (i.e. longjmp to) the contents of TARGET.  */
+
+static void __attribute__((noreturn))
+uw_install_context (struct _Unwind_Context *current __attribute__((unused)),
+                   struct _Unwind_Context *target)
+{
+  unsigned long ireg_buf[4], ireg_nat = 0, ireg_pr = 0;
+  long i;
+
+  /* Copy integer register data from the target context to a
+     temporary buffer.  Do this so that we can frob AR.UNAT
+     to get the NaT bits for these registers set properly.  */
+  for (i = 4; i <= 7; ++i)
+    {
+      char nat;
+      void *t = target->ireg[i - 2].loc;
+      if (t)
+       {
+         unw_access_gr (target, i, &ireg_buf[i - 4], &nat, 0);
+          ireg_nat |= (long)nat << (((size_t)&ireg_buf[i - 4] >> 3) & 0x3f);
+         /* Set p6 - p9.  */
+         ireg_pr |= 4L << i;
+       }
+    }
+
+  /* The value in uc_bsp that we've computed is that for the 
+     target function.  The value that we install below will be
+     adjusted by the BR.RET instruction based on the contents
+     of AR.PFS.  So we must unadjust that here.  */
+  target->bsp = (unsigned long)
+    ia64_rse_skip_regs ((unsigned long *)target->bsp,
+                       (*target->pfs_loc >> 7) & 0x7f);
+
+  if (target->bsp < target->regstk_top)
+    target->rnat = *ia64_rse_rnat_addr ((unsigned long *) target->bsp);
+
+  /* Provide assembly with the offsets into the _Unwind_Context.  */
+  asm volatile ("uc_rnat = %0"
+               : : "i"(offsetof (struct _Unwind_Context, rnat)));
+  asm volatile ("uc_bsp = %0"
+               : : "i"(offsetof (struct _Unwind_Context, bsp)));
+  asm volatile ("uc_psp = %0"
+               : : "i"(offsetof (struct _Unwind_Context, psp)));
+  asm volatile ("uc_rp = %0"
+               : : "i"(offsetof (struct _Unwind_Context, rp)));
+  asm volatile ("uc_pr = %0"
+               : : "i"(offsetof (struct _Unwind_Context, pr)));
+  asm volatile ("uc_gp = %0"
+               : : "i"(offsetof (struct _Unwind_Context, gp)));
+  asm volatile ("uc_pfs_loc = %0"
+               : : "i"(offsetof (struct _Unwind_Context, pfs_loc)));
+  asm volatile ("uc_unat_loc = %0"
+               : : "i"(offsetof (struct _Unwind_Context, unat_loc)));
+  asm volatile ("uc_lc_loc = %0"
+               : : "i"(offsetof (struct _Unwind_Context, lc_loc)));
+  asm volatile ("uc_fpsr_loc = %0"
+               : : "i"(offsetof (struct _Unwind_Context, fpsr_loc)));
+  asm volatile ("uc_eh_data = %0"
+               : : "i"(offsetof (struct _Unwind_Context, eh_data)));
+  asm volatile ("uc_br_loc = %0"
+               : : "i"(offsetof (struct _Unwind_Context, br_loc)));
+  asm volatile ("uc_fr_loc = %0"
+               : : "i"(offsetof (struct _Unwind_Context, fr_loc)));
+
+  asm volatile (
+       /* Load up call-saved non-window integer registers from ireg_buf.  */
+       "add r20 = 8, %1                        \n\t"
+       "mov ar.unat = %2                       \n\t"
+       "mov pr = %3, 0x3c0                     \n\t"
+       ";;                                     \n\t"
+       "(p6) ld8.fill r4 = [%1]                \n\t"
+       "(p7) ld8.fill r5 = [r20]               \n\t"
+       "add r21 = uc_br_loc + 16, %0           \n\t"
+       "adds %1 = 16, %1                       \n\t"
+       "adds r20 = 16, r20                     \n\t"
+       ";;                                     \n\t"
+       "(p8) ld8.fill r6 = [%1]                \n\t"
+       "(p9) ld8.fill r7 = [r20]               \n\t"
+       "add r20 = uc_br_loc + 8, %0            \n\t"
+       ";;                                     \n\t"
+       /* Load up call-saved branch registers.  */
+       "ld8 r22 = [r20], 16                    \n\t"
+       "ld8 r23 = [r21], 16                    \n\t"
+       ";;                                     \n\t"
+       "ld8 r24 = [r20], 16                    \n\t"
+       "ld8 r25 = [r21], uc_fr_loc - (uc_br_loc + 32)\n\t"
+       ";;                                     \n\t"
+       "ld8 r26 = [r20], uc_fr_loc + 8 - (uc_br_loc + 40)\n\t"
+       "ld8 r27 = [r21], 24                    \n\t"
+       "cmp.ne p6, p0 = r0, r22                \n\t"
+       ";;                                     \n\t"
+       "ld8 r28 = [r20], 8                     \n\t"
+       "(p6) ld8 r22 = [r22]                   \n\t"
+       "cmp.ne p7, p0 = r0, r23                \n\t"
+       ";;                                     \n\t"
+       "(p7) ld8 r23 = [r23]                   \n\t"
+       "cmp.ne p8, p0 = r0, r24                \n\t"
+       ";;                                     \n\t"
+       "(p8) ld8 r24 = [r24]                   \n\t"
+       "(p6) mov b1 = r22                      \n\t"
+       "cmp.ne p9, p0 = r0, r25                \n\t"
+       ";;                                     \n\t"
+       "(p9) ld8 r25 = [r25]                   \n\t"
+       "(p7) mov b2 = r23                      \n\t"
+       "cmp.ne p6, p0 = r0, r26                \n\t"
+       ";;                                     \n\t"
+       "(p6) ld8 r26 = [r26]                   \n\t"
+       "(p8) mov b3 = r24                      \n\t"
+       "cmp.ne p7, p0 = r0, r27                \n\t"
+       ";;                                     \n\t"
+       /* Load up call-saved fp registers.  */
+       "(p7) ldf.fill f2 = [r27]               \n\t"
+       "(p9) mov b4 = r25                      \n\t"
+       "cmp.ne p8, p0 = r0, r28                \n\t"
+       ";;                                     \n\t"
+       "(p8) ldf.fill f3 = [r28]               \n\t"
+       "(p6) mov b5 = r26                      \n\t"
+       ";;                                     \n\t"
+       "ld8 r29 = [r20], 16*8 - 4*8            \n\t"
+       "ld8 r30 = [r21], 17*8 - 5*8            \n\t"
+       ";;                                     \n\t"
+       "ld8 r22 = [r20], 16                    \n\t"
+       "ld8 r23 = [r21], 16                    \n\t"
+       ";;                                     \n\t"
+       "ld8 r24 = [r20], 16                    \n\t"
+       "ld8 r25 = [r21]                        \n\t"
+       "cmp.ne p6, p0 = r0, r29                \n\t"
+       ";;                                     \n\t"
+       "ld8 r26 = [r20], 8                     \n\t"
+       "(p6) ldf.fill f4 = [r29]               \n\t"
+       "cmp.ne p7, p0 = r0, r30                \n\t"
+       ";;                                     \n\t"
+       "ld8 r27 = [r20], 8                     \n\t"
+       "(p7) ldf.fill f5 = [r30]               \n\t"
+       "cmp.ne p6, p0 = r0, r22                \n\t"
+       ";;                                     \n\t"
+       "ld8 r28 = [r20], 8                     \n\t"
+       "(p6) ldf.fill f16 = [r22]              \n\t"
+       "cmp.ne p7, p0 = r0, r23                \n\t"
+       ";;                                     \n\t"
+       "ld8 r29 = [r20], 8                     \n\t"
+       "(p7) ldf.fill f17 = [r23]              \n\t"
+       "cmp.ne p6, p0 = r0, r24                \n\t"
+       ";;                                     \n\t"
+       "ld8 r22 = [r20], 8                     \n\t"
+       "(p6) ldf.fill f18 = [r24]              \n\t"
+       "cmp.ne p7, p0 = r0, r25                \n\t"
+       ";;                                     \n\t"
+       "ld8 r23 = [r20], 8                     \n\t"
+       "(p7) ldf.fill f19 = [r25]              \n\t"
+       "cmp.ne p6, p0 = r0, r26                \n\t"
+       ";;                                     \n\t"
+       "ld8 r24 = [r20], 8                     \n\t"
+       "(p6) ldf.fill f20 = [r26]              \n\t"
+       "cmp.ne p7, p0 = r0, r27                \n\t"
+       ";;                                     \n\t"
+       "ld8 r25 = [r20], 8                     \n\t"
+       "(p7) ldf.fill f21 = [r27]              \n\t"
+       "cmp.ne p6, p0 = r0, r28                \n\t"
+       ";;                                     \n\t"
+       "ld8 r26 = [r20], 8                     \n\t"
+       "(p6) ldf.fill f22 = [r28]              \n\t"
+       "cmp.ne p7, p0 = r0, r29                \n\t"
+       ";;                                     \n\t"
+       "ld8 r27 = [r20], 8                     \n\t"
+       ";;                                     \n\t"
+       "ld8 r28 = [r20], 8                     \n\t"
+       "(p7) ldf.fill f23 = [r29]              \n\t"
+       "cmp.ne p6, p0 = r0, r22                \n\t"
+       ";;                                     \n\t"
+       "ld8 r29 = [r20], 8                     \n\t"
+       "(p6) ldf.fill f24 = [r22]              \n\t"
+       "cmp.ne p7, p0 = r0, r23                \n\t"
+       ";;                                     \n\t"
+       "(p7) ldf.fill f25 = [r23]              \n\t"
+       "cmp.ne p6, p0 = r0, r24                \n\t"
+       "cmp.ne p7, p0 = r0, r25                \n\t"
+       ";;                                     \n\t"
+       "(p6) ldf.fill f26 = [r24]              \n\t"
+       "(p7) ldf.fill f27 = [r25]              \n\t"
+       "cmp.ne p6, p0 = r0, r26                \n\t"
+       ";;                                     \n\t"
+       "(p6) ldf.fill f28 = [r26]              \n\t"
+       "cmp.ne p7, p0 = r0, r27                \n\t"
+       "cmp.ne p6, p0 = r0, r28                \n\t"
+       ";;                                     \n\t"
+       "(p7) ldf.fill f29 = [r27]              \n\t"
+       "(p6) ldf.fill f30 = [r28]              \n\t"
+       "cmp.ne p7, p0 = r0, r29                \n\t"
+       ";;                                     \n\t"
+       "(p7) ldf.fill f31 = [r29]              \n\t"
+       "add r20 = uc_rnat, %0                  \n\t"
+       "add r21 = uc_bsp, %0                   \n\t"
+       ";;                                     \n\t"
+       /* Load the balance of the thread state from the context.  */
+       "ld8 r22 = [r20], uc_psp - uc_rnat      \n\t"
+       "ld8 r23 = [r21], uc_gp - uc_bsp        \n\t"
+       ";;                                     \n\t"
+       "ld8 r24 = [r20], uc_pfs_loc - uc_psp   \n\t"
+       "ld8 r1 = [r21], uc_rp - uc_gp          \n\t"
+       ";;                                     \n\t"
+       "ld8 r25 = [r20], uc_unat_loc - uc_pfs_loc\n\t"
+       "ld8 r26 = [r21], uc_pr - uc_rp         \n\t"
+       ";;                                     \n\t"
+       "ld8 r27 = [r20], uc_lc_loc - uc_unat_loc\n\t"
+       "ld8 r28 = [r21], uc_fpsr_loc - uc_pr   \n\t"
+       ";;                                     \n\t"
+       "ld8 r29 = [r20], uc_eh_data - uc_lc_loc\n\t"
+       "ld8 r30 = [r21], uc_eh_data + 8 - uc_fpsr_loc\n\t"
+       ";;                                     \n\t"
+       /* Load data for the exception handler.  */
+       "ld8 r15 = [r20], 16                    \n\t"
+       "ld8 r16 = [r21], 16                    \n\t"
+       ";;                                     \n\t"
+       "ld8 r17 = [r20]                        \n\t"
+       "ld8 r18 = [r21]                        \n\t"
+       ";;                                     \n\t"
+       /* Install the balance of the thread state loaded above.  */
+       "cmp.ne p6, p0 = r0, r25                \n\t"
+       "cmp.ne p7, p0 = r0, r27                \n\t"
+       ";;                                     \n\t"
+       "(p6) ld8 r25 = [r25]                   \n\t"
+       "(p7) ld8 r27 = [r27]                   \n\t"
+       ";;                                     \n\t"
+       "(p7) mov.m ar.unat = r27               \n\t"
+       "(p6) mov.i ar.pfs = r25                \n\t"
+       "cmp.ne p9, p0 = r0, r29                \n\t"
+       ";;                                     \n\t"
+       "(p9) ld8 r29 = [r29]                   \n\t"
+       "cmp.ne p6, p0 = r0, r30                \n\t"
+       ";;                                     \n\t"
+       "(p6) ld8 r30 = [r30]                   \n\t"
+       /* Don't clobber p6-p9, which are in use at present.  */
+       "mov pr = r28, ~0x3c0                   \n\t"
+       "(p9) mov.i ar.lc = r29                 \n\t"
+       ";;                                     \n\t"
+       "mov.m r25 = ar.rsc                     \n\t"
+       "(p6) mov.m ar.fpsr = r30               \n\t"
+       ";;                                     \n\t"
+       "and r29 = 0x1c, r25                    \n\t"
+       "mov b0 = r26                           \n\t"
+       ";;                                     \n\t"
+       "mov.m ar.rsc = r29                     \n\t"
+       ";;                                     \n\t"
+       /* This must be done before setting AR.BSPSTORE, otherwise 
+          AR.BSP will be initialized with a random displacement
+          below the value we want, based on the current number of
+          dirty stacked registers.  */
+       "loadrs                                 \n\t"
+       "invala                                 \n\t"
+       ";;                                     \n\t"
+       "mov.m ar.bspstore = r23                \n\t"
+       ";;                                     \n\t"
+       "mov.m ar.rnat = r22                    \n\t"
+       ";;                                     \n\t"
+       "mov.m ar.rsc = r25                     \n\t"
+       "mov sp = r24                           \n\t"
+       "br.ret.sptk.few b0"
+       : : "r"(target), "r"(ireg_buf), "r"(ireg_nat), "r"(ireg_pr)
+       : "r15", "r16", "r17", "r18", "r20", "r21", "r22",
+         "r23", "r24", "r25", "r26", "r27", "r28", "r29",
+         "r30", "r31");
+  /* NOTREACHED */
+  while (1);
+}
+
+static inline _Unwind_Ptr
+uw_identify_context (struct _Unwind_Context *context)
+{
+  return _Unwind_GetIP (context);
+}
+
+#include "unwind.inc"
+
+#if defined (USE_GAS_SYMVER) && defined (SHARED) && defined (USE_LIBUNWIND_EXCEPTIONS)
+alias (_Unwind_Backtrace);
+alias (_Unwind_DeleteException);
+alias (_Unwind_FindEnclosingFunction);
+alias (_Unwind_ForcedUnwind);
+alias (_Unwind_GetBSP);
+alias (_Unwind_GetCFA);
+alias (_Unwind_GetGR);
+alias (_Unwind_GetIP);
+alias (_Unwind_GetLanguageSpecificData);
+alias (_Unwind_GetRegionStart);
+alias (_Unwind_RaiseException);
+alias (_Unwind_Resume);
+alias (_Unwind_Resume_or_Rethrow);
+alias (_Unwind_SetGR);
+alias (_Unwind_SetIP);
+#endif
+
+#endif
diff --git a/libgcc/config/ia64/unwind-ia64.h b/libgcc/config/ia64/unwind-ia64.h
new file mode 100644 (file)
index 0000000..b98f048
--- /dev/null
@@ -0,0 +1,43 @@
+/* Copyright (C) 1999, 2000, 2001, 2007, 2009 Free Software Foundation, Inc.
+   Contributed by Andrew MacLeod  <amacleod@cygnus.com>
+                  Andrew Haley  <aph@cygnus.com>
+
+   This file is part of GCC.
+
+   GCC 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 3, or (at your option)
+   any later version.
+
+   GCC 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 GCC; see the file COPYING3.  If not see
+   <http://www.gnu.org/licenses/>.  */
+
+struct unw_table_entry
+{
+  unsigned long start_offset;
+  unsigned long end_offset;
+  unsigned long info_offset;
+};
+
+/* Accessors to fields of an unwind info block header.  In this common file to
+   be visible from all the units involved in a target implementation.  */
+   
+#ifndef __USING_SJLJ_EXCEPTIONS__
+#define UNW_VER(x)             ((x) >> 48)
+#define UNW_FLAG_MASK          0x0000ffff00000000
+#define UNW_FLAG_OSMASK                0x0000f00000000000
+#define UNW_FLAG_EHANDLER(x)   ((x) & 0x0000000100000000L)
+#define UNW_FLAG_UHANDLER(x)   ((x) & 0x0000000200000000L)
+#define UNW_LENGTH(x)          ((x) & 0x00000000ffffffffL)
+#endif
+
+extern struct unw_table_entry *
+_Unwind_FindTableEntry (void *pc, unsigned long *segment_base,
+                       unsigned long *gp, struct unw_table_entry *ent)
+                       __attribute__ ((__visibility__ ("hidden")));
index 41c76ae768c0ba2c112081e36fca36fa29f074ec..48bdc6884ea7f6b615302fd09470272d836a5c92 100644 (file)
@@ -1,5 +1,5 @@
 /* DWARF2 EH unwinding support for IA64 VMS.
-   Copyright (C) 2005-2009 Free Software Foundation, Inc.
+   Copyright (C) 2005-2011 Free Software Foundation, Inc.
 
    This file is part of GCC.
 
@@ -32,6 +32,9 @@
 #include <stdio.h>
 #include <string.h>
 
+#define UNW_IVMS_MODE(HEADER) (((HEADER) >> 44) & 0x3L)
+#define MD_UNW_COMPATIBLE_PERSONALITY_P(HEADER) (!UNW_IVMS_MODE (HEADER))
+
 #define DYN$C_SSENTRY 66
 /* ??? would rather get the proper header file.  */
 
diff --git a/libgcc/config/picochip/t-picochip b/libgcc/config/picochip/t-picochip
new file mode 100644 (file)
index 0000000..5135d50
--- /dev/null
@@ -0,0 +1,2 @@
+# Turn off the building of exception handling libraries.
+LIB2ADDEH =
diff --git a/libgcc/config/rs6000/aix-unwind.h b/libgcc/config/rs6000/aix-unwind.h
new file mode 100644 (file)
index 0000000..9e12659
--- /dev/null
@@ -0,0 +1,57 @@
+/* DWARF2 EH unwinding support for AIX.
+   Copyright (C) 2011 Free Software Foundation, Inc.
+
+   This file is part of GCC.
+
+   GCC 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 3, or (at your option)
+   any later version.
+
+   GCC 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.
+
+   Under Section 7 of GPL version 3, you are granted additional
+   permissions described in the GCC Runtime Library Exception, version
+   3.1, as published by the Free Software Foundation.
+
+   You should have received a copy of the GNU General Public License and
+   a copy of the GCC Runtime Library Exception along with this program;
+   see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+   <http://www.gnu.org/licenses/>.  */
+
+/* If the current unwind info (FS) does not contain explicit info
+   saving R2, then we have to do a minor amount of code reading to
+   figure out if it was saved.  The big problem here is that the
+   code that does the save/restore is generated by the linker, so
+   we have no good way to determine at compile time what to do.  */
+
+#define R_LR 65
+
+#ifdef __64BIT__
+#define MD_FROB_UPDATE_CONTEXT(CTX, FS)                                        \
+  do {                                                                 \
+    if ((FS)->regs.reg[2].how == REG_UNSAVED)                          \
+      {                                                                        \
+       unsigned int *insn                                              \
+         = (unsigned int *)                                            \
+           _Unwind_GetGR ((CTX), R_LR);                                \
+       if (*insn == 0xE8410028)                                        \
+         _Unwind_SetGRPtr ((CTX), 2, (CTX)->cfa + 40);                 \
+      }                                                                        \
+  } while (0)
+#else
+#define MD_FROB_UPDATE_CONTEXT(CTX, FS)                                        \
+  do {                                                                 \
+    if ((FS)->regs.reg[2].how == REG_UNSAVED)                          \
+      {                                                                        \
+       unsigned int *insn                                              \
+         = (unsigned int *)                                            \
+           _Unwind_GetGR ((CTX), R_LR);                                \
+       if (*insn == 0x80410014)                                        \
+         _Unwind_SetGRPtr ((CTX), 2, (CTX)->cfa + 20);                 \
+      }                                                                        \
+  } while (0)
+#endif
diff --git a/libgcc/config/rs6000/darwin-fallback.c b/libgcc/config/rs6000/darwin-fallback.c
new file mode 100644 (file)
index 0000000..4591071
--- /dev/null
@@ -0,0 +1,487 @@
+/* Fallback frame-state unwinder for Darwin.
+   Copyright (C) 2004, 2005, 2007, 2009 Free Software Foundation, Inc.
+
+   This file is part of GCC.
+
+   GCC 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 3, or (at your option)
+   any later version.
+
+   GCC 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.
+
+   Under Section 7 of GPL version 3, you are granted additional
+   permissions described in the GCC Runtime Library Exception, version
+   3.1, as published by the Free Software Foundation.
+
+   You should have received a copy of the GNU General Public License and
+   a copy of the GCC Runtime Library Exception along with this program;
+   see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#ifdef __ppc__
+
+#include "tconfig.h"
+#include "tsystem.h"
+#include "coretypes.h"
+#include "tm.h"
+#include "dwarf2.h"
+#include "unwind.h"
+#include "unwind-dw2.h"
+#include <stdint.h>
+#include <stdbool.h>
+#include <sys/types.h>
+#include <signal.h>
+
+#define R_LR           65
+#define R_CTR          66
+#define R_CR2          70
+#define R_XER          76
+#define R_VR0          77
+#define R_VRSAVE       109
+#define R_VSCR         110
+#define R_SPEFSCR      112
+
+typedef unsigned long reg_unit;
+
+/* Place in GPRS the parameters to the first 'sc' instruction that would
+   have been executed if we were returning from this CONTEXT, or
+   return false if an unexpected instruction is encountered.  */
+
+static bool
+interpret_libc (reg_unit gprs[32], struct _Unwind_Context *context)
+{
+  uint32_t *pc = (uint32_t *)_Unwind_GetIP (context);
+  uint32_t cr;
+  reg_unit lr = (reg_unit) pc;
+  reg_unit ctr = 0;
+  uint32_t *invalid_address = NULL;
+
+  int i;
+
+  for (i = 0; i < 13; i++)
+    gprs[i] = 1;
+  gprs[1] = _Unwind_GetCFA (context);
+  for (; i < 32; i++)
+    gprs[i] = _Unwind_GetGR (context, i);
+  cr = _Unwind_GetGR (context, R_CR2);
+
+  /* For each supported Libc, we have to track the code flow
+     all the way back into the kernel.
+  
+     This code is believed to support all released Libc/Libsystem builds since
+     Jaguar 6C115, including all the security updates.  To be precise,
+
+     Libc      Libsystem       Build(s)
+     262~1     60~37           6C115
+     262~1     60.2~4          6D52
+     262~1     61~3            6F21-6F22
+     262~1     63~24           6G30-6G37
+     262~1     63~32           6I34-6I35
+     262~1     63~64           6L29-6L60
+     262.4.1~1 63~84           6L123-6R172
+     
+     320~1     71~101          7B85-7D28
+     320~1     71~266          7F54-7F56
+     320~1     71~288          7F112
+     320~1     71~289          7F113
+     320.1.3~1 71.1.1~29       7H60-7H105
+     320.1.3~1 71.1.1~30       7H110-7H113
+     320.1.3~1 71.1.1~31       7H114
+     
+     That's a big table!  It would be insane to try to keep track of
+     every little detail, so we just read the code itself and do what
+     it would do.
+  */
+
+  for (;;)
+    {
+      uint32_t ins = *pc++;
+      
+      if ((ins & 0xFC000003) == 0x48000000)  /* b instruction */
+       {
+         pc += ((((int32_t) ins & 0x3FFFFFC) ^ 0x2000000) - 0x2000004) / 4;
+         continue;
+       }
+      if ((ins & 0xFC600000) == 0x2C000000)  /* cmpwi */
+       {
+         int32_t val1 = (int16_t) ins;
+         int32_t val2 = gprs[ins >> 16 & 0x1F];
+         /* Only beq and bne instructions are supported, so we only
+            need to set the EQ bit.  */
+         uint32_t mask = 0xF << ((ins >> 21 & 0x1C) ^ 0x1C);
+         if (val1 == val2)
+           cr |= mask;
+         else
+           cr &= ~mask;
+         continue;
+       }
+      if ((ins & 0xFEC38003) == 0x40820000)  /* forwards beq/bne */
+       {
+         if ((cr >> ((ins >> 16 & 0x1F) ^ 0x1F) & 1) == (ins >> 24 & 1))
+           pc += (ins & 0x7FFC) / 4 - 1;
+         continue;
+       }
+      if ((ins & 0xFC0007FF) == 0x7C000378) /* or, including mr */
+       {
+         gprs [ins >> 16 & 0x1F] = (gprs [ins >> 11 & 0x1F] 
+                                    | gprs [ins >> 21 & 0x1F]);
+         continue;
+       }
+      if (ins >> 26 == 0x0E)  /* addi, including li */
+       {
+         reg_unit src = (ins >> 16 & 0x1F) == 0 ? 0 : gprs [ins >> 16 & 0x1F];
+         gprs [ins >> 21 & 0x1F] = src + (int16_t) ins;
+         continue;
+       }
+      if (ins >> 26 == 0x0F)  /* addis, including lis */
+       {
+         reg_unit src = (ins >> 16 & 0x1F) == 0 ? 0 : gprs [ins >> 16 & 0x1F];
+         gprs [ins >> 21 & 0x1F] = src + ((int16_t) ins << 16);
+         continue;
+       }
+      if (ins >> 26 == 0x20)  /* lwz */
+       {
+         reg_unit src = (ins >> 16 & 0x1F) == 0 ? 0 : gprs [ins >> 16 & 0x1F];
+         uint32_t *p = (uint32_t *)(src + (int16_t) ins);
+         if (p == invalid_address)
+           return false;
+         gprs [ins >> 21 & 0x1F] = *p;
+         continue;
+       }
+      if (ins >> 26 == 0x21)  /* lwzu */
+       {
+         uint32_t *p = (uint32_t *)(gprs [ins >> 16 & 0x1F] += (int16_t) ins);
+         if (p == invalid_address)
+           return false;
+         gprs [ins >> 21 & 0x1F] = *p;
+         continue;
+       }
+      if (ins >> 26 == 0x24)  /* stw */
+       /* What we hope this is doing is '--in_sigtramp'.  We don't want
+          to actually store to memory, so just make a note of the
+          address and refuse to load from it.  */
+       {
+         reg_unit src = (ins >> 16 & 0x1F) == 0 ? 0 : gprs [ins >> 16 & 0x1F];
+         uint32_t *p = (uint32_t *)(src + (int16_t) ins);
+         if (p == NULL || invalid_address != NULL)
+           return false;
+         invalid_address = p;
+         continue;
+       }
+      if (ins >> 26 == 0x2E) /* lmw */
+       {
+         reg_unit src = (ins >> 16 & 0x1F) == 0 ? 0 : gprs [ins >> 16 & 0x1F];
+         uint32_t *p = (uint32_t *)(src + (int16_t) ins);
+         int i;
+
+         for (i = (ins >> 21 & 0x1F); i < 32; i++)
+           {
+             if (p == invalid_address)
+               return false;
+             gprs[i] = *p++;
+           }
+         continue;
+       }
+      if ((ins & 0xFC1FFFFF) == 0x7c0803a6)  /* mtlr */
+       {
+         lr = gprs [ins >> 21 & 0x1F];
+         continue;
+       }
+      if ((ins & 0xFC1FFFFF) == 0x7c0802a6)  /* mflr */
+       {
+         gprs [ins >> 21 & 0x1F] = lr;
+         continue;
+       }
+      if ((ins & 0xFC1FFFFF) == 0x7c0903a6)  /* mtctr */
+       {
+         ctr = gprs [ins >> 21 & 0x1F];
+         continue;
+       }
+      /* The PowerPC User's Manual says that bit 11 of the mtcrf
+        instruction is reserved and should be set to zero, but it
+        looks like the Darwin assembler doesn't do that... */
+      if ((ins & 0xFC000FFF) == 0x7c000120) /* mtcrf */
+       {
+         int i;
+         uint32_t mask = 0;
+         for (i = 0; i < 8; i++)
+           mask |= ((-(ins >> (12 + i) & 1)) & 0xF) << 4 * i;
+         cr = (cr & ~mask) | (gprs [ins >> 21 & 0x1F] & mask);
+         continue;
+       }
+      if (ins == 0x429f0005)  /* bcl- 20,4*cr7+so,.+4, loads pc into LR */
+       {
+         lr = (reg_unit) pc;
+         continue;
+       }
+      if (ins == 0x4e800420) /* bctr */
+       {
+         pc = (uint32_t *) ctr;
+         continue;
+       }
+      if (ins == 0x44000002) /* sc */
+       return true;
+
+      return false;
+    }
+}
+
+/* We used to include <ucontext.h> and <mach/thread_status.h>,
+   but they change so much between different Darwin system versions
+   that it's much easier to just write the structures involved here
+   directly.  */
+
+/* These defines are from the kernel's bsd/dev/ppc/unix_signal.c.  */
+#define UC_TRAD                 1
+#define UC_TRAD_VEC             6
+#define UC_TRAD64               20
+#define UC_TRAD64_VEC           25
+#define UC_FLAVOR               30
+#define UC_FLAVOR_VEC           35
+#define UC_FLAVOR64             40
+#define UC_FLAVOR64_VEC         45
+#define UC_DUAL                 50
+#define UC_DUAL_VEC             55
+
+struct gcc_ucontext 
+{
+  int onstack;
+  sigset_t sigmask;
+  void * stack_sp;
+  size_t stack_sz;
+  int stack_flags;
+  struct gcc_ucontext *link;
+  size_t mcsize;
+  struct gcc_mcontext32 *mcontext;
+};
+
+struct gcc_float_vector_state 
+{
+  double fpregs[32];
+  uint32_t fpscr_pad;
+  uint32_t fpscr;
+  uint32_t save_vr[32][4];
+  uint32_t save_vscr[4];
+};
+
+struct gcc_mcontext32 {
+  uint32_t dar;
+  uint32_t dsisr;
+  uint32_t exception;
+  uint32_t padding1[5];
+  uint32_t srr0;
+  uint32_t srr1;
+  uint32_t gpr[32];
+  uint32_t cr;
+  uint32_t xer;
+  uint32_t lr;
+  uint32_t ctr;
+  uint32_t mq;
+  uint32_t vrsave;
+  struct gcc_float_vector_state fvs;
+};
+
+/* These are based on /usr/include/ppc/ucontext.h and
+   /usr/include/mach/ppc/thread_status.h, but rewritten to be more
+   convenient, to compile on Jaguar, and to work around Radar 3712064
+   on Panther, which is that the 'es' field of 'struct mcontext64' has
+   the wrong type (doh!).  */
+
+struct gcc_mcontext64 {
+  uint64_t dar;
+  uint32_t dsisr;
+  uint32_t exception;
+  uint32_t padding1[4];
+  uint64_t srr0;
+  uint64_t srr1;
+  uint32_t gpr[32][2];
+  uint32_t cr;
+  uint32_t xer[2];  /* These are arrays because the original structure has them misaligned.  */
+  uint32_t lr[2];
+  uint32_t ctr[2];
+  uint32_t vrsave;
+  struct gcc_float_vector_state fvs;
+};
+
+#define UC_FLAVOR_SIZE \
+  (sizeof (struct gcc_mcontext32) - 33*16)
+
+#define UC_FLAVOR_VEC_SIZE (sizeof (struct gcc_mcontext32))
+
+#define UC_FLAVOR64_SIZE \
+  (sizeof (struct gcc_mcontext64) - 33*16)
+
+#define UC_FLAVOR64_VEC_SIZE (sizeof (struct gcc_mcontext64))
+
+/* Given GPRS as input to a 'sc' instruction, and OLD_CFA, update FS
+   to represent the execution of a signal return; or, if not a signal
+   return, return false.  */
+
+static bool
+handle_syscall (_Unwind_FrameState *fs, const reg_unit gprs[32],
+               _Unwind_Ptr old_cfa)
+{
+  struct gcc_ucontext *uctx;
+  bool is_64, is_vector;
+  struct gcc_float_vector_state * float_vector_state;
+  _Unwind_Ptr new_cfa;
+  int i;
+  static _Unwind_Ptr return_addr;
+  
+  /* Yay!  We're in a Libc that we understand, and it's made a
+     system call.  In Jaguar, this is a direct system call with value 103;
+     in Panther and Tiger it is a SYS_syscall call for system call number 184,
+     and in Leopard it is a direct syscall with number 184.  */
+  
+  if (gprs[0] == 0x67 /* SYS_SIGRETURN */)
+    {
+      uctx = (struct gcc_ucontext *) gprs[3];
+      is_vector = (uctx->mcsize == UC_FLAVOR64_VEC_SIZE
+                  || uctx->mcsize == UC_FLAVOR_VEC_SIZE);
+      is_64 = (uctx->mcsize == UC_FLAVOR64_VEC_SIZE
+              || uctx->mcsize == UC_FLAVOR64_SIZE);
+    }
+  else if (gprs[0] == 0 /* SYS_syscall */ && gprs[3] == 184)
+    {
+      int ctxstyle = gprs[5];
+      uctx = (struct gcc_ucontext *) gprs[4];
+      is_vector = (ctxstyle == UC_FLAVOR_VEC || ctxstyle == UC_FLAVOR64_VEC
+                  || ctxstyle == UC_TRAD_VEC || ctxstyle == UC_TRAD64_VEC);
+      is_64 = (ctxstyle == UC_FLAVOR64_VEC || ctxstyle == UC_TRAD64_VEC
+              || ctxstyle == UC_FLAVOR64 || ctxstyle == UC_TRAD64);
+    }
+  else if (gprs[0] == 184 /* SYS_sigreturn */)
+    {
+      int ctxstyle = gprs[4];
+      uctx = (struct gcc_ucontext *) gprs[3];
+      is_vector = (ctxstyle == UC_FLAVOR_VEC || ctxstyle == UC_FLAVOR64_VEC
+                  || ctxstyle == UC_TRAD_VEC || ctxstyle == UC_TRAD64_VEC);
+      is_64 = (ctxstyle == UC_FLAVOR64_VEC || ctxstyle == UC_TRAD64_VEC
+              || ctxstyle == UC_FLAVOR64 || ctxstyle == UC_TRAD64);
+    }
+  else
+    return false;
+
+#define set_offset(r, addr)                                    \
+  (fs->regs.reg[r].how = REG_SAVED_OFFSET,                     \
+   fs->regs.reg[r].loc.offset = (_Unwind_Ptr)(addr) - new_cfa)
+
+  /* Restore even the registers that are not call-saved, since they
+     might be being used in the prologue to save other registers,
+     for instance GPR0 is sometimes used to save LR.  */
+
+  /* Handle the GPRs, and produce the information needed to do the rest.  */
+  if (is_64)
+    {
+      /* The context is 64-bit, but it doesn't carry any extra information
+        for us because only the low 32 bits of the registers are
+        call-saved.  */
+      struct gcc_mcontext64 *m64 = (struct gcc_mcontext64 *)uctx->mcontext;
+      int i;
+
+      float_vector_state = &m64->fvs;
+
+      new_cfa = m64->gpr[1][1];
+      
+      set_offset (R_CR2, &m64->cr);
+      for (i = 0; i < 32; i++)
+       set_offset (i, m64->gpr[i] + 1);
+      set_offset (R_XER, m64->xer + 1);
+      set_offset (R_LR, m64->lr + 1);
+      set_offset (R_CTR, m64->ctr + 1);
+      if (is_vector)
+       set_offset (R_VRSAVE, &m64->vrsave);
+      
+      /* Sometimes, srr0 points to the instruction that caused the exception,
+        and sometimes to the next instruction to be executed; we want
+        the latter.  */
+      if (m64->exception == 3 || m64->exception == 4
+         || m64->exception == 6
+         || (m64->exception == 7 && !(m64->srr1 & 0x10000)))
+       return_addr = m64->srr0 + 4;
+      else
+       return_addr = m64->srr0;
+    }
+  else
+    {
+      struct gcc_mcontext32 *m = uctx->mcontext;
+      int i;
+
+      float_vector_state = &m->fvs;
+      
+      new_cfa = m->gpr[1];
+
+      set_offset (R_CR2, &m->cr);
+      for (i = 0; i < 32; i++)
+       set_offset (i, m->gpr + i);
+      set_offset (R_XER, &m->xer);
+      set_offset (R_LR, &m->lr);
+      set_offset (R_CTR, &m->ctr);
+
+      if (is_vector)
+       set_offset (R_VRSAVE, &m->vrsave);
+
+      /* Sometimes, srr0 points to the instruction that caused the exception,
+        and sometimes to the next instruction to be executed; we want
+        the latter.  */
+      if (m->exception == 3 || m->exception == 4
+         || m->exception == 6
+         || (m->exception == 7 && !(m->srr1 & 0x10000)))
+       return_addr = m->srr0 + 4;
+      else
+       return_addr = m->srr0;
+    }
+
+  fs->regs.cfa_how = CFA_REG_OFFSET;
+  fs->regs.cfa_reg = STACK_POINTER_REGNUM;
+  fs->regs.cfa_offset = new_cfa - old_cfa;;
+  
+  /* The choice of column for the return address is somewhat tricky.
+     Fortunately, the actual choice is private to this file, and
+     the space it's reserved from is the GCC register space, not the
+     DWARF2 numbering.  So any free element of the right size is an OK
+     choice.  Thus: */
+  fs->retaddr_column = ARG_POINTER_REGNUM;
+  /* FIXME: this should really be done using a DWARF2 location expression,
+     not using a static variable.  In fact, this entire file should
+     be implemented in DWARF2 expressions.  */
+  set_offset (ARG_POINTER_REGNUM, &return_addr);
+
+  for (i = 0; i < 32; i++)
+    set_offset (32 + i, float_vector_state->fpregs + i);
+  set_offset (R_SPEFSCR, &float_vector_state->fpscr);
+  
+  if (is_vector)
+    {
+      for (i = 0; i < 32; i++)
+       set_offset (R_VR0 + i, float_vector_state->save_vr + i);
+      set_offset (R_VSCR, float_vector_state->save_vscr);
+    }
+
+  return true;
+}
+
+/* This is also prototyped in rs6000/darwin.h, inside the
+   MD_FALLBACK_FRAME_STATE_FOR macro.  */
+extern bool _Unwind_fallback_frame_state_for (struct _Unwind_Context *context,
+                                             _Unwind_FrameState *fs);
+
+/* Implement the MD_FALLBACK_FRAME_STATE_FOR macro,
+   returning true iff the frame was a sigreturn() frame that we
+   can understand.  */
+
+bool
+_Unwind_fallback_frame_state_for (struct _Unwind_Context *context,
+                                 _Unwind_FrameState *fs)
+{
+  reg_unit gprs[32];
+
+  if (!interpret_libc (gprs, context))
+    return false;
+  return handle_syscall (fs, gprs, _Unwind_GetCFA (context));
+}
+#endif
index 4541e4ed3ed4c6bcd1567851c66e61036c7b5eb1..404df85870f9d64656860f741ba1a007bada3256 100644 (file)
@@ -3,4 +3,6 @@ DARWIN_EXTRA_CRT_BUILD_CFLAGS = -mlongcall -mmacosx-version-min=10.4
 crt2.o: $(srcdir)/config/rs6000/darwin-crt2.c
        $(crt_compile) $(DARWIN_EXTRA_CRT_BUILD_CFLAGS) -c $<
 
+LIB2ADDEH += $(srcdir)/config/rs6000/darwin-fallback.c
+
 SHLIB_VERPFX = $(gcc_srcdir)/config/rs6000/darwin-libgcc
index 2110c688d5f7b0e99b3ac227ed254c5c4f013570..9d416acc12d3e569134db3dd824d1a5cf46d2dd8 100644 (file)
@@ -1,7 +1,2 @@
 # Compile libgcc2.a with pic.
 HOST_LIBGCC2_CFLAGS += -fPIC
-
-# Use unwind-dw2-fde-glibc.
-LIB2ADDEH = $(gcc_srcdir)/unwind-dw2.c $(gcc_srcdir)/unwind-dw2-fde-glibc.c \
-  $(gcc_srcdir)/unwind-sjlj.c $(gcc_srcdir)/unwind-c.c \
-  $(gcc_srcdir)/emutls.c
index 548f0e3d469c9a82ec5460aa24af1029a1949ddb..311b7e2679f866392b1f07565b1aa59a39ad67b5 100644 (file)
@@ -2,3 +2,7 @@
 crt3.o: $(srcdir)/config/darwin-crt3.c
        $(crt_compile) \
          -fno-tree-dominator-opts $(DARWIN_EXTRA_CRT_BUILD_CFLAGS) -c $<
+
+# Use unwind-dw2-fde-darwin
+LIB2ADDEH = $(srcdir)/unwind-dw2.c $(srcdir)/config/unwind-dw2-fde-darwin.c \
+  $(srcdir)/unwind-sjlj.c $(srcdir)/unwind-c.c
diff --git a/libgcc/config/t-eh-dw2-dip b/libgcc/config/t-eh-dw2-dip
new file mode 100644 (file)
index 0000000..88fa103
--- /dev/null
@@ -0,0 +1,3 @@
+# Use unwind-dw2-fde-dip.
+LIB2ADDEH = $(srcdir)/unwind-dw2.c $(srcdir)/unwind-dw2-fde-dip.c \
+  $(srcdir)/unwind-sjlj.c $(srcdir)/unwind-c.c
diff --git a/libgcc/config/t-libunwind b/libgcc/config/t-libunwind
new file mode 100644 (file)
index 0000000..1c7a898
--- /dev/null
@@ -0,0 +1,3 @@
+LIB2ADDEH = $(srcdir)/unwind-sjlj.c $(srcdir)/unwind-c.c \
+  $(srcdir)/unwind-compat.c $(srcdir)/unwind-dw2-fde-compat.c
+LIB2ADDEHSTATIC = $(srcdir)/unwind-sjlj.c $(srcdir)/unwind-c.c
diff --git a/libgcc/config/t-libunwind-elf b/libgcc/config/t-libunwind-elf
new file mode 100644 (file)
index 0000000..47a460b
--- /dev/null
@@ -0,0 +1,51 @@
+# Copyright (C) 2004, 2005, 2011 Free Software Foundation, Inc.
+#
+# This file is part of GCC.
+#
+# GCC 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 3, or (at your option)
+# any later version.
+#
+# GCC 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 GCC; see the file COPYING3.  If not see
+# <http://www.gnu.org/licenses/>.
+
+# Build libunwind for ELF with the GNU linker.
+
+SHLIB_SOLINK = @shlib_base_name@.so
+SHLIB_OBJS = @shlib_objs@
+SHLIB_DIR = @multilib_dir@
+SHLIB_SLIBDIR_QUAL = @shlib_slibdir_qual@
+
+# Use unwind-dw2-fde-dip
+LIBUNWIND = $(srcdir)/unwind-dw2.c $(srcdir)/unwind-dw2-fde-dip.c
+
+SHLIBUNWIND_SOVERSION = 7
+SHLIBUNWIND_SONAME = @shlib_base_name@.so.$(SHLIBUNWIND_SOVERSION)
+
+SHLIBUNWIND_LINK = $(CC) $(LIBGCC2_CFLAGS) -shared \
+       -nodefaultlibs -Wl,-h,$(SHLIBUNWIND_SONAME) \
+       -Wl,-z,text -Wl,-z,defs -o $(SHLIB_DIR)/$(SHLIBUNWIND_SONAME).tmp \
+       @multilib_flags@ $(SHLIB_OBJS) -lc && \
+       rm -f $(SHLIB_DIR)/$(SHLIB_SOLINK) && \
+       if [ -f $(SHLIB_DIR)/$(SHLIBUNWIND_SONAME) ]; then \
+         mv -f $(SHLIB_DIR)/$(SHLIBUNWIND_SONAME) \
+               $(SHLIB_DIR)/$(SHLIBUNWIND_SONAME).backup; \
+       else true; fi && \
+       mv $(SHLIB_DIR)/$(SHLIBUNWIND_SONAME).tmp \
+          $(SHLIB_DIR)/$(SHLIBUNWIND_SONAME) && \
+       $(LN_S) $(SHLIBUNWIND_SONAME) $(SHLIB_DIR)/$(SHLIB_SOLINK)
+
+SHLIBUNWIND_INSTALL = \
+       $(SHELL) $(srcdir)/mkinstalldirs $(DESTDIR)$(slibdir)$(SHLIB_SLIBDIR_QUAL); \
+       $(INSTALL_DATA) $(SHLIB_DIR)/$(SHLIBUNWIND_SONAME) \
+         $(DESTDIR)$(slibdir)$(SHLIB_SLIBDIR_QUAL)/$(SHLIBUNWIND_SONAME); \
+       rm -f $(DESTDIR)$(slibdir)$(SHLIB_SLIBDIR_QUAL)/$(SHLIB_SOLINK); \
+       $(LN_S) $(SHLIBUNWIND_SONAME) \
+         $(DESTDIR)$(slibdir)$(SHLIB_SLIBDIR_QUAL)/$(SHLIB_SOLINK)
index e55c64f646d1e779ad177d53507a39c87245627e..bfb8f3b5cc2ee3144778f5d2ab537e9f1aee5d34 100644 (file)
 # along with GCC; see the file COPYING3.  If not see
 # <http://www.gnu.org/licenses/>.
 
-# Use unwind-dw2-fde-glibc.c.  Unless linker support and dl_iterate_phdr
-# are present, automatically falls back to unwind-dw2-fde.c.
-LIB2ADDEH = $(gcc_srcdir)/unwind-dw2.c $(gcc_srcdir)/unwind-dw2-fde-glibc.c \
-  $(gcc_srcdir)/unwind-sjlj.c $(gcc_srcdir)/unwind-c.c $(gcc_srcdir)/emutls.c
-
 # gmon build rule:
 gmon.o:        $(srcdir)/config/gmon-sol2.c
        $(gcc_compile) -c $<
diff --git a/libgcc/config/unwind-dw2-fde-darwin.c b/libgcc/config/unwind-dw2-fde-darwin.c
new file mode 100644 (file)
index 0000000..75b404e
--- /dev/null
@@ -0,0 +1,289 @@
+/* Copyright (C) 2001, 2002, 2003, 2005, 2009, 2010
+   Free Software Foundation, Inc.
+
+   This file is part of GCC.
+
+   GCC 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 3, or (at your option)
+   any later version.
+
+   GCC 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.
+
+   Under Section 7 of GPL version 3, you are granted additional
+   permissions described in the GCC Runtime Library Exception, version
+   3.1, as published by the Free Software Foundation.
+
+   You should have received a copy of the GNU General Public License and
+   a copy of the GCC Runtime Library Exception along with this program;
+   see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+   <http://www.gnu.org/licenses/>.  */
+
+/* Locate the FDE entry for a given address, using Darwin's keymgr support.  */
+
+#include "tconfig.h"
+#include "tsystem.h"
+#include <string.h>
+#include <stdlib.h>
+#include "dwarf2.h"
+#include "unwind.h"
+#define NO_BASE_OF_ENCODED_VALUE
+#define DWARF2_OBJECT_END_PTR_EXTENSION
+#include "unwind-pe.h"
+#include "unwind-dw2-fde.h"
+/* Carefully don't include gthr.h.  */
+
+typedef int __gthread_mutex_t;
+#define __gthread_mutex_lock(x)  (void)(x)
+#define __gthread_mutex_unlock(x) (void)(x)
+
+static const fde * _Unwind_Find_registered_FDE (void *pc,
+                                               struct dwarf_eh_bases *bases);
+
+#define _Unwind_Find_FDE _Unwind_Find_registered_FDE
+#include "unwind-dw2-fde.c"
+#undef _Unwind_Find_FDE
+
+/* KeyMgr stuff.  */
+#define KEYMGR_GCC3_LIVE_IMAGE_LIST     301     /* loaded images  */
+#define KEYMGR_GCC3_DW2_OBJ_LIST        302     /* Dwarf2 object list  */
+
+extern void *_keymgr_get_and_lock_processwide_ptr (int);
+extern void _keymgr_set_and_unlock_processwide_ptr (int, void *);
+extern void _keymgr_unlock_processwide_ptr (int);
+
+struct mach_header;
+struct mach_header_64;
+extern char *getsectdatafromheader (struct mach_header*, const char*,
+                                   const char *, unsigned long *);
+extern char *getsectdatafromheader_64 (struct mach_header_64*, const char*,
+                                      const char *, unsigned long *);
+
+/* This is referenced from KEYMGR_GCC3_DW2_OBJ_LIST.  */
+struct km_object_info {
+  struct object *seen_objects;
+  struct object *unseen_objects;
+  unsigned spare[2];
+};
+
+/* Node of KEYMGR_GCC3_LIVE_IMAGE_LIST.  Info about each resident image.  */
+struct live_images {
+  unsigned long this_size;                      /* sizeof (live_images)  */
+  struct mach_header *mh;                       /* the image info  */
+  unsigned long vm_slide;
+  void (*destructor)(struct live_images *);     /* destructor for this  */
+  struct live_images *next;
+  unsigned int examined_p;
+  void *fde;
+  void *object_info;
+  unsigned long info[2];                        /* Future use.  */
+};
+
+/* Bits in the examined_p field of struct live_images.  */
+enum {
+  EXAMINED_IMAGE_MASK = 1,     /* We've seen this one.  */
+  ALLOCED_IMAGE_MASK = 2,      /* The FDE entries were allocated by
+                                  malloc, and must be freed.  This isn't
+                                  used by newer libgcc versions.  */
+  IMAGE_IS_TEXT_MASK = 4,      /* This image is in the TEXT segment.  */
+  DESTRUCTOR_MAY_BE_CALLED_LIVE = 8  /* The destructor may be called on an
+                                       object that's part of the live
+                                       image list.  */
+};
+\f
+/* Delete any data we allocated on a live_images structure.  Either
+   IMAGE has already been removed from the
+   KEYMGR_GCC3_LIVE_IMAGE_LIST and the struct will be deleted
+   after we return, or that list is locked and we're being called
+   because this object might be about to be unloaded.  Called by
+   KeyMgr.  */
+
+static void
+live_image_destructor (struct live_images *image)
+{
+  if (image->object_info)
+    {
+      struct km_object_info *the_obj_info;
+
+      the_obj_info =
+       _keymgr_get_and_lock_processwide_ptr (KEYMGR_GCC3_DW2_OBJ_LIST);
+      if (the_obj_info)
+       {
+         seen_objects = the_obj_info->seen_objects;
+         unseen_objects = the_obj_info->unseen_objects;
+
+         /* Free any sorted arrays.  */
+         __deregister_frame_info_bases (image->fde);
+
+         the_obj_info->seen_objects = seen_objects;
+         the_obj_info->unseen_objects = unseen_objects;
+       }
+      _keymgr_set_and_unlock_processwide_ptr (KEYMGR_GCC3_DW2_OBJ_LIST,
+                                             the_obj_info);
+
+      free (image->object_info);
+      image->object_info = NULL;
+      if (image->examined_p & ALLOCED_IMAGE_MASK)
+       free (image->fde);
+      image->fde = NULL;
+    }
+  image->examined_p = 0;
+  image->destructor = NULL;
+}
+
+/* Run through the list of live images.  If we can allocate memory,
+   give each unseen image a new `struct object'.  Even if we can't,
+   check whether the PC is inside the FDE of each unseen image.
+ */
+
+static inline const fde *
+examine_objects (void *pc, struct dwarf_eh_bases *bases, int dont_alloc)
+{
+  const fde *result = NULL;
+  struct live_images *image;
+
+  image = _keymgr_get_and_lock_processwide_ptr (KEYMGR_GCC3_LIVE_IMAGE_LIST);
+
+  for (; image != NULL; image = image->next)
+    if ((image->examined_p & EXAMINED_IMAGE_MASK) == 0)
+      {
+       char *fde = NULL;
+       unsigned long sz;
+
+       /* For ppc only check whether or not we have __DATA eh frames.  */
+#ifdef __ppc__
+       fde = getsectdatafromheader (image->mh, "__DATA", "__eh_frame", &sz);
+#endif
+
+       if (fde == NULL)
+         {
+#if __LP64__
+           fde = getsectdatafromheader_64 ((struct mach_header_64 *) image->mh,
+                                           "__TEXT", "__eh_frame", &sz);
+#else
+           fde = getsectdatafromheader (image->mh, "__TEXT",
+                                        "__eh_frame", &sz);
+#endif
+           if (fde != NULL)
+             image->examined_p |= IMAGE_IS_TEXT_MASK;
+         }
+
+       /* If .eh_frame is empty, don't register at all.  */
+       if (fde != NULL && sz > 0)
+         {
+           char *real_fde = (fde + image->vm_slide);
+           struct object *ob = NULL;
+           struct object panicob;
+
+           if (! dont_alloc)
+             ob = calloc (1, sizeof (struct object));
+           dont_alloc |= ob == NULL;
+           if (dont_alloc)
+             ob = &panicob;
+
+           ob->pc_begin = (void *)-1;
+           ob->tbase = 0;
+           ob->dbase = 0;
+           ob->u.single = (struct dwarf_fde *)real_fde;
+           ob->s.i = 0;
+           ob->s.b.encoding = DW_EH_PE_omit;
+           ob->fde_end = real_fde + sz;
+
+           image->fde = real_fde;
+
+           result = search_object (ob, pc);
+
+           if (! dont_alloc)
+             {
+               struct object **p;
+
+               image->destructor = live_image_destructor;
+               image->object_info = ob;
+
+               image->examined_p |= (EXAMINED_IMAGE_MASK
+                                     | DESTRUCTOR_MAY_BE_CALLED_LIVE);
+
+               /* 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 (result)
+             {
+               int encoding;
+               _Unwind_Ptr func;
+
+               bases->tbase = ob->tbase;
+               bases->dbase = ob->dbase;
+
+               encoding = ob->s.b.encoding;
+               if (ob->s.b.mixed_encoding)
+                 encoding = get_fde_encoding (result);
+               read_encoded_value_with_base (encoding,
+                                             base_from_object (encoding, ob),
+                                             result->pc_begin, &func);
+               bases->func = (void *) func;
+               break;
+             }
+         }
+       else
+         image->examined_p |= EXAMINED_IMAGE_MASK;
+      }
+
+  _keymgr_unlock_processwide_ptr (KEYMGR_GCC3_LIVE_IMAGE_LIST);
+
+  return result;
+}
+
+const fde *
+_Unwind_Find_FDE (void *pc, struct dwarf_eh_bases *bases)
+{
+  struct km_object_info *the_obj_info;
+  const fde *ret = NULL;
+
+  the_obj_info =
+    _keymgr_get_and_lock_processwide_ptr (KEYMGR_GCC3_DW2_OBJ_LIST);
+  if (! the_obj_info)
+    the_obj_info = calloc (1, sizeof (*the_obj_info));
+
+  if (the_obj_info != NULL)
+    {
+      seen_objects = the_obj_info->seen_objects;
+      unseen_objects = the_obj_info->unseen_objects;
+
+      ret = _Unwind_Find_registered_FDE (pc, bases);
+    }
+
+  /* OK, didn't find it in the list of FDEs we've seen before,
+     so go through and look at the new ones.  */
+  if (ret == NULL)
+    ret = examine_objects (pc, bases, the_obj_info == NULL);
+
+  if (the_obj_info != NULL)
+    {
+      the_obj_info->seen_objects = seen_objects;
+      the_obj_info->unseen_objects = unseen_objects;
+    }
+  _keymgr_set_and_unlock_processwide_ptr (KEYMGR_GCC3_DW2_OBJ_LIST,
+                                         the_obj_info);
+  return ret;
+}
+
+void *
+_darwin10_Unwind_FindEnclosingFunction (void *pc ATTRIBUTE_UNUSED)
+{
+#if __MACH__ && (__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ >= 1060)
+  struct dwarf_eh_bases bases;
+  const struct dwarf_fde *fde = _Unwind_Find_FDE (pc-1, &bases);
+  if (fde)
+    return bases.func;
+#endif
+  return NULL;
+}
+
diff --git a/libgcc/config/xtensa/t-xtensa b/libgcc/config/xtensa/t-xtensa
new file mode 100644 (file)
index 0000000..7d9e9db
--- /dev/null
@@ -0,0 +1,2 @@
+LIB2ADDEH = $(srcdir)/config/xtensa/unwind-dw2-xtensa.c \
+   $(srcdir)/unwind-dw2-fde.c $(srcdir)/unwind-sjlj.c $(srcdir)/unwind-c.c
diff --git a/libgcc/config/xtensa/unwind-dw2-xtensa.c b/libgcc/config/xtensa/unwind-dw2-xtensa.c
new file mode 100644 (file)
index 0000000..54daf76
--- /dev/null
@@ -0,0 +1,544 @@
+/* DWARF2 exception handling and frame unwinding for Xtensa.
+   Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006,
+   2007, 2008, 2009, 2011
+   Free Software Foundation, Inc.
+
+   This file is part of GCC.
+
+   GCC 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 3, or (at your option)
+   any later version.
+
+   GCC 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.
+
+   Under Section 7 of GPL version 3, you are granted additional
+   permissions described in the GCC Runtime Library Exception, version
+   3.1, as published by the Free Software Foundation.
+
+   You should have received a copy of the GNU General Public License and
+   a copy of the GCC Runtime Library Exception along with this program;
+   see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include "tconfig.h"
+#include "tsystem.h"
+#include "coretypes.h"
+#include "tm.h"
+#include "dwarf2.h"
+#include "unwind.h"
+#ifdef __USING_SJLJ_EXCEPTIONS__
+# define NO_SIZE_OF_ENCODED_VALUE
+#endif
+#include "unwind-pe.h"
+#include "unwind-dw2-fde.h"
+#include "unwind-dw2-xtensa.h"
+
+#ifndef __USING_SJLJ_EXCEPTIONS__
+
+/* The standard CIE and FDE structures work fine for Xtensa but the
+   variable-size register window save areas are not a good fit for the rest
+   of the standard DWARF unwinding mechanism.  Nor is that mechanism
+   necessary, since the register save areas are always in fixed locations
+   in each stack frame.  This file is a stripped down and customized version
+   of the standard DWARF unwinding code.  It needs to be customized to have
+   builtin logic for finding the save areas and also to track the stack
+   pointer value (besides the CFA) while unwinding since the primary save
+   area is located below the stack pointer.  It is stripped down to reduce
+   code size and ease the maintenance burden of tracking changes in the
+   standard version of the code.  */
+
+#ifndef DWARF_REG_TO_UNWIND_COLUMN
+#define DWARF_REG_TO_UNWIND_COLUMN(REGNO) (REGNO)
+#endif
+
+#define XTENSA_RA_FIELD_MASK 0x3FFFFFFF
+
+/* This is the register and unwind state for a particular frame.  This
+   provides the information necessary to unwind up past a frame and return
+   to its caller.  */
+struct _Unwind_Context
+{
+  /* Track register window save areas of 4 registers each, instead of
+     keeping separate addresses for the individual registers.  */
+  _Unwind_Word *reg[4];
+
+  void *cfa;
+  void *sp;
+  void *ra;
+
+  /* Cache the 2 high bits to replace the window size in return addresses.  */
+  _Unwind_Word ra_high_bits;
+
+  void *lsda;
+  struct dwarf_eh_bases bases;
+  /* Signal frame context.  */
+#define SIGNAL_FRAME_BIT ((~(_Unwind_Word) 0 >> 1) + 1)
+  _Unwind_Word flags;
+  /* 0 for now, can be increased when further fields are added to
+     struct _Unwind_Context.  */
+  _Unwind_Word version;
+};
+
+\f
+/* Read unaligned data from the instruction buffer.  */
+
+union unaligned
+{
+  void *p;
+} __attribute__ ((packed));
+
+static void uw_update_context (struct _Unwind_Context *, _Unwind_FrameState *);
+static _Unwind_Reason_Code uw_frame_state_for (struct _Unwind_Context *,
+                                              _Unwind_FrameState *);
+
+static inline void *
+read_pointer (const void *p) { const union unaligned *up = p; return up->p; }
+\f
+static inline _Unwind_Word
+_Unwind_IsSignalFrame (struct _Unwind_Context *context)
+{
+  return (context->flags & SIGNAL_FRAME_BIT) ? 1 : 0;
+}
+
+static inline void
+_Unwind_SetSignalFrame (struct _Unwind_Context *context, int val)
+{
+  if (val)
+    context->flags |= SIGNAL_FRAME_BIT;
+  else
+    context->flags &= ~SIGNAL_FRAME_BIT;
+}
+\f
+/* Get the value of register INDEX as saved in CONTEXT.  */
+
+inline _Unwind_Word
+_Unwind_GetGR (struct _Unwind_Context *context, int index)
+{
+  _Unwind_Word *ptr;
+
+  index = DWARF_REG_TO_UNWIND_COLUMN (index);
+  ptr = context->reg[index >> 2] + (index & 3);
+
+  return *ptr;
+}
+
+/* Get the value of the CFA as saved in CONTEXT.  */
+
+_Unwind_Word
+_Unwind_GetCFA (struct _Unwind_Context *context)
+{
+  return (_Unwind_Ptr) context->cfa;
+}
+
+/* Overwrite the saved value for register INDEX in CONTEXT with VAL.  */
+
+inline void
+_Unwind_SetGR (struct _Unwind_Context *context, int index, _Unwind_Word val)
+{
+  _Unwind_Word *ptr;
+
+  index = DWARF_REG_TO_UNWIND_COLUMN (index);
+  ptr = context->reg[index >> 2] + (index & 3);
+
+  *ptr = val;
+}
+
+/* Retrieve the return address for CONTEXT.  */
+
+inline _Unwind_Ptr
+_Unwind_GetIP (struct _Unwind_Context *context)
+{
+  return (_Unwind_Ptr) context->ra;
+}
+
+/* Retrieve the return address and flag whether that IP is before
+   or after first not yet fully executed instruction.  */
+
+inline _Unwind_Ptr
+_Unwind_GetIPInfo (struct _Unwind_Context *context, int *ip_before_insn)
+{
+  *ip_before_insn = _Unwind_IsSignalFrame (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;
+}
+
+void *
+_Unwind_FindEnclosingFunction (void *pc)
+{
+  struct dwarf_eh_bases bases;
+  const struct dwarf_fde *fde = _Unwind_Find_FDE (pc-1, &bases);
+  if (fde)
+    return bases.func;
+  else
+    return NULL;
+}
+
+_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;
+}
+
+#include "md-unwind-support.h"
+\f
+/* 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 (const struct dwarf_cie *cie, struct _Unwind_Context *context,
+                 _Unwind_FrameState *fs)
+{
+  const unsigned char *aug = cie->augmentation;
+  const unsigned char *p = aug + strlen ((const char *)aug) + 1;
+  const unsigned char *ret = NULL;
+  _uleb128_t utmp;
+  _sleb128_t stmp;
+
+  /* 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, &utmp);
+  p = read_sleb128 (p, &stmp);
+  if (cie->version == 1)
+    fs->retaddr_column = *p++;
+  else
+    {
+      p = read_uleb128 (p, &utmp);
+      fs->retaddr_column = (_Unwind_Word)utmp;
+    }
+  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, &utmp);
+      ret = p + utmp;
+
+      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')
+       {
+         _Unwind_Ptr personality;
+         
+         p = read_encoded_value (context, *p, p + 1, &personality);
+         fs->personality = (_Unwind_Personality_Fn) personality;
+         aug += 1;
+       }
+
+      /* "S" indicates a signal frame.  */
+      else if (aug[0] == 'S')
+       {
+         fs->signal_frame = 1;
+         aug += 1;
+       }
+
+      /* Otherwise we have an unknown augmentation string.
+        Bail unless we saw a 'z' prefix.  */
+      else
+       return ret;
+    }
+
+  return ret ? ret : p;
+}
+\f
+/* Given the _Unwind_Context CONTEXT for a stack frame, look up the FDE for
+   its caller and decode it into FS.  This function also sets the
+   lsda member of CONTEXT, as it is really information
+   about the caller's frame.  */
+
+static _Unwind_Reason_Code
+uw_frame_state_for (struct _Unwind_Context *context, _Unwind_FrameState *fs)
+{
+  const struct dwarf_fde *fde;
+  const struct dwarf_cie *cie;
+  const unsigned char *aug;
+  int window_size;
+  _Unwind_Word *ra_ptr;
+
+  memset (fs, 0, sizeof (*fs));
+  context->lsda = 0;
+
+  fde = _Unwind_Find_FDE (context->ra + _Unwind_IsSignalFrame (context) - 1,
+                         &context->bases);
+  if (fde == NULL)
+    {
+#ifdef MD_FALLBACK_FRAME_STATE_FOR
+      _Unwind_Reason_Code reason;
+      /* Couldn't find frame unwind info for this function.  Try a
+        target-specific fallback mechanism.  This will necessarily
+        not provide a personality routine or LSDA.  */
+      reason = MD_FALLBACK_FRAME_STATE_FOR (context, fs);
+      if (reason != _URC_END_OF_STACK)
+       return reason;
+#endif
+      /* The frame was not recognized and handled by the fallback function,
+        but it is not really the end of the stack.  Fall through here and
+        unwind it anyway.  */
+    }
+  else
+    {
+      cie = get_cie (fde);
+      if (extract_cie_info (cie, context, fs) == NULL)
+       /* CIE contained unknown augmentation.  */
+       return _URC_FATAL_PHASE1_ERROR;
+
+      /* Locate augmentation for the fde.  */
+      aug = (const unsigned char *) fde + sizeof (*fde);
+      aug += 2 * size_of_encoded_value (fs->fde_encoding);
+      if (fs->saw_z)
+       {
+         _uleb128_t i;
+         aug = read_uleb128 (aug, &i);
+       }
+      if (fs->lsda_encoding != DW_EH_PE_omit)
+       {
+         _Unwind_Ptr lsda;
+
+         aug = read_encoded_value (context, fs->lsda_encoding, aug, &lsda);
+         context->lsda = (void *) lsda;
+       }
+    }
+
+  /* Check for the end of the stack.  This needs to be checked after
+     the MD_FALLBACK_FRAME_STATE_FOR check for signal frames because
+     the contents of context->reg[0] are undefined at a signal frame,
+     and register a0 may appear to be zero.  (The return address in
+     context->ra comes from register a4 or a8).  */
+  ra_ptr = context->reg[0];
+  if (ra_ptr && *ra_ptr == 0)
+    return _URC_END_OF_STACK;
+
+  /* Find the window size from the high bits of the return address.  */
+  if (ra_ptr)
+    window_size = (*ra_ptr >> 30) * 4;
+  else
+    window_size = 8;
+
+  fs->retaddr_column = window_size;
+
+  return _URC_NO_REASON;
+}
+\f
+static void
+uw_update_context_1 (struct _Unwind_Context *context, _Unwind_FrameState *fs)
+{
+  struct _Unwind_Context orig_context = *context;
+  _Unwind_Word *sp, *cfa, *next_cfa;
+  int i;
+
+  if (fs->signal_regs)
+    {
+      cfa = (_Unwind_Word *) fs->signal_regs[1];
+      next_cfa = (_Unwind_Word *) cfa[-3];
+
+      for (i = 0; i < 4; i++)
+       context->reg[i] = fs->signal_regs + (i << 2);
+    }
+  else
+    {
+      int window_size = fs->retaddr_column >> 2;
+
+      sp = (_Unwind_Word *) orig_context.sp;
+      cfa = (_Unwind_Word *) orig_context.cfa;
+      next_cfa = (_Unwind_Word *) cfa[-3];
+
+      /* Registers a0-a3 are in the save area below sp.  */
+      context->reg[0] = sp - 4;
+
+      /* Find the extra save area below next_cfa.  */
+      for (i = 1; i < window_size; i++)
+       context->reg[i] = next_cfa - 4 * (1 + window_size - i);
+
+      /* Remaining registers rotate from previous save areas.  */
+      for (i = window_size; i < 4; i++)
+       context->reg[i] = orig_context.reg[i - window_size];
+    }
+
+  context->sp = cfa;
+  context->cfa = next_cfa;
+
+  _Unwind_SetSignalFrame (context, fs->signal_frame);
+}
+
+/* CONTEXT describes the unwind state for a frame, and FS describes the FDE
+   of its caller.  Update CONTEXT to refer to the caller as well.  Note
+   that the lsda member is not updated here, but later in
+   uw_frame_state_for.  */
+
+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.  */
+  if (fs->signal_ra != 0)
+    context->ra = (void *) fs->signal_ra;
+  else
+    context->ra = (void *) ((_Unwind_GetGR (context, fs->retaddr_column)
+                            & XTENSA_RA_FIELD_MASK) | context->ra_high_bits);
+}
+
+static void
+uw_advance_context (struct _Unwind_Context *context, _Unwind_FrameState *fs)
+{
+  uw_update_context (context, fs);
+}
+\f
+/* 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                                                                      \
+    {                                                                     \
+      __builtin_unwind_init ();                                                   \
+      uw_init_context_1 (CONTEXT, __builtin_dwarf_cfa (),                 \
+                        __builtin_return_address (0));                    \
+    }                                                                     \
+  while (0)
+
+static void __attribute__((noinline))
+uw_init_context_1 (struct _Unwind_Context *context, void *outer_cfa,
+                  void *outer_ra)
+{
+  void *ra = __builtin_return_address (0);
+  void *cfa = __builtin_dwarf_cfa ();
+  _Unwind_FrameState fs;
+
+  memset (context, 0, sizeof (struct _Unwind_Context));
+  context->ra = ra;
+
+  memset (&fs, 0, sizeof (fs));
+  fs.retaddr_column = 8;
+  context->sp = cfa;
+  context->cfa = outer_cfa;
+  context->ra_high_bits =
+    ((_Unwind_Word) uw_init_context_1) & ~XTENSA_RA_FIELD_MASK;
+  uw_update_context_1 (context, &fs);
+
+  context->ra = 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 long
+uw_install_context_1 (struct _Unwind_Context *current,
+                     struct _Unwind_Context *target)
+{
+  long i;
+
+  /* The eh_return insn assumes a window size of 8, so don't bother copying
+     the save areas for registers a8-a15 since they won't be reloaded.  */
+  for (i = 0; i < 2; ++i)
+    {
+      void *c = current->reg[i];
+      void *t = target->reg[i];
+
+      if (t && c && t != c)
+       memcpy (c, t, 4 * sizeof (_Unwind_Word));
+    }
+
+  return 0;
+}
+
+static inline _Unwind_Ptr
+uw_identify_context (struct _Unwind_Context *context)
+{
+  return _Unwind_GetCFA (context);
+}
+
+
+#include "unwind.inc"
+
+#if defined (USE_GAS_SYMVER) && defined (SHARED) && defined (USE_LIBUNWIND_EXCEPTIONS)
+alias (_Unwind_Backtrace);
+alias (_Unwind_DeleteException);
+alias (_Unwind_FindEnclosingFunction);
+alias (_Unwind_ForcedUnwind);
+alias (_Unwind_GetDataRelBase);
+alias (_Unwind_GetTextRelBase);
+alias (_Unwind_GetCFA);
+alias (_Unwind_GetGR);
+alias (_Unwind_GetIP);
+alias (_Unwind_GetLanguageSpecificData);
+alias (_Unwind_GetRegionStart);
+alias (_Unwind_RaiseException);
+alias (_Unwind_Resume);
+alias (_Unwind_Resume_or_Rethrow);
+alias (_Unwind_SetGR);
+alias (_Unwind_SetIP);
+#endif
+
+#endif /* !USING_SJLJ_EXCEPTIONS */
diff --git a/libgcc/config/xtensa/unwind-dw2-xtensa.h b/libgcc/config/xtensa/unwind-dw2-xtensa.h
new file mode 100644 (file)
index 0000000..d13b326
--- /dev/null
@@ -0,0 +1,50 @@
+/* DWARF2 frame unwind data structure for Xtensa.
+   Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2007, 2008,
+   2009  Free Software Foundation, Inc.
+
+   This file is part of GCC.
+
+   GCC 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 3, or (at your option)
+   any later version.
+
+   GCC 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.
+
+   Under Section 7 of GPL version 3, you are granted additional
+   permissions described in the GCC Runtime Library Exception, version
+   3.1, as published by the Free Software Foundation.
+
+   You should have received a copy of the GNU General Public License and
+   a copy of the GCC Runtime Library Exception along with this program;
+   see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+   <http://www.gnu.org/licenses/>.  */
+
+/* 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
+
+/* Xtensa's variable-size register window save areas can be unwound without
+   any unwind info.  This is a stripped down version of the standard DWARF
+   _Unwind_FrameState.  */
+typedef struct
+{
+  /* The information we care about from the CIE/FDE.  */
+  _Unwind_Personality_Fn personality;
+  _Unwind_Word retaddr_column;
+  unsigned char fde_encoding;
+  unsigned char lsda_encoding;
+  unsigned char saw_z;
+  unsigned char signal_frame;
+  void *eh_ptr;
+
+  /* Saved registers for a signal frame.  */
+  _Unwind_Word *signal_regs;
+  _Unwind_Word signal_ra;
+} _Unwind_FrameState;
+
index 9845eadb65a54ef0eabdc752c6d38fadbf4301d6..6036338731279a7144cc030702fe130b0d54177f 100644 (file)
@@ -651,6 +651,7 @@ with_slibdir
 enable_maintainer_mode
 with_build_libsubdir
 enable_decimal_float
+with_system_libunwind
 enable_tls
 '
       ac_precious_vars='build_alias
@@ -1295,6 +1296,7 @@ Optional Packages:
   --with-ld               arrange to use the specified ld (full pathname)
   --with-slibdir=DIR      shared libraries in DIR LIBDIR
   --with-build-libsubdir=DIR  Directory where to find libraries for build system
+  --with-system-libunwind use installed libunwind
 
 Some influential environment variables:
   CC          C compiler command
@@ -3743,6 +3745,46 @@ $as_echo "$libgcc_cv_fixed_point" >&6; }
 fixed_point=$libgcc_cv_fixed_point
 
 
+# For platforms with the unwind ABI which includes an unwind library,
+# libunwind, we can choose to use the system libunwind.
+# config.gcc also contains tests of with_system_libunwind.
+
+
+# Check whether --with-system-libunwind was given.
+if test "${with_system_libunwind+set}" = set; then :
+  withval=$with_system_libunwind;
+fi
+
+  # If system-libunwind was not specifically set, pick a default setting.
+  if test x$with_system_libunwind = x; then
+    case ${target} in
+      ia64-*-hpux*) with_system_libunwind=yes ;;
+      *) with_system_libunwind=no ;;
+    esac
+  fi
+  # Based on system-libunwind and target, do we have ipinfo?
+  if  test x$with_system_libunwind = xyes; then
+    case ${target} in
+      ia64-*-*) have_unwind_getipinfo=no ;;
+      *) have_unwind_getipinfo=yes ;;
+    esac
+  else
+    # Darwin before version 9 does not have _Unwind_GetIPInfo.
+
+    case ${target} in
+      *-*-darwin[3-8]|*-*-darwin[3-8].*) have_unwind_getipinfo=no ;;
+      *) have_unwind_getipinfo=yes ;;
+    esac
+
+  fi
+
+  if test x$have_unwind_getipinfo = xyes; then
+
+$as_echo "#define HAVE_GETIPINFO 1" >>confdefs.h
+
+  fi
+
+
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking if the linker ($LD) is GNU ld" >&5
 $as_echo_n "checking if the linker ($LD) is GNU ld... " >&6; }
 if test "${acl_cv_prog_gnu_ld+set}" = set; then :
@@ -3962,6 +4004,8 @@ tmake_file="${tmake_file_}"
 
 ac_config_links="$ac_config_links enable-execute-stack.c:$enable_execute_stack"
 
+ac_config_links="$ac_config_links unwind.h:$unwind_header"
+
 ac_config_links="$ac_config_links md-unwind-support.h:config/$md_unwind_header"
 
 
@@ -4690,6 +4734,7 @@ for ac_config_target in $ac_config_targets
 do
   case $ac_config_target in
     "enable-execute-stack.c") CONFIG_LINKS="$CONFIG_LINKS enable-execute-stack.c:$enable_execute_stack" ;;
+    "unwind.h") CONFIG_LINKS="$CONFIG_LINKS unwind.h:$unwind_header" ;;
     "md-unwind-support.h") CONFIG_LINKS="$CONFIG_LINKS md-unwind-support.h:config/$md_unwind_header" ;;
     "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;;
     "default") CONFIG_COMMANDS="$CONFIG_COMMANDS default" ;;
index 39a2e920ba75a1c954a9e0277002d74ec9e19989..d96bcb4224a9c5b339296ea13c7c6841dbeadc86 100644 (file)
@@ -7,6 +7,7 @@ sinclude(../config/no-executables.m4)
 sinclude(../config/lib-ld.m4)
 sinclude(../config/override.m4)
 sinclude(../config/dfp.m4)
+sinclude(../config/unwind_ipinfo.m4)
 
 AC_PREREQ(2.64)
 AC_INIT([GNU C Runtime Library], 1.0,,[libgcc])
@@ -167,6 +168,11 @@ AC_CACHE_CHECK([whether fixed-point is supported], [libgcc_cv_fixed_point],
 fixed_point=$libgcc_cv_fixed_point
 AC_SUBST(fixed_point)
 
+# For platforms with the unwind ABI which includes an unwind library,
+# libunwind, we can choose to use the system libunwind.
+# config.gcc also contains tests of with_system_libunwind.
+GCC_CHECK_UNWIND_GETIPINFO
+
 AC_LIB_PROG_LD_GNU
 
 AC_MSG_CHECKING([for thread model used by GCC])
@@ -277,6 +283,7 @@ AC_SUBST(cpu_type)
 AC_SUBST(extra_parts)
 AC_SUBST(asm_hidden_op)
 AC_CONFIG_LINKS([enable-execute-stack.c:$enable_execute_stack])
+AC_CONFIG_LINKS([unwind.h:$unwind_header])
 AC_CONFIG_LINKS([md-unwind-support.h:config/$md_unwind_header])
 
 # We need multilib support.
diff --git a/libgcc/emutls.c b/libgcc/emutls.c
new file mode 100644 (file)
index 0000000..b7ee3bd
--- /dev/null
@@ -0,0 +1,202 @@
+/* TLS emulation.
+   Copyright (C) 2006, 2008, 2009 Free Software Foundation, Inc.
+   Contributed by Jakub Jelinek <jakub@redhat.com>.
+
+This file is part of GCC.
+
+GCC 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 3, or (at your option) any later
+version.
+
+GCC 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.
+
+Under Section 7 of GPL version 3, you are granted additional
+permissions described in the GCC Runtime Library Exception, version
+3.1, as published by the Free Software Foundation.
+
+You should have received a copy of the GNU General Public License and
+a copy of the GCC Runtime Library Exception along with this program;
+see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+<http://www.gnu.org/licenses/>.  */
+
+#include "tconfig.h"
+#include "tsystem.h"
+#include "coretypes.h"
+#include "tm.h"
+#include "gthr.h"
+
+typedef unsigned int word __attribute__((mode(word)));
+typedef unsigned int pointer __attribute__((mode(pointer)));
+
+struct __emutls_object
+{
+  word size;
+  word align;
+  union {
+    pointer offset;
+    void *ptr;
+  } loc;
+  void *templ;
+};
+
+struct __emutls_array
+{
+  pointer size;
+  void **data[];
+};
+
+void *__emutls_get_address (struct __emutls_object *);
+void __emutls_register_common (struct __emutls_object *, word, word, void *);
+
+#ifdef __GTHREADS
+#ifdef __GTHREAD_MUTEX_INIT
+static __gthread_mutex_t emutls_mutex = __GTHREAD_MUTEX_INIT;
+#else
+static __gthread_mutex_t emutls_mutex;
+#endif
+static __gthread_key_t emutls_key;
+static pointer emutls_size;
+
+static void
+emutls_destroy (void *ptr)
+{
+  struct __emutls_array *arr = ptr;
+  pointer size = arr->size;
+  pointer i;
+
+  for (i = 0; i < size; ++i)
+    {
+      if (arr->data[i])
+       free (arr->data[i][-1]);
+    }
+
+  free (ptr);
+}
+
+static void
+emutls_init (void)
+{
+#ifndef __GTHREAD_MUTEX_INIT
+  __GTHREAD_MUTEX_INIT_FUNCTION (&emutls_mutex);
+#endif
+  if (__gthread_key_create (&emutls_key, emutls_destroy) != 0)
+    abort ();
+}
+#endif
+
+static void *
+emutls_alloc (struct __emutls_object *obj)
+{
+  void *ptr;
+  void *ret;
+
+  /* We could use here posix_memalign if available and adjust
+     emutls_destroy accordingly.  */
+  if (obj->align <= sizeof (void *))
+    {
+      ptr = malloc (obj->size + sizeof (void *));
+      if (ptr == NULL)
+       abort ();
+      ((void **) ptr)[0] = ptr;
+      ret = ptr + sizeof (void *);
+    }
+  else
+    {
+      ptr = malloc (obj->size + sizeof (void *) + obj->align - 1);
+      if (ptr == NULL)
+       abort ();
+      ret = (void *) (((pointer) (ptr + sizeof (void *) + obj->align - 1))
+                     & ~(pointer)(obj->align - 1));
+      ((void **) ret)[-1] = ptr;
+    }
+
+  if (obj->templ)
+    memcpy (ret, obj->templ, obj->size);
+  else
+    memset (ret, 0, obj->size);
+
+  return ret;
+}
+
+void *
+__emutls_get_address (struct __emutls_object *obj)
+{
+  if (! __gthread_active_p ())
+    {
+      if (__builtin_expect (obj->loc.ptr == NULL, 0))
+       obj->loc.ptr = emutls_alloc (obj);
+      return obj->loc.ptr;
+    }
+
+#ifndef __GTHREADS
+  abort ();
+#else
+  pointer offset = obj->loc.offset;
+
+  if (__builtin_expect (offset == 0, 0))
+    {
+      static __gthread_once_t once = __GTHREAD_ONCE_INIT;
+      __gthread_once (&once, emutls_init);
+      __gthread_mutex_lock (&emutls_mutex);
+      offset = obj->loc.offset;
+      if (offset == 0)
+       {
+         offset = ++emutls_size;
+         obj->loc.offset = offset;
+       }
+      __gthread_mutex_unlock (&emutls_mutex);
+    }
+
+  struct __emutls_array *arr = __gthread_getspecific (emutls_key);
+  if (__builtin_expect (arr == NULL, 0))
+    {
+      pointer size = offset + 32;
+      arr = calloc (size + 1, sizeof (void *));
+      if (arr == NULL)
+       abort ();
+      arr->size = size;
+      __gthread_setspecific (emutls_key, (void *) arr);
+    }
+  else if (__builtin_expect (offset > arr->size, 0))
+    {
+      pointer orig_size = arr->size;
+      pointer size = orig_size * 2;
+      if (offset > size)
+       size = offset + 32;
+      arr = realloc (arr, (size + 1) * sizeof (void *));
+      if (arr == NULL)
+       abort ();
+      arr->size = size;
+      memset (arr->data + orig_size, 0,
+             (size - orig_size) * sizeof (void *));
+      __gthread_setspecific (emutls_key, (void *) arr);
+    }
+
+  void *ret = arr->data[offset - 1];
+  if (__builtin_expect (ret == NULL, 0))
+    {
+      ret = emutls_alloc (obj);
+      arr->data[offset - 1] = ret;
+    }
+  return ret;
+#endif
+}
+
+void
+__emutls_register_common (struct __emutls_object *obj,
+                         word size, word align, void *templ)
+{
+  if (obj->size < size)
+    {
+      obj->size = size;
+      obj->templ = NULL;
+    }
+  if (obj->align < align)
+    obj->align = align;
+  if (templ && size == obj->size)
+    obj->templ = templ;
+}
diff --git a/libgcc/unwind-c.c b/libgcc/unwind-c.c
new file mode 100644 (file)
index 0000000..86b9f55
--- /dev/null
@@ -0,0 +1,229 @@
+/* Supporting functions for C exception handling.
+   Copyright (C) 2002, 2003, 2009 Free Software Foundation, Inc.
+   Contributed by Aldy Hernandez <aldy@quesejoda.com>.
+   Shamelessly stolen from the Java front end.
+
+This file is part of GCC.
+
+GCC 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 3, or (at your option) any later
+version.
+
+GCC 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.
+
+Under Section 7 of GPL version 3, you are granted additional
+permissions described in the GCC Runtime Library Exception, version
+3.1, as published by the Free Software Foundation.
+
+You should have received a copy of the GNU General Public License and
+a copy of the GCC Runtime Library Exception along with this program;
+see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+<http://www.gnu.org/licenses/>.  */
+
+#include "tconfig.h"
+#include "tsystem.h"
+#include "unwind.h"
+#define NO_SIZE_OF_ENCODED_VALUE
+#include "unwind-pe.h"
+
+typedef struct
+{
+  _Unwind_Ptr Start;
+  _Unwind_Ptr LPStart;
+  _Unwind_Ptr ttype_base;
+  const unsigned char *TType;
+  const unsigned char *action_table;
+  unsigned char ttype_encoding;
+  unsigned char call_site_encoding;
+} lsda_header_info;
+
+static const unsigned char *
+parse_lsda_header (struct _Unwind_Context *context, const unsigned char *p,
+                  lsda_header_info *info)
+{
+  _uleb128_t tmp;
+  unsigned char lpstart_encoding;
+
+  info->Start = (context ? _Unwind_GetRegionStart (context) : 0);
+
+  /* Find @LPStart, the base to which landing pad offsets are relative.  */
+  lpstart_encoding = *p++;
+  if (lpstart_encoding != DW_EH_PE_omit)
+    p = read_encoded_value (context, lpstart_encoding, p, &info->LPStart);
+  else
+    info->LPStart = info->Start;
+
+  /* Find @TType, the base of the handler and exception spec type data.  */
+  info->ttype_encoding = *p++;
+  if (info->ttype_encoding != DW_EH_PE_omit)
+    {
+      p = read_uleb128 (p, &tmp);
+      info->TType = p + tmp;
+    }
+  else
+    info->TType = 0;
+
+  /* The encoding and length of the call-site table; the action table
+     immediately follows.  */
+  info->call_site_encoding = *p++;
+  p = read_uleb128 (p, &tmp);
+  info->action_table = p + tmp;
+
+  return p;
+}
+
+#ifdef __ARM_EABI_UNWINDER__
+/* ARM EABI personality routines must also unwind the stack.  */
+#define CONTINUE_UNWINDING \
+  do                                                           \
+    {                                                          \
+      if (__gnu_unwind_frame (ue_header, context) != _URC_OK)  \
+       return _URC_FAILURE;                                    \
+      return _URC_CONTINUE_UNWIND;                             \
+    }                                                          \
+  while (0)
+#else
+#define CONTINUE_UNWINDING return _URC_CONTINUE_UNWIND
+#endif
+
+#ifdef __USING_SJLJ_EXCEPTIONS__
+#define PERSONALITY_FUNCTION    __gcc_personality_sj0
+#define __builtin_eh_return_data_regno(x) x
+#else
+#define PERSONALITY_FUNCTION    __gcc_personality_v0
+#endif
+
+#ifdef __ARM_EABI_UNWINDER__
+_Unwind_Reason_Code
+PERSONALITY_FUNCTION (_Unwind_State, struct _Unwind_Exception *,
+                     struct _Unwind_Context *);
+
+_Unwind_Reason_Code
+PERSONALITY_FUNCTION (_Unwind_State state,
+                     struct _Unwind_Exception * ue_header,
+                     struct _Unwind_Context * context)
+#else
+_Unwind_Reason_Code
+PERSONALITY_FUNCTION (int, _Unwind_Action, _Unwind_Exception_Class,
+                     struct _Unwind_Exception *, struct _Unwind_Context *);
+
+_Unwind_Reason_Code
+PERSONALITY_FUNCTION (int version,
+                     _Unwind_Action actions,
+                     _Unwind_Exception_Class exception_class ATTRIBUTE_UNUSED,
+                     struct _Unwind_Exception *ue_header,
+                     struct _Unwind_Context *context)
+#endif
+{
+  lsda_header_info info;
+  const unsigned char *language_specific_data, *p;
+  _Unwind_Ptr landing_pad, ip;
+  int ip_before_insn = 0;
+
+#ifdef __ARM_EABI_UNWINDER__
+  if ((state & _US_ACTION_MASK) != _US_UNWIND_FRAME_STARTING)
+    CONTINUE_UNWINDING;
+
+  /* The dwarf unwinder assumes the context structure holds things like the
+     function and LSDA pointers.  The ARM implementation caches these in
+     the exception header (UCB).  To avoid rewriting everything we make the
+     virtual IP register point at the UCB.  */
+  ip = (_Unwind_Ptr) ue_header;
+  _Unwind_SetGR (context, 12, ip);
+#else
+  if (version != 1)
+    return _URC_FATAL_PHASE1_ERROR;
+
+  /* Currently we only support cleanups for C.  */
+  if ((actions & _UA_CLEANUP_PHASE) == 0)
+    CONTINUE_UNWINDING;
+#endif
+
+  language_specific_data = (const unsigned char *)
+    _Unwind_GetLanguageSpecificData (context);
+
+  /* If no LSDA, then there are no handlers or cleanups.  */
+  if (! language_specific_data)
+    CONTINUE_UNWINDING;
+
+  /* Parse the LSDA header.  */
+  p = parse_lsda_header (context, language_specific_data, &info);
+#ifdef HAVE_GETIPINFO
+  ip = _Unwind_GetIPInfo (context, &ip_before_insn);
+#else
+  ip = _Unwind_GetIP (context);
+#endif
+  if (! ip_before_insn)
+    --ip;
+  landing_pad = 0;
+
+#ifdef __USING_SJLJ_EXCEPTIONS__
+  /* The given "IP" is an index into the call-site table, with two
+     exceptions -- -1 means no-action, and 0 means terminate.  But
+     since we're using uleb128 values, we've not got random access
+     to the array.  */
+  if ((int) ip <= 0)
+    return _URC_CONTINUE_UNWIND;
+  else
+    {
+      _uleb128_t cs_lp, cs_action;
+      do
+       {
+         p = read_uleb128 (p, &cs_lp);
+         p = read_uleb128 (p, &cs_action);
+       }
+      while (--ip);
+
+      /* Can never have null landing pad for sjlj -- that would have
+        been indicated by a -1 call site index.  */
+      landing_pad = (_Unwind_Ptr)cs_lp + 1;
+      goto found_something;
+    }
+#else
+  /* Search the call-site table for the action associated with this IP.  */
+  while (p < info.action_table)
+    {
+      _Unwind_Ptr cs_start, cs_len, cs_lp;
+      _uleb128_t cs_action;
+
+      /* Note that all call-site encodings are "absolute" displacements.  */
+      p = read_encoded_value (0, info.call_site_encoding, p, &cs_start);
+      p = read_encoded_value (0, info.call_site_encoding, p, &cs_len);
+      p = read_encoded_value (0, info.call_site_encoding, p, &cs_lp);
+      p = read_uleb128 (p, &cs_action);
+
+      /* The table is sorted, so if we've passed the ip, stop.  */
+      if (ip < info.Start + cs_start)
+       p = info.action_table;
+      else if (ip < info.Start + cs_start + cs_len)
+       {
+         if (cs_lp)
+           landing_pad = info.LPStart + cs_lp;
+         goto found_something;
+       }
+    }
+#endif
+
+  /* IP is not in table.  No associated cleanups.  */
+  /* ??? This is where C++ calls std::terminate to catch throw
+     from a destructor.  */
+  CONTINUE_UNWINDING;
+
+ found_something:
+  if (landing_pad == 0)
+    {
+      /* IP is present, but has a null landing pad.
+        No handler to be run.  */
+      CONTINUE_UNWINDING;
+    }
+
+  _Unwind_SetGR (context, __builtin_eh_return_data_regno (0),
+                (_Unwind_Ptr) ue_header);
+  _Unwind_SetGR (context, __builtin_eh_return_data_regno (1), 0);
+  _Unwind_SetIP (context, landing_pad);
+  return _URC_INSTALL_CONTEXT;
+}
diff --git a/libgcc/unwind-compat.c b/libgcc/unwind-compat.c
new file mode 100644 (file)
index 0000000..5b41f24
--- /dev/null
@@ -0,0 +1,210 @@
+/* Backward compatibility unwind routines.
+   Copyright (C) 2004, 2005, 2006, 2009
+   Free Software Foundation, Inc.
+
+   This file is part of GCC.
+
+   GCC 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 3, or (at your option)
+   any later version.
+
+   GCC 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.
+
+   Under Section 7 of GPL version 3, you are granted additional
+   permissions described in the GCC Runtime Library Exception, version
+   3.1, as published by the Free Software Foundation.
+
+   You should have received a copy of the GNU General Public License and
+   a copy of the GCC Runtime Library Exception along with this program;
+   see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#if defined (USE_GAS_SYMVER) && defined (USE_LIBUNWIND_EXCEPTIONS)
+#include "tconfig.h"
+#include "tsystem.h"
+#include "unwind.h"
+#include "unwind-dw2-fde.h"
+#include "unwind-compat.h"
+
+extern _Unwind_Reason_Code __libunwind_Unwind_Backtrace
+  (_Unwind_Trace_Fn, void *);
+
+_Unwind_Reason_Code LIBGCC2_UNWIND_ATTRIBUTE
+_Unwind_Backtrace (_Unwind_Trace_Fn trace, void *trace_argument)
+{
+  return __libunwind_Unwind_Backtrace (trace, trace_argument);
+}
+symver (_Unwind_Backtrace, GCC_3.3);
+
+extern void __libunwind_Unwind_DeleteException
+  (struct _Unwind_Exception *);
+
+void
+_Unwind_DeleteException (struct _Unwind_Exception *exc)
+{
+  return __libunwind_Unwind_DeleteException (exc);
+}
+symver (_Unwind_DeleteException, GCC_3.0);
+
+extern void * __libunwind_Unwind_FindEnclosingFunction (void *);
+
+void *
+_Unwind_FindEnclosingFunction (void *pc)
+{
+  return __libunwind_Unwind_FindEnclosingFunction (pc);
+}
+symver (_Unwind_FindEnclosingFunction, GCC_3.3);
+
+extern _Unwind_Reason_Code __libunwind_Unwind_ForcedUnwind
+  (struct _Unwind_Exception *, _Unwind_Stop_Fn, void *);
+
+_Unwind_Reason_Code LIBGCC2_UNWIND_ATTRIBUTE
+_Unwind_ForcedUnwind (struct _Unwind_Exception *exc,
+                     _Unwind_Stop_Fn stop, void * stop_argument)
+{
+  return __libunwind_Unwind_ForcedUnwind (exc, stop, stop_argument);
+}
+symver (_Unwind_ForcedUnwind, GCC_3.0);
+
+extern _Unwind_Word __libunwind_Unwind_GetCFA
+  (struct _Unwind_Context *);
+
+_Unwind_Word
+_Unwind_GetCFA (struct _Unwind_Context *context)
+{
+  return __libunwind_Unwind_GetCFA (context);
+}
+symver (_Unwind_GetCFA, GCC_3.3);
+
+#ifdef __ia64__
+extern _Unwind_Word __libunwind_Unwind_GetBSP
+  (struct _Unwind_Context *);
+
+_Unwind_Word
+_Unwind_GetBSP (struct _Unwind_Context * context)
+{
+  return __libunwind_Unwind_GetBSP (context);
+}
+symver (_Unwind_GetBSP, GCC_3.3.2);
+#else
+extern _Unwind_Ptr __libunwind_Unwind_GetDataRelBase
+  (struct _Unwind_Context *);
+
+_Unwind_Ptr
+_Unwind_GetDataRelBase (struct _Unwind_Context *context)
+{
+  return __libunwind_Unwind_GetDataRelBase (context);
+}
+symver (_Unwind_GetDataRelBase, GCC_3.0);
+
+extern _Unwind_Ptr __libunwind_Unwind_GetTextRelBase
+  (struct _Unwind_Context *);
+
+_Unwind_Ptr
+_Unwind_GetTextRelBase (struct _Unwind_Context *context)
+{
+  return __libunwind_Unwind_GetTextRelBase (context);
+}
+symver (_Unwind_GetTextRelBase, GCC_3.0);
+#endif
+
+extern _Unwind_Word __libunwind_Unwind_GetGR
+  (struct _Unwind_Context *, int );
+
+_Unwind_Word
+_Unwind_GetGR (struct _Unwind_Context *context, int index)
+{
+  return __libunwind_Unwind_GetGR (context, index);
+}
+symver (_Unwind_GetGR, GCC_3.0);
+
+extern _Unwind_Ptr __libunwind_Unwind_GetIP (struct _Unwind_Context *);
+
+_Unwind_Ptr
+_Unwind_GetIP (struct _Unwind_Context *context)
+{
+  return __libunwind_Unwind_GetIP (context);
+}
+symver (_Unwind_GetIP, GCC_3.0);
+
+_Unwind_Ptr
+_Unwind_GetIPInfo (struct _Unwind_Context *context, int *ip_before_insn)
+{
+  *ip_before_insn = 0;
+  return __libunwind_Unwind_GetIP (context);
+}
+
+extern void *__libunwind_Unwind_GetLanguageSpecificData
+  (struct _Unwind_Context *);
+
+void *
+_Unwind_GetLanguageSpecificData (struct _Unwind_Context *context)
+{
+  return __libunwind_Unwind_GetLanguageSpecificData (context);
+}
+symver (_Unwind_GetLanguageSpecificData, GCC_3.0);
+
+extern _Unwind_Ptr __libunwind_Unwind_GetRegionStart
+  (struct _Unwind_Context *);
+
+_Unwind_Ptr
+_Unwind_GetRegionStart (struct _Unwind_Context *context)
+{
+  return __libunwind_Unwind_GetRegionStart (context);
+}
+symver (_Unwind_GetRegionStart, GCC_3.0);
+
+extern _Unwind_Reason_Code __libunwind_Unwind_RaiseException
+  (struct _Unwind_Exception *);
+
+_Unwind_Reason_Code LIBGCC2_UNWIND_ATTRIBUTE
+_Unwind_RaiseException(struct _Unwind_Exception *exc)
+{
+  return __libunwind_Unwind_RaiseException (exc);
+}
+symver (_Unwind_RaiseException, GCC_3.0);
+
+extern void __libunwind_Unwind_Resume (struct _Unwind_Exception *);
+
+void LIBGCC2_UNWIND_ATTRIBUTE
+_Unwind_Resume (struct _Unwind_Exception *exc)
+{
+  __libunwind_Unwind_Resume (exc);
+}
+symver (_Unwind_Resume, GCC_3.0);
+
+extern _Unwind_Reason_Code __libunwind_Unwind_Resume_or_Rethrow
+   (struct _Unwind_Exception *);
+
+_Unwind_Reason_Code LIBGCC2_UNWIND_ATTRIBUTE
+_Unwind_Resume_or_Rethrow (struct _Unwind_Exception *exc)
+{
+  return __libunwind_Unwind_Resume_or_Rethrow (exc);
+}
+symver (_Unwind_Resume_or_Rethrow, GCC_3.3);
+
+extern void __libunwind_Unwind_SetGR
+  (struct _Unwind_Context *, int, _Unwind_Word);
+
+void
+_Unwind_SetGR (struct _Unwind_Context *context, int index,
+              _Unwind_Word val)
+{
+  __libunwind_Unwind_SetGR (context, index, val);
+}
+symver (_Unwind_SetGR, GCC_3.0);
+
+extern void __libunwind_Unwind_SetIP
+  (struct _Unwind_Context *, _Unwind_Ptr);
+
+void
+_Unwind_SetIP (struct _Unwind_Context *context, _Unwind_Ptr val)
+{
+  return __libunwind_Unwind_SetIP (context, val);
+}
+symver (_Unwind_SetIP, GCC_3.0);
+#endif
diff --git a/libgcc/unwind-compat.h b/libgcc/unwind-compat.h
new file mode 100644 (file)
index 0000000..24c8de1
--- /dev/null
@@ -0,0 +1,30 @@
+/* Backward compatibility unwind routines.
+   Copyright (C) 2004, 2009
+   Free Software Foundation, Inc.
+
+   This file is part of GCC.
+
+   GCC 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 3, or (at your option)
+   any later version.
+
+   GCC 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.
+
+   Under Section 7 of GPL version 3, you are granted additional
+   permissions described in the GCC Runtime Library Exception, version
+   3.1, as published by the Free Software Foundation.
+
+   You should have received a copy of the GNU General Public License and
+   a copy of the GCC Runtime Library Exception along with this program;
+   see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#define symver(name, version) \
+  __asm__ (".symver " #name"," #name "@" #version)
+
+#define alias(name) \
+  __typeof(name) __libunwind##name __attribute__ ((alias (#name)))
diff --git a/libgcc/unwind-dw2-fde-compat.c b/libgcc/unwind-dw2-fde-compat.c
new file mode 100644 (file)
index 0000000..f305a55
--- /dev/null
@@ -0,0 +1,43 @@
+/* Backward compatibility unwind routines.
+   Copyright (C) 2004, 2005, 2009
+   Free Software Foundation, Inc.
+
+   This file is part of GCC.
+
+   GCC 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 3, or (at your option)
+   any later version.
+
+   GCC 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.
+
+   Under Section 7 of GPL version 3, you are granted additional
+   permissions described in the GCC Runtime Library Exception, version
+   3.1, as published by the Free Software Foundation.
+
+   You should have received a copy of the GNU General Public License and
+   a copy of the GCC Runtime Library Exception along with this program;
+   see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#if defined (USE_GAS_SYMVER) && defined (USE_LIBUNWIND_EXCEPTIONS)
+#include "tconfig.h"
+#include "tsystem.h"
+#include "unwind.h"
+#include "unwind-dw2-fde.h"
+#include "unwind-compat.h"
+
+extern const fde * __libunwind__Unwind_Find_FDE
+  (void *, struct dwarf_eh_bases *);
+
+const fde *
+_Unwind_Find_FDE (void *pc, struct dwarf_eh_bases *bases)
+{
+  __libunwind__Unwind_Find_FDE (pc, bases);
+}
+
+symver (_Unwind_Find_FDE, GCC_3.0);
+#endif
diff --git a/libgcc/unwind-dw2-fde-dip.c b/libgcc/unwind-dw2-fde-dip.c
new file mode 100644 (file)
index 0000000..d8e3c0e
--- /dev/null
@@ -0,0 +1,470 @@
+/* Copyright (C) 2001, 2002, 2003, 2004, 2005, 2009, 2010
+   Free Software Foundation, Inc.
+   Contributed by Jakub Jelinek <jakub@redhat.com>.
+
+   This file is part of GCC.
+
+   GCC 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 3, or (at your option)
+   any later version.
+
+   GCC 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.
+
+   Under Section 7 of GPL version 3, you are granted additional
+   permissions described in the GCC Runtime Library Exception, version
+   3.1, as published by the Free Software Foundation.
+
+   You should have received a copy of the GNU General Public License and
+   a copy of the GCC Runtime Library Exception along with this program;
+   see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+   <http://www.gnu.org/licenses/>.  */
+
+/* Locate the FDE entry for a given address, using PT_GNU_EH_FRAME ELF
+   segment and dl_iterate_phdr to avoid register/deregister calls at
+   DSO load/unload.  */
+
+#ifndef _GNU_SOURCE
+#define _GNU_SOURCE 1
+#endif
+
+#include "tconfig.h"
+#include "tsystem.h"
+#ifndef inhibit_libc
+#include <elf.h>               /* Get DT_CONFIG.  */
+#endif
+#include "coretypes.h"
+#include "tm.h"
+#include "dwarf2.h"
+#include "unwind.h"
+#define NO_BASE_OF_ENCODED_VALUE
+#include "unwind-pe.h"
+#include "unwind-dw2-fde.h"
+#include "unwind-compat.h"
+#include "gthr.h"
+
+#if !defined(inhibit_libc) && defined(HAVE_LD_EH_FRAME_HDR) \
+    && (__GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ > 2) \
+       || (__GLIBC__ == 2 && __GLIBC_MINOR__ == 2 && defined(DT_CONFIG)))
+# define USE_PT_GNU_EH_FRAME
+#endif
+
+#if !defined(inhibit_libc) && defined(HAVE_LD_EH_FRAME_HDR) \
+    && defined(__FreeBSD__) && __FreeBSD__ >= 7
+# define ElfW __ElfN
+# define USE_PT_GNU_EH_FRAME
+#endif
+
+#if !defined(inhibit_libc) && defined(HAVE_LD_EH_FRAME_HDR) \
+    && defined(TARGET_DL_ITERATE_PHDR) \
+    && defined(__sun__) && defined(__svr4__)
+# define USE_PT_GNU_EH_FRAME
+#endif
+
+#if defined(USE_PT_GNU_EH_FRAME)
+
+#include <link.h>
+
+#ifndef __RELOC_POINTER
+# define __RELOC_POINTER(ptr, base) ((ptr) + (base))
+#endif
+
+static const fde * _Unwind_Find_registered_FDE (void *pc, struct dwarf_eh_bases *bases);
+
+#define _Unwind_Find_FDE _Unwind_Find_registered_FDE
+#include "unwind-dw2-fde.c"
+#undef _Unwind_Find_FDE
+
+#ifndef PT_GNU_EH_FRAME
+#define PT_GNU_EH_FRAME (PT_LOOS + 0x474e550)
+#endif
+
+struct unw_eh_callback_data
+{
+  _Unwind_Ptr pc;
+  void *tbase;
+  void *dbase;
+  void *func;
+  const fde *ret;
+  int check_cache;
+};
+
+struct unw_eh_frame_hdr
+{
+  unsigned char version;
+  unsigned char eh_frame_ptr_enc;
+  unsigned char fde_count_enc;
+  unsigned char table_enc;
+};
+
+#define FRAME_HDR_CACHE_SIZE 8
+
+static struct frame_hdr_cache_element
+{
+  _Unwind_Ptr pc_low;
+  _Unwind_Ptr pc_high;
+  _Unwind_Ptr load_base;
+  const ElfW(Phdr) *p_eh_frame_hdr;
+  const ElfW(Phdr) *p_dynamic;
+  struct frame_hdr_cache_element *link;
+} frame_hdr_cache[FRAME_HDR_CACHE_SIZE];
+
+static struct frame_hdr_cache_element *frame_hdr_cache_head;
+
+/* Like base_of_encoded_value, but take the base from a struct
+   unw_eh_callback_data instead of an _Unwind_Context.  */
+
+static _Unwind_Ptr
+base_from_cb_data (unsigned char encoding, struct unw_eh_callback_data *data)
+{
+  if (encoding == DW_EH_PE_omit)
+    return 0;
+
+  switch (encoding & 0x70)
+    {
+    case DW_EH_PE_absptr:
+    case DW_EH_PE_pcrel:
+    case DW_EH_PE_aligned:
+      return 0;
+
+    case DW_EH_PE_textrel:
+      return (_Unwind_Ptr) data->tbase;
+    case DW_EH_PE_datarel:
+      return (_Unwind_Ptr) data->dbase;
+    default:
+      gcc_unreachable ();
+    }
+}
+
+static int
+_Unwind_IteratePhdrCallback (struct dl_phdr_info *info, size_t size, void *ptr)
+{
+  struct unw_eh_callback_data *data = (struct unw_eh_callback_data *) ptr;
+  const ElfW(Phdr) *phdr, *p_eh_frame_hdr, *p_dynamic;
+  long n, match;
+#ifdef __FRV_FDPIC__
+  struct elf32_fdpic_loadaddr load_base;
+#else
+  _Unwind_Ptr load_base;
+#endif
+  const unsigned char *p;
+  const struct unw_eh_frame_hdr *hdr;
+  _Unwind_Ptr eh_frame;
+  struct object ob;
+  _Unwind_Ptr pc_low = 0, pc_high = 0;
+
+  struct ext_dl_phdr_info
+    {
+      ElfW(Addr) dlpi_addr;
+      const char *dlpi_name;
+      const ElfW(Phdr) *dlpi_phdr;
+      ElfW(Half) dlpi_phnum;
+      unsigned long long int dlpi_adds;
+      unsigned long long int dlpi_subs;
+    };
+
+  match = 0;
+  phdr = info->dlpi_phdr;
+  load_base = info->dlpi_addr;
+  p_eh_frame_hdr = NULL;
+  p_dynamic = NULL;
+
+  struct frame_hdr_cache_element *prev_cache_entry = NULL,
+    *last_cache_entry = NULL;
+
+  if (data->check_cache && size >= sizeof (struct ext_dl_phdr_info))
+    {
+      static unsigned long long adds = -1ULL, subs;
+      struct ext_dl_phdr_info *einfo = (struct ext_dl_phdr_info *) info;
+
+      /* We use a least recently used cache replacement policy.  Also,
+        the most recently used cache entries are placed at the head
+        of the search chain.  */
+
+      if (einfo->dlpi_adds == adds && einfo->dlpi_subs == subs)
+       {
+         /* Find data->pc in shared library cache.
+            Set load_base, p_eh_frame_hdr and p_dynamic
+            plus match from the cache and goto
+            "Read .eh_frame_hdr header." below.  */
+
+         struct frame_hdr_cache_element *cache_entry;
+
+         for (cache_entry = frame_hdr_cache_head;
+              cache_entry;
+              cache_entry = cache_entry->link)
+           {
+             if (data->pc >= cache_entry->pc_low
+                 && data->pc < cache_entry->pc_high)
+               {
+                 load_base = cache_entry->load_base;
+                 p_eh_frame_hdr = cache_entry->p_eh_frame_hdr;
+                 p_dynamic = cache_entry->p_dynamic;
+
+                 /* And move the entry we're using to the head.  */
+                 if (cache_entry != frame_hdr_cache_head)
+                   {
+                     prev_cache_entry->link = cache_entry->link;
+                     cache_entry->link = frame_hdr_cache_head;
+                     frame_hdr_cache_head = cache_entry;
+                   }
+                 goto found;
+               }
+
+             last_cache_entry = cache_entry;
+             /* Exit early if we found an unused entry.  */
+             if ((cache_entry->pc_low | cache_entry->pc_high) == 0)
+               break;
+             if (cache_entry->link != NULL)
+               prev_cache_entry = cache_entry;
+           }
+       }
+      else
+       {
+         adds = einfo->dlpi_adds;
+         subs = einfo->dlpi_subs;
+         /* Initialize the cache.  Create a chain of cache entries,
+            with the final one terminated by a NULL link.  */
+         int i;
+         for (i = 0; i < FRAME_HDR_CACHE_SIZE; i++)
+           {
+             frame_hdr_cache[i].pc_low = 0;
+             frame_hdr_cache[i].pc_high = 0;
+             frame_hdr_cache[i].link = &frame_hdr_cache[i+1];
+           }
+         frame_hdr_cache[i-1].link = NULL;
+         frame_hdr_cache_head = &frame_hdr_cache[0];
+         data->check_cache = 0;
+       }
+    }
+
+  /* Make sure struct dl_phdr_info is at least as big as we need.  */
+  if (size < offsetof (struct dl_phdr_info, dlpi_phnum)
+            + sizeof (info->dlpi_phnum))
+    return -1;
+
+  /* See if PC falls into one of the loaded segments.  Find the eh_frame
+     segment at the same time.  */
+  for (n = info->dlpi_phnum; --n >= 0; phdr++)
+    {
+      if (phdr->p_type == PT_LOAD)
+       {
+         _Unwind_Ptr vaddr = (_Unwind_Ptr)
+           __RELOC_POINTER (phdr->p_vaddr, load_base);
+         if (data->pc >= vaddr && data->pc < vaddr + phdr->p_memsz)
+           {
+             match = 1;
+             pc_low = vaddr;
+             pc_high =  vaddr + phdr->p_memsz;
+           }
+       }
+      else if (phdr->p_type == PT_GNU_EH_FRAME)
+       p_eh_frame_hdr = phdr;
+#ifdef PT_SUNW_UNWIND
+      /* Sun ld emits PT_SUNW_UNWIND .eh_frame_hdr sections instead of
+        PT_SUNW_EH_FRAME/PT_GNU_EH_FRAME, so accept them as well.  */
+      else if (phdr->p_type == PT_SUNW_UNWIND)
+       p_eh_frame_hdr = phdr;
+#endif
+      else if (phdr->p_type == PT_DYNAMIC)
+       p_dynamic = phdr;
+    }
+
+  if (!match)
+    return 0;
+
+  if (size >= sizeof (struct ext_dl_phdr_info))
+    {
+      /* Move the cache entry we're about to overwrite to the head of
+        the list.  If either last_cache_entry or prev_cache_entry are
+        NULL, that cache entry is already at the head.  */
+      if (last_cache_entry != NULL && prev_cache_entry != NULL)
+       {
+         prev_cache_entry->link = last_cache_entry->link;
+         last_cache_entry->link = frame_hdr_cache_head;
+         frame_hdr_cache_head = last_cache_entry;
+       }
+
+      frame_hdr_cache_head->load_base = load_base;
+      frame_hdr_cache_head->p_eh_frame_hdr = p_eh_frame_hdr;
+      frame_hdr_cache_head->p_dynamic = p_dynamic;
+      frame_hdr_cache_head->pc_low = pc_low;
+      frame_hdr_cache_head->pc_high = pc_high;
+    }
+
+ found:
+
+  if (!p_eh_frame_hdr)
+    return 0;
+
+  /* Read .eh_frame_hdr header.  */
+  hdr = (const struct unw_eh_frame_hdr *)
+    __RELOC_POINTER (p_eh_frame_hdr->p_vaddr, load_base);
+  if (hdr->version != 1)
+    return 1;
+
+#ifdef CRT_GET_RFIB_DATA
+# ifdef __i386__
+  data->dbase = NULL;
+  if (p_dynamic)
+    {
+      /* For dynamically linked executables and shared libraries,
+        DT_PLTGOT is the gp value for that object.  */
+      ElfW(Dyn) *dyn = (ElfW(Dyn) *)
+       __RELOC_POINTER (p_dynamic->p_vaddr, load_base);
+      for (; dyn->d_tag != DT_NULL ; dyn++)
+       if (dyn->d_tag == DT_PLTGOT)
+         {
+           data->dbase = (void *) dyn->d_un.d_ptr;
+#if defined __linux__
+           /* On IA-32 Linux, _DYNAMIC is writable and GLIBC has
+              relocated it.  */
+#elif defined __sun__ && defined __svr4__
+           /* On Solaris 2/x86, we need to do this ourselves.  */
+           data->dbase += load_base;
+#endif
+           break;
+         }
+    }
+# elif defined __FRV_FDPIC__ && defined __linux__
+  data->dbase = load_base.got_value;
+# elif defined __x86_64__ && defined __sun__ && defined __svr4__
+  /* While CRT_GET_RFIB_DATA is also defined for 64-bit Solaris 10+/x86, it
+     doesn't apply since it uses DW_EH_PE_pcrel encoding.  */
+# else
+#  error What is DW_EH_PE_datarel base on this platform?
+# endif
+#endif
+
+  p = read_encoded_value_with_base (hdr->eh_frame_ptr_enc,
+                                   base_from_cb_data (hdr->eh_frame_ptr_enc,
+                                                      data),
+                                   (const unsigned char *) (hdr + 1),
+                                   &eh_frame);
+
+  /* We require here specific table encoding to speed things up.
+     Also, DW_EH_PE_datarel here means using PT_GNU_EH_FRAME start
+     as base, not the processor specific DW_EH_PE_datarel.  */
+  if (hdr->fde_count_enc != DW_EH_PE_omit
+      && hdr->table_enc == (DW_EH_PE_datarel | DW_EH_PE_sdata4))
+    {
+      _Unwind_Ptr fde_count;
+
+      p = read_encoded_value_with_base (hdr->fde_count_enc,
+                                       base_from_cb_data (hdr->fde_count_enc,
+                                                          data),
+                                       p, &fde_count);
+      /* Shouldn't happen.  */
+      if (fde_count == 0)
+       return 1;
+      if ((((_Unwind_Ptr) p) & 3) == 0)
+       {
+         struct fde_table {
+           signed initial_loc __attribute__ ((mode (SI)));
+           signed fde __attribute__ ((mode (SI)));
+         };
+         const struct fde_table *table = (const struct fde_table *) p;
+         size_t lo, hi, mid;
+         _Unwind_Ptr data_base = (_Unwind_Ptr) hdr;
+         fde *f;
+         unsigned int f_enc, f_enc_size;
+         _Unwind_Ptr range;
+
+         mid = fde_count - 1;
+         if (data->pc < table[0].initial_loc + data_base)
+           return 1;
+         else if (data->pc < table[mid].initial_loc + data_base)
+           {
+             lo = 0;
+             hi = mid;
+
+             while (lo < hi)
+               {
+                 mid = (lo + hi) / 2;
+                 if (data->pc < table[mid].initial_loc + data_base)
+                   hi = mid;
+                 else if (data->pc >= table[mid + 1].initial_loc + data_base)
+                   lo = mid + 1;
+                 else
+                   break;
+               }
+
+             gcc_assert (lo < hi);
+           }
+
+         f = (fde *) (table[mid].fde + data_base);
+         f_enc = get_fde_encoding (f);
+         f_enc_size = size_of_encoded_value (f_enc);
+         read_encoded_value_with_base (f_enc & 0x0f, 0,
+                                       &f->pc_begin[f_enc_size], &range);
+         if (data->pc < table[mid].initial_loc + data_base + range)
+           data->ret = f;
+         data->func = (void *) (table[mid].initial_loc + data_base);
+         return 1;
+       }
+    }
+
+  /* We have no sorted search table, so need to go the slow way.
+     As soon as GLIBC will provide API so to notify that a library has been
+     removed, we could cache this (and thus use search_object).  */
+  ob.pc_begin = NULL;
+  ob.tbase = data->tbase;
+  ob.dbase = data->dbase;
+  ob.u.single = (fde *) eh_frame;
+  ob.s.i = 0;
+  ob.s.b.mixed_encoding = 1;  /* Need to assume worst case.  */
+  data->ret = linear_search_fdes (&ob, (fde *) eh_frame, (void *) data->pc);
+  if (data->ret != NULL)
+    {
+      _Unwind_Ptr func;
+      unsigned int encoding = get_fde_encoding (data->ret);
+
+      read_encoded_value_with_base (encoding,
+                                   base_from_cb_data (encoding, data),
+                                   data->ret->pc_begin, &func);
+      data->func = (void *) func;
+    }
+  return 1;
+}
+
+const fde *
+_Unwind_Find_FDE (void *pc, struct dwarf_eh_bases *bases)
+{
+  struct unw_eh_callback_data data;
+  const fde *ret;
+
+  ret = _Unwind_Find_registered_FDE (pc, bases);
+  if (ret != NULL)
+    return ret;
+
+  data.pc = (_Unwind_Ptr) pc;
+  data.tbase = NULL;
+  data.dbase = NULL;
+  data.func = NULL;
+  data.ret = NULL;
+  data.check_cache = 1;
+
+  if (dl_iterate_phdr (_Unwind_IteratePhdrCallback, &data) < 0)
+    return NULL;
+
+  if (data.ret)
+    {
+      bases->tbase = data.tbase;
+      bases->dbase = data.dbase;
+      bases->func = data.func;
+    }
+  return data.ret;
+}
+
+#else
+/* Prevent multiple include of header files.  */
+#define _Unwind_Find_FDE _Unwind_Find_FDE
+#include "unwind-dw2-fde.c"
+#endif
+
+#if defined (USE_GAS_SYMVER) && defined (SHARED) && defined (USE_LIBUNWIND_EXCEPTIONS)
+alias (_Unwind_Find_FDE);
+#endif
diff --git a/libgcc/unwind-dw2-fde.c b/libgcc/unwind-dw2-fde.c
new file mode 100644 (file)
index 0000000..93d4271
--- /dev/null
@@ -0,0 +1,1054 @@
+/* Subroutines needed for unwinding stack frames for exception handling.  */
+/* Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2008,
+   2009, 2010  Free Software Foundation, Inc.
+   Contributed by Jason Merrill <jason@cygnus.com>.
+
+This file is part of GCC.
+
+GCC 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 3, or (at your option) any later
+version.
+
+GCC 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.
+
+Under Section 7 of GPL version 3, you are granted additional
+permissions described in the GCC Runtime Library Exception, version
+3.1, as published by the Free Software Foundation.
+
+You should have received a copy of the GNU General Public License and
+a copy of the GCC Runtime Library Exception along with this program;
+see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+<http://www.gnu.org/licenses/>.  */
+
+#ifndef _Unwind_Find_FDE
+#include "tconfig.h"
+#include "tsystem.h"
+#include "coretypes.h"
+#include "tm.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
+   its 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 __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
+
+/* Called from crtbegin.o to register the unwind info for an object.  */
+
+void
+__register_frame_info_bases (const void *begin, struct object *ob,
+                            void *tbase, void *dbase)
+{
+  /* If .eh_frame is empty, don't register at all.  */
+  if ((const uword *) begin == 0 || *(const uword *) begin == 0)
+    return;
+
+  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;
+#ifdef DWARF2_OBJECT_END_PTR_EXTENSION
+  ob->fde_end = NULL;
+#endif
+
+  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 (const void *begin, struct object *ob)
+{
+  __register_frame_info_bases (begin, ob, 0, 0);
+}
+
+void
+__register_frame (void *begin)
+{
+  struct object *ob;
+
+  /* If .eh_frame is empty, don't register at all.  */
+  if (*(uword *) begin == 0)
+    return;
+
+  ob = 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 = 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 die.
+
+   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 (const void *begin)
+{
+  struct object **p;
+  struct object *ob = 0;
+
+  /* If .eh_frame is empty, we haven't registered.  */
+  if ((const uword *) begin == 0 || *(const uword *) begin == 0)
+    return ob;
+
+  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;
+         }
+      }
+
+ out:
+  __gthread_mutex_unlock (&object_mutex);
+  gcc_assert (ob);
+  return (void *) ob;
+}
+
+void *
+__deregister_frame_info (const void *begin)
+{
+  return __deregister_frame_info_bases (begin);
+}
+
+void
+__deregister_frame (void *begin)
+{
+  /* If .eh_frame is empty, we haven't registered.  */
+  if (*(uword *) begin != 0)
+    free (__deregister_frame_info (begin));
+}
+
+\f
+/* 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;
+    default:
+      gcc_unreachable ();
+    }
+}
+
+/* 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 (const struct dwarf_cie *cie)
+{
+  const unsigned char *aug, *p;
+  _Unwind_Ptr dummy;
+  _uleb128_t utmp;
+  _sleb128_t stmp;
+
+  aug = cie->augmentation;
+  p = aug + strlen ((const char *)aug) + 1; /* Skip the augmentation string.  */
+  if (__builtin_expect (cie->version >= 4, 0))
+    {
+      if (p[0] != sizeof (void *) || p[1] != 0)
+       return DW_EH_PE_omit;           /* We are not prepared to handle unexpected
+                                          address sizes or segment selectors.  */
+      p += 2;                          /* Skip address size and segment size.  */
+    }
+
+  if (aug[0] != 'z')
+    return DW_EH_PE_absptr;
+
+  p = read_uleb128 (p, &utmp);         /* Skip code alignment.  */
+  p = read_sleb128 (p, &stmp);         /* Skip data alignment.  */
+  if (cie->version == 1)               /* Skip return address column.  */
+    p++;
+  else
+    p = read_uleb128 (p, &utmp);
+
+  aug++;                               /* Skip 'z' */
+  p = read_uleb128 (p, &utmp);         /* 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 (const struct dwarf_fde *f)
+{
+  return get_cie_encoding (get_cie (f));
+}
+
+\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 int
+fde_unencoded_compare (struct object *ob __attribute__((unused)),
+                      const fde *x, const fde *y)
+{
+  _Unwind_Ptr x_ptr, y_ptr;
+  memcpy (&x_ptr, x->pc_begin, sizeof (_Unwind_Ptr));
+  memcpy (&y_ptr, y->pc_begin, sizeof (_Unwind_Ptr));
+
+  if (x_ptr > y_ptr)
+    return 1;
+  if (x_ptr < y_ptr)
+    return -1;
+  return 0;
+}
+
+static int
+fde_single_encoding_compare (struct object *ob, const fde *x, const 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);
+
+  if (x_ptr > y_ptr)
+    return 1;
+  if (x_ptr < y_ptr)
+    return -1;
+  return 0;
+}
+
+static int
+fde_mixed_encoding_compare (struct object *ob, const fde *x, const 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);
+
+  if (x_ptr > y_ptr)
+    return 1;
+  if (x_ptr < y_ptr)
+    return -1;
+  return 0;
+}
+
+typedef int (*fde_compare_t) (struct object *, const fde *, const 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 (const fde *) * count;
+  if ((accu->linear = malloc (size)))
+    {
+      accu->linear->count = 0;
+      if ((accu->erratic = malloc (size)))
+       accu->erratic->count = 0;
+      return 1;
+    }
+  else
+    return 0;
+}
+
+static inline void
+fde_insert (struct fde_accumulator *accu, const 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 const fde *marker;
+  size_t count = linear->count;
+  const fde *const *chain_end = &marker;
+  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.  */
+  gcc_assert (sizeof (const fde *) == sizeof (const fde **));
+
+  for (i = 0; i < count; i++)
+    {
+      const fde *const *probe;
+
+      for (probe = chain_end;
+          probe != &marker && fde_compare (ob, linear->array[i], *probe) < 0;
+          probe = chain_end)
+       {
+         chain_end = (const fde *const*) erratic->array[probe - linear->array];
+         erratic->array[probe - linear->array] = NULL;
+       }
+      erratic->array[i] = (const 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;
+}
+
+#define SWAP(x,y) do { const fde * tmp = x; x = y; y = tmp; } while (0)
+
+/* Convert a semi-heap to a heap.  A semi-heap is a heap except possibly
+   for the first (root) node; push it down to its rightful place.  */
+
+static void
+frame_downheap (struct object *ob, fde_compare_t fde_compare, const fde **a,
+               int lo, int hi)
+{
+  int i, j;
+
+  for (i = lo, j = 2*i+1;
+       j < hi;
+       j = 2*i+1)
+    {
+      if (j+1 < hi && fde_compare (ob, a[j], a[j+1]) < 0)
+       ++j;
+
+      if (fde_compare (ob, a[i], a[j]) < 0)
+       {
+         SWAP (a[i], a[j]);
+         i = j;
+       }
+      else
+       break;
+    }
+}
+
+/* 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.  */
+  const 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].  */
+  size_t n = erratic->count;
+  int m;
+
+  /* Expand our heap incrementally from the end of the array, heapifying
+     each resulting semi-heap as we go.  After each step, a[m] is the top
+     of a heap.  */
+  for (m = n/2-1; m >= 0; --m)
+    frame_downheap (ob, fde_compare, a, m, n);
+
+  /* Shrink our heap incrementally from the end of the array, first
+     swapping out the largest element a[0] and then re-heapifying the
+     resulting semi-heap.  After each step, a[0..m) is a heap.  */
+  for (m = n-1; m >= 1; --m)
+    {
+      SWAP (a[0], a[m]);
+      frame_downheap (ob, fde_compare, a, 0, m);
+    }
+#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;
+  const 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;
+
+  gcc_assert (!accu->linear || accu->linear->count == count);
+
+  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);
+      gcc_assert (accu->linear->count + accu->erratic->count == count);
+      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);
+    }
+}
+
+\f
+/* 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, const fde *this_fde)
+{
+  const struct dwarf_cie *last_cie = 0;
+  size_t count = 0;
+  int encoding = DW_EH_PE_absptr;
+  _Unwind_Ptr base = 0;
+
+  for (; ! last_fde (ob, this_fde); this_fde = next_fde (this_fde))
+    {
+      const 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);
+         if (encoding == DW_EH_PE_omit)
+           return -1;
+         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 = (((_Unwind_Ptr) 1) << (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, const fde *this_fde)
+{
+  const struct dwarf_cie *last_cie = 0;
+  int encoding = ob->s.b.encoding;
+  _Unwind_Ptr base = base_from_object (ob->s.b.encoding, ob);
+
+  for (; ! last_fde (ob, this_fde); this_fde = next_fde (this_fde))
+    {
+      const 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)
+       {
+         _Unwind_Ptr ptr;
+         memcpy (&ptr, this_fde->pc_begin, sizeof (_Unwind_Ptr));
+         if (ptr == 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 = (((_Unwind_Ptr) 1) << (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)
+           {
+             size_t cur_count = classify_object_over_fdes (ob, *p);
+             if (cur_count == (size_t) -1)
+               goto unhandled_fdes;
+             count += cur_count;
+           }
+       }
+      else
+       {
+         count = classify_object_over_fdes (ob, ob->u.single);
+         if (count == (size_t) -1)
+           {
+             static const fde terminator;
+           unhandled_fdes:
+             ob->s.i = 0;
+             ob->s.b.encoding = DW_EH_PE_omit;
+             ob->u.single = &terminator;
+             return;
+           }
+       }
+
+      /* 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 const fde *
+linear_search_fdes (struct object *ob, const fde *this_fde, void *pc)
+{
+  const struct dwarf_cie *last_cie = 0;
+  int encoding = ob->s.b.encoding;
+  _Unwind_Ptr base = base_from_object (ob->s.b.encoding, ob);
+
+  for (; ! last_fde (ob, this_fde); this_fde = next_fde (this_fde))
+    {
+      const 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)
+       {
+         const _Unwind_Ptr *pc_array = (const _Unwind_Ptr *) this_fde->pc_begin;
+         pc_begin = pc_array[0];
+         pc_range = pc_array[1];
+         if (pc_begin == 0)
+           continue;
+       }
+      else
+       {
+         _Unwind_Ptr mask;
+         const unsigned 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 = (((_Unwind_Ptr) 1) << (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 const 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;
+      const fde *const f = vec->array[i];
+      void *pc_begin;
+      uaddr pc_range;
+      memcpy (&pc_begin, (const void * const *) f->pc_begin, sizeof (void *));
+      memcpy (&pc_range, (const uaddr *) f->pc_begin + 1, sizeof (uaddr));
+
+      if (pc < pc_begin)
+       hi = i;
+      else if (pc >= pc_begin + pc_range)
+       lo = i + 1;
+      else
+       return f;
+    }
+
+  return NULL;
+}
+
+static inline const 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;
+      const fde *f = vec->array[i];
+      _Unwind_Ptr pc_begin, pc_range;
+      const unsigned 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 const 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;
+      const fde *f = vec->array[i];
+      _Unwind_Ptr pc_begin, pc_range;
+      const unsigned 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 const 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 laborious linear search, cos we've no memory.  */
+      if (ob->s.b.from_array)
+       {
+         fde **p;
+         for (p = ob->u.array; *p ; p++)
+           {
+             const fde *f = linear_search_fdes (ob, *p, pc);
+             if (f)
+               return f;
+           }
+         return NULL;
+       }
+      else
+       return linear_search_fdes (ob, ob->u.single, pc);
+    }
+}
+
+const fde *
+_Unwind_Find_FDE (void *pc, struct dwarf_eh_bases *bases)
+{
+  struct object *ob;
+  const 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 descending, 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;
+      _Unwind_Ptr func;
+
+      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, &func);
+      bases->func = (void *) func;
+    }
+
+  return f;
+}
diff --git a/libgcc/unwind-dw2-fde.h b/libgcc/unwind-dw2-fde.h
new file mode 100644 (file)
index 0000000..6d7a8de
--- /dev/null
@@ -0,0 +1,183 @@
+/* Subroutines needed for unwinding stack frames for exception handling.  */
+/* Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2004, 2009
+   Free Software Foundation, Inc.
+   Contributed by Jason Merrill <jason@cygnus.com>.
+
+This file is part of GCC.
+
+GCC 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 3, or (at your option) any later
+version.
+
+GCC 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.
+
+Under Section 7 of GPL version 3, you are granted additional
+permissions described in the GCC Runtime Library Exception, version
+3.1, as published by the Free Software Foundation.
+
+You should have received a copy of the GNU General Public License and
+a copy of the GCC Runtime Library Exception along with this program;
+see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+<http://www.gnu.org/licenses/>.  */
+
+#ifndef GCC_UNWIND_DW2_FDE_H
+#define GCC_UNWIND_DW2_FDE_H
+
+#ifndef HIDE_EXPORTS
+#pragma GCC visibility push(default)
+#endif
+
+struct fde_vector
+{
+  const void *orig_data;
+  size_t count;
+  const struct dwarf_fde *array[];
+};
+
+struct object
+{
+  void *pc_begin;
+  void *tbase;
+  void *dbase;
+  union {
+    const 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;
+
+#ifdef DWARF2_OBJECT_END_PTR_EXTENSION
+  char *fde_end;
+#endif
+
+  struct object *next;
+};
+
+/* 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 (const void *, struct object *,
+                                        void *, void *);
+extern void __register_frame_info (const 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 (const void *);
+extern void *__deregister_frame_info_bases (const void *);
+extern void __deregister_frame (void *);
+
+\f
+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 specification, 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[];
+} __attribute__ ((packed, aligned (__alignof__ (void *))));
+
+/* The first few fields of an FDE.  */
+struct dwarf_fde
+{
+  uword length;
+  sword CIE_delta;
+  unsigned char pc_begin[];
+} __attribute__ ((packed, aligned (__alignof__ (void *))));
+
+typedef struct dwarf_fde fde;
+
+/* Locate the CIE for a given FDE.  */
+
+static inline const struct dwarf_cie *
+get_cie (const struct dwarf_fde *f)
+{
+  return (const void *)&f->CIE_delta - f->CIE_delta;
+}
+
+static inline const fde *
+next_fde (const fde *f)
+{
+  return (const fde *) ((const char *) f + f->length + sizeof (f->length));
+}
+
+extern const fde * _Unwind_Find_FDE (void *, struct dwarf_eh_bases *);
+
+static inline int
+last_fde (struct object *obj __attribute__ ((__unused__)), const fde *f)
+{
+#ifdef DWARF2_OBJECT_END_PTR_EXTENSION
+  return (char *)f == obj->fde_end || f->length == 0;
+#else
+  return f->length == 0;
+#endif
+}
+
+#ifndef HIDE_EXPORTS
+#pragma GCC visibility pop
+#endif
+
+#endif /* unwind-dw2-fde.h */
diff --git a/libgcc/unwind-dw2.c b/libgcc/unwind-dw2.c
new file mode 100644 (file)
index 0000000..19da299
--- /dev/null
@@ -0,0 +1,1611 @@
+/* DWARF2 exception handling and frame unwind runtime interface routines.
+   Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006,
+   2008, 2009, 2010, 2011  Free Software Foundation, Inc.
+
+   This file is part of GCC.
+
+   GCC 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 3, or (at your option)
+   any later version.
+
+   GCC 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.
+
+   Under Section 7 of GPL version 3, you are granted additional
+   permissions described in the GCC Runtime Library Exception, version
+   3.1, as published by the Free Software Foundation.
+
+   You should have received a copy of the GNU General Public License and
+   a copy of the GCC Runtime Library Exception along with this program;
+   see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include "tconfig.h"
+#include "tsystem.h"
+#include "coretypes.h"
+#include "tm.h"
+#include "dwarf2.h"
+#include "unwind.h"
+#ifdef __USING_SJLJ_EXCEPTIONS__
+# define NO_SIZE_OF_ENCODED_VALUE
+#endif
+#include "unwind-pe.h"
+#include "unwind-dw2-fde.h"
+#include "gthr.h"
+#include "unwind-dw2.h"
+
+#ifdef HAVE_SYS_SDT_H
+#include <sys/sdt.h>
+#endif
+
+#ifndef __USING_SJLJ_EXCEPTIONS__
+
+#ifndef STACK_GROWS_DOWNWARD
+#define STACK_GROWS_DOWNWARD 0
+#else
+#undef STACK_GROWS_DOWNWARD
+#define STACK_GROWS_DOWNWARD 1
+#endif
+
+/* Dwarf frame registers used for pre gcc 3.0 compiled glibc.  */
+#ifndef PRE_GCC3_DWARF_FRAME_REGISTERS
+#define PRE_GCC3_DWARF_FRAME_REGISTERS DWARF_FRAME_REGISTERS
+#endif
+
+#ifndef DWARF_REG_TO_UNWIND_COLUMN
+#define DWARF_REG_TO_UNWIND_COLUMN(REGNO) (REGNO)
+#endif
+
+/* This is the register and unwind state for a particular frame.  This
+   provides the information necessary to unwind up past a frame and return
+   to its caller.  */
+struct _Unwind_Context
+{
+  void *reg[DWARF_FRAME_REGISTERS+1];
+  void *cfa;
+  void *ra;
+  void *lsda;
+  struct dwarf_eh_bases bases;
+  /* Signal frame context.  */
+#define SIGNAL_FRAME_BIT ((~(_Unwind_Word) 0 >> 1) + 1)
+  /* Context which has version/args_size/by_value fields.  */
+#define EXTENDED_CONTEXT_BIT ((~(_Unwind_Word) 0 >> 2) + 1)
+  _Unwind_Word flags;
+  /* 0 for now, can be increased when further fields are added to
+     struct _Unwind_Context.  */
+  _Unwind_Word version;
+  _Unwind_Word args_size;
+  char by_value[DWARF_FRAME_REGISTERS+1];
+};
+
+/* Byte size of every register managed by these routines.  */
+static unsigned char dwarf_reg_size_table[DWARF_FRAME_REGISTERS+1];
+
+\f
+/* 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 void uw_update_context (struct _Unwind_Context *, _Unwind_FrameState *);
+static _Unwind_Reason_Code uw_frame_state_for (struct _Unwind_Context *,
+                                              _Unwind_FrameState *);
+
+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; }
+\f
+static inline _Unwind_Word
+_Unwind_IsSignalFrame (struct _Unwind_Context *context)
+{
+  return (context->flags & SIGNAL_FRAME_BIT) ? 1 : 0;
+}
+
+static inline void
+_Unwind_SetSignalFrame (struct _Unwind_Context *context, int val)
+{
+  if (val)
+    context->flags |= SIGNAL_FRAME_BIT;
+  else
+    context->flags &= ~SIGNAL_FRAME_BIT;
+}
+
+static inline _Unwind_Word
+_Unwind_IsExtendedContext (struct _Unwind_Context *context)
+{
+  return context->flags & EXTENDED_CONTEXT_BIT;
+}
+\f
+/* Get the value of register INDEX as saved in CONTEXT.  */
+
+inline _Unwind_Word
+_Unwind_GetGR (struct _Unwind_Context *context, int index)
+{
+  int size;
+  void *ptr;
+
+#ifdef DWARF_ZERO_REG
+  if (index == DWARF_ZERO_REG)
+    return 0;
+#endif
+
+  index = DWARF_REG_TO_UNWIND_COLUMN (index);
+  gcc_assert (index < (int) sizeof(dwarf_reg_size_table));
+  size = dwarf_reg_size_table[index];
+  ptr = context->reg[index];
+
+  if (_Unwind_IsExtendedContext (context) && context->by_value[index])
+    return (_Unwind_Word) (_Unwind_Internal_Ptr) ptr;
+
+  /* This will segfault if the register hasn't been saved.  */
+  if (size == sizeof(_Unwind_Ptr))
+    return * (_Unwind_Ptr *) ptr;
+  else
+    {
+      gcc_assert (size == sizeof(_Unwind_Word));
+      return * (_Unwind_Word *) ptr;
+    }
+}
+
+static inline void *
+_Unwind_GetPtr (struct _Unwind_Context *context, int index)
+{
+  return (void *)(_Unwind_Ptr) _Unwind_GetGR (context, index);
+}
+
+/* Get the value of the CFA as saved in CONTEXT.  */
+
+_Unwind_Word
+_Unwind_GetCFA (struct _Unwind_Context *context)
+{
+  return (_Unwind_Ptr) context->cfa;
+}
+
+/* Overwrite the saved value for register INDEX in CONTEXT with VAL.  */
+
+inline void
+_Unwind_SetGR (struct _Unwind_Context *context, int index, _Unwind_Word val)
+{
+  int size;
+  void *ptr;
+
+  index = DWARF_REG_TO_UNWIND_COLUMN (index);
+  gcc_assert (index < (int) sizeof(dwarf_reg_size_table));
+  size = dwarf_reg_size_table[index];
+
+  if (_Unwind_IsExtendedContext (context) && context->by_value[index])
+    {
+      context->reg[index] = (void *) (_Unwind_Internal_Ptr) val;
+      return;
+    }
+
+  ptr = context->reg[index];
+
+  if (size == sizeof(_Unwind_Ptr))
+    * (_Unwind_Ptr *) ptr = val;
+  else
+    {
+      gcc_assert (size == sizeof(_Unwind_Word));
+      * (_Unwind_Word *) ptr = val;
+    }
+}
+
+/* Get the pointer to a register INDEX as saved in CONTEXT.  */
+
+static inline void *
+_Unwind_GetGRPtr (struct _Unwind_Context *context, int index)
+{
+  index = DWARF_REG_TO_UNWIND_COLUMN (index);
+  if (_Unwind_IsExtendedContext (context) && context->by_value[index])
+    return &context->reg[index];
+  return context->reg[index];
+}
+
+/* Set the pointer to a register INDEX as saved in CONTEXT.  */
+
+static inline void
+_Unwind_SetGRPtr (struct _Unwind_Context *context, int index, void *p)
+{
+  index = DWARF_REG_TO_UNWIND_COLUMN (index);
+  if (_Unwind_IsExtendedContext (context))
+    context->by_value[index] = 0;
+  context->reg[index] = p;
+}
+
+/* Overwrite the saved value for register INDEX in CONTEXT with VAL.  */
+
+static inline void
+_Unwind_SetGRValue (struct _Unwind_Context *context, int index,
+                   _Unwind_Word val)
+{
+  index = DWARF_REG_TO_UNWIND_COLUMN (index);
+  gcc_assert (index < (int) sizeof(dwarf_reg_size_table));
+  gcc_assert (dwarf_reg_size_table[index] == sizeof (_Unwind_Ptr));
+
+  context->by_value[index] = 1;
+  context->reg[index] = (void *) (_Unwind_Internal_Ptr) val;
+}
+
+/* Return nonzero if register INDEX is stored by value rather than
+   by reference.  */
+
+static inline int
+_Unwind_GRByValue (struct _Unwind_Context *context, int index)
+{
+  index = DWARF_REG_TO_UNWIND_COLUMN (index);
+  return context->by_value[index];
+}
+
+/* Retrieve the return address for CONTEXT.  */
+
+inline _Unwind_Ptr
+_Unwind_GetIP (struct _Unwind_Context *context)
+{
+  return (_Unwind_Ptr) context->ra;
+}
+
+/* Retrieve the return address and flag whether that IP is before
+   or after first not yet fully executed instruction.  */
+
+inline _Unwind_Ptr
+_Unwind_GetIPInfo (struct _Unwind_Context *context, int *ip_before_insn)
+{
+  *ip_before_insn = _Unwind_IsSignalFrame (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;
+}
+
+void *
+_Unwind_FindEnclosingFunction (void *pc)
+{
+  struct dwarf_eh_bases bases;
+  const struct dwarf_fde *fde = _Unwind_Find_FDE (pc-1, &bases);
+  if (fde)
+    return bases.func;
+  else
+    return NULL;
+}
+
+#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
+
+#include "md-unwind-support.h"
+\f
+/* 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 (const struct dwarf_cie *cie, struct _Unwind_Context *context,
+                 _Unwind_FrameState *fs)
+{
+  const unsigned char *aug = cie->augmentation;
+  const unsigned char *p = aug + strlen ((const char *)aug) + 1;
+  const unsigned char *ret = NULL;
+  _uleb128_t utmp;
+  _sleb128_t stmp;
+
+  /* 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;
+    }
+
+  /* After the augmentation resp. pointer for "eh" augmentation
+     follows for CIE version >= 4 address size byte and
+     segment size byte.  */
+  if (__builtin_expect (cie->version >= 4, 0))
+    {
+      if (p[0] != sizeof (void *) || p[1] != 0)
+       return NULL;
+      p += 2;
+    }
+  /* Immediately following this are the code and
+     data alignment and return address column.  */
+  p = read_uleb128 (p, &utmp);
+  fs->code_align = (_Unwind_Word)utmp;
+  p = read_sleb128 (p, &stmp);
+  fs->data_align = (_Unwind_Sword)stmp;
+  if (cie->version == 1)
+    fs->retaddr_column = *p++;
+  else
+    {
+      p = read_uleb128 (p, &utmp);
+      fs->retaddr_column = (_Unwind_Word)utmp;
+    }
+  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, &utmp);
+      ret = p + utmp;
+
+      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')
+       {
+         _Unwind_Ptr personality;
+
+         p = read_encoded_value (context, *p, p + 1, &personality);
+         fs->personality = (_Unwind_Personality_Fn) personality;
+         aug += 1;
+       }
+
+      /* "S" indicates a signal frame.  */
+      else if (aug[0] == 'S')
+       {
+         fs->signal_frame = 1;
+         aug += 1;
+       }
+
+      /* Otherwise we have an unknown augmentation string.
+        Bail unless we saw a 'z' prefix.  */
+      else
+       return ret;
+    }
+
+  return ret ? ret : p;
+}
+
+
+/* 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;
+      _uleb128_t reg, utmp;
+      _sleb128_t offset, stmp;
+
+      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_GNU_encoded_addr:
+         {
+           _Unwind_Ptr presult;
+           op_ptr = read_encoded_value (context, *op_ptr, op_ptr+1, &presult);
+           result = presult;
+         }
+         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, &utmp);
+         result = (_Unwind_Word)utmp;
+         break;
+       case DW_OP_consts:
+         op_ptr = read_sleb128 (op_ptr, &stmp);
+         result = (_Unwind_Sword)stmp;
+         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, &reg);
+         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, &offset);
+         result = _Unwind_GetGR (context, op - DW_OP_breg0) + offset;
+         break;
+       case DW_OP_bregx:
+         op_ptr = read_uleb128 (op_ptr, &reg);
+         op_ptr = read_sleb128 (op_ptr, &offset);
+         result = _Unwind_GetGR (context, reg) + (_Unwind_Word)offset;
+         break;
+
+       case DW_OP_dup:
+         gcc_assert (stack_elt);
+         result = stack[stack_elt - 1];
+         break;
+
+       case DW_OP_drop:
+         gcc_assert (stack_elt);
+         stack_elt -= 1;
+         goto no_push;
+
+       case DW_OP_pick:
+         offset = *op_ptr++;
+         gcc_assert (offset < stack_elt - 1);
+         result = stack[stack_elt - 1 - offset];
+         break;
+
+       case DW_OP_over:
+         gcc_assert (stack_elt >= 2);
+         result = stack[stack_elt - 2];
+         break;
+
+       case DW_OP_swap:
+         {
+           _Unwind_Word t;
+           gcc_assert (stack_elt >= 2);
+           t = stack[stack_elt - 1];
+           stack[stack_elt - 1] = stack[stack_elt - 2];
+           stack[stack_elt - 2] = t;
+           goto no_push;
+         }
+
+       case DW_OP_rot:
+         {
+           _Unwind_Word t1, t2, t3;
+
+           gcc_assert (stack_elt >= 3);
+           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.  */
+         gcc_assert (stack_elt);
+         stack_elt -= 1;
+
+         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:
+                   gcc_unreachable ();
+                 }
+             }
+             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, &utmp);
+             result += (_Unwind_Word)utmp;
+             break;
+
+           default:
+             gcc_unreachable ();
+           }
+         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_shl:
+       case DW_OP_shr:
+       case DW_OP_shra:
+       case DW_OP_xor:
+       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;
+           gcc_assert (stack_elt >= 2);
+           stack_elt -= 2;
+
+           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 = second % 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) second <= (_Unwind_Sword) first;
+               break;
+             case DW_OP_ge:
+               result = (_Unwind_Sword) second >= (_Unwind_Sword) first;
+               break;
+             case DW_OP_eq:
+               result = (_Unwind_Sword) second == (_Unwind_Sword) first;
+               break;
+             case DW_OP_lt:
+               result = (_Unwind_Sword) second < (_Unwind_Sword) first;
+               break;
+             case DW_OP_gt:
+               result = (_Unwind_Sword) second > (_Unwind_Sword) first;
+               break;
+             case DW_OP_ne:
+               result = (_Unwind_Sword) second != (_Unwind_Sword) first;
+               break;
+
+             default:
+               gcc_unreachable ();
+             }
+         }
+         break;
+
+       case DW_OP_skip:
+         offset = read_2s (op_ptr);
+         op_ptr += 2;
+         op_ptr += offset;
+         goto no_push;
+
+       case DW_OP_bra:
+         gcc_assert (stack_elt);
+         stack_elt -= 1;
+
+         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:
+         gcc_unreachable ();
+       }
+
+      /* Most things push a result value.  */
+      gcc_assert ((size_t) stack_elt < sizeof(stack)/sizeof(*stack));
+      stack[stack_elt++] = result;
+    no_push:;
+    }
+
+  /* We were executing this program to get a value.  It should be
+     at top of stack.  */
+  gcc_assert (stack_elt);
+  stack_elt -= 1;
+  return stack[stack_elt];
+}
+
+
+/* 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;
+
+  /* The comparison with the return address uses < rather than <= because
+     we are only interested in the effects of code before the call; for a
+     noreturn function, the return address may point to unrelated code with
+     a different stack configuration that we are not interested in.  We
+     assume that the call itself is unwind info-neutral; if not, or if
+     there are delay instructions that adjust the stack, these must be
+     reflected at the point immediately before the call insn.
+     In signal frames, return address is after last completed instruction,
+     so we add 1 to return address to make the comparison <=.  */
+  while (insn_ptr < insn_end
+        && fs->pc < context->ra + _Unwind_IsSignalFrame (context))
+    {
+      unsigned char insn = *insn_ptr++;
+      _uleb128_t reg, utmp;
+      _sleb128_t offset, stmp;
+
+      if ((insn & 0xc0) == DW_CFA_advance_loc)
+       fs->pc += (insn & 0x3f) * fs->code_align;
+      else if ((insn & 0xc0) == DW_CFA_offset)
+       {
+         reg = insn & 0x3f;
+         insn_ptr = read_uleb128 (insn_ptr, &utmp);
+         offset = (_Unwind_Sword) utmp * fs->data_align;
+         fs->regs.reg[DWARF_REG_TO_UNWIND_COLUMN (reg)].how
+           = REG_SAVED_OFFSET;
+         fs->regs.reg[DWARF_REG_TO_UNWIND_COLUMN (reg)].loc.offset = offset;
+       }
+      else if ((insn & 0xc0) == DW_CFA_restore)
+       {
+         reg = insn & 0x3f;
+         fs->regs.reg[DWARF_REG_TO_UNWIND_COLUMN (reg)].how = REG_UNSAVED;
+       }
+      else switch (insn)
+       {
+       case DW_CFA_set_loc:
+         {
+           _Unwind_Ptr pc;
+
+           insn_ptr = read_encoded_value (context, fs->fde_encoding,
+                                          insn_ptr, &pc);
+           fs->pc = (void *) 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, &reg);
+         insn_ptr = read_uleb128 (insn_ptr, &utmp);
+         offset = (_Unwind_Sword) utmp * fs->data_align;
+         fs->regs.reg[DWARF_REG_TO_UNWIND_COLUMN (reg)].how
+           = REG_SAVED_OFFSET;
+         fs->regs.reg[DWARF_REG_TO_UNWIND_COLUMN (reg)].loc.offset = offset;
+         break;
+
+       case DW_CFA_restore_extended:
+         insn_ptr = read_uleb128 (insn_ptr, &reg);
+         /* FIXME, this is wrong; the CIE might have said that the
+            register was saved somewhere.  */
+         fs->regs.reg[DWARF_REG_TO_UNWIND_COLUMN(reg)].how = REG_UNSAVED;
+         break;
+
+       case DW_CFA_same_value:
+         insn_ptr = read_uleb128 (insn_ptr, &reg);
+         fs->regs.reg[DWARF_REG_TO_UNWIND_COLUMN(reg)].how = REG_UNSAVED;
+         break;
+
+       case DW_CFA_undefined:
+         insn_ptr = read_uleb128 (insn_ptr, &reg);
+         fs->regs.reg[DWARF_REG_TO_UNWIND_COLUMN(reg)].how = REG_UNDEFINED;
+         break;
+
+       case DW_CFA_nop:
+         break;
+
+       case DW_CFA_register:
+         {
+           _uleb128_t reg2;
+           insn_ptr = read_uleb128 (insn_ptr, &reg);
+           insn_ptr = read_uleb128 (insn_ptr, &reg2);
+           fs->regs.reg[DWARF_REG_TO_UNWIND_COLUMN (reg)].how = REG_SAVED_REG;
+           fs->regs.reg[DWARF_REG_TO_UNWIND_COLUMN (reg)].loc.reg =
+             (_Unwind_Word)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, &utmp);
+         fs->regs.cfa_reg = (_Unwind_Word)utmp;
+         insn_ptr = read_uleb128 (insn_ptr, &utmp);
+         fs->regs.cfa_offset = (_Unwind_Word)utmp;
+         fs->regs.cfa_how = CFA_REG_OFFSET;
+         break;
+
+       case DW_CFA_def_cfa_register:
+         insn_ptr = read_uleb128 (insn_ptr, &utmp);
+         fs->regs.cfa_reg = (_Unwind_Word)utmp;
+         fs->regs.cfa_how = CFA_REG_OFFSET;
+         break;
+
+       case DW_CFA_def_cfa_offset:
+         insn_ptr = read_uleb128 (insn_ptr, &utmp);
+         fs->regs.cfa_offset = utmp;
+         /* cfa_how deliberately not set.  */
+         break;
+
+       case DW_CFA_def_cfa_expression:
+         fs->regs.cfa_exp = insn_ptr;
+         fs->regs.cfa_how = CFA_EXP;
+         insn_ptr = read_uleb128 (insn_ptr, &utmp);
+         insn_ptr += utmp;
+         break;
+
+       case DW_CFA_expression:
+         insn_ptr = read_uleb128 (insn_ptr, &reg);
+         fs->regs.reg[DWARF_REG_TO_UNWIND_COLUMN (reg)].how = REG_SAVED_EXP;
+         fs->regs.reg[DWARF_REG_TO_UNWIND_COLUMN (reg)].loc.exp = insn_ptr;
+         insn_ptr = read_uleb128 (insn_ptr, &utmp);
+         insn_ptr += utmp;
+         break;
+
+         /* Dwarf3.  */
+       case DW_CFA_offset_extended_sf:
+         insn_ptr = read_uleb128 (insn_ptr, &reg);
+         insn_ptr = read_sleb128 (insn_ptr, &stmp);
+         offset = stmp * fs->data_align;
+         fs->regs.reg[DWARF_REG_TO_UNWIND_COLUMN (reg)].how
+           = REG_SAVED_OFFSET;
+         fs->regs.reg[DWARF_REG_TO_UNWIND_COLUMN (reg)].loc.offset = offset;
+         break;
+
+       case DW_CFA_def_cfa_sf:
+         insn_ptr = read_uleb128 (insn_ptr, &utmp);
+         fs->regs.cfa_reg = (_Unwind_Word)utmp;
+         insn_ptr = read_sleb128 (insn_ptr, &stmp);
+         fs->regs.cfa_offset = (_Unwind_Sword)stmp;
+         fs->regs.cfa_how = CFA_REG_OFFSET;
+         fs->regs.cfa_offset *= fs->data_align;
+         break;
+
+       case DW_CFA_def_cfa_offset_sf:
+         insn_ptr = read_sleb128 (insn_ptr, &stmp);
+         fs->regs.cfa_offset = (_Unwind_Sword)stmp;
+         fs->regs.cfa_offset *= fs->data_align;
+         /* cfa_how deliberately not set.  */
+         break;
+
+       case DW_CFA_val_offset:
+         insn_ptr = read_uleb128 (insn_ptr, &reg);
+         insn_ptr = read_uleb128 (insn_ptr, &utmp);
+         offset = (_Unwind_Sword) utmp * fs->data_align;
+         fs->regs.reg[DWARF_REG_TO_UNWIND_COLUMN (reg)].how
+           = REG_SAVED_VAL_OFFSET;
+         fs->regs.reg[DWARF_REG_TO_UNWIND_COLUMN (reg)].loc.offset = offset;
+         break;
+
+       case DW_CFA_val_offset_sf:
+         insn_ptr = read_uleb128 (insn_ptr, &reg);
+         insn_ptr = read_sleb128 (insn_ptr, &stmp);
+         offset = stmp * fs->data_align;
+         fs->regs.reg[DWARF_REG_TO_UNWIND_COLUMN (reg)].how
+           = REG_SAVED_VAL_OFFSET;
+         fs->regs.reg[DWARF_REG_TO_UNWIND_COLUMN (reg)].loc.offset = offset;
+         break;
+
+       case DW_CFA_val_expression:
+         insn_ptr = read_uleb128 (insn_ptr, &reg);
+         fs->regs.reg[DWARF_REG_TO_UNWIND_COLUMN (reg)].how
+           = REG_SAVED_VAL_EXP;
+         fs->regs.reg[DWARF_REG_TO_UNWIND_COLUMN (reg)].loc.exp = insn_ptr;
+         insn_ptr = read_uleb128 (insn_ptr, &utmp);
+         insn_ptr += utmp;
+         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, &utmp);
+         context->args_size = (_Unwind_Word)utmp;
+         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, &reg);
+         insn_ptr = read_uleb128 (insn_ptr, &utmp);
+         offset = (_Unwind_Word) utmp * fs->data_align;
+         fs->regs.reg[DWARF_REG_TO_UNWIND_COLUMN (reg)].how
+           = REG_SAVED_OFFSET;
+         fs->regs.reg[DWARF_REG_TO_UNWIND_COLUMN (reg)].loc.offset = -offset;
+         break;
+
+       default:
+         gcc_unreachable ();
+       }
+    }
+}
+\f
+/* Given the _Unwind_Context CONTEXT for a stack frame, look up the FDE for
+   its caller and decode it into FS.  This function also sets the
+   args_size and lsda members of CONTEXT, as they are really information
+   about the caller's frame.  */
+
+static _Unwind_Reason_Code
+uw_frame_state_for (struct _Unwind_Context *context, _Unwind_FrameState *fs)
+{
+  const struct dwarf_fde *fde;
+  const struct dwarf_cie *cie;
+  const unsigned char *aug, *insn, *end;
+
+  memset (fs, 0, sizeof (*fs));
+  context->args_size = 0;
+  context->lsda = 0;
+
+  if (context->ra == 0)
+    return _URC_END_OF_STACK;
+
+  fde = _Unwind_Find_FDE (context->ra + _Unwind_IsSignalFrame (context) - 1,
+                         &context->bases);
+  if (fde == NULL)
+    {
+#ifdef MD_FALLBACK_FRAME_STATE_FOR
+      /* Couldn't find frame unwind info for this function.  Try a
+        target-specific fallback mechanism.  This will necessarily
+        not provide a personality routine or LSDA.  */
+      return MD_FALLBACK_FRAME_STATE_FOR (context, fs);
+#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 = (const unsigned char *) next_fde ((const struct dwarf_fde *) cie);
+  execute_cfa_program (insn, end, context, fs);
+
+  /* Locate augmentation for the fde.  */
+  aug = (const unsigned char *) fde + sizeof (*fde);
+  aug += 2 * size_of_encoded_value (fs->fde_encoding);
+  insn = NULL;
+  if (fs->saw_z)
+    {
+      _uleb128_t i;
+      aug = read_uleb128 (aug, &i);
+      insn = aug + i;
+    }
+  if (fs->lsda_encoding != DW_EH_PE_omit)
+    {
+      _Unwind_Ptr lsda;
+
+      aug = read_encoded_value (context, fs->lsda_encoding, aug, &lsda);
+      context->lsda = (void *) lsda;
+    }
+
+  /* Then the insns in the FDE up to our target PC.  */
+  if (insn == NULL)
+    insn = aug;
+  end = (const unsigned char *) next_fde (fde);
+  execute_cfa_program (insn, end, context, fs);
+
+  return _URC_NO_REASON;
+}
+\f
+typedef struct frame_state
+{
+  void *cfa;
+  void *eh_ptr;
+  long cfa_offset;
+  long args_size;
+  long reg_or_offset[PRE_GCC3_DWARF_FRAME_REGISTERS+1];
+  unsigned short cfa_reg;
+  unsigned short retaddr_column;
+  char saved[PRE_GCC3_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.flags = EXTENDED_CONTEXT_BIT;
+  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.regs.cfa_how == CFA_EXP)
+    return 0;
+
+  for (reg = 0; reg < PRE_GCC3_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.regs.cfa_offset;
+  state_in->cfa_reg = fs.regs.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;
+}
+\f
+typedef union { _Unwind_Ptr ptr; _Unwind_Word word; } _Unwind_SpTmp;
+
+static inline void
+_Unwind_SetSpColumn (struct _Unwind_Context *context, void *cfa,
+                    _Unwind_SpTmp *tmp_sp)
+{
+  int size = dwarf_reg_size_table[__builtin_dwarf_sp_column ()];
+
+  if (size == sizeof(_Unwind_Ptr))
+    tmp_sp->ptr = (_Unwind_Ptr) cfa;
+  else
+    {
+      gcc_assert (size == sizeof(_Unwind_Word));
+      tmp_sp->word = (_Unwind_Ptr) cfa;
+    }
+  _Unwind_SetGRPtr (context, __builtin_dwarf_sp_column (), tmp_sp);
+}
+
+static void
+uw_update_context_1 (struct _Unwind_Context *context, _Unwind_FrameState *fs)
+{
+  struct _Unwind_Context orig_context = *context;
+  void *cfa;
+  long i;
+
+#ifdef EH_RETURN_STACKADJ_RTX
+  /* 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.
+
+     In very special situations (such as unwind info for signal return),
+     there may be location expressions that use the stack pointer as well.
+
+     Do this conditionally for one frame.  This allows the unwind info
+     for one frame to save a copy of the stack pointer from the previous
+     frame, and be able to use much easier CFA mechanisms to do it.
+     Always zap the saved stack pointer value for the next frame; carrying
+     the value over from one frame to another doesn't make sense.  */
+
+  _Unwind_SpTmp tmp_sp;
+
+  if (!_Unwind_GetGRPtr (&orig_context, __builtin_dwarf_sp_column ()))
+    _Unwind_SetSpColumn (&orig_context, context->cfa, &tmp_sp);
+  _Unwind_SetGRPtr (context, __builtin_dwarf_sp_column (), NULL);
+#endif
+
+  /* Compute this frame's CFA.  */
+  switch (fs->regs.cfa_how)
+    {
+    case CFA_REG_OFFSET:
+      cfa = _Unwind_GetPtr (&orig_context, fs->regs.cfa_reg);
+      cfa += fs->regs.cfa_offset;
+      break;
+
+    case CFA_EXP:
+      {
+       const unsigned char *exp = fs->regs.cfa_exp;
+       _uleb128_t len;
+
+       exp = read_uleb128 (exp, &len);
+       cfa = (void *) (_Unwind_Ptr)
+         execute_stack_op (exp, exp + len, &orig_context, 0);
+       break;
+      }
+
+    default:
+      gcc_unreachable ();
+    }
+  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:
+      case REG_UNDEFINED:
+       break;
+
+      case REG_SAVED_OFFSET:
+       _Unwind_SetGRPtr (context, i,
+                         (void *) (cfa + fs->regs.reg[i].loc.offset));
+       break;
+
+      case REG_SAVED_REG:
+       if (_Unwind_GRByValue (&orig_context, fs->regs.reg[i].loc.reg))
+         _Unwind_SetGRValue (context, i,
+                             _Unwind_GetGR (&orig_context,
+                                            fs->regs.reg[i].loc.reg));
+       else
+         _Unwind_SetGRPtr (context, i,
+                           _Unwind_GetGRPtr (&orig_context,
+                                             fs->regs.reg[i].loc.reg));
+       break;
+
+      case REG_SAVED_EXP:
+       {
+         const unsigned char *exp = fs->regs.reg[i].loc.exp;
+         _uleb128_t len;
+         _Unwind_Ptr val;
+
+         exp = read_uleb128 (exp, &len);
+         val = execute_stack_op (exp, exp + len, &orig_context,
+                                 (_Unwind_Ptr) cfa);
+         _Unwind_SetGRPtr (context, i, (void *) val);
+       }
+       break;
+
+      case REG_SAVED_VAL_OFFSET:
+       _Unwind_SetGRValue (context, i,
+                           (_Unwind_Internal_Ptr)
+                           (cfa + fs->regs.reg[i].loc.offset));
+       break;
+
+      case REG_SAVED_VAL_EXP:
+       {
+         const unsigned char *exp = fs->regs.reg[i].loc.exp;
+         _uleb128_t len;
+         _Unwind_Ptr val;
+
+         exp = read_uleb128 (exp, &len);
+         val = execute_stack_op (exp, exp + len, &orig_context,
+                                 (_Unwind_Ptr) cfa);
+         _Unwind_SetGRValue (context, i, val);
+       }
+       break;
+      }
+
+  _Unwind_SetSignalFrame (context, fs->signal_frame);
+
+#ifdef MD_FROB_UPDATE_CONTEXT
+  MD_FROB_UPDATE_CONTEXT (context, fs);
+#endif
+}
+
+/* CONTEXT describes the unwind state for a frame, and FS describes the FDE
+   of its caller.  Update CONTEXT to refer to the caller as well.  Note
+   that the args_size and lsda members are not updated here, but later in
+   uw_frame_state_for.  */
+
+static void
+uw_update_context (struct _Unwind_Context *context, _Unwind_FrameState *fs)
+{
+  uw_update_context_1 (context, fs);
+
+  /* In general this unwinder doesn't make any distinction between
+     undefined and same_value rule.  Call-saved registers are assumed
+     to have same_value rule by default and explicit undefined
+     rule is handled like same_value.  The only exception is
+     DW_CFA_undefined on retaddr_column which is supposed to
+     mark outermost frame in DWARF 3.  */
+  if (fs->regs.reg[DWARF_REG_TO_UNWIND_COLUMN (fs->retaddr_column)].how
+      == REG_UNDEFINED)
+    /* uw_frame_state_for uses context->ra == 0 check to find outermost
+       stack frame.  */
+    context->ra = 0;
+  else
+    /* Compute the return address now, since the return address column
+       can change from frame to frame.  */
+    context->ra = __builtin_extract_return_addr
+      (_Unwind_GetPtr (context, fs->retaddr_column));
+}
+
+static void
+uw_advance_context (struct _Unwind_Context *context, _Unwind_FrameState *fs)
+{
+  uw_update_context (context, fs);
+}
+\f
+/* 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 inline void
+init_dwarf_reg_size_table (void)
+{
+  __builtin_init_dwarf_reg_size_table (dwarf_reg_size_table);
+}
+
+static void __attribute__((noinline))
+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;
+  _Unwind_SpTmp sp_slot;
+  _Unwind_Reason_Code code;
+
+  memset (context, 0, sizeof (struct _Unwind_Context));
+  context->ra = ra;
+  context->flags = EXTENDED_CONTEXT_BIT;
+
+  code = uw_frame_state_for (context, &fs);
+  gcc_assert (code == _URC_NO_REASON);
+
+#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
+
+  /* Force the frame state to use the known cfa value.  */
+  _Unwind_SetSpColumn (context, outer_cfa, &sp_slot);
+  fs.regs.cfa_how = CFA_REG_OFFSET;
+  fs.regs.cfa_reg = __builtin_dwarf_sp_column ();
+  fs.regs.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);
+}
+
+static void _Unwind_DebugHook (void *, void *)
+  __attribute__ ((__noinline__, __used__, __noclone__));
+
+/* This function is called during unwinding.  It is intended as a hook
+   for a debugger to intercept exceptions.  CFA is the CFA of the
+   target frame.  HANDLER is the PC to which control will be
+   transferred.  */
+static void
+_Unwind_DebugHook (void *cfa __attribute__ ((__unused__)),
+                  void *handler __attribute__ ((__unused__)))
+{
+  /* We only want to use stap probes starting with v3.  Earlier
+     versions added too much startup cost.  */
+#if defined (HAVE_SYS_SDT_H) && defined (STAP_PROBE2) && _SDT_NOTE_TYPE >= 3
+  STAP_PROBE2 (libgcc, unwind, cfa, handler);
+#else
+  asm ("");
+#endif
+}
+
+/* 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);       \
+      _Unwind_DebugHook ((TARGET)->cfa, handler);                      \
+      __builtin_eh_return (offset, handler);                           \
+    }                                                                  \
+  while (0)
+
+static long
+uw_install_context_1 (struct _Unwind_Context *current,
+                     struct _Unwind_Context *target)
+{
+  long i;
+  _Unwind_SpTmp sp_slot;
+
+  /* If the target frame does not have a saved stack pointer,
+     then set up the target's CFA.  */
+  if (!_Unwind_GetGRPtr (target, __builtin_dwarf_sp_column ()))
+    _Unwind_SetSpColumn (target, target->cfa, &sp_slot);
+
+  for (i = 0; i < DWARF_FRAME_REGISTERS; ++i)
+    {
+      void *c = current->reg[i];
+      void *t = target->reg[i];
+
+      gcc_assert (current->by_value[i] == 0);
+      if (target->by_value[i] && c)
+       {
+         _Unwind_Word w;
+         _Unwind_Ptr p;
+         if (dwarf_reg_size_table[i] == sizeof (_Unwind_Word))
+           {
+             w = (_Unwind_Internal_Ptr) t;
+             memcpy (c, &w, sizeof (_Unwind_Word));
+           }
+         else
+           {
+             gcc_assert (dwarf_reg_size_table[i] == sizeof (_Unwind_Ptr));
+             p = (_Unwind_Internal_Ptr) t;
+             memcpy (c, &p, sizeof (_Unwind_Ptr));
+           }
+       }
+      else if (t && c && t != c)
+       memcpy (c, t, dwarf_reg_size_table[i]);
+    }
+
+  /* If the current frame doesn't have a saved stack pointer, then we
+     need to rely on EH_RETURN_STACKADJ_RTX to get our target stack
+     pointer value reloaded.  */
+  if (!_Unwind_GetGRPtr (current, __builtin_dwarf_sp_column ()))
+    {
+      void *target_cfa;
+
+      target_cfa = _Unwind_GetPtr (target, __builtin_dwarf_sp_column ());
+
+      /* 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;
+    }
+  return 0;
+}
+
+static inline _Unwind_Ptr
+uw_identify_context (struct _Unwind_Context *context)
+{
+  /* The CFA is not sufficient to disambiguate the context of a function
+     interrupted by a signal before establishing its frame and the context
+     of the signal itself.  */
+  if (STACK_GROWS_DOWNWARD)
+    return _Unwind_GetCFA (context) - _Unwind_IsSignalFrame (context);
+  else
+    return _Unwind_GetCFA (context) + _Unwind_IsSignalFrame (context);
+}
+
+
+#include "unwind.inc"
+
+#if defined (USE_GAS_SYMVER) && defined (SHARED) && defined (USE_LIBUNWIND_EXCEPTIONS)
+alias (_Unwind_Backtrace);
+alias (_Unwind_DeleteException);
+alias (_Unwind_FindEnclosingFunction);
+alias (_Unwind_ForcedUnwind);
+alias (_Unwind_GetDataRelBase);
+alias (_Unwind_GetTextRelBase);
+alias (_Unwind_GetCFA);
+alias (_Unwind_GetGR);
+alias (_Unwind_GetIP);
+alias (_Unwind_GetLanguageSpecificData);
+alias (_Unwind_GetRegionStart);
+alias (_Unwind_RaiseException);
+alias (_Unwind_Resume);
+alias (_Unwind_Resume_or_Rethrow);
+alias (_Unwind_SetGR);
+alias (_Unwind_SetIP);
+#endif
+
+#endif /* !USING_SJLJ_EXCEPTIONS */
diff --git a/libgcc/unwind-dw2.h b/libgcc/unwind-dw2.h
new file mode 100644 (file)
index 0000000..2c558b4
--- /dev/null
@@ -0,0 +1,87 @@
+/* DWARF2 frame unwind data structure.
+   Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2009
+   Free Software Foundation, Inc.
+
+   This file is part of GCC.
+
+   GCC 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 3, or (at your option)
+   any later version.
+
+   GCC 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.
+
+   Under Section 7 of GPL version 3, you are granted additional
+   permissions described in the GCC Runtime Library Exception, version
+   3.1, as published by the Free Software Foundation.
+
+   You should have received a copy of the GNU General Public License and
+   a copy of the GCC Runtime Library Exception along with this program;
+   see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+   <http://www.gnu.org/licenses/>.  */
+
+/* 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
+
+/* 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 {
+       _Unwind_Word reg;
+       _Unwind_Sword offset;
+       const unsigned char *exp;
+      } loc;
+      enum {
+       REG_UNSAVED,
+       REG_SAVED_OFFSET,
+       REG_SAVED_REG,
+       REG_SAVED_EXP,
+       REG_SAVED_VAL_OFFSET,
+       REG_SAVED_VAL_EXP,
+       REG_UNDEFINED
+      } how;
+    } reg[DWARF_FRAME_REGISTERS+1];
+
+    /* Used to implement DW_CFA_remember_state.  */
+    struct frame_state_reg_info *prev;
+
+    /* 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;
+  } regs;
+
+  /* The PC described by the current frame state.  */
+  void *pc;
+
+  /* The information we care about from the CIE/FDE.  */
+  _Unwind_Personality_Fn personality;
+  _Unwind_Sword data_align;
+  _Unwind_Word code_align;
+  _Unwind_Word retaddr_column;
+  unsigned char fde_encoding;
+  unsigned char lsda_encoding;
+  unsigned char saw_z;
+  unsigned char signal_frame;
+  void *eh_ptr;
+} _Unwind_FrameState;
+
diff --git a/libgcc/unwind-generic.h b/libgcc/unwind-generic.h
new file mode 100644 (file)
index 0000000..4ff9017
--- /dev/null
@@ -0,0 +1,276 @@
+/* Exception handling and frame unwind runtime interface routines.
+   Copyright (C) 2001, 2003, 2004, 2006, 2008, 2009 Free Software Foundation, Inc.
+
+   This file is part of GCC.
+
+   GCC 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 3, or (at your option)
+   any later version.
+
+   GCC 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.
+
+   Under Section 7 of GPL version 3, you are granted additional
+   permissions described in the GCC Runtime Library Exception, version
+   3.1, as published by the Free Software Foundation.
+
+   You should have received a copy of the GNU General Public License and
+   a copy of the GCC Runtime Library Exception along with this program;
+   see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+   <http://www.gnu.org/licenses/>.  */
+
+/* This is derived from the C++ ABI for IA-64.  Where we diverge
+   for cross-architecture compatibility are noted with "@@@".  */
+
+#ifndef _UNWIND_H
+#define _UNWIND_H
+
+#ifndef HIDE_EXPORTS
+#pragma GCC visibility push(default)
+#endif
+
+#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__(__unwind_word__)));
+typedef signed _Unwind_Sword __attribute__((__mode__(__unwind_word__)));
+#if defined(__ia64__) && defined(__hpux__)
+typedef unsigned _Unwind_Ptr __attribute__((__mode__(__word__)));
+#else
+typedef unsigned _Unwind_Ptr __attribute__((__mode__(__pointer__)));
+#endif
+typedef unsigned _Unwind_Internal_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
+#define _UA_END_OF_STACK       16
+
+/* The target can override this macro to define any back-end-specific
+   attributes required for the lowest-level stack frame.  */
+#ifndef LIBGCC2_UNWIND_ATTRIBUTE
+#define LIBGCC2_UNWIND_ATTRIBUTE
+#endif
+
+/* 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 LIBGCC2_UNWIND_ATTRIBUTE
+_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 LIBGCC2_UNWIND_ATTRIBUTE
+_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 LIBGCC2_UNWIND_ATTRIBUTE
+_Unwind_Resume (struct _Unwind_Exception *);
+
+/* @@@ Resume propagation of a FORCE_UNWIND exception, or to rethrow
+   a normal exception that was handled.  */
+extern _Unwind_Reason_Code LIBGCC2_UNWIND_ATTRIBUTE
+_Unwind_Resume_or_Rethrow (struct _Unwind_Exception *);
+
+/* @@@ Use unwind data to perform a stack backtrace.  The trace callback
+   is called for every stack frame in the call chain, but no cleanup
+   actions are performed.  */
+typedef _Unwind_Reason_Code (*_Unwind_Trace_Fn)
+     (struct _Unwind_Context *, void *);
+
+extern _Unwind_Reason_Code LIBGCC2_UNWIND_ATTRIBUTE
+_Unwind_Backtrace (_Unwind_Trace_Fn, void *);
+
+/* 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 may be 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 _Unwind_Ptr _Unwind_GetIPInfo (struct _Unwind_Context *, int *);
+extern void _Unwind_SetIP (struct _Unwind_Context *, _Unwind_Ptr);
+
+/* @@@ Retrieve the CFA of the given context.  */
+extern _Unwind_Word _Unwind_GetCFA (struct _Unwind_Context *);
+
+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 LIBGCC2_UNWIND_ATTRIBUTE
+_Unwind_SjLj_RaiseException (struct _Unwind_Exception *);
+extern _Unwind_Reason_Code LIBGCC2_UNWIND_ATTRIBUTE
+_Unwind_SjLj_ForcedUnwind (struct _Unwind_Exception *, _Unwind_Stop_Fn, void *);
+extern void LIBGCC2_UNWIND_ATTRIBUTE
+_Unwind_SjLj_Resume (struct _Unwind_Exception *);
+extern _Unwind_Reason_Code LIBGCC2_UNWIND_ATTRIBUTE
+_Unwind_SjLj_Resume_or_Rethrow (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 __attribute__ ((__unused__)))
+{
+  abort ();
+  return 0;
+}
+
+/* @@@ Retrieve the Backing Store Pointer of the given context.  */
+extern _Unwind_Word _Unwind_GetBSP (struct _Unwind_Context *);
+#else
+extern _Unwind_Ptr _Unwind_GetDataRelBase (struct _Unwind_Context *);
+extern _Unwind_Ptr _Unwind_GetTextRelBase (struct _Unwind_Context *);
+#endif
+
+/* @@@ Given an address, return the entry point of the function that
+   contains it.  */
+extern void * _Unwind_FindEnclosingFunction (void *pc);
+
+#ifndef __SIZEOF_LONG__
+  #error "__SIZEOF_LONG__ macro not defined"
+#endif
+
+#ifndef __SIZEOF_POINTER__
+  #error "__SIZEOF_POINTER__ macro not defined"
+#endif
+
+
+/* leb128 type numbers have a potentially unlimited size.
+   The target of the following definitions of _sleb128_t and _uleb128_t
+   is to have efficient data types large enough to hold the leb128 type
+   numbers used in the unwind code.
+   Mostly these types will simply be defined to long and unsigned long
+   except when a unsigned long data type on the target machine is not
+   capable of storing a pointer.  */
+
+#if __SIZEOF_LONG__ >= __SIZEOF_POINTER__
+  typedef long _sleb128_t;
+  typedef unsigned long _uleb128_t;
+#elif __SIZEOF_LONG_LONG__ >= __SIZEOF_POINTER__
+  typedef long long _sleb128_t;
+  typedef unsigned long long _uleb128_t;
+#else
+# error "What type shall we use for _sleb128_t?"
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#ifndef HIDE_EXPORTS
+#pragma GCC visibility pop
+#endif
+
+#endif /* unwind.h */
diff --git a/libgcc/unwind-pe.h b/libgcc/unwind-pe.h
new file mode 100644 (file)
index 0000000..121f877
--- /dev/null
@@ -0,0 +1,289 @@
+/* Exception handling and frame unwind runtime interface routines.
+   Copyright (C) 2001, 2002, 2003, 2004, 2008, 2009 Free Software Foundation, Inc.
+
+   This file is part of GCC.
+
+   GCC 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 3, or (at your option)
+   any later version.
+
+   GCC 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.
+
+   Under Section 7 of GPL version 3, you are granted additional
+   permissions described in the GCC Runtime Library Exception, version
+   3.1, as published by the Free Software Foundation.
+
+   You should have received a copy of the GNU General Public License and
+   a copy of the GCC Runtime Library Exception along with this program;
+   see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+   <http://www.gnu.org/licenses/>.  */
+
+/* @@@ 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.  */
+
+#ifndef GCC_UNWIND_PE_H
+#define GCC_UNWIND_PE_H
+
+/* 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
+\f
+
+#ifndef NO_SIZE_OF_ENCODED_VALUE
+
+/* 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.  */
+
+static unsigned int
+size_of_encoded_value (unsigned char encoding) __attribute__ ((unused));
+
+static unsigned int
+size_of_encoded_value (unsigned char encoding)
+{
+  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
+
+/* Read an unsigned leb128 value from P, store the value in VAL, return
+   P incremented past the value.  We assume that a word is large enough to
+   hold any value so encoded; if it is smaller than a pointer on some target,
+   pointers should not be leb128 encoded on that target.  */
+
+static const unsigned char *
+read_uleb128 (const unsigned char *p, _uleb128_t *val)
+{
+  unsigned int shift = 0;
+  unsigned char byte;
+  _uleb128_t result;
+
+  result = 0;
+  do
+    {
+      byte = *p++;
+      result |= ((_uleb128_t)byte & 0x7f) << shift;
+      shift += 7;
+    }
+  while (byte & 0x80);
+
+  *val = result;
+  return p;
+}
+
+/* Similar, but read a signed leb128 value.  */
+
+static const unsigned char *
+read_sleb128 (const unsigned char *p, _sleb128_t *val)
+{
+  unsigned int shift = 0;
+  unsigned char byte;
+  _uleb128_t result;
+
+  result = 0;
+  do
+    {
+      byte = *p++;
+      result |= ((_uleb128_t)byte & 0x7f) << shift;
+      shift += 7;
+    }
+  while (byte & 0x80);
+
+  /* Sign-extend a negative value.  */
+  if (shift < 8 * sizeof(result) && (byte & 0x40) != 0)
+    result |= -(((_uleb128_t)1L) << shift);
+
+  *val = (_sleb128_t) result;
+  return p;
+}
+
+/* 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.  */
+
+static const unsigned char *
+read_encoded_value_with_base (unsigned char encoding, _Unwind_Ptr base,
+                             const unsigned char *p, _Unwind_Ptr *val)
+{
+  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__));
+
+  const union unaligned *u = (const union unaligned *) p;
+  _Unwind_Internal_Ptr result;
+
+  if (encoding == DW_EH_PE_aligned)
+    {
+      _Unwind_Internal_Ptr a = (_Unwind_Internal_Ptr) p;
+      a = (a + sizeof (void *) - 1) & - sizeof(void *);
+      result = *(_Unwind_Internal_Ptr *) a;
+      p = (const unsigned char *) (_Unwind_Internal_Ptr) (a + sizeof (void *));
+    }
+  else
+    {
+      switch (encoding & 0x0f)
+       {
+       case DW_EH_PE_absptr:
+         result = (_Unwind_Internal_Ptr) u->ptr;
+         p += sizeof (void *);
+         break;
+
+       case DW_EH_PE_uleb128:
+         {
+           _uleb128_t tmp;
+           p = read_uleb128 (p, &tmp);
+           result = (_Unwind_Internal_Ptr) tmp;
+         }
+         break;
+
+       case DW_EH_PE_sleb128:
+         {
+           _sleb128_t tmp;
+           p = read_sleb128 (p, &tmp);
+           result = (_Unwind_Internal_Ptr) tmp;
+         }
+         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_Internal_Ptr) u : base);
+         if (encoding & DW_EH_PE_indirect)
+           result = *(_Unwind_Internal_Ptr *) result;
+       }
+    }
+
+  *val = result;
+  return p;
+}
+
+#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
+
+#endif /* unwind-pe.h */
diff --git a/libgcc/unwind-sjlj.c b/libgcc/unwind-sjlj.c
new file mode 100644 (file)
index 0000000..c71e798
--- /dev/null
@@ -0,0 +1,326 @@
+/* SJLJ exception handling and frame unwind runtime interface routines.
+   Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2006,
+   2009  Free Software Foundation, Inc.
+
+   This file is part of GCC.
+
+   GCC 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 3, or (at your option)
+   any later version.
+
+   GCC 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.
+
+   Under Section 7 of GPL version 3, you are granted additional
+   permissions described in the GCC Runtime Library Exception, version
+   3.1, as published by the Free Software Foundation.
+
+   You should have received a copy of the GNU General Public License and
+   a copy of the GCC Runtime Library Exception along with this program;
+   see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include "tconfig.h"
+#include "tsystem.h"
+#include "coretypes.h"
+#include "tm.h"
+#include "unwind.h"
+#include "gthr.h"
+
+#ifdef __USING_SJLJ_EXCEPTIONS__
+
+#ifdef DONT_USE_BUILTIN_SETJMP
+#ifndef inhibit_libc
+#include <setjmp.h>
+#else
+typedef void *jmp_buf[JMP_BUF_SIZE];
+extern void longjmp(jmp_buf, int) __attribute__((noreturn));
+#endif
+#else
+#define longjmp __builtin_longjmp
+#endif
+
+/* The setjmp side is dealt with in the except.c file.  */
+#undef setjmp
+#define setjmp setjmp_should_not_be_used_in_this_file
+
+
+/* This structure is allocated on the stack of the target function.
+   This must match the definition created in except.c:init_eh.  */
+struct SjLj_Function_Context
+{
+  /* This is the chain through all registered contexts.  It is
+     filled in by _Unwind_SjLj_Register.  */
+  struct SjLj_Function_Context *prev;
+
+  /* This is assigned in by the target function before every call
+     to the index of the call site in the lsda.  It is assigned by
+     the personality routine to the landing pad index.  */
+  int call_site;
+
+  /* This is how data is returned from the personality routine to
+     the target function's handler.  */
+  _Unwind_Word data[4];
+
+  /* These are filled in once by the target function before any
+     exceptions are expected to be handled.  */
+  _Unwind_Personality_Fn personality;
+  void *lsda;
+
+#ifdef DONT_USE_BUILTIN_SETJMP
+  /* We don't know what sort of alignment requirements the system
+     jmp_buf has.  We over estimated in except.c, and now we have
+     to match that here just in case the system *didn't* have more
+     restrictive requirements.  */
+  jmp_buf jbuf __attribute__((aligned));
+#else
+  void *jbuf[];
+#endif
+};
+
+struct _Unwind_Context
+{
+  struct SjLj_Function_Context *fc;
+};
+
+typedef struct
+{
+  _Unwind_Personality_Fn personality;
+} _Unwind_FrameState;
+
+\f
+/* Manage the chain of registered function contexts.  */
+
+/* Single threaded fallback chain.  */
+static struct SjLj_Function_Context *fc_static;
+
+#if __GTHREADS
+static __gthread_key_t fc_key;
+static int use_fc_key = -1;
+
+static void
+fc_key_init (void)
+{
+  use_fc_key = __gthread_key_create (&fc_key, 0) == 0;
+}
+
+static void
+fc_key_init_once (void)
+{
+  static __gthread_once_t once = __GTHREAD_ONCE_INIT;
+  if (__gthread_once (&once, fc_key_init) != 0 || use_fc_key < 0)
+    use_fc_key = 0;
+}
+#endif
+
+void
+_Unwind_SjLj_Register (struct SjLj_Function_Context *fc)
+{
+#if __GTHREADS
+  if (use_fc_key < 0)
+    fc_key_init_once ();
+
+  if (use_fc_key)
+    {
+      fc->prev = __gthread_getspecific (fc_key);
+      __gthread_setspecific (fc_key, fc);
+    }
+  else
+#endif
+    {
+      fc->prev = fc_static;
+      fc_static = fc;
+    }
+}
+
+static inline struct SjLj_Function_Context *
+_Unwind_SjLj_GetContext (void)
+{
+#if __GTHREADS
+  if (use_fc_key < 0)
+    fc_key_init_once ();
+
+  if (use_fc_key)
+    return __gthread_getspecific (fc_key);
+#endif
+  return fc_static;
+}
+
+static inline void
+_Unwind_SjLj_SetContext (struct SjLj_Function_Context *fc)
+{
+#if __GTHREADS
+  if (use_fc_key < 0)
+    fc_key_init_once ();
+
+  if (use_fc_key)
+    __gthread_setspecific (fc_key, fc);
+  else
+#endif
+    fc_static = fc;
+}
+
+void
+_Unwind_SjLj_Unregister (struct SjLj_Function_Context *fc)
+{
+  _Unwind_SjLj_SetContext (fc->prev);
+}
+
+\f
+/* Get/set the return data value at INDEX in CONTEXT.  */
+
+_Unwind_Word
+_Unwind_GetGR (struct _Unwind_Context *context, int index)
+{
+  return context->fc->data[index];
+}
+
+/* Get the value of the CFA as saved in CONTEXT.  */
+
+_Unwind_Word
+_Unwind_GetCFA (struct _Unwind_Context *context __attribute__((unused)))
+{
+  /* ??? Ideally __builtin_setjmp places the CFA in the jmpbuf.  */
+
+#ifndef DONT_USE_BUILTIN_SETJMP
+  /* This is a crude imitation of the CFA: the saved stack pointer.
+     This is roughly the CFA of the frame before CONTEXT.  When using the
+     DWARF-2 unwinder _Unwind_GetCFA returns the CFA of the frame described
+     by CONTEXT instead; but for DWARF-2 the cleanups associated with
+     CONTEXT have already been run, and for SJLJ they have not yet been.  */
+  if (context->fc != NULL)
+    return (_Unwind_Word) context->fc->jbuf[2];
+#endif
+
+  /* Otherwise we're out of luck for now.  */
+  return (_Unwind_Word) 0;
+}
+
+void
+_Unwind_SetGR (struct _Unwind_Context *context, int index, _Unwind_Word val)
+{
+  context->fc->data[index] = val;
+}
+
+/* Get the call-site index as saved in CONTEXT.  */
+
+_Unwind_Ptr
+_Unwind_GetIP (struct _Unwind_Context *context)
+{
+  return context->fc->call_site + 1;
+}
+
+_Unwind_Ptr
+_Unwind_GetIPInfo (struct _Unwind_Context *context, int *ip_before_insn)
+{
+  *ip_before_insn = 0;
+  if (context->fc != NULL)
+    return context->fc->call_site + 1;
+  else
+    return 0;
+}
+
+/* Set the return landing pad index in CONTEXT.  */
+
+void
+_Unwind_SetIP (struct _Unwind_Context *context, _Unwind_Ptr val)
+{
+  context->fc->call_site = val - 1;
+}
+
+void *
+_Unwind_GetLanguageSpecificData (struct _Unwind_Context *context)
+{
+  return context->fc->lsda;
+}
+
+_Unwind_Ptr
+_Unwind_GetRegionStart (struct _Unwind_Context *context __attribute__((unused)) )
+{
+  return 0;
+}
+
+void *
+_Unwind_FindEnclosingFunction (void *pc __attribute__((unused)))
+{
+  return NULL;
+}
+
+#ifndef __ia64__
+_Unwind_Ptr
+_Unwind_GetDataRelBase (struct _Unwind_Context *context __attribute__((unused)) )
+{
+  return 0;
+}
+
+_Unwind_Ptr
+_Unwind_GetTextRelBase (struct _Unwind_Context *context __attribute__((unused)) )
+{
+  return 0;
+}
+#endif
+\f
+static inline _Unwind_Reason_Code
+uw_frame_state_for (struct _Unwind_Context *context, _Unwind_FrameState *fs)
+{
+  if (context->fc == NULL)
+    {
+      fs->personality = NULL;
+      return _URC_END_OF_STACK;
+    }
+  else
+    {
+      fs->personality = context->fc->personality;
+      return _URC_NO_REASON;
+    }
+}
+
+static inline void
+uw_update_context (struct _Unwind_Context *context,
+                  _Unwind_FrameState *fs __attribute__((unused)) )
+{
+  context->fc = context->fc->prev;
+}
+
+static void
+uw_advance_context (struct _Unwind_Context *context, _Unwind_FrameState *fs)
+{
+  _Unwind_SjLj_Unregister (context->fc);
+  uw_update_context (context, fs);
+}
+
+static inline void
+uw_init_context (struct _Unwind_Context *context)
+{
+  context->fc = _Unwind_SjLj_GetContext ();
+}
+
+static void __attribute__((noreturn))
+uw_install_context (struct _Unwind_Context *current __attribute__((unused)),
+                    struct _Unwind_Context *target)
+{
+  _Unwind_SjLj_SetContext (target->fc);
+  longjmp (target->fc->jbuf, 1);
+}
+
+static inline _Unwind_Ptr
+uw_identify_context (struct _Unwind_Context *context)
+{
+  return (_Unwind_Ptr) context->fc;
+}
+
+
+/* Play games with unwind symbols so that we can have call frame
+   and sjlj symbols in the same shared library.  Not that you can
+   use them simultaneously...  */
+#define _Unwind_RaiseException         _Unwind_SjLj_RaiseException
+#define _Unwind_ForcedUnwind           _Unwind_SjLj_ForcedUnwind
+#define _Unwind_Resume                 _Unwind_SjLj_Resume
+#define _Unwind_Resume_or_Rethrow      _Unwind_SjLj_Resume_or_Rethrow
+
+#include "unwind.inc"
+
+#endif /* USING_SJLJ_EXCEPTIONS */
diff --git a/libgcc/unwind.inc b/libgcc/unwind.inc
new file mode 100644 (file)
index 0000000..5e2ec29
--- /dev/null
@@ -0,0 +1,307 @@
+/* Exception handling and frame unwind runtime interface routines. -*- C -*-
+   Copyright (C) 2001, 2003, 2008, 2009 Free Software Foundation, Inc.
+
+   This file is part of GCC.
+
+   GCC 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 3, or (at your option)
+   any later version.
+
+   GCC 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.
+
+   Under Section 7 of GPL version 3, you are granted additional
+   permissions described in the GCC Runtime Library Exception, version
+   3.1, as published by the Free Software Foundation.
+
+   You should have received a copy of the GNU General Public License and
+   a copy of the GCC Runtime Library Exception along with this program;
+   see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+   <http://www.gnu.org/licenses/>.  */
+
+/* This is derived from the C++ ABI for IA-64.  Where we diverge
+   for cross-architecture compatibility are noted with "@@@".  
+   This file is included from unwind-dw2.c, unwind-sjlj.c or
+   unwind-ia64.c.  */
+
+/* Subroutine of _Unwind_RaiseException also invoked from _Unwind_Resume. 
+
+   Unwind the stack calling the personality routine to find both the
+   exception handler and intermediary cleanup code.  We'll only locate
+   the first such frame here.  Cleanup code will call back into
+   _Unwind_Resume and we'll continue Phase 2 there.  */
+
+static _Unwind_Reason_Code
+_Unwind_RaiseException_Phase2(struct _Unwind_Exception *exc,
+                             struct _Unwind_Context *context)
+{
+  _Unwind_Reason_Code code;
+
+  while (1)
+    {
+      _Unwind_FrameState fs;
+      int match_handler;
+
+      code = uw_frame_state_for (context, &fs);
+
+      /* Identify when we've reached the designated handler context.  */
+      match_handler = (uw_identify_context (context) == exc->private_2
+                      ? _UA_HANDLER_FRAME : 0);
+
+      if (code != _URC_NO_REASON)
+       /* Some error encountered.  Usually the unwinder doesn't
+          diagnose these and merely crashes.  */
+       return _URC_FATAL_PHASE2_ERROR;
+
+      /* Unwind successful.  Run the personality routine, if any.  */
+      if (fs.personality)
+       {
+         code = (*fs.personality) (1, _UA_CLEANUP_PHASE | match_handler,
+                                   exc->exception_class, exc, context);
+         if (code == _URC_INSTALL_CONTEXT)
+           break;
+         if (code != _URC_CONTINUE_UNWIND) 
+           return _URC_FATAL_PHASE2_ERROR;
+       }
+
+      /* Don't let us unwind past the handler context.  */
+      gcc_assert (!match_handler);
+
+      uw_update_context (context, &fs);
+    }
+
+  return code;
+}
+
+/* Raise an exception, passing along the given exception object.  */
+
+_Unwind_Reason_Code LIBGCC2_UNWIND_ATTRIBUTE
+_Unwind_RaiseException(struct _Unwind_Exception *exc)
+{
+  struct _Unwind_Context this_context, cur_context;
+  _Unwind_Reason_Code code;
+
+  /* Set up this_context to describe the current stack frame.  */
+  uw_init_context (&this_context);
+  cur_context = this_context;
+
+  /* Phase 1: Search.  Unwind the stack, calling the personality routine
+     with the _UA_SEARCH_PHASE flag set.  Do not modify the stack yet.  */
+  while (1)
+    {
+      _Unwind_FrameState fs;
+
+      /* Set up fs to describe the FDE for the caller of cur_context.  The
+        first time through the loop, that means __cxa_throw.  */
+      code = uw_frame_state_for (&cur_context, &fs);
+
+      if (code == _URC_END_OF_STACK)
+       /* Hit end of stack with no handler found.  */
+       return _URC_END_OF_STACK;
+
+      if (code != _URC_NO_REASON)
+       /* Some error encountered.  Usually the unwinder doesn't
+          diagnose these and merely crashes.  */
+       return _URC_FATAL_PHASE1_ERROR;
+
+      /* Unwind successful.  Run the personality routine, if any.  */
+      if (fs.personality)
+       {
+         code = (*fs.personality) (1, _UA_SEARCH_PHASE, exc->exception_class,
+                                   exc, &cur_context);
+         if (code == _URC_HANDLER_FOUND)
+           break;
+         else if (code != _URC_CONTINUE_UNWIND)
+           return _URC_FATAL_PHASE1_ERROR;
+       }
+
+      /* Update cur_context to describe the same frame as fs.  */
+      uw_update_context (&cur_context, &fs);
+    }
+
+  /* Indicate to _Unwind_Resume and associated subroutines that this
+     is not a forced unwind.  Further, note where we found a handler.  */
+  exc->private_1 = 0;
+  exc->private_2 = uw_identify_context (&cur_context);
+
+  cur_context = this_context;
+  code = _Unwind_RaiseException_Phase2 (exc, &cur_context);
+  if (code != _URC_INSTALL_CONTEXT)
+    return code;
+
+  uw_install_context (&this_context, &cur_context);
+}
+
+
+/* Subroutine of _Unwind_ForcedUnwind also invoked from _Unwind_Resume.  */
+
+static _Unwind_Reason_Code
+_Unwind_ForcedUnwind_Phase2 (struct _Unwind_Exception *exc,
+                            struct _Unwind_Context *context)
+{
+  _Unwind_Stop_Fn stop = (_Unwind_Stop_Fn) (_Unwind_Ptr) exc->private_1;
+  void *stop_argument = (void *) (_Unwind_Ptr) exc->private_2;
+  _Unwind_Reason_Code code, stop_code;
+
+  while (1)
+    {
+      _Unwind_FrameState fs;
+      int action;
+
+      /* Set up fs to describe the FDE for the caller of cur_context.  */
+      code = uw_frame_state_for (context, &fs);
+      if (code != _URC_NO_REASON && code != _URC_END_OF_STACK)
+       return _URC_FATAL_PHASE2_ERROR;
+
+      /* Unwind successful.  */
+      action = _UA_FORCE_UNWIND | _UA_CLEANUP_PHASE;
+      if (code == _URC_END_OF_STACK)
+       action |= _UA_END_OF_STACK;
+      stop_code = (*stop) (1, action, exc->exception_class, exc,
+                          context, stop_argument);
+      if (stop_code != _URC_NO_REASON)
+       return _URC_FATAL_PHASE2_ERROR;
+
+      /* Stop didn't want to do anything.  Invoke the personality
+        handler, if applicable, to run cleanups.  */
+      if (code == _URC_END_OF_STACK)
+       break;
+       
+      if (fs.personality)
+       {
+         code = (*fs.personality) (1, _UA_FORCE_UNWIND | _UA_CLEANUP_PHASE,
+                                   exc->exception_class, exc, context);
+         if (code == _URC_INSTALL_CONTEXT)
+           break;
+         if (code != _URC_CONTINUE_UNWIND) 
+           return _URC_FATAL_PHASE2_ERROR;
+       }
+
+      /* Update cur_context to describe the same frame as fs, and discard
+        the previous context if necessary.  */
+      uw_advance_context (context, &fs);
+    }
+
+  return code;
+}
+
+
+/* Raise an exception for forced unwinding.  */
+
+_Unwind_Reason_Code LIBGCC2_UNWIND_ATTRIBUTE
+_Unwind_ForcedUnwind (struct _Unwind_Exception *exc,
+                     _Unwind_Stop_Fn stop, void * stop_argument)
+{
+  struct _Unwind_Context this_context, cur_context;
+  _Unwind_Reason_Code code;
+
+  uw_init_context (&this_context);
+  cur_context = this_context;
+
+  exc->private_1 = (_Unwind_Ptr) stop;
+  exc->private_2 = (_Unwind_Ptr) stop_argument;
+
+  code = _Unwind_ForcedUnwind_Phase2 (exc, &cur_context);
+  if (code != _URC_INSTALL_CONTEXT)
+    return code;
+
+  uw_install_context (&this_context, &cur_context);
+}
+
+
+/* Resume propagation of an existing exception.  This is used after
+   e.g. executing cleanup code, and not to implement rethrowing.  */
+
+void LIBGCC2_UNWIND_ATTRIBUTE
+_Unwind_Resume (struct _Unwind_Exception *exc)
+{
+  struct _Unwind_Context this_context, cur_context;
+  _Unwind_Reason_Code code;
+
+  uw_init_context (&this_context);
+  cur_context = this_context;
+
+  /* Choose between continuing to process _Unwind_RaiseException
+     or _Unwind_ForcedUnwind.  */
+  if (exc->private_1 == 0)
+    code = _Unwind_RaiseException_Phase2 (exc, &cur_context);
+  else
+    code = _Unwind_ForcedUnwind_Phase2 (exc, &cur_context);
+
+  gcc_assert (code == _URC_INSTALL_CONTEXT);
+
+  uw_install_context (&this_context, &cur_context);
+}
+
+
+/* Resume propagation of an FORCE_UNWIND exception, or to rethrow
+   a normal exception that was handled.  */
+
+_Unwind_Reason_Code LIBGCC2_UNWIND_ATTRIBUTE
+_Unwind_Resume_or_Rethrow (struct _Unwind_Exception *exc)
+{
+  struct _Unwind_Context this_context, cur_context;
+  _Unwind_Reason_Code code;
+
+  /* Choose between continuing to process _Unwind_RaiseException
+     or _Unwind_ForcedUnwind.  */
+  if (exc->private_1 == 0)
+    return _Unwind_RaiseException (exc);
+
+  uw_init_context (&this_context);
+  cur_context = this_context;
+
+  code = _Unwind_ForcedUnwind_Phase2 (exc, &cur_context);
+
+  gcc_assert (code == _URC_INSTALL_CONTEXT);
+
+  uw_install_context (&this_context, &cur_context);
+}
+
+
+/* A convenience function that calls the exception_cleanup field.  */
+
+void
+_Unwind_DeleteException (struct _Unwind_Exception *exc)
+{
+  if (exc->exception_cleanup)
+    (*exc->exception_cleanup) (_URC_FOREIGN_EXCEPTION_CAUGHT, exc);
+}
+
+
+/* Perform stack backtrace through unwind data.  */
+
+_Unwind_Reason_Code LIBGCC2_UNWIND_ATTRIBUTE
+_Unwind_Backtrace(_Unwind_Trace_Fn trace, void * trace_argument)
+{
+  struct _Unwind_Context context;
+  _Unwind_Reason_Code code;
+
+  uw_init_context (&context);
+
+  while (1)
+    {
+      _Unwind_FrameState fs;
+
+      /* Set up fs to describe the FDE for the caller of context.  */
+      code = uw_frame_state_for (&context, &fs);
+      if (code != _URC_NO_REASON && code != _URC_END_OF_STACK)
+       return _URC_FATAL_PHASE1_ERROR;
+
+      /* Call trace function.  */
+      if ((*trace) (&context, trace_argument) != _URC_NO_REASON)
+       return _URC_FATAL_PHASE1_ERROR;
+
+      /* We're done at end of stack.  */       
+      if (code == _URC_END_OF_STACK)
+       break;
+
+      /* Update context to describe the same frame as fs.  */
+      uw_update_context (&context, &fs);
+    }
+
+  return code;
+}
index 26a6e78d64fed4095681938e671051affcbec835..740e8d257f41b68bf3dba8838d3e46d33779d9e8 100644 (file)
@@ -38,7 +38,7 @@ ACLOCAL_AMFLAGS = -I ./config -I ../config
 
 AM_CFLAGS = -fexceptions -fplan9-extensions $(SPLIT_STACK) $(WARN_CFLAGS) \
        $(STRINGOPS_FLAG) \
-       -I $(srcdir)/../gcc -I $(MULTIBUILDTOP)../../gcc/include
+       -I $(srcdir)/../libgcc -I $(MULTIBUILDTOP)../../gcc/include
 
 if USING_SPLIT_STACK
 AM_LDFLAGS = -XCClinker $(SPLIT_STACK)
index 5060d289261cdc554f54f92db27f2365c36161a0..42a160f3cf5154f394bc6eba42cda0704d4528c9 100644 (file)
@@ -495,7 +495,7 @@ AM_CPPFLAGS = -I $(srcdir)/runtime $(LIBFFIINCS) $(PTHREAD_CFLAGS)
 ACLOCAL_AMFLAGS = -I ./config -I ../config
 AM_CFLAGS = -fexceptions -fplan9-extensions $(SPLIT_STACK) $(WARN_CFLAGS) \
        $(STRINGOPS_FLAG) \
-       -I $(srcdir)/../gcc -I $(MULTIBUILDTOP)../../gcc/include
+       -I $(srcdir)/../libgcc -I $(MULTIBUILDTOP)../../gcc/include
 
 @USING_SPLIT_STACK_TRUE@AM_LDFLAGS = -XCClinker $(SPLIT_STACK)
 
index 98b72f501fe6e1abe0f62a0525b8c9ac70e4404a..f6bb404978e9b4a05bf30ba6f48990fc12969841 100644 (file)
@@ -1,3 +1,12 @@
+2011-08-05  Rainer Orth  <ro@CeBiTec.Uni-Bielefeld.DE>
+
+       * configure.ac (GCC_UNWIND_INCLUDE): Rename to
+       LIBGCC_UNWIND_INCLUDE.
+       Point to $(multi_basedir)/./libjava/../libgcc.
+       * configure: Regenerate.
+       * Makefile.am (GCC_UNWIND_INCLUDE): Reflect this.
+       * Makefile.in: Regenerate.
+
 2011-07-12  Andrew Haley  <aph@redhat.com>
 
        * interpret.cc (check_handler): Fix bit rot.
index 152170862c07007c7759d72416306e42850e59c4..1309defb623f5ae1a9fa2d49c361c2d80963ed45 100644 (file)
@@ -342,7 +342,7 @@ LIBLINK = $(LIBTOOL) --tag=CXX $(LIBTOOLFLAGS) --mode=link $(CXX) -L$(here) \
 CXXLINK = $(LIBTOOL) --tag=CXX $(LIBTOOLFLAGS) --mode=link $(CXXLD) \
          $(AM_CXXFLAGS) $(CXXFLAGS) $(AM_LDFLAGS) $(LTLDFLAGS) -o $@
 
-GCC_UNWIND_INCLUDE = @GCC_UNWIND_INCLUDE@
+LIBGCC_UNWIND_INCLUDE = @LIBGCC_UNWIND_INCLUDE@
 
 WARNINGS = -Wextra -Wall
 ## Some systems don't allow `$' in identifiers by default, so we force
@@ -410,7 +410,7 @@ AM_CPPFLAGS = -I$(top_srcdir) \
        -Iclasspath/include \
        -I$(top_srcdir)/classpath/native/fdlibm \
        $(GCINCS) $(THREADINCS) $(INCLTDL) \
-       $(GCC_UNWIND_INCLUDE) $(ZINCS) $(LIBFFIINCS)
+       $(LIBGCC_UNWIND_INCLUDE) $(ZINCS) $(LIBFFIINCS)
 
 BOOTCLASSPATH = $(srcdir)/classpath/lib
 
index 6c966a1efd5b73d2f96e78c5ad7581b0fde4e721..e741f26d06d55ec629e73f88cc8159bbccc86ebc 100644 (file)
@@ -552,7 +552,6 @@ EXCEPTIONSPEC = @EXCEPTIONSPEC@
 EXEEXT = @EXEEXT@
 FGREP = @FGREP@
 GCC_FOR_ECJX = @GCC_FOR_ECJX@
-GCC_UNWIND_INCLUDE = @GCC_UNWIND_INCLUDE@
 GCDEPS = @GCDEPS@
 GCINCS = @GCINCS@
 GCJ = @GCJ@
@@ -600,6 +599,7 @@ LIBART_LIBS = @LIBART_LIBS@
 LIBDIR = @LIBDIR@
 LIBFFI = @LIBFFI@
 LIBFFIINCS = @LIBFFIINCS@
+LIBGCC_UNWIND_INCLUDE = @LIBGCC_UNWIND_INCLUDE@
 LIBGCJDEBUG = @LIBGCJDEBUG@
 LIBGCJTESTSPEC = @LIBGCJTESTSPEC@
 LIBGCJ_BC_SPEC = @LIBGCJ_BC_SPEC@
@@ -1040,7 +1040,7 @@ AM_CPPFLAGS = -I$(top_srcdir) \
        -Iclasspath/include \
        -I$(top_srcdir)/classpath/native/fdlibm \
        $(GCINCS) $(THREADINCS) $(INCLTDL) \
-       $(GCC_UNWIND_INCLUDE) $(ZINCS) $(LIBFFIINCS)
+       $(LIBGCC_UNWIND_INCLUDE) $(ZINCS) $(LIBFFIINCS)
 
 BOOTCLASSPATH = $(srcdir)/classpath/lib
 libgij_la_SOURCES = gij.cc
index 4c3ab55746b59717c1eab0c75454c196c6c2d361..c2779c07c91b38c97df9501e8eab0f207b28522b 100755 (executable)
@@ -648,7 +648,7 @@ GCJVERSION
 toolexeclibdir
 toolexecmainlibdir
 toolexecdir
-GCC_UNWIND_INCLUDE
+LIBGCC_UNWIND_INCLUDE
 INSTALL_BINARIES_FALSE
 INSTALL_BINARIES_TRUE
 NEEDS_DATA_START_FALSE
@@ -6781,7 +6781,7 @@ case "${which_gcj}" in
    cross)
       if test "x${with_newlib}" = "xyes"; then
          # FIXME (comment): Why is this needed?
-         GCC_UNWIND_INCLUDE=
+         LIBGCC_UNWIND_INCLUDE=
       fi
       GCJH='$(target_noncanonical)-gcjh'
    ;;
@@ -20907,8 +20907,8 @@ else
 fi
 
 
-# We're in the tree with gcc, and need to include some of its headers.
-GCC_UNWIND_INCLUDE='-I$(multi_basedir)/./libjava/../gcc'
+# We're in the tree with libgcc, and need to include some of its headers.
+LIBGCC_UNWIND_INCLUDE='-I$(multi_basedir)/./libjava/../libgcc'
 
 if test "x${with_newlib}" = "xyes"; then
    # We are being configured with a cross compiler.  AC_REPLACE_FUNCS
index 5f673ea7cfdc332684eb7a29b4140a68280fa39e..92546f72b99cc239bda465f6701908406d614497 100644 (file)
@@ -469,7 +469,7 @@ case "${which_gcj}" in
    cross)
       if test "x${with_newlib}" = "xyes"; then
          # FIXME (comment): Why is this needed?
-         GCC_UNWIND_INCLUDE=
+         LIBGCC_UNWIND_INCLUDE=
       fi
       GCJH='$(target_noncanonical)-gcjh'
    ;;
@@ -1204,8 +1204,8 @@ AC_SUBST(HASH_SYNC_SPEC)
 
 AM_CONDITIONAL(USING_GCC, test "$GCC" = yes)
 
-# We're in the tree with gcc, and need to include some of its headers.
-GCC_UNWIND_INCLUDE='-I$(multi_basedir)/./libjava/../gcc'
+# We're in the tree with libgcc, and need to include some of its headers.
+LIBGCC_UNWIND_INCLUDE='-I$(multi_basedir)/./libjava/../libgcc'
 
 if test "x${with_newlib}" = "xyes"; then
    # We are being configured with a cross compiler.  AC_REPLACE_FUNCS
@@ -1569,7 +1569,7 @@ AM_CONDITIONAL(NATIVE, test "$NATIVE" = yes)
 AM_CONDITIONAL(ENABLE_SHARED, test "$enable_shared" = yes)
 AM_CONDITIONAL(NEEDS_DATA_START, test "$NEEDS_DATA_START" = yes && test "$NATIVE" = yes)
 AM_CONDITIONAL(INSTALL_BINARIES, test -z "${with_multisubdir}")
-AC_SUBST(GCC_UNWIND_INCLUDE)
+AC_SUBST(LIBGCC_UNWIND_INCLUDE)
 
 # Process the option "--enable-version-specific-runtime-libs"
 # Calculate toolexeclibdir
index 45f04859578008a143ad2e261198242e48d8c76d..61d4ac335d7f978fd512e98a6c6f426bf3b3bd7e 100644 (file)
@@ -1,3 +1,8 @@
+2011-08-05  Rainer Orth  <ro@CeBiTec.Uni-Bielefeld.DE>
+
+       * Makefile.in (INCLUDES): Search
+       $(srcdir)/$(MULTISRCTOP)../libgcc.
+
 2011-06-08  Nicola Pero  <nicola.pero@meta-innovation.com>
 
        * objc/objc.h (__GNU_LIBOBJC__): Bumped to 20110608.
index 02443327058132aa0b24b4e99227bd371c2778f5..0935ccd98d6923b5aaeab05036b656d47d39b2e3 100644 (file)
@@ -101,6 +101,7 @@ OBJC_BOEHM_GC_LIBS=../boehm-gc/libgcjgc_convenience.la $(thread_libs_and_flags)
 INCLUDES = -I$(srcdir)/$(MULTISRCTOP)../gcc \
   -I$(srcdir)/$(MULTISRCTOP)../gcc/config \
   -I$(MULTIBUILDTOP)../../$(host_subdir)/gcc \
+  -I$(srcdir)/$(MULTISRCTOP)../libgcc \
   -I$(srcdir)/$(MULTISRCTOP)../include \
   $(OBJC_BOEHM_GC_INCLUDES)
 
index 5168fa3e38de51dcdfde299af81a944048e51eb1..a02326c6dbea756f460d08b60bb178a773641c01 100644 (file)
@@ -1,3 +1,9 @@
+2011-08-05  Rainer Orth  <ro@CeBiTec.Uni-Bielefeld.DE>
+
+       * acinclude.m4 (GLIBCXX_EXPORT_INCLUDES): Point TOPLEVEL_INCLUDES
+       to $(toplevel_srcdir)/libgcc.
+       * configure: Regenerate.
+
 2011-08-04  Benjamin Kosnik  <bkoz@redhat.com>
 
        * doc/xml/manual/build_hacking.xml: Use relative fileref for PNG
index 6f6810de23545df145fef22dd246ccfe0b169203..8bbc40e95f22e9d3015451c291a2d910116526f5 100644 (file)
@@ -685,9 +685,9 @@ AC_DEFUN([GLIBCXX_EXPORT_INCLUDES], [
   fi
 
   # Stuff in the actual top level.  Currently only used by libsupc++ to
-  # get unwind* headers from the gcc dir.
-  #TOPLEVEL_INCLUDES='-I$(toplevel_srcdir)/gcc -I$(toplevel_srcdir)/include'
-  TOPLEVEL_INCLUDES='-I$(toplevel_srcdir)/gcc'
+  # get unwind* headers from the libgcc dir.
+  #TOPLEVEL_INCLUDES='-I$(toplevel_srcdir)/libgcc -I$(toplevel_srcdir)/include'
+  TOPLEVEL_INCLUDES='-I$(toplevel_srcdir)/libgcc'
 
   # Now, export this to all the little Makefiles....
   AC_SUBST(GLIBCXX_INCLUDES)
index 0bbc485d3006d1bcf5efef85a7939162387ad482..c7be667dc8043a129b0385344cf537dade390559 100755 (executable)
@@ -65769,9 +65769,9 @@ $as_echo "$gxx_include_dir" >&6; }
   fi
 
   # Stuff in the actual top level.  Currently only used by libsupc++ to
-  # get unwind* headers from the gcc dir.
-  #TOPLEVEL_INCLUDES='-I$(toplevel_srcdir)/gcc -I$(toplevel_srcdir)/include'
-  TOPLEVEL_INCLUDES='-I$(toplevel_srcdir)/gcc'
+  # get unwind* headers from the libgcc dir.
+  #TOPLEVEL_INCLUDES='-I$(toplevel_srcdir)/libgcc -I$(toplevel_srcdir)/include'
+  TOPLEVEL_INCLUDES='-I$(toplevel_srcdir)/libgcc'
 
   # Now, export this to all the little Makefiles....