Skip to content

Gcc Driver

how src file is turned into binary

this article will explain how gcc driver works, and how you can control its behavior, using command line interface.

to compile any source file from a text to a binary executable, the file goes through many stages, each one is done by a separate program, the gcc job is to orchestrate them and make them work together.

1. Preprocessing

this is the first phase on compiling which meant to resolve all preprocessing statements in the source file like #define and #include. to tell gcc that you need only to preprocess the input file w/o compiling or linking you can use the -E option:

gcc -E main.c -o main.i

main.i file contains the preprocessed version of main.c you can use cpp command to get same result, cpp stand for C PreProcessing.

2. Compiling

this is the main job of the compiler, where it parses machine independent C file and transformes it into machine depending assembly, this why C is very portable. you can instruct gcc to stop right after this step, by using the -S option:

gcc -S main.c -o main.s

main.s file contains the assembly instruction, that will later be compiled into a binary.

3. Assembly

this step takes an assembly file as input and gives an object file as an output. to stop gcc after this step, use the option -c:

gcc -c main.c -o main.o

you can emulate the same thing if you use an actual assembler, for example as.

4. Linking

the last step is linking, which takes one or many object files, and resolve all there undefined symbols, and assign them addresses, this is where libraries can get involved.

to link a program you don't have to say anything because it is the default:

gcc main.c -o main
./main

there is a separate program called ld, the same linker used by gcc.

Helpfull Options:

to see gcc in action, use the -v option and you will see all the commands invoked by the driver. there is also a couple intresting options that allows you to hook into different programs used during compilation steps, to influence there behavior bypassing the driver, e.g you can use -Wp, to tell the driver to pass an option to the preprocessor:

gcc -Wp,-MMD,$(depfile)

This instruct the preprocessor to generate a dependency map for the compiled src file.

Or you can use -Wa, to hook into the assembler. Or -Wl, to pass options to the linker:

gcc -Wl,--entry,func1 main.c

This will instruct the linker to use func1 function as an entry point instead of the default, which is _start.