Skip to content

Compiler options

Hide debugging information and symbols. Use optimization and generates complicated code. Disable dynamic linking.

-g

Enable debugging information.

Debugging informations are stored in .debug_* sections.

Show all sections : readelf -S ./binary

-s

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 .symtab is removed by the -s flag.

Show symbols : readelf --syms ./binary

-fvisibility=hidden

Hide all possible symbols.

-O3

Optimization flag.

  1. -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.
  2. -O2 : Optimize even more. GCC performs nearly all supported optimizations that do not involve a space-speed tradeoff.
  3. -O3 : All optimizations in -O2 plus a handful of others.
  4. -Os : All -O2 optimizations that do not typically increase code size. It also performs further optimizations designed to reduce code size.

-funroll-loops

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.

-static

Prevents linking with the shared libraries.

glibc, the libc version shipped with many major Linux distros, is really not meant to be statically linked. When we do statically link it, some libc 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
  • uClibc
  • 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 : ldd <binary>

If the binary doesn't have any dynamic dependencies, you cannot use LD_PRELOAD or ltrace to hook functions.

Conclusion

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

References