为什么链接二进制文件包含已使用目标文件的文件名,如何删除它们?

时间:2014-08-23 00:52:42

标签: c gcc linker ghc ld

我正在努力使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

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

1 个答案:

答案 0 :(得分:3)

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

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

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

strip -N ghc21220_5.c ghc21220_5.o

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