Hide debugging information and symbols. Use optimization and generates complicated code. Disable dynamic linking.
Enable debugging information.
Debugging informations are stored in
Show all sections :
readelf -S ./binary
Strip the binary (remove all symbol table and relocation information from the executable).
.dynsym & .symtab :
.dynsym: will be loaded into memory when the program is started.
.symtab: will not be loaded into memory and is therefore not necessary to execute the program.
- The section
.symtabis removed by the
Show symbols :
readelf --syms ./binary
Hide all possible symbols.
- -O1 : With -O, the compiler tries to reduce code size and execution time, without performing any optimizations that take a great deal of compilation time.
- -O2 : Optimize even more. GCC performs nearly all supported optimizations that do not involve a space-speed tradeoff.
- -O3 : All optimizations in -O2 plus a handful of others.
- -Os : All -O2 optimizations that do not typically increase code size. It also performs further optimizations designed to reduce code size.
Unroll or undo the looping structure of any loop whose iterations can be determined at compile time.
This will produce increasingly long and complicated code.
Prevents linking with the shared libraries.
libc version shipped with many major Linux distros, is really not meant to be statically linked. When we do statically link it, some
functionality gets broken and it makes our binary significantlly larger.
There are other versions of
libc that are intended to be statically linked :
- diet libc
- musl libc
$ gcc -static reverse.c -o reverse $ du -h reverse 780K reverse $ musl-gcc -static reverse.c -o reverse $ du -h reverse 24K reverse
Show dynamic section :
readelf -d <binary>
Show external dependencies :
If the binary doesn't have any dynamic dependencies, you cannot use
ltrace to hook functions.
Combining all the options will result into the following command :
musl-gcc -Wall -Wextra -Wshadow -s -fvisibility=hidden -O3 -funroll-loops -static main.c -o main