7

我有一个 Solaris 进程,它是一个 C++ 应用程序,由ld几个.so库加载。该应用程序有一个函数,它在调用函数中获取返回地址,然后尝试确定所述调用函数的名称。

如果我使用dladdr(3)它,它并不总是将我期望看到的内容放在 Dl_info::dli_sname 中。看起来它返回的函数名称在指针值下方或指针值处不最近。如果我获取指针值并查看 的输出nm,我可以将该值与我期望的确切函数进行匹配。

我想知道是否有一种方法可以检索进程的符号映射并让它在不使用dladdr(3). 我特别有兴趣获得一个符号映射,不仅适用于可执行文件本身,还适用于.so它已加载的所有库。

我在 Solaris10/SPARC 上运行,我使用的是 gcc 4.2.x。

谢谢!

4

2 回答 2

4

我尝试了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可能是一种前进的方式。这正是您提到的一些实用程序正在使用的,例如nmhttp ://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 符号上借用)?

于 2011-08-12T00:03:17.803 回答
3

有点晚了,但也许仍然有帮助:在 elf-object 文件中,通常有 2 个符号表:.symtab 和 .dynsym nm 默认读取 .symtab,使用 nm -D 读取 .dynsym 表。dladdr(以及动态加载程序)确实使用 .dynsym 表。.symtab 表更完整。您也可以使用 -rdynamic 链接器标志强制所有符号在 .dynsym 表中。但是,这会显着减慢链接速度(例如,在我当前的项目中,大约需要 200 毫秒)。(注意:上面提到的是 linux,但符号处理在 sunos 上的工作原理基本相同。命令行选项可能会有所不同)

于 2011-09-15T10:22:03.223 回答