Sunday, May 24, 2015

Embedded C Build Process


  • Pre-Processor:
    • .c + .h --> .i
    • .c + .h --> .i
    • .c + .h --> .i
    • Stripes out the comments
    • Substitute the #include
    • Substitute the # macros
  • Compiler:
    • .i --> .s --> .o
    • .i --> .s --> .o
    • .i --> .s --> .o
    • from c to assembly
    • the assembly is written in machine code
    • each .o file contains:
      • symbol table
        • symbol name | address in memory | symbol size | symbol section (bss - data - rodata - text - ...etc)
        • all addresses are relative to the file
        • for external variables, the addresses are not determined. (to be determined after linking)
      • sections
        • bss: uninitialized global variables
        • data: initialized global variables
        • rodata: constants
        • text: code
  • Linker:
    • .o + .o + .o + startup.o + standard_libs.o --> app.o
    • standard_libs.o
      • to resolve functions like printf(), ...etc
    • startup.o
      • disable all interrupts
      • copy initialized variables from ROM to RAM
      • initialize uninitialized data
      • allocate space for stack and initialize it
      • initializes the processor stack pointer
      • create and initialize the heap
      • enable interrupts
      • call main
      • startup is written by the developer as assembly or c, then compiled and linked with the application
      • When the reset line is disabled (once the processor start working), the program counter points to the start up
      • "Start up" can be called "boot loader", usually it is called a boot loader if it comes more complicated than just doing the above points.
        A "boot loader" can load OS, initialize HW, ...etc.
        If a boorloader is interupted "by a push button, or an escape method, ...etc", it stops loading the main program, and wait for a new main program to be flashed ...etc.
    • app.o:
      • all text, bss, data, rodata sections of all the input object files are merged together, hence:
        • symbol table contains zero unresolved symbols
        • bss contains all uninitialized variables
        • data contains all initialized variables
        • rodata contains all constants
        • text contains all code
      • In case of embedded systems: 
        • the addresses needs to be mapped to the system memory
        • this is done using a "linker script" in the "locating" process
  • Locator:
    • app.o + linker script --> targetFile
    • To be continued



You can use the files in the this link, a long with the following commands to see the above info in action:
// to run preprocessor-compiler-linker-locator, saving all temp file
gcc main.c add.c -o adder -save-temps
// you can view the preprocessor output
*.i
// you can view the assembly
*.s
// to view the object files, and target file:
objdump -d -t -s adder > adderObjectDump
objdump -d -t -s main.o > mainObjectDump
objdump -d -t -s add.o > addObjectDump

    where:  -d // display the executable sections in assembly form (disassemble)
                 -t // print symbol table
                 -s // display the contents of the sections

No comments:

Post a Comment