summaryrefslogtreecommitdiff
path: root/sys/arch
diff options
context:
space:
mode:
authorVisa Hankala <visa@cvs.openbsd.org>2022-02-22 07:46:05 +0000
committerVisa Hankala <visa@cvs.openbsd.org>2022-02-22 07:46:05 +0000
commit91a21e3d176543e31896b2698a9c4f2dcad60722 (patch)
treede256fe666fe2fd4a4a9d2f89fcf22a85793c457 /sys/arch
parent2135b2fd316289d0a4449abfd454b8433f0f2a7a (diff)
ddb: Improve stack unwinding on riscv64
Add logic to navigate across trapframes. Stop unwinding if the frame pointer is clearly bad. Adjust output, and tweak details. OK miod@ kettenis@
Diffstat (limited to 'sys/arch')
-rw-r--r--sys/arch/riscv64/riscv64/db_trace.c82
1 files changed, 49 insertions, 33 deletions
diff --git a/sys/arch/riscv64/riscv64/db_trace.c b/sys/arch/riscv64/riscv64/db_trace.c
index 348eb20569c..87b1e0cc29d 100644
--- a/sys/arch/riscv64/riscv64/db_trace.c
+++ b/sys/arch/riscv64/riscv64/db_trace.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: db_trace.c,v 1.4 2021/07/09 20:59:51 jasper Exp $ */
+/* $OpenBSD: db_trace.c,v 1.5 2022/02/22 07:46:04 visa Exp $ */
/*
* Copyright (c) 2000, 2001 Ben Harris
@@ -43,6 +43,9 @@
#include <ddb/db_sym.h>
#include <ddb/db_output.h>
+extern unsigned char cpu_exception_handler_supervisor[];
+extern unsigned char cpu_exception_handler_user[];
+
db_regs_t ddb_regs;
#define INKERNEL(va) (((vaddr_t)(va)) & (1ULL << 63))
@@ -51,7 +54,7 @@ void
db_stack_trace_print(db_expr_t addr, int have_addr, db_expr_t count,
char *modif, int (*pr)(const char *, ...))
{
- vaddr_t frame, lastframe, ra, lastra, sp;
+ vaddr_t frame, lastframe, ra, subr;
char c, *cp = modif;
db_expr_t offset;
Elf_Sym * sym;
@@ -68,60 +71,73 @@ db_stack_trace_print(db_expr_t addr, int have_addr, db_expr_t count,
}
if (!have_addr) {
- sp = ddb_regs.tf_sp;
ra = ddb_regs.tf_ra;
- lastra = ddb_regs.tf_ra;
frame = ddb_regs.tf_s[0];
} else {
- sp = addr;
- db_read_bytes(sp - 16, sizeof(vaddr_t), (char *)&frame);
- db_read_bytes(sp - 8, sizeof(vaddr_t), (char *)&ra);
- lastra = 0;
+ db_read_bytes(addr - 16, sizeof(vaddr_t), (char *)&frame);
+ db_read_bytes(addr - 8, sizeof(vaddr_t), (char *)&ra);
}
- while (count-- && frame != 0) {
- lastframe = frame;
-
- sym = db_search_symbol(lastra, DB_STGY_ANY, &offset);
- db_symbol_values(sym, &name, NULL);
+ while (count != 0 && frame != 0) {
+ if (INKERNEL(frame)) {
+ sym = db_search_symbol(ra, DB_STGY_ANY, &offset);
+ db_symbol_values(sym, &name, NULL);
+ } else {
+ sym = NULL;
+ name = NULL;
+ }
if (name == NULL || strcmp(name, "end") == 0) {
- (*pr)("%llx at 0x%lx", lastra, ra - 4);
+ (*pr)("%llx() at 0x%lx", ra, ra);
} else {
(*pr)("%s() at ", name);
- db_printsym(ra - 4, DB_STGY_PROC, pr);
+ db_printsym(ra, DB_STGY_PROC, pr);
}
(*pr)("\n");
- // can we detect traps ?
- db_read_bytes(frame - 16, sizeof(vaddr_t), (char *)&frame);
- if (frame == 0)
+ if ((frame & 0x7) != 0) {
+ (*pr)("bad frame pointer: 0x%lx\n", frame);
break;
- lastra = ra;
- db_read_bytes(frame - 8, sizeof(vaddr_t), (char *)&ra);
-
-#if 0
- if (name != NULL) {
- if ((strcmp (name, "handle_el0_irq") == 0) ||
- (strcmp (name, "handle_el1_irq") == 0)) {
- (*pr)("--- interrupt ---\n");
- } else if (
- (strcmp (name, "handle_el0_sync") == 0) ||
- (strcmp (name, "handle_el1_sync") == 0)) {
- (*pr)("--- trap ---\n");
+ }
+
+ subr = 0;
+ if (sym != NULL)
+ subr = ra - (vaddr_t)offset;
+
+ lastframe = frame;
+ if (subr == (vaddr_t)cpu_exception_handler_supervisor ||
+ subr == (vaddr_t)cpu_exception_handler_user) {
+ struct trapframe *tf = (struct trapframe *)frame;
+
+ db_read_bytes((vaddr_t)&tf->tf_ra, sizeof(ra),
+ (char *)&ra);
+ db_read_bytes((vaddr_t)&tf->tf_s[0], sizeof(frame),
+ (char *)&frame);
+ } else {
+ db_read_bytes(frame - 16, sizeof(frame),
+ (char *)&frame);
+ if (frame == 0)
+ break;
+ if ((frame & 0x7) != 0) {
+ (*pr)("bad frame pointer: 0x%lx\n", frame);
+ break;
}
+ db_read_bytes(frame - 8, sizeof(ra), (char *)&ra);
}
-#endif
+
if (INKERNEL(frame)) {
if (frame <= lastframe) {
- (*pr)("Bad frame pointer: 0x%lx\n", frame);
+ (*pr)("bad frame pointer: 0x%lx\n", frame);
break;
}
} else {
- if (kernel_only)
+ if (kernel_only) {
+ (*pr)("end of kernel\n");
break;
+ }
}
--count;
}
+ (*pr)("end trace frame: 0x%lx, count: %d\n", frame, count);
}