mirror of
https://git.stationery.faith/corn/corn.git
synced 2024-11-21 18:22:16 +00:00
added backtraces
This commit is contained in:
parent
417d5b17b8
commit
6b8f33c22d
8 changed files with 130 additions and 9 deletions
20
include/backtrace.h
Normal file
20
include/backtrace.h
Normal 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);
|
|
@ -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);
|
||||
|
|
53
src/arch/amd64/backtrace.c
Normal file
53
src/arch/amd64/backtrace.c
Normal 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;
|
||||
}
|
||||
|
||||
}
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
24
src/kmain.c
24
src/kmain.c
|
@ -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");
|
||||
|
|
Loading…
Reference in a new issue