1. 程式人生 > >除錯技巧(一):OOPS除錯

除錯技巧(一):OOPS除錯

當核心出現類似使用者空間的Segmentation Fault時(例如核心訪問一個並不存在的虛擬地址), Oops會被列印到控制檯和寫入核心log緩衝區。
我們在globalmem.c的globalmem_read()函式中加上下面一行程式碼
 

} else {
    *ppos += count;
    ret = count;
    *(unsigned int *)0 = 1; /* a kernel panic */
    printk(KERN_INFO "read %u bytes(s) from %lu\n", count, p
}

假設這個字元裝置對應的裝置節點是/dev/globalmem,通過cat/dev/globalmem命令讀裝置檔案,將得到如下Oops資訊:
 

# cat /dev/globalmem
Unable to handle kernel NULL pointer dereference at virtual address 0000
pgd = 9ec08000
[00000000] *pgd=7f733831, *pte=00000000, *ppte=00000000
Internal error: Oops: 817 [#1] SMP ARM
Modules linked in: globalmem
CPU: 0 PID: 609 Comm: cat Not tainted 3.16.0+ #13
task: 9f7d8000 ti: 9f722000 task.ti: 9f722000
PC is at globalmem_read+0xbc/0xcc [globalmem]
LR is at 0x0
pc : [<7f000200>] lr : [<00000000>] psr: 00000013
sp : 9f723f30 ip : 00000000 fp : 00000000
r10: 9f414000 r9 : 00000000 r8 : 00001000
r7 : 00000000 r6 : 00001000 r5 : 00001000 r4 : 00000000
r3 : 00000001 r2 : 00000000 r1 : 00001000 r0 : 7f0003cc
Flags: nzcv IRQs on FIQs on Mode SVC_32 ISA ARM Segment user
Control: 10c53c7d Table: 7ec08059 DAC: 00000015
Process cat (pid: 609, stack limit = 0x9f722240)
Stack: (0x9f723f30 to 0x9f724000)
3f20: 7ed5ff91 9f723f80 00000000 9f7
3f40: 00001000 7ed5eb18 9f723f80 00000000 00000000 800cb114 00000020 9f7
3f60: 9f5e4628 9f79ab40 9f79ab40 00001000 7ed5eb18 00000000 00000000 800
3f80: 00001000 00000000 9f7168c0 00001000 7ed5eb18 00000003 00000003 800
3fa0: 9f722000 8000e360 00001000 7ed5eb18 00000003 7ed5eb18 00001000 000
3fc0: 00001000 7ed5eb18 00000003 00000003 7ed5eb18 00000001 00000003 000
3fe0: 0015c23c 7ed5eb00 0000f718 00008d8c 60000010 00000003 00000000 000
[<7f000200>] (globalmem_read [globalmem]) from [<800cb114>] (vfs_read+0x
[<800cb114>] (vfs_read) from [<800cb2ec>] (SyS_read+0x44/0x84)
[<800cb2ec>] (SyS_read) from [<8000e360>] (ret_fast_syscall+0x0/0x30)
Code: e1a05008 e2a77000 e1c360f0 e3a03001 (e58c3000)
---[ end trace 5a36d6470da50d02 ]---
Segmentation fault

上述Oops的第一行給出了“原因”,即訪問了NULLpointer。 Oops中的PC is at globalmem_read+0xbc/0xcc這一行程式碼也比較關鍵,給出了“事發現場”,即globalmem_read()函式偏移0xbc位元組的指令處。

通過反彙編globalmem.o可以尋找到globalmem_read()函式開頭位置偏移0xbc的指令,反彙編方法如下:
 

 arm-linux-objdump -d -S globalmem.o > err.txt

對應的反彙編程式碼如下, global_read()開始於0x144,偏移0xbc的位置為0x200:
 

static ssize_t globalmem_read(struct file *filp, char __user * buf, size
loff_t * ppos)
{
    144: e92d45f0 push {r4, r5, r6, r7, r8, sl, lr}
    148: e24dd00c sub sp, sp, #12
        //unsigned long p = *ppos;
    14c: e5934000 ldr r4, [r3]

        //*ppos += count;
    1f4: e2a77000 adc r7, r7, #0
    1f8: e1c360f0 strd r6, [r3]
        //ret = count;
        //*(unsigned int *)0 = 1; /* a kernel panic */
    1fc: e3a03001 mov r3, #1
    200: e58c3000 str r3, [ip]
        //printk(KERN_INFO "read %u bytes(s) from %lu\n", count, p);

        //return ret;
}

“str r3, [ip]”是引起Oops的指令。這裡僅僅給出了一個例子,工程實踐中的“事發現場”並不全那麼容易找到,但方法都是類似的。
 

 

也可以參考:

https://www.cnblogs.com/haomcu/p/4385517.html