c - GCC 正在生成充满零的二进制文件

标签 c gcc glibc uclibc musl

我试图找出为什么 GCC 生成的二进制文件如此之大。

考虑这个空程序:

int main() {
    return 0;
}

现在我使用 GCC 9.2.1 20190827 (Red Hat 9.2.1-1)glibc 2.29 构建它,无需任何其他参数:

gcc -o test test.c

生成的二进制文件大小为 21984 字节 (~22 KB)。使用xxd查看生成的文件,在多个位置存在长时间的空字节:

00000370: 006c 6962 632e 736f 2e36 005f 5f6c 6962  .libc.so.6.__lib
00000380: 635f 7374 6172 745f 6d61 696e 0047 4c49  c_start_main.GLI
00000390: 4243 5f32 2e32 2e35 005f 5f67 6d6f 6e5f  BC_2.2.5.__gmon_
000003a0: 7374 6172 745f 5f00 0000 0200 0000 0000  start__.........
000003b0: 0100 0100 0100 0000 1000 0000 0000 0000  ................
000003c0: 751a 6909 0000 0200 1d00 0000 0000 0000  u.i.............
000003d0: f03f 4000 0000 0000 0600 0000 0100 0000  .?@.............
000003e0: 0000 0000 0000 0000 f83f 4000 0000 0000  .........?@.....
000003f0: 0600 0000 0200 0000 0000 0000 0000 0000  ................
00000400: 0000 0000 0000 0000 0000 0000 0000 0000  ................
<3040 bytes of zeroes>
00000ff0: 0000 0000 0000 0000 0000 0000 0000 0000  ................
00001000: f30f 1efa 4883 ec08 488b 05e9 2f00 0048  ....H...H.../..H
<not zeroes>
00001190: f30f 1efa c300 0000 f30f 1efa 4883 ec08  ............H...
000011a0: 4883 c408 c300 0000 0000 0000 0000 0000  H...............
000011b0: 0000 0000 0000 0000 0000 0000 0000 0000  ................
<3632 bytes of zeros>
00001ff0: 0000 0000 0000 0000 0000 0000 0000 0000  ................
00002000: 0100 0200 0000 0000 0000 0000 0000 0000  ................
00002010: 011b 033b 3400 0000 0500 0000 10f0 ffff  ...;4...........
<not zeroes>
000020e0: 410e 2842 0e20 420e 1842 0e10 420e 0800  A.(B. B..B..B...
000020f0: 1000 0000 ac00 0000 98f0 ffff 0500 0000  ................
00002100: 0000 0000 0000 0000 0000 0000 0000 0000  ................
<3376 bytes of zeroes>
00002e40: 0000 0000 0000 0000 0000 0000 0000 0000  ................
00002e50: 0011 4000 0000 0000 d010 4000 0000 0000  ..@.......@.....
...

因此生成的二进制文件大约有 10 KB,或者几乎一半,其中没有任何内容。

使用 size -A 来看,大小更像是一个除了返回退出代码之外什么也不做的程序所期望的大小:

test  :
section                 size      addr
.interp                   28   4194984
.note.ABI-tag             32   4195012
.note.gnu.build-id        36   4195044
.gnu.hash                 28   4195080
.dynsym                   72   4195112
.dynstr                   56   4195184
.gnu.version               6   4195240
.gnu.version_r            32   4195248
.rela.dyn                 48   4195280
.init                     27   4198400
.text                    373   4198432
.fini                     13   4198808
.rodata                   16   4202496
.eh_frame_hdr             52   4202512
.eh_frame                192   4202568
.init_array                8   4210256
.fini_array                8   4210264
.dynamic                 400   4210272
.got                      16   4210672
.got.plt                  24   4210688
.data                      4   4210712
.bss                       4   4210716
.comment                  44         0
.gnu.build.attributes   4472   4218912
Total                   5991

当使用GCC 9.2.0musl 1.1.23对PowerPC进行交叉编译时,情况甚至更糟。二进制文件的大小增长到 67872 字节 (~67 KB),并且使用 xxd 进行查找,发现连续运行的 64074 字节只有零。

不过,size -A 报告此版本的尺寸甚至更小:

test  :
section              size        addr
.interp                26   268435796
.note.gnu.build-id     36   268435824
.hash                  36   268435860
.dynsym                64   268435896
.dynstr                39   268435960
.rela.plt              12   268436000
.init                  28   268436012
.text                 496   268436048
.fini                  28   268436544
.eh_frame_hdr          28   268436572
.eh_frame              80   268436600
.init_array             4   268566284
.fini_array             4   268566288
.dynamic              216   268566292
.branch_lt              8   268566508
.got                   12   268566516
.plt                    4   268566528
.data                   4   268566532
.bss                   28   268566536
.comment               17           0
Total                1170

我还尝试使用旧版本的 GCC 编译该程序,我碰巧手头有这个版本:GCC 4.7.2uClibc 1.0.12。通过这种组合,生成的二进制文件只有 4769 字节 (~4 KB),并且其中没有明显的空字节运行。

为了确保这种情况不仅仅发生在不执行任何操作的小程序上,我查看了一些与 GCC 9.2.0musl 交叉编译的真实程序1.1.23。例如,使用 -Os 编译并剥离的 tcpdump 二进制文件包含 32628 字节长的连续运行的空字节。那么,为什么零试图消耗我的所有磁盘空间?

最佳答案

最近的 binutils 默认为 -z separate-code ,这会向需要进一步对齐的程序添加额外的 PT_LOAD 段。

您可以像这样覆盖默认值:

gcc -Wl,-z,noseparate-code -o test test.c

由于对齐要求,此更改仍会保留一些零。

关于c - GCC 正在生成充满零的二进制文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59026218/

相关文章:

c 结构体和 pthread 指针分配

c - 通过类型限制多对多资源访问

c - 指向 C 中指针的指针未按预期工作

c - 为 ARM NEON 进行编译时出现未知的 GCC 错误(严重)

c++ - 用宏确定GCC编译器

c - 为什么 gcc 编译器在这两种情况下表现不同?

c - 为什么字符串上的完美释放会导致 "free(): invalid next size"?

c - Eclipse 构建 C 程序中的构建文件错误

linux - 删除符号链接(symbolic link)libc.so.6后如何恢复?

c - 使用指针添加时出现 glibc 错误