kernel oops调试方法一则 - 通过stack表得知代码出错位置的文件名以及行号的方法

kernel上我们可能经常会遇到kernel oops或kernel pannic错误,
通常我们通过串口LOG应该能得到类似下面的debug信息:
----------------------------------------------------------------------------------------------------
[    3.256221] [<c00e4624>] (__queue_work+0x2dc/0x444) from [<c00e47ec>] (queue_work_on+0x38/0x40)
[    3.264889] [<c00e47ec>] (queue_work_on+0x38/0x40) from [<c00e4834>] (queue_work+0x2c/0x54)
[    3.273223] [<c00e4834>] (queue_work+0x2c/0x54) from [<c03a1018>] (switch_key_irq+0x24/0x38)
[    3.281648] [<c03a1018>] (switch_key_irq+0x24/0x38) from [<c010dc48>] (handle_irq_event_percpu+0xe4/0x2d0)
[    3.291281] [<c010dc48>] (handle_irq_event_percpu+0xe4/0x2d0) from [<c010de70>] (handle_irq_event+0x3c/0x5c)
[    3.301086] [<c010de70>] (handle_irq_event+0x3c/0x5c) from [<c0110c3c>] (handle_edge_irq+0x130/0x16c)
[    3.310289] [<c0110c3c>] (handle_edge_irq+0x130/0x16c) from [<c010d6ec>] (generic_handle_irq+0x28/0x3c)
[    3.319669] [<c010d6ec>] (generic_handle_irq+0x28/0x3c) from [<c00b6b8c>] (msm_gpio_irq_handler+0x80/0xcc)
[    3.329301] [<c00b6b8c>] (msm_gpio_irq_handler+0x80/0xcc) from [<c010d6ec>] (generic_handle_irq+0x28/0x3c)
[    3.338936] [<c010d6ec>] (generic_handle_irq+0x28/0x3c) from [<c0042fc0>] (handle_IRQ+0x7c/0xc0)
[    3.347703] [<c0042fc0>] (handle_IRQ+0x7c/0xc0) from [<c003c348>] (gic_handle_irq+0xa8/0x100)
[    3.356211] [<c003c348>] (gic_handle_irq+0xa8/0x100) from [<c05a84d4>] (__irq_svc+0x54/0x80)
----------------------------------------------------------------------------------------------------
 
下面介绍一个通过stack表得知代码出错位置的文件名以及行号的方法:
1. 找到kernel编译时生成的map文件:System.map,此文件位于 out/target/product/<项目名>/obj/KERNEL_OBJ 目录下面
2. 执行命令:
   cat System.map | grep __queue_work
   其中:__queue_work 就是上面debug信息中call stack的第一行,这实际上就是PC指针所在的位置。
   命令返回如下类似的结果:
   c00e4348 t __queue_work
   其中,c00e4348就是符号__queue_work的地址值。
3. 使用交叉编译链的gdb工具加载vmlinux文件
   vmlinux文件与System.map通常是在一个文件夹下,位于 out/target/product/<项目名>/obj/KERNEL_OBJ 目录下面。
   交叉编译链的gdb工具通常名叫:arm-eabi-gdb 此命令在执行 choosecomboext 命令选择项目后即可执行。
   执行命令如下:
   arm-eabi-gdb vmlinux
   命令执行完毕后你就处于了gdb调试环境中。
   此时,计算代码所在位置,就是符号地址 + 偏移量,本例中就是  c00e4348 + 0x2dc 结果是:c00e4624
   在gdb环境中输入以下命令:
   b * 0xC00E4624
   此例中输出了如下结果:
   Breakpoint 1 at 0xc00e4624: file /home/diao/workspace2/ics8x25/kernel/kernel/workqueue.c, line 1037.
   这就是我们想要的答案了,找到代码所在地,本例中,workqueue.c, line 1037 处的代码如下:
   1037   BUG_ON(!list_empty(&work->entry));
   这样我们就知道了代码出错在哪一行。
   当然,可能这里还不是答案,你可能需要继续在call stack中向前查找,但这对于我们定位问题确实有帮助。
   最后,退出gdb环境的命令是:q
 
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值