Linux下动态加载库的地址范围

时间:2012-09-25 19:02:45

标签: c linux process dynamic-linking dlopen

我有一个使用dlopen加载插件的工作程序。

新要求:在代码中的某个时刻,我给了一个指针,我需要测试这个指针是否指向插件的代码或静态数据。

bool is_pointer_into_plugin(void *p, void *handle);

等效地,我需要检索指针所指向的插件(如果有的话)。我还需要知道指针是指向主程序的代码还是静态数据(理想情况下,区分只读和读写区域)。

void *handle plugin_containing_pointer(void *p);

等效地,我需要能够检索插件映射的范围(地址和大小)。我还需要这个主要程序的信息。

如何实施is_pointer_into_pluginplugin_containing_pointer或等效的内容?

如有必要,我可以将通话更改为dlopen。查找应该尽可能快,加载时代码不需要很快。在单独的进程中运行插件并通过共享内存进行通信不是一种选择。

我的程序在Linux下运行(和Windows,但那是another question)。未来对其他unix系统的可移植性(至少是OSX)将是一个优势。

2 个答案:

答案 0 :(得分:1)

一种方式(完全针对Linux)是解析/proc/self/maps(另请参阅Understanding Linux /proc/id/maps),它描述了进程的内存映射。每个动态加载的库都有一个或多个条目(通常为3),它提供其地址范围,访问权限和文件名。这是一个显示C库映射的示例:

f7622000-f7775000 r-xp 00000000 08:06 6950542                            /lib/tls/i686/cmov/libc-2.11.1.so
f7775000-f7777000 r--p 00153000 08:06 6950542                            /lib/tls/i686/cmov/libc-2.11.1.so
f7777000-f7778000 rw-p 00155000 08:06 6950542                            /lib/tls/i686/cmov/libc-2.11.1.so

第一列给出了地址范围,第二列给出了权限,第三列给出了库(或主可执行文件)的完整路径。具有空的最后一列或最后一列不是文件名的条目对应于非文件支持的区域(堆栈,堆等)。权限r-xp表示代码,r--p是只读数据,rw-p是可变数据。

如果重命名或删除了插件文件,这将反映在/proc/self/maps中。如果发生这种情况,为避免出现问题,请在致电(dlopen)后尽快阅读相关信息;请注意,有一个不可避免的竞争条件。设备和inode可以跟踪插件文件:打开文件,在dlopen上调用/dev/fd/NUM,阅读/proc/self/maps,将第4和第5列与使用{{1}获得的值进行比较}}

答案 1 :(得分:1)

一种方法是,如果你足够控制插件 - 使用链接器脚本应该可以做到 - 这将确保在开始和结束时指定符号 - 即类似于__executable_start,{{1 },_etext_edata - 然后使用dlsym获取其地址。您可以在具有动态库的所有系统上获得相同的效果,从而在构建方面推动大多数系统依赖性。