【发布时间】:2025-12-24 04:05:11
【问题描述】:
如果您编译两个仅在返回值上有所不同的 C 程序,我希望二进制文件仅在此值的位上有所不同。但是,如果我使用 GCC 编译以下程序,转储二进制位(使用 xxd)并区分转储,我会得到另一个不同。
文件
return127.c
int main() {
return 127;
}
return128.c
int main() {
return 128;
}
编译、转储和差异
# compile
gcc -Os -fdata-sections -ffunction-sections -fipa-pta -Wl,--gc-sections -Wl,-O1 -Wl,--as-needed -Wl,--strip-all return127.c -o return127
gcc -Os -fdata-sections -ffunction-sections -fipa-pta -Wl,--gc-sections -Wl,-O1 -Wl,--as-needed -Wl,--strip-all return128.c -o return128
# dump
xxd -b return127 > return127.xxd-bits
xxd -b return128 > return128.xxd-bits
# diff
diff return127.xxd-bits return128.xxd-bits
注意:我使用this 的编译命令注释一个关于C 程序最小二进制的问题。
差异
108,111c108,111
< 00000282: 01010101 00000000 01101011 11011010 11101100 11100011 U.k...
< 00000288: 00111010 10001111 00101111 00101100 01100001 00111100 :./,a<
< 0000028e: 10010010 11001011 00011000 11101010 11100111 00100011 .....#
< 00000294: 01001010 00111011 11111001 11111010 00000001 00000000 J;....
---
> 00000282: 01010101 00000000 00011101 11000011 10101000 00011001 U.....
> 00000288: 11011011 00110001 10100000 01001101 01000110 10010011 .1.MF.
> 0000028e: 00101101 01011101 11101001 00001000 01010101 11111101 -]..U.
> 00000294: 11011011 01000011 11010100 10101011 00000001 00000000 .C....
211c211
< 000004ec: 00000000 00000000 00000000 00000000 10111000 01111111 ......
---
> 000004ec: 00000000 00000000 00000000 00000000 10111000 10000000 ......
有两个不同之处。底部的差异显示了返回值的(预期)差异。这些行仅在最后一个字节/块中有所不同。二进制 01111111 是十进制 127。二进制10000000 是十进制128。
顶部有什么区别?
【问题讨论】:
-
如果您从相同的源代码构建两次,二进制文件是否相同?我的猜测是构建的日期和时间可能存储在可执行文件的标头中的某个位置。您正在创建什么类型的二进制文件? ELF?如果前 4 个字节的值为
7F 45 4C 46,则它是一个 ELF 文件。 -
是的,如果我构建两次它们是相同的(即使我在构建之间等待几分钟)。这是一个 ELF 文件。
-
google.com/search?q=gcc+reproducible+builds |
-Wl,-O1为什么将O1传递给链接器,而将Os传递给 gcc? -
如果您从名为
return127.c的文件中执行return 128会怎样? -
@SteveSummit 我得到了相同的二进制文件。
标签: c gcc compiler-optimization