summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIan Moffett <ian@osmora.org>2024-04-09 17:33:09 -0400
committerIan Moffett <ian@osmora.org>2024-04-09 17:33:09 -0400
commitd52caa46b10eb1670bc6f9c55eff6dce288926c5 (patch)
tree0f2dbb29fef2df37ddf4db3ab6af2d7313429e2a
parent3c8dd7d392dc50ca9d356beefba7820a14d7fd74 (diff)
kernel/amd64: Add backtrace support for panic()
Signed-off-by: Ian Moffett <ian@osmora.org>
-rw-r--r--sys/arch/amd64/amd64/machdep.c48
-rw-r--r--sys/include/sys/machdep.h1
-rw-r--r--sys/kern/kern_panic.c1
3 files changed, 50 insertions, 0 deletions
diff --git a/sys/arch/amd64/amd64/machdep.c b/sys/arch/amd64/amd64/machdep.c
index 1c158da..809eb27 100644
--- a/sys/arch/amd64/amd64/machdep.c
+++ b/sys/arch/amd64/amd64/machdep.c
@@ -30,6 +30,7 @@
#include <sys/machdep.h>
#include <sys/cdefs.h>
#include <sys/panic.h>
+#include <sys/ksyms.h>
#include <machine/trap.h>
#include <machine/idt.h>
#include <machine/io.h>
@@ -161,6 +162,53 @@ intr_unmask(void)
__ASMV("sti");
}
+static const char*
+backtrace_addr_to_name(uintptr_t addr, off_t *off)
+{
+ uintptr_t prev_addr = 0;
+ const char *name = NULL;
+
+ for (size_t i = 0;;) {
+ if (g_ksym_table[i].addr > addr) {
+ *off = addr - prev_addr;
+ return name;
+ }
+
+ prev_addr = g_ksym_table[i].addr;
+ name = g_ksym_table[i].name;
+ if (g_ksym_table[i++].addr == (uint64_t)-1)
+ break;
+ }
+
+ return NULL;
+}
+
+void
+backtrace(void)
+{
+ uintptr_t *rbp;
+ uintptr_t rip;
+
+ off_t off;
+ const char *name;
+
+ kprintf("** Backtrace **\n");
+ __ASMV("mov %%rbp, %0" : "=r" (rbp) :: "memory");
+
+ while (1) {
+ rip = rbp[1];
+ rbp = (uintptr_t *)rbp[0];
+ name = backtrace_addr_to_name(rip, &off);
+
+ if (rbp == NULL)
+ break;
+ if (name == NULL)
+ name = "???";
+
+ kprintf("[0x%p] <%s+0x%x>\n", rip, name, off);
+ }
+}
+
int
processor_init_pcb(struct proc *proc)
{
diff --git a/sys/include/sys/machdep.h b/sys/include/sys/machdep.h
index 0c06374..811f6be 100644
--- a/sys/include/sys/machdep.h
+++ b/sys/include/sys/machdep.h
@@ -48,6 +48,7 @@ void intr_unmask(void);
__weak void chips_init(void);
__weak void pre_init(void);
__weak void serial_dbgch(char c);
+__weak void backtrace(void);
#endif /* defined(_KERNEL) */
#endif /* !_SYS_MACHDEP_H_ */
diff --git a/sys/kern/kern_panic.c b/sys/kern/kern_panic.c
index 9fe3fdd..d22f5b2 100644
--- a/sys/kern/kern_panic.c
+++ b/sys/kern/kern_panic.c
@@ -50,6 +50,7 @@ panic(const char *fmt, ...)
kprintf("panic: ");
vkprintf(fmt, &ap);
+ __TRY_CALL(backtrace);
processor_halt();
__builtin_unreachable();