- 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:
parent
32313a3411
commit
5a529aa332
@ -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
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user