Terlepas dari yang sudah jelas (-Os -s
), menyelaraskan fungsi ke nilai sekecil mungkin yang tidak akan macet (saya tidak tahu persyaratan penyelarasan ARM) mungkin memeras beberapa byte per fungsi.
-Os
harus sudah menonaktifkan fungsi penyelarasan, tetapi ini mungkin masih default ke nilai seperti 4 atau 8. Jika menyelaraskan mis. ke 1 dimungkinkan dengan ARM, yang mungkin menghemat beberapa byte.
-ffast-math
(atau -fno-math-errno
yang kurang abrasif ) tidak akan menyetel errno dan menghindari beberapa pemeriksaan, yang mengurangi ukuran kode. Jika, seperti kebanyakan orang, Anda tetap tidak membaca errno, itu adalah pilihan.
Menggunakan __restrict
dengan benar (atau restrict
) dan const
menghilangkan beban berlebihan, membuat kode lebih cepat dan lebih kecil (dan lebih benar). Menandai fungsi murni dengan benar akan menghilangkan panggilan fungsi.
Mengaktifkan LTO dapat membantu, dan jika itu tidak tersedia, kompilasi semua file sumber menjadi biner sekaligus (gcc foo.c bar.c baz.c -o program
alih-alih mengkompilasi foo.c
, bar.c
, dan baz.c
ke objek file terlebih dahulu dan kemudian menautkan) akan memiliki efek yang serupa. Itu membuat semuanya terlihat oleh pengoptimal sekaligus, memungkinkannya bekerja lebih baik.
-fdelete-null-pointer-checks
mungkin merupakan opsi (perhatikan bahwa ini biasanya diaktifkan dengan "O" apa pun, tetapi tidak pada target tersemat).
Menempatkan global statis (mudah-mudahan Anda tidak memiliki sebanyak itu, tapi masih) ke dalam struct dapat menghilangkan banyak overhead menginisialisasi mereka. Saya mempelajarinya saat menulis loader OpenGL pertama saya. Memiliki semua pointer fungsi dalam sebuah struct dan menginisialisasi struct dengan = {}
menghasilkan satu panggilan ke memset
, sedangkan menginisialisasi pointer dengan "cara normal" menghasilkan seratus kilobyte kode hanya untuk menyetel masing-masing ke nol satu per satu.
Hindari local non-trivial-constructor statis variabel seperti iblis (tipe POD tidak masalah). Gcc akan menginisialisasi non-trivial-constructor static locals threadsafe kecuali Anda mengompilasi dengan -fno-threadsafe-statics
, yang menautkan banyak kode tambahan (bahkan jika Anda tidak menggunakan utas sama sekali).
Menggunakan sesuatu seperti libowfat daripada crt normal dapat sangat kurangi ukuran biner Anda.
Jika Anda ingin memeras setiap tetes ruang terakhir dari binari Anda, Anda mungkin harus belajar perakitan. Untuk intro yang sangat menarik (dan menghibur), lihat tautan ini:
Tutorial Angin Puyuh untuk Membuat Executable ELF yang Sangat Kecil untuk Linux
Anda juga dapat menggunakan -nostartfiles
dan/atau -nodefaultlibs
atau kombo keduanya -nostdlib
. Jika Anda tidak menginginkan file awal standar, Anda harus menulis fungsi _start Anda sendiri. Lihat juga utas ini (diarsipkan) di oompf:
(mengutip Perrin)
# man syscalls
# cat phat.cc
extern "C" void _start() {
asm("int $0x80" :: "a"(1), "b"(42));
}
# g++ -fno-exceptions -Os -c phat.cc
# objdump -d phat.o
phat.o: file format elf64-x86-64
Disassembly of section .text:
0000000000000000 <_start>:
0: 53 push %rbx
1: b8 01 00 00 00 mov $0x1,%eax
6: bb 2a 00 00 00 mov $0x2a,%ebx
b: cd 80 int $0x80
d: 5b pop %rbx
e: c3 retq
# ld -nostdlib -nostartfiles phat.o -o phat
# sstrip phat
# ls -l phat
-rwxr-xr-x 1 tbp src 294 2007-04-11 22:47 phat
# ./phat; echo $?
42
Rangkuman:Cuplikan di atas menghasilkan biner 294 byte , setiap byte 8 bit.
Dengan asumsi bahwa alat lain juga diperbolehkan;-)
Lalu pertimbangkan UPX:Ultimate Packer untuk Binari yang menggunakan dekompresi runtime.
Selamat membuat kode.