#include <sys/param.h>
#include <sys/systm.h>
#include <uvm/uvm_extern.h>
#include <machine/db_machdep.h>
#include <machine/frame.h>
#include <ddb/db_access.h>
#include <ddb/db_command.h>
#include <ddb/db_output.h>
#include <ddb/db_sym.h>
#include <ddb/db_variables.h>
#include <ddb/db_extern.h>
#include <ddb/db_interface.h>
extern int etext;
struct opcode opcode[] = {
{ OPC_PAL, "call_pal", 0 },
{ OPC_RES, "opc01", 0 },
{ OPC_RES, "opc02", 0 },
{ OPC_RES, "opc03", 0 },
{ OPC_RES, "opc04", 0 },
{ OPC_RES, "opc05", 0 },
{ OPC_RES, "opc06", 0 },
{ OPC_RES, "opc07", 0 },
{ OPC_MEM, "lda", 1 },
{ OPC_MEM, "ldah", 1 },
{ OPC_RES, "opc0a", 0 },
{ OPC_MEM, "ldq_u", 1 },
{ OPC_RES, "opc0c", 0 },
{ OPC_RES, "opc0d", 0 },
{ OPC_RES, "opc0e", 0 },
{ OPC_MEM, "stq_u", 1 },
{ OPC_OP, "inta", 0 },
{ OPC_OP, "intl", 0 },
{ OPC_OP, "ints", 0 },
{ OPC_OP, "intm", 0 },
{ OPC_RES, "opc14", 0 },
{ OPC_OP, "fltv", 1 },
{ OPC_OP, "flti", 1 },
{ OPC_OP, "fltl", 1 },
{ OPC_MEM, "misc", 0 },
{ OPC_PAL, "pal19", 0 },
{ OPC_MEM, "jsr", 0 },
{ OPC_PAL, "pal1b", 0 },
{ OPC_RES, "opc1c", 0 },
{ OPC_PAL, "pal1d", 0 },
{ OPC_PAL, "pal1e", 0 },
{ OPC_PAL, "pal1f", 0 },
{ OPC_MEM, "ldf", 1 },
{ OPC_MEM, "ldg", 1 },
{ OPC_MEM, "lds", 1 },
{ OPC_MEM, "ldt", 1 },
{ OPC_MEM, "stf", 1 },
{ OPC_MEM, "stg", 1 },
{ OPC_MEM, "sts", 1 },
{ OPC_MEM, "stt", 1 },
{ OPC_MEM, "ldl", 1 },
{ OPC_MEM, "ldq", 1 },
{ OPC_MEM, "ldl_l", 1 },
{ OPC_MEM, "ldq_l", 1 },
{ OPC_MEM, "stl", 1 },
{ OPC_MEM, "stq", 1 },
{ OPC_MEM, "stl_c", 1 },
{ OPC_MEM, "stq_c", 1 },
{ OPC_BR, "br", 1 },
{ OPC_BR, "fbeq", 1 },
{ OPC_BR, "fblt", 1 },
{ OPC_BR, "fble", 1 },
{ OPC_BR, "bsr", 1 },
{ OPC_BR, "fbne", 1 },
{ OPC_BR, "fbge", 1 },
{ OPC_BR, "fbgt", 1 },
{ OPC_BR, "blbc", 1 },
{ OPC_BR, "beq", 1 },
{ OPC_BR, "blt", 1 },
{ OPC_BR, "ble", 1 },
{ OPC_BR, "blbs", 1 },
{ OPC_BR, "bne", 1 },
{ OPC_BR, "bge", 1 },
{ OPC_BR, "bgt", 1 },
};
static __inline int sext(u_int);
static __inline int rega(u_int);
static __inline int regb(u_int);
static __inline int regc(u_int);
static __inline int disp(u_int);
static __inline int
sext(u_int x)
{
return ((x & 0x8000) ? -(-x & 0xffff) : (x & 0xffff));
}
static __inline int
rega(u_int x)
{
return ((x >> 21) & 0x1f);
}
static __inline int
regb(u_int x)
{
return ((x >> 16) & 0x1f);
}
static __inline int
regc(u_int x)
{
return (x & 0x1f);
}
static __inline int
disp(u_int x)
{
return (sext(x & 0xffff));
}
void
db_stack_trace_print(db_expr_t addr, int have_addr, db_expr_t count,
char *modif, int (*pr)(const char *, ...))
{
u_long *frame;
int i, framesize;
vaddr_t pc, ra;
u_int inst;
const char *name;
db_expr_t offset;
db_regs_t *regs;
u_long *slot[32];
bzero(slot, sizeof(slot));
if (count == -1)
count = 65535;
if (have_addr) {
(*pr)("alpha trace requires a trap frame... giving up.\n");
return;
}
regs = &ddb_regs;
trapframe:
for (i = 0; i < 31; i++)
slot[i] = ®s->tf_regs[0] +
((u_long *)db_regs[i].valuep - &ddb_regs.tf_regs[0]);
frame = (u_long *)regs->tf_regs[FRAME_SP];
pc = (vaddr_t)regs->tf_regs[FRAME_PC];
ra = (vaddr_t)regs->tf_regs[FRAME_RA];
while (count-- && pc >= (vaddr_t)KERNBASE && pc < (vaddr_t)&etext) {
db_find_sym_and_offset(pc, &name, &offset);
if (name == NULL) {
(*pr)("%lx(", pc);
offset = 65536;
} else {
(*pr)("%s(", name);
}
framesize = 0;
for (i = sizeof (int); i <= offset; i += sizeof (int)) {
inst = *(u_int *)(pc - i);
if (name[0] == '?' && inst_return(inst))
break;
if ((inst & 0xffff0000) == 0x23de0000)
framesize -= disp(inst) / sizeof (u_long);
else if ((inst & 0xfc1f0000) == 0xb41e0000)
slot[rega(inst)] =
frame + disp(inst) / sizeof (u_long);
else if ((inst & 0xfc000fe0) == 0x44000400 &&
rega(inst) == regb(inst)) {
if (rega(inst) != 31)
slot[rega(inst)] = slot[regc(inst)];
slot[regc(inst)] = 0;
} else if (db_inst_load(inst))
slot[rega(inst)] = 0;
else if (opcode[inst >> 26].opc_fmt == OPC_OP)
slot[regc(inst)] = 0;
}
for (i = 0; i < 6; i++) {
if (i > 0)
(*pr)(", ");
if (slot[16 + i])
(*pr)("%lx", *slot[16 + i]);
else
(*pr)("?");
}
#if 0
(*pr)(") [%p: ", frame);
if (framesize > 1) {
for (i = 0; i < framesize - 1; i++)
(*pr)("%lx, ", frame[i]);
(*pr)("%lx", frame[i]);
}
(*pr)("] at ");
#else
(*pr)(") at ");
#endif
db_printsym(pc, DB_STGY_PROC, pr);
(*pr)("\n");
if (strncmp(name, "Xent", sizeof("Xent") - 1) == 0) {
regs = (db_regs_t *)frame;
goto trapframe;
}
if (slot[26])
ra = *(vaddr_t *)slot[26];
else
break;
frame += framesize;
if (ra == pc)
break;
pc = ra;
}
}