Getting started with GCC
GCC (GNU Compiler Collection) is a suite of tools aimed at compiling various programming languages for different CPU architectures.
Following instructions can be carried out at enos.itcollege.ee
via SSH, the software is already installed there so you don't have to run apt-get install
lines.
On your personal Ubuntu machine you can install GCC via APT:
apt-get install build-essential
Sample source files
Create a plain-text file libfib.c
with following content:
int fib(n) { if (n == 1 || n== 2) { return 1; } else { return fib(n-1) + fib(n-2); } }
Create another plain-text file to invoke the function described above:
#include <stdio.h> int main(int argc, char **argv) { if (argc != 2) { printf("Please specify only one argument\n"); return -1; } else { int n; sscanf("%d", argv[1], &n); printf("%dth fibonacci number is %d\n", n, fib(n)); return 0; } }
Compiling native binaries
Verify that the code works:
gcc libfib.c hello.c -o hello-simple
Invocation of the binary should result in output 42th fibonacci number is 267914296
:
./hello-simple 42
Use file
to inspect what kind of executable was created:
file hello-simple
Compiling assembly
Generate assembly for the C file which contains fib
function:
gcc libfib.c -S -o libfib.s
Investigate the assembly corresponding to fib
:
gcc -static libfib.c hello.c -o hello-simple-static
Dynamic vs static linking
The hello-simple
compiled above is dynamically linked library, you can list dependant libraries width ldd
:
ldd hello-simple
Compile the static version:
gcc -static libfib.c hello.c -o hello-simple-static
Attempting to run ldd
against such binary will result in error not a dynamic executable
.
List the files and their sizes, what is the difference and why?
ls -lah hello-simple hello-simple-static
Libraries
Use the compiler to compile assembly from the C source code:
gcc -fPIC libfib.c -S -o libfib-native.s gcc hello.c -S -o hello-native.s
Turn assembly into object files:
gcc -fPIC -c libfib-native.s -o libfib-native.o gcc -c hello-native.s -o hello-native.o
Finally link the object file against system libraries to produce usable binary:
mkdir mylibs gcc -fPIC libfib-native.o -shared -o mylibs/libfib-native.so gcc hello-native.o -o hello-native -L mylibs -l fib-native
Invoke the binary to test if it actually works, expect the program to print line Hello, World!
:
LD_LIBRARY_PATH=mylibs ./hello-native 42
The binary was compiled dynamically which means that during it's invocation OS is requested to load dependent libraries to the memory is necessary.
You can use ldd
to investigate which libraries are required to invoke the binaries:
LD_LIBRARY_PATH=mylibs ldd hello-native
Alternatively you can compile the binary statically, in that case all the necessary machinery get's bundled into the resulting binary:
gcc libfib-native.o hello-native.o -static -o hello-native-static
Deassembling a binary
Use objdump
to locate the section corresponding to function fib
.
objdump -D mylibs/libfib-native.so
Cross-compiling
Use ARM cross-compiler to compile ARM binaries on x86:
arm-linux-gnueabihf-gcc hello.c -static -o hello
./a.out
Hello, World! lvosandi@enos:~$ cat hello.c
lvosandi@enos:~$ arm-linux-gnueabihf-gcc -march=armv8-a hello.c -static -O hello
arm-linux-gnueabihf-gcc: error: hello: No such file or directory
lvosandi@enos:~$ arm-linux-gnueabihf-gcc -march=armv8-a hello.c -static -o hello
lvosandi@enos:~$ ./hello
Hello, World!
lvosandi@enos:~$ file hello
hello: ELF 32-bit LSB executable, ARM, EABI5 version 1 (SYSV), statically linked, for GNU/Linux 2.6.32, BuildID[sha1]=f553117e8aa8d9d9e26ae85b29437b5193a1790a, not stripped