Home » Linux, OS Concepts and Networking » Operating System Concepts » How executable is created during compilation on Linux ?

How executable is created during compilation on Linux ?

This code is tested on Ubuntu . You may need to twick the script if you use a different Linux 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

We will create helloworld.c as,

$ vim helloworld.c
#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;
}

Now lets run preprocessor

$ gcc -E helloworld.c -o helloworld.i

Once we see preprocessor command completed, it does the job of replacing all “MY_NAME” #define with DevBee string and we will get the file helloworld.i as,

xtern int __uflow (FILE *);
extern int __overflow (FILE *, int);
# 873 "/usr/include/stdio.h" 3 4

# 2 "hello.c" 2



# 4 "hello.c"
int main(int argc, char **argv) {
 printf("validating preprocessor string: %s\n", "DevBee");
 printf("Hello world for understanding compilation\n");
 return 0;
}

As we can see above, it would add stdio.h contents and replaced MY_NAME with DevBee string.

Now we can see, how compiler creates assembly code by taking input as pre-processed code

$ gcc -S helloworld.i -o helloworld.s
$ file helloworld.s
helloworld.s: assembler source, ASCII text

The assembly code can be as,

        .file   "helloworld.c"
        .text
        .section        .rodata
.LC0:
        .string "DevBee"
        .align 8
.LC1:
        .string "validating preprocessor string: %s\n"
        .align 8
.LC2:
        .string "Hello world for understanding compilation"
        .text
        .globl  main
        .type   main, @function
main:
.LFB0:
        .cfi_startproc

Now, we will see the job of assembler to create object .o files by taking assembly code .s,

$ as -o helloworld.o helloworld.s
$ file helloworld.o
helloworld.o: ELF 64-bit LSB relocatable, x86-64, version 1 (SYSV), not stripped

The final step is where linker is executed to link all the object files as created above and link those with the dependent libraries and create the executable. The command would be something as,

$ ld -o helloworld.exe helloworld.o dependent_libs
 /usr/lib/gcc/x86_64-linux-gnu/9/collect2 -plugin /usr/lib/gcc/x86_64-linux-gnu/9/liblto_plugin.so -plugin-opt=/usr/lib/gcc/x86_64-linux-gnu/9/lto-wrapper -plugin-opt=-fresolution=/tmp/cc0lt61x.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 --build-id --eh-frame-hdr -m elf_x86_64 --hash-style=gnu --as-needed -dynamic-linker /lib64/ld-linux-x86-64.so.2 -pie -z now -z relro -o hello.exe /usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/Scrt1.o /usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/crti.o /usr/lib/gcc/x86_64-linux-gnu/9/crtbeginS.o -L/usr/lib/gcc/x86_64-linux-gnu/9 -L/usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu -L/usr/lib/gcc/x86_64-linux-gnu/9/../../../../lib -L/lib/x86_64-linux-gnu -L/lib/../lib -L/usr/lib/x86_64-linux-gnu -L/usr/lib/../lib -L/usr/lib/gcc/x86_64-linux-gnu/9/../../.. /tmp/ccTdnlGv.o -lgcc --push-state --as-needed -lgcc_s --pop-state -lc -lgcc --push-state --as-needed -lgcc_s --pop-state /usr/lib/gcc/x86_64-linux-gnu/9/crtendS.o /usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-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 http://www.tenouk.com/ModuleW.html for great details.


Subscribe our Rurban Life YouTube Channel.. "Rural Life, Urban LifeStyle"

Leave a Comment