如果我使用dladdr(3),它并不总是把我期望在Dl_info :: dli_sname中看到.看起来它返回的函数名称不是最接近下方或指针值.如果我取指针值并查看nm的输出,我可以将该值与我期望的确切函数匹配.
我想知道是否有办法检索进程的符号映射,并让它搜索函数名称而不使用dladdr(3).我特别感兴趣的是获得一个符号映射,不仅可以用于可执行文件本身,还可以用于已加载的所有.so库.
我在Solaris10 / SPARC上运行,我正在使用gcc 4.2.x.
谢谢!
解决方法
#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借用)?