Skip to content

[gcc] O3比O0生成文件更大

前言

  • 最近发现 gcc 在编译时添加 -g 后,启用优化 O3 生成的可执行文件大小会明显比 O0 更大
  • 挺有意思的,按之前的经验,往往都是启用优化,即 release 应当比 debug 小特别多。
  • 之所以这次需要在 O3 的同时添加 -g,是为了在段错误崩溃时能打印堆栈信息,如果不添加调试信息(符号表、行号等),打印出来只有一些地址。

过程

  • 首先是直接用 gcc 编译生成二进制对比看看,可以发现 release 生成的更大: alt text
  • 换一个代码更简单的试试也是一样: alt text
  • 接下来我们用 readelf 看一下可执行程序的分段大小,看看到底是哪里有偏差
    • 下面是一个程序的 debug(118 MB)和 release(169 MB)对比
    • debug :
txt
There are 42 section headers, starting at offset 0x7598078:

Section Headers:
  [Nr] Name              Type             Address           Offset
       Size              EntSize          Flags  Link  Info  Align
  [ 0]                   NULL             0000000000000000  00000000
       0000000000000000  0000000000000000           0     0     0
  [ 1] .interp           PROGBITS         0000000000400350  00000350
       000000000000001c  0000000000000000   A       0     0     1
  [ 2] .note.gnu.pr[...] NOTE             0000000000400370  00000370
       0000000000000020  0000000000000000   A       0     0     8
  [ 3] .note.ABI-tag     NOTE             0000000000400390  00000390
       0000000000000020  0000000000000000   A       0     0     4
  [ 4] .hash             HASH             00000000004003b0  000003b0
       000000000004264c  0000000000000004   A       6     0     8
  [ 5] .gnu.hash         GNU_HASH         0000000000442a00  00042a00
       000000000004a030  0000000000000000   A       6     0     8
  [ 6] .dynsym           DYNSYM           000000000048ca30  0008ca30
       00000000000ce550  0000000000000018   A       7     1     8
  [ 7] .dynstr           STRTAB           000000000055af80  0015af80
       0000000000345511  0000000000000000   A       0     0     1
  [ 8] .gnu.version      VERSYM           00000000008a0492  004a0492
       000000000001131c  0000000000000002   A       6     0     2
  [ 9] .gnu.version_r    VERNEED          00000000008b17b0  004b17b0
       00000000000002b0  0000000000000000   A       7     5     8
  [10] .rela.dyn         RELA             00000000008b1a60  004b1a60
       0000000000005610  0000000000000018   A       6     0     8
  [11] .rela.plt         RELA             00000000008b7070  004b7070
       0000000000001f08  0000000000000018  AI       6    27     8
  [12] .init             PROGBITS         00000000008b9000  004b9000
       0000000000000020  0000000000000000  AX       0     0     4
  [13] .plt              PROGBITS         00000000008b9020  004b9020
       00000000000014c0  0000000000000010  AX       0     0     16
  [14] .plt.got          PROGBITS         00000000008ba4e0  004ba4e0
       0000000000000088  0000000000000008  AX       0     0     8
  [15] .text             PROGBITS         00000000008bb000  004bb000
       0000000000728762  0000000000000000  AX       0     0     4096
  [16] .fini             PROGBITS         0000000000fe3764  00be3764
       000000000000000d  0000000000000000  AX       0     0     4
  [17] .rodata           PROGBITS         0000000000fe4000  00be4000
       00000000000b97dd  0000000000000000   A       0     0     64
  [18] .eh_frame_hdr     PROGBITS         000000000109d7e0  00c9d7e0
       0000000000055664  0000000000000000   A       0     0     4
  [19] .eh_frame         PROGBITS         00000000010f2e48  00cf2e48
       0000000000163398  0000000000000000   A       0     0     8
  [20] .gcc_except_table PROGBITS         00000000012561e0  00e561e0
       0000000000049fea  0000000000000000   A       0     0     4
  [21] .tbss             NOBITS           00000000012a1a18  00ea0a18
       0000000000000081  0000000000000000 WAT       0     0     8
  [22] .init_array       INIT_ARRAY       00000000012a1a18  00ea0a18
       0000000000000160  0000000000000008  WA       0     0     8
  [23] .fini_array       FINI_ARRAY       00000000012a1b78  00ea0b78
       0000000000000008  0000000000000008  WA       0     0     8
  [24] .data.rel.ro      PROGBITS         00000000012a1b80  00ea0b80
       000000000006ef80  0000000000000000  WA       0     0     32
  [25] .dynamic          DYNAMIC          0000000001310b00  00f0fb00
       0000000000000220  0000000000000010  WA       7     0     8
  [26] .got              PROGBITS         0000000001310d20  00f0fd20
       00000000000002c8  0000000000000008  WA       0     0     8
  [27] .got.plt          PROGBITS         0000000001311000  00f10000
       0000000000000a70  0000000000000008  WA       0     0     8
  [28] .data             PROGBITS         0000000001311a80  00f10a80
       000000000000bce0  0000000000000000  WA       0     0     64
  [29] .bss              NOBITS           000000000131d760  00f1c760
       000000000001cab8  0000000000000000  WA       0     0     32
  [30] .comment          PROGBITS         0000000000000000  00f1c760
       0000000000000012  0000000000000001  MS       0     0     1
  [31] .debug_aranges    PROGBITS         0000000000000000  00f1c780
       00000000003d1240  0000000000000000           0     0     16
  [32] .debug_info       PROGBITS         0000000000000000  012ed9c0
       0000000003f86e8c  0000000000000000           0     0     1
  [33] .debug_abbrev     PROGBITS         0000000000000000  0527484c
       000000000012cda3  0000000000000000           0     0     1
  [34] .debug_line       PROGBITS         0000000000000000  053a15ef
       0000000000dec849  0000000000000000           0     0     1
  [35] .debug_str        PROGBITS         0000000000000000  0618de38
       0000000000a397a4  0000000000000001  MS       0     0     1
  [36] .debug_line_str   PROGBITS         0000000000000000  06bc75dc
       000000000001452d  0000000000000001  MS       0     0     1
  [37] .debug_loclists   PROGBITS         0000000000000000  06bdbb09
       0000000000105e7f  0000000000000000           0     0     1
  [38] .debug_rnglists   PROGBITS         0000000000000000  06ce1988
       00000000002916f5  0000000000000000           0     0     1
  [39] .symtab           SYMTAB           0000000000000000  06f73080
       00000000001634d0  0000000000000018          40   25425     8
  [40] .strtab           STRTAB           0000000000000000  070d6550
       00000000004c198c  0000000000000000           0     0     1
  [41] .shstrtab         STRTAB           0000000000000000  07597edc
       000000000000019c  0000000000000000           0     0     1
Key to Flags:
  W (write), A (alloc), X (execute), M (merge), S (strings), I (info),
  L (link order), O (extra OS processing required), G (group), T (TLS),
  C (compressed), x (unknown), o (OS specific), E (exclude),
  R (retain), D (mbind), l (large), p (processor specific)
- release :
txt
There are 42 section headers, starting at offset 0xa829d90:

Section Headers:
  [Nr] Name              Type             Address           Offset
       Size              EntSize          Flags  Link  Info  Align
  [ 0]                   NULL             0000000000000000  00000000
       0000000000000000  0000000000000000           0     0     0
  [ 1] .interp           PROGBITS         0000000000400350  00000350
       000000000000001c  0000000000000000   A       0     0     1
  [ 2] .note.gnu.pr[...] NOTE             0000000000400370  00000370
       0000000000000020  0000000000000000   A       0     0     8
  [ 3] .note.ABI-tag     NOTE             0000000000400390  00000390
       0000000000000020  0000000000000000   A       0     0     4
  [ 4] .hash             HASH             00000000004003b0  000003b0
       0000000000015e10  0000000000000004   A       6     0     8
  [ 5] .gnu.hash         GNU_HASH         00000000004161c0  000161c0
       0000000000019804  0000000000000000   A       6     0     8
  [ 6] .dynsym           DYNSYM           000000000042f9c8  0002f9c8
       0000000000053298  0000000000000018   A       7     1     8
  [ 7] .dynstr           STRTAB           0000000000482c60  00082c60
       000000000008eea3  0000000000000000   A       0     0     1
  [ 8] .gnu.version      VERSYM           0000000000511b04  00111b04
       0000000000006ee2  0000000000000002   A       6     0     2
  [ 9] .gnu.version_r    VERNEED          00000000005189e8  001189e8
       00000000000002c0  0000000000000000   A       7     5     8
  [10] .rela.dyn         RELA             0000000000518ca8  00118ca8
       0000000000005700  0000000000000018   A       6     0     8
  [11] .rela.plt         RELA             000000000051e3a8  0011e3a8
       0000000000001da0  0000000000000018  AI       6    27     8
  [12] .init             PROGBITS         0000000000521000  00121000
       0000000000000020  0000000000000000  AX       0     0     4
  [13] .plt              PROGBITS         0000000000521020  00121020
       00000000000013d0  0000000000000010  AX       0     0     16
  [14] .plt.got          PROGBITS         00000000005223f0  001223f0
       0000000000000080  0000000000000008  AX       0     0     8
  [15] .text             PROGBITS         0000000000523000  00123000
       0000000000610622  0000000000000000  AX       0     0     4096
  [16] .fini             PROGBITS         0000000000b33624  00733624
       000000000000000d  0000000000000000  AX       0     0     4
  [17] .rodata           PROGBITS         0000000000b34000  00734000
       0000000000088498  0000000000000000   A       0     0     64
  [18] .eh_frame_hdr     PROGBITS         0000000000bbc498  007bc498
       00000000000230cc  0000000000000000   A       0     0     4
  [19] .eh_frame         PROGBITS         0000000000bdf568  007df568
       00000000000c4e28  0000000000000000   A       0     0     8
  [20] .gcc_except_table PROGBITS         0000000000ca4390  008a4390
       000000000003b831  0000000000000000   A       0     0     4
  [21] .tbss             NOBITS           0000000000ce1018  008e0018
       0000000000000088  0000000000000000 WAT       0     0     8
  [22] .init_array       INIT_ARRAY       0000000000ce1018  008e0018
       0000000000000160  0000000000000008  WA       0     0     8
  [23] .fini_array       FINI_ARRAY       0000000000ce1178  008e0178
       0000000000000008  0000000000000008  WA       0     0     8
  [24] .data.rel.ro      PROGBITS         0000000000ce1180  008e0180
       000000000006f700  0000000000000000  WA       0     0     32
  [25] .dynamic          DYNAMIC          0000000000d50880  0094f880
       0000000000000220  0000000000000010  WA       7     0     8
  [26] .got              PROGBITS         0000000000d50aa0  0094faa0
       0000000000000550  0000000000000008  WA       0     0     8
  [27] .got.plt          PROGBITS         0000000000d51000  00950000
       00000000000009f8  0000000000000008  WA       0     0     8
  [28] .data             PROGBITS         0000000000d51a00  00950a00
       0000000000008fb8  0000000000000000  WA       0     0     64
  [29] .bss              NOBITS           0000000000d5a9c0  009599b8
       000000000001ca40  0000000000000000  WA       0     0     32
  [30] .comment          PROGBITS         0000000000000000  009599b8
       0000000000000012  0000000000000001  MS       0     0     1
  [31] .debug_aranges    PROGBITS         0000000000000000  009599ca
       000000000004c5a0  0000000000000000           0     0     1
  [32] .debug_info       PROGBITS         0000000000000000  009a5f6a
       0000000005bcda91  0000000000000000           0     0     1
  [33] .debug_abbrev     PROGBITS         0000000000000000  065739fb
       000000000008ad9a  0000000000000000           0     0     1
  [34] .debug_line       PROGBITS         0000000000000000  065fe795
       0000000000fb88d8  0000000000000000           0     0     1
  [35] .debug_str        PROGBITS         0000000000000000  075b706d
       00000000008c130a  0000000000000001  MS       0     0     1
  [36] .debug_line_str   PROGBITS         0000000000000000  07e78377
       0000000000003c60  0000000000000001  MS       0     0     1
  [37] .debug_loclists   PROGBITS         0000000000000000  07e7bfd7
       000000000221bd0b  0000000000000000           0     0     1
  [38] .debug_rnglists   PROGBITS         0000000000000000  0a097ce2
       00000000005fa870  0000000000000000           0     0     1
  [39] .symtab           SYMTAB           0000000000000000  0a692558
       000000000009d410  0000000000000018          40   12646     8
  [40] .strtab           STRTAB           0000000000000000  0a72f968
       00000000000fa286  0000000000000000           0     0     1
  [41] .shstrtab         STRTAB           0000000000000000  0a829bee
       000000000000019c  0000000000000000           0     0     1
Key to Flags:
  W (write), A (alloc), X (execute), M (merge), S (strings), I (info),
  L (link order), O (extra OS processing required), G (group), T (TLS),
  C (compressed), x (unknown), o (OS specific), E (exclude),
  R (retain), D (mbind), l (large), p (processor specific)
  • 用 git 对比一下,可以发现,主要是 debug_info(+) 和 debug_loclists 段大幅增加了: alt text
  • 经过一顿搜索和 AI 后,基本结论是:
    • 无优化时,源代码和汇编指令的对应关系比较准确,此时生成的调试信息比较简单。
    • 开启优化后,源码和汇编指令的对应比较复杂,因此需要更多信息来记录这些关系。