x86_64: implement stack traces for user-mode stacks
This commit is contained in:
@@ -1,8 +1,11 @@
|
|||||||
#include <arch/irq.h>
|
#include <arch/irq.h>
|
||||||
|
#include <kernel/address-space.h>
|
||||||
#include <kernel/libc/stdio.h>
|
#include <kernel/libc/stdio.h>
|
||||||
#include <kernel/machine/cpu.h>
|
#include <kernel/machine/cpu.h>
|
||||||
#include <kernel/machine/panic.h>
|
#include <kernel/machine/panic.h>
|
||||||
#include <kernel/printk.h>
|
#include <kernel/printk.h>
|
||||||
|
#include <kernel/sched.h>
|
||||||
|
#include <kernel/task.h>
|
||||||
#include <kernel/vm.h>
|
#include <kernel/vm.h>
|
||||||
|
|
||||||
#define R_CF 0
|
#define R_CF 0
|
||||||
@@ -166,36 +169,64 @@ static void print_stack_item(uintptr_t addr)
|
|||||||
printk("%s", buf);
|
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:");
|
printk("call trace:");
|
||||||
|
|
||||||
print_stack_item(ip);
|
print_stack_item(ip);
|
||||||
|
|
||||||
int max_frames = 10, current_frame = 0;
|
int max_frames = 10, current_frame = 0;
|
||||||
while (1) {
|
while (current_frame < max_frames) {
|
||||||
if (!vm_virt_to_phys(stk) || bp == NULL
|
uintptr_t addr = stk.rip;
|
||||||
|| current_frame > max_frames) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
uintptr_t addr = stk->rip;
|
|
||||||
print_stack_item(addr);
|
print_stack_item(addr);
|
||||||
|
|
||||||
stk = (struct stack_frame *)stk->rbp;
|
bp = stk.rbp;
|
||||||
|
if (!read_stack_frame(space, bp, &stk)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
current_frame++;
|
current_frame++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ml_print_stack_trace(uintptr_t ip)
|
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));
|
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)
|
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