0

I have a C++ toolchain for the ARM chip SAMD21g18 and I have just recently implemented the __libc_init_array function, so that global C++ objects have their constructors called before main().

I am using the code shown here: https://embeddedartistry.com/blog/2019/04/17/exploring-startup-implementations-newlib-arm/

/* Handle ELF .{pre_init,init,fini}_array sections.  */
#include <sys/types.h>

#ifdef HAVE_INITFINI_ARRAY

/* These magic symbols are provided by the linker.  */
extern void (*__preinit_array_start []) (void) __attribute__((weak));
extern void (*__preinit_array_end []) (void) __attribute__((weak));
extern void (*__init_array_start []) (void) __attribute__((weak));
extern void (*__init_array_end []) (void) __attribute__((weak));

#ifdef HAVE_INIT_FINI
extern void _init (void);
#endif

/* Iterate over all the init routines.  */
void
__libc_init_array (void)
{
  size_t count;
  size_t i;

  count = __preinit_array_end - __preinit_array_start;
  for (i = 0; i < count; i++)
    __preinit_array_start[i] ();

#ifdef HAVE_INIT_FINI
  _init ();       //NOTE: I have actually removed this because I Have no init() function
#endif

  count = __init_array_end - __init_array_start;
  for (i = 0; i < count; i++)
    __init_array_start[i] ();
}
#endif

And I have added the following two sections to my linker script:

.preinit_array:
    {
    PROVIDE_HIDDEN (__preinit_array_start = .);
    KEEP (*(.preinit_array*))
    PROVIDE_HIDDEN (__preinit_array_end = .);
} > ram AT > flash
.init_array :
{
    PROVIDE_HIDDEN (__init_array_start = .);
    KEEP (*(SORT(.init_array.*)))
    KEEP (*(.init_array*))
    PROVIDE_HIDDEN (__init_array_end = .);
} > ram AT > flash

When debugging a sample project, I see in the debugger that the "count" variable before the last for loop in the function, has value 1, which means the compiler must have found one constructor. I have used arm-none-eabi-objdump to check the section, and it has indeed size 4 (meaning one pointer was added to the section).

However, when the CPU tries to jump to that constructor function, it crashes (in gdb, an exception is raised). I looked at the memory address of the pointer, with the debugger, and it was a very high address, starting at 0xEXXXXXXX, but I think it's an incorrect address becasue in my linker script I Have not those addresses assigined to any function. My linker script is basically this: https://github.com/ataradov/mcu-starter-projects/blob/master/samd21/linker/samd21j18.ld

What could be going on? Is the init() function important for this or, as I Have done, can it be commented? I don't know where that function was supposed to come from nor my toolchain was finding it.

4

0 回答 0