没有Args的KeWaitForSingleObject

时间:2014-10-23 21:31:31

标签: windows windbg windows-nt

我目前正在尝试调试系统死锁,而我很难理解这一点。

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的第一个参数为空?

除非我误解了对象等待的第一个参数? 死锁只是说这个线程没有等待或是这种普通的行为吗?

此外,我看到另一个显示类似堆栈跟踪的进程(services.exe):

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

这个帖子本身是在等待吗?

2 个答案:

答案 0 :(得分:12)

您正在调试64位进程。

记住x64调用约定,解释为here。前4个参数在寄存器中传递。之后,参数被压入堆栈。

不幸的是,kv盲目地显示堆栈参数。实际上,它很难(有时甚至不可能)确定调用时实际上前4个参数是什么,因为它们可能没有存储在任何可以恢复的地方。

因此,您正在查看nt!NtWaitForSingleObject的第5个参数,其中nullptrTimeout的非常典型的参数。

幸运的是我们调试类型,一切都不会丢失!有一个windbg扩展,它在调用函数时尽力重建参数。该扩展名称为CMKD。您可以将扩展DLL放在winext文件夹中,并按如下方式调用它:

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)       

请注意,它并不总能成功找到参数,因为其中一些是(unknown)。但是,它做得非常好,在调试64位代码时可以成为一个非常宝贵的工具。

答案 1 :(得分:4)

这看起来像64位操作系统,因此调用约定不是传递堆栈上的所有参数。相反,前四个参数在RCX,RDX,R8和R9中传递,其余参数在堆栈上。因此,如果您接到对KeWaitForSingleObject的调用,很容易看到RCX中的内容并从那里开始。一旦你有几个堆栈帧,那么很难分辨,因为有些东西会被加载到该寄存器中。原始值可能存储在某处,但很难找到。