【问题标题】:Why do linked binaries contain the file names of used object files, how to remove them?为什么链接的二进制文件包含使用的目标文件的文件名,如何删除它们?
【发布时间】:2014-08-23 00:52:42
【问题描述】:

我正在尝试使 GHC Haskell 编译器的编译 100% 可重现(字节相同)。

目标文件已经是字节相同的,但最终链接的二进制文件不是。

GHC 将最终链接委托给gcc,例如:

/usr/bin/gcc -fno-stack-protector -DTABLES_NEXT_TO_CODE -o Main Main.o [..some more files..] /tmp/ghc21220_0/ghc21220_5.o /tmp/ghc21220_0/ghc21220_7.o [...] '-Wl,--hash-size=31' -Wl,--reduce-memory-overheads

有趣的是,临时文件ghc21220_7.o的文件名出现在链接的二进制文件中。

看来我可以使用strip 工具将其删除。

为什么会出现文件名,它的用途是什么?

是否有一个标志告诉gcc(或者ld?)不要包含这些文件名?


更新:如果我在二进制文件上运行objdump --syms,我会看到

0000000000000000 l    df *ABS*  0000000000000000              ghc21220_5.c
0000000000000000 l    df *ABS*  0000000000000000              ghc21220_7.c

根据thisd表示调试,f表示文件。我的问题仍然存在:.c 文件的文件名为什么以及如何使其进入最终二进制文件,我可以在编译时抑制它(而不是稍后运行strip)?

【问题讨论】:

  • 1) 期望工具链一遍又一遍地生成 100 字节相同的二进制文件是不现实的,如果不包含其他时间戳的话,通常是不现实的。是的,如果您制作的 .bin 或 .hex 或某种不支持其他内容的格式在理论上肯定是相同的,只要它是 100% 您的代码且没有库。 2)这些东西是为那些使用调试器的人准备的,他们不喜欢阅读汇编程序,如果那是他们得到的东西,就会抱怨 3)只使用条带。或者一种文件格式,除了代码和数据之外没有任何空间,没有元数据。
  • 如果可能的话,我想这里唯一与 stackoverflow 相关的真正问题是如何不首先添加调试内容,而不必稍后将其删除。

标签: c gcc linker ghc ld


【解决方案1】:

源文件名在可执行文件中显示为符号,因为 GCC 在发出程序集时所做的第一件事就是将 .file 指令写入输出。然后,汇编器将其转换为目标文件中的符号,链接器将其与所有其他符号一起放入可执行文件中。我不确定它是否有用,但它可能允许链接器在错误中给出源文件名而不是目标文件名。

除了修改代码之外,您无法阻止 GCC 生成 .file 指令或阻止汇编程序将它们转换为目标文件中的符号。您可以使用-x 选项告诉链接器不要将它们包含在可执行文件中,该选项告诉链接器去除所有本地符号。

另一个更有针对性的选项是使用strip 命令从目标文件中只删除文件名符号:

strip -N ghc21220_5.c ghc21220_5.o

最后,当 C 源文件应该相同时,您可以选择为它们提供相同的名称。最终,您选择的文件名是您在可执行文件中看到的差异的根源。

【讨论】:

  • 感谢您的回答。我已经分析了有问题的 C 文件的内容,它们确实可以被赋予一个通常的(非生成的)名称。
猜你喜欢
  • 2014-08-13
  • 2015-07-20
  • 2012-10-15
  • 2014-05-15
  • 1970-01-01
  • 1970-01-01
  • 2015-02-27
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多