在 32 位和 64 位上编译,但校验和不同

Posted

技术标签:

【中文标题】在 32 位和 64 位上编译,但校验和不同【英文标题】:Compiled on 32-bit and 64-bit but checksum is different 【发布时间】:2020-07-09 18:54:28 【问题描述】:

编译了两个二进制文件。一个在 32 位 Windows 7 机器上,另一个在 64 位 Windows 10 上。所有源文件和依赖项都相同;但是,编译后校验和进行了比较,它们是不同的。有人可以解释原因吗?

【问题讨论】:

您是否在比较 32 位版本和 64 位版本并想知道为什么二进制文件不同?如果校验和相同,您就会遇到问题。机器指令将大不相同。 你为什么希望它们是一样的?我觉得你在做一个不成立的假设。 除非你采取了具体措施来实现reproducible builds,否则即使在同一台机器上它们也会有所不同。 即使在同一台机器上编译两次也可能不会给出相同的校验和,因为有些编译器有在可执行文件中添加时间戳的恼人习惯。 @VictorS 问他们为什么不同意味着你不希望他们如此。 【参考方案1】:

如果您要比较 32 位版本和 64 位版本,您需要记住,编译后的代码几乎完全不同。 64 位 x86_64 和 32 位 x86 机器代码不仅会有很大差异,而且即使不是这种情况,请记住指针的大小是 64 位代码的两倍,所以很多代码的结构都会不同,代码中的地址会用更大的指针表示。

技术原因是不同架构之间的机器码不一样。 Intel x86 和 x86_64 在操作码的表达方式以及程序的内部结构方面存在相当大的差异。如果您想了解这些差异,有很多已发表的材料可以解释,例如 Intel's own references。

正如其他人指出的那样,在同一台机器上构建两次甚至可能不会生成逐字节匹配的二进制文件。会有细微差别,特别是如果有代码签名步骤。

简而言之,您不能这样做并期望它们匹配。

【讨论】:

【参考方案2】:

所有的源文件和依赖都是一样的;但是,编译后校验和进行了比较,它们是不同的。

校验和是根据编译器生成的二进制代码计算的,而不是源代码。如果 anything 不同,您应该得到不同的校验和。 源代码中的更改将更改二进制文件,因此校验和不同。但是使用不同的编译器也会产生不同的二进制文件。使用具有不同选项的相同编译器将产生不同的二进制文件。在不同的机器上使用相同的编译器和相同的编译器选项编译相同的程序可能会产生不同的二进制文件。为不同的处理器架构编译相同的程序将肯定产生不同的二进制文件。

【讨论】:

以上是关于在 32 位和 64 位上编译,但校验和不同的主要内容,如果未能解决你的问题,请参考以下文章

你能在 64 位机器上编译 32 位 Apache DSO(Oracle HTTP 服务器)吗?

在运行 64 位 linux 的 Armv8 (aarch64) 上编译并运行 32 位二进制文​​件

如何在 64 位 osx 上编译 gcc 32 位应用程序

在 64 位机器上编译 32 位:/usr/bin/ld: 找不到 -l<someLibs>

在 64 位 Arm 上编译和安装 Chez 方案?

BFD_RELOC_64:使用 C++ 在 32 位 linux 上编译汇编器指令