天天看點

Oops分析方法詳解

Oops是核心程式設計中比較容易遇到的問題,為了跟多的了解Oops來便于調試,我對Oops提供的資訊進行一個總結,以及如何調試Oops。

一個完整的Oops:

BUG: unable to handle kernel paging request at 00316b01

IP: [<c05dd045>] netif_receive_skb+0x335/0x377

*pde = 00000000

Thread overran stack, or stack corrupted

Oops: 0000 [#1] SMP

last sysfs file: /sys/block/hda/size

Modules linked in: mymod ipv6 autofs4 nls_utf8 cifs lockd sunrpc dm_multipath 

scsi_dh video output sbs sbshc battery lp sg snd_ens1371 gameport ide_cd_mod 

snd_rawmidi cdrom snd_ac97_codec ac97_bus snd_seq_dummy snd_seq_oss 

snd_seq_midi_event snd_seq snd_seq_device snd_pcm_oss snd_mixer_oss 

parport_pc ac floppy serio_raw snd_pcm button parport rtc_cmos rtc_core 

rtc_lib snd_timer snd pcnet32 mii soundcore snd_page_alloc i2c_piix4 i2c_core 

pcspkr dm_snapshot dm_zero dm_mirror dm_region_hash dm_log dm_mod ata_piix 

libata mptspi mptscsih mptbase scsi_transport_spi sd_mod scsi_mod ext3 jbd 

uhci_hcd ohci_hcd ehci_hcd [last unloaded: mymod]

Pid: 0, comm: swapper Not tainted (2.6.30.9 #1) VMware Virtual Platform

EIP: 0060:[<c05dd045>] EFLAGS: 00010206 CPU: 0

EIP is at netif_receive_skb+0x335/0x377

EAX: 00316ae1 EBX: deb7d600 ECX: 00316ae1 EDX: e2f357c0

ESI: 00000008 EDI: de9a4800 EBP: c9403f40 ESP: c9403f10

 DS: 007b ES: 007b FS: 00d8 GS: 0000 SS: 0068

Process swapper (pid: 0, ti=c9403000 task=c0737320 task.ti=c0779000)

Stack:

 00316ae1 c07777a0 e2f787c0 00000000 00000001 00000008 00000010 deb7d600

 c9403f40 deb7d600 00000000 df5acc58 c9403fb0 e0e61db0 00000000 00000010

 de9a4bb8 de9a4b40 de9a4800 00002000 00000001 00000000 1ea2c822 deb7d600

Call Trace:

 [<e0e61db0>] ? pcnet32_poll+0x347/0x66a [pcnet32]

 [<c041f984>] ? run_rebalance_domains+0x13d/0x3ed

 [<c05df364>] ? net_rx_action+0x6a/0xf4

 [<c0429e2a>] ? __do_softirq+0x94/0x138

 [<c0429d96>] ? __do_softirq+0x0/0x138

 <IRQ> <0> [<c0429d94>] ? irq_exit+0x29/0x2b

 [<c040423b>] ? do_IRQ+0x6d/0x83

 [<c0402e89>] ? common_interrupt+0x29/0x30

 [<c040828a>] ? default_idle+0x5b/0x92

 [<c0401a92>] ? cpu_idle+0x3a/0x4e

 [<c063d84b>] ? rest_init+0x53/0x55

 [<c077f7df>] ? start_kernel+0x293/0x298

 [<c077f06a>] ? i386_start_kernel+0x6a/0x6f

Code: 74 14 f0 ff 83 a8 00 00 00 8b 4d d8 89 d8 8b 53 14 57 ff 51 08 58 8b 45 

d0 89 45 d8 8b 55 d0 8b 42 20 83 e8 20 89 45 d0 8b 4d d0 <8b> 41 20 0f 18 00 

90 89 c8 83 c0 20 3b 45 d4 75 a4 83 7d d8 00

EIP: [<c05dd045>] netif_receive_skb+0x335/0x377 SS:ESP 0068:c9403f10

CR2: 0000000000316b01

---[ end trace 0330855ac41edfb5 ]---

Kernel panic - not syncing: Fatal exception in interrupt

Pid: 0, comm: swapper Tainted: G      D    2.6.30.9 #1

Call Trace:

 [<c0425ff3>] panic+0x3f/0xdf

 [<c0405644>] oops_end+0x8c/0x9b

 [<c041673a>] no_context+0x10c/0x116

 [<c04168c7>] __bad_area_nosemaphore+0xe0/0xe8

 [<c0416933>] bad_area_nosemaphore+0xd/0x10

 [<c0416aa7>] do_page_fault+0xde/0x1e3

 [<c04169c9>] ? do_page_fault+0x0/0x1e3

 [<c064f38d>] error_code+0x6d/0x74

 [<c061007b>] ? tcp_v4_rcv+0x55b/0x600

 [<c04169c9>] ? do_page_fault+0x0/0x1e3

 [<c05dd045>] ? netif_receive_skb+0x335/0x377

 [<e0e61db0>] pcnet32_poll+0x347/0x66a [pcnet32]

 [<c041f984>] ? run_rebalance_domains+0x13d/0x3ed

 [<c05df364>] net_rx_action+0x6a/0xf4

 [<c0429e2a>] __do_softirq+0x94/0x138

 [<c0429d96>] ? __do_softirq+0x0/0x138

 <IRQ>  [<c0429d94>] ? irq_exit+0x29/0x2b

 [<c040423b>] ? do_IRQ+0x6d/0x83

 [<c0402e89>] ? common_interrupt+0x29/0x30

 [<c040828a>] ? default_idle+0x5b/0x92

 [<c0401a92>] ? cpu_idle+0x3a/0x4e

 [<c063d84b>] ? rest_init+0x53/0x55

 [<c077f7df>] ? start_kernel+0x293/0x298

 [<c077f06a>] ? i386_start_kernel+0x6a/0x6f

解析Oops的具體含義:

BUG: unable to handle kernel paging request at 00316b01

IP: [<c05dd045>] netif_receive_skb+0x335/0x377

*pde = 00000000

Thread overran stack, or stack corrupted

Oops: 0000 [#1] SMP

last sysfs file: /sys/block/hda/size

Modules linked in: mymod ipv6 autofs4 nls_utf8 cifs lockd sunrpc dm_multipath 

scsi_dh video output sbs sbshc battery lp sg snd_ens1371 gameport ide_cd_mod 

snd_rawmidi cdrom snd_ac97_codec ac97_bus snd_seq_dummy snd_seq_oss 

snd_seq_midi_event snd_seq snd_seq_device snd_pcm_oss snd_mixer_oss 

parport_pc ac floppy serio_raw snd_pcm button parport rtc_cmos rtc_core 

rtc_lib snd_timer snd pcnet32 mii soundcore snd_page_alloc i2c_piix4 i2c_core 

pcspkr dm_snapshot dm_zero dm_mirror dm_region_hash dm_log dm_mod ata_piix 

libata mptspi mptscsih mptbase scsi_transport_spi sd_mod scsi_mod ext3 jbd 

uhci_hcd ohci_hcd ehci_hcd [last unloaded: mymod]

上面這段這個是載入的子產品資訊

Pid: 0, comm: swapper Not tainted (2.6.30.9 #1) VMware Virtual Platform

EIP: 0060:[<c05dd045>] EFLAGS: 00010206 CPU: 0

EIP is at netif_receive_skb+0x335/0x377

EIP這行指明發生Oops的具體位置,我們可以通過這個來找到出現Oops的源代碼的具體行。

具體方法如下:

通過使用objdump -S反彙編netif_receice_skb所在的目标檔案,然後找到偏移量為0x355的行,看看這行是有什麼代碼彙編來的,再結合寄存器的值就能分析這個Oops的原因了。

EAX: 00316ae1 EBX: deb7d600 ECX: 00316ae1 EDX: e2f357c0

ESI: 00000008 EDI: de9a4800 EBP: c9403f40 ESP: c9403f10

 DS: 007b ES: 007b FS: 00d8 GS: 0000 SS: 0068

Process swapper (pid: 0, ti=c9403000 task=c0737320 task.ti=c0779000)

Stack:

 00316ae1 c07777a0 e2f787c0 00000000 00000001 00000008 00000010 deb7d600

 c9403f40 deb7d600 00000000 df5acc58 c9403fb0 e0e61db0 00000000 00000010

 de9a4bb8 de9a4b40 de9a4800 00002000 00000001 00000000 1ea2c822 deb7d600

上面這段是寄存器和棧的資訊。

Call Trace:

 [<e0e61db0>] ? pcnet32_poll+0x347/0x66a [pcnet32]

 [<c041f984>] ? run_rebalance_domains+0x13d/0x3ed

 [<c05df364>] ? net_rx_action+0x6a/0xf4

 [<c0429e2a>] ? __do_softirq+0x94/0x138

 [<c0429d96>] ? __do_softirq+0x0/0x138

 <IRQ> <0> [<c0429d94>] ? irq_exit+0x29/0x2b

 [<c040423b>] ? do_IRQ+0x6d/0x83

 [<c0402e89>] ? common_interrupt+0x29/0x30

 [<c040828a>] ? default_idle+0x5b/0x92

 [<c0401a92>] ? cpu_idle+0x3a/0x4e

 [<c063d84b>] ? rest_init+0x53/0x55

 [<c077f7df>] ? start_kernel+0x293/0x298

 [<c077f06a>] ? i386_start_kernel+0x6a/0x6f

發生Oops的核心棧資訊。

Code: 74 14 f0 ff 83 a8 00 00 00 8b 4d d8 89 d8 8b 53 14 57 ff 51 08 58 8b 45 

d0 89 45 d8 8b 55 d0 8b 42 20 83 e8 20 89 45 d0 8b 4d d0 <8b> 41 20 0f 18 00 

90 89 c8 83 c0 20 3b 45 d4 75 a4 83 7d d8 00

EIP: [<c05dd045>] netif_receive_skb+0x335/0x377 SS:ESP 0068:c9403f10

CR2: 0000000000316b01

---[ end trace 0330855ac41edfb5 ]---

Kernel panic - not syncing: Fatal exception in interrupt

Pid: 0, comm: swapper Tainted: G      D    2.6.30.9 #1

如果kernel報告Tainted,說明kernel被損壞了,在“Trainted:”後面最多會有10個字元的提示資訊來表示具體的資訊。每一位上使用一個字母來表示,如下:

1: 'G': 所有的子產品都是GPL的License。如果有子產品缺少MODULE_LICENSE()或者聲明是Proprietary的,則為'P'。

2: 'F': 如果有子產品是使用 insmod -f 強制載入的。否則為空。

3: 'S': 如果Oops發生在SMP的CPU上,但這個型号的CPU還沒有被認為是SMP安全的。

4: 'R': 如果有子產品是使用 rmmod -f 強制解除安裝的。否則為空。

5: 'M': 有CPU報告了Machine Check Exception,否則為空。

6: 'B': 如果有page-release函數發現一個錯誤的page或未知的page标志。

7: 'U': 來自使用者空間的程式設定的這個标志位。

8: 'D': 核心剛剛死掉,比如Oops或者是bug。

9: 'A': ACPI表被覆寫。

10: 'W': 之前kernel已經産生過警告。

Tainted字元串主要的目的是告訴調試器這個kernel已經不是一個幹淨的kernel了。如果一個子產品在加載了之後又解除安裝了,Tainted仍然會保持。

Call Trace:

 [<c0425ff3>] panic+0x3f/0xdf

 [<c0405644>] oops_end+0x8c/0x9b

 [<c041673a>] no_context+0x10c/0x116

 [<c04168c7>] __bad_area_nosemaphore+0xe0/0xe8

 [<c0416933>] bad_area_nosemaphore+0xd/0x10

 [<c0416aa7>] do_page_fault+0xde/0x1e3

 [<c04169c9>] ? do_page_fault+0x0/0x1e3

 [<c064f38d>] error_code+0x6d/0x74

 [<c061007b>] ? tcp_v4_rcv+0x55b/0x600

 [<c04169c9>] ? do_page_fault+0x0/0x1e3

 [<c05dd045>] ? netif_receive_skb+0x335/0x377

 [<e0e61db0>] pcnet32_poll+0x347/0x66a [pcnet32]

 [<c041f984>] ? run_rebalance_domains+0x13d/0x3ed

 [<c05df364>] net_rx_action+0x6a/0xf4

 [<c0429e2a>] __do_softirq+0x94/0x138

 [<c0429d96>] ? __do_softirq+0x0/0x138

 <IRQ>  [<c0429d94>] ? irq_exit+0x29/0x2b

 [<c040423b>] ? do_IRQ+0x6d/0x83

 [<c0402e89>] ? common_interrupt+0x29/0x30

 [<c040828a>] ? default_idle+0x5b/0x92

 [<c0401a92>] ? cpu_idle+0x3a/0x4e

 [<c063d84b>] ? rest_init+0x53/0x55

 [<c077f7df>] ? start_kernel+0x293/0x298

 [<c077f06a>] ? i386_start_kernel+0x6a/0x6f

 最後發現一篇調試Oops的專題:

paper on debugging kernel oops or hang <http://mail.nl.linux.org/kernelnewbies/2003-08/msg00347.html> 雖然是針對2.4的,但還是值得一讀。