【问题标题】:Can gcc linker options change assembler instructions in the compiled binary?gcc 链接器选项可以更改已编译二进制文件中的汇编程序指令吗?
【发布时间】:2016-09-13 16:39:59
【问题描述】:

我想知道 gcc 链接器选项(例如:-Wl,options)是否可以更改已编译可执行文件中的汇编程序指令,因为如果您使用某些 gcc 优化选项会发生这种情况? 比较编译后的二进制文件(例如比较签名)时,是否可以看出使用链接器选项和不使用它的区别?

更新

更准确地说,我想弄清楚当我在编译过程中使用某些链接选项时FLIRT 签名是否会发生变化。这些签名仅使用库函数来创建签名。

【问题讨论】:

  • 参见例如--wrap.
  • @Phillip 你能更准确地解释一下吗?
  • 手册页有关于该选项的详细信息;它可以用来覆盖符号,至少对于 C 目标文件,它也可以改变函数的签名。
  • 你的问题没有多大意义。链接器可以在不涉及链接器选项的情况下出于多种不同原因更改最终在可执行文件中的汇编指令,而 GCC 优化选项通常会对最终在可执行文件中的汇编指令进行大量更改。
  • 你问的是什么改变了整个二进制文件的哈希值,还是只是实际的机器代码? (即,您是否排除了像节标题这样的目标文件元数据?)我很确定您在跳转和类似的东西中包含不同的 rel32 偏移量,所以排序很重要。如果您只关心不同的指令操作码,那只会发生在链接时优化中,其中代码生成在链接时完成/重新完成。

标签: gcc assembly optimization compilation linker


【解决方案1】:

对于某些链接器选项,可以在生成的二进制文件中看到更改,例如:

  • 删除/保留调试符号的选项(--strip-all--strip-debug--discard-all
  • 删除/保留未使用部分的选项,例如包含在其他部分中从未引用的函数的部分。这些部分可以很容易地删除。或保留重定位部分/内容。 (--as-needed, --emit-relocs)
  • 包含一个静态库或另一个兼容库的选项(例如库版本 x.0 与版本 x.1)
  • 对象和静态库在命令行中的放置顺序。例如,ld -o foo a.obj b.obj c.objld -o foo a.obj c.obj b.obj可能如果从 a 到 c 中的函数的调用被解析(来自 c.obj 的代码的偏移量以及因此的地址c 中的函数可能会有所不同)

但即使在链接之后,二进制文件的签名也可能会改变。例如在 Linux 中,当您通过运行 prelink 优化二进制启动时间时

【讨论】:

  • 其实我只对函数级别的二进制变化感兴趣。如果修改了特定的调试符号,这不会改变函数的汇编代码。你能想象一个使用链接器选项改变基于函数的汇编代码的场景吗?
  • 是的,对其他对象的调用可能会解析为不同的偏移量/地址,具体取决于它们的顺序或静态库的顺序,或不同版本的库。
  • 但是静态库中的函数将保持不变,对吧?
  • @PeterFox 不,它们通常最终会有所不同,具体取决于它们最终在可执行文件中的位置以及它们引用的其他内容最终驻留的位置。
【解决方案2】:

是的,您会在使用不同链接器选项链接的两个二进制文件上看到不同的校验和——除非该选项无效,例如当您指定默认选项或不更改二进制文件的选项时(-print-地图)。

你到底想弄清楚什么?当您指定某些链接器选项并且您试图找出原因时,听起来您遇到了问题。告诉我们更多信息,也许我们可以提供更好的帮助。

【讨论】:

    猜你喜欢
    • 2012-11-25
    • 1970-01-01
    • 1970-01-01
    • 2020-05-16
    • 1970-01-01
    • 2010-12-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多