2

如果您因为认为这不可能而单击它,那么在遇到它之前,我一直在想同样的事情。

我正在做一个项目,用 C 语言为 PIC 编写,它是用 Makefile 构建的。Makefile 非常杂乱无章,所以我想清理它。为了确保在执行此操作时没有破坏任何内容,我在新制作后记录了所有文件的哈希值:(此项目中没有子目录。使用 SDCC 和 GPUTILS 构建。)

make clean
make
md5sum ./* > ../allsums.txt

然后我修改了 Makefile 并再次尝试,这次将生成的文件与allsums.txt进行比较。

make clean
vim Makefile
make
md5sum -c ../allsums.txt

有趣的是,.o 文件的哈希值不匹配,但最终结果匹配。假设问题是我以某种方式创造的,我花了很多时间试图找到它。

然后,凭直觉,我使用原始 Makefile 做到了这一点:

make clean
make
md5sum ./* > ../allsums.txt
make clean
make
md5sum -c ../allsums.txt

我发现这里的目标文件也发生了变化!一些搜索使我想到了这个问题,这证实了(至少对于 gcc).o 文件在每次编译之间都会发生变化。

这是什么原因造成的?

4

1 回答 1

3

对象中的调试信息(符号、日期)可以使对象发生变化,即使代码完全相同。

为确保您没有任何更改,只需剥离对象:

strip *.o

比较对象/对其执行校验和的最佳方法是剥离对象,否则您永远无法确定。

(同样的技术可以应用于可执行文件)

注意:一旦你剥离了对象,你就可以链接它们,但你将很难调试。您可以在副本上执行此操作(theobject.o则未更改):

strip theobject.o -o theobject_stripped.o

我们在交付前执行可执行文件的“正式生产”时使用该流程。

实际上我们反过来做:我们比较剥离的可执行文件,如果有差异,我们比较剥离的对象以找到罪魁祸首并缩小范围。然后我们在源代码上使用我们的版本控制系统来找出它改变的原因。

编辑:如果使用自定义时间相关宏来定义对象文件(-DDATE=\"somedate\")中的日期,则校验和过程将需要的不仅仅是剥离操作。必须使用自定义工具从目标文件(或文件)中进行反向操作(删除日期/版本/任何内容)。您可以从此功能中受益,并通过仅将宏应用于包含Version.o导出符号的版本 ( ) 的一个文件来保持大多数目标文件不变。

该文件上的校验和会有所不同,但其他校验和将相同(或者您的同事无意义地让您很难)

编辑:对于 SDCC,您有一个类似的工具,称为sdobjcopy界面,它看起来非常像objcopy并且具有剥离对象的功能

sdobjcopy --strip-all theobject.o theobject_stripped.o

--strip-debug(如果--strip-all选项太“暴力” ,还有一个选项)

查看sdobjcopy 手册页以获取更多详细信息。

于 2016-09-23T19:02:18.457 回答