- Add a /e option to db_stack_trace_print() which dumps the saved

registers in any trap/interrupt exception frame found.

- Slight tweak to more accurately detect the correct call-site when
  looking for a function's prologue.
This commit is contained in:
scw 2002-09-22 20:31:18 +00:00
parent 32313a3411
commit 5a529aa332
3 changed files with 114 additions and 94 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: trap.h,v 1.5 2002/09/10 11:51:01 scw Exp $ */
/* $NetBSD: trap.h,v 1.6 2002/09/22 20:31:18 scw Exp $ */
/*
* Copyright 2002 Wasabi Systems, Inc.
@ -117,6 +117,10 @@ extern void trapa(struct proc *, struct trapframe *);
extern void panic_trap(struct trapframe *, register_t, register_t,
register_t, int);
extern const char *trap_type(int);
#if defined(DIAGNOSTIC) || defined(DDB)
extern void dump_trapframe(void (*)(const char *, ...), const char *,
struct trapframe *);
#endif
extern label_t *onfault;
#endif

View File

@ -1,4 +1,4 @@
/* $NetBSD: db_trace.c,v 1.5 2002/09/19 15:47:33 scw Exp $ */
/* $NetBSD: db_trace.c,v 1.6 2002/09/22 20:31:19 scw Exp $ */
/*
* Copyright 2002 Wasabi Systems, Inc.
@ -125,12 +125,13 @@ db_stack_trace_print(db_expr_t addr, int have_addr, db_expr_t count,
db_addr_t pc, fp;
db_addr_t nextpc, nextfp;
db_sym_t sym;
db_expr_t diff;
db_expr_t diff, pc_adj;
char *symp;
int trace_thread;
int trace_thread, dump_eframe;
/* trace_thread is non-zero if tracing a specific process */
trace_thread = (strchr(modif, 't') != NULL);
dump_eframe = (strchr(modif, 'e') != NULL);
if (have_addr == 0) {
/*
@ -180,6 +181,8 @@ db_stack_trace_print(db_expr_t addr, int have_addr, db_expr_t count,
}
}
pc_adj = 0;
/*
* Walk the call stack until the PC or FP are not valid
*/
@ -189,7 +192,8 @@ db_stack_trace_print(db_expr_t addr, int have_addr, db_expr_t count,
* Lookup the name of the current function
*/
symp = NULL;
if ((sym = db_search_symbol(pc, DB_STGY_PROC, &diff)) == NULL) {
sym = db_search_symbol(pc - pc_adj, DB_STGY_PROC, &diff);
if (sym == NULL) {
(*pr)("0x%lx: Symbol not found\n");
break;
}
@ -200,27 +204,6 @@ db_stack_trace_print(db_expr_t addr, int have_addr, db_expr_t count,
break;
}
/*
* Compensate for the <handy breakpoint location after
* process "wakes"> symbol in ltsleep(), which matches
* before the real function name.
*/
if (strcmp(symp, "bpendtsleep") == 0) {
symp = NULL;
sym = db_search_symbol(pc - 4, DB_STGY_PROC, &diff);
if (sym == NULL) {
(*pr)("0x%lx: Symbol not found\n");
break;
}
symp = NULL;
db_symbol_values(sym, &symp, NULL);
if (symp == NULL) {
(*pr)("0x%lx: No symbol string found\n");
break;
}
diff += 4;
}
/*
* There's no point even trying to grovel for function
* parameters. It's just Too Much Trouble.
@ -229,7 +212,7 @@ db_stack_trace_print(db_expr_t addr, int have_addr, db_expr_t count,
* figure out what's what anyway.
*/
(*pr)("0x%lx: %s() at ", fp, symp);
db_printsym(pc, DB_STGY_PROC, pr);
db_printsym(pc - pc_adj, DB_STGY_PROC, pr);
(*pr)("\n");
/*
@ -252,12 +235,17 @@ db_stack_trace_print(db_expr_t addr, int have_addr, db_expr_t count,
pc = (db_addr_t) tf->tf_state.sf_spc & ~1;
fp = (db_addr_t) tf->tf_caller.r14;
cur_intrframe = &tf->tf_ifr;
pc_adj = 0;
(*pr)("\tTrap Type: %s\n",
trap_type((int)tf->tf_state.sf_expevt));
(*pr)("\tSSR=0x%lx, TEA=0x%lx, TRA=0x%lx\n",
(*pr)("\tSSR=0x%lx, TEA=0x%lx, TRA=0x%lx",
(long)tf->tf_state.sf_ssr,
(long)tf->tf_state.sf_tea,
(long)tf->tf_state.sf_tra);
if (dump_eframe)
dump_trapframe(pr, "\n\t", tf);
else
(*pr)("\n");
} else
if (strcmp(symp, "Lsh5_event_interrupt") == 0 ||
strcmp(symp, "Lintrexit") == 0) {
@ -271,26 +259,34 @@ db_stack_trace_print(db_expr_t addr, int have_addr, db_expr_t count,
pc = (db_addr_t) tf->if_state.sf_spc & ~1;
fp = (db_addr_t) tf->if_caller.r14;
cur_intrframe = tf;
(*pr)("\tSSR=0x%lx, INTEVT=0x%lx\n",
pc_adj = 0;
(*pr)("\tSSR=0x%lx, INTEVT=0x%lx",
(long)tf->if_state.sf_ssr,
(long)tf->if_state.sf_intevt);
if (dump_eframe) {
struct trapframe tfr;
memset(&tfr, 0, sizeof(tfr));
tfr.tf_ifr = *tf;
dump_trapframe(pr, "\n\t", &tfr);
} else
(*pr)("\n");
} else
/*
* Looks like we have to grovel the current function's
* prologue to find out the next PC and FP. Start the
* search from "PC - 4" to ensure we catch the actual
* "blink" instruction which made the call. Without this,
* we can fall foul of tail-calls and functions with
* the "__noreturn__" attribute (depending on alignment,
* we could pick up the symbol for the *next* function
* and, hence, get the wrong prologue).
* search from "PC - pc_adj" to ensure we catch the actual
* call-site. Without this, we can fall foul of tail-calls
* and functions with the "__noreturn__" attribute
* (depending on alignment, we could pick up the symbol for
* the *next* function and, hence, get the wrong prologue).
*/
if (prev_frame(fp, pc - 4, &nextfp, &nextpc) == 0) {
(*pr)("Can't find caller's stack frame.\n");
break;
} else {
if (prev_frame(fp, pc - pc_adj, &nextfp, &nextpc)) {
fp = nextfp;
pc = nextpc & ~1;
pc_adj = 4;
} else {
(*pr)("Can't find caller's stack frame.\n");
break;
}
}

View File

@ -1,4 +1,4 @@
/* $NetBSD: trap.c,v 1.12 2002/09/10 12:15:39 scw Exp $ */
/* $NetBSD: trap.c,v 1.13 2002/09/22 20:31:20 scw Exp $ */
/*
* Copyright 2002 Wasabi Systems, Inc.
@ -94,11 +94,6 @@
#include <machine/db_machdep.h>
#endif
#ifdef DIAGNOSTIC
static void dump_trapframe(struct trapframe *);
static void print_a_reg(const char *, register_t, int);
#endif
/* Used to trap faults while probing */
label_t *onfault;
@ -205,7 +200,7 @@ trap(struct proc *p, struct trapframe *tf)
kdb_trap(traptype, tf);
#else
#ifdef DIAGNOSTIC
dump_trapframe(tf);
dump_trapframe(printf, "\n", tf);
#endif
#endif
panic("trap");
@ -363,6 +358,11 @@ trap(struct proc *p, struct trapframe *tf)
case T_FPUEXC|T_USER:
sig = SIGFPE;
ucode = vaddr; /* XXX: "code" should probably be FPSCR */
#ifdef DEBUG
sh5_fpsave((u_int)tf->tf_state.sf_usr, &p->p_addr->u_pcb);
printf("trap: FPUEXC - fpscr = 0x%x\n",
(u_int)p->p_addr->u_pcb.pcb_ctx.sf_fpregs.fpscr);
#endif
break;
case T_AST|T_USER:
@ -373,14 +373,16 @@ trap(struct proc *p, struct trapframe *tf)
userret(p);
return;
#ifdef DDB
case T_NMI:
case T_NMI|T_USER:
printf("trap: NMI detected\n");
if (kdb_trap(traptype, tf))
sh5_nmi_clear();
#ifdef DDB
if (kdb_trap(traptype, tf)) {
return;
goto dopanic;
}
#endif
goto dopanic;
}
trapsignal(p, sig, ucode);
@ -435,10 +437,10 @@ trapa_panic:
p->p_pid, p->p_comm, (uintptr_t)tf->tf_caller.r15);
else
printf("curproc == NULL ");
printf("trapa: SPC=0x%lx, SSR=0x%x, TRA=0x%x\n\n",
printf("trapa: SPC=0x%lx, SSR=0x%x, TRA=0x%x\n",
(uintptr_t)tf->tf_state.sf_spc,
(u_int)tf->tf_state.sf_ssr, (u_int)tf->tf_state.sf_tra);
dump_trapframe(tf);
dump_trapframe(printf, "\n", tf);
panic(pstr);
/*NOTREACHED*/
}
@ -557,10 +559,10 @@ panic_trap(struct trapframe *tf, register_t ssr, register_t spc,
printf(" SPC: 0x%08x%08x\n",
(u_int)(excf.es_spc >> 32), (u_int)excf.es_spc);
printf(" SSR: 0x%08x\n", (u_int)excf.es_ssr);
printf(" USR: 0x%04x\n\n", (u_int)excf.es_usr);
printf(" USR: 0x%04x\n", (u_int)excf.es_usr);
#ifdef DIAGNOSTIC
dump_trapframe(tf);
dump_trapframe(printf, "\n", tf);
#endif
#ifdef DDB
kdb_trap(0, tf);
@ -618,10 +620,10 @@ panic_critical_fault(struct trapframe *tf, struct exc_scratch_frame *es,
printf(" SSR: 0x%08x\n", (u_int)excf.es_ssr);
printf(" USR: 0x%04x\n\n", (u_int)excf.es_usr);
} else
printf("exit.\nNot much to show.\n\n");
printf("exit.\nNot much to show.\n");
#ifdef DIAGNOSTIC
dump_trapframe(tf);
dump_trapframe(printf, "\n", tf);
#endif
#ifdef DDB
kdb_trap(0, tf);
@ -710,10 +712,19 @@ trap_type(int traptype)
return (t);
}
#ifdef DIAGNOSTIC
static void
dump_trapframe(struct trapframe *tf)
#if defined(DIAGNOSTIC) || defined(DDB)
void
dump_trapframe(void (*pr)(const char *, ...), const char *prefix,
struct trapframe *tf)
{
const char fmt[] = "%s=0x%08x%08x%s";
const char comma[] = ", ";
(*pr)(prefix);
#define print_a_reg(reg, v, nl) (*pr)(fmt, (reg), \
(u_int)((v) >> 32), (u_int)(v), (nl) ? prefix : comma)
print_a_reg(" r0", tf->tf_caller.r0, 0);
print_a_reg(" r1", tf->tf_caller.r1, 0);
print_a_reg(" r2", tf->tf_caller.r2, 1);
@ -746,21 +757,24 @@ dump_trapframe(struct trapframe *tf)
print_a_reg("r22", tf->tf_caller.r22, 0);
print_a_reg("r23", tf->tf_caller.r23, 1);
print_a_reg("r24", 0, 0);
print_a_reg("r24", (register_t)0, 0);
print_a_reg("r25", tf->tf_caller.r25, 0);
print_a_reg("r26", tf->tf_caller.r26, 1);
print_a_reg("r27", tf->tf_caller.r27, 0);
print_a_reg("r28", tf->tf_callee.r28, 0);
print_a_reg("r29", tf->tf_callee.r29, 1);
if (tf->tf_state.sf_flags & SF_FLAGS_CALLEE_SAVED) {
print_a_reg("r28", tf->tf_callee.r28, 0);
print_a_reg("r29", tf->tf_callee.r29, 1);
print_a_reg("r30", tf->tf_callee.r30, 0);
print_a_reg("r31", tf->tf_callee.r31, 0);
print_a_reg("r32", tf->tf_callee.r32, 1);
print_a_reg("r30", tf->tf_callee.r30, 0);
print_a_reg("r31", tf->tf_callee.r31, 0);
print_a_reg("r32", tf->tf_callee.r32, 1);
print_a_reg("r33", tf->tf_callee.r33, 0);
print_a_reg("r34", tf->tf_callee.r34, 0);
print_a_reg("r35", tf->tf_callee.r35, 1);
print_a_reg("r33", tf->tf_callee.r33, 0);
print_a_reg("r34", tf->tf_callee.r34, 0);
print_a_reg("r35", tf->tf_callee.r35, 1);
} else
(*pr)(prefix);
print_a_reg("r36", tf->tf_caller.r36, 0);
print_a_reg("r37", tf->tf_caller.r37, 0);
@ -772,51 +786,57 @@ dump_trapframe(struct trapframe *tf)
print_a_reg("r42", tf->tf_caller.r42, 0);
print_a_reg("r43", tf->tf_caller.r43, 0);
print_a_reg("r44", tf->tf_callee.r44, 1);
if (tf->tf_state.sf_flags & SF_FLAGS_CALLEE_SAVED) {
print_a_reg("r44", tf->tf_callee.r44, 1);
print_a_reg("r45", tf->tf_callee.r45, 0);
print_a_reg("r46", tf->tf_callee.r46, 0);
print_a_reg("r47", tf->tf_callee.r47, 1);
print_a_reg("r45", tf->tf_callee.r45, 0);
print_a_reg("r46", tf->tf_callee.r46, 0);
print_a_reg("r47", tf->tf_callee.r47, 1);
print_a_reg("r48", tf->tf_callee.r48, 0);
print_a_reg("r49", tf->tf_callee.r49, 0);
print_a_reg("r50", tf->tf_callee.r50, 1);
print_a_reg("r48", tf->tf_callee.r48, 0);
print_a_reg("r49", tf->tf_callee.r49, 0);
print_a_reg("r50", tf->tf_callee.r50, 1);
print_a_reg("r51", tf->tf_callee.r51, 0);
print_a_reg("r52", tf->tf_callee.r52, 0);
print_a_reg("r53", tf->tf_callee.r53, 1);
print_a_reg("r51", tf->tf_callee.r51, 0);
print_a_reg("r52", tf->tf_callee.r52, 0);
print_a_reg("r53", tf->tf_callee.r53, 1);
print_a_reg("r54", tf->tf_callee.r54, 0);
print_a_reg("r55", tf->tf_callee.r55, 0);
print_a_reg("r56", tf->tf_callee.r56, 1);
print_a_reg("r54", tf->tf_callee.r54, 0);
print_a_reg("r55", tf->tf_callee.r55, 0);
print_a_reg("r56", tf->tf_callee.r56, 1);
print_a_reg("r57", tf->tf_callee.r57, 0);
print_a_reg("r58", tf->tf_callee.r58, 0);
print_a_reg("r59", tf->tf_callee.r59, 1);
print_a_reg("r57", tf->tf_callee.r57, 0);
print_a_reg("r58", tf->tf_callee.r58, 0);
print_a_reg("r59", tf->tf_callee.r59, 1);
} else
(*pr)(prefix);
print_a_reg("r60", tf->tf_caller.r60, 0);
print_a_reg("r61", tf->tf_caller.r61, 0);
print_a_reg("r62", tf->tf_caller.r62, 1);
print_a_reg("\ntr0", tf->tf_caller.tr0, 0);
(*pr)(prefix);
print_a_reg("tr0", tf->tf_caller.tr0, 0);
print_a_reg("tr1", tf->tf_caller.tr1, 0);
print_a_reg("tr2", tf->tf_caller.tr2, 1);
print_a_reg("tr3", tf->tf_caller.tr3, 0);
print_a_reg("tr4", tf->tf_caller.tr4, 0);
print_a_reg("tr5", tf->tf_callee.tr5, 1);
if (tf->tf_state.sf_flags & SF_FLAGS_CALLEE_SAVED) {
print_a_reg("tr5", tf->tf_callee.tr5, 1);
print_a_reg("tr6", tf->tf_callee.tr6, 0);
print_a_reg("tr7", tf->tf_callee.tr7, 1);
print_a_reg("tr6", tf->tf_callee.tr6, 0);
print_a_reg("tr7", tf->tf_callee.tr7, 0);
}
(*pr)("\n");
#undef print_a_reg
}
#endif
static void
print_a_reg(const char *reg, register_t v, int nl)
{
printf("%s=0x%08x%08x%s", reg,
(u_int)(v >> 32), (u_int)v, nl ? "\n" : ", ");
}
#ifdef DIAGNOSTIC
/*
* Called from Ltrapexit in exception.S just before we restore the
* trapframe in order to verify that the trapframe is valid enough
@ -884,7 +904,7 @@ validate_trapframe(struct trapframe *tf)
boom:
printf("oops: current trapframe address: %p\n", tf);
dump_trapframe(tf);
dump_trapframe(printf, "\n", tf);
#ifdef DDB
kdb_trap(0, tf);
#endif