From 0d437cfcca4f117d27e78fb2873b02b869a08442 Mon Sep 17 00:00:00 2001 From: apio Date: Wed, 7 Dec 2022 17:39:59 +0100 Subject: [PATCH] Add support for stack traces --- kernel/src/arch/CPU.h | 3 +++ kernel/src/arch/x86_64/CPU.cpp | 43 ++++++++++++++++++++++++++++++++++ 2 files changed, 46 insertions(+) diff --git a/kernel/src/arch/CPU.h b/kernel/src/arch/CPU.h index 35159630..ac05ed6a 100644 --- a/kernel/src/arch/CPU.h +++ b/kernel/src/arch/CPU.h @@ -20,4 +20,7 @@ namespace CPU void enable_interrupts(); void disable_interrupts(); void wait_for_interrupt(); + + void get_stack_trace(void (*callback)(u64, void*), void* arg); + void get_stack_trace_at(Registers* regs, void (*callback)(u64, void*), void* arg); } \ No newline at end of file diff --git a/kernel/src/arch/x86_64/CPU.cpp b/kernel/src/arch/x86_64/CPU.cpp index 6a9f8600..8d8476c9 100644 --- a/kernel/src/arch/x86_64/CPU.cpp +++ b/kernel/src/arch/x86_64/CPU.cpp @@ -3,6 +3,7 @@ #include "arch/Timer.h" #include "arch/x86_64/CPU.h" #include "arch/x86_64/IO.h" +#include "memory/MemoryManager.h" #include "thread/Scheduler.h" #include #include @@ -301,6 +302,17 @@ static void setup_idt() u64 cr2; asm volatile("mov %%cr2, %0" : "=r"(cr2)); kerrorln("Page fault at RIP %lx while accessing %lx!", regs->rip, cr2); + + int frame_index = 0; + CPU::get_stack_trace_at( + regs, + [](u64 instruction, void* arg) { + int* ptr = (int*)arg; + kinfoln("#%d at %p", *ptr, (void*)instruction); + (*ptr)++; + }, + &frame_index); + CPU::efficient_halt(); } @@ -444,6 +456,37 @@ namespace CPU { task_state_segment.rsp[0] = top; } + + struct StackFrame + { + StackFrame* next; + u64 instruction; + }; + + void get_stack_trace(void (*callback)(u64, void*), void* arg) + { + u64 rbp; + asm volatile("mov %%rbp, %0" : "=r"(rbp)); + StackFrame* current_frame = (StackFrame*)rbp; + // FIXME: Validate that the frame itself is readable, might span across multiple pages + while (current_frame && MemoryManager::validate_readable_page((u64)current_frame)) + { + callback(current_frame->instruction, arg); + current_frame = current_frame->next; + } + } + + void get_stack_trace_at(Registers* regs, void (*callback)(u64, void*), void* arg) + { + callback(regs->rip, arg); + StackFrame* current_frame = (StackFrame*)regs->rbp; + // FIXME: Validate that the frame itself is readable, might span across multiple pages + while (current_frame && MemoryManager::validate_readable_page((u64)current_frame)) + { + callback(current_frame->instruction, arg); + current_frame = current_frame->next; + } + } } // called by kernel_yield