kb对64位进程有什么作用?

Tho*_*ler 7 debugging 64-bit windbg stack-trace

我最近在分析一个callstack时犯了一个错误,因为我没想到应用程序是64位的.我使用WinDbg命令kb来显示传递给方法的callstack和参数.

在64位时,参数不通过堆栈传递,而是通过寄存器(RCX,RDX,R8和R9)传递.似乎WinDbg没有或没有完全实现这一点.部分我想这几乎是不可能的,因为寄存器值可能同时发生了变化.

但是,WinDbg帮助仍然kb列为有效命令User-Mode, x64 Processor.因此我的问题是:

kb64位用户模式进程的显示内容是什么?何时/如何输出有用?

sno*_*one 7

在WinDbg中以kb和kv显示的"Args to Child"输出始终非常可疑,即使在x86上,这些列也不一定显示函数的参数.

在x86上,"Args to Child"只是[EBP + 0x08],[EBP + 0x0C]和[EBP + 0x10](kv显示四个参数,因此最后一列是[EBP + 0x14]).这些只是函数的参数,如果:

  1. 该函数使用EBP框架
  2. 该函数有堆栈传递的参数(取决于调用约定)
  3. 优化器没有重复使用这些位置

在x64上,正如您所注意到的,函数的前四个参数通过寄存器传递.但是,作为调用约定的一部分,调用者需要在堆栈上为每个参数分配"Home"(或"Spill")空间.即使被调用的函数少于四个参数,也始终会分配此空间.然后,被调用的函数可以自由选择使用此Home Space,它可以:

  1. 忽略它
  2. 在那里保存非易失性寄存器
  3. "Home"寄存器将参数传递到堆栈

kb和kv输出按顺序显示Home Space(RCX Home,RDX Home,R8 Home,R9 Home).最常见的是这个空间将用于上面的1或2,因此它实际上与传入的参数没有任何关系.但是,在Debug构建中,编译器立即对传入的参数进行Homes,以使调试更容易.

例如,这里是一个带有两个参数编译Debug的函数的序言.注意参数的归位作为第一条指令:

0:000> u DriverEntry
mov     qword ptr [rsp+10h],rdx
mov     qword ptr [rsp+8],rcx
push    rdi
sub     rsp,0C0h
Run Code Online (Sandbox Code Playgroud)

并且相同的代码编译了Release,使用Home Space进行非易失性寄存器保存:

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
Run Code Online (Sandbox Code Playgroud)

这意味着在获取函数的参数方面,Home Space通常是无用的.但是,它仍然可以用作调试辅助来重建函数入口上的非易失性寄存器值(即我可以通过查看Home Space告诉您上面的RBX或RDI的值)