ARM 架构 dump_stack 实现分析(2.0 调用时序)

看下具体调用时序:

void dump_stack(void)
{
	dump_backtrace(NULL, NULL);
}


 

dump_stack
    -->dump_backtrace
            -->unwind_backtrace 
                - ->dump_backtrace_entry
                     -->printk(%pS)
                         - ->kallsyms_lookup


 

void unwind_backtrace(struct pt_regs *regs, struct task_struct *tsk)
{
	struct stackframe frame;
        ......
        //得到 FP ,SP ,LR ,及 PC的值
        //其中真正用的是: FP及PC
	if (regs) {
		frame.fp = regs->ARM_fp;
		frame.sp = regs->ARM_sp;
		frame.lr = regs->ARM_lr;
		/* PC might be corrupted, use LR in that case. */
		frame.pc = kernel_text_address(regs->ARM_pc)
			 ? regs->ARM_pc : regs->ARM_lr;
	} 
	while (1) {
		int urc;
		unsigned long where = frame.pc;
                //设置上一帧的FP,PC,SP等值
		urc = unwind_frame(&frame);
		if (urc < 0)
			break;
                //打印出对应函数指针的函数名及偏移量
		dump_backtrace_entry(where, frame.pc, frame.sp - 4);
	}
}


 

// 堆栈的大小,FP指针不能超过此值
#define THREAD_SIZE		8192
int notrace unwind_frame(struct stackframe *frame)
{
	unsigned long high, low;
	unsigned long fp = frame->fp;

	//此时,堆栈地址是一步一步往高地址爬的
	low = frame->sp;
	high = ALIGN(low, THREAD_SIZE);

	//确保帧指针是合法的
	if (fp < (low + 12) || fp + 4 >= high)
		return -EINVAL;
         //从堆栈中取出之前备份的值,设置成上一帧的值
         // 为什么是 -12 -8 - 4
         //因为函数调用前大概会执行:
      // ldm  sp, {fp, sp, pc}   把当前fp, sp, pc的值保存到堆栈中
	frame->fp = *(unsigned long *)(fp - 12);
	frame->sp = *(unsigned long *)(fp - 8);
	frame->pc = *(unsigned long *)(fp - 4);

	return 0;
}



大家可以想想,为什么有了LR寄存器,还要保存pc值在堆栈中。
个人LR保存的是调用函数指令,下面的代码地址,不能反映当时真实的函数调用
配合下面这张函数调用堆栈图,可能会更清晰些:

当然编译内核的时候,要打开 CONFIG_KALLSYMS ,这样才能查找找函数地址对应的函数名及偏移量
void dump_backtrace_entry(unsigned long where, unsigned long from, unsigned long frame)
{
#ifdef CONFIG_KALLSYMS
        //记住%pS是关键  printk 与 普通printf最大的不同
        //惭愧啊,现在才知道此选项
	printk("symbol<%08lx>] (%pS) from [<%08lx>] (%pS)\n", where, (void *)where, from, (void *)from);
#else
	printk("Function entered at [<%08lx>] from [<%08lx>]\n", where, from);
#endif
	if (in_exception_text(where))
		dump_mem("", "Exception stack", frame + 4, frame + 4 + sizeof(struct pt_regs));
}


 

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值