4

我有一个动态加载库的应用程序,它动态加载库...

在 Windows 中,我可以遍历所有加载的模块以查找我感兴趣的符号。不知道如何在 Unix/Linux 环境中执行此操作。我知道我可以对前两个符号使用dlsym(dlopen(0, flag))ordlsym(RTLD_DEFAULT / RTLD_NEXT)并且知道要搜索的模块的顺序——我怎样才能更深入并获得给定符号的所有定义?

4

2 回答 2

6

要在分片对象中查找符号,请使用dlopen.

 void* foobar = dlopen ("/usr/local/lib/foobar.so", RTLD_NOW);
 void* mysymbol = dlsym (foobar, "mysymbol");

更新这是一个迭代所有名为“foo”的符号的程序。这不是 POSIX,而是 GNU 库。我几乎可以肯定 POSIX 不提供这样的功能。

#define _GNU_SOURCE 
#include <link.h>
#include <dlfcn.h>
#include <stdio.h>

void doit (const char* s)
{
    void* obj = dlopen (s, RTLD_LAZY);
    void* fcn = dlsym (obj, "foo");
    if (fcn)
        printf ("Object %s has 'foo' at addr %p\n", *s ? s : "(exe)", fcn);
}    
int cb (struct dl_phdr_info *info, size_t size, void *data)
{
    doit (info->dlpi_name);
    return 0;
}    
int main ()
{
    dl_iterate_phdr (cb, 0);    
    return 0;
}

这是输出:

Object (exe) has 'foo' at addr 0xb76f8418
Object (exe) has 'foo' at addr 0xb76f8418
Object /tmp/libfoo.so has 'foo' at addr 0xb76f8418
Object /tmp/libfoo1.so has 'foo' at addr 0xb76f5418
Object /tmp/libfoo2.so has 'foo' at addr 0xb76f2418

有一些重复,但这是一个小问题。

于 2011-11-30T17:26:07.527 回答
2

回答自己的问题,使寻找解决方案的人们的生活更轻松。没有统一的方法,想要迭代加载的模块应该搜索以下命令/数据类型(请专家对此发表评论):

Windows:
MODULEENTRY32、CreateToolhelp32Snapshot、Module32First、Module32Next

Linux:
如 nm 的回答中所述,当找到正确的模块(结束循环)时,从回调中返回非零值。

AIX:
加载查询(L_GETINFO,缓冲区,大小),结构 ld_info。

HP-UX:
dlget、dlgetname(如果需要模块路径)。

Solaris:
ldinfo、Link_map。

此外,我建议 dlopen 模块并从新句柄中获取符号以增加库的引用计数,从而防止它被卸载。至少在 AIX 上,它可能对再次加载和初始化库有副作用,但在大多数情况下,它比尝试从卸载的库中调用函数要好。

于 2011-12-05T00:07:36.943 回答