Mac OS X 为动态加载提供了一个有用的库,称为 dyld。在许多有趣的动态加载处理函数中,有一些函数允许安装回调函数,无论何时加载或卸载图像,dyld 都会调用这些回调函数,作者 dlopen
和 dlclose
, 分别。这些函数是 void _dyld_register_func_for_add_image(void (*func)(const struct mach_header* mh, intptr_t vmaddr_slide))
和 void _dyld_register_func_for_remove_image(void (*func)(const struct mach_header* mh, intptr_t vmaddr_slide))
, 分别。
我知道不可能有 Linux 的确切端口,因为 dyld 函数处理 mach-o 文件,而 Linux 使用 ELF 文件。
那么,Linux 是否有一个等效的 dyld 库。或者,至少,是否存在这两个函数的等价物 _dyld_register_func_for_add_image
和 _dyld_register_func_for_remove_image
, 在任何 Linux 库中?或者我必须自己实现这两个版本,这并不难,但我必须找到一种方法来制作 dlopen
和 dlclose
每当它们被调用时调用回调函数。
编辑
为了让事情更清楚,我需要创建一个具有回调函数的库,每当外部库被 dlopen
动态加载时必须调用该回调函数.我的回调函数必须对任何动态加载的库执行一些操作。
最佳答案
是的,它叫做dlopen(3)使用 -ldl
标准库
更准确地说:
- 使用
-fPIC
标志编译您的插件源代码以获得位置独立的代码目标文件*.pic.o
- 通过使用
gcc -shared
链接您的*.pic.o
文件来制作一个共享库插件(您也可以链接另一个共享库)。 - 使用GCC function attributes ,特别是
constructor
和destructor
函数(或具有显式构造函数和析构函数的静态 C++ 数据,因此得名)。具有__attribute__((constructor))
的函数在您的插件的dlopen
期间被调用,具有__attribute__((destructor))
的函数在您的插件中被调用在dlclose
时间内调用 - 将主程序与
-rdynamic
属性链接起来很有用且需要,一旦插件调用了主程序中的某些函数。 - 不要忘记声明
extern "C"
您的 C++ 插件函数(程序需要) - 在主程序中使用
dlsym
来获取插件中的函数或数据地址。
dlopen
确实没有像 _dyld_register_func_for_add_image
那样的钩子(Hook)。您可能想使用构造函数和/或 dl_iterate_phdr(3)模仿那个。
如果您可以更改插件(您dlopen
的共享对象),您可以在其中玩构造函数技巧来模仿此类 Hook 。否则,使用一些自己的约定(例如,具有 module_start
函数的插件在 dlopen
等之后调用 module_start
函数等)。
一些库正在将 dlopen
包装到更高级别的东西中。例如 Qt 有 QPluginLoader & QLibrary等等……
还有 LD_PRELOAD trick (也许您可以通过这样的技巧重新定义您自己的 dlopen
和 dlclose
,并让您修改的函数执行 Hook )。 ifunc
function attribute也可能是相关的。
自 Gnu Libc是free software提供 dlopen
- 还有 MUSL Libc ,您可以对其进行修补以满足您的需要。 dladdr(3)也可能有用!
附录
如果您正在为某些 Objective-C 创建自己的运行时,您应该非常了解使用该运行时的 Objective-C 编译器的约定,并且您可能拥有自己的模块加载器,而不是重载 dlopen
...
关于linux - Linux 是否有等效的 dyld?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15703569/