kb对64位进程显示什么



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

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

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

对于64位用户模式进程,kb显示什么?该输出何时/如何有用?

WinDbg中以kb和kv显示的"Args to Child"输出一直很可疑,即使在x86上,这些列也不一定会向您显示函数的参数。

在x86上,"Args to Child"简单地为[EBP+0x08]、[EBP+00x0C]和[EBP+0x10](kv显示四个自变量,因此最后一列为[EBP+0x14])。只有在以下情况下,这些才是函数的自变量:

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

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

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

kb和kv输出按顺序显示Home Space(RCX Home、RDX Home、R8 Home、R9 Home)。这个空格通常用于上面的1或2,因此它实际上与传入的参数没有任何关系。但是,在调试构建中,编译器会立即将传入的参数放置在原位,以使调试更容易。

例如,下面是一个函数的序言,其中包含编译Debug的两个参数。注意参数的归位作为第一条指令:

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

并编译了相同的代码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

这意味着Home Space在为函数获取参数方面通常非常无用。然而,它仍然可以用作调试辅助工具,在函数条目上重建非易失性寄存器值(即,我可以通过查看主页空间告诉您上面RBX或RDI的值)

kb确实列出了堆栈回溯和三个参数,但参数传递机制(调用约定)并不能使显示的参数可信。您必须阅读更多内容@http://www.codemachine.com/article_x64deepdive.html

dv和所有其他变体dv/v等都可以显示垃圾值。只有在__this调用的情况下,我们才能使用rcx作为this指针,但我们必须反汇编并确保指针没有备份到其他地方,然后重用。除非我们有固定的参数,否则拆卸是可行的。

最新更新