Thursday, April 12, 2018

Build-and-Run: From C Programs to Linux Processes


A typical C program undergoes several transformations before it becomes a running process. This post illustrates these transformations. We are given two source files and one header file. These steps were tested on a x86-64 Ubuntu 16.04 machine. The figure below (from https://www.hackerearth.com/practice/notes/build-process-cc/ ) summarizes the steps.


Image result for C compilation process
 

//sum.h
#ifndef __SUM_H_
int sum(int, int);
#endif


------------------

//sum.c
#include "sum.h"
int sum(int a, int b){
   return a+b;
}


------------------

//main.c
#include <stdio.h>
#include "sum.h"

int a=3;
int main(){
   int b=4;
   printf("a+b=%d\n",sum(a,b));
   return 0;
}

-----------------



Create sum.o
----------------------
1. Preprocess
$ cpp -o sum.i sum.c

2. Generate asm code from preprocessed
$ gcc -S -o sum.S sum.i

3. Create object file
$ as -o sum.o sum.S

4. Examine object file
$ objdump -x -d -M intel sum.o | less


Create main.o
-----------------------
1. Preprocess
$ cpp -o main.i main.c

2. Generate asm code from preprocessed
$ gcc -S -o main.S main.i

3. Create object file
$ as -o main.o main.S

4. Examine object file
$ objdump -x -d -M intel main.o | less   

Create the final executable main.exe
------------------------------------------------------------
1. Link main.o sum.o and system libraries
$ ld -o main.exe main.o sum.o -dynamic-linker /lib64/ld-linux-x86-64.so.2 /usr/lib/x86_64-linux-gnu/crt1.o /usr/lib/x86_64-linux-gnu/crti.o /usr/lib/gcc/x86_64-linux-gnu/5/crtbegin.o -lc /usr/lib/gcc/x86_64-linux-gnu/5/crtend.o /usr/lib/x86_64-linux-gnu/crtn.o

2. Examine object file
$ objdump -x -d -M intel main.exe | less

3. Use gdb to load the program and create a process
$ gdb ./main.exe
(gdb) set disassembly-flavor intel
(gdb) b main
(gdb) r
(gdb) disas main
(gdb) info proc all
(gdb) c
(gdb) quit