在静态iOS库中重写符号



我正在开发一个iOS应用程序,它链接了几个静态库。挑战在于,那些链接的库用不同的实现定义了相同的方法名。奇怪的是,我没有得到任何duplicate symbol definition错误;但是,不出所料,我最终只能访问该方法的一个实现。

为了更清楚,假设我有libA和libB,它们都定义了一个全局C方法称为func1()

当我链接libA和libB,并调用func1()时,它解析为libA或libB的实现而没有任何编译警告。但是,我需要能够分别访问libA的func1()和libB的func1()。

有一个类似的SO帖子解释了如何在C中完成(通过符号重命名),但不幸的是,正如我发现的那样,objcopy工具不适用于ARM架构(因此iPhone)。

(我将提交它到App Store,因此,动态链接不是一个选项)

看来你很幸运-你仍然可以用ARM二进制格式重命名符号,它只是比objcopy方法更黑客…

注意:这只进行了最低限度的测试,我强烈建议您在尝试之前对所有有问题的库进行备份 !

还请注意,这只适用于未使用c++编译器编译的文件!如果在这些文件上使用c++编译器,这个失败。

    首先,你需要一个像样的十六进制编辑器,对于这个例子,我将使用hex恶魔。
  1. 接下来,您将打开一个库的副本,我们将其命名为lib1-renamed.a,并对其执行以下操作:

    • 找到要重命名的符号的名称。它可以使用nm工具找到,或者,如果你知道头名称,你应该设置。

    • 接下来,您将使用十六进制,并以文本替换旧名称(在本例中为foo),并给它一个新名称(在本例中为bar)。这些名称必须具有相同的长度,否则会破坏二进制的偏移量!

      注意:如果有多个函数包含foo的名字,你可能会有问题

  2. 现在,您必须编辑您更改的库的头文件,以使用新的函数名(bar)而不是旧的函数名。

如果你已经正确地完成了上面三个简单的步骤,你现在应该能够编译&成功链接两个文件,并调用两个实现。

如果您试图使用通用二进制文件(例如,在模拟器上也是如此),您最好使用lipo来分离两个二进制文件,在i386/x64二进制文件上使用objcopy,然后在ARM二进制文件上使用我的方法,并将lipo重新组合在一起。

†:不保证简单性,也不包括在Richard J. Ross III超级保修范围内。想了解更多关于超级保修的信息,请拨打1-800-FREE-WARRANTY。现在是1-800免费保修!

最新更新