fis-gtm/sr_port/symb_line.c

118 lines
3.9 KiB
C

/****************************************************************
* *
* Copyright 2001, 2010 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"
#define OFFSET_LEN 5
GBLREF unsigned char *stackbase, *stacktop;
GBLREF unsigned short proc_act_type;
GBLREF mstr *err_act;
GBLREF mval dollar_ztrap;
unsigned char *symb_line(unsigned char *in_addr, unsigned char *out, unsigned char **b_line, rhdtyp *routine)
{
unsigned char temp[OFFSET_LEN], *adjusted_in_addr;
lab_tabent *max_label, *label_table, *last_label;
lnr_tabent *line_table, *last_line;
int4 len, ct, offset, in_addr_offset;
boolean_t mpc_reset_to_linestart;
if (!ADDR_IN_CODE(in_addr, routine))
return out;
routine = CURRENT_RHEAD_ADR(routine);
USHBIN_ONLY(
assert(routine->labtab_adr);
assert(routine->lnrtab_adr);
);
NON_USHBIN_ONLY(
assert(routine->labtab_ptr >= 0);
assert(routine->lnrtab_ptr >= 0);
);
assert(routine->labtab_len >= 0);
assert(routine->lnrtab_len >= 0);
if ((SFT_DEV_ACT == proc_act_type) || ((SFT_ZTRAP == proc_act_type) && (err_act == &dollar_ztrap.str)))
{ /* This means we got an error while trying to compile the device-exception or ZTRAP string as
* part of handling yet another primary error. The primary error would have reset fp->mpc to
* the beginning of the line so note this down.
*/
mpc_reset_to_linestart = TRUE;
} else
mpc_reset_to_linestart = FALSE;
label_table = LABTAB_ADR(routine);
last_label = label_table + routine->labtab_len;
max_label = label_table++;
adjusted_in_addr = in_addr + (mpc_reset_to_linestart ? 1 : 0);
while (label_table < last_label)
{ /* Label table entries are sorted by label name (for faster lookup by indirects using op_labaddr) so we
* scan to find all of the label addresses that meet our specification (adjusted addr > label address) and
* keep the one with the lowest linenumber offset. This means we have to go through all of them rather than
* stop at the first label meeting our address criteria but this is not a high-use module so it is ok.
*/
if (adjusted_in_addr > LABEL_ADDR(routine, label_table))
{ /* Now check if this label is a keeper by checking for minimum LNR_OFFSET */
if (max_label->LABENT_LNR_OFFSET <= label_table->LABENT_LNR_OFFSET)
max_label = label_table;
}
label_table++;
}
line_table = LABENT_LNR_ENTRY(routine, max_label);
len = max_label->lab_name.len;
if (len)
{
memcpy(out, max_label->lab_name.addr, len);
out += len;
}
offset = 0;
in_addr_offset = (int4)(adjusted_in_addr - CODE_BASE_ADDR(routine));
last_line = LNRTAB_ADR(routine);
last_line += routine->lnrtab_len;
for ( ; ++line_table < last_line ; offset++)
{ /* Find first line that is >= input addr. The previous line is the target line.
* In addition, ensure we never return NULL label and ZERO offset i.e. no ^MODULENAME.
* Line #s start at 1 so in this case, return +1^MODULENAME.
* The "(offset || len)" check below takes care of this.
*/
if ((in_addr_offset <= *line_table) && (offset || len))
{
if (b_line)
*b_line = LINE_NUMBER_ADDR(routine, (line_table - 1));
break;
}
}
if (line_table >= last_line && b_line)
*b_line = LINE_NUMBER_ADDR(routine, (line_table - 1));
if (offset)
{
*out++ = '+';
ct = OFFSET_LEN;
for ( ; ct > 0 ; )
{
temp[--ct] = (offset % 10) + '0';
if ((offset /= 10) == 0)
break;
}
len = OFFSET_LEN - ct;
memcpy (out, &temp[ct], len);
out += len;
}
*out++ = '^';
len = routine->routine_name.len;
memcpy(out, routine->routine_name.addr, len);
out += len;
return out;
}