2012-02-05 11:35:58 -05:00
|
|
|
/****************************************************************
|
|
|
|
* *
|
|
|
|
* Copyright 2010, 2011 Fidelity Information Services, Inc *
|
|
|
|
* *
|
|
|
|
* This source code contains the intellectual property *
|
|
|
|
* of its copyright holder(s), and is made available *
|
|
|
|
* under a license. If you do not know the terms of *
|
|
|
|
* the license, please stop and do not read further. *
|
|
|
|
* *
|
|
|
|
****************************************************************/
|
|
|
|
|
|
|
|
#include "mdef.h"
|
|
|
|
|
|
|
|
#include "gtm_stdio.h"
|
|
|
|
|
2012-06-14 08:55:06 -04:00
|
|
|
#include <rtnhdr.h>
|
2012-02-05 11:35:58 -05:00
|
|
|
#include "stack_frame.h"
|
|
|
|
#include "tp_frame.h"
|
|
|
|
#include "golevel.h"
|
|
|
|
#include "dollar_zlevel.h"
|
|
|
|
#include "error.h"
|
|
|
|
|
|
|
|
GBLREF stack_frame *frame_pointer;
|
|
|
|
|
|
|
|
#ifdef GTM_TRIGGER
|
|
|
|
void golevel(int4 level, boolean_t unwtrigrframe)
|
|
|
|
#else
|
|
|
|
void golevel(int4 level)
|
|
|
|
#endif
|
|
|
|
{
|
|
|
|
stack_frame *fp, *fpprev;
|
|
|
|
int4 unwframes, unwlevels, prevlvl;
|
|
|
|
|
|
|
|
error_def(ERR_ZGOTOTOOBIG);
|
|
|
|
error_def(ERR_ZGOTOLTZERO);
|
|
|
|
|
|
|
|
if (0 > level)
|
|
|
|
rts_error(VARLSTCNT(1) ERR_ZGOTOLTZERO);
|
|
|
|
unwlevels = dollar_zlevel() - level;
|
|
|
|
if (0 > unwlevels)
|
|
|
|
/* Couldn't get to the level we were trying to unwind to */
|
|
|
|
rts_error(VARLSTCNT(1) ERR_ZGOTOTOOBIG);
|
|
|
|
unwframes = 0;
|
|
|
|
for (fp = frame_pointer; NULL != fp; fp = fpprev)
|
|
|
|
{
|
|
|
|
assert(0 <= unwlevels);
|
|
|
|
fpprev = fp->old_frame_pointer;
|
|
|
|
if (NULL == fpprev GTMTRIG_ONLY( && !(SFT_TRIGR & fp->type)))
|
|
|
|
break; /* break on base frame not trigger related */
|
|
|
|
# ifdef GTM_TRIGGER
|
|
|
|
/* Break if level reached -- note trigger base frame is type=counted but is not counted as
|
|
|
|
* part of level our count is not decremented on a trigger base frame.
|
|
|
|
*/
|
|
|
|
if (SFT_COUNT & fp->type)
|
|
|
|
{
|
|
|
|
if (0 == unwlevels)
|
|
|
|
break; /* break on reaching target level with a counted frame */
|
|
|
|
if (!(SFT_TRIGR & fp->type))
|
|
|
|
unwlevels--;
|
|
|
|
}
|
|
|
|
unwframes++;
|
|
|
|
if (SFT_TRIGR & fp->type)
|
|
|
|
{ /* Unwinding a trigger base frame leave a null frame_pointer so allow us to jump over the
|
|
|
|
* base frame to the rich stack beneath..
|
|
|
|
*/
|
|
|
|
assert(NULL == fpprev);
|
|
|
|
fpprev = *(stack_frame **)(fp + 1);
|
|
|
|
assert(NULL != fpprev);
|
|
|
|
}
|
|
|
|
# else
|
|
|
|
if ((SFT_COUNT & fp->type) && (0 == unwlevels--))
|
|
|
|
break; /* break on reaching target level with a counted frame */
|
|
|
|
unwframes++;
|
|
|
|
# endif
|
|
|
|
}
|
|
|
|
DBGEHND_ONLY(prevlvl = dollar_zlevel());
|
|
|
|
GOFRAMES(unwframes, unwtrigrframe, FALSE);
|
|
|
|
DBGEHND((stderr, "golevel: Unwound from level %d to level %d which is %d frames ending in stackframe 0x"lvaddr" with"
|
|
|
|
" type 0x%04lx\n", prevlvl, level, unwframes, frame_pointer, (frame_pointer ? frame_pointer->type : 0xffff)));
|
|
|
|
return;
|
|
|
|
}
|