diff options
author | ro <ro@138bc75d-0d04-0410-961f-82ee72b054a4> | 2011-08-05 14:37:48 +0000 |
---|---|---|
committer | ro <ro@138bc75d-0d04-0410-961f-82ee72b054a4> | 2011-08-05 14:37:48 +0000 |
commit | e59be7e3775cce7a65bfac5c9aeb5f76d42f539b (patch) | |
tree | 80376027cf518687afe9d3c715d908e42d42c267 /gcc | |
parent | 81b424acb24cb12818bca93206e80e9476919f75 (diff) | |
download | gcc-e59be7e3775cce7a65bfac5c9aeb5f76d42f539b.tar.gz |
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.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@177447 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc')
58 files changed, 84 insertions, 12073 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index f269930732d..438e8bb95f0 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -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. diff --git a/gcc/Makefile.in b/gcc/Makefile.in index 0204f93208a..889deb16240 100644 --- a/gcc/Makefile.in +++ b/gcc/Makefile.in @@ -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; \ diff --git a/gcc/aclocal.m4 b/gcc/aclocal.m4 index 73afd7fedee..1b90b2f5ee6 100644 --- a/gcc/aclocal.m4 +++ b/gcc/aclocal.m4 @@ -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]) diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index ce02f4f2889..743fa0e57dc 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -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 @@ -100,6 +105,7 @@ 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, diff --git a/gcc/ada/gcc-interface/Makefile.in b/gcc/ada/gcc-interface/Makefile.in index 1642cc8622b..1e7a392edf4 100644 --- a/gcc/ada/gcc-interface/Makefile.in +++ b/gcc/ada/gcc-interface/Makefile.in @@ -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 diff --git a/gcc/config.gcc b/gcc/config.gcc index 94f15d8706d..673b768b770 100644 --- a/gcc/config.gcc +++ b/gcc/config.gcc @@ -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 index 48eb592fd1a..00000000000 --- a/gcc/config/arm/libunwind.S +++ /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 index deee661e264..00000000000 --- a/gcc/config/arm/pr-support.c +++ /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, - ®); - _Unwind_VRS_Set (context, _UVRSC_CORE, R_PC, _UVRSD_UINT32, - ®); - 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, ®); - if (op & 0x40) - reg -= offset; - else - reg += offset; - _Unwind_VRS_Set (context, _UVRSC_CORE, R_SP, _UVRSD_UINT32, ®); - 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, ®); - _Unwind_VRS_Set (context, _UVRSC_CORE, R_SP, _UVRSD_UINT32, ®); - 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, - ®); - 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, - ®); - 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/gcc/config/arm/t-bpabi b/gcc/config/arm/t-bpabi index 78812b35bd8..b6b5f40d723 100644 --- a/gcc/config/arm/t-bpabi +++ b/gcc/config/arm/t-bpabi @@ -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 diff --git a/gcc/config/arm/t-symbian b/gcc/config/arm/t-symbian index 3be83f445aa..f074591acbe 100644 --- a/gcc/config/arm/t-symbian +++ b/gcc/config/arm/t-symbian @@ -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 index 90d258d3c80..00000000000 --- a/gcc/config/arm/unwind-arm.c +++ /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 index 1a51d8d4824..00000000000 --- a/gcc/config/arm/unwind-arm.h +++ /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 */ diff --git a/gcc/config/frv/t-frv b/gcc/config/frv/t-frv index 0c58bb16713..2729008879c 100644 --- a/gcc/config/frv/t-frv +++ b/gcc/config/frv/t-frv @@ -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 index 12760b96eda..00000000000 --- a/gcc/config/ia64/fde-glibc.c +++ /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 index b310f0d11b6..00000000000 --- a/gcc/config/ia64/fde-vms.c +++ /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; -} diff --git a/gcc/config/ia64/t-glibc b/gcc/config/ia64/t-glibc index e6d72b94a87..ce18a92e275 100644 --- a/gcc/config/ia64/t-glibc +++ b/gcc/config/ia64/t-glibc @@ -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 index df78f1d094f..00000000000 --- a/gcc/config/ia64/t-glibc-libunwind +++ /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 diff --git a/gcc/config/ia64/t-hpux b/gcc/config/ia64/t-hpux index a97ab5c4478..4aa661441b2 100644 --- a/gcc/config/ia64/t-hpux +++ b/gcc/config/ia64/t-hpux @@ -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. diff --git a/gcc/config/ia64/t-ia64 b/gcc/config/ia64/t-ia64 index 4f013e2d591..f130f7c09d1 100644 --- a/gcc/config/ia64/t-ia64 +++ b/gcc/config/ia64/t-ia64 @@ -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) \ diff --git a/gcc/config/ia64/t-vms b/gcc/config/ia64/t-vms index bcd753401f1..094d53483ee 100644 --- a/gcc/config/ia64/t-vms +++ b/gcc/config/ia64/t-vms @@ -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 index 061bd4b8980..00000000000 --- a/gcc/config/ia64/unwind-ia64.c +++ /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 -}; - - -#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); - } -} - -/* 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 (®s[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; -} - - -#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) - - -/* - * 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; -} - - -/* 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; -} - - -/* 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; - } -} - -/* 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" - -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 index b98f048fdb5..00000000000 --- a/gcc/config/ia64/unwind-ia64.h +++ /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"))); diff --git a/gcc/config/ia64/vms.h b/gcc/config/ia64/vms.h index 847d79afa1d..853e0239d3b 100644 --- a/gcc/config/ia64/vms.h +++ b/gcc/config/ia64/vms.h @@ -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. */ diff --git a/gcc/config/picochip/t-picochip b/gcc/config/picochip/t-picochip index ba4394eceeb..4df74a01fc6 100644 --- a/gcc/config/picochip/t-picochip +++ b/gcc/config/picochip/t-picochip @@ -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 diff --git a/gcc/config/rs6000/aix.h b/gcc/config/rs6000/aix.h index 13d317f508a..2c678a3a247 100644 --- a/gcc/config/rs6000/aix.h +++ b/gcc/config/rs6000/aix.h @@ -209,40 +209,6 @@ /* 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 index 4591071ea74..00000000000 --- a/gcc/config/rs6000/darwin-fallback.c +++ /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 diff --git a/gcc/config/rs6000/t-darwin b/gcc/config/rs6000/t-darwin index 8113b9ecbcb..27fc07b69b3 100644 --- a/gcc/config/rs6000/t-darwin +++ b/gcc/config/rs6000/t-darwin @@ -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 diff --git a/gcc/config/sh/t-sh b/gcc/config/sh/t-sh index a897bfffb47..27cbd3d3e88 100644 --- a/gcc/config/sh/t-sh +++ b/gcc/config/sh/t-sh @@ -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) diff --git a/gcc/config/spu/t-spu-elf b/gcc/config/spu/t-spu-elf index 5189f28584d..ab680f5be88 100644 --- a/gcc/config/spu/t-spu-elf +++ b/gcc/config/spu/t-spu-elf @@ -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 diff --git a/gcc/config/t-darwin b/gcc/config/t-darwin index 9e77395998d..d952bd39273 100644 --- a/gcc/config/t-darwin +++ b/gcc/config/t-darwin @@ -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 diff --git a/gcc/config/t-freebsd b/gcc/config/t-freebsd index af2df24f105..0680618a6ec 100644 --- a/gcc/config/t-freebsd +++ b/gcc/config/t-freebsd @@ -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 diff --git a/gcc/config/t-libunwind b/gcc/config/t-libunwind index 6fdaf676b37..6b8d2dd1292 100644 --- a/gcc/config/t-libunwind +++ b/gcc/config/t-libunwind @@ -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 index 5ae0d62de25..00000000000 --- a/gcc/config/t-libunwind-elf +++ /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) diff --git a/gcc/config/t-linux b/gcc/config/t-linux index 039fa27ae82..64d19ca8dd7 100644 --- a/gcc/config/t-linux +++ b/gcc/config/t-linux @@ -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 diff --git a/gcc/config/t-sol2 b/gcc/config/t-sol2 index 73fd8eb3667..f53da4d3ca6 100644 --- a/gcc/config/t-sol2 +++ b/gcc/config/t-sol2 @@ -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 diff --git a/gcc/config/xtensa/t-xtensa b/gcc/config/xtensa/t-xtensa index c3d98ae30b5..641e6fe7620 100644 --- a/gcc/config/xtensa/t-xtensa +++ b/gcc/config/xtensa/t-xtensa @@ -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 index 54daf7637ce..00000000000 --- a/gcc/config/xtensa/unwind-dw2-xtensa.c +++ /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; -}; - - -/* 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; } - -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; -} - -/* 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" - -/* 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; -} - -/* 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; -} - -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); -} - -/* 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 index d13b3264c99..00000000000 --- a/gcc/config/xtensa/unwind-dw2-xtensa.h +++ /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; - diff --git a/gcc/configure b/gcc/configure index 63e44c5e43d..88bb116dc1f 100755 --- a/gcc/configure +++ b/gcc/configure @@ -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 diff --git a/gcc/configure.ac b/gcc/configure.ac index c71281cbeb2..81345d6f328 100644 --- a/gcc/configure.ac +++ b/gcc/configure.ac @@ -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 index b7ee3bdfa7c..00000000000 --- a/gcc/emutls.c +++ /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; -} diff --git a/gcc/po/ChangeLog b/gcc/po/ChangeLog index 1123a00424d..610ca9ba7d0 100644 --- a/gcc/po/ChangeLog +++ b/gcc/po/ChangeLog @@ -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. diff --git a/gcc/po/EXCLUDES b/gcc/po/EXCLUDES index cc29a2bd1ac..12fced15f72 100644 --- a/gcc/po/EXCLUDES +++ b/gcc/po/EXCLUDES @@ -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 diff --git a/gcc/system.h b/gcc/system.h index 7ac98596bc7..a7db6f58f85 100644 --- a/gcc/system.h +++ b/gcc/system.h @@ -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 index 86b9f557048..00000000000 --- a/gcc/unwind-c.c +++ /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 index 5b41f24688d..00000000000 --- a/gcc/unwind-compat.c +++ /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 index 24c8de11801..00000000000 --- a/gcc/unwind-compat.h +++ /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 index f305a5501a0..00000000000 --- a/gcc/unwind-dw2-fde-compat.c +++ /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 index 75b404e09e9..00000000000 --- a/gcc/unwind-dw2-fde-darwin.c +++ /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. */ -}; - -/* 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 index d8e3c0e934b..00000000000 --- a/gcc/unwind-dw2-fde-glibc.c +++ /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 index 93d427165c4..00000000000 --- a/gcc/unwind-dw2-fde.c +++ /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)); -} - - -/* 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)); -} - - -/* 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 = ▮ - 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); - } -} - - -/* 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 index 6d7a8dee2cf..00000000000 --- a/gcc/unwind-dw2-fde.h +++ /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 *); - - -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 index 19da29982b6..00000000000 --- a/gcc/unwind-dw2.c +++ /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]; - - -/* 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; } - -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; -} - -/* 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" - -/* 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, ®); - 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, ®); - 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, ®); - 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, ®); - /* 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, ®); - fs->regs.reg[DWARF_REG_TO_UNWIND_COLUMN(reg)].how = REG_UNSAVED; - break; - - case DW_CFA_undefined: - insn_ptr = read_uleb128 (insn_ptr, ®); - 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, ®); - insn_ptr = read_uleb128 (insn_ptr, ®2); - 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, ®); - 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, ®); - 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, ®); - 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, ®); - 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, ®); - 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, ®); - 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 (); - } - } -} - -/* 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; -} - -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; -} - -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); -} - -/* 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 index 2c558b4962a..00000000000 --- a/gcc/unwind-dw2.h +++ /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 index 4ff9017b88b..00000000000 --- a/gcc/unwind-generic.h +++ /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 index 121f8776721..00000000000 --- a/gcc/unwind-pe.h +++ /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 - - -#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 index c71e79858ee..00000000000 --- a/gcc/unwind-sjlj.c +++ /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; - - -/* 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); -} - - -/* 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 - -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 index 5e2ec29c79a..00000000000 --- a/gcc/unwind.inc +++ /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; -} |