如何在函数中获取函数返回地址
How to get function return address within function?
我想在我的跟踪器中打印返回值,有两个问题
- 如何获取返回地址
- 返回位置在~Tracer()之前或之后更新
此处需要文本,以便Stackoverflow格式化代码:
struct Tracer
{
int* _retval;
~Tracer()
{ printf("return value is %d", *_retval); }
};
int foo()
{
Tracer __tracter = { __Question_1_how_to_get_return_address_here__ };
if(cond) {
return 0;
} else {
return 99;
}
//Question-2:
// return postion is updated before OR after ~Tracer() called ???
}
我发现了问题1的一些提示,现在检查Vc代码
对于gcc,__builtin_return_addresshttp://gcc.gnu.org/onlinedocs/gcc/Return-Address.html
对于Visual C++,_ReturnAddress
您无法在C++中以便携或可靠的方式做到这一点。返回值可以在存储器或寄存器中,在不同的情况下可以是间接的,也可以不是间接的。
您可能会使用内联汇编来使某些东西在某些硬件/编译器上工作。
一种可能的方法是使Tracer
成为一个模板,它引用一个返回值变量(在适当的时候),并在销毁之前打印出。
还要注意,带有__
(双下划线)的标识符是为实现保留的。
您的问题相当令人困惑,您可以互换使用术语"地址"answers"值",这两个术语是不可互换的。
返回值是函数在x86(_64)中输出的值,它在E/RAX、EDX:EAX或XMM0等中以4/8字节值的形式出现,您可以在此处阅读更多信息。
另一方面,返回地址是E/RSP在进行调用时所指向的地址(也就是堆栈顶部的东西),并保存函数完成时"跳"回的地址(定义称为返回)。
现在我甚至不知道示踪剂是什么tbh,但我可以告诉你你是怎么得到的,这都是关于钩子的。
对于值,假设您在内部执行,只需将函数与具有相同定义的函数挂钩,一旦它返回,您就会得到结果。
对于地址,它有点复杂,因为你必须降低一点,并且可能会做一些asm恶作剧,我真的不知道你到底想做什么,但如果你愿意的话,我做了一个小"存根",为被调用者提供返回指针。
这里是:
void __declspec(noinline) __declspec(naked) __stdcall _replaceFirstArgWithRetPtrAndJump_() {
__asm { //let's call the function we jump to "callee", and the function that called us "caller"
push ebp //save ebp, ESP IS NOW -4
mov ebp, [esp + 4] //save return address
mov eax, [esp + 8] //get callee's address (which is the first param) - eax is volatile so iz fine
mov[esp + 8], ebp //put the return address where the callee's address was (to the callee, it will be the caller)
pop ebp //restore ebp
jmp eax //jump to callee
} }
#define CallFunc_RetPtr(Function, ...) ((decltype(&Function))_replaceFirstArgWithRetPtrAndJump_)(Function, __VA_ARGS__)
unsigned __declspec(noinline) __stdcall printCaller(void* caller, unsigned param1, unsigned param2) {
printf("I'm printCaller, Called By %p; Param1: %u, Param2: %un", caller, param1, param2);
return 20;
}
void __declspec(noinline) doshit() {
printf("us: %pnFunction we're calling: %pn", doshit, printCaller);
CallFunc_RetPtr(printCaller, 69, 420);
}
现在可以肯定的是,您可以也可能应该使用_ReturnAddress()或任何不同编译器的内部函数,但如果这不可用(根据您的工作,这应该是一种非常罕见的情况),并且您了解ASM,这个概念应该适用于任何体系结构,因为无论指令集如何不同,它们都遵循相同的程序计数器设计。
我之所以写这篇文章,是因为很久以前出于某种目的,我一直在寻找答案,但我找不到一个好的答案,因为大多数人都会说"尽管这不可能,也不便携",我觉得这会有所帮助。
- 从函数返回const char*数组
- 检查函数返回类型是否与STL容器类型值相同
- 从 c 或 cpp 系列子函数返回到主函数
- 从函数返回任意简单类型的数据
- 警告:在函数返回类型 [-Wignore 限定符] 时忽略类型限定符
- 从 C++ 中的函数返回数组地址问题
- VirtDisk.h QueryChangesVirtualDisk() 函数返回 RangeCount 为 0
- 为什么glGetSubroutineIndex为不同的函数返回相同的值?
- 在 c++ 中将函数返回类型指定为模板参数
- 从封装在对象中的函数 C++ 返回时为空的列表
- 为什么向量内部的指针在从函数返回时会发生变化?
- 函数返回的 rvalue 引用(表达式)是 xvalue - 但没有标识?
- 程序中的布尔函数返回输入的范围无论如何都是无效的
- 寿命延长从函数返回引用
- 程序不向函数返回值
- 字符串函数返回奇怪的值
- 类的大问题,以及从空函数c++返回
- 为什么在尝试测量函数返回所需的时间时,我的运行时编号是错误的?
- C++二叉搜索树模板从函数返回节点
- NVCC 错误:string_view.h:constexpr 函数返回是非常量