2

I'm trying to understand how bare metal C applications work exactly. I wrote my own startup assembly code that calls __libc_init_array, I saw it iterating over preinit_array section and calling all functions inside. As I understand gcc adds that section for some its own initialization routines that need to run before main, but then comes _init() function in the .init section.

Does gcc generate that function? Does it come from libc? Or do I have to provide one by my own? What are some good resources to learn those things?

user694733
  • 15,208
  • 2
  • 42
  • 68
Zhani Baramidze
  • 1,407
  • 1
  • 13
  • 32
  • Good resources include your platform documentation and `objdump`. – spectras Aug 28 '17 at 09:30
  • what does symbols have to do with platform? is init_() generated by gcc on one platform and not on another?:) – Zhani Baramidze Aug 28 '17 at 09:44
  • All the process is platform-specific. For instance, on AVR, the init code must include some padding to skip past the interruption vector table. And then the content itself is here to setup the environment for a C program to run: initialize fixed registers, setup a stack pointer, perhaps install some trap handlers… Again, all of that is platform specific. – spectras Aug 28 '17 at 09:46
  • yes but who generates _init? shall I write manually? gcc? is it linked from some lib? – Zhani Baramidze Aug 28 '17 at 10:24
  • 2
    The __libc_init_array is just some weird gcc-specific thing, it is not related to the processor start-up code as such. It is rather common for smaller embedded applications to not use the standard lib at all. – Lundin Aug 28 '17 at 11:35
  • if you are using libc you are probably not baremetal. but as the name implies it is part of libc, implementation specific to that c library – old_timer Aug 28 '17 at 22:37
  • I have provided minimal working examples at: https://stackoverflow.com/questions/22054578/how-to-run-a-program-without-an-operating-system/32483545#32483545 – Ciro Santilli OurBigBook.com May 07 '19 at 07:54

1 Answers1

1

what does symbols have to do with platform? is init_() generated by gcc on one platform and not on another?

Yes the startup and the epiloque routines are left to the implementation, and actually gcc does not generate it.

the libc provides those sysmbols - https://github.com/bminor/newlib/blob/e0f24404b3fcfa2c332ae14c3934546c91be3f42/newlib/libc/misc/init.c

Depending on your target hardware the initialisation may be done completely different way.

Example STM32Fxxx startup.

    .section    .text.Reset_Handler
    .weak   Reset_Handler
    .type   Reset_Handler, %function
Reset_Handler:
  ldr   sp, =_estack    /* Atollic update: set stack pointer */

/* Copy the data segment initializers from flash to SRAM */
  movs  r1, #0
  b LoopCopyDataInit

CopyDataInit:
    ldr r3, =_sidata
    ldr r3, [r3, r1]
    str r3, [r0, r1]
    adds    r1, r1, #4

LoopCopyDataInit:
    ldr r0, =_sdata
    ldr r3, =_edata
    adds    r2, r0, r1
    cmp r2, r3
    bcc CopyDataInit
    ldr r2, =_sbss
    b   LoopFillZerobss
/* Zero fill the bss segment. */
FillZerobss:
    movs    r3, #0
    str r3, [r2], #4

LoopFillZerobss:
    ldr r3, = _ebss
    cmp r2, r3
    bcc FillZerobss

/* Call the clock system intitialization function.*/
    bl  SystemInit
/* Call static constructors */
    bl __libc_init_array
/* Call the application's entry point.*/
    bl  main

As you see in this implementation two functions are called - one SystemInit for very low lever hardware initialisation and __libc_init_array

it is an internal initialisation of the newlib library (nowadays most common used in the bare metal projects)

The problem is if you decide to do not use standard libraries and you do not want to link any standard libraries. Some tookchains provide weak functions with just the return statement, some not. If you are getting linker problems just comment this call in the startup file or provide an empty function yourself

0___________
  • 60,014
  • 4
  • 34
  • 74