内核调试死机排查

内核调试死机排查

标签(空格分隔): 内核调试


http://blog.csdn.net/kangear/article/details/8217329
一版出现Unable to handle kernel NULL pointer dereference at virtual address 0xxxxxxx多是空指针或是缓冲区溢出产生
/output/host/usr/bin/mips-linux-gnu-addr2line -e output/build/linux-20160205B/vmlinux 0x8055b480
在串口编译日志里搜索cross可以找到编译链工具mips-linux-gnu-
这个命令可以很好的定位oops信息的具体行数。
这个可以找到出错行数,如果找到行数还不知道错在哪里就可以打印出反汇编文件进行查找了

使用空指针和缓冲区溢出是产生oops的两个最常见原因
还有访问了一个不存在的映射后的寄存器地址。
要让内核出错时能够打印栈回溯信息,编译内核时要增加“-fno-omit-frame-pointer”选项,这可以通过配置 CONFIG_FRAME_POINTER 来实现。

看下面的例子:

Unhandled kernel unaligned access[#1]:
CPU: 0 PID: 1 Comm: swapper Not tainted 3.12.20S3921-00035-g5aba0df-dirty #112
task: 8f8395b0 ti: 8f83a000 task.ti: 8f83a000
$ 0   : 00000000 00000000 808b9774 00000001

$ 4 : 8fa61a00 8fa72878 00000001 fffffffc
$ 8 : 00000008 803c5768 00100100 00000001
$12 : 00000001 80802296 00000000 6e5f3530
$16 : 8fa61a10 80950000 808b9774 00000000
$20 : 808b9774 8088a060 8093a860 80b50000
$24 : 00000018 808e0408
$28 : 8f83a000 8f83bcf0 8fa7c000 804301f8
Hi : 0000000b
Lo : 0000000e
epc : 808e0410 dev_probe+0x8/0x50 //异常程序计数器
exception program counter
Not tainted
ra : 804301f8 driver_probe_device+0x100/0x284 //返回地址 return address
Status: 11008803 KERNEL EXL IE
Cause : 00800014
BadVA : 00000001
PrId : 00019755 (MIPS 74Kc)
Modules linked in:
Process swapper (pid: 1, threadinfo=8f83a000, task=8f8395b0, tls=00000000)
Stack : 80802294 00000008 8fa67b80 8fa61a10 80950000 804301f8 8fa7c000 8fa67c00
8f86cc08 00000000 80740000 8fa61a10 8fa61a44 808b9774 00000000 8093a860
8093a860 80430458 8093a860 8042e2f0 8fa67c00 00000000 00000000 808b9774
804303e0 8042e3a0 8f8352dc 806b60f4 80b50000 8042e150 8f8352cc 8fa73230
808b9774 808abbe0 8fa67c00 8042f7ac 00000000 00000000 00000000 00000000

Call Trace:
[<808e0410>] dev_probe+0x8/0x50
[<804301f8>] driver_probe_device+0x100/0x284
[<80430458>] __driver_attach+0x78/0xb0
[<8042e3a0>] bus_for_each_dev+0x98/0xa8
[<8042f7ac>] bus_add_driver+0x10c/0x278
[<80430c10>] driver_register+0xb0/0x104
[<80431d9c>] platform_driver_probe+0x2c/0xc0
[<808e0818>] dev_init+0x3c0/0x3f0
[<801001b8>] do_one_initcall+0x100/0x1b8
[<808c6adc>] kernel_init_freeable+0x150/0x230
[<806b680c>] kernel_init+0x10/0xf8
[<801082cc>] ret_from_kernel_thread+0x14/0x1c

Code: 27bd0028  27bdffe8  afbf0014 <ac000001> 8c870004  24030068  3c0280b5  70e32802  244210d8 
---[ end trace cd5a6fc207314a1e ]---

Kernel panic - not syncing: Attempted to kill init! exitcode=0x0000000b
我们根据epc : 808e0410 dev_probe+0x8/0x50 ,这是程序异常的地方,执行:
mips-linux-gnu-addr2line -e output/build/vmlinux 0x808e0410
output/build/linux-20160205B/drivers/modules/dev_linux.c:900
可以知道是dev_linux.c的900行

调试手段:
1、在内核的menuconfig中配置调试选项,典型的调试选项位于“kernel hacking”中,很多有用的调试选项CONFIG_DEBUG_SLAB/CONFIG_KALLSYMS…,这种方法比较明显的缺陷:内核体积变大,需要重编内核。
2、调试的万金油–打印,内核态用printk(用户态用printf),这种方法明显的优点是:门槛低,上手快,定位问题有帮助;明显缺点:要不断的加打印和重编内核。同时,要注意优先级的问题。另外,有个技巧就是通过编译宏来控制打印是否使能及使用用户态接口还是内核接口适配你自己的打印宏,从而方便调试。最后,注意内核打印printk有优先级的问题,7种优先级,用户可以根据需要进行配置,也可以通过proc/sys/kernel/printk动态修改设置。
3、通过proc文件系统动态来确认及获取内核一些状态信息。同时,用户也可以实现自己的proc文件,来获取自己想要的信息。
4、ioctl方法,其主要作用于文件描述符上,用户可以定制自己的命令及相应的动作机制,比较灵活。
5、监视调试,通过strace来跟踪系统调用的参数、消耗时间及调用顺序等,比较有用的一个跟踪工具。
6、oops信息分析。
7、魔术键sysrq。这种方法主要针对系统假死的状态比较有效。使用前需要动态配置,使用ALT+SysRQ+各个功能组合。
8、gdb调试内核,可以调试内核映像。
9、kdb内核调试。
10、kgdb调试,明显的缺点是需要两台机器,一台调试机,一台被调试机,通过串口调试。
11、UML(User-Mode Linux),简单的讲就是将linux作为一个用户进程进行调试,最大的缺点就是不能调试与硬件相关的功能,如驱动。
12、LTT,内核的一个补丁包。
13、Dprobe动态茶庄的一个工具。
14、指令断点kprobe,可以对内核的指令动态设置断点。
15、数据断点hw_breakpoint,可以对指令和数据都进行动态监控。
16、perf调试,这个工具社区在不断地更新,而且集成了很多工具具有的功能,后面这个工具要引起重视。
17、oprofile,其实这个工具主要对性能调试,采点关键的性能函数很有用。
18、内核热补丁,非常有用的利器,但可靠性是一个挑战性问题。
19、仿真器或模拟器,这绝对是定位问题的利器,有了他们,上面的一切调试工具都是浮云,呵呵。调试就像在VC窗口下调试一样轻松。

  • 2
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值