出错的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/0xac10 pc : [] lr : [ ] psr: 4000011311 sp : dc05bdb8 ip : dc05bcc0 fp : dc05bdd412 r10: c0a20a80 r9 : 0000009e r8 : c03e274813 r7 : 00000000 r6 : c08ccee4 r5 : c08ccf00 r4 : c075dbbc14 r3 : 00000000 r2 : 00000001 r1 : 20000193 r0 : 0000002015 Flags: nZcv IRQs on FIQs on Mode SVC_32 ISA ARM Segment kernel16 Control: 10c5387d Table: 1000404a DAC: 0000001517 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] ; c03e27e02 56 c03e27bc: eb0c86de bl c070433c 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 6 60 c03e27c8: eb0c86db bl c070433c
可以看出错误的语句是: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-,你编译时也必须是这个,不然算出来的行号可能会偏差比较大。
(End)