在两个以上共享库之间切换LD_PRELOAD

问题描述

假设存在三个共享库A.soB.soC.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)。