问题描述
假设存在三个共享库A.so
,B.so
和C.so
,每个共享库都具有一个功能f()
。我想在运行时确定的某些情况下在每个函数f()
之间切换。使用LD_PRELOAD
技巧,我将按以下方式执行程序p
(即这些库的用户):
LD_PRELOAD=A.so:B.so:C.so ./p
f()
中的 A.so
将是默认值。在该f()
实例中,我可以使用f()
访问B.so
的{{1}},如下所示:
dlsym()
如何访问void f() // in A.so
{
...
void *f_in_B = dlsym(RTLD_NEXT,"f");
...
}
中的f()
实例?
更新:
尽管yugr
's answer在简单情况下有效,但在更多一般条件下仍存在问题。我将通过给出更多详细信息 当前情况
我需要两个不同动态内存分配器,并且不想要处理{ {1}} C.so
。简而言之,我有两个单独的存储区,每个存储区都有自己的glibc
。我使用malloc(),...
根据某些运行时间条件在分配器之间切换。我使用yugr
's answer来加载和访问中学库。
首先,我在辅助库中调用glibc
以初始化 LD_PRELOAD
数据结构。我还在操作系统系统调用级别上进行了管理 ptmalloc_init()
调用,以使每个库具有自己的 大{{ 1}}范围,这避免了进一步的冲突。
问题在于该解决方案仅在malloc()
边界上有效。例如,当我在 secondary 库中使用brk()
时,它将调用 primary 库中的brk()
之类的函数,内部,并且这些呼叫不能通过application/glibc
技巧来捕获。
为什么会发生?我以为,库的内部符号是在库编译时内部设置的内部,但在此处看来,它们是在malloc()
的 primary 库中使用符号。如果解析是由链接器完成的,为什么__default_morecore()
技巧不能 捕获这些看似内部的符号?
如何解决问题?我是否应该次要库中的所有导出功能重命名?还是唯一可行的方法是使用单个库并深入研究实施工具?
解决方法
您可以在启动时null
中的三个库中的每一个获取它们的句柄,并使用它们来调用dlopen
以获取dlsym(h,"f")
的特定实现。如果您事先不知道库名称,则可以使用f
来获取它们(例如,请参见this code)。