Пример #1
0
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);
}
Пример #2
0
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;
}
Пример #3
0
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;
}
Пример #4
0
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);
}