前言
最近遇到一个kernel奔溃的问题,错误日志开头一部分如下:
[ 355.262451@0] Unhandled fault: external abort on non-linefetch (0x008) at 0xfe004328
[ 355.264547@0] Internal error: : 8 [#1] PREEMPT SMP ARM
[ 355.269632@0] Modules linked in: audio_data mali aml_thermal otz_client(O)
[ 355.276449@0] CPU: 0 PID: 287 Comm: sh Tainted: G O 3.10.33 #1
[ 355.283088@0] task: d9356400 ti: da42a000 task.ti: da42a000
[ 355.288616@0] PC is at dbg_do_command+0x214/0x550
[ 355.293267@0] LR is at dbg_do_command+0x1ec/0x550
[ 355.297924@0] pc : [<c002b694>] lr : [<c002b66c>] psr: 800b0113
[ 355.297924@0] sp : da42bf00 ip : 00000030 fp : 00000000
[ 355.309652@0] r10: dabe930c r9 : da42bf80 r8 : fe004328
[ 355.314999@0] r7 : 00000030 r6 : dac70680 r5 : 00000010 r4 : c090b4bc
[ 355.321641@0] r3 : 00000000 r2 : fe004328 r1 : fe004328 r0 : fe004328
[ 355.328283@0] Flags: Nzcv IRQs on FIQs on Mode SVC_32 ISA ARM Segment user
[ 355.335528@0] Control: 10c5387d Table: 1a62c04a DAC: 00000015
[ 355.341395@0]
对于没有debug经验的人来讲,这段东西其实看得是一头雾水。”external abort on non-linefetch“这是个什么错误呢?网上找到了一个参考链接:http://www.it1352.com/230717.html
这个错误大概是因为试图读取未映射(通过MMU)的内存,按我的理解就是访问了非法的内存地址或者说这个内存地址根本不存在。不管怎么样,反汇编一下看看大概原因吧。
正文
1、首先我们要反汇编一下vmlinux
命令如下:
arm-linux-gnueabihf-objdump -D vmlinux > vmlinux.dis
2、再看一下错误日志的信息:
[ 355.288616@0] PC is at dbg_do_command+0x214/0x550
[ 355.293267@0] LR is at dbg_do_command+0x1ec/0x550
[ 355.297924@0] pc : [<c002b694>] lr : [<c002b66c>] psr: 800b0113
内核是奔溃在dbg_do_command函数的0x214偏移处,也就是地址0xc002b694的地方,另外0x550是dbg_do_command函数的大小,这个我们暂且不用理会。而lr寄存器保存了返回的地址,也就是地址0xc002b66c。我们用c002b694地址在vmlinux.dis里面搜索一下,得到以下结果:
c002b68c: ea000083 b c002b8a0 <dbg_do_command+0x420>
c002b690: f57ff05f dmb sy
c002b694: e5903000 ldr r3, [r0]
c002b698: e3570030 cmp r7, #48 ; 0x30
3、从上面一步,我们可以看到出错的地方是一条读取指令:
ldr r3, [r0]
我们再看一下出错时候各寄存器的值:
[ 355.297924@0] sp : da42bf00 ip : 00000030 fp : 00000000
[ 355.309652@0] r10: dabe930c r9 : da42bf80 r8 : fe004328
[ 355.314999@0] r7 : 00000030 r6 : dac70680 r5 : 00000010 r4 : c090b4bc
[ 355.321641@0] r3 : 00000000 r2 : fe004328 r1 : fe004328 r0 : fe004328
我们可以看到这时候,r0=fe004328,r3=00000000。r3寄存器没什么问题,那就是访问内存地址0xfe004328出现这个错误了。这个地址是芯片商FAE告诉我的,它是一个寄存器的地址,可以通过设置它来打开展频功能。我将这个错误反馈给他们,查实后原来他们给错地址值了,囧!所以当然是访问了非法地址咯。
结语
上面的分析是常规的流程,我也没啥经验,就当做给自己做个记录吧。也希望给遇到同样错误的同学提供一个思路方向。
往期好文:
抽奖!可能会迟到,但从不会缺席
普通人的节奏
回复「 篮球的大肚子」进入技术群聊
回复「1024」获取1000G学习资料