static void unwind_regular_code (frame_state_t * fs) { PDSCDEF * pv = PV_FOR (fs->fp); ADDR frame_base; /* Use the procedure value to unwind, in a way depending on the kind of procedure at hand. See ABI-3.3 [Procedure Representation] and ABI-3.4 [Procedure Types]. */ if (pv == 0 || pv->pdsc$w_flags & PDSC$M_BASE_FRAME) return; frame_base = (pv->pdsc$w_flags & PDSC$M_BASE_REG_IS_FP) ? fs->fp : fs->sp; switch (pv->pdsc$w_flags & 0xf) { case PDSC$K_KIND_FP_STACK: /* Stack Frame Procedure (ABI-3.4.1). Retrieve the necessary registers from the Register Save Area in the frame. */ { ADDR rsa_base = frame_base + pv->pdsc$w_rsa_offset; int i, j; fs->saved_rar = REG_AT (rsa_base); fs->saved_pvr = REG_AT (frame_base); for (i = 0, j = 0; i < 32; i++) if (pv->pdsc$l_ireg_mask & (1 << i)) fs->saved_regs[i] = REG_AT (rsa_base + 8 * ++j); /* Note that the loop above is guaranteed to set fs->saved_fpr, because "The preserved register set must always include R29(FP) since it will always be used." (ABI-3.4.3.4 [Register Save Area for All Stack Frames]). Also note that we need to run through all the registers to ensure that unwinding through register procedures (see below) gets the right values out of the saved_regs array. */ } break; case PDSC$K_KIND_FP_REGISTER: /* Register Procedure (ABI-3.4.4). Retrieve the necessary registers from the registers where they have been saved. */ { fs->saved_rar = fs->saved_regs[pv->pdsc$b_save_ra]; fs->saved_fpr = fs->saved_regs[pv->pdsc$b_save_fp]; } break; default: /* ??? Are we supposed to ever get here ? Don't think so. */ break; } /* SP is actually never part of the saved registers area, so we use the corresponding entry in the saved_regs array to manually keep track of it's evolution. */ fs->saved_spr = AS_REG (frame_base) + pv->pdsc$l_size; }
static void unwind_kernel_handler (frame_state_t * fs) { PDSCDEF * pv = PV_FOR (fs->fp); CHFDEF1 *sigargs; CHFDEF2 *mechargs; /* Retrieve the arguments passed to the handler, by way of a VMS service providing the corresponding "Invocation Context Block". */ { long handler_ivhandle; INVO_CONTEXT_BLK handler_ivcb; CHFCTX *chfctx; handler_ivcb.libicb$q_ireg [29] = AS_REG (fs->fp); handler_ivcb.libicb$q_ireg [30] = 0; handler_ivhandle = LIB$GET_INVO_HANDLE (&handler_ivcb); if ((LIB$GET_INVO_CONTEXT (handler_ivhandle, &handler_ivcb) & 1) != 1) return; chfctx = (CHFCTX *) AS_ADDR (handler_ivcb.libicb$ph_chfctx_addr); sigargs = (CHFDEF1 *) AS_ADDR (chfctx->chfctx$q_sigarglst); mechargs = (CHFDEF2 *) AS_ADDR (chfctx->chfctx$q_mcharglst); } /* Compute the saved return address as the PC of the instruction causing the condition, accounting for the fact that it will be adjusted by the next call to "unwind" as if it was an actual call return address. */ { /* ABI-6.5.1.1 [Signal Argument Vector]: The signal occurrence address is available from the sigargs argument to the handler, designed to support both 32 and 64 bit addresses. The initial reference we get is a pointer to the 32bit form, from which one may extract a pointer to the 64bit version if need be. We work directly from the 32bit form here. */ /* The sigargs vector structure for 32bits addresses is: <......32bit......> +-----------------+ | Vsize | :chf$is_sig_args +-----------------+ -+- | Condition Value | : [0] +-----------------+ : | ... | : +-----------------+ : vector of Vsize entries | Signal PC | : +-----------------+ : | PS | : [Vsize - 1] +-----------------+ -+- */ unsigned long * sigargs_vector = ((unsigned long *) (&sigargs->chf$is_sig_args)) + 1; long sigargs_vsize = sigargs->chf$is_sig_args; fs->saved_rar = (REG) sigargs_vector [sigargs_vsize - 2] + PC_ADJUST; } fs->saved_spr = RA_UNKNOWN; fs->saved_fpr = (REG) mechargs->chf$q_mch_frame; fs->saved_pvr = (REG) mechargs->chf$q_mch_savr27; fs->saved_regs[16] = (REG) mechargs->chf$q_mch_savr16; fs->saved_regs[17] = (REG) mechargs->chf$q_mch_savr17; fs->saved_regs[18] = (REG) mechargs->chf$q_mch_savr18; fs->saved_regs[19] = (REG) mechargs->chf$q_mch_savr19; fs->saved_regs[20] = (REG) mechargs->chf$q_mch_savr20; }