2013-05-24 7 views
12

私が書いたLinuxデバイスドライバにカーネルがあります。私は、どの行がoopsを担当しているのか判断したい。私は以下の出力を持っていますが、それをどのように解釈するのか分かりません。カーネル内のアドレスを解釈する方法oops

私のコードがwrite_func + 0x63の命令でクラッシュしたことを意味しますか? EIPの値を自分の関数にどのように関連付けることができますか?バックスラッシュの後の値はどういう意味ですか?

[10991.880354] BUG: unable to handle kernel NULL pointer dereference at (null) 
[10991.880359] IP: [<c06969d4>] iret_exc+0x7d0/0xa59 
[10991.880365] *pdpt = 000000002258a001 *pde = 0000000000000000 
[10991.880368] Oops: 0002 [#1] PREEMPT SMP 
[10991.880371] last sysfs file: /sys/devices/platform/coretemp.3/temp1_input 
[10991.880374] Modules linked in: nfs lockd fscache nfs_acl auth_rpcgss sunrpc hdrdmod(F) coretemp(F) af_packet fuse edd cpufreq_conservative cpufreq_userspace cpufreq_powersave acpi_cpufreq mperf microcode dm_mod ppdev sg og3 ghes i2c_i801 igb hed pcspkr iTCO_wdt dca iTCO_vendor_support parport_pc floppy parport ext4 jbd2 crc16 i915 drm_kms_helper drm i2c_algo_bit video button fan processor thermal thermal_sys [last unloaded: preloadtrace] 
[10991.880400] 
[10991.880402] Pid: 4487, comm: python Tainted: GF   2.6.37.1-1.2-desktop #1 To be filled by O.E.M. To be filled by O.E.M./To be filled by O.E.M. 
[10991.880408] EIP: 0060:[<c06969d4>] EFLAGS: 00210246 CPU: 0 
[10991.880411] EIP is at iret_exc+0x7d0/0xa59 
[10991.880413] EAX: 00000000 EBX: 00000000 ECX: 0000018c EDX: b7837000 
[10991.880415] ESI: b7837000 EDI: 00000000 EBP: b7837000 ESP: e2a81ee0 
[10991.880417] DS: 007b ES: 007b FS: 00d8 GS: 0033 SS: 0068 
[10991.880420] Process python (pid: 4487, ti=e2a80000 task=df940530 task.ti=e2a80000) 
[10991.880422] Stack: 
[10991.880423] 00000000 0000018c 00000000 0000018c e5e903dc e4616353 00000009 df99735c 
[10991.880428] df900a7c df900a7c b7837000 df80ad80 df99735c 00000009 e46182a4 e2a81f70 
[10991.880433] e28cd800 e09fc840 e28cd800 fffffffb e09fc888 c03718c1 e4618290 0000018c 
[10991.880438] Call Trace: 
[10991.882006] Inexact backtrace: 
[10991.882006] 
[10991.882012] [<e4616353>] ? write_func+0x63/0x160 [mymod] 
[10991.882017] [<c03718c1>] ? proc_file_write+0x71/0xa0 
[10991.882020] [<c0371850>] ? proc_file_write+0x0/0xa0 
[10991.882023] [<c036c971>] ? proc_reg_write+0x61/0x90 
[10991.882026] [<c036c910>] ? proc_reg_write+0x0/0x90 
[10991.882031] [<c0323060>] ? vfs_write+0xa0/0x160 
[10991.882034] [<c03243c6>] ? fget_light+0x96/0xb0 
[10991.882037] [<c0323331>] ? sys_write+0x41/0x70 
[10991.882040] [<c0202f0c>] ? sysenter_do_call+0x12/0x22 
[10991.882044] [<c069007b>] ? _lock_kernel+0xab/0x180 
[10991.882046] Code: f3 aa 58 59 e9 5a f9 d7 ff 8d 0c 88 e9 12 fa d7 ff 01 d9 e9 7b fa d7 ff 8d 0c 8b e9 73 fa d7 ff 01 d9 eb 03 8d 0c 8b 51 50 31 c0 <f3> aa 58 59 e9 cf fa d7 ff 01 d9 e9 38 fb d7 ff 8d 0c 8b e9 30 
[10991.882069] EIP: [<c06969d4>] iret_exc+0x7d0/0xa59 SS:ESP 0068:e2a81ee0 
[10991.882072] CR2: 0000000000000000 
[10991.889660] ---[ end trace 26fe339b54b2ea3e ]--- 
+0

これはまさにその意味です。この場合、割り込みを処理している間にクラッシュしたように見えます。これは、 'write_func()'と何か関係があるかもしれません。完全なトレースまたはソースコードがより便利です。 –

+0

完全なスタックトレースを追加しました。バックスラッシュ後の値はどういう意味ですか?例えば。 write_func + 0x63/_0x160_ –

+1

@HansThen write_func + 0x63/0x160はシンボル+オフセット/長さです。この記事をチェックしてください:http://www.linuxforu.com/2011/01/understanding-a-kernel-oops/ –

答えて

24

あなたが必要なすべての情報はすぐそこです:

[10991.880354] BUG: unable to handle kernel NULL pointer dereference at (null) 

理由だこと。

[10991.880359] IP: [<c06969d4>] iret_exc+0x7d0/0xa59 

これは、障害時の命令ポインタです。私たちはこれを瞬間的に取り上げます。

[10991.880365] *pdpt = 000000002258a001 *pde = 0000000000000000 

物理ページテーブルのエントリです。記述子テーブル、およびページ記述子エントリを含む。当然のことながら、NULLポインタなので、後者はNULLです。上記の値はあまり役に立ちません(物理メモリマッピングが必要な場合のみ)

[10991.880368] Oops: 0002 [#1] PREEMPT SMP 

これはoopsコードです。 PREEMPT SMPは、カーネルがプリエンプティブであり、UPではなくSMP用にコンパイルされていることを示しています。これは、必ずしも犯人ではないが、しばしばあるバグは、いくつかの競合状態からある場合など

[10991.880371] last sysfs file: /sys/devices/platform/coretemp.3/temp1_input 

のために重要です。 sysファイルはさまざまなカーネルモジュールによってエクスポートされますが、sysファイルのI/O操作によってモジュールコードが正しく実行されないことがよくあります。

[10991.880374] Modules linked in: ... [last unloaded: preloadtrace] 

カーネルは必ずしも責任があるどのモジュールを知らないので、それはあなたがそれらのすべてを与えています。また、最近アンロードされたモジュールがカーネルにクリーンアップや残量(タイマーやコールバックのような)を残していないこともよくあります。カーネルは最後にアンロードされたものも報告します。

[10991.880402] Pid: 4487, comm: python Tainted: GF   2.6.37.1-1.2-desktop #1 To be filled by O.E.M. To be filled by O.E.M./To be filled by O.E.M. 

障害スレッドがユーザーモードスレッドの場合は、PIDとコマンドラインが表示されます。 「汚れた」フラグが、それはカーネルのせいではないというのが、カーネルの方法です(カーネルソースはオープンで、「純粋な」。「テイント」冒涜非GPLモジュール、および他の人から来ている。

[10991.880408] EIP: 0060:[<c06969d4>] EFLAGS: 00210246 CPU: 0 
[10991.880411] EIP is at iret_exc+0x7d0/0xa59 

ことができますあなたは、命令ポインタ、両方の直接および記号で+ offset形式の断層運動。スラッシュの後の部分は、関数の大きさである。

[10991.880413] EAX: 00000000 EBX: 00000000 ECX: 0000018c EDX: b7837000 
[10991.880415] ESI: b7837000 EDI: 00000000 EBP: b7837000 ESP: e2a81ee0 
[10991.880417] DS: 007b ES: 007b FS: 00d8 GS: 0033 SS: 0068 

レジスタがここに表示されます。あなたのNULLはEAX可能性がある。

[10991.880420] Process python (pid: 4487, ti=e2a80000 task=df940530 task.ti=e2a80000) 
[10991.880422] Stack: 
[10991.880423] 00000000 0000018c 00000000 0000018c e5e903dc e4616353 00000009 df99735c 
[10991.880428] df900a7c df900a7c b7837000 df80ad80 df99735c 00000009 e46182a4 e2a81f70 
[10991.880433] e28cd800 e09fc840 e28cd800 fffffffb e09fc888 c03718c1 e4618290 0000018c 

スタックポインタの近くの領域が表示されます。カーネルはこれらの値が何を意味するかは分かりませんが、$ rspを表示しているgdbの出力と同じです。だから彼らが何であるか把握するのはあなた次第です。 (例えば、c03718c1はカーネルのリターンアドレスである可能性が高いので、/ proc/kallsymsに行き、それを把握するか、トレースにそのまま置くことができます)。これは、それまでのすべてのデータが今

スタックフレームであることを示しています、あなたはスタックコールトレースを持っているので、あなたが断片を一緒に置くことができます。

再び
[10991.880423] 00000000 0000018c 00000000 0000018c e5e903dc e4616353 --> back to write_func 

[   ] ..................................................... 00000009 df99735c 
[10991.880428] df900a7c df900a7c b7837000 df80ad80 df99735c 00000009 e46182a4 e2a81f70 
[10991.880433] e28cd800 e09fc840 e28cd800 fffffffb e09fc888 c03718c1 --> back to proc_file_write 

[10991.882046] Code: f3 aa 58 59 e9 5a f9 d7 ff 8d 0c 88 e9 12 fa d7 ff 01 d9 e9 7b fa d7 ff 8d 0c 8b e9 73 fa d7 ff 01 d9 eb 03 8d 0c 8b 51 50 31 c0 <f3> aa 58 59 e9 cf fa d7 ff 01 d9 e9 38 fb d7 ff 8d 0c 8b e9 30 

、カーネルがために逆アセンブルすることはできませんあなたは(それはおっとりです、そして非常にうんざりするかもしれません、休憩を与えてください!)。しかし、gdbを使ってこれらの値を逆アセンブルすることができます。

今、あなたはすべてを知っています。あなたは実際に自分のモジュールを逆アセンブルし、NULLポインタが参照解除されたwrite_funcのどこにあるのかを調べることができます。 (おそらくそれを関数の引数として渡しています)。

+0

+1:優れた徹底的なプライマー! – wallyk

+0

Thx非常に。ちょうど私が探していた情報。 –

+0

これまでのところ最高の説明があります –