Reg*_*ser 109 c optimization gcc binary-reproducibility
我创建了两个C程序
计划1
int main()
{
}
Run Code Online (Sandbox Code Playgroud)计划2
int main()
{
//Some Harmless comments
}
Run Code Online (Sandbox Code Playgroud)AFAIK,在编译时,编译器(gcc)应该忽略注释和冗余空白,因此输出必须类似.
但是当我检查输出二进制文件的md5sums时,它们不匹配.我也试图与优化的编译-O3
和-Ofast
,但他们仍然不匹配.
这里发生了什么?
编辑:确切的命令和md5sums是(t1.c是程序1,t2.c是程序2)
gcc ./t1.c -o aaa
gcc ./t2.c -o bbb
98c1a86e593fd0181383662e68bac22f aaa
c10293cbe6031b13dc6244d01b4d2793 bbb
gcc ./t2.c -Ofast -o bbb
gcc ./t1.c -Ofast -o aaa
2f65a6d5bc9bf1351bdd6919a766fa10 aaa
c0bee139c47183ce62e10c3dbc13c614 bbb
gcc ./t1.c -O3 -o aaa
gcc ./t2.c -O3 -o bbb
564a39d982710b0070bb9349bfc0e2cd aaa
ad89b15e73b26e32026fd0f1dc152cd2 bbb
Run Code Online (Sandbox Code Playgroud)
是的,md5sums匹配多个具有相同标志的编译.
顺便说一句我的系统是gcc (GCC) 5.2.0
和Linux 4.2.0-1-MANJARO #1 SMP PREEMPT x86_64 GNU/Linux
cyp*_*har 158
这是因为文件名不同(尽管字符串输出是相同的).如果您尝试修改文件本身(而不是有两个文件),您会注意到输出二进制文件不再是不同的.正如Jens和我所说的那样,这是因为GCC将一大堆元数据转储到它构建的二进制文件中,包括确切的源文件名(和AFAICS也是如此).
试试这个:
$ cp code.c code2.c subdir/code.c
$ gcc code.c -o a
$ gcc code2.c -o b
$ gcc subdir/code.c -o a2
$ diff a b
Binary files a and b differ
$ diff a2 b
Binary files a2 and b differ
$ diff -s a a2
Files a and a2 are identical
Run Code Online (Sandbox Code Playgroud)
这解释了为什么你的md5sums不会在构建之间发生变化,但它们在不同文件之间是不同的.如果您愿意,您可以执行Jens建议的操作,并比较strings
每个二进制文件的输出,您会注意到文件名嵌入在二进制文件中.如果您想"修复"此问题,您可以strip
删除二进制文件和元数据:
$ strip a a2 b
$ diff -s a b
Files a and b are identical
$ diff -s a2 b
Files a2 and b are identical
$ diff -s a a2
Files a and a2 are identical
Run Code Online (Sandbox Code Playgroud)
Jen*_*ens 27
最常见的原因是编译器添加的文件名和时间戳(通常在ELF部分的调试信息部分中).
试试跑步
$ strings -a program > x
...recompile program...
$ strings -a program > y
$ diff x y
Run Code Online (Sandbox Code Playgroud)
你可能会看到原因.我曾经用它来查找为什么在不同的目录中编译时,相同的源会导致不同的代码.结果是__FILE__
宏扩展为绝对文件名,两个树都不同.
LSe*_*rni 15
注意:请记住,源文件名将进入未提取的二进制文件,因此来自不同命名的源文件的两个程序将具有不同的哈希值.
在类似情况下,如果以上不适用,您可以尝试:
strip
针对二进制文件运行以删除一些脂肪.如果剥离的二进制文件是相同的,那么它是一些对程序操作不重要的元数据.strings
或将两个程序转储为十六进制并在两个十六进制转储上运行diff.找到差异后,您可以尝试查看是否存在一些押韵或理由(PID,时间戳,源文件时间戳......).例如,您可能有一个例程在编译时存储时间戳以用于诊断目的. 归档时间: |
|
查看次数: |
5578 次 |
最近记录: |