added backtraces

This commit is contained in:
trimill 2024-01-30 10:19:33 -05:00
parent 417d5b17b8
commit 6b8f33c22d
No known key found for this signature in database
GPG key ID: 4F77A16E17E10BCB
8 changed files with 130 additions and 9 deletions

20
include/backtrace.h Normal file
View file

@ -0,0 +1,20 @@
#pragma once
#include <stddef.h>
// Fill dst with a stack trace consisting of return addresses
// in order from top to bottom. returns the number filled (at most len)
size_t backtrace(void **dst, size_t len);
// same as backtrace but with specified instruction and base pointer
size_t backtrace_ex(void **dst, size_t len, void* ip, void *bp);
// TODO symbols
//size_t backtrace_symbols(char *const *dst, size_t len);
// Log a backtrace
void log_backtrace();
// same as log_backtrace with specified insruction and base pointer
void log_backtrace_ex(void *ip, void *bp);

View file

@ -6,3 +6,5 @@
#define panic(msg) _panic_impl(_PANIC_STR(__LINE__), __FILE__, msg)
_Noreturn void _panic_impl(char *line, char *file, char *msg);
_Noreturn void panic_interrupt(void *ip, void *bp, char *msg);

View file

@ -0,0 +1,53 @@
#include <backtrace.h>
#include <lib.h>
#include "serial.h"
struct stackframe {
struct stackframe *rbp;
void *rip;
};
size_t backtrace(void **dst, size_t len) {
struct stackframe *rbp;
__asm__ volatile ("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__ volatile ("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() {
struct stackframe *rbp;
__asm__ volatile ("mov %%rbp, %0" : "=r"(rbp));
log_backtrace_ex(rbp->rip, rbp->rbp);
}
void log_backtrace_ex(void *ip, void *bp) {
struct stackframe *frame = bp;
char buf[20];
serial_out_str("Stack trace:\n");
ultoa((size_t)ip, buf, 16);
serial_out_str(" 0x");
serial_out_str(buf);
serial_out_str("\n");
while(frame) {
ultoa((size_t)frame->rip, buf, 16);
serial_out_str(" 0x");
serial_out_str(buf);
serial_out_str("\n");
frame = frame->rbp;
}
}

View file

@ -136,13 +136,16 @@ start:
bits 64
code64:
mov dx, 16
mov ds, dx
mov dx, 16 ; set segment registers
mov ds, dx ; so that interrupts work
mov ss, dx
xor rbp, rbp ; set ebp to 0 so we know where to end stack traces
pop rdi
call amd64_shim
mov rdi, rax
sti
call kmain
cli

View file

@ -49,8 +49,10 @@ align 8
isr_stub_%+%1:
PUSHALL
cld
mov rdi, %1
mov rsi, 0
mov rdi, %1 ; exception number
mov rsi, 0 ; placeholder error code
mov rdx, [rsp + 15 * 8] ; instruction pointer
mov rcx, rbp ; base pointer for stack trace
call idt_exception_handler
POPALL
iretq
@ -64,10 +66,13 @@ align 8
isr_stub_%+%1:
PUSHALL
cld
mov rdi, %1
pop rsi
mov rdi, %1 ; exception number
mov rsi, [rsp + 15 * 8] ; error code
mov rdx, [rsp + 16 * 8] ; instruction pointer
mov rcx, rbp ; base pointer for stack trace
call idt_exception_handler
POPALL
sub rsp, 8 ; discard error code
iretq
%endmacro

View file

@ -4,6 +4,7 @@
#include <lib.h>
#include <serial.h>
#include "backtrace.h"
#include "idt.h"
#include "pic.h"
@ -107,7 +108,7 @@ char *EXCEPTIONS[] = {
"0x1F Reserved",
};
void idt_exception_handler(uint64_t exception, uint64_t code) {
void idt_exception_handler(uint64_t exception, uint64_t code, void *rip, void *rbp) {
// TODO don't just panic
char buf[24];
char msg[256] = "Exception ";
@ -127,7 +128,7 @@ void idt_exception_handler(uint64_t exception, uint64_t code) {
strcat(msg, buf);
}
panic(msg);
panic_interrupt(rip, rbp, msg);
}
void idt_pic_eoi(uint8_t exception) {

View file

@ -1,4 +1,5 @@
#include <panic.h>
#include <backtrace.h>
#include "serial.h"
#include "bindings.h"
@ -12,7 +13,19 @@ _Noreturn void _panic_impl(char *line, char *file, char *msg) {
serial_out_str(line);
serial_out_str(":\n");
serial_out_str(msg);
serial_out('\n');
serial_out_str("\n\n");
log_backtrace();
while (1) {
halt();
}
}
_Noreturn void panic_interrupt(void *ip, void *bp, char *msg) {
cli();
serial_out_str("\n\n!!! PANIC !!!\n");
serial_out_str(msg);
serial_out_str("\n\n");
log_backtrace_ex(ip, bp);
while (1) {
halt();
}

View file

@ -4,6 +4,30 @@
#include <fb.h>
#include <shim.h>
void print_memory() {
size_t WIDTH = 64;
for(size_t i = 0;; i += WIDTH) {
char buf[20];
ultoa(i, buf, 16);
serial_out_str("0x");
for(size_t k = 0; k < 6 - strlen(buf); k++) {
serial_out('0');
}
serial_out_str(buf);
serial_out_str(": ");
for(size_t j = 0; j < WIDTH; j++) {
char x = *(char *)(i + j);
if(x < 0x20 || x >= 0x7f) {
serial_out('.');
} else {
serial_out(x);
}
}
serial_out('\n');
}
}
void kmain(struct boot_info *info) {
memory_init(info->map);
serial_out_str("entered kmain\n");