我尝试了dladdr()
在 Solaris 10/SPARC 上使用的简单测试(但需要注意:GCC 3.4,直接 C),这对我来说很好:
#include <dlfcn.h>
#include <stdio.h>
void print_name(char *name, void *addr);
void print_name_by_dladdr(void *addr);
int main(int argc, const char *argv[])
{
print_name("main", (void *)&main);
print_name("print_name", (void *)&print_name);
print_name("printf", (void *)&printf);
return 0;
}
void print_name(char *name, void *addr)
{
(void)printf("Getting name of function %s() at 0x%x\n", name, addr);
print_name_by_dladdr(addr);
}
void print_name_by_dladdr(void *addr)
{
Dl_info dli;
if(!dladdr(addr, &dli)) {
perror("dladdr()");
exit(1);
}
(void)printf(" %s\n", dli.dli_sname);
}
输出:
Getting name of function main() at 0x10714
main
Getting name of function print_name() at 0x10778
print_name
Getting name of function printf() at 0x209b8
_PROCEDURE_LINKAGE_TABLE_
如果我写(例如),这也可以正常工作
print_name("main", (void *)&main + 4);
您说您可以正确解析输出,nm
因此可能性似乎有限……您确定返回地址是派生的或正确传递给您的解析器函数吗?我猜你正在为此使用GCC 内置函数?我已经测试过__builtin_return_address(0)
了,这对我来说也很好。如果您使用的是 GCC 内置函数,您是否调用__builtin_extract_return_address()
过(有关详细信息,请参见上页,明确提及 SPARC)?你可以发布你的代码吗?
你能稍微延伸一下“处理重新读取它自己的二进制/共享目标文件”吗?如果是这样,那么libelf可能是一种前进的方式。这正是您提到的一些实用程序正在使用的,例如nm
:http ://cr.opensolaris.org/~devnull/6515400/usr/src/cmd/sgs/nm/common/nm.c.html
sun.com 的这篇介绍性文章可能有用(警告:文章已有 10 年历史)。
这不如做原生内省好,而且奇怪的是dladdr(3C)
不起作用:(
替代中间体:您是否尝试过RTLD_DL_SYMENT
标志dladdr1(3C)
(然后可能从nm.c
上面返回的 ELF 符号上借用)?