优化 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
将不使用的 function
、data
从 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 .