获取来电者的回信地址

时间:2019-08-23 07:48:19

标签: c++ assembly visual-c++ x86

我试图弄清楚如何在MSVC中获取调用方的返回地址。我可以使用_ReturnAddress()来获取函数的返回地址,但似乎找不到找到调用方的方法。

我尝试使用CaptureStackBackTrace,但是由于某些原因,它在多次调用后崩溃。我也希望通过内联汇编解决方案。

void my_function(){
    cout << "return address of caller_function: " << [GET CALLER'S RETURN VALUE];
} // imaginary return address: 0x15AF7C0

void caller_function(){
     my_function();
}// imaginary return address: 0x15AFA70

输出: return address of caller_function: 0x15AFA70

到目前为止,我还没有运气。感谢您的帮助

1 个答案:

答案 0 :(得分:6)

如果有一个保留的调用堆栈(即在调试版本中或不存在优化的情况下),并考虑将MSVC x86作为目标PE,则可以执行以下操作:

// getting our own return address is easy, and should always work
// using inline asm at all forces MSVC to set up EBP as a frame pointer even with optimization enabled
// But this function might still inline into its caller
__cdecl void *get_own_retaddr()
{
   // consider you can put this asm inline snippet inside the function you want to get its return address
   __asm
   {
       MOV EAX, DWORD PTR SS:[EBP + 4]
   }
   // fall off the end of a non-void function after asm writes EAX:
   // supported by MSVC but not clang's -fasm-blocks option
}

在调试版本中,当在编译器上禁用优化(MSVC编译器参数:/Od)并且未省略帧指针(MSVC编译器参数:/Oy-)时,函数会调用{{1} }函数将始终将返回地址保存在被调用者堆栈帧的偏移量cdecl处。寄存器+4存储正在运行的函数的堆栈帧的开头。因此,在EBP以上的代码中,它将返回其调用者的返回地址。


通过再次阅读您的问题,我认为您可能想要呼叫者的呼叫者的回信地址。您可以通过访问直接调用者的堆栈框架,然后获取其返回地址来实现。像这样:

foo

重要的是要注意,这要求调用方将EBP设置为具有传统堆栈框架布局的框架指针。这不是现代操作系统中的调用约定或ABI的一部分;堆栈展开异常使用不同的元数据。但是,如果禁用了调用方的优化功能,情况就是如此。

如Michael Petch所述,MSVC不允许在x86-64 C / C ++代码上使用 asm inline 构造。尽管如此,编译器允许使用整个 intrinsic functions 来处理该问题。