如何判断两个源文件是否生成了具有相同功能的代码?

3
我正在使用uncrustify来格式化一个C和C++代码的目录。我需要确保uncrustify不会改变生成的代码;我无法对目标文件或二进制文件进行diff,因为目标文件具有时间戳,所以永远不会完全相同。我无法逐个检查文件的源代码,因为这样需要花费很长时间。
该项目使用make进行构建过程,因此我想知道是否有一些输出可以在那里进行检查。
我已经在SO和Google上搜索了,但没有找到答案,如果这是重复问题,请见谅。
编辑:我正在使用gcc/g++编译32位代码。

1
您可以使用像 objdump 这样的命令来反汇编二进制文件并进行比较。 - Fazlin
“我无法对目标文件或二进制文件进行差异比较,因为目标文件具有时间戳,所以永远不会完全相同。” “.o”文件是否有嵌入式时间戳?我不知道。 - underscore_d
1
时间戳是如何嵌入到目标文件中的?它是否可以被去除?也许有一些二进制比较工具可以跳过或忽略文件中特定范围的字节,您尝试寻找过这样的实用程序了吗? - Some programmer dude
1
实际上,您可以在从对象文件中清除时间戳后执行二进制差异。一个示例程序,可用于PE/PDB文件的是zap_timestamps - user824425
2
过去,我曾经不得不比较应该完全相同的生成二进制文件(尽管出于不同的原因)。在这种情况下,我使用objcopy从elf文件中提取相关部分-- .text、.data等--并进行比较。虽然有点繁琐,但在这种情况下不是也可以这样做吗? - G.M.
显示剩余2条评论
1个回答

2

一种可能性是使用CLang编译它们,并将输出作为LLVM IR获取。如果我的记忆没有出错,这应该是-S -emit-llvm的命令行参数。

要使用gcc/g++完成相同的操作,您可以使用其中一个标志,在某个编译阶段生成包含其中间表示的文件。早期阶段仍会显示白色空格等变化的差异,但快速测试表明,在SSA阶段,这样的非运算更改已从IR中消失。

g++ -c -fdump-tree-ssa foo.cpp

除了正常的目标文件外,这将生成一个名为foo.cpp.018t.ssa的文件,表示源文件中的语义动作。
如上所述,我虽然没有进行全面测试,但在这个阶段,一些非操作性更改可能仍会产生不同的输出文件(尽管我有点怀疑)。如果需要,可以使用-fdump-tree-all来获取来自编译的所有阶段的输出1。简单的经验法则是,我希望后期阶段对格式和其他方面的更改更加免疫,因此,如果ssa阶段不起作用,我的下一个选择可能是优化阶段,这是最后一个阶段之一(注意:生成的文件按照产生每个文件的阶段顺序编号,因此当您转储所有阶段时,很明显哪些是早期阶段产生的,哪些是后期阶段产生的)。

1.请注意,这会产生相当多的文件,其中许多文件非常大。第一次这样做时,您可能想在单独的目录中对单个源文件进行操作,以避免淹没在文件中。此外,不要惊讶当以这种方式编译时需要比正常情况下花费更长的时间。


我生成了ssa文件,将来自"crusty"源的文件放在一个文件夹中,将来自"crustfree"的文件放在另一个文件夹中。使用diff -rq crusty crustfree进行比较可以发现它们都不相同(一些文件仅存在于"crusty"输出中)。这是否表明去除壳层的过程已经以某种方式改变了代码的功能? - Alex Meuer
1
@AlexMeuer:这就是困难所在:如果文件完全相同,我们可以轻易得出结论,改动对生成的代码没有任何影响。但是由于它们不同,意义的改变是可能的,但并非确定(可惜的是,我怀疑您能够轻易提供的其他东西也无法提供更强的保证)。 - Jerry Coffin

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接