【问题标题】:how can I verify that dead code was stripped from the binary?如何验证死代码已从二进制文件中删除?
【发布时间】:2012-11-07 10:04:19
【问题描述】:

我的 c/obj-c 代码(一个用 clang 构建的 iOS 应用程序)有一些被#ifdefs 排除的功能。我想确保从这些函数调用而不是从其他函数调用的代码(死代码)在链接时被剥离(消除)。 我试过了:

  1. 在应消除的函数中添加本地文字 char[];在可执行文件上运行 strings 时,该字符串仍然可见。
  2. 添加一个应该被淘汰的功能;运行字符串时,函数名仍然可见。

在你问之前,我正在为发布而构建,并且所有剥离设置(显然包括死代码剥离)都已启用。

这个问题并不是 xcode/apple/iOS 特定的;我认为答案在任何 POSIX 开发平台上都应该几乎相同。

【问题讨论】:

  • 相关函数是否定义为static?它们必须存在,否则编译器必须保留它们,以防其他目标文件中的其他代码想要调用它们。
  • 不,它们不是静态的,但我的观点是在链接时消除。链接器确实知道它们是否被使用。
  • 听起来好像你手头有一个项目......通常,链接器只是简单地获取目标文件中的所有内容并修复它。如果你想要全程序优化(并且死代码消除可以被视为一种优化),那么你需要看看GCC中的工作是否有帮助,如果失败,你总是可以自己编写。如果未使用的函数是静态的,编译器会有所帮助。如果它们不能是静态的,那么您会将它们包含在可执行文件中。如果你想消除未使用的,你需要更加小心你的条件代码。
  • @noamtm 直到最近,GNU 工具链才能够在链接时删除部分目标文件。 That feature is now available 但尚未广泛使用。您可能没有使用它。它也不简单:它依赖于让编译器将一堆额外信息写入链接器然后使用的目标文件。
  • 基于llvm的iOS工具链支持死码消除;事实上,当我关闭它时,最终的二进制文件 确实 变大了。但它似乎并没有删除我上面写的东西。

标签: xcode linux macos unix


【解决方案1】:

(编辑)

在 binutils 中,ld 具有 --gc-sections 选项,它可以为对象级别的部分执行您想要的操作。您有多种选择:

  • 使用gcc的标志-ffunction-sections-fdata-sections将每个符号隔离到自己的部分,然后使用--gc-sections

  • 将要删除的所有候选对象放入单独的文件中,链接器将能够剥离整个部分;

  • 反汇编生成的二进制文件,删除死代码,再次汇编;

  • strip 与适当的 -N 选项一起使用,以从 符号表 - 这会将代码和数据保留在那里,但不会显示在符号表中。

【讨论】:

  • 我不熟悉该选项,但我只是读过它,我认为它不会满足 OP 的要求。它似乎只用于删除整个未使用的部分(如.text.bss 等),但在这种情况下,我们希望消除某些功能(主要是在 .text)同时保留其他功能(这也主要是在.text)。
  • 谢谢。我会检查 iOS 中使用的 llvm/clang 工具链是否支持这些选项。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-06-12
  • 1970-01-01
  • 2011-02-21
  • 1970-01-01
  • 2015-02-27
  • 2012-06-11
  • 2012-01-18
相关资源
最近更新 更多