如何编译 C 程序,使二进制文件仅在 return 值不同?

How to compile C programs such that binaries differ only in different return value?

如果您编译两个仅 return 值不同的 C 程序,我希望二进制文件仅在此值的位上不同。但是,如果我使用 GCC 编译以下程序,转储二进制文件的位(使用 xxd)并对转储进行 diff,我会得到另一个不同之处。

文件

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

注:我用的编译命令评论一个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  ......

有两个区别。底部的差异显示 return 值的(预期)差异。这些行仅在最后 byte/block 处不同。二进制 01111111 是十进制 127。二进制 10000000 是十进制 128.

上面有什么区别?

What is the difference at the top?

这是构建 ID 的差异。安装 diffoscope(或比较两个库的 readelf --wide --notes 输出),您会很好地看到:

│  Displaying notes found in: .note.gnu.build-id
│    Owner                Data size     Description
│ -  GNU                  0x00000014    NT_GNU_BUILD_ID (unique build ID bitstring)     Build ID: 817d41c45a09c3822337307250bdb9410a1959b4
│ +  GNU                  0x00000014    NT_GNU_BUILD_ID (unique build ID bitstring)     Build ID: de5fb81907549af3332e8136d6bd7ab4d884e0ce

How to compile C programs such that binaries differ only in different return value?

  1. 你必须在两个 gcc 上同时设置 __TIME____DATE__
  2. 您必须为这两个调用创建唯一的构建 ID。

以下脚本:

export SOURCE_DATE_EPOCH=$(date +%s)
f() {
    gcc -Wl,--build-id=none \
       -Os -fdata-sections -ffunction-sections -fipa-pta \
       -Wl,--gc-sections -Wl,--as-needed -Wl,--strip-all \
       -xc - -o ""
}
echo 'main(){return 127;}' | f /tmp/1
echo 'main(){return 128;}' | f /tmp/2
diffoscope /tmp/1 /tmp/2

diffoscope输出:

│  0000000000001020 <.text>:
│ - mov    [=12=]x7f,%eax
│ + mov    [=12=]x80,%eax
│   retq