Add support for stack traces
All checks were successful
continuous-integration/drone/push Build is passing

This commit is contained in:
apio 2022-12-07 17:39:59 +01:00
parent 416e96c4d5
commit 0d437cfcca
Signed by: apio
GPG Key ID: B8A7D06E42258954
2 changed files with 46 additions and 0 deletions

View File

@ -20,4 +20,7 @@ namespace CPU
void enable_interrupts(); void enable_interrupts();
void disable_interrupts(); void disable_interrupts();
void wait_for_interrupt(); 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);
} }

View File

@ -3,6 +3,7 @@
#include "arch/Timer.h" #include "arch/Timer.h"
#include "arch/x86_64/CPU.h" #include "arch/x86_64/CPU.h"
#include "arch/x86_64/IO.h" #include "arch/x86_64/IO.h"
#include "memory/MemoryManager.h"
#include "thread/Scheduler.h" #include "thread/Scheduler.h"
#include <cpuid.h> #include <cpuid.h>
#include <luna/Check.h> #include <luna/Check.h>
@ -301,6 +302,17 @@ static void setup_idt()
u64 cr2; u64 cr2;
asm volatile("mov %%cr2, %0" : "=r"(cr2)); asm volatile("mov %%cr2, %0" : "=r"(cr2));
kerrorln("Page fault at RIP %lx while accessing %lx!", regs->rip, 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(); CPU::efficient_halt();
} }
@ -444,6 +456,37 @@ namespace CPU
{ {
task_state_segment.rsp[0] = top; 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 // called by kernel_yield