Arm内核的Oops错误定位方法

出错的log信息如下:

 1 Unable to handle kernel NULL pointer dereference at virtual address 00000014
 2 pgd = c0004000
 3 [00000014] *pgd=00000000
 4 Internal error: Oops: 5 [#1] PREEMPT SMP ARM
 5 Modules linked in:
 6 CPU: 0 PID: 1 Comm: swapper/0 Not tainted 3.10.45 #125
 7 task: dc078000 ti: dc05a000 task.ti: dc05a000
 8 PC is at at24c02_probe+0x78/0xa0
 9 LR is at wake_up_klogd+0x84/0xac
10 pc : [<c03e27c0>]    lr : [<c002d9b0>]    psr: 40000113
11 sp : dc05bdb8  ip : dc05bcc0  fp : dc05bdd4
12 r10: c0a20a80  r9 : 0000009e  r8 : c03e2748
13 r7 : 00000000  r6 : c08ccee4  r5 : c08ccf00  r4 : c075dbbc
14 r3 : 00000000  r2 : 00000001  r1 : 20000193  r0 : 00000020
15 Flags: nZcv  IRQs on  FIQs on  Mode SVC_32  ISA ARM  Segment kernel
16 Control: 10c5387d  Table: 1000404a  DAC: 00000015
17 Process swapper/0 (pid: 1, stack limit = 0xdc05a238)

1) 根据log信息,PC的值是 PC is at at24c02_probe+0x78/0xa0;

  at24c02_probe:表示出错的函数;

  0x78:表示出错语句在出错函数中的偏移位置;

  0xa0:表示at24c02_probe函数的大小;

2) 利用arm-none-linux-gnueabi-gcc-nm命令,找出函数at24c02_probe在内核中的线性地址(也可以从System.map文件中查找):

  arm-none-linux-gnueabi-gcc-nm vmlinux | grep at24c02_probe

  (vmlinux是没有压缩的镜像文件,在内核的编译文件夹中)

输出结果如下:

1 c03e2748 t at24c02_probe

说明at24c02_probe函数在内核中起始线性地址是0xc03e2748;

3) 根据偏差值0x78,利用arm-none-linux-gnueabi-objdump命令,显示出地址c03e2748-c03e27ff的反汇编(估算大概范围):

  arm-none-linux-gnueabi-objdump -S vmlinux --start-address=0xc03e2748 --stop-address=0xc03e27ff > /tmp/file

  偏差值+函数的起始地址=0x78+0xc03e2748=0xc03e27c0(也可以从log的pc值取得)

从file文件中找到的错误地方如下:

1  c03e27b8:       e59f0020        ldr     r0, [pc, #32]   ; c03e27e0 <at24c02_probe+0x98>
2  56 c03e27bc:       eb0c86de        bl      c070433c <printk>
3  57     printk("The i2c device id data is %d\n", id->driver_data);
4  58 c03e27c0:       e5971014        ldr     r1, [r7, #20]
5  59 c03e27c4:       e59f0018        ldr     r0, [pc, #24]   ; c03e27e4 <at24c02_probe+0x9c>
6  60 c03e27c8:       eb0c86db        bl      c070433c <printk>

可以看出错误的语句是:printk("The i2c device id data is %d\n", id->driver_data);

另外一种方法: 

直接通过addr2line命令获取:

在编译的源码文件夹地下执行以下的命令,就可以显示出那一个函数哪一行代码出了问题, 

   arm-none-linux-gnueabi-addr2line -e vmlinux c03e27c0

/opt/Sourcery_CodeBench_for_ARM_Embedded/bin/arm-none-linux-gnueabi-addr2line -e vmlinux c03e27c0

注:请确保CROSS_COMPILE跟你编译用的是一样的前缀,例如上面的arm-none-linux-gnueabi-,你编译时也必须是这个,不然算出来的行号可能会偏差比较大。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值