我有许多共享库(仅二进制文件)互相调用(.so,ARM,Android)。
funcA(),...,funcZ()中调用这些函数。
我可以在原始库中重命名一个函数(将名称保留在同一存储桶中有些棘手,但可以)。 >
我要:


在调用库的依赖项列表中添加一个额外的库,即最初仅引用libsomething.solibstuff1.so,我希望它引用libstuffN.solibstuff1.so都可以。
或者,向现有库中添加一个额外的功能,例如在libsomething.so中,我将libsomething.so重命名为libOneMoreLib.so并定义(即添加)libsomething.so以打印日志并调用funcA()

我该怎么做?

#1 楼

所需的共享库作为DT_NEEDED条目存储在可执行文件的动态部分中。该条目又指向动态字符串表。因此,要添加另一个库,您将需要执行以下操作:


解析程序头列表并找到PT_DYNAMIC条目
将其p_vaddr映射回文件使用其他PT_LOAD条目补偿。 (您可以使用p_offset条目本身的PT_DYNAMIC字段,但不能保证它是正确的。)
读取并解析动态节条目,直到您单击DT_NULL为止。 DT_STRTAB / DT_STRSZ)。请注意,这是一个虚拟地址,需要使用PT_LOAD条目将其映射回文件偏移。
用您的库名称扩展字符串表。您可能需要为它找到一些其他位置,因为表的末尾不可能有足够的空间。如果是这样,您可能需要添加另一个PT_LOAD条目,以确保它最终出现在过程存储器中。这将意味着移动其他条目的所有文件偏移。但是,假设您已完成操作。
再次遍历动态部分,并使用新地址更新指向字符串表的所有条目。同时更新DT_STRTAB / DT_STRSZ
现在,您终于可以为lib添加一个新的DT_NEEDED条目,并在其后添加另一个DT_NULL终止符。并希望新的DT_NULL不会覆盖任何重要的内容:)


评论


是否有一个库可以将.so读取到内存中,然后将其转换为某些数据结构(例如DOM解析器读取XML),以便可以向列表中添加一个元素并将其写回?

– 18446744073709551615
2014年4月21日在10:04

还没看过

–伊戈尔·斯科钦斯基♦
2014年4月21日在12:48

更新:PatchELF似乎至少实现了一些必要的功能,因此您可以尝试扩展它或提交功能请求。

–伊戈尔·斯科钦斯基♦
2014年4月23日下午13:42

#2 楼

有一个简单的方法。 readelf -d libxyz.so所有依赖项列表。这些库之一可以扩展或替代。

#3 楼

我知道这不是您问题的直接答案,但是类似LD_PRELOAD的机制可以使您实现所需的功能吗?将代替原始库中的库。这是在Linux系统上执行功能挂接的常见且简单的方法。

以下是使用LD_PRELOAD钩函数的示例。