我有一个Solaris进程,它是一个C ++应用程序,由ld
加载了几个.so
库。该应用程序有一个函数,它在调用函数中获取一个返回地址,然后尝试确定所述调用函数的名称。
如果我使用dladdr(3)
,那么它并不总是放在我希望在Dl_info :: dli_sname中看到的内容。它看起来像是返回一个函数的名称,该函数不是最接近下方或指针值。如果我获取指针值并查看nm
的输出,我可以将该值与我期望的确切函数匹配。
我想知道是否有办法为流程检索符号映射,并让它在不使用dladdr(3)
的情况下搜索函数名称。我特别感兴趣的是获得一个符号映射,不仅可以用于可执行文件本身,还可以用于已加载的所有.so
库。
我在Solaris10 / SPARC上运行,我正在使用gcc 4.2.x。
谢谢!
答案 0 :(得分:4)
我在Solaris 10 / SPARC上使用dladdr()
尝试了一个简单的测试(但需要注意: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 builtins吗?我测试了__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的introductory article可能有用(警告:文章是10年)。
这不如做本机内省那么好,dladdr(3C)
不起作用很奇怪:(
替代中间人:您是否尝试过RTLD_DL_SYMENT
标志dladdr1(3C)
(然后可能在返回的ELF sym上从nm.c
借用)?
答案 1 :(得分:3)
有点晚了,但也许还是一个帮助: 在elf-object文件中,通常有2个符号表: .symtab和.dynsym nm默认读取.symtab,使用nm -D读取.dynsym 表。 dladdr(以及动态加载器)确实使用了 .dynsym表。 .symtab表更完整。 你可以强制所有符号在.dynsym表中 好好使用-rdynamic链接器标志。然而,这种情况变慢了 显着降低链接(例如,在我目前的项目中) aprox的。 200毫秒)。 (nb:上面说的是对linux的引用,但符号处理 在sunos上工作原理相同。命令行选项可能 不同)