
start_kernel
addi sp,sp,-16 ---① 分配栈帧sp=sp-16,sp指向栈顶
sw ra,12(sp) ---② 将ra存储到sp+12的位置
sw s0,8(sp)
xxxxxx
jal ra, 6000dba2 <backtrace>
xxxxxx
lw s0,8(sp)
lw ra,12(sp)
addi sp,sp,16
_backtrace
for(level = 1; level < BT_LEVEL_LIMIT; level++)
backtrace_from_stack(&SP, &PC, &LR, print_func, 1);
for(i = 2; i < BT_SCAN_MAX_LIMIT; i += 2)
riscv_ins16_get_push_lr_framesize(ins16, &offset);
//获取到分配栈帧的位置,地址为parse_addr,该位置也是函数的起始位置,如上的①
//同时也获取到ra的在栈中的偏移位置offset,通过类似sw ra,12(sp)计算得出。
for(i = 0; parse_addr + i < PC; i += 2)
riscv_ins16_backtrace_stask_push(ins16);
//计算函数的起始位置到当前运行的PC位置,使用了多少栈空间。存储到framesize中。
LR = (char *) * (SP + offset);
//计算LR的值,如上②,RA是存储到SP+offset的位置。
*pSP = SP + framesize;
//*pSP即为栈底位置,即为上一个函数的栈顶,为下一次遍历做准备
offset = find_lr_offset(LR, print_func);
print_backtrace(print_func, (unsigned long)LR_fixed - offset);//打印位置
*pPC = LR - offset;
//因为RA存储的是跳转指令的下一条指令,所以需要减去一条指令就得到跳转的位置。
//到这里*pSP、*pPC就更新到上一个函数的值,再接着继续遍历即可。