x86_64: implement stack traces for user-mode stacks

This commit is contained in:
2026-03-14 22:28:24 +00:00
parent 62bdb51618
commit a50826eb15

View File

@@ -1,8 +1,11 @@
#include <arch/irq.h>
#include <kernel/address-space.h>
#include <kernel/libc/stdio.h>
#include <kernel/machine/cpu.h>
#include <kernel/machine/panic.h>
#include <kernel/printk.h>
#include <kernel/sched.h>
#include <kernel/task.h>
#include <kernel/vm.h>
#define R_CF 0
@@ -166,36 +169,64 @@ static void print_stack_item(uintptr_t addr)
printk("%s", buf);
}
static void print_stack_trace(uintptr_t ip, uintptr_t *bp)
static bool read_stack_frame(
struct address_space *space,
uintptr_t bp,
struct stack_frame *out)
{
struct stack_frame *stk = (struct stack_frame *)bp;
if (bp >= VM_PAGEMAP_BASE) {
*out = *(struct stack_frame *)out;
return true;
}
if (!space) {
return false;
}
size_t tmp;
kern_status_t status
= address_space_read(space, bp, sizeof *out, out, &tmp);
return status == KERN_OK;
}
static void print_stack_trace(
struct address_space *space,
uintptr_t ip,
uintptr_t bp)
{
struct stack_frame stk;
if (!read_stack_frame(space, bp, &stk)) {
return;
}
printk("call trace:");
print_stack_item(ip);
int max_frames = 10, current_frame = 0;
while (1) {
if (!vm_virt_to_phys(stk) || bp == NULL
|| current_frame > max_frames) {
break;
}
uintptr_t addr = stk->rip;
while (current_frame < max_frames) {
uintptr_t addr = stk.rip;
print_stack_item(addr);
stk = (struct stack_frame *)stk->rbp;
bp = stk.rbp;
if (!read_stack_frame(space, bp, &stk)) {
break;
}
current_frame++;
}
}
void ml_print_stack_trace(uintptr_t ip)
{
uintptr_t *bp;
struct task *task = current_task();
struct address_space *space = task ? task->t_address_space : NULL;
uintptr_t bp;
asm volatile("mov %%rbp, %0" : "=r"(bp));
print_stack_trace(ip, bp);
print_stack_trace(space, ip, bp);
}
void ml_print_stack_trace_irq(struct ml_cpu_context *ctx)
{
print_stack_trace(ctx->rip, (uintptr_t *)ctx->rbp);
struct task *task = current_task();
struct address_space *space = task ? task->t_address_space : NULL;
print_stack_trace(space, ctx->rip, ctx->rbp);
}