2011-09-08 39 views
4

我想按名称获取函数的地址。如何按名称获取函数地址?

例如,目前我使用dlsym

unsigned long get_func_addr(const char *func_name) 
{ 
    return (unsigned long)dlsym(NULL, func_name); 
} 

然而,dlsym仅适用于外部函数。它不适用于静态功能。我知道在不同的文件中可能会有多个具有相同名称的静态函数。但我需要至少得到一个静态函数的地址和名称。有时静态函数将被调入。但是,如果C文件是使用调试编译的,那么也可以。我认为与-g,静态功能的符号表是存在的,但我怎么可以访问它?

我不想创建一个表来将字符串映射到函数地址。我需要找到一种动态的方法。

+1

使用'stdint.h'中的'uintptr_t'而不是'unsigned long'。 –

+0

你为什么想这样做?如果你能够保证带有静态模块是以调试模式编译的,你应该能够使该函数成为非静态的,或者为它添加一个简单的非静态包装器。 –

+1

This SO question has some pointers to information on how to read debugging symbols:http://stackoverflow.com/q/5045430/12711 –

回答

3

如果不创建一些可用于查找的外部文件,这实在是不可能的......例如,正如您所提到的,静态函数的符号表存在,但是这是在编译时生成的/链接时间...它不是从非编译代码模块访问的东西。

因此,基本上你可以从编译和链接的可执行文件中生成和导出符号表作为外部文件,然后有一个函数在外部文件中动态地查找函数名,该函数名将提供获取编译器和链接器编译/链接到的函数的地址。

+0

我想这可能是可能的。你知道,backtrace()可以从地址获得函数的名字。扩展回溯以支持从名称获取地址不应太困难。 – limi

+0

是的,但'backtrace()'是'libc'实现的一个函数,因此它是运行您的可执行文件的操作系统运行时的一部分。如果您有另一个程序正在为您的C可执行文件创建一个虚拟运行时,那么您还可以创建可从您的可执行文件调用的函数,以便运行时可以检查您的进程,然后将信息返回给您(即ptrace,调试程序等) 。但是,除非运行时已经在可执行文件和自身之间创建了一种通信方法,否则这在你自己的代码中是不可能的。 – Jason

3

A static函数在二进制文件中甚至不需要存在,所以没有办法得到它的地址。即使它确实存在,它可能已被编译器根据某些参数只能采用特定值的知识进行了修改,或者它可能调用了调用约定,使其不能被外部调用等。唯一的办法就是可以确保存在一个静态函数的“真实”版本,如果它的地址通过函数指针对其他模块可见的话。

0

如果您要查找的功能位于DLL中,您可以使用Windows API getprocaddress(),它将函数的名称和DLL的名称作为参数。

如果你想找到用户定义的函数,我会建议使用查找表作为这些函数的名称不存储。

对于用户定义的函数,可以强制每个函数在其起始处将其名称导出到另一个函数。即:

void my_func() 
{ 
    register(my_func,"my_func");// the address and the name 
    // ... 
} 

因此,你可以稍后按名称查找函数。