0%

优化 c 程序可执行文件大小

优化 elf 大小的各种方式

编译优化等级

  • -O0 默认
  • -O1
  • -O2
  • -O3
  • -Ofast
  • Os

应该使用 -Os 来保证编译的 elf 最小,禁用了类似 inline 之类的编译优化选项,同时对性能敏感的代码使用 #pragma 来保证

#pragma GCC push_options
#pragma GCC optimize ("O2")

/*
 * Code that needs optimizing O2
 */

#pragma GCC pop_options

Linker Garbage Collection

将不使用的 functiondata 从 elf 中删除

CFLAGS += -ffunction-sections -fdata-sections
LDFLAGS += -Wl,--gc-sections

需要避免某些符号被优化掉,例如中断向量,使用 KEEP

    .text :
    {
        KEEP(*(.vectors .vectors.*))
            [...]
    } > rom

strip elf

去除非必要段

$ objcopy -S -g out.elf
$ strip -S --strip-unneeded --remove-section=.note.gnu.gold-version --remove-section=.comment --remove-section=.note --remove-section=.note.gnu.build-id --remove-section=.note.ABI-tag
  • Remove all symbol and relocation information
  • Remove all debugging symbols & sections
  • Remove all symbols not needed by relocations

-m32

Use -m32 to compile a 32-bit binary. 32-bit binaries are smaller than 64-bit binaries because pointers are shorter.

Options

  • -fno-stack-protector
  • -fomit-frame-pointer
  • -fno-math-errno, and don’t check the errno after calling math functions.
  • Try -fno-unroll-loops, sometimes it makes the file smaller.
  • -fmerge-all-constants
  • -fno-ident, this will prevent the generation of the .ident assembler directive, which adds an identification of the compiler to the binary.
  • -mfpmath=387 -mfancy-math-387 to make floating point computations shorter.
  • If you don’t need double precision, but float preecision is enough, use -fshort-double -fsingle-precision-constant .
  • If you don’t need IEEE-conformat floating point calculations, use -ffast-math .
  • Use -Wl,-z,norelro for linking, which is equivalent to ld -z norelro .
  • Use -Wl,–hash-style=gnu for linking, which is equivalent to ld –hash-style=gnu . You may also try =sysv instead of =gnu, sometimes it’s smaller by a couple of bytes. The goal here is to avoid =both, which is the default on some systems.
  • Use -Wl,–build-id=none for linking, which is equivalent to ld –build-id=none .
  • Get more flags from the Os list in diet.c of diet libc, for about 15 architectures.
  • Don’t use these flags: -pie, -fpie, -fPIE, -fpic, -fPIC. Some of these are useful in shared libraries, so enable them only when compiling shared libraries.

C++

  • use -fno-exceptions if your code doesn’t use exceptions.
  • use -fno-rtti if your code doesn’t use RTTI (run-time type identification) or dynamic_cast.
  • use -fvtable-gc to let the linker know about and remove unused virtual method tables.

i386

  • use -mpreferred-stack-boundary=2 .
  • use -falign-functions=1 -falign-jumps=1 -falign-loops=1 .

Ref

  1. How to make smaller C and C++ binaries
  2. Code Size Optimization: GCC Compiler Flags