118 lines
3.9 KiB
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;
|
|
}
|