调试小技巧记录
查看panic的调用栈
// kernel/printf.c
void backtrace() {
uint64 fp = r_fp(); // 读取帧指针寄存器
uint64 top = PGROUNDUP(fp);
uint64 bottom = PGROUNDDOWN(fp);
printf("backtrace:\n");
while(fp < top && fp > bottom) {
uint64 ra = *(uint64*)(fp - 8); // 返回地址
printf(" %p\n", ra);
fp = *(uint64*)(fp - 16); // 上一帧指针
}
}
void
panic(char *s)
{
pr.locking = 0;
printf("panic: ");
printf(s);
printf("\n");
//新增
printf("\nStack trace:\n");
backtrace();
//新增结束
panicked = 1; // freeze uart output from other CPUs
for(;;)
;
}
// kernel/riscv.h
static inline uint64 r_fp() {
uint64 x;
asm volatile("mv %0, s0" : "=r" (x));
return x;
}
当发生panic时,就会打印出调用栈函数的地址
backtrace:
0x000000008000059e
0x0000000080001234
0x0000000080001a48
0x0000000080002082
0x0000000080002eac
0x0000000080002e20
0x0000000080002b0a
然后结束qemu,通过命令:
riscv64-unknown-elf-addr2line -e kernel/kernel 0x0000000080002b0a
就会打印出函数名和对应的行数