Table of Contents
Concepts covered in this write-up
- Symbol Tables.
- Linking
- Relocation.
- Basics of bootloader and system start-up.
A small detour into understanding what is a symbol table.
I would recommend reading the chapter one before reading the rest of this write up.
Symbol Tables
This is more towards the design of compilers; but a brief idea on this would be good to have.
The symbol table is nothing but a data structure; maintained by the program to keep account of all the names, symbols, variables, functions, inclusion names etc.
Let’s say you reference a global variable in a file b.c from a.c
example
/* File: a.c */
#include <stdio.h>
#include "b.h"
#define UNKNOWN 0
main()
{
gummy bear = UNKNOWN;
printf(" gumm bear = %d" ,
gummy bear);
}
Now imagine this is compiled first ; the variable gummy bear is unknown to the compiler; what it does is stores the name into its symbol table and lets the linker take care of finding its definition.
Without a b.h and a definition ; the linker will throw an error stating ” Unresolved symbol gummy bear”. This is solved by including the b.h file which holds b.c as below
/* File : b.c*/
int gummy bear = 0;
main()
{
.
.
.
}
To keep an account of what is used; a symbol table is used. For available references; the symbol table is filled automatically at compilation; for those that do not have declarations the table remains empty until linking starts.
Hope this gives you a brief idea of what the symbol table is used for.
This will be known to the linker; and the symbols will be resolved. More on this later!
LINKER
The linker mainly does two things
- To combine all the object files into one object file (which is not limited to segregating the .obj file into data, .bss and text sections).
- To resolve all the unresolved symbols that was missed during the compilation process.
The linker knows the existence of all the files and it aims to resolve symbols by looking for their definition.
If the definition is not available; the linker throws an unresolved symbol error or any other as applicable.
NOTE:
Certain standard C headers are available to embedded cross compilers through a construct called newLib; which is from the redhat developers. The presence of this folder; tells the linker to resolve definitions such as memcpy; strcpy etc.
Now the code is linked; what is left to do?
The physical memory assignment needs to be done. How is the host computer to know of the memory architecture of the target embedded system?
The answer is Linker Scripts.
The process of physically assigning an address is called Relocation.
The linker script holds the memory layout of the flash and the respective physical addressing is done.
Now what is Mem-Map and Make file?
The Mem-Map tells you what the linker/relocator has been able to achieve based on inputs from the linker script. It tells you where, who is sitting. A good way to check the RAM/ROM metrics and perform memory optimizations as required.
The Make File?
The make file simply acts as a guide to feed files into the compiler. It tells the compiler and linker what to consider into the build and what not to; merely a script.
A really good introductory video on make file in the video mentioned below; do check it out! A shout out to them!!
Piecing them all together
Now that, the final executable file is ready. All there is left to do is to flash the target with this image. Most targets take in hex / elf etc formats and now this is done.
There is usually something called the start-up code .
The start up code does the following
- Disables all interrupts.
- Initializes data from ROM –> RAM
- Initialize the stack
- Stack Pointer Initialization
- Calling the application main
Please note: This is a generic concept and is customized based on the application necessity; the application main can even be boot loader main.
This start up code is usually part of the compilation and builds process. This acts as base to prepare the further incoming data.
The start up code contains a few functions that initializes the processor and its register and within which is the reset handler function.
This reset handler branches and calls for the application main; so if anyone has ever wondered how main is invoked in the controller; this is how it is done 😉 .
As always I hope you enjoyed reading this article. Share your views down in the comment section below.
Cheers!