x86_64: implement stack traces for user-mode stacks
This commit is contained in:
@@ -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);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user