我试图弄清楚如何在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
到目前为止,我还没有运气。感谢您的帮助
答案 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 来处理该问题。