Backtrace(moderate)
在kernel/defs.h中添加backtrace的原型
diff --git a/kernel/defs.h b/kernel/defs.h
index 4b9bbc0..137c786 100644
--- a/kernel/defs.h
+++ b/kernel/defs.h
@@ -80,6 +80,7 @@ int pipewrite(struct pipe*, uint64, int);
void printf(char*, ...);
void panic(char*) __attribute__((noreturn));
void printfinit(void);
void backtrace(void);
// proc.c
int cpuid(void);
那样就能在sys_sleep中引用backtrace
diff --git a/kernel/sysproc.c b/kernel/sysproc.c
index e8bcda9..fd19d2a 100644
--- a/kernel/sysproc.c
+++ b/kernel/sysproc.c
@@ -70,6 +70,7 @@ sys_sleep(void)
sleep(&ticks, &tickslock);
}
release(&tickslock);
backtrace();
return 0;
}
将下面的函数添加到kernel/riscv.h
GCC编译器将当前正在执行的函数的帧指针保存在s0寄存器
diff --git a/kernel/riscv.h b/kernel/riscv.h
index 0aec003..7a443e9 100644
--- a/kernel/riscv.h
+++ b/kernel/riscv.h
@@ -311,6 +311,14 @@ r_ra()
return x;
}
static inline uint64
r_fp()
{
uint64 x;
asm volatile("mv %0, s0" : "=r" (x) );
return x;
}
// flush the TLB.
static inline void
sfence_vma()
后续在backtrace中调用此函数来读取当前的帧指针。这个函数使用内联汇编来读取s0
打印返回地址和回溯上一个栈帧
https://pdos.csail.mit.edu/6.828/2020/lec/l-riscv-slides.pdf
返回地址位于栈帧帧指针的固定偏移(-8)位置,并且保存的帧指针位于帧指针的固定偏移(-16)位置
一旦backtrace能够运行,就在kernel/printf.c的panic中调用它,就可以在panic发生时看到内核的backtrace
diff --git a/kernel/printf.c b/kernel/printf.c
index e1347de..7d7900c 100644
--- a/kernel/printf.c
+++ b/kernel/printf.c
@@ -121,6 +121,7 @@ panic(char *s)
printf("panic: ");
printf(s);
printf("\n");
backtrace();
panicked = 1; // freeze uart output from other CPUs
for(;;)
;
@@ -132,3 +133,16 @@ printfinit(void)
initlock(&pr.lock, "pr");
pr.locking = 1;
}
void
backtrace(void)
{
uint64 fp = r_fp();
uint64 top = PGROUNDUP(fp);
uint64 bottom = PGROUNDDOWN(fp);
while(fp < top && fp > bottom){
printf("%p\n", *((uint64 *) (fp - 8)));
fp = *((uint64 *) (fp - 16));
}
}
\ No newline at end of file
结果
bash
xv6 kernel is booting
hart 2 starting
hart 1 starting
init: starting sh
$ bttest
0x0000000080002dd6
0x0000000080002c32
0x000000008000291c
$ QEMU: Terminated
eason@eason-VMware-Virtual-Platform:~/work/xv6-labs-2020$ addr2line -e kernel/kernel
0x0000000080002dd6
/home/eason/work/xv6-labs-2020/kernel/sysproc.c:74
0x0000000080002c32
/home/eason/work/xv6-labs-2020/kernel/syscall.c:140 (discriminator 1)
0x000000008000291c
/home/eason/work/xv6-labs-2020/kernel/trap.c:76