简体   繁体   English

你如何获得函数的原始地址?

[英]How do you get the raw address of a function?

I'm writing a Jit compiler and I need to call a function based on its (offset) address from assembly. 我正在编写一个Jit编译器,我需要根据汇编中的(偏移)地址调用一个函数。 IE, given: IE,给出:

void myfunction() { }

I want to be able to get the actual address for this function so I can call it by offset from assembly. 我希望能够获得此函数的实际地址,以便我可以通过程序集偏移来调用它。 I've tried a couple of things, but I get different answers: 我尝试了几件事,但我得到了不同的答案:

void *address1 = (void *&)myfunction;
void (*address2)() = &myfunction;

cout << &address1 << endl; // 0x7fff5fbff800
cout << &(*address1) << endl; // 0x20ec8348e5894855
cout << &(address2) << endl; // 0x7fff5fbff808

Which of those is correct (if either of them is)? 哪一个是正确的(如果其中任何一个是)? If there is an easier way I'm overlooking, definitely interested in that as well. 如果有一种我更容易忽视的方式,那对它也很感兴趣。

Update 更新

I did the smart thing and did an objdump , which says: 我做了聪明的事并做了一次objdump ,其中说:

000000010000fd70 <__Z10myfunctionv>:
10000fe76:  48 8d 05 f3 fe ff ff    lea    -0x10d(%rip),%rax        # 10000fd70 <__Z10myfunctionv>

so the correct answer appears to be: 所以正确答案似乎是:

cout << (void *)(void (*)())myfunction << endl; // 0x10000fd70

Per Eric below, this is the best answer: 以下是Eric,这是最好的答案:

cout << hex << (uintptr_t)myfunction << endl;

There is no standard way to do this in C++, because the standard does not define any conversions from pointers to integers or to non-function pointers or any behavior for printing function pointers other than interpreting them as true/false, and function pointers are always true (non-null). 在C ++中没有标准的方法可以做到这一点,因为标准没有定义从指针到整数或非函数指针的任何转换,也没有定义打印函数指针的任何行为,而不是将它们解释为true / false,并且函数指针总是如此true(非null)。 Function pointers are not intended to be printed or exported from a program. 函数指针不打算从程序打印或导出。

In C, you may convert a function pointer to uintptr_t and print that: 在C中,您可以将函数指针转换为uintptr_t并打印出:

#include <inttypes.h>
#include <stdint.h>
#include <stdio.h>
…
    printf("0x%" PRIxPTR "\n", (uintptr_t) myfunction);

Some C++ implementations will allow you to cast function pointers to other types of pointers or to integer types. 某些C ++实现允许您将函数指针强制转换为其他类型的指针或整数类型。 You should ensure the conversions performed by these casts are supported by the C++ implementation(s) you are using before relying on them. 您应确保在依赖它们之前,您正在使用的C ++实现支持这些强制转换所执行的转换。 In some implementations, the value of a function pointer might not be the address of actual code; 在一些实现中,函数指针的值可能不是实际代码的地址; it might be the address of a descriptor of the function. 它可能是函数描述符的地址。 In that case, branching to the address would not work; 在这种情况下,分支到该地址是行不通的; you need to conform to the platform's requirements for calling functions. 您需要符合平台调用函数的要求。

Printing the address of a function for further use in other programs is rarely likely to be of any use. 打印功能的地址以便在其他程序中进一步使用很可能没有任何用处。 Using the printed address to call the function typically requires recompiling the program with new code that uses the address derived from the printing, and changing the program and then recompiling may change the address of the function. 使用打印的地址来调用函数通常需要使用使用从打印派生的地址的新代码重新编译程序,并且更改程序然后重新编译可能会更改函数的地址。 The usual way that a function would be called from assembly is that its address would be provided to assembly code other via the normal linking mechanisms (refer to it by name in assembly and let the linker resolve the reference) or by passing a pointer to the function to the assembly routine as a parameter. 从程序集调用函数的常用方法是将其地址通过常规链接机制提供给汇编代码(在程序集中按名称引用它,让链接器解析引用)或者通过将指针传递给函数作为参数组装例程。

Another option is to place the function in a dynamic library, in which case its address can be looked up by features of the dynamic loader, such as the dlsym routine. 另一种选择是将函数放在动态库中,在这种情况下,可以通过动态加载器的功能(例如dlsym例程)查找其地址。

To get the memory address of a function, use the function name without parentheses. 要获取函数的内存地址,请使用不带括号的函数名称。

void f(); 
void (*p_fun)() = f;

You may optionally include an ampersand: 您可以选择包含&符号:

void f(); 
void (*p_fun)() = & f;

So, for your question, address2 is pointing to the function, to print out its address, use 所以,对于你的问题, address2指向函数,打印出它的地址,使用

cout << address2 << endl;

The correct one is 正确的是

 cout << &(*address1) << endl; // 0x20ec8348e5894855

the same would be 同样的

 cout << address1 << endl; 

The other two are referring to the addresses of the function pointer, ie the variable adress1 and address2. 另外两个是指函数指针的地址,即变量adress1和address2。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM