我正在编写一个Jit编译器,我需要根据汇编中的(偏移)地址调用一个函数。 IE,给出:
void myfunction() { }
我希望能够获得此函数的实际地址,以便我可以通过偏移从程序集调用它。我尝试了几件事,但我得到了不同的答案:
void *address1 = (void *&)myfunction;
void (*address2)() = &myfunction;
cout << &address1 << endl; // 0x7fff5fbff800
cout << &(*address1) << endl; // 0x20ec8348e5894855
cout << &(address2) << endl; // 0x7fff5fbff808
哪一个是正确的(如果其中任何一个是)?如果有一种我更容易忽视的方式,那么对它也很感兴趣。
更新
我做了聪明的事并做了一个objdump
,其中说:
000000010000fd70 <__Z10myfunctionv>:
10000fe76: 48 8d 05 f3 fe ff ff lea -0x10d(%rip),%rax # 10000fd70 <__Z10myfunctionv>
所以正确答案似乎是:
cout << (void *)(void (*)())myfunction << endl; // 0x10000fd70
以下是Eric,这是最好的答案:
cout << hex << (uintptr_t)myfunction << endl;
答案 0 :(得分:6)
在C ++中没有标准的方法可以做到这一点,因为标准没有定义从指针到整数或非函数指针的任何转换,也没有定义打印函数指针的任何行为,而不是将它们解释为true / false,以及函数指针始终为true(非null)。函数指针不打算从程序中打印或导出。
在C中,您可以将函数指针转换为uintptr_t
并打印出:
#include <inttypes.h>
#include <stdint.h>
#include <stdio.h>
…
printf("0x%" PRIxPTR "\n", (uintptr_t) myfunction);
某些C ++实现允许您将函数指针强制转换为其他类型的指针或整数类型。您应确保在依赖它们之前,您正在使用的C ++实现支持这些强制转换所执行的转换。在一些实现中,函数指针的值可能不是实际代码的地址;它可能是函数描述符的地址。在这种情况下,分支到该地址是行不通的;您需要符合平台调用函数的要求。
打印功能的地址以便在其他程序中进一步使用很可能没有任何用处。使用打印的地址来调用函数通常需要使用使用从打印派生的地址的新代码重新编译程序,并且更改程序然后重新编译可能会更改函数的地址。从程序集调用函数的常用方法是将其地址通过常规链接机制提供给汇编代码(在程序集中按名称引用它,让链接器解析引用)或者通过将指针传递给将装配例程作为参数运行。
另一种选择是将函数放在动态库中,在这种情况下,可以通过动态加载器的功能查找其地址,例如dlsym
例程。
答案 1 :(得分:2)
要获取函数的内存地址,请使用不带括号的函数名称。
void f();
void (*p_fun)() = f;
您可以选择包含&符号:
void f();
void (*p_fun)() = & f;
因此,对于您的问题,address2
指向该函数,打印出其地址,使用
cout << address2 << endl;
答案 2 :(得分:2)
正确的是
cout << &(*address1) << endl; // 0x20ec8348e5894855
同样是
cout << address1 << endl;
另外两个是指函数指针的地址,即变量adress1和address2。