内核和模块oops信息调试
模块加载后出错,打印信息:
Unable to handle kernel NULL pointer dereference at virtual address 00000014 //指针引起的问题
pgd = c3ae8000
[00000014] *pgd=33adb831, *pte=00000000, *ppte=00000000
Internal error: Oops: 817 [#1] ARM
Modules linked in: usb_mouse1(O+)
CPU: 0 Tainted: G O (3.4.2 #8)
PC is at usb_mouse_probe+0x124/0x610 [usb_mouse1] //PC的值,这里表示PC指向的是usb_mouse_probe函数偏移的0x124处,一共0x610
LR is at usb_mouse_probe+0x530/0x610 [usb_mouse1]
pc : [<bf000428>] lr : [<bf000834>] psr: 60000013 //各个寄存器的值
sp : c3a83e40 ip : c3a127a0 fp : 00000001
r10: 00000034 r9 : 00000001 r8 : 00000158
r7 : c3a85e00 r6 : c3a97c00 r5 : 00000001 r4 : c3a12832
r3 : 00000000 r2 : 00000001 r1 : c068b588 r0 : c3a13000
Flags: nZCv IRQs on FIQs on Mode SVC_32 ISA ARM Segment user
Control: c000717f Table: 33ae8000 DAC: 00000015
Process insmod (pid: 973, stack limit = 0xc3a82270) //发生错误的进程
Stack: (0xc3a83e40 to 0xc3a84000) //下面是栈里的值
3e40: c3b08b88 c01e2978 00000000 c3a96148 c3a83e70 c3b08b88 00000000 000000d0
3e60: c3a85e20 c3a85e00 c3a85e20 bf001050 c3a85e20 c3a97c00 bf001020 bf000984
3e80: 00000000 c0379af4 c3a85e20 c3a85e20 bf001050 bf001050 c06ac854 c068ab80
3ea0: 00000000 c02e0420 c3a85e20 c3a85e54 bf001050 c02e05b0 c3a10260 c02e063c
3ec0: 00000000 c3a83ed0 bf001050 c02deec0 c385c618 c3a10410 bf001020 bf001020
3ee0: bf001050 bf001050 c067de44 c02df600 bf000fec 00000000 00000000 bf001020
3f00: bf001050 bf000fec bf001050 c067de44 bf003000 c02e0bfc bf001020 bf0010a0
3f20: bf000fec bf001050 c067de44 c0379888 00019c44 000e2e38 bf0010a0 c3a82000
3f40: c0115668 bf003014 00019c44 c0108750 00000000 00000000 00000000 c0192ad4
3f60: 00019c44 00019c44 000e2e38 bf0010a0 00000000 c0115668 c3a82000 00000000
3f80: befc0e84 c015b6a8 c381dc88 c381dc80 c3842da0 00000001 00000000 befc0e88
3fa0: 00000080 c01154c0 00000001 00000000 000ef040 00019c44 000e2e38 00000000
3fc0: 00000001 00000000 befc0e88 00000080 befc0e84 befc0e88 00000001 befc0e84
3fe0: 00000069 befc0b44 000220a0 b6e2ac24 60000010 000ef040 00000000 00000000
[<bf000428>] (usb_mouse_probe+0x124/0x610 [usb_mouse1]) from [<c0379af4>] (usb_probe_interface+0xc8/0x15c) //栈回溯
[<c0379af4>] (usb_probe_interface+0xc8/0x15c) from [<c02e0420>] (driver_probe_device+0x84/0x214)
[<c02e0420>] (driver_probe_device+0x84/0x214) from [<c02e063c>] (__driver_attach+0x8c/0x90)
[<c02e063c>] (__driver_attach+0x8c/0x90) from [<c02deec0>] (bus_for_each_dev+0x64/0x90)
[<c02deec0>] (bus_for_each_dev+0x64/0x90) from [<c02df600>] (bus_add_driver+0x180/0x248)
[<c02df600>] (bus_add_driver+0x180/0x248) from [<c02e0bfc>] (driver_register+0x58/0x130)
[<c02e0bfc>] (driver_register+0x58/0x130) from [<c0379888>] (usb_register_driver+0x6c/0x120)
[<c0379888>] (usb_register_driver+0x6c/0x120) from [<bf003014>] (usb_mouse_init+0x14/0x40 [usb_mouse1])
[<bf003014>] (usb_mouse_init+0x14/0x40 [usb_mouse1]) from [<c0108750>] (do_one_initcall+0x34/0x17c)
[<c0108750>] (do_one_initcall+0x34/0x17c) from [<c015b6a8>] (sys_init_module+0x84/0x19c)
[<c015b6a8>] (sys_init_module+0x84/0x19c) from [<c01154c0>] (ret_fast_syscall+0x0/0x2c)
Code: e3530002 03a02001 02433002 13a03000 (05832014)
---[ end trace 182099cc61be0d99 ]---
Segmentation fault
从PC的值,可以定位错误发生的地方,这里可以从
PC is at usb_mouse_probe+0x124/0x610 [usb_mouse1]
看出PC发生在usb_mouse_probe
函数偏移0x124
的位置
在板子上执行
# cat /proc/kallsyms // 内核函数、加载的函数的地址,t是静态函数,T是全局函数
截取对我们有用的结果:
00000000 a usb_mouse1.c [usb_mouse1]
bf000000 t usb_mouse_read [usb_mouse1]
bf000000 t $a [usb_mouse1]
bf000914 t usb_mouse_exit [usb_mouse1]
bf000914 t $a [usb_mouse1]
bf00091c t $d [usb_mouse1]
bf000008 t usb_mouse_irq [usb_mouse1]
bf0000dc t $d [usb_mouse1]
bf0000f0 t usb_mouse_release [usb_mouse1]
bf0000f0 t $a [usb_mouse1]
bf000144 t $d [usb_mouse1]
bf000148 t usb_mouse_open [usb_mouse1]
bf000148 t $a [usb_mouse1]
bf00028c t $d [usb_mouse1]
bf0002a8 t usb_mouse_disconnect [usb_mouse1]
bf0002a8 t $a [usb_mouse1]
bf0002fc t $d [usb_mouse1]
bf000304 t usb_mouse_probe [usb_mouse1]
bf000304 t $a [usb_mouse1]
bf00037c t $d [usb_mouse1]
bf000390 t $a [usb_mouse1]
bf000844 t $d [usb_mouse1]
bf003000 t usb_mouse_init [usb_mouse1]
bf003000 t $a [usb_mouse1]
bf003030 t $d [usb_mouse1]
bf000984 r usb_mouse_id_table [usb_mouse1]
bf000984 r $d [usb_mouse1]
bf0009ac r usb_mouse_fops [usb_mouse1]
c4868a88 ? __mod_description389 [usb_mouse1]
c4868a9f ? __mod_license388 [usb_mouse1]
bf001020 d usb_mouse_driver [usb_mouse1]
bf001020 d $d [usb_mouse1]
bf001090 d usb_mouse_class [usb_mouse1]
bf0011e8 b $d [usb_mouse1]
bf0011e8 b devmap [usb_mouse1]
00000000 a usb_mouse1.mod.c [usb_mouse1]
c4868aac ? __module_depends [usb_mouse1]
c4868ab5 ? __mod_vermagic5 [usb_mouse1]
bf00115c d $d [usb_mouse1]
c4873573 n $d [usb_mouse1]
c0376f88 u usb_alloc_urb [usb_mouse1]
c0376ce8 u usb_free_urb [usb_mouse1]
c02dfeec u dev_get_drvdata [usb_mouse1]
c02851d0 u _clear_bit [usb_mouse1]
bf0010a0 d __this_module [usb_mouse1]
c02876a0 u _set_bit [usb_mouse1]
c011a4dc u __aeabi_unwind_cpp_pr0 [usb_mouse1]
c037981c u usb_register_driver [usb_mouse1]
bf000914 t cleanup_module [usb_mouse1]
c018de08 u kfree [usb_mouse1]
bf003000 t init_module [usb_mouse1]
c036f110 u usb_find_interface [usb_mouse1]
c018eab8 u kmem_cache_alloc [usb_mouse1]
c03768e0 u usb_submit_urb [usb_mouse1]
c037ba10 u usb_register_dev [usb_mouse1]
c04cfa24 u printk [usb_mouse1]
c037969c u usb_deregister [usb_mouse1]
c0290a60 u sprintf [usb_mouse1]
c037b974 u usb_deregister_dev [usb_mouse1]
c03767f4 u usb_kill_urb [usb_mouse1]
c066f5d4 u malloc_sizes [usb_mouse1]
c02e00bc u dev_set_drvdata [usb_mouse1]
c018e9e0 u __kmalloc [usb_mouse1]
c02863c4 u _find_next_zero_bit_le [usb_mouse1]
usb_mouse_probe
的基地址是bf000304
,偏移0x124
后,位置就是bf000408
,这与错误信息中的
pc : [<bf000428>] lr : [<bf000834>] psr: 60000013
一样,有时会显示pc:[]
,就可以用上面信息确定位置。在这里又可以看出模块的绝对位置是从bf000000
开始,那么模块的反汇编文件需要找的位置要减去偏移量,算出错误的相对偏移,也就是bf000408
减去bf000000
等于408
确定了位置后,就可以反汇编二进制文件找到对应代码。
如果错误是发生在内核文件中,反汇编vmlinux
文件定位,直接寻找绝对位置就可以,不需要找相对偏移的地方
如果错误发生在模块里,反汇编模块的文件后,寻找相对偏移量的位置。
这里的错误发生在了加载的模块中,所以反汇编加载的模块进行分析:
arm-linux-objdump -S usb_mouse1.ko > objdump_mouse1.txt
-S
参数表示反汇编的时候带上源码,-D参数表示纯反汇编。
反汇编后找到相对偏移量是408
位置的代码查看出错的代码:
else if(intf->cur_altsetting->desc.bInterfaceProtocol == USB_INTERFACE_PROTOCOL_MOUSE) {
usb_mouse_dev->dev_type = USB_DEV_TYPE_MOUSE;
428: 05832014 streq r2, [r3, #20]
这里实际上usb_mouse_dev
指针指向了NULL,dev_type
成员偏移量是20,十六进制是0x14,和错误信息匹配
Unable to handle kernel NULL pointer dereference at virtual address 00000014