Debugging Tools for Windows

.call (Call Function)

.call 命令使得目标进程执行一个函数。

语法

.call [/vFunction( Arguments ) 
.call /c 
.call /C 
.call /s Prototype Function( Arguments )

参数

/v
显示该call和参数的详细信息。
Function
指定要调用的函数。这可以是函数名(最好带有模块名),或者值等于函数地址的任何表达式。如果需要调用构造函数或析构函数,则必须提供地址 — 或者使用C++表达式来为操作符的名字语法求值 (查看数值表达式语法获取详细信息)。
Arguments
指定传递给函数的参数。如果调用一个方法,第一个参数必须是this,并且所有其它参数跟在后面。参数之间用逗号分开并且要符合常规的参数语法。可以支持不定个数的参数。参数中的表达式使用C++表达式求值器进行求值,查看C++ 数值和操作符获取详细信息。 不能使用字符串作为参数,但是可以使用字符串指针,或目标进程可以访问的其它任何内存。
/c
清除当前线程的任何已存在的call。
/C
清除当前线程的任何已存在的call ,并且将当前线程的上下文重置为保存的上一层call的上下文。
/s Prototype
允许当没有正确的符号时也可以调用由Function指定的函数。这时,必须具有另一个和要调用的函数预定义类型相同的另一个函数的符号。Prototype参数就是这个用来表示预定义类型函数的名字。

环境

模式 仅用户模式
目标 仅活动调试
平台 仅x86和x64

注释

指定函数是被当前进程的当前线程调用的。

只支持 cdeclstdcallfastcallthiscall 调用约定。不能使用该方法调用托管代码。

使用.call 之后,调试器会刷新堆栈,将指令指针修改为指向被调用函数的开头,调用该函数,然后停止。使用g (Go)来恢复执行或者~. g 来执行刚才进行调用的线程。

函数返回时,会发生一次中断并且调试器显示函数的返回值。返回值也会保存在可以得到返回值类型的 $callret 伪寄存器中。

如果使用CTRL+C 或CTRL+BREAK来中断到目标中,当前线程是一个用来处理中断(breakin)的附加线程。 如果这时候使用.call命令,则会使用该额外线程来调用函数。

如果遇到了之前定义的断点,线程不会进行额外的中断。如果在用户模式断点中断时使用.call ,可以使用g来执行整个进程或者 ~. g来执行当前线程。使用g可能会造成程序行为的错误,因为已经将某个线程转移来执行新的函数了。另一方面,该线程还是保留它的锁和其他属性,所以~. g 也可能遇到死锁。

安全的使用.call的方法是,将断点设置到可以安全调用指定函数的代码位置。遇到该断点时,如果需要就可以使用.call来执行函数。如果在不能正常调用该函数的地方使用.call,则可能造成死锁或目标执行错误。

在代码中包含一些只由调试器调用而不由代码来调用的额外函数可能会很有用。例如,可以添加一些函数用来检查代码的当前状态、环境并且将这些状态信息保存到已知的内存位置。注意不能优化代码,否则这些函数会被编译器去除。这种技术应该当作最后的手段,因为如果程序崩溃,.call在调试dump文件时是不能使用的。

.call /c .call /C 命令应该仅在.call 失败,或者进入g命令前改变主意时使用。它们不能随便使用,因为放弃未完成的call会造成目标状态被破坏。

下面的例子说明了如何使用.call /s命令。

.call /s KnownFunction UnknownFunction( 1 )

这里,如果拥有KnownFunction的私有符号,该函数唯一的参数是一个整型,返回值也是整型,如指针或者数组。没有UnknownFunction的符号或者只有共有符号,但是知道它也只有一个整型参数,并且返回一个数组的指针。通过使用/s选项,就可以指定让UnknownFunction按照KnownFunction同样的方式工作。这样就能成功调用UnknownFunction

Build machine: CAPEBUILD