天天看點

Linux系統移植實驗---核心調試實驗十  核心調試

實驗十  核心調試

【實驗目的】

由于在驅動開發中經常看到核心崩潰的問題,最常見的就是OOPS錯誤,本實驗要求學員掌握這種調試方法。

【實驗環境】

1、 ubuntu 12.04發行版

2、 FS4412平台

3、 交叉編譯器 arm-none-linux-gnueabi-gcc

【實驗步驟】

1、通過OOPS資訊中PC寄存器的值可以知道出錯指令的位址,通過棧回朔資訊可以知道出錯時的函數調用的關系,根據這兩點可以很快定位錯誤。

2、 修改drivers/net/ethernet/davicom/dm9000.c,在dm9000_probe函數中u32 id_val;下增加下面語句:

int *ptr  =  NULL;

*ptr  = 0xff;

3、編譯核心下載下傳到開發闆上,核心啟動會出現如類似下資訊:

Unable to handle kernel NULL pointer dereference at virtual address 00000000

pgd = c0004000

[00000000] *pgd=00000000

Internal error: Oops: 805 [#1] PREEMPT SMP ARM

Modules linked in:

CPU: 1 PID: 1 Comm: swapper/0 Not tainted 3.14.0 #11

task: ee8a0000 ti: ee8a4000 task.ti: ee8a4000

PC is at dm9000_probe+0x1c/0x8f0

LR is at platform_drv_probe+0x18/0x48

pc : [<c0277cc8>]    lr : [<c0247f7c>]    psr: 60000153

sp : ee8a5e48  ip : 00000000  fp : 00000000

r10: c052a4fc  r9 : 00000000  r8 : c0591e98

r7 : 00000000  r6 : ee97c810  r5 : ee97c800  r4 : 00000000

r3 : 000000ff  r2 : 00000000  r1 : ee8a5de8  r0 : ee97c800

Flags: nZCv  IRQs on  FIQs off  Mode SVC_32  ISA ARM  Segment kernel

Control: 10c5387d  Table: 4000404a  DAC: 00000015

Process swapper/0 (pid: 1, stack limit = 0xee8a4240)

Stack: (0xee8a5e48 to 0xee8a6000)

5e40:  ee975cf0 00000000 ee1503a8 00000001 c0561afc ee150438

5e60: 00000000 ee97c810 c0591e98 ee97c810 00000000 c0591e98 c0561afc c052a4fc

5e80: 00000000 c0247f7c c0247f64 c05d931c c0591e98 c0246668 ee97c810 c0591e98

5ea0: ee97c844 00000000 c054332c c0246804 c0591e98 c0246778 00000000 c0244fbc

5ec0: ee805478 ee9771c0 c0591e98 eeb73a00 c0590028 c0245e28 c04c3128 c0591e98

5ee0: 00000000 c0591e98 00000000 c054e2ac c059f280 c0246e1c 00000000 ee8a4000

5f00: 00000000 c00087b4 ee903b00 c05c3d50 60000153 c0571c00 60000100 c0571c00

5f20: 00000000 00000000 c0571bfc 00000000 c0505bc8 ef7fc918 00000089 c0034c6c

5f40: c04ca680 c0505338 00000006 00000006 00000000 c054e2c8 c054e2cc 00000006

5f60: c054e2ac c059f280 00000089 c052a4fc 00000000 c052ac4c 00000006 00000006

5f80: c052a4fc c003e0dc 00000000 c03b46ec 00000000 00000000 00000000 00000000

5fa0: 00000000 c03b46f4 00000000 c000e4b8 00000000 00000000 00000000 00000000

5fc0: 0000000000000000 00000000 00000000 00000000 00000000 00000000 00000000

5fe0: 00000000 00000000 00000000 00000000 00000013 00000000 ffffffff ffffffff

[<c0277cc8>] (dm9000_probe) from [<c0247f7c>] (platform_drv_probe+0x18/0x48)

[<c0247f7c>] (platform_drv_probe) from [<c0246668>] (driver_probe_device+0x100/0x210)

[<c0246668>] (driver_probe_device) from [<c0246804>] (__driver_attach+0x8c/0x90)

[<c0246804>] (__driver_attach) from [<c0244fbc>] (bus_for_each_dev+0x58/0x88)

[<c0244fbc>] (bus_for_each_dev) from [<c0245e28>] (bus_add_driver+0xd8/0x1cc)

[<c0245e28>] (bus_add_driver) from [<c0246e1c>] (driver_register+0x78/0xf4)

[<c0246e1c>] (driver_register) from [<c00087b4>] (do_one_initcall+0x30/0x144)

[<c00087b4>] (do_one_initcall) from [<c052ac4c>] (kernel_init_freeable+0xfc/0x1c8)

[<c052ac4c>] (kernel_init_freeable) from [<c03b46f4>] (kernel_init+0x8/0xe4)

錯誤分析:

1、第一行

Unable to handle kernel NULL pointer dereference at virtual address 00000000

說明是空指針造成的錯誤

2、寄存器資訊主要是PC的值

PC is at dm9000_probe+0x1c/0x8f0

pc : [<c0277cc8>]

錯誤定位:

$ arm-none-linux-gnueabi-objdump -D vmlinux > vmlinux.dis   

檔案vmlinux.dis非常大打開需要一定時間

Linux系統移植實驗---核心調試實驗十  核心調試

對于大多數情況,從反彙編代碼定位到C代碼并不會如此容易,需要有較強的閱讀彙編代碼的能力。

另外一種方法是通過addr2line去定位

$ arm-none-linux-gnueabi-addr2line  0xc0277cc8  -e  vmlinux  -f

重要  : 該實驗完成後不要忘記恢複被修改的代碼

繼續閱讀