static void dump_backtrace(struct pt_regs *regs, struct task_struct *tsk)
{
struct stackframe frame;
pr_debug("%s(regs = %p tsk = %p)\n", __func__, regs, tsk);
if (!tsk)
tsk = current;
if (regs) {
frame.fp = regs->regs[29];
frame.sp = regs->sp;
frame.pc = regs->pc;
} else if (tsk == current) {
frame.fp = (unsigned long)__builtin_frame_address(0);
frame.sp = current_stack_pointer;
frame.pc = (unsigned long)dump_backtrace;
} else {
/*
* task blocked in __switch_to
*/
frame.fp = thread_saved_fp(tsk);
frame.sp = thread_saved_sp(tsk);
frame.pc = thread_saved_pc(tsk);
}
pr_emerg("Call trace:\n");
while (1) {
unsigned long where = frame.pc;
int ret;
ret = unwind_frame(&frame);
if (ret < 0)
break;
dump_backtrace_entry(where, frame.sp);
}
}
/*
* This struct defines the way the registers are stored on the stack during an
* exception. Note that sizeof(struct pt_regs) has to be a multiple of 16 (for
* stack alignment). struct user_pt_regs must form a prefix of struct pt_regs.
*/
struct pt_regs {
union {
struct user_pt_regs user_regs;
struct {
u64 regs[31];
u64 sp;
u64 pc;
u64 pstate;
};
};
u64 orig_x0;
u64 syscallno;
};
struct stackframe {
unsigned long fp;
unsigned long sp;
unsigned long pc;
};
/*
* AArch64 PCS assigns the frame pointer to x29.
*
* A simple function prologue looks like this:
* sub sp, sp, #0x10
* stp x29, x30, [sp]
* mov x29, sp
*
* A simple function epilogue looks like this:
* mov sp, x29
* ldp x29, x30, [sp]
* add sp, sp, #0x10
*/
int notrace unwind_frame(struct stackframe *frame)
{
unsigned long high, low;
unsigned long fp = frame->fp;
low = frame->sp;
high = ALIGN(low, THREAD_SIZE);/*fp的内容是stack: 所以下面的位置比较*/
if (fp < low || fp > high - 0x18 || fp & 0xf)
return -EINVAL;
/*已知当前帧的fp:+0x10 得到caller的sp*/
/*已知当前帧的fp: 得到caller的fp*/
/*已知当前帧的fp: +0x8得到caller的pc*/
frame->sp = fp + 0x10;
frame->fp = *(unsigned long *)(fp);
/*
* -4 here because we care about the PC at time of bl,
* not where the return will go.
*/
frame->pc = *(unsigned long *)(fp + 8) - 4;
return 0;
}
static void dump_backtrace_entry(unsigned long where, unsigned long stack)
{
print_ip_sym(where);
if (in_exception_text(where))
dump_mem("", "Exception stack", stack,
stack + sizeof(struct pt_regs));
}
static inline void print_ip_sym(unsigned long ip)
{
printk("[<%p>] %pS\n", (void *) ip, (void *) ip);
}
进程的堆栈中保存的内容:肯定包括LR:
frame->pc = *(unsigned long *)(fp + 8) - 4;
如果从打印的看:应该是%p+4:在堆栈中.请验证下:找到了fp: 就找到了函数的栈.A4