几个常识概念:
1.程序计数器PC (R15),可以作为一般的通用寄存器使用,但有一些指令在使用R15时有一些限制。由于ARM采用了流水线处理器机制,当正确读取了PC的值时,该值为当前指令地址值加上8个字节。也就是说,对于ARM指令集来说,PC指向当前指令的下两条指令的地址。由于ARM指令是字对齐的,PC值的第0位和第一位总为 0。
2.寄存器R13(SP),通常用作堆栈指针,每一种模式都有自己的物理R13,程序初始化R13。当进入该模式
时,可以将要使用的寄存器保存在R13所指的栈中,当退出时,将弹出,从而实现了现场保护。
3.寄存器R14被称为链接寄存器(LR),当中存放每种模式下,当前子程序的返回地址或者
发生异常中断的时候,将R14设置成异常模式将要返回的地址。
需要用到的交叉编译连工具arm-linx-gdb arm-linux-add2line arm-linux-objdump
一.有自己编译的vmlinux的内核或者应用报错.
如下两个OOPS log
A.
[17184178.672000] Bad mode in data abort handler detected
[17184178.672000] Internal error: Oops - bad mode: 0 [#1] PREEMPT
[17184178.672000] CPU: 0 Not tainted (2.6.26.5 #1255)
[17184178.672000] PC is at 0xd201393a
[17184178.672000] LR is at 0xd20132fd
[17184178.672000] pc : [<d201393a>] lr : [<d20132fd>] psr: 200000bb
[17184178.672000] sp : d202df68 ip : 00000000 fp : 4021fc34
[17184178.672000] r10: 4003e000 r9 : 00000000 r8 : e0096c0c
[17184178.672000] r7 : e00aa340 r6 : e0096c04 r5 : e009e7c0 r4 : 000000b0
[17184178.672000] r3 : e001a418 r2 : 00000000 r1 : e00a11e8 r0 : 00accbad
[17184178.672000] Flags: nzCv IRQs off FIQs on Mode UND_32 ISA Thumb Segment user
[17184178.672000] Control: 0005317d Table: 21aa4000 DAC: 00000015
[17184178.672000] Stack: (0xd202df68 to 0xd002e800)
[17184178.672000] Code: 6868 0029 2800 d01a (6802)
[17184178.676000] ---[ end trace 31c4d86500000008 ]---
B.
[17179681.444000] Internal error: Oops - bad syscall: ddf04c [#1] PREEMPT
[17179681.444000] Modules linked in: coma_dsr coma_voice coma_ss7 coma_cpi coma_config
[17179681.444000] CPU: 0 Not tainted (2.6.26.5 #659)
[17179681.444000] PC is at __dabt_usr+0x4/0x60
[17179681.444000] LR is at 0x377a4
[17179681.444000] pc : [<b4023884>] lr : [<000377a4>] psr: 80000093
[17179681.444000] sp : 4021fc10 ip : 0000f1b4 fp : 4021fc34
[17179681.444000] r10: 4003e000 r9 : 00000000 r8 : 003d0f00
[17179681.444000] r7 : 00000152 r6 : 400286f8 r5 : 402202b0 r4 : 00000000
[17179681.444000] r3 : 000000e4 r2 : 000000e4 r1 : 000f229c r0 : b428bcec
[17179681.444000] Flags: Nzcv IRQs off FIQs on Mode SVC_32 ISA ARM Segment user
[17179681.444000] Control: 0005317d Table: 21990000 DAC: 00000015
[17179681.444000] Process my_app(pid: 81, stack limit = 0xb5b8a268)
上面两种Oops:第一种是UND_32表示是发生了用户空间,第二种SVC_32表示发生在内核空间。pc表示出问题的地址。
对于PC is at 0xd201393a,
首先确认内核源码选项有打开 Kernel hacking ---> Compile-time checks and compiler options ---> [*] Compile the kernel with debug info ,选上这个后,vmlinux就包含了调试所需要的符号表.
直接arm-linux-addr2line -e vmlinx d201393a 可定位PC具体的行,然后再具体分析.
对于PC is at __dabt_usr+0x4/0x60 (表示PC指向_dabt_usr这个函数,这个函数共有0x60大小,错误发生在0x4这个偏移上)
1.这个可以先grep -rn "__dabt_usr" System.map 得到__dabt_usr所对应的地址XXXX,然后加上偏移0x4,就得到PC地址,
2.直接arm-linx-gdb vmlinux 进入调试模式
(gdb) b *pc_addr或者直接 l * __dabt_usr+0x4
可以得到错误代码对应的行
二.KO文件报错
arm-linux-objdump -d faulty.ko > faulty.s
然后打开faulty.s找到对应的函数入口地址,然后根据偏移量在找到对应的行
继续跟踪对应的 c 函数
在原来的Makefile
CFLAGS += -g // 加上 -g 调试
arm-linux-objdump -Dz -S faulty.ko > faulty.s 可以得到更多的调试信息