Linux 内核OOPS 代码定位

https://blog.csdn.net/weixin_39878023/article/details/98733858?utm_medium=distribute.pc_relevant_t0.none-task-blog-2~default~BlogCommendFromMachineLearnPai2~default-1.control&dist_request_id=&depth_1-utm_source=distribute.pc_relevant_t0.none-task-blog-2~default~BlogCommendFromMachineLearnPai2~default-1.control

几个常识概念:

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 可以得到更多的调试信息

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

九月天-深圳专业软硬件开发

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值