lin*_*ker 5 linker elf dlopen dlsym
在我的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)
Run Code Online (Sandbox Code Playgroud)
此打印
“基本地址是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
Run Code Online (Sandbox Code Playgroud)
有人建议l_addr不是实际的库基址,而是与可执行标头的偏移量-但我不确定如何找到该标头地址。
是的,您绝对可以通过编程方式获取符号表。我建议您不要在 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) 和程序头数组。