#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: db_trace.c,v 1.13 2013/10/19 14:03:04 skrll Exp $");
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/proc.h>
#include <machine/db_machdep.h>
#include <ddb/db_access.h>
#include <ddb/db_sym.h>
#include <ddb/db_interface.h>
#include <ddb/db_proc.h>
void
db_stack_trace_print(db_expr_t addr, bool have_addr, db_expr_t count,
const char *modif, void (*pr)(const char *, ...))
{
register_t *fp, pc, rp;
#if 0
bool kernel_only = true;
#endif
bool trace_thread = false;
bool lwpaddr = false;
db_sym_t sym;
db_expr_t off;
const char *name;
const char *cp = modif;
char c;
if (count < 0)
count = 65536;
while ((c = *cp++) != 0) {
if (c == 'a') {
lwpaddr = true;
trace_thread = true;
}
if (c == 't')
trace_thread = true;
#if 0
if (c == 'u')
kernel_only = false;
#endif
}
if (!have_addr) {
fp = (register_t *)ddb_regs.tf_r3;
pc = ddb_regs.tf_iioq_head;
rp = ddb_regs.tf_rp;
} else {
if (trace_thread) {
proc_t p;
lwp_t l;
pid_t pid;
if (lwpaddr) {
db_read_bytes(addr, sizeof(l), (char *)&l);
db_read_bytes((db_addr_t)l.l_proc, sizeof(p),
(char *)&p);
(*pr)("trace: pid %d ", p.p_pid);
} else {
proc_t *pp;
pid = (pid_t)addr;
(*pr)("trace: pid %d ", pid);
pp = db_proc_find(pid);
if (pp == NULL) {
(*pr)("not found\n");
return;
}
db_read_bytes((db_addr_t)pp, sizeof(p),
(char *)&p);
addr = (db_addr_t)p.p_lwps.lh_first;
db_read_bytes(addr, sizeof(l), (char *)&l);
}
(*pr)("lid %d ", l.l_lid);
#ifdef _KERNEL
if (l.l_proc == curproc && (lwp_t *)addr == curlwp) {
fp = (int *)ddb_regs.tf_r3;
pc = ddb_regs.tf_iioq_head;
rp = ddb_regs.tf_rp;
} else
#endif
{
struct pcb *pcb = lwp_getpcb(&l);
register_t sp;
db_read_bytes((db_addr_t)&pcb->pcb_ksp,
sizeof(sp), (char *)&sp);
fp = (register_t *)(sp -
(HPPA_FRAME_SIZE + 16*4));
pc = 0;
db_read_bytes((db_addr_t)&fp[-5], sizeof(rp),
(char *)&rp);
}
(*pr)("at %p\n", fp);
} else {
pc = 0;
fp = (register_t *)addr;
db_read_bytes((db_addr_t)&fp[-5], sizeof(rp),
(char *)&rp);
}
}
while (fp && count--) {
register_t *newfp;
#ifdef DDB_DEBUG
pr(">> %08x %08x %08x\t", fp, pc, rp);
#endif
if (USERMODE(pc))
return;
if (pc) {
sym = db_search_symbol(pc, DB_STGY_ANY, &off);
db_symbol_values (sym, &name, NULL);
pr("%s() at ", name);
db_printsym(pc, DB_STGY_PROC, pr);
pr("\n");
}
db_read_bytes((db_addr_t)&fp[0], sizeof(newfp), (char *)&newfp);
if (!newfp) {
register_t scargs[5];
struct trapframe tf, *ktf;
int scoff;
scoff = HPPA_FRAME_ROUND(HPPA_FRAME_SIZE +
HPPA_FRAME_MAXARGS);
ktf = (struct trapframe *)((char *)fp - scoff -
sizeof(tf));
db_read_bytes((db_addr_t)((char *)fp - scoff),
sizeof(scargs), (char *)&scargs);
db_read_bytes((db_addr_t)ktf, sizeof(tf), (char *)&tf);
if (tf.tf_flags & TFF_SYS)
pr("-- syscall #%d(%x, %x, %x, %x, ...) (%p)\n",
tf.tf_t1, scargs[1], scargs[2],
scargs[3], scargs[4], ktf);
else
pr("-- trap #%d (%p) %s\n", tf.tf_flags & 0x3f,
ktf, (tf.tf_flags & T_USER)? " from user" :
"");
if (!(tf.tf_flags & TFF_LAST)) {
fp = (register_t *)tf.tf_r3;
pc = tf.tf_iioq_head;
rp = tf.tf_rp;
} else {
pc = 0;
fp = 0;
}
} else {
fp = newfp;
pc = rp;
db_read_bytes((db_addr_t)&fp[-5], sizeof(rp),
(char *)&rp);
}
}
if (count && pc) {
db_printsym(pc, DB_STGY_XTRN, pr);
pr(":\n");
}
}