7

在我的 C 共享库中,我想 dlopen() 另一个共享库并检索该库具有的导出符号列表。

有没有一种方法可以在不运行 nm/objdump 的情况下以编程方式做到这一点?

作为第二个问题:如何检索在 dlopen() 之后加载第二个库的基地址 - 不知道任何符号的名称(所以我不能运行 dlsym!)并且不读取 /proc/self/maps?

我尝试了以下方法:

struct link_map *imagehandle = (struct link_map*)dlopen(libraryname, RTLD_LOCAL | RTLD_LAZY);
void * fbase = (void*) imagehandle->l_addr;
printf("base addr is %p",fbase)

这打印

“基本地址是 0x6862696c”

但是,图书馆并不在那里:

[ /proc/pid/maps 输出:]

b6d27000-b6d28000 r-xp 00000000 1f:01 1581       mysecondlib.so
b6d28000-b6d29000 r--p 00000000 1f:01 1581       mysecondlib.so
b6d29000-b6d2a000 rw-p 00001000 1f:01 1581       mysecondlib.so

有人建议 l_addr 不是实际的库基地址,而是可执行头的偏移量 - 但我不确定如何找到该头地址。

4

1 回答 1

4

是的,您绝对可以通过编程方式获取符号表。我建议不要在 SO 上运行 dlopen() ,而是通过 mmap 自己打开它,甚至自己将文件读入连续的内存。一旦它在内存中,您可以通过以下文档轻松遍历 SO 的每个部分:http: //linux.die.net/man/5/elf。sh_type 等于 SHT_SYMTAB(符号表)的部分就是您要查找的部分。

如果您仍然需要找到已加载 SO 的基地址,根据我的经验,我还没有找到从 dlopen() 获取它的方法。我发现最好的方法是在 SO 中的一个已知符号上调用 dladdr(),它会填充一个包含 dli_fbase 成员的 Dl_info 结构,这是符号来自的模块的基地址。如果您确实不知道该 SO 中的任何符号,则可以使用 dl_iterate_phdr ( http://linux.die.net/man/3/dl_iterate_phdr ),它将遍历您进程中所有已加载的 SO 并为您提供 dl_phdr_info每个结构实例。该结构包含名称、基地址 (dlpi_addr) 和程序头数组。

于 2014-11-17T03:07:50.787 回答