Solaris 进程如何读取自己的符号表?

发布于 2024-11-29 01:17:18 字数 436 浏览 2 评论 0原文

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

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

我想知道是否有一种方法可以检索进程的符号映射并让它在不使用 dladdr(3) 的情况下搜索函数名称。我特别感兴趣的是不仅要获取可执行文件本身的符号映射,还要获取它加载的所有 .so 库的符号映射。

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

谢谢你!

I have a Solaris process, which is a C++ application that is loaded by ld with a few .so libraries. This application has a function that gets a return address in the calling function and then tries to determine the name of the said calling function.

If I use dladdr(3) for that, it does not always put what I expect to see in Dl_info::dli_sname. It looks like it returns a name of a function that is not nearest below or at the pointer value. If I take the pointer value and look at the output of nm, I can match the value to the exact function I expect it to be.

I am wondering if there is a way to retrieve a symbol map for a process and let it search for the function name without using dladdr(3). I am especially interested to get a symbol map not just for the executable itself but also for all .so libraries that it has loaded.

I'm running on Solaris10/SPARC and I'm using gcc 4.2.x.

Thank you!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

我们只是彼此的过ke 2024-12-06 01:17:18

我在 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 内置函数 来实现此目的?我已经测试过 __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 符号)?

I have tried a simple test using dladdr() on Solaris 10/SPARC (but caveats: GCC 3.4, straight C), and this works fine for me:

#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);
}

Output:

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_

This also works correctly if I write (for example)

    print_name("main", (void *)&main + 4);

You say you can resolve correctly against the output of nm so possibilities seem limited... are you certain that the return address is being derived or passed correctly to your resolver function? I guess you are using the GCC builtins for this? I have tested __builtin_return_address(0) and this also works fine for me. If you are using the GCC builtins, did you call __builtin_extract_return_address() (see above page for details, mentions SPARC explicitly)? Can you post your code?

Can you stretch slightly to "process re-reading it's own binary/shared object files"? If so then libelf may be a way forwards. This is exactly what some of those utilities you mention are using, eg nm: http://cr.opensolaris.org/~devnull/6515400/usr/src/cmd/sgs/nm/common/nm.c.html

This introductory article from sun.com might be of use (warning: article is 10 years old).

This isn't as nice as doing native introspection and it's odd that dladdr(3C) doesn't work :(

Alternative intermediate: have you tried the RTLD_DL_SYMENT flag to dladdr1(3C) (and then perhaps borrow from nm.c as above on the returned ELF sym)?

蓝戈者 2024-12-06 01:17:18

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

a little late, but maybe still a help:
in elf-object files, there are generally 2 symbol tables:
.symtab and .dynsym
nm by default reads .symtab, use nm -D to read the .dynsym
table. dladdr (as well as the dynamic loader) do use the
.dynsym table. the .symtab table is more complete.
you can force all symbols being in the .dynsym table as
well using the -rdynamic linker flag. however, this slows
down linking significantly (e.g. in my current project by
aprox. 200ms).
(nb: the above said referes to linux, but the symbol handling
works principly the same on sunos. command line options might
differ)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文