2013-05-24 2 views
12

내가 작성한 리눅스 장치 드라이버에 커널이 있습니다. 어떤 라인이 그럴 수 있는지 결정하고 싶습니다. 나는 다음과 같은 결과를 얻었지만 해석 방법을 모른다.커널에서 주소를 해석하는 법 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 

그게 죄송합니다. PREEMPT SMP는 커널이 preemptible이며 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] 

커널은 반드시 비난하는 어떤 모듈을 모르는, 그래서 당신이 그들 모두를주고 있어요. 또한, 최근에 언로드 된 모듈이 정리되지 않고 커널에 일부 잔여 물 (일부 타이머 또는 콜백과 같은)을 남겨 두었을 수도 있습니다. 이것은 oops 또는 패닉의 고전적인 사례입니다. 따라서 커널은 마지막으로 언로드 된 것을보고합니다.

[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 

즉 제공 당신은 장애 유발 명령 포인터는 모두 직접 기호에 양식 오프셋 +. 슬래시 이후의 부분은 함수의 크기입니다.

[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 

스택 포인터 근처의 영역이 표시됩니다. 커널은이 값들이 무엇을 의미하는지 알지 못하지만 gdb가 $ rsp를 표시 할 때 얻는 출력과 같습니다. 따라서 그들이 무엇인지 파악하는 것은 당신에게 달려 있습니다. (예를 들어, 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

감사합니다. –