bool unwind_nocounts(void) { short unwind; bool dmode; stack_frame *fp; boolean_t sf_error_ret = FALSE; dmode = FALSE; unwind = 0; /* while unwinding uncounted frames, reset "error_frame" to point to the counted frame in case error_frame happens to be * one of the to-be-unwound uncounted frames so we remember to do error_ret() processing (if applicable) * while "op_unwind()"ing the counted frame. */ for (fp = frame_pointer; !(fp->type & SFT_COUNT) && fp->old_frame_pointer; fp = fp->old_frame_pointer) { if (error_frame == fp) { SET_ERROR_FRAME(fp->old_frame_pointer); assert(NULL != error_frame); } if (fp->type & SFT_DM) dmode = TRUE; unwind++; } if (tp_pointer && tp_pointer->fp < fp) rts_error(VARLSTCNT(1) ERR_TPQUIT); while (unwind-- > 0) { assert(error_frame != frame_pointer); /* make sure op_unwind() won't call error_ret() */ op_unwind(); } return(dmode); }
void goerrorframe() { stack_frame *fp; int4 unwind; for (unwind = 0, fp = frame_pointer; fp < error_frame; fp = fp->old_frame_pointer) unwind++; assert(fp == error_frame); goframes(unwind); assert(error_frame == frame_pointer); /* Now that we (the caller mdb_condition_handler) are going to rethrow an error, ensure that the * SFF_ETRAP_ERR bit is set in "error_frame" in case it got reset by flush_jmp. */ SET_ERROR_FRAME(error_frame); assert(error_frame->flags & SFF_ETRAP_ERR); return; }
void trans_code(void) { mval dummy; int level2go; DCL_THREADGBL_ACCESS; SETUP_THREADGBL_ACCESS; if (SFT_ZINTR & proc_act_type) { /* Need different translator EP */ jobinterrupt_process(); return; } assert(err_act); if (stringpool.base != rts_stringpool.base) stringpool = rts_stringpool; assert(SFT_ZTRAP == proc_act_type || SFT_DEV_ACT == proc_act_type); /* The frame_pointer->mpc of error-causing M routine should always be set * to 'error_return' irrespective of the validity of $etrap code to make sure * the error-occuring frame is always unwound and the new error is rethrown * at one level below */ if (IS_ETRAP) SET_ERROR_FRAME(frame_pointer); /* reset error_frame to point to frame_pointer */ if (!(ztrap_form & ZTRAP_CODE) && !IS_ETRAP && POP_SPECIFIED) { GOLEVEL(level2go, TRUE); } dummy.mvtype = MV_STR; dummy.str = *err_act; TREF(trans_code_pop) = push_mval(&dummy); ESTABLISH(trans_code_ch); op_commarg(TREF(trans_code_pop), ((ztrap_form & ZTRAP_CODE) || IS_ETRAP) ? indir_linetail : indir_goto); REVERT; # ifdef UNIX if (NULL != gtm_err_dev) { remove_rms(gtm_err_dev); gtm_err_dev = NULL; } # endif trans_code_finish(); return; }
void trans_code_cleanup(void) { stack_frame *fp, *fpprev; uint4 errmsg; DCL_THREADGBL_ACCESS; SETUP_THREADGBL_ACCESS; assert(!(SFT_ZINTR & proc_act_type)); /* With no extra ztrap frame being pushed onto stack, we may miss error(s) * during trans_code if we don't check proc_act_type in addition to * frame_pointer->type below. */ if (SFT_ZTRAP == proc_act_type) { if (0 < dollar_ztrap.str.len) errmsg = ERR_ERRWZTRAP; else errmsg = ERR_ERRWETRAP; } else if (SFT_DEV_ACT == proc_act_type) errmsg = ERR_ERRWIOEXC; else errmsg = 0; proc_act_type = 0; if (TREF(compile_time)) { TREF(compile_time) = FALSE; if (stringpool.base != rts_stringpool.base) stringpool = rts_stringpool; } for (fp = frame_pointer; fp; fp = fpprev) { fpprev = fp->old_frame_pointer; # ifdef GTM_TRIGGER if (SFT_TRIGR & fpprev->type) fpprev = *(stack_frame **)(fpprev + 1); # endif if (fp->type & SFT_DM) break; if (fp->type & SFT_COUNT) { if ((ERR_ERRWZTRAP == errmsg) || (ERR_ERRWETRAP == errmsg)) { /* Whether ETRAP or ZTRAP we want to rethrow the error at one level down */ SET_ERROR_FRAME(fp); /* reset error_frame to point to the closest counted frame */ assert(fp->flags & SFF_ETRAP_ERR); /* Turn off any device exception related flags now that we are going to handle errors using * $ETRAP or $ZTRAP AT THE PARENT LEVEL only (no more device exceptions). */ dollar_ztrap.str.len = 0; ztrap_explicit_null = FALSE; fp->flags &= SFF_DEV_ACT_ERR_OFF; fp->flags &= SFF_ZTRAP_ERR_OFF; err_act = &dollar_etrap.str; break; } else if (ERR_ERRWIOEXC == errmsg) { /* Error while compiling device exception. Set SFF_ETRAP_ERR bit so control is transferred to * error_return() which in turn will rethrow the error AT THE SAME LEVEL in order to try and * use $ZTRAP or $ETRAP whichever is active. Also set the SFF_DEV_ACT_ERR bit to signify this * is a device exception that is rethrown instead of a ztrap/etrap error. Also assert that * the rethrow will not use IO exception again (thereby ensuring error processing will * eventually terminate instead of indefinitely recursing). */ fp->flags |= (SFF_DEV_ACT_ERR | SFF_ETRAP_ERR); assert(NULL == active_device); /* mdb_condition_handler should have reset it */ break; } else if ((ERR_ERRWZBRK == errmsg) || (ERR_ERRWEXC == errmsg)) { /* For typical exceptions in ZBREAK and ZSTEP, get back to direct mode */ dm_setup(); break; } else { /* The only known way to be here is if the command is a command given in direct mode as * mdb_condition_handler won't drive an error handler in that case which would be caught in * one of the above conditions. Not breaking out of the loop here means the frame will just * unwind and we'll break on the direct mode frame which will be redriven. If the parent frame * is not a direct mode frame, we'll assert in debug or break in pro and just continue. * to direct mode. */ assert(fp->flags && (SFF_INDCE)); if (!fp->old_frame_pointer || !(fp->old_frame_pointer->type & SFT_DM)) { assert(FALSE); break; } } } if (fp->type) { SET_ERR_CODE(fp, errmsg); } /* If this frame is indicated for cache cleanup, do that cleanup * now before we get rid of the pointers used by that cleanup. */ IF_INDR_FRAME_CLEANUP_CACHE_ENTRY_AND_UNMARK(fp); fp->mpc = CODE_ADDRESS(pseudo_ret); fp->ctxt = GTM_CONTEXT(pseudo_ret); fp->flags &= SFF_IMPLTSTART_CALLD_OFF; /* Frame enterable now with mpc reset */ GTMTRIG_ONLY(DBGTRIGR((stderr, "trans_code_cleanup: turning off SFF_IMPLTSTART_CALLD in frame 0x"lvaddr"\n", frame_pointer))); } TREF(transform) = TRUE; if (0 != errmsg) dec_err(VARLSTCNT(1) errmsg); }