【问题标题】:Rewriting symbols in static iOS libraries在静态 iOS 库中重写符号
【发布时间】:2013-02-27 00:53:32
【问题描述】:

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

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

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

There's a similar SO post 解释了如何在 C 中完成它(通过符号重命名),但不幸的是,正如我发现的那样,objcopy 工具不适用于 ARM 架构(因此是 iPhone)。

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

【问题讨论】:

  • 如果你有任何一个库的源代码,那么解决方案是显而易见的。或者,您可以使用lipo 将两个库打包为一个,如果我没有记错的话,应该只保留其中一个符号。
  • 感谢@RichardJ.RossIII,但我没有源代码并且不确定您的建议是否会有所帮助,因为我想单独保留这些符号,我需要它们,我不想减少他们到一个符号
  • 我会说使用dlopendlsym 分别动态加载符号,但不幸的是,现在苹果禁止使用这些符号,这将不起作用。我不是.a 文件结构方面的专家,但我觉得可以通过十六进制编辑器手动执行此操作。让我试试,看看能不能帮到你。

标签: ios xcode static-linking


【解决方案1】:

看来你很幸运——你仍然可以使用 ARM 二进制格式重命名符号,它只是比objcopy 方法更hacky...

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

另请注意,这仅适用于未使用 C++ 编译器编译的文件!如果在这些文件上使用了 C++ 编译器,此失败。

  1. 首先,您需要一个不错的十六进制编辑器,在本例中,我将使用Hex Fiend
  2. 接下来,您将打开您的图书馆的副本,我们将其命名为 lib1-renamed.a,然后使用它执行以下操作:

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

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

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

  3. 现在,您必须编辑您更改的库的标题,以使用新的函数名称 (bar) 而不是旧的。

如果您已正确完成上述三个简单的 步骤,您现在应该能够成功编译和链接这两个文件,并调用这两个实现。

如果您尝试使用通用二进制文件执行此操作(例如,模拟器上的一个作品),您最好使用lipo 分隔两个二进制文件,在 i386/ 上使用 objcopy x64 二进制文件,然后在 ARM 二进制文件上使用我的方法,然后将 lipo 重新组合在一起。

†:不保证简单性,也不包括在 Richard J. Ross III 超级保修范围内。有关超级保修的更多信息,请立即致电 1-800-FREE-WARRANTY。现在是 1-800 免费保修!

【讨论】:

  • 明天测试第一件事,非常感谢您的努力(以及您的脚注!):)
  • @EgeAkpinar 不要忘记您的免费超级保修!
  • 好吧,事实证明我不需要保修,因为它就像一个魅力。我之前尝试过重命名,但错过了我应该重命名为相同的长度。非常感谢!
  • @AndiDog 我很欣赏你的编辑,但我的幽默将继续存在。有时人们把这个网站看得太重了,开怀大笑会让你心情愉快。
  • 如果它可以工作,那就太好了……但是,我不会制作静态库的副本,因为我正在使用源代码管理。这里什么都没有!附言有没有办法用lipo 或其他命令行工具来做到这一点?我对后组装开发/渗透测试等了解不够。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-12-16
  • 1970-01-01
  • 1970-01-01
  • 2012-07-16
  • 2015-06-18
  • 1970-01-01
相关资源
最近更新 更多