2

我有一个可以加载插件的工作程序dlopen

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

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

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

void *handle plugin_containing_pointer(void *p);

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

我怎样才能实现is_pointer_into_plugin, 或plugin_containing_pointer, 或等效的东西?

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

我的程序在 Linux(和 Windows,但这是另一个问题)下运行。未来对其他 unix 系统(至少对 OSX)的可移植性将是一个加分项。

4

2 回答 2

1

一种方法,如果你足够控制插件——使用链接器脚本应该可以解决问题——将确保在开始和结束时有指定的符号——即类似于__executable_start, _etext, _edata, _end——然后使用 dlsym 来获取它们地址。您可能可以在具有动态库的所有系统上获得相同的效果,从而将大多数系统依赖项推到构建端。

于 2012-09-25T19:20:16.540 回答
1

一种方法(完全特定于 Linux)是解析/proc/self/maps(另请参阅了解 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 列与使用 获得的值进行比较fstat

于 2012-09-25T19:02:44.803 回答