Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys/arch/sh3/sh3 fix backtrace. it was broken.
details: https://anonhg.NetBSD.org/src/rev/5b769850b1ec
branches: trunk
changeset: 841348:5b769850b1ec
user: ryo <ryo%NetBSD.org@localhost>
date: Thu May 09 16:48:31 2019 +0000
description:
fix backtrace. it was broken.
- use db_read_bytes() to avoid faults.
- quite a few functions do not use frame pointers,
therefore always detect stack depth without a frame pointer.
however, since the framepointer(=r14) is used as a trapframe,
the code to detect the frame pointer is still needed.
- dump the contents of trapframe during backtracing.
- KNF
diffstat:
sys/arch/sh3/sh3/db_trace.c | 294 ++++++++++++++++++++++++++++---------------
1 files changed, 192 insertions(+), 102 deletions(-)
diffs (truncated from 428 to 300 lines):
diff -r ac08d8faa500 -r 5b769850b1ec sys/arch/sh3/sh3/db_trace.c
--- a/sys/arch/sh3/sh3/db_trace.c Thu May 09 15:48:55 2019 +0000
+++ b/sys/arch/sh3/sh3/db_trace.c Thu May 09 16:48:31 2019 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: db_trace.c,v 1.25 2013/11/09 02:23:57 christos Exp $ */
+/* $NetBSD: db_trace.c,v 1.26 2019/05/09 16:48:31 ryo Exp $ */
/*-
* Copyright (c) 2000 Tsubai Masanari. All rights reserved.
@@ -27,7 +27,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: db_trace.c,v 1.25 2013/11/09 02:23:57 christos Exp $");
+__KERNEL_RCSID(0, "$NetBSD: db_trace.c,v 1.26 2019/05/09 16:48:31 ryo Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@@ -37,16 +37,21 @@
#include <ddb/db_access.h>
#include <ddb/db_interface.h>
#include <ddb/db_output.h>
+#include <ddb/db_proc.h>
#include <ddb/db_sym.h>
#include <ddb/db_variables.h>
volatile int db_trace_debug = 0; /* settabble from ddb */
-#define DPRINTF if (__predict_false(db_trace_debug)) (*print)
-
+#define DPRINTF(level, fmt, args...) \
+ do { \
+ if (__predict_false(db_trace_debug > (level))) { \
+ print(fmt, ## args); \
+ } \
+ } while (0 /* CONSTCOND*/)
extern char start[], etext[];
-static void db_nextframe(db_addr_t, db_addr_t *, db_addr_t *,
- void (*)(const char *, ...));
+static bool db_nextframe(db_addr_t, db_addr_t, db_addr_t *, db_addr_t *,
+ db_addr_t *, void (*)(const char *, ...) __printflike(1, 2));
const struct db_variable db_regs[] = {
{ "r0", (long *)&ddb_regs.tf_r0, FCN_NULL },
@@ -74,13 +79,28 @@
const struct db_variable * const db_eregs = db_regs + __arraycount(db_regs);
+static void
+dump_trapframe(struct trapframe *tf,
+ void (*print)(const char *, ...) __printflike(1, 2))
+{
+ print(" sr=%08x gbr=%08x pc=%08x pr=%08x\n",
+ tf->tf_ssr, tf->tf_gbr, tf->tf_spc, tf->tf_pr);
+ print(" r0=%08x r1=%08x r2=%08x r3=%08x\n",
+ tf->tf_r0, tf->tf_r1, tf->tf_r2, tf->tf_r3);
+ print(" r4=%08x r6=%08x r7=%08x r8=%08x\n",
+ tf->tf_r4, tf->tf_r5, tf->tf_r6, tf->tf_r7);
+ print(" r5=%08x r9=%08x r10=%08x r11=%08x\n",
+ tf->tf_r8, tf->tf_r9, tf->tf_r10, tf->tf_r11);
+ print(" r12=%08x r13=%08x r14=%08x sp=r15=%08x\n",
+ tf->tf_r12, tf->tf_r13, tf->tf_r14, tf->tf_r15);
+}
void
db_stack_trace_print(db_expr_t addr, bool have_addr, db_expr_t count,
- const char *modif, void (*print)(const char *, ...))
+ const char *modif, void (*print)(const char *, ...) __printflike(1, 2))
{
struct trapframe *tf;
- db_addr_t callpc, frame, lastframe;
+ db_addr_t func, pc, lastpc, pr, sp, fp;
uint32_t vbr;
bool lwpid = false;
bool lwpaddr = false;
@@ -106,17 +126,20 @@
return;
}
-
if (!have_addr) {
tf = &ddb_regs;
- frame = tf->tf_r14;
- callpc = tf->tf_spc;
- if (callpc == 0) {
- (*print)("calling through null pointer?\n");
- callpc = tf->tf_pr;
+ fp = tf->tf_r14;
+ sp = tf->tf_r15;
+ pr = tf->tf_pr;
+ pc = tf->tf_spc;
+ if (pc == 0) {
+ print("calling through null pointer?\n");
+ pc = tf->tf_pr;
}
- }
- else if (lwpaddr || lwpid) {
+ DPRINTF(1, "# trapframe: pc=%lx pr=%lx fp=%lx sp=%lx\n",
+ pc, pr, fp, sp);
+
+ } else if (lwpaddr || lwpid) {
struct proc *p;
struct lwp *l;
struct pcb *pcb;
@@ -124,121 +147,143 @@
if (lwpaddr) {
l = (struct lwp *)addr;
p = l->l_proc;
- (*print)("trace: lwp addr %p pid %d ",
- (void *)addr, p->p_pid);
- }
- else {
+ print("trace: lwp addr %p pid %d ",
+ (void *)addr, p->p_pid);
+ } else {
pid_t pid = (pid_t)addr;
- (*print)("trace: pid %d ", pid);
- p = proc_find_raw(pid);
+ print("trace: pid %d ", pid);
+ p = db_proc_find(pid);
if (p == NULL) {
- (*print)("not found\n");
+ print("not found\n");
return;
}
l = LIST_FIRST(&p->p_lwps);
}
KASSERT(l != NULL);
- (*print)("lid %d ", l->l_lid);
+ print("lid %d", l->l_lid);
pcb = lwp_getpcb(l);
tf = (struct trapframe *)pcb->pcb_sf.sf_r6_bank;
- frame = pcb->pcb_sf.sf_r14;
- callpc = pcb->pcb_sf.sf_pr;
- (*print)("at %p\n", frame);
- }
- else {
- /* XXX */
- db_printf("trace by frame address is not supported\n");
- return;
+ fp = pcb->pcb_sf.sf_r14;
+ sp = pcb->pcb_sf.sf_r15;
+ pr = pcb->pcb_sf.sf_pr;
+ pc = pcb->pcb_sf.sf_pr;
+ print(", fp=%lx, sp=%lx\n", fp, sp);
+ DPRINTF(1, "# lwp: pc=%lx pr=%lx fp=%lx sp=%lx\n",
+ pc, pr, fp, sp);
+ } else {
+ fp = 0;
+ sp = addr;
+ pr = 0;
+ /*
+ * Assume that the frame address (__builtin_frame_address)
+ * passed as an argument is the same level
+ * as this __builtin_return_address().
+ */
+ pc = (db_addr_t)__builtin_return_address(0);
}
- lastframe = 0;
- while (count > 0 && frame != 0) {
+ lastpc = 0;
+ while (count > 0 && pc != 0 && sp != 0) {
+ DPRINTF(2, "# trace: pc=%lx sp=%lx fp=%lx\n", pc, sp, fp);
+
/* Are we crossing a trap frame? */
- if ((callpc & ~PAGE_MASK) == vbr) {
- /* r14 in exception vectors points to trap frame */
- tf = (void *)frame;
+ if ((pc & ~PAGE_MASK) == vbr) {
+ struct trapframe trapframe;
+ tf = &trapframe;
- frame = tf->tf_r14;
- callpc = tf->tf_spc;
+ /* r14 in exception vectors points to trap frame */
+ db_read_bytes((db_addr_t)fp, sizeof(*tf), (char *)tf);
+ pc = tf->tf_spc;
+ pr = tf->tf_pr;
+ fp = tf->tf_r14;
+ sp = tf->tf_r15;
- (*print)("<EXPEVT %03x; SSR=%08x> at ",
- tf->tf_expevt, tf->tf_ssr);
- db_printsym(callpc, DB_STGY_PROC, print);
- (*print)("\n");
+ print("<EXPEVT %03x; SSR=%08x> at ",
+ tf->tf_expevt, tf->tf_ssr);
+ db_printsym(pc, DB_STGY_PROC, print);
+ print("\n");
- lastframe = 0;
+ print("[trapframe 0x%lx]\n", fp);
+ dump_trapframe(tf, print);
/* XXX: don't venture into the userland yet */
if ((tf->tf_ssr & PSL_MD) == 0)
break;
} else {
- db_addr_t oldfp;
const char *name;
db_expr_t offset;
db_sym_t sym;
-
-
- DPRINTF(" (1) newpc 0x%lx, newfp 0x%lx\n",
- callpc, frame);
+ bool found;
- sym = db_search_symbol(callpc, DB_STGY_ANY, &offset);
- db_symbol_values(sym, &name, NULL);
-
- if (lastframe == 0 && sym == 0) {
- (*print)("symbol not found\n");
+ sym = db_search_symbol(pc, DB_STGY_ANY, &offset);
+ if (sym == 0) {
+ print("symbol not found\n");
break;
}
+ db_symbol_values(sym, &name, NULL);
- oldfp = frame;
+ func = pc - offset;
- db_nextframe(callpc - offset, &frame, &callpc, print);
- DPRINTF(" (2) newpc 0x%lx, newfp 0x%lx\n",
- callpc, frame);
-
- /* leaf routine or interrupted early? */
- if (lastframe == 0 && callpc == 0) {
- callpc = tf->tf_pr; /* PR still in register */
+ DPRINTF(1,
+ " (1) func=%lx+%lx, pc=%lx, sp=%lx, fp=%lx\n",
+ func, offset, pc, sp, fp);
- /* asm routine w/out frame? */
- if (frame == 0)
- frame = oldfp;
- DPRINTF(" (3) newpc 0x%lx, newfp 0x%lx\n",
- callpc, frame);
- }
+ found = db_nextframe(func, pc, &fp, &pr, &sp, print);
+ if (!found && lastpc == pc)
+ break;
+ lastpc = pc;
+
+ DPRINTF(1, " (2) newpc=%lx, newsp=%lx, newfp=%lx\n",
+ pr, sp, fp);
- (*print)("%s() at ", name ? name : "");
- db_printsym(callpc, DB_STGY_PROC, print);
- (*print)("\n");
+ DPRINTF(1, "sp=%lx ", sp);
+ print("%s() at ", name ? name : "");
+ db_printsym(pr, DB_STGY_PROC, print);
+ print("\n");
- lastframe = frame;
+ pc = pr;
+ pr = 0;
}
count--;
}
}
-static void
+static bool
db_nextframe(
- db_addr_t pc, /* in: entry address of current function */
- db_addr_t *fp, /* in: current fp, out: parent fp */
+ db_addr_t func, /* in: entry address of current function */
+ db_addr_t curpc, /* in: current pc in the function */
+ db_addr_t *fp, /* out: parent fp */
db_addr_t *pr, /* out: parent pr */
- void (*print)(const char *, ...))
+ db_addr_t *sp, /* in: current sp, out: parent sp */
+ void (*print)(const char *, ...) __printflike(1, 2))
{
- int *frame = (void *)*fp;
- int i, inst;
+ int *stack = (void *)*sp;
+ int i, inst, inst2;
int depth, prdepth, fpdepth;
+ db_addr_t pc;
+ if (__predict_false(db_trace_debug >= 2)) {
+ DPRINTF(2, "%s:%d: START: func=%lx=", __func__, __LINE__, func);
+ db_printsym(func, DB_STGY_PROC, print);
+ DPRINTF(2, " pc=%lx fp=%lx pr=%lx, sp=%lx\n",
+ curpc, *fp, *pr, *sp);
+ }
+
+ pc = func;
depth = 0;
prdepth = fpdepth = -1;
if (pc < (db_addr_t)start || pc > (db_addr_t)etext)
goto out;
Home |
Main Index |
Thread Index |
Old Index