178 lines
5.0 KiB
C
178 lines
5.0 KiB
C
/****************************************************************
|
|
* *
|
|
* Copyright 2001, 2012 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_string.h"
|
|
|
|
#include <rtnhdr.h>
|
|
#include "stack_frame.h"
|
|
#include "stringpool.h"
|
|
#include "error_trap.h"
|
|
#include "objlabel.h"
|
|
#include "cache.h"
|
|
#include "cache_cleanup.h"
|
|
#include "mu_gv_stack_init.h"
|
|
#include "gtmimagename.h"
|
|
|
|
#include "op.h" /* for op_fntext() prototype */
|
|
|
|
GBLREF stack_frame *frame_pointer;
|
|
GBLREF stack_frame *error_frame;
|
|
GBLREF spdesc stringpool;
|
|
GBLREF dollar_ecode_type dollar_ecode; /* structure containing $ECODE related information */
|
|
GBLREF enum gtmImageTypes image_type;
|
|
|
|
void get_frame_place_mcode(int level, stack_mode_t mode, int cur_zlevel, mval *result)
|
|
{
|
|
int count;
|
|
stack_frame *fp;
|
|
unsigned char pos_str[MAX_ENTRYREF_LEN];
|
|
mval label;
|
|
mval routine;
|
|
int ips;
|
|
int offset;
|
|
int s1, s2;
|
|
boolean_t indirect_frame;
|
|
ihdtyp *irtnhdr;
|
|
cache_entry *indce;
|
|
INTPTR_T *vp;
|
|
unsigned char *fpmpc;
|
|
|
|
assert(DOLLAR_STACK_PLACE == mode || DOLLAR_STACK_MCODE == mode);
|
|
assert(0 <= level);
|
|
assert(level < cur_zlevel);
|
|
count = cur_zlevel;
|
|
for (fp = frame_pointer; ; fp = fp->old_frame_pointer)
|
|
{
|
|
if (NULL == fp->old_frame_pointer)
|
|
{
|
|
if (fp->type & SFT_TRIGR)
|
|
/* Have a trigger baseframe, pick up stack continuation frame_pointer stored by base_frame() */
|
|
fp = *(stack_frame **)(fp + 1);
|
|
else
|
|
{ /* Something wrong, just return null or assert if debug mode */
|
|
assert(FALSE);
|
|
result->str.len = 0;
|
|
return;
|
|
}
|
|
}
|
|
assert(NULL != fp);
|
|
if (!(fp->type & SFT_COUNT))
|
|
continue;
|
|
count--;
|
|
if (count == level)
|
|
break;
|
|
}
|
|
fpmpc = fp->mpc;
|
|
if (ADDR_IN_CODE(fpmpc, fp->rvector))
|
|
{
|
|
result->str.addr = (char *)&pos_str[0];
|
|
result->str.len = INTCAST(symb_line(fpmpc, &pos_str[0], 0, fp->rvector) - &pos_str[0]);
|
|
indirect_frame = FALSE;
|
|
} else
|
|
{
|
|
indirect_frame = TRUE;
|
|
pos_str[0] = '@';
|
|
result->str.addr = (char *)&pos_str[0];
|
|
result->str.len = 1;
|
|
}
|
|
if (DOLLAR_STACK_PLACE == mode)
|
|
{
|
|
if (result->str.len)
|
|
{
|
|
s2pool(&result->str);
|
|
assert(((unsigned char *)result->str.addr + result->str.len) == stringpool.free);
|
|
}
|
|
}
|
|
if (DOLLAR_STACK_MCODE == mode)
|
|
{
|
|
if (!indirect_frame)
|
|
{
|
|
if (IS_GTM_IMAGE || (0 < level))
|
|
{
|
|
label.mvtype = MV_STR;
|
|
routine.mvtype = MV_STR;
|
|
result->mvtype = MV_STR;
|
|
label.str.len = result->str.len;
|
|
label.str.addr = (char *)&pos_str[0];
|
|
routine.str.len = 0;
|
|
for (ips = 0, s1 = s2 = -1; ips < result->str.len; ips++)
|
|
{
|
|
if ('+' == pos_str[ips])
|
|
{
|
|
assert((-1 == s1) && (-1 == s2));
|
|
s1 = ips;
|
|
}
|
|
if ('^' == pos_str[ips])
|
|
{
|
|
s2 = ips;
|
|
break;
|
|
}
|
|
}
|
|
if (s2 >= 0)
|
|
{
|
|
routine.str.addr = (char *)&pos_str[s2 + 1];
|
|
routine.str.len = result->str.len - s2 - 1;
|
|
label.str.len = s2;
|
|
}
|
|
offset = 0;
|
|
if (s1 >= 0)
|
|
{
|
|
label.str.len = s1;
|
|
if (s2 < 0)
|
|
s2 = result->str.len;
|
|
for (ips = s1 + 1; ips < s2; ips++)
|
|
offset = offset * 10 + pos_str[ips] - '0';
|
|
}
|
|
op_fntext(&label, offset, &routine, result);
|
|
} else
|
|
{ /* Utility base frame does not have source code */
|
|
result->str.addr = UTIL_BASE_FRAME_CODE;
|
|
result->str.len = STRLEN(UTIL_BASE_FRAME_CODE);
|
|
}
|
|
} else
|
|
{
|
|
/* We think we are looking for an indirect invocation (mpc not in routine expected) but if the
|
|
* indirect flag is not on, then it's something else and trying to dig out indirect information
|
|
* is going to cause this process to explode. So some simple validation first and if it is not
|
|
* an indirect, deal with that fact.
|
|
*/
|
|
if (fp->flags & SFF_INDCE)
|
|
{ /* This is a real indirect - dig a bit to find the cache header and the actual code.
|
|
* Note, this code picked up from cache_cleanup(). any changes here might need to be
|
|
* reflected there.
|
|
*/
|
|
vp = (INTPTR_T *)fp->ctxt;
|
|
assert(NULL != vp);
|
|
vp--;
|
|
assertpro(((GTM_OMAGIC << 16) + OBJ_LABEL) == *vp); /* Validate backward linkage */
|
|
vp--;
|
|
irtnhdr = (ihdtyp *)((char *)vp + *vp);
|
|
indce = irtnhdr->indce;
|
|
assert(NULL != indce);
|
|
assert(0 < indce->refcnt); /* currently used in the M stack better have a non-zero refcnt */
|
|
s2pool(&indce->src.str);
|
|
result->str = indce->src.str;
|
|
assert(((unsigned char *)result->str.addr + result->str.len) == stringpool.free);
|
|
} else
|
|
{ /* Not a real indirect. The mpc may have been reset by error handling to various assembler
|
|
* routines or it just may be broken. Whatever the reason, the value to return is that the
|
|
* code address and thus the code itself is not available so make an appropriate return.
|
|
*/
|
|
result->str.addr = "N/A";
|
|
result->str.len = SIZEOF("N/A") - 1;
|
|
}
|
|
}
|
|
}
|
|
return;
|
|
}
|