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.


lynxbee_ezoic

Subscribe with Valid Email Id to receive updates in Inbox. ( Secured by Google FeedBurner )

   


Leave a Comment

Android Android Applications Android Build system Android Commands Application Libraries Application Stack / User Interface Bash / Shell Scripts Bluetooth driver Cloud Technologies Commands and Packages Compilation Content Management System Core Kernel C Programs Development & Build Development, Debugging and Performance Tools Development Environment Setup Django & REST Api Errors & Failures Git Hardware Platforms HTML JAVA Programs Linux, OS Concepts and Networking Linux Device Drivers Linux Host, Ubuntu, SysAdmin Linux Kernel Linux Networking Middleware Libraries, HAL Multimedia Audio, Video, Images NDK / Middleware / HAL OS Concepts PHP Programming Languages Scripting and Automation Search Engine Optimisation ( SEO ) Social Media Source Code Management ( SCM ) System Administration, Security Testing and Debugging Uncategorized Web design and development Website Hosting Wordpress Yocto / Bitbake / Openembedded