summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFreya Murphy <freya@freyacat.org>2025-04-08 17:55:13 -0400
committerFreya Murphy <freya@freyacat.org>2025-04-08 17:55:13 -0400
commit331a2a442b2c8595002d342372d4d08f104b382d (patch)
tree7f46cf1a774d9135383125211b268b28df34d232
parentremove boot dir (diff)
downloadcomus-331a2a442b2c8595002d342372d4d08f104b382d.tar.gz
comus-331a2a442b2c8595002d342372d4d08f104b382d.tar.bz2
comus-331a2a442b2c8595002d342372d4d08f104b382d.zip
backtrace
-rw-r--r--build.zig3
-rw-r--r--kernel/cpu/idt.c3
-rw-r--r--kernel/drivers/term.c14
-rw-r--r--kernel/drivers/tty.c105
-rw-r--r--kernel/include/lib/klib.h26
-rw-r--r--kernel/lib/backtrace.c46
-rw-r--r--kernel/lib/panic.c2
7 files changed, 86 insertions, 113 deletions
diff --git a/build.zig b/build.zig
index b0f021f..63c861a 100644
--- a/build.zig
+++ b/build.zig
@@ -32,10 +32,11 @@ const kernel_src = &[_][]const u8{
"kernel/drivers/clock.c",
"kernel/drivers/drivers.c",
"kernel/drivers/pci.c",
- "kernel/drivers/tty.c",
+ "kernel/drivers/term.c",
"kernel/drivers/uart.c",
"kernel/fs/fs.c",
"kernel/lib/atox.c",
+ "kernel/lib/backtrace.c",
"kernel/lib/bound.c",
"kernel/lib/btoa.c",
"kernel/lib/ctoi.c",
diff --git a/kernel/cpu/idt.c b/kernel/cpu/idt.c
index 6bd1a7a..5b93987 100644
--- a/kernel/cpu/idt.c
+++ b/kernel/cpu/idt.c
@@ -1,3 +1,4 @@
+#include "lib/klib.h"
#include <lib.h>
#include <comus/memory.h>
#include <comus/asm.h>
@@ -197,6 +198,8 @@ void idt_exception_handler(uint64_t exception, uint64_t code, regs_t *state)
kputs("\n");
+ log_backtrace_ex((void *)state->rip, (void *)state->rbp);
+
while (1) {
halt();
}
diff --git a/kernel/drivers/term.c b/kernel/drivers/term.c
index e9d3e50..d1cd553 100644
--- a/kernel/drivers/term.c
+++ b/kernel/drivers/term.c
@@ -1,5 +1,5 @@
#include <lib.h>
-#include <comus/drivers/tty.h>
+#include <comus/drivers/term.h>
#include <comus/asm.h>
#include <comus/memory.h>
@@ -18,7 +18,7 @@ static uint8_t fg = 15, bg = 0;
// blank color
const uint16_t blank = (uint16_t)0 | 0 << 12 | 15 << 8;
-static void term_clear_line(int line)
+void term_clear_line(int line)
{
if (line < 0 || line >= height)
return;
@@ -28,13 +28,13 @@ static void term_clear_line(int line)
}
}
-static void term_clear(void)
+void term_clear(void)
{
for (uint8_t y = 0; y < height; y++)
term_clear_line(y);
}
-static void term_scroll(int lines)
+void term_scroll(int lines)
{
cli();
y -= lines;
@@ -52,7 +52,7 @@ static void term_scroll(int lines)
sti();
}
-void tty_out(char c)
+void term_out(char c)
{
if (buffer == NULL)
return;
@@ -98,8 +98,8 @@ void tty_out(char c)
outb(0x3D5, (uint8_t)((pos >> 8) & 0xFF));
}
-void tty_out_str(const char *str)
+void term_out_str(const char *str)
{
while (*str)
- tty_out(*str++);
+ term_out(*str++);
}
diff --git a/kernel/drivers/tty.c b/kernel/drivers/tty.c
deleted file mode 100644
index d1cd553..0000000
--- a/kernel/drivers/tty.c
+++ /dev/null
@@ -1,105 +0,0 @@
-#include <lib.h>
-#include <comus/drivers/term.h>
-#include <comus/asm.h>
-#include <comus/memory.h>
-
-#define VGA_ADDR 0xB8000
-
-static const uint8_t width = 80;
-static const uint8_t height = 25;
-static volatile uint16_t *buffer = (uint16_t *)VGA_ADDR;
-
-// position
-static uint32_t x = 0, y = 0;
-
-// color
-static uint8_t fg = 15, bg = 0;
-
-// blank color
-const uint16_t blank = (uint16_t)0 | 0 << 12 | 15 << 8;
-
-void term_clear_line(int line)
-{
- if (line < 0 || line >= height)
- return;
- for (uint8_t x = 0; x < width; x++) {
- const size_t index = line * width + x;
- buffer[index] = blank;
- }
-}
-
-void term_clear(void)
-{
- for (uint8_t y = 0; y < height; y++)
- term_clear_line(y);
-}
-
-void term_scroll(int lines)
-{
- cli();
- y -= lines;
- if (!lines)
- return;
- if (lines >= height || lines <= -height) {
- term_clear();
- } else if (lines > 0) {
- memmovev(buffer, buffer + lines * width, 2 * (height - lines) * width);
- term_clear_line(height - lines);
- } else {
- memmovev(buffer + lines * width, buffer + lines,
- (height + lines) * width);
- }
- sti();
-}
-
-void term_out(char c)
-{
- if (buffer == NULL)
- return;
-
- // handle special chars
- switch (c) {
- case '\n':
- x = 0;
- y++;
- break;
- case '\t':
- x += 4;
- break;
- case '\v':
- case '\f':
- y++;
- break;
- case '\r':
- x = 0;
- break;
- default: {
- const size_t index = y * width + x;
- buffer[index] = c | bg << 12 | fg << 8;
- x++;
- }
- }
-
- // wrap cursor if needed
- if (x >= width) {
- x = 0;
- y++;
- }
- if (y >= height) {
- term_scroll(y - (height - 1));
- y = height - 1;
- }
-
- // set cursor position on screen
- const uint16_t pos = y * width + x;
- outb(0x3D4, 0x0F);
- outb(0x3D5, (uint8_t)(pos & 0xFF));
- outb(0x3D4, 0x0E);
- outb(0x3D5, (uint8_t)((pos >> 8) & 0xFF));
-}
-
-void term_out_str(const char *str)
-{
- while (*str)
- term_out(*str++);
-}
diff --git a/kernel/include/lib/klib.h b/kernel/include/lib/klib.h
index c67e57d..3afe925 100644
--- a/kernel/include/lib/klib.h
+++ b/kernel/include/lib/klib.h
@@ -193,4 +193,30 @@ unsigned int bound(unsigned int min, unsigned int value, unsigned int max);
*/
__attribute__((noreturn)) void panic(const char *format, ...);
+/**
+ * Fill dst with a stack trace consisting of return addresses in order
+ * from top to bottom
+ *
+ * @returns number of backtraces (at most len)
+ */
+size_t backtrace(void **dst, size_t len);
+
+/**
+ * Fill dst with a stack trace consisting of return addresses in order
+ * from top to bottom, starting at a provided ip/bp
+ *
+ * @returns number of backtraces (at most len)
+ */
+size_t backtrace_ex(void **dst, size_t len, void *ip, void *bp);
+
+/**
+ * Log a backtrace to output
+ */
+void log_backtrace(void);
+
+/**
+ * Log a backtrace to output starting at a provided ip/bp
+ */
+void log_backtrace_ex(void *ip, void *bp);
+
#endif /* klib.h */
diff --git a/kernel/lib/backtrace.c b/kernel/lib/backtrace.c
new file mode 100644
index 0000000..fb708b2
--- /dev/null
+++ b/kernel/lib/backtrace.c
@@ -0,0 +1,46 @@
+#include <lib.h>
+
+struct stackframe {
+ struct stackframe *rbp;
+ void *rip;
+};
+
+size_t backtrace(void **dst, size_t len)
+{
+ struct stackframe *rbp;
+ __asm__("mov %%rbp, %0" : "=r"(rbp));
+ return backtrace_ex(dst, len, rbp->rip, rbp->rbp);
+}
+
+size_t backtrace_ex(void **dst, size_t len, void *ip, void *bp)
+{
+ struct stackframe *frame = bp;
+ __asm__("mov %%rbp, %0" : "=r"(frame));
+ if (len > 0) {
+ dst[0] = ip;
+ }
+ size_t i;
+ for (i = 1; frame && i < len; i++) {
+ dst[i] = frame->rip;
+ frame = frame->rbp;
+ }
+ return i;
+}
+
+void log_backtrace(void)
+{
+ struct stackframe *rbp;
+ __asm__("mov %%rbp, %0" : "=r"(rbp));
+ log_backtrace_ex(rbp->rip, rbp->rbp);
+}
+
+void log_backtrace_ex(void *ip, void *bp)
+{
+ struct stackframe *frame = bp;
+ kputs("Stack trace:\n");
+ kprintf(" %p\n", ip);
+ while (frame) {
+ kprintf(" %p\n", frame->rip);
+ frame = frame->rbp;
+ }
+}
diff --git a/kernel/lib/panic.c b/kernel/lib/panic.c
index 5381041..d3db908 100644
--- a/kernel/lib/panic.c
+++ b/kernel/lib/panic.c
@@ -1,3 +1,4 @@
+#include "lib/klib.h"
#include <lib.h>
#include <stdarg.h>
#include <comus/asm.h>
@@ -10,6 +11,7 @@ __attribute__((noreturn)) void panic(const char *format, ...)
kprintf("\n\n!!! PANIC !!!\n");
kvprintf(format, list);
kprintf("\n\n");
+ log_backtrace();
while (1)
halt();