我有一个动态加载库的应用程序,它动态加载库...
在 Windows 中,我可以遍历所有加载的模块以查找我感兴趣的符号。不知道如何在 Unix/Linux 环境中执行此操作。我知道我可以对前两个符号使用dlsym(dlopen(0, flag))
ordlsym(RTLD_DEFAULT / RTLD_NEXT)
并且知道要搜索的模块的顺序——我怎样才能更深入并获得给定符号的所有定义?
要在分片对象中查找符号,请使用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
有一些重复,但这是一个小问题。
回答自己的问题,使寻找解决方案的人们的生活更轻松。没有统一的方法,想要迭代加载的模块应该搜索以下命令/数据类型(请专家对此发表评论):
Windows:
MODULEENTRY32、CreateToolhelp32Snapshot、Module32First、Module32Next
Linux:
如 nm 的回答中所述,当找到正确的模块(结束循环)时,从回调中返回非零值。
AIX:
加载查询(L_GETINFO,缓冲区,大小),结构 ld_info。
HP-UX:
dlget、dlgetname(如果需要模块路径)。
Solaris:
ldinfo、Link_map。
此外,我建议 dlopen 模块并从新句柄中获取符号以增加库的引用计数,从而防止它被卸载。至少在 AIX 上,它可能对再次加载和初始化库有副作用,但在大多数情况下,它比尝试从卸载的库中调用函数要好。