2009-08-14 22:38:36 +02:00
|
|
|
/* DWARF2 EH unwinding support for IA64 VMS.
|
2022-01-03 10:42:10 +01:00
|
|
|
Copyright (C) 2005-2022 Free Software Foundation, Inc.
|
2009-08-14 22:38:36 +02:00
|
|
|
|
|
|
|
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/>. */
|
|
|
|
|
unwind-ia64.h: Declare unw_word and unw_sword.
2012-03-26 Tristan Gingold <gingold@adacore.com>
* config/ia64/unwind-ia64.h: Declare unw_word and unw_sword.
(unw_table_entry): Use unw_word instead of unsigned long.
(_Unwind_FindTableEntry): Likewise.
* config/ia64/fde-glibc.c (_Unwind_FindTableEntry): Likewise.
* config/ia64/fde-vms.c (vms_unwtable_entry): Likewise.
(_Unwind_FindTableEntry): Likewise.
* config/ia64/unwind-ia64.c (unw_reg_info, unw_reg_state)
(unw_labeled_state, unw_state_record, unw_stack, _Uwind_Context)
(set_reg, alloc_spill_area, finish_prologue, ia64_rse_slot_num)
(ia64_rse_is_rnat_slot, ia64_rse_rnat_addr, ia64_rse_num_regs)
(ia64_rse_skip_regs, ia64_copy_rbs, unw_access_gr)
(uw_frame_state_for, uw_update_reg_address, uw_update_context)
(uw_init_context_1, uw_install_context): Likewise.
(unw_word): Move to unwind-ia64.h
From-SVN: r185852
2012-03-27 11:50:10 +02:00
|
|
|
#define __NEW_STARLET
|
|
|
|
#include <libicb.h>
|
|
|
|
#include <chfdef.h>
|
|
|
|
#include <lib_c/chfctxdef.h>
|
|
|
|
#include <lib_c/intstkdef.h>
|
2009-08-14 22:38:36 +02:00
|
|
|
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <string.h>
|
|
|
|
|
Makefile.in (UNWIND_H): Remove.
gcc:
* Makefile.in (UNWIND_H): Remove.
(LIB2ADDEH, LIB2ADDEHSTATIC, LIB2ADDEHSHARED): Move to
../libgcc/Makefile.in.
(LIBUNWIND, SHLIBUNWIND_LINK, SHLIBUNWIND_INSTALL): Likewise.
(LIBUNWINDDEP): Remove.
(libgcc-support): Remove LIB2ADDEH, $(srcdir)/emutls.c dependencies.
(libgcc.mvars): Remove LIB2ADDEH, LIB2ADDEHSTATIC, LIB2ADDEHSHARED,
LIBUNWIND, SHLIBUNWIND_LINK, SHLIBUNWIND_INSTALL.
(stmp-int-hdrs): Remove $(UNWIND_H) dependency.
Don't copy $(UNWIND_H).
* config.gcc (ia64*-*-linux*): Remove with_system_libunwind
handling.
* configure.ac (GCC_CHECK_UNWIND_GETIPINFO): Remove.
* aclocal.m4: Regenerate.
* configure: Regenerate.
* emutls.c, unwind-c.c, unwind-compat.c, unwind-compat.h,
unwind-dw2-fde-compat.c, unwind-dw2-fde-glibc.c, unwind-dw2-fde.c,
unwind-dw2-fde.h, unwind-dw2.c, unwind-dw2.h, unwind-generic.h,
unwind-pe.h, unwind-sjlj.c, unwind.inc: Move to ../libgcc.
* unwind-dw2-fde-darwin.c: Move to ../libgcc/config.
* config/arm/libunwind.S, config/arm/pr-support.c,
config/arm/unwind-arm.c, config/arm/unwind-arm.h: Move to
../libgcc/config/arm.
* config/arm/t-bpabi (UNWIND_H, LIB2ADDEH): Remove.
* config/arm/t-symbian (UNWIND_H, LIB2ADDEH): Remove.
* config/frv/t-frv ($(T)frvbegin$(objext)): Use
$(srcdir)/../libgcc to refer to unwind-dw2-fde.h.
($(T)frvend$(objext)): Likewise.
* config/ia64/t-glibc (LIB2ADDEH): Remove.
* config/ia64/t-glibc-libunwind: Move to ../libgcc/config/ia64.
* config/ia64/fde-glibc.c, config/ia64/fde-vms.c,
config/ia64/unwind-ia64.c, config/ia64/unwind-ia64.h: Move to
../libgcc/config/ia64.
* config/ia64/t-hpux (LIB2ADDEH): Remove.
* config/ia64/t-ia64 (LIB2ADDEH): Remove.
* config/ia64/t-vms (LIB2ADDEH): Remove.
* config/ia64/vms.h (UNW_IVMS_MODE,
MD_UNW_COMPATIBLE_PERSONALITY_P): Remove.
* config/picochip/t-picochip (LIB2ADDEH): Remove.
* config/rs6000/aix.h (R_LR, MD_FROB_UPDATE_CONTEXT): Remove.
* config/rs6000/t-darwin (LIB2ADDEH): Remove.
* config/rs6000/darwin-fallback.c: Move to ../libgcc/config/rs6000.
* config/sh/t-sh ($(T)unwind-dw2-Os-4-200.o): Use
$(srcdir)/../libgcc to refer to unwinder sources.
* config/spu/t-spu-elf (LIB2ADDEH): Remove.
* config/t-darwin (LIB2ADDEH): Remove.
* config/t-freebsd (LIB2ADDEH): Remove.
* config/t-libunwind (LIB2ADDEH, LIB2ADDEHSTATIC): Remove.
* config/t-libunwind-elf: Move to ../libgcc/config.
* config/t-linux (LIB2ADDEH): Remove.
* config/t-sol2 (LIB2ADDEH): Remove.
* config/xtensa/t-xtensa (LIB2ADDEH): Remove.
* system.h (MD_FROB_UPDATE_CONTEXT): Poison.
gcc/po:
* EXCLUDES (unwind-c.c, unwind-dw2-fde-darwin.c)
(unwind-dw2-fde-glibc.c, unwind-dw2-fde.c, unwind-dw2-fde.h)
(unwind-dw2.c, unwind-pe.h, unwind-sjlj.c, unwind.h): Remove.
libgcc:
* Makefile.in (LIB2ADDEH, LIB2ADDEHSTATIC, LIB2ADDEHSHARED): New
variables.
(LIBUNWIND, SHLIBUNWIND_LINK, SHLIBUNWIND_INSTALL): New variables.
(LIB2ADDEH, LIB2ADDEHSTATIC, LIB2ADDEHSHARED): Add $(srcdir)/emutls.c.
(install-unwind_h): New target.
(all): Depend on it.
* config.host (unwind_header): New variable.
(*-*-freebsd*): Set tmake_file to t-eh-dw2-dip.
(*-*-linux*, frv-*-*linux*, *-*-kfreebsd*-gnu, *-*-knetbsd*-gnu,
*-*-gnu*): Likewise, also for *-*-kopensolaris*-gnu.
(*-*-solaris2*): Add t-eh-dw2-dip to tmake_file.
(arm*-*-linux*): Add arm/t-bpabi for arm*-*-linux-*eabi.
Set unwind_header.
(arm*-*-uclinux*): Add arm/t-bpabi for arm*-*-uclinux*eabi.
Set unwind_header.
(arm*-*-eabi*, arm*-*-symbianelf*): Add arm/t-bpabi for
arm*-*-eabi*.
Add arm/t-symbian to tmake_file for arm*-*-symbianelf*.
Set unwind_header.
(ia64*-*-elf*): Add ia64/t-eh-ia64 to tmake_file.
(ia64*-*-freebsd*): Likewise.
(ia64*-*-linux*): Add ia64/t-glibc, ia64/t-eh-ia64, t-libunwind to
tmake_file.
Add t-libunwind-elf, ia64/t-glibc-libunwind unless
$with_system_libunwind.
(ia64*-*-hpux*): Set tmake_file.
(ia64-hp-*vms*): Add ia64/t-eh-ia64 to tmake_file.
(picochip-*-*): Set tmake_file.
(rs6000-ibm-aix4.[3456789]*, powerpc-ibm-aix4.[3456789]*): Set
md_unwind_header.
(rs6000-ibm-aix5.1.*, powerpc-ibm-aix5.1.*): Likewise.
(rs6000-ibm-aix[56789].*, powerpc-ibm-aix[56789].*): Likewise.
(s390x-ibm-tpf*): Add t-eh-dw2-dip to tmake_file.
(xtensa*-*-elf*): Set tmake_file.
(xtensa*-*-linux*): Likewise.
* configure.ac: Include ../config/unwind_ipinfo.m4.
Call GCC_CHECK_UNWIND_GETIPINFO.
Link unwind.h to $unwind_header.
* configure: Regenerate.
* emutls.c, unwind-c.c, unwind-compat.c, unwind-compat.h,
unwind-dw2-fde-compat.c, unwind-dw2-fde-dip.c, unwind-dw2-fde.c,
unwind-dw2-fde.h, unwind-dw2.c, unwind-dw2.h, unwind-generic.h,
unwind-pe.h, unwind-sjlj.c, unwind.inc: New files.
* config/unwind-dw2-fde-darwin.c: New file.
* config/arm/libunwind.S, config/arm/pr-support.c,
config/arm/t-bpabi, config/arm/t-symbian, config/arm/unwind-arm.c,
config/arm/unwind-arm.h,: New files.
* config/ia64/fde-glibc.c, config/ia64/fde-vms.c,
config/ia64/t-eh-ia64, config/ia64/t-glibc,
config/ia64/t-glibc-libunwind, config/ia64/t-hpux,
config/ia64/t-vms, config/ia64/unwind-ia64.c,
config/ia64/unwind-ia64.h: New files.
* config/picochip/t-picochip: New file.
* config/rs6000/aix-unwind.h, config/rs6000/darwin-fallback.c: New
files.
* config/rs6000/t-darwin (LIB2ADDEH): Set.
* config/s390/t-tpf (LIB2ADDEH): Remove.
* config/t-darwin (LIB2ADDEH): Set.
* config/t-eh-dw2-dip: New file.
* config/t-libunwind, config/t-libunwind-elf: New files.
* config/t-sol2 (LIB2ADDEH): Remove.
* config/xtensa/t-xtensa: New file.
gcc/ada:
* gcc-interface/Makefile.in (raise-gcc.o): Search
$(srcdir)/../libgcc.
libgo:
* Makefile.am (AM_CFLAGS): Search $(srcdir)/../libgcc.
* Makefile.in: Regenerate.
libjava:
* configure.ac (GCC_UNWIND_INCLUDE): Rename to
LIBGCC_UNWIND_INCLUDE.
Point to $(multi_basedir)/./libjava/../libgcc.
* configure: Regenerate.
* Makefile.am (GCC_UNWIND_INCLUDE): Reflect this.
* Makefile.in: Regenerate.
libobjc:
* Makefile.in (INCLUDES): Search
$(srcdir)/$(MULTISRCTOP)../libgcc.
libstdc++-v3:
* acinclude.m4 (GLIBCXX_EXPORT_INCLUDES): Point TOPLEVEL_INCLUDES
to $(toplevel_srcdir)/libgcc.
* configure: Regenerate.
From-SVN: r177447
2011-08-05 16:37:48 +02:00
|
|
|
#define UNW_IVMS_MODE(HEADER) (((HEADER) >> 44) & 0x3L)
|
|
|
|
#define MD_UNW_COMPATIBLE_PERSONALITY_P(HEADER) (!UNW_IVMS_MODE (HEADER))
|
|
|
|
|
2009-08-14 22:38:36 +02:00
|
|
|
#define DYN$C_SSENTRY 66
|
|
|
|
/* ??? would rather get the proper header file. */
|
|
|
|
|
|
|
|
#define MD_FALLBACK_FRAME_STATE_FOR ia64_vms_fallback_frame_state
|
|
|
|
|
|
|
|
extern INVO_CONTEXT_BLK * LIB$I64_CREATE_INVO_CONTEXT (void);
|
|
|
|
|
|
|
|
extern int LIB$I64_IS_EXC_DISPATCH_FRAME (void *);
|
|
|
|
extern int LIB$I64_IS_AST_DISPATCH_FRAME (void *);
|
|
|
|
|
|
|
|
extern int LIB$I64_INIT_INVO_CONTEXT (INVO_CONTEXT_BLK *, int, int);
|
|
|
|
extern int LIB$I64_GET_CURR_INVO_CONTEXT (INVO_CONTEXT_BLK *);
|
|
|
|
extern int LIB$I64_GET_PREV_INVO_CONTEXT (INVO_CONTEXT_BLK *);
|
|
|
|
|
|
|
|
typedef unsigned int uint;
|
2012-03-16 11:58:28 +01:00
|
|
|
typedef unsigned __int64 uw_reg;
|
2009-08-14 22:38:36 +02:00
|
|
|
typedef uw_reg * uw_loc;
|
|
|
|
|
|
|
|
typedef char fp_reg[16];
|
|
|
|
|
|
|
|
#define DENOTES_VMS_DISPATCHER_FRAME(icb) \
|
|
|
|
(LIB$I64_IS_EXC_DISPATCH_FRAME (&(icb)->libicb$ih_pc))
|
|
|
|
|
|
|
|
#define DENOTES_BOTTOM_OF_STACK(icb) ((icb)->libicb$v_bottom_of_stack)
|
|
|
|
|
|
|
|
#define FAIL_IF(COND) \
|
|
|
|
do { if (COND) { context->rp = 0; return _URC_END_OF_STACK; } } while (0)
|
|
|
|
/* Clearing context->rp is required to prevent the ia64 gcc unwinder from
|
|
|
|
attempting to keep on walking the call chain. */
|
|
|
|
|
|
|
|
static int
|
|
|
|
ia64_vms_fallback_frame_state (struct _Unwind_Context *context,
|
|
|
|
_Unwind_FrameState *fs)
|
|
|
|
{
|
|
|
|
int i, status;
|
|
|
|
|
|
|
|
INVO_CONTEXT_BLK local_icb;
|
|
|
|
INVO_CONTEXT_BLK *icb = &local_icb;
|
|
|
|
|
|
|
|
CHFCTX * chfctx;
|
|
|
|
CHF$MECH_ARRAY * chfmech;
|
|
|
|
CHF64$SIGNAL_ARRAY *chfsig64;
|
|
|
|
INTSTK * intstk;
|
|
|
|
|
|
|
|
static int eh_debug = -1;
|
|
|
|
int try_bs_copy = 0;
|
|
|
|
/* Non zero to attempt copy of alternate backing store contents for
|
|
|
|
dirty partition in interrupted context. ??? Alpha code, only activated
|
|
|
|
on specific request via specific bit in EH_DEBUG. */
|
|
|
|
|
|
|
|
if (eh_debug == -1)
|
|
|
|
{
|
|
|
|
char * EH_DEBUG = getenv ("EH_DEBUG");
|
|
|
|
const uint try_bs_copy_mask = (1 << 16);
|
|
|
|
|
|
|
|
eh_debug = EH_DEBUG ? atoi (EH_DEBUG) : 0;
|
|
|
|
|
|
|
|
/* Fetch and clear the try_bs_copy bit. */
|
|
|
|
try_bs_copy = (uint)eh_debug & try_bs_copy_mask;
|
|
|
|
eh_debug &= ~try_bs_copy_mask;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* We're called to attempt unwinding through a frame for which no unwind
|
|
|
|
info is available, typical of an operating system exception dispatcher
|
|
|
|
frame. The code below knows how to handle this case, and only this one,
|
|
|
|
returning a failure code if it finds it is not in this situation.
|
|
|
|
|
|
|
|
Note that we're called from deep down in the exception propagation call
|
|
|
|
chain, possibly below an exception dispatcher but for a frame above it
|
|
|
|
like some os entry point. */
|
|
|
|
|
|
|
|
if (eh_debug)
|
|
|
|
printf ("FALLBACK - ctxt->rp=0x%lx, sp=0x%lx, psp=0x%lx, bsp=0x%lx\n",
|
|
|
|
context->rp, context->sp, context->psp, context->bsp);
|
|
|
|
|
|
|
|
/* Step 0 :
|
|
|
|
-------------------------------------------------------------------------
|
|
|
|
VMS-unwind up until we reach a VMS dispatcher frame corresponding to the
|
|
|
|
context we are trying to unwind through. Fail if get past this context or
|
|
|
|
if we reach the bottom of stack along the way.
|
|
|
|
-------------------------------------------------------------------------
|
|
|
|
*/
|
|
|
|
|
|
|
|
status = LIB$I64_INIT_INVO_CONTEXT (icb, LIBICB$K_INVO_CONTEXT_VERSION, 0);
|
|
|
|
FAIL_IF (status == 0);
|
|
|
|
|
|
|
|
status = LIB$I64_GET_CURR_INVO_CONTEXT (icb);
|
|
|
|
|
|
|
|
/* Beware: we might be unwinding through nested condition handlers, so the
|
|
|
|
dispatcher frame we seek might not be the first one on the way up. Loop
|
|
|
|
thus. */
|
|
|
|
do {
|
|
|
|
|
|
|
|
/* Seek the next dispatcher frame up the "current" point. Stop if we
|
|
|
|
either get past the target context or hit the bottom-of-stack along
|
|
|
|
the way. */
|
|
|
|
status = LIB$I64_GET_PREV_INVO_CONTEXT (icb);
|
|
|
|
FAIL_IF (status == 0);
|
|
|
|
FAIL_IF ((uw_reg)icb->libicb$ih_sp > (uw_reg)context->psp
|
|
|
|
|| DENOTES_BOTTOM_OF_STACK (icb));
|
|
|
|
|
|
|
|
if (eh_debug)
|
|
|
|
printf ("frame%s sp @ 0x%llx, pc @ 0x%llx bsp=0x%llx\n",
|
|
|
|
DENOTES_VMS_DISPATCHER_FRAME (icb) ? " (dispatcher)" : "",
|
|
|
|
icb->libicb$ih_sp, icb->libicb$ih_pc, icb->libicb$ih_bsp);
|
|
|
|
|
|
|
|
/* Continue until the target frame is found. */
|
|
|
|
} while ((uw_reg)icb->libicb$ih_bsp != (uw_reg)context->bsp);
|
|
|
|
|
|
|
|
/* If this is not a dispatcher frame, this is certainly a frame for a leaf
|
|
|
|
subprogram. Use default unwind information. */
|
|
|
|
if (! DENOTES_VMS_DISPATCHER_FRAME (icb))
|
|
|
|
return _URC_END_OF_STACK;
|
|
|
|
|
|
|
|
/* At this point, we know we are really trying to unwind past an exception
|
|
|
|
dispatcher frame, and have it described in ICB. Proceed. */
|
|
|
|
|
|
|
|
/* Step 1 :
|
|
|
|
------------------------------------------------------------------------
|
|
|
|
We have the VMS dispatcher frame ICB handy and know we are trying to
|
|
|
|
unwind past it. Fetch pointers to useful datastructures from there, then
|
|
|
|
unwind one step further up to the interrupted user context from which
|
|
|
|
some required values will be easily accessible.
|
|
|
|
------------------------------------------------------------------------
|
|
|
|
*/
|
|
|
|
|
|
|
|
chfctx = icb->libicb$ph_chfctx_addr;
|
|
|
|
FAIL_IF (chfctx == 0);
|
|
|
|
|
|
|
|
chfmech = (CHF$MECH_ARRAY *)chfctx->chfctx$q_mcharglst;
|
|
|
|
FAIL_IF (chfmech == 0);
|
|
|
|
|
|
|
|
chfsig64 = (CHF64$SIGNAL_ARRAY *)chfmech->chf$ph_mch_sig64_addr;
|
|
|
|
FAIL_IF (chfsig64 == 0);
|
|
|
|
|
|
|
|
intstk = (INTSTK *)chfmech->chf$q_mch_esf_addr;
|
|
|
|
FAIL_IF (intstk == 0 || intstk->intstk$b_subtype == DYN$C_SSENTRY);
|
|
|
|
|
|
|
|
status = LIB$I64_GET_PREV_INVO_CONTEXT (icb);
|
|
|
|
FAIL_IF (status == 0);
|
|
|
|
|
|
|
|
if (eh_debug)
|
|
|
|
printf ("User frame, "
|
2012-03-16 11:58:28 +01:00
|
|
|
"chfmech @ 0x%p, chfsig64 @ 0x%p, intstk @ 0x%p\n",
|
|
|
|
chfmech, chfsig64, intstk);
|
2009-08-14 22:38:36 +02:00
|
|
|
|
|
|
|
/* Step 2 :
|
|
|
|
------------------------------------------------------------------------
|
|
|
|
Point the GCC context locations/values required for further unwinding at
|
|
|
|
their corresponding locations/values in the datastructures at hand.
|
|
|
|
------------------------------------------------------------------------
|
|
|
|
*/
|
|
|
|
|
|
|
|
/* Static General Register locations, including scratch registers in case
|
|
|
|
the unwinder needs to refer to a value stored in one of them. */
|
|
|
|
{
|
|
|
|
uw_reg * ctxregs = (uw_reg *)&intstk->intstk$q_regbase;
|
|
|
|
|
|
|
|
for (i = 2; i <= 3; i++)
|
|
|
|
context->ireg[i - 2].loc = (uw_loc)&ctxregs[i];
|
|
|
|
for (i = 8; i <= 11; i++)
|
|
|
|
context->ireg[i - 2].loc = (uw_loc)&ctxregs[i];
|
|
|
|
for (i = 14; i <= 31; i++)
|
|
|
|
context->ireg[i - 2].loc = (uw_loc)&ctxregs[i];
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Static Floating Point Register locations, as available from the
|
|
|
|
mechargs array, which happens to include all the to be preserved
|
|
|
|
ones + others. */
|
|
|
|
{
|
|
|
|
fp_reg * ctxregs;
|
|
|
|
|
|
|
|
ctxregs = (fp_reg *)&chfmech->chf$fh_mch_savf2;
|
|
|
|
for (i = 2; i <= 5 ; i++)
|
|
|
|
context->fr_loc[i - 2] = (uw_loc)&ctxregs[i - 2];
|
|
|
|
|
|
|
|
ctxregs = (fp_reg *)&chfmech->chf$fh_mch_savf12;
|
|
|
|
for (i = 12; i <= 31 ; i++)
|
|
|
|
context->fr_loc[i - 2] = (uw_loc)&ctxregs[i - 12];
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Relevant application register locations. */
|
|
|
|
|
|
|
|
context->fpsr_loc = (uw_loc)&intstk->intstk$q_fpsr;
|
|
|
|
context->lc_loc = (uw_loc)&intstk->intstk$q_lc;
|
|
|
|
context->unat_loc = (uw_loc)&intstk->intstk$q_unat;
|
|
|
|
|
|
|
|
/* Branch register locations. */
|
|
|
|
|
|
|
|
{
|
|
|
|
uw_reg * ctxregs = (uw_reg *)&intstk->intstk$q_b0;
|
|
|
|
|
|
|
|
for (i = 0; i < 8; i++)
|
|
|
|
context->br_loc[i] = (uw_loc)&ctxregs[i];
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Necessary register values. */
|
|
|
|
|
|
|
|
/* ??? Still unclear if we need to account for possible flushes to an
|
|
|
|
alternate backing store (maybe the unwinding performed above did the
|
|
|
|
trick already) and how this would be handled. Blind alpha tentative
|
|
|
|
below for experimentation purposes in malfunctioning cases. */
|
|
|
|
{
|
2012-03-16 11:58:28 +01:00
|
|
|
uw_reg q_bsp = (uw_reg) intstk->intstk$q_bsp;
|
|
|
|
uw_reg q_bspstore = (uw_reg) intstk->intstk$q_bspstore;
|
|
|
|
uw_reg q_bspbase = (uw_reg) intstk->intstk$q_bspbase;
|
|
|
|
uw_reg ih_bspbase = (uw_reg) icb->libicb$ih_bspbase;
|
2009-08-14 22:38:36 +02:00
|
|
|
|
|
|
|
if (eh_debug)
|
|
|
|
printf ("q_bspstore = 0x%lx, q_bsp = 0x%lx, q_bspbase = 0x%lx\n"
|
|
|
|
"ih_bspbase = 0x%lx\n",
|
|
|
|
q_bspstore, q_bsp, q_bspbase, ih_bspbase);
|
|
|
|
|
|
|
|
/* We witness many situations where q_bspbase is set while ih_bspbase is
|
|
|
|
null, and every attempt made with q_bspbase badly failed while doing
|
|
|
|
nothing resulted in proper behavior. */
|
|
|
|
if (q_bspstore < q_bsp && ih_bspbase && try_bs_copy)
|
|
|
|
{
|
2012-03-16 11:58:28 +01:00
|
|
|
uw_reg dirty_size = q_bsp - q_bspstore;
|
|
|
|
uw_reg q_rnat = (uw_reg) intstk->intstk$q_rnat;
|
2009-08-14 22:38:36 +02:00
|
|
|
|
|
|
|
if (eh_debug)
|
|
|
|
printf ("Attempting an alternate backing store copy ...\n");
|
|
|
|
|
|
|
|
ia64_copy_rbs
|
|
|
|
(context, q_bspstore, ih_bspbase, dirty_size, q_rnat);
|
|
|
|
/* Not clear if these are the proper arguments here. This is what
|
|
|
|
looked the closest to what is performed in the Linux case. */
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
context->bsp = (uw_reg)intstk->intstk$q_bsp;
|
|
|
|
fs->no_reg_stack_frame = 1;
|
|
|
|
|
|
|
|
context->pr = (uw_reg)intstk->intstk$q_preds;
|
|
|
|
context->gp = (uw_reg)intstk->intstk$q_gp;
|
|
|
|
|
|
|
|
/* We're directly setting up the "context" for a VMS exception handler.
|
|
|
|
The "previous SP" for it is the SP upon the handler's entry, that is
|
|
|
|
the SP at the condition/interruption/exception point. */
|
|
|
|
context->psp = (uw_reg)icb->libicb$ih_sp;
|
|
|
|
|
|
|
|
/* Previous Frame State location. What eventually ends up in pfs_loc is
|
|
|
|
installed with ar.pfs = pfs_loc; br.ret; so setup to target intstk->q_ifs
|
|
|
|
to have the interrupted context restored and not that of its caller if
|
|
|
|
we happen to have a handler in the interrupted context itself. */
|
|
|
|
fs->curr.reg[UNW_REG_PFS].where = UNW_WHERE_PSPREL;
|
|
|
|
fs->curr.reg[UNW_REG_PFS].val
|
|
|
|
= (uw_reg)&intstk->intstk$q_ifs - (uw_reg)context->psp;
|
|
|
|
fs->curr.reg[UNW_REG_PFS].when = -1;
|
|
|
|
|
|
|
|
/* If we need to unwind further up, past the interrupted context, we need to
|
|
|
|
hand out the interrupted context's pfs, still. */
|
|
|
|
context->signal_pfs_loc = (uw_loc) &intstk->intstk$q_pfs;
|
|
|
|
|
|
|
|
/* Finally, rules for RP . */
|
|
|
|
{
|
|
|
|
uw_reg * post_sigarray
|
|
|
|
= (uw_reg *)chfsig64 + 1 + chfsig64->chf64$l_sig_args;
|
|
|
|
|
|
|
|
uw_reg * ih_pc_loc = post_sigarray - 2;
|
|
|
|
|
|
|
|
fs->curr.reg[UNW_REG_RP].where = UNW_WHERE_PSPREL;
|
|
|
|
fs->curr.reg[UNW_REG_RP].val
|
|
|
|
= (uw_reg)ih_pc_loc - (uw_reg)context->psp;
|
|
|
|
fs->curr.reg[UNW_REG_RP].when = -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
return _URC_NO_REASON;
|
|
|
|
}
|
|
|
|
|