XSLT存档  

不及格的程序员-八神

 查看分类:  ASP.NET XML/XSLT JavaScripT   我的MSN空间Blog

I have recently made a mistake analyzing a callstack, because I didn't expect the application to be 64 bit. I have used the WinDbg command kb to show the callstack and parameters passed to methods.

On 64 bit, the parameters are not passed via the stack but in registers (RCX, RDX, R8 and R9) instead. It seems that WinDbg has not or not fully implemented this. Partly I guess it is almost impossible since the register values might have changed meanwhile.

However, the WinDbg help still lists kb as a valid command under User-Mode, x64 Processor. Therefore my question is:

What does kb display for 64 bit user mode processes? When/how is that output useful?

  •  
    Stack walks cannot show you accurate function argument values. Passed in registers, they were spilled to memory before the register was used to store something else. Very painful if you really need to know, digging out the memory address is not simple. Last time I looked, been a while, it was something I had to learn how to live with.   Sep 9, 2014 at 9:27

The "Args to Child" output shown in kb and kv in WinDbg has always been very suspect, even on the x86 those columns don't necessarily show you the arguments to the function.

On the x86, the "Args to Child" are simply [EBP+0x08], [EBP+0x0C], and [EBP+0x10] (kv shows four arguments, thus the last column is [EBP+0x14]). These will only be the arguments to the function if:

  1. The function uses an EBP frame
  2. The function has stack passed arguments (depends on the calling convention)
  3. The optimizer hasn't reused those locations for something else

On the x64, as you noted the first four arguments to the function are passed via registers. However, as part of the calling convention the caller is required to allocate "Home" (or "Spill") Space on the stack for each of these arguments. This space is always allocated, even if the called function takes fewer than four arguments. The called function is then free to use this Home Space any way it chooses, it may:

  1. Ignore it
  2. Save non-volatile registers there
  3. "Home" the register passed parameters onto the stack

The kb and kv output shows the Home Space in order (RCX Home, RDX Home, R8 Home, R9 Home). Most frequently this space will be used for 1 or 2 above, thus it won't actually have anything to do with the passed in arguments. However, in the Debug build the compiler immediately Homes the passed in arguments to make debugging easier.

For example, here's the prolog of a function with two arguments compiled Debug. Note the Homing of the arguments as the first instructions:

0:000> u DriverEntry
mov     qword ptr [rsp+10h],rdx
mov     qword ptr [rsp+8],rcx
push    rdi
sub     rsp,0C0h

And the same code compiled Release, using the Home Space for non-volatile register preservation:

0:000> u DriverEntry
mov     qword ptr [rsp+8],rbx
mov     qword ptr [rsp+10h],rdi
push    rbp
lea     rbp,[rsp-57h]
sub     rsp,0B0h

This means the Home Space is usually pretty useless in terms of getting the arguments to the function. However, it can still be used as a debugging aid to reconstruct non-volatile register values on function entry (i.e. I can tell you the value of RBX or RDI above by looking at the Home Space)

 
posted on 2023-02-02 11:03  不及格的程序员-八神  阅读(14)  评论(0编辑  收藏  举报