From source code to executable : How executable is created during compilation on Linux

We will use a self explanatory bash script, you can just copy paste the below highlighted code and create a file called” and execute it on terminal as “bash”

This code is tested on Ubuntu 15.04, Vivid. You may need to twick the script if you use a different version.

The steps for compilation as as below,

  1. write a source code helloworld.c
  2. run a preprocessor which create helloworld.i
  3. run a compiler which creates helloworld.s by taking preprocessed file helloworld.i as input.
  4. run a assembler which creates helloworld.o b taking helloworld.s as input
  5. run a linker which takes helloworld.o as input and generates helloworld executable


echo “our helloworld program is”

echo “

#include <stdio.h>

#define MY_NAME \”DevBee\”

int main(int argc, char **argv) {
printf(\”validating preprocessor string: %s\n\”, MY_NAME);
printf(\”Hello world for understanding compilation\n\”);
return 0;

” > helloworld.c

echo “executing preprocessor”

/usr/lib/gcc/i686-linux-gnu/4.9/cc1 -E -quiet -v -imultiarch i386-linux-gnu helloworld.c -mtune=generic -march=i686 -fpch-preprocess -fstack-protector-strong -Wformat -Wformat-security -o helloworld.i

echo “executing compiler”
/usr/lib/gcc/i686-linux-gnu/4.9/cc1 -fpreprocessed helloworld.i -quiet -dumpbase helloworld.c -mtune=generic -march=i686 -auxbase helloworld -version -fstack-protector-strong -Wformat -Wformat-security -o helloworld.s

echo “executing assembler”
as -v –32 -o helloworld.o helloworld.s

echo “ececuting loader to create final executable”

/usr/lib/gcc/i686-linux-gnu/4.9/collect2 -plugin /usr/lib/gcc/i686-linux-gnu/4.9/ -plugin-opt=/usr/lib/gcc/i686-linux-gnu/4.9/lto-wrapper -plugin-opt=-fresolution=helloworld.res -plugin-opt=-pass-through=-lgcc -plugin-opt=-pass-through=-lgcc_s -plugin-opt=-pass-through=-lc -plugin-opt=-pass-through=-lgcc -plugin-opt=-pass-through=-lgcc_s –sysroot=/ –build-id –eh-frame-hdr -m elf_i386 –hash-style=gnu –as-needed -dynamic-linker /lib/ -z relro -o helloworld /usr/lib/gcc/i686-linux-gnu/4.9/../../../i386-linux-gnu/crt1.o /usr/lib/gcc/i686-linux-gnu/4.9/../../../i386-linux-gnu/crti.o /usr/lib/gcc/i686-linux-gnu/4.9/crtbegin.o -L/usr/lib/gcc/i686-linux-gnu/4.9 -L/usr/lib/gcc/i686-linux-gnu/4.9/../../../i386-linux-gnu -L/usr/lib/gcc/i686-linux-gnu/4.9/../../../../lib -L/lib/i386-linux-gnu -L/lib/../lib -L/usr/lib/i386-linux-gnu -L/usr/lib/../lib -L/usr/lib/gcc/i686-linux-gnu/4.9/../../.. helloworld.o -lgcc –as-needed -lgcc_s –no-as-needed -lc -lgcc –as-needed -lgcc_s –no-as-needed /usr/lib/gcc/i686-linux-gnu/4.9/crtend.o /usr/lib/gcc/i686-linux-gnu/4.9/../../../i386-linux-gnu/crtn.o

The files created during compilation time are as below,

$ file helloworld.c
helloworld.c: C source, ASCII text

$ file helloworld.i
helloworld.i: C source, ASCII text

$ file helloworld.s
helloworld.s: assembler source, ASCII text
$ file helloworld.o
helloworld.o: ELF 32-bit LSB relocatable, Intel 80386, version 1 (SYSV), not stripped
$ file helloworld
helloworld: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.32, BuildID[sha1]=e9c198a3e75c0d32d8c775381b3641cbcb8f8848, not stripped

You can refer for great details.

Follow Lynxbee

Leave a Reply / Ask Question