The Process Of Compiling C Programs Explained

Yago Martinez-Falero Hein
3 min readSep 16, 2020
What happens when you type “gcc main.c”? | LaptrinhX

C is a low-level programming language meaning that by itself it cannot be read by the computer. It needs to be compiled with a compiler (gcc for example) in order to be “translated” into code that your computer will understand (i.e. binary). In this article, we will explain the process of compiling C programs.

The compiler components

The compiler is not a single module compiler, it has four big modules and can be simply described as it follows:

  • Preprocessor: a program that modifies data to conform with the input requirements of the compiler.
  • Compiler: generates an assembly code from the preprocessor input
  • Assembler: convert the assembly code into a computer-readable code (i.e. binary)
  • Linker: used with the assembler to provide links to the libraries needed for an executable program

Let’s look at these steps in-depth

For the sake of this exercise, let’s consider the following C program hello.c:

#include <stdio.h>

/**
* main - Entry point
*
* Return: Always 0 (Success)
*/
int main(void)
{
printf("Hello World\n");
return (0);
}

If we were to run this program the expected output should simply be:

Hello World

But before this happens we need to compile the program so it can be executed.

For that, we will be using the shell command gcc . Obviously, the command gcc hello.c allows you to firectly create a a.out executable file for your C program. Like so:

Command: gcc hello.c && ./a.out

Output: Hello World

But in order to understand the process we will brake it down into the 4 modules to check out how the compiler works.

Preprocessor

The gcc command allows us to process the file without compiling, assembling and linking it.

Let’s preprocess it and save its output on a file named hello_p and print the first 10 lines:

Command:

gcc -E hello.c > hello_p and then… head hello_p

Output:

# 1 "hello.c"# 1 "<built-in>"# 1 "<command-line>"# 1 "/usr/include/stdc-predef.h" 1 3 4# 1 "<command-line>" 2# 1 "hello.c"# 1 "/usr/include/stdio.h" 1 3 4# 27 "/usr/include/stdio.h" 3 4# 1 "/usr/include/features.h" 1 3 4# 374 "/usr/include/features.h" 3 4

Compiler

Now let’s compile it only and see its output in the file hello.o :

Command:

gcc -c hello.c > hello.o and less hello.o

Output:

^?ELF^B^A^A^@^@^@^@^@^@^@^@^@^A^@>^@^A^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@0^A^@^@^@^@^@^@^@^@^@^@@^@^@^@^@^@@^@^M^@^@UH<89><E5><BF>^@^@^@^@<E8>^@^@^@^@<B8>^@^@^@^@]<C3>Hello World^@^@GCC: (Ubuntu 4.8.4-2ubuntu1~14.04.4) 4.8.4^@^@^@^@^T^@^@^@^@^@^@^@^AzR^@^Ax^P^AESC^L^G^H<90>^A^@^@^\^@^@^@^\^@^@^@^@^@^@^@^U^@^@^@^@A^N^P<86>^BC^M^FP^L^G^H^@^@^@^@.symtab^@.strtab^@.shstrtab^@.rela.text^@.data^@.bss^@.rodata^@.comment^@.note.GNU-stack^@.rela.eh_frame^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@ ^@^@^@^A^@^@^@^F^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@@^@^@^@^@^@^@^@^U^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^A^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@ESC^@^@^@^D^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@<90>^E^@^@^@^@^@^@0^@^@^@^@^@^@^@^K^@^@^@^A^@^@^@^H^@^@^@^@^@^@^@^X^@^@^@^@^@^@^@&^@^@^@^A^@^@^@^C^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@U^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^A^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@,^@^@^@^H^@^@^@^C^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@U^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^A^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@1^@^@^@^A^@^@^@^B^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@U^@^@^@^@^@^@^@^L^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^A^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@9^@^@^@^A^@^@^@0^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@a^@^@^@^@^@^@^@,^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^A^@^@^@^@^@^@^@^A^@^@^@^@^@^@^@B^@^@^@^A^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@<8D>^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^A^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@W^@^@^@^A^@^@^@^B^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@<90>^@^@^@^@^@^@^@8^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^H^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@R^@^@^@^D^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@<C0>^E^@^@^@^@^@^@^X^@^@^@^@^@^@^@^K^@^@^@^H^@^@^@^H^@^@^@^@^@^@^@^X^@^@^@^@^@^@^@^Q^@^@^@^C^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@<C8>^@^@^@^@^@^@^@a^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^A^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^A^@^@^@^B^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@p^D^@^@^@^@^@^@^H^A^@^@^@^@^@^@^L^@^@^@ ^@^@^@^H^@^@^@^@^@^@^@^X^@^@^@^@^@^@^@  ^@^@^@^C^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@x^E^@^@^@^@^@^@^S^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^A^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^A^@^@^@^D^@<F1><FF>^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^C^@^A^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^C^@^C^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^C^@^D^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^C^@^E^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^C^@^G^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^C^@^H^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^C^@^F^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@       ^@^@^@^R^@^A^@^@^@^@^@^@^@^@^@^U^@^@^@^@^@^@^@^N^@^@^@^P^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@hello.c^@main^@puts^@^@^@^@^@^@^E^@^@^@^@^@^@^

Assembler

Now let’s assemble it only and see its output in the file hello.s :

Command:

gcc -S hello.c > hello.s and less hello.s

Output:

.file   "hello.c".section        .rodata.LC0:.string "Hello World".text.globl  main.type   main, @functionmain:.LFB0:.cfi_startprocpushq   %rbp.cfi_def_cfa_offset 16.cfi_offset 6, -16movq    %rsp, %rbp.cfi_def_cfa_register 6movl    $.LC0, %edicall    putsmovl    $0, %eaxpopq    %rbp.cfi_def_cfa 7, 8ret.cfi_endproc.LFE0:.size   main, .-main.ident  "GCC: (Ubuntu 4.8.4-2ubuntu1~14.04.4) 4.8.4".section        .note.GNU-stack,"",@progbits

Linker

This time we’ll checkout what a fully compiled file looks like.

Now we can directly insert the following:

Command: gcc hello.c and then less a.out

Output:

^?ELF^B^A^A^@^@^@^@^@^@^@^@^@^B^@>^@^A^@^@^@@^D@^@^@^@^@^@@^@^@^@^@^@^@^@x^Q^@^@^@^@^@^@^@^@^@^@@^@8^@  ^@@^@^^^@ESC^@^F^@^@^@^E^@^@^@@^@^@^@^@^@^@^@@^@@^@^@^@^@^@@^@@^@^@^@^@^@<F8>^A^@^@^@^@^@^@<F8>^A^@^@^@^@^@^@^H^@^@^@^@^@^@^@^C^@^@^@^D^@^@^@8^B^@^@^@^@^@^@8^B@^@^@^@^@^@8^B@^@^@^@^@^@^\^@^@^@^@^@^@^@^\^@^@^@^@^@^@^@^A^@^@^@^@^@^@^@^A^@^@^@^E^@^@^@^@^@^@^@^@^@^@^@^@^@@^@^@^@^@^@^@^@@^@^@^@^@^@^L^G^@^@^@^@^@^@^L^G^@^@^@^@^@^@^@^@ ^@^@^@^@^@^A^@^@^@^F^@^@^@^P^N^@^@^@^@^@^@^P^N`^@^@^@^@^@^P^N`^@^@^@^@^@0^B^@^@^@^@^@^@8^B^@^@^@^@^@^@^@^@ ^@^@^@^@^@^B^@^@^@^F^@^@^@(^N^@^@^@^@^@^@(^N`^@^@^@^@^@(^N`^@^@^@^@^@<D0>^A^@^@^@^@^@^@<D0>^A^@^@^@^@^@^@^H^@^@^@^@^@^@^@^D^@^@^@^D^@^@^@T^B^@^@^@^@^@^@T^B@^@^@^@^@^@T^B@^@^@^@^@^@D^@^@^@^@^@^@^@D^@^@^@^@^@^@^@^D^@^@^@^@^@^@^@P<E5>td^D^@^@^@<E0>^E^@^@^@^@^@^@<E0>^E@^@^@^@^@^@<E0>^E@^@^@^@^@^@4^@^@^@^@^@^@^@4^@^@^@^@^@^@^@^D^@^@^@^@^@^@^@Q<E5>td^F^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^P^@^@^@^@^@^@^@R<E5>td^D^@^@^@^P^N^@^@^@^@^@^@^P^N`^@^@^@^@^@^P^N`^@^@^@^@^@<F0>^A^@^@^@^@^@^@<F0>^A^@^@^@^@^@^@^A^@^@^@^@^@^@^@/lib64/ld-linux-x86-64.so.2^@^D^@^@^@^P^@^@^@^A^@^@^@GNU^@^@^@^@^@^B^@^@^@^F^@^@^@^X^@^@^@^D^@^@^@^T^@^@^@^C^@^@^@GNU^@<D1><98>J<BA>^]L^Q<C0>)a=<DB>F<84><A9>^W<]p<E7>^A^@^@^@^A^@^@^@^A^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^K^@^@^@^R^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^P^@^@^@^R^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@"^@^@^@ ^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@libc.so.6^@puts^@__libc_start_main^@__gmon_start__^@GLIBC_2.2.5^@^@^@^@^B^@^B^@^@^@^@^@^A^@^A^@^A^@^@^@^P^@^@^@^@^@^@^@u^Zi      ^@^@^B^@1^@^@^@^@^@^@^@<F8>^O`^@^@^@^@^@^F^@^@^@^C^@^@^@^@^@^@^@^@^@^@^@^X^P`^@^@^@^@^@^G^@^@^@^A^@^@^@^@^@^@^@^@^@^@^@^P`^@^@^@^@^@^G^@^@^@^B^@^@^@^@^@^@^@^@^@^@^@(^P`^@^@^@^@^@^G^@^@^@^C^@^@^@^@^@^@^@^@^@^@^@H<83><EC>^HH<8B>^E^M^L ^@H<85><C0>t^E<E8>;^@^@^@H<83><C4>^H<C3>^@^@^@^@^@^@<FF>5^B^L ^@<FF>%^D^L ^@^O^_@^@<FF>%^B^L ^@h^@^@^@^@<E9><E0><FF><FF><FF><FF>%<FA>^K ^@h^A^@^@^@<E9><D0><FF><FF><FF><FF>%<F2>^K ^@h^B^@^@^@<E9><C0><FF><FF><FF>1<ED>I<89><D1>^H<89><E2>H<83><E4><F0>PTI<C7><C0><C0>^E@^@H<C7><C1>P^E@^@H<C7><C7>-^E@^@<E8><B7><FF><FF><FF><F4>f^O^_D^@^@<B8>G^P`^@UH-@^P`^@H<83><F8>^NH<89><E5>w^B]<C3><B8>^@^@^@^@H<85><C0>t<F4>]<BF>@^P`^@<FF><E0>^O^_<80>^@^@^@^@<B8>@^P`^@UH-@^P`^@H<C1><F8>^CH<89><E5>H<89><C2>H<C1><EA>?H^A<D0>H<D1><F8>u^B]<C3><BA>^@^@^@^@H<85><D2>t<F4>]H<89><C6><BF>@^P`^@<FF><E2>^O^_<80>^@^@^@^@<80>=Y^K ^@^@u^QUH<89><E5><E8>~<FF><FF><FF>]<C6>^EF^K ^@^A<F3><C3>^O^_@^@H<83>=^X       ^@^@t^^<B8>^@^@^@^@H<85><C0>t^TU<BF> ^N`^@H<89><E5><FF><D0>]<E9>{<FF><FF><FF>^O^_^@<E9>s<FF><FF><FF>UH<89><E5><BF><D4>^E@^@<E8><D5><FE><FF><FF><B8>^@^@^@^@]<C3>f.^O^_<84>^@^@^@^@^@^O^_@^@AWA<89><FF>AVI<89><F6>AUI<89><D5>ATLa.out

--

--

Yago Martinez-Falero Hein

👨🏼‍💻 Entrepreneur and software engeneer // Former employee at TheFamily.co // 👨🏼‍🎓 Holberton School & Reverse Origins