1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82
|
/****************************************************************
* *
* Copyright (c) 2010-2021 Fidelity National Information *
* Services, Inc. and/or its subsidiaries. All rights reserved. *
* *
* 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"
#include <rtnhdr.h>
#include "stack_frame.h"
#include "tp_frame.h"
#include "golevel.h"
#include "dollar_zlevel.h"
#include "error.h"
GBLREF stack_frame *frame_pointer;
error_def(ERR_ZGOTOTOOBIG);
error_def(ERR_ZGOTOLTZERO);
#ifdef GTM_TRIGGER
void golevel(int4 level, boolean_t unwtrigrframe)
#else
void golevel(int4 level)
#endif
{
stack_frame *fp, *fpprev;
int4 unwframes, unwlevels, prevlvl;
if (0 > level)
RTS_ERROR_CSA_ABT(NULL, 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_CSA_ABT(NULL, 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 leaves 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;
}
|