2014-10-23 2 views
4

현재 시스템 교착 상태를 디버그하려고하고 있으며이를 이해하는 데 어려움을 겪고 있습니다.nt! Args가없는 KeWaitForSingleObject

Child-SP   RetAddr   : Args to Child               : Call Site 
fffff880`035cb760 fffff800`02ecef72 : 00000000`00000002 fffffa80`066e8b50 00000000`00000000 fffffa80`066a16e0 : nt!KiSwapContext+0x7a 
fffff880`035cb8a0 fffff800`02ee039f : fffffa80`0b9256b0 00000000`000007ff 00000000`00000000 00000000`00000000 : nt!KiCommitThreadWait+0x1d2 
fffff880`035cb930 fffff880`0312a5e4 : 00000000`00000000 fffff800`00000000 fffffa80`079a3c00 00000000`00000000 : nt!KeWaitForSingleObject+0x19 

왜 KeWaitForSingleObject의 첫 번째 인수는 null입니까?

내가 오해하고있는 경우를 제외하고는 개체가 기다리는 첫 번째 인수가 아닌가요? 교착 상태는 단순히이 스레드가 아무 것도 기다리지 않거나이 일반적인 동작입니까?

1: kd> .thread fffffa800d406b50 
Implicit thread is now fffffa80`0d406b50 
1: kd> kv 
    *** Stack trace for last set context - .thread/.cxr resets it 
Child-SP   RetAddr   : Args to Child               : Call Site 
fffff880`09ed4800 fffff800`02ecef72 : fffffa80`0d406b50 fffffa80`0d406b50 00000000`00000000 fffff8a0`00000000 : nt!KiSwapContext+0x7a 
fffff880`09ed4940 fffff800`02ee039f : 00000000`000000b4 fffffa80`0b1df7f0 00000000`0000005e fffff800`031ae5e7 : nt!KiCommitThreadWait+0x1d2 
fffff880`09ed49d0 fffff800`031d1e3e : fffffa80`0d406b00 00000000`00000006 00000000`00000001 00000000`093bf000 : nt!KeWaitForSingleObject+0x19f 
fffff880`09ed4a70 fffff800`02ed87d3 : fffffa80`0d406b50 00000000`77502410 fffff880`09ed4ab8 fffffa80`0b171a50 : nt!NtWaitForSingleObject+0xde 

이 스레드가 본질적으로 그 자체를 기다리고

:

는 또한 나는 다른 프로세스 (services.exe를) 비슷한 스택 추적을 보여 보여?

답변

10

64 비트 프로세스를 디버깅하고 있습니다.

here으로 설명되는 x64 호출 규칙을 기억하십시오. 처음 4 개의 인수는 레지스터로 전달됩니다. 그런 다음 인수가 스택에 푸시됩니다.

불행히도 kv은 맹목적으로 스택 인수를 표시합니다. 실제로 처음 4 개의 주장이 실제로는 복구 될 수있는 곳에 저장되지 않았을 수 있기 때문에 호출 당시에 실제로 무엇인지 판별하는 것은 매우 어렵습니다 (때로는 불가능).

따라서 nt!NtWaitForSingleObject의 다섯 번째 인수를 찾고 있습니다. 여기서 nullptrTimeout의 일반적인 인수입니다.

운좋게도 우리는 디버깅 유형을 모두 잃어 버리지 않았습니다! 함수가 호출 될 때 인수를 재구성하기 위해 최선을 다하는 windbg 확장이 있습니다. 확장자는 CMKD입니다. 당신은 당신의 winext 폴더에 확장 DLL을 놓고과 같이 호출 할 수 있습니다 : 그들 중 일부는 (unknown)를 그대로 항상 인수를 찾는에서 성공하지 못한

0:000> !cmkd.stack -p 
Call Stack : 7 frames 
## Stack-Pointer Return-Address Call-Site  
00 000000a408c7fb28 00007ffda95b1148 ntdll!NtWaitForSingleObject+a 
    Parameter[0] = 0000000000000034 
    Parameter[1] = 0000000000000000 
    Parameter[2] = 0000000000000000 
    Parameter[3] = (unknown)  
01 000000a408c7fb30 00007ff7e44c13f1 KERNELBASE!WaitForSingleObjectEx+98 
    Parameter[0] = 0000000000000034 
    Parameter[1] = 00000000ffffffff 
    Parameter[2] = 0000000000000000 
    Parameter[3] = 00007ff7e44cba28 
02 000000a408c7fbd0 00007ff7e44c3fed ConsoleApplication2!main+41 
    Parameter[0] = (unknown)  
    Parameter[1] = (unknown)  
    Parameter[2] = (unknown)  
    Parameter[3] = (unknown)  

공지있다. 그러나 64 비트 코드를 디버깅 할 때 매우 유용한 도구입니다.

3

이것은 64 비트 OS처럼 보입니다. 따라서 호출 규칙은 스택의 모든 매개 변수를 전달하지 않습니다. 첫 번째 네 개의 매개 변수는 RCX, RDX, R8 및 R9로 전달되고 나머지 매개 변수는 스택에 전달됩니다. 따라서 KeWaitForSingleObject에 대한 호출을 수신하면 RCX에있는 것을보고 쉽게 이동할 수 있습니다. 그 이상의 스택 프레임이 있으면, 그 레지스터에 어떤 것이로드 될 것이기 때문에 말하기가 어렵습니다. 원래 값은 어딘가에 저장되어 있지만 찾기가 어려울 수 있습니다.