ack/util/int/dump.c
2019-03-17 22:46:32 +08:00

615 lines
13 KiB
C

/** @file
For dumping the stack, GDA, heap and text segment.
*/
/* $Id$ */
#include <ctype.h>
#include "em_abs.h"
#include "dump.h"
#include "logging.h"
#include "global.h"
#include "log.h"
#include "memdirect.h"
#include "mem.h"
#include "fra.h"
#include "text.h"
#include "proctab.h"
#include "shadow.h"
#include "linfil.h"
#include "rsb.h"
extern long inr; /* from log.c */
/****************************************************************
* Dumping routines for debugging, in human-readable form. *
****************************************************************/
#ifdef LOGGING
/* The file is repetitive and should probably be partly generated,
although it is not directly evident how.
*/
/* Forward declarations */
PRIVATE char *displ_undefs(int, ptr), *displ_fil(ptr), *displ_sh(char, int), *displ_code(int);
PRIVATE ptr std_raw(ptr, int), std_rsb(ptr);
PRIVATE int std_bytes(ptr, ptr, int), dtd_bytes(ptr, ptr, int), FRAd_bytes(int, int, int);
PRIVATE void std_item(ptr), std_left_undefs(int, ptr);
PRIVATE void gdad_item(ptr), gdad_left_undefs(int, ptr);
PRIVATE void hpd_item(ptr), hpd_left_undefs(int, ptr);
PRIVATE void FRA_dump(void), FRA_item(int);
/******** Stack Dump ********/
void std_all(long sz, int rawfl)
{
register ptr addr;
if (!check_log(" d1 "))
return;
LOG((" d2 "));
LOG((" d2 . . STACK_DUMP[%ld/%ld%s] . . INR = %lu . . STACK_DUMP . .",
wsize, psize, rawfl ? ", raw" : "", inr));
LOG((" d2 ----------------------------------------------------------------"));
/* find a good start address */
addr = (sz && sz < ML - SP ? SP + sz : ML);
/* find RSB backwards */
while (in_stack(addr) && !is_st_prot(addr)) {
addr++;
}
/* find end of RSB backwards */
while (in_stack(addr) && is_st_prot(addr)) {
addr++;
}
addr--;
/* dump the stack */
while (in_stack(addr)) {
addr = std_raw(addr, rawfl);
addr = std_rsb(addr);
}
FRA_dump();
LOG((" d1 >> AB = %lu, LB = %lu, SP = %lu, HP = %lu, LIN = %lu, FIL = %s",
AB, LB, SP, HP, getLIN(), displ_fil(getFIL())));
LOG((" d2 ----------------------------------------------------------------"));
LOG((" d2 "));
}
PRIVATE ptr std_raw(ptr addr, int rawfl)
{
/* Produces a formatted dump of the stack segment starting
at addr, up to the Return Status Block (identified
by protection bits)
*/
register int nundef = 0;
LOG((" d2 ADDRESS BYTE ITEM VALUE SHADOW"));
while ( in_stack(addr)
&& (!is_st_prot(addr) || rawfl)
) {
if (st_sh(addr) == UNDEFINED) {
if (nundef++ == 0)
LOG((" d2 %10lu undef", addr));
}
else {
if (nundef) {
std_left_undefs(nundef, addr + 1);
nundef = 0;
}
std_item(addr);
}
addr--;
}
if (nundef)
std_left_undefs(nundef, addr + 1);
return addr;
}
PRIVATE void std_item(ptr addr)
{
if ( is_wordaligned(addr)
&& is_in_stack(addr, psize)
&& std_bytes(addr, addr + psize, SH_DATAP|SH_INSP)
) {
/* print a pointer value */
LOG((" d2 %10lu %3lu [%10lu] (%-s)",
addr,
btol(stack_loc(addr)),
p_in_stack(addr),
displ_sh(st_sh(addr), stack_loc(addr))));
}
else
if ( is_wordaligned(addr)
&& w_is_in_stack(addr)
&& std_bytes(addr, addr + wsize, SH_INT)
) {
/* print a word value */
LOG((" d2 %10lu %3lu [%10ld] (%-s)",
addr,
btol(stack_loc(addr)),
w_in_stack(addr),
displ_sh(st_sh(addr), stack_loc(addr))));
}
else {
/* just print the byte */
LOG((" d2 %10lu %3lu (%-s)",
addr,
btol(stack_loc(addr)),
displ_sh(st_sh(addr), stack_loc(addr))));
}
}
/** Dumps the Return Status Block. */
PRIVATE ptr std_rsb(ptr addr)
{
ptr dmp_lb;
int code;
long pi;
ptr pc;
ptr lb;
long lin;
ptr fil;
char pr_descr[300];
if (!in_stack(addr))
return addr;
dmp_lb = addr - (rsbsize-1); /* pseudo local base */
if (!in_stack(dmp_lb)) {
LOG((" d1 >>RSB: >>>> INCOMPLETE <<<<"));
return dmp_lb;
}
code = (int)w_in_stack(dmp_lb + rsb_rsbcode);
pi = (long)p_in_stack(dmp_lb + rsb_PI);
pc = p_in_stack(dmp_lb + rsb_PC);
lb = p_in_stack(dmp_lb + rsb_LB);
lin = LIN_in_stack(dmp_lb + rsb_LIN);
fil = p_in_stack(dmp_lb + rsb_FIL);
if (pi == -1) {
sprintf(pr_descr, "uninit");
}
else
if (pi < NProc) {
sprintf(pr_descr, "(%ld,%ld)",
pi, (long)proctab[pi].pr_nloc);
}
else {
sprintf(pr_descr, "%ld >>>> ILLEGAL <<<<", pi);
}
LOG((" d1 >> RSB: code = %s, PI = %s, PC = %lu, LB = %lu, LIN = %lu, FIL = %s",
displ_code(code), pr_descr, pc, lb, lin, displ_fil(fil)));
LOG((" d2 "));
return addr - rsbsize;
}
PRIVATE char *displ_code(int rsbcode)
{
switch (rsbcode) {
case RSB_STP: return "STP";
case RSB_CAL: return "CAL";
case RSB_RTT: return "RTT";
case RSB_NRT: return "NRT";
default: return ">>Bad RSB code<<";
}
/*NOTREACHED*/
}
PRIVATE void std_left_undefs(int nundef, ptr addr)
{
/* handle pending undefineds */
switch (nundef) {
case 1:
break;
case 2:
LOG((" d2 %10lu undef", addr));
break;
default:
LOG((" d2 | | | | | |"));
LOG((" d2 %10lu undef (%s)",
addr, displ_undefs(nundef, addr)));
break;
}
}
PRIVATE void FRA_dump(void)
{
register int addr;
LOG((" d2 FRA: size = %d, %s",
FRASize, FRA_def ? "defined" : "undefined"));
for (addr = 0; addr < FRASize; addr++) {
FRA_item(addr);
}
}
PRIVATE void FRA_item(int addr)
{
if ( is_wordaligned(addr)
&& is_in_FRA(addr, psize)
&& FRAd_bytes(addr, (int)(addr + psize), SH_DATAP|SH_INSP)
) {
/* print a pointer value */
LOG((" d2 FRA[%1d] %3lu [%10lu] (%-s)",
addr,
btol(FRA[addr]),
p_in_FRA(addr),
displ_sh(FRA_sh[addr], FRA[addr])));
}
else
if ( is_wordaligned(addr)
&& is_in_FRA(addr, wsize)
&& FRAd_bytes(addr, (int)(addr + wsize), SH_INT)
) {
/* print a word value */
LOG((" d2 FRA[%1d] %3lu [%10ld] (%-s)",
addr,
btol(FRA[addr]),
w_in_FRA(addr),
displ_sh(FRA_sh[addr], FRA[addr])));
}
else {
/* just print the byte */
LOG((" d2 FRA[%1d] %3lu (%-s)",
addr,
btol(FRA[addr]),
displ_sh(FRA_sh[addr], FRA[addr])));
}
}
/******** Global Data Area Dump ********/
void gdad_all(ptr low, ptr high)
{
register ptr addr;
register int nundef = 0;
if (!check_log(" +1 "))
return;
if (low == 0 && high == 0)
high = HB;
LOG((" +1 "));
LOG((" +1 . . GDA_DUMP[%ld/%ld] . . INR = %lu . . GDA_DUMP . .",
wsize, psize, inr));
LOG((" +1 ----------------------------------------------------------------"));
LOG((" +1 ADDRESS BYTE WORD VALUE SHADOW"));
/* dump global data area contents */
addr = low;
while (addr < min(HB, high)) {
if (dt_sh(addr) == UNDEFINED) {
if (nundef++ == 0)
LOG((" +1 %10lu undef", addr));
}
else {
if (nundef) {
gdad_left_undefs(nundef, addr-1);
nundef = 0;
}
gdad_item(addr);
}
addr++;
}
if (nundef)
gdad_left_undefs(nundef, addr-1);
LOG((" +1 ----------------------------------------------------------------"));
LOG((" +1 "));
}
PRIVATE void gdad_item(ptr addr)
{
if ( is_wordaligned(addr)
&& is_in_data(addr, psize)
&& dtd_bytes(addr, addr + psize, SH_DATAP|SH_INSP)
) {
/* print a pointer value */
LOG((" +1 %10lu %3lu [%10lu] (%-s)",
addr,
btol(data_loc(addr)),
p_in_data(addr),
displ_sh(dt_sh(addr), data_loc(addr))));
}
else
if ( is_wordaligned(addr)
&& is_in_data(addr, wsize)
&& dtd_bytes(addr, addr + wsize, SH_INT)
) {
/* print a word value */
LOG((" +1 %10lu %3lu [%10ld] (%-s)",
addr,
btol(data_loc(addr)),
w_in_data(addr),
displ_sh(dt_sh(addr), data_loc(addr))));
}
else {
/* just print the byte */
LOG((" +1 %10lu %3lu (%-s)",
addr,
btol(data_loc(addr)),
displ_sh(dt_sh(addr), data_loc(addr))));
}
}
PRIVATE void gdad_left_undefs(int nundef, ptr addr)
{
/* handle pending undefineds */
switch (nundef) {
case 1:
break;
case 2:
LOG((" +1 %10lu undef", addr));
break;
default:
LOG((" +1 | | | | | |"));
LOG((" +1 %10lu undef (%s)",
addr, displ_undefs(nundef, addr)));
break;
}
}
/******** Heap Area Dump ********/
void hpd_all(void)
{
register ptr addr;
register int nundef = 0;
if (!check_log(" *1 "))
return;
LOG((" *1 "));
LOG((" *1 . . HEAP_DUMP[%ld/%ld] . . INR = %lu . . HEAP_DUMP . .",
wsize, psize, inr));
LOG((" *1 ----------------------------------------------------------------"));
LOG((" *1 ADDRESS BYTE WORD VALUE SHADOW"));
/* dump heap contents */
for (addr = HB; addr < HP; addr++) {
if (dt_sh(addr) == UNDEFINED) {
if (nundef++ == 0)
LOG((" *1 %10lu undef", addr));
}
else {
if (nundef) {
hpd_left_undefs(nundef, addr-1);
nundef = 0;
}
hpd_item(addr);
}
}
if (nundef)
hpd_left_undefs(nundef, addr-1);
LOG((" *1 ----------------------------------------------------------------"));
LOG((" *1 "));
}
PRIVATE void hpd_item(ptr addr)
{
if ( is_wordaligned(addr)
&& is_in_data(addr, psize)
&& dtd_bytes(addr, addr + psize, SH_DATAP|SH_INSP)
) {
/* print a pointer value */
LOG((" *1 %10lu %3lu [%10lu] (%-s)",
addr,
btol(data_loc(addr)),
p_in_data(addr),
displ_sh(dt_sh(addr), data_loc(addr))));
}
else
if ( is_wordaligned(addr)
&& is_in_data(addr, wsize)
&& dtd_bytes(addr, addr + wsize, SH_INT)
) {
/* print a word value */
LOG((" *1 %10lu %3lu [%10ld] (%-s)",
addr,
btol(data_loc(addr)),
w_in_data(addr),
displ_sh(dt_sh(addr), data_loc(addr))));
}
else {
/* just print the byte */
LOG((" *1 %10lu %3lu (%-s)",
addr,
btol(data_loc(addr)),
displ_sh(dt_sh(addr), data_loc(addr))));
}
}
PRIVATE void hpd_left_undefs(int nundef, ptr addr)
{
/* handle pending undefineds */
switch (nundef) {
case 1:
break;
case 2:
LOG((" *1 %10lu undef", addr));
break;
default:
LOG((" *1 | | | | | |"));
LOG((" *1 %10lu undef (%s)",
addr, displ_undefs(nundef, addr)));
break;
}
}
/* Service routines */
PRIVATE int std_bytes(ptr low, ptr high, int bits)
{
/* True if all stack bytes from low to high-1 have one of the
bits in bits on.
*/
int byte = bits;
while (low < high) {
byte &= st_sh(low);
low++;
}
return byte & bits;
}
PRIVATE int dtd_bytes(ptr low, ptr high, int bits)
{
/* True if all data bytes from low to high-1 have one of the
bits in bits on.
*/
int byte = bits;
while (low < high) {
byte &= dt_sh(low);
low++;
}
return byte & bits;
}
PRIVATE int FRAd_bytes(int low, int high, int bits)
{
/* True if all data bytes from low to high-1 have one of the
bits in bits on.
*/
int byte = bits;
while (low < high) {
byte &= FRA_sh[low];
low++;
}
return byte & bits;
}
PRIVATE char *displ_undefs(int nundef, ptr addr)
{
/* Given the number of undefineds, we want to report the number
of words with the left-over numbers of bytes on both sides:
| nundef |
|left| wrds |right
.....|........|........|........|...
a
d
d
r
This takes some arithmetic.
*/
static char buf[30];
register int left = wsize - 1 - p2i(addr-1) % wsize;
register int wrds = (nundef-left) / wsize;
register int right = nundef - left - wrds*wsize;
if (wrds == 0) {
sprintf(buf, "%d byte%s",
nundef, nundef == 1 ? "" : "s");
}
else if (left == 0 && right == 0) {
sprintf(buf, "%d word%s",
wrds, wrds == 1 ? "" : "s");
}
else if (left == 0) {
sprintf(buf, "%d word%s + %d byte%s",
wrds, wrds == 1 ? "" : "s",
right, right == 1 ? "" : "s");
}
else if (right == 0) {
sprintf(buf, "%d byte%s + %d word%s",
left, left == 1 ? "" : "s",
wrds, wrds == 1 ? "" : "s");
}
else {
sprintf(buf, "%d byte%s + %d word%s + %d byte%s",
left, left == 1 ? "" : "s",
wrds, wrds == 1 ? "" : "s",
right, right == 1 ? "" : "s");
}
return buf;
}
PRIVATE char *displ_fil(ptr fil)
{ /* Returns a buffer containing a representation of the
filename derived from FIL-value fil.
*/
static char buf[40];
char *bp = &buf[0];
int ch;
if (!fil)
return "NULL";
if (fil >= HB)
return "***NOT IN GDA***";
*bp++ = '"';
while (in_gda(fil) && (ch = data_loc(fil))) {
if (bp < &buf[sizeof buf-1]) {
*bp++ = (ch < 040 || ch > 126 ? '?' : ch);
}
fil++;
}
if (bp < &buf[sizeof buf-1])
*bp++ = '"';
*bp++ = '\0';
return &buf[0];
}
PRIVATE char *displ_sh(char shadow, int byte)
{ /* Returns a buffer containing a description of the
shadow byte.
*/
static char buf[32];
register char *bufp;
int check = 0;
bufp = buf;
if (shadow & SH_INT) {
*bufp++ = 'I';
*bufp++ = 'n';
check++;
}
if (shadow & SH_FLOAT) {
*bufp++ = 'F';
*bufp++ = 'l';
}
if (shadow & SH_DATAP) {
*bufp++ = 'D';
*bufp++ = 'p';
}
if (shadow & SH_INSP) {
*bufp++ = 'I';
*bufp++ = 'p';
}
if (shadow & SH_PROT) {
*bufp++ = ',';
*bufp++ = ' ';
*bufp++ = 'P';
*bufp++ = 'r';
*bufp++ = 'o';
*bufp++ = 't';
}
if (check && isascii(byte) && isprint(byte)) {
*bufp++ = ',';
*bufp++ = ' ';
*bufp++ = byte;
*bufp++ = ' ';
}
*bufp = 0;
return (buf);
}
#endif /* LOGGING */