Static variable initialisation

Asked by Paul Manners

Hi,

I'm trying to set up a custom bootloader to run on one of the STM3210x processors. I am experiencing hardfaults during startup and it's while it's trying to initialise a static variable, specifically in the aeabi_atexit -> _cxa_atexit -> _register_exitproc methods which from what I can work out is registering the destructor method for this static variable.

There is a obviously a gap in my knowledge about how this is supposed to work and also what I should be expecting and I have not been able to find much useful information about this online.

I am using gcc-arm-none-eabi-4_8-2013q4 release on Saucy. My main application uses methods defined in a library. The static variable is defined in this library. The initialisation of other variables appears to work fine but not for this variable. I am wondering if this is due to an incorrect linker script? The important parts of my linker script look like this:

ENTRY(reset_handler)

MEMORY
{
  UNPLACED_SECTIONS : ORIGIN = 0x100000000, LENGTH = 0
  SRAM : ORIGIN = 0x20000000, LENGTH = 0x00008000
  FLASH : ORIGIN = 0x08000000, LENGTH = 0x00002e00
}

/* Include the HAL definitions - CORTEX-M3 and STM32 registers */
INCLUDE Hal.ld
INCLUDE Extra.ld

__STACKSIZE__ = 3096;

SECTIONS
{

/***************************************************************************************************************
* FLASH SECTION
***************************************************************************************************************/

  . = 0x08000000;
  __vectors_start__ = .;
  .vectors ALIGN(4) : {
    KEEP(*(.vectors .vectors.*))
  }
  __vectors_end__ = __vectors_start__ + SIZEOF(.vectors);

  /* .init => Process initialisation code (code that gets run before main) */
  .init ALIGN(4) : {
    __init_start__ = .;
    *(.init .init.*)
  }
  __init_end__ = __init_start__ + SIZEOF(.init);

  /* .fini => Process termination code (when the program exits normally, the system will execute this code) */
  .fini ALIGN(4) : {
    __fini_start__ = .;
    KEEP(*(.fini))
  }
  __fini_end__ = __fini_start__ + SIZEOF(.fini);

  /* .eh_frame => Exception handling code that helps with stack unwinding */
  /* TODO = STRIP LATER? */
  .eh_frame ALIGN(4) : {
    *(.eh_frame)
  }

  /* .ARM.exidx => Used for exception handing */
  /* TODO = STRIP LATER? */
  .ARM.exidx ALIGN(4) : {
    __exidx_start = .;
 *(.ARM.exidx)
    *(.ARM.exidx*)
  }
  __exidx_end = __exidx_start + SIZEOF(.ARM.exidx);

  /* .text => Holds the program */
  .text ALIGN(4) : {
    __text_load_start__ = .;
    __text_start__ = .;
    *(.text)
    *(.text*)
  }
  __text_end__ = __text_start__ + SIZEOF(.text);
  __etext = __text_end__;

  /* .dtors => Contains a list of global destructor pointers */
  .dtors ALIGN(4) : {
    __dtors_load_start__ = .;
    __dtors_start__ = .;
    KEEP(*(.fini_array*))
    KEEP (*(SORT(.dtors.*)))
    KEEP (*(.dtors))
  }
  __dtors_end__ = __dtors_start__ + SIZEOF(.dtors);

  /* .ctors => Contains a list of global constructor pointers */
  .ctors ALIGN(4) : {
    __ctors_load_start__ = .;
    __ctors_start__ = .;
    KEEP(*(.init_array*))
    KEEP (*(SORT(.ctors.*)))
    KEEP (*(.ctors))
  }
  __ctors_end__ = __ctors_start__ + SIZEOF(.ctors);

  /* .rodata => read-only data */
  .rodata ALIGN(4) : {
    __rodata_load_start__ = .;
    __rodata_start__ = .;
    *(.rodata)
    *(.rodata*)
  }
  __rodata_end__ = __rodata_start__ + SIZEOF(.rodata);

  /* .jcr => Contains information necessary for registering compiled Java classes */
  .jcr ALIGN(4) : {
    *(.jcr)
  }

  /* .glue = ARM glue code */
  .linker_stubs ALIGN(4) : {
    *(.glue_7*)
    *(.rel*)
    *(.vfp11_veneer)
    *(.v4_bx)
    *(.iplt)
    *(.igot*)
  }

  /DISCARD/ : {
    *(.ARM.attributes)
  }

/***************************************************************************************************************
* RAM SECTION
***************************************************************************************************************/

  . = 0x20000000;

  /* We create our vector table in RAM after initialization */
  .vectors_ram ALIGN(4) (NOLOAD) : {
    __vectors_ram_start__ = .;
    KEEP(*.vectors_ram)
    . = MAX(__vectors_ram_start__ + 0x130 , .);
  }
  __vectors_ram_end__ = __vectors_ram_start__ + SIZEOF(.vectors_ram);

  . = 0x20000144;
  .bss ALIGN(4) (NOLOAD) : {
    __bss_start__ = .;
    *(.bss)
    *(.bss*)
  }
  __bss_end__ = __bss_start__ + SIZEOF(.bss);

  /* .data => Initalised data that contributes to the */
  .data ALIGN(4) (NOLOAD) : {
    __data_load_start__ = .;
    __data_start__ = .;
    *(.data .data.* .gnu.linkonce.d.*)
  }
  __data_end__ = __data_start__ + SIZEOF(.data);

  .stack ALIGN(4) (NOLOAD) : {
    __stack_start__ = .;
    *(.stack)
    . = ALIGN(MAX(__stack_start__ + __STACKSIZE__ , .), 4);
  }
  __stack_end__ = __stack_start__ + SIZEOF(.stack);

  .heap ALIGN(4) (NOLOAD) : {
    __heap_start__ = .;
    *(.heap)
  }
  __heap_end__ = __heap_start__ + SIZEOF(.heap);

}

Any suggestions into working out what is going on would be greatly appreciated.

Thanks
Paul

Question information

Language:
English Edit question
Status:
Solved
For:
GNU Arm Embedded Toolchain Edit question
Assignee:
No assignee Edit question
Solved by:
Paul Manners
Solved:
Last query:
Last reply:
Revision history for this message
Joey Ye (jinyun-ye) said :
#1

Paul,

Since the complete project is not posted I can only guess what happened. Things look suspicious to me is that you are putting
 KEEP(*(.fini_array*)) KEEP(*(.init_array*)) in FLASH, which should be in RAM instead.

Also, if you would try --specs=nano.specs, it will skip global distructors, which might work around your issue.

Thanks,
Joey

Revision history for this message
Paul Manners (paulmanners) said :
#2

Hi Joey

So you're proposing that I put this in my RAM section?

  .init_array ALIGN(4) : {
    KEEP(*(.init_array*))
  }

  .fini_array ALIGN(4) : {
    KEEP(*(.fini_array*))
  }

I see I am not exporting these two sections when I create my ELF image. I presume that I should be? What I'm also seeing a reference to impure_data on the line of the disassembled assembler code where it is hard faulting. What is this "impure_data" and should it even been there?

I will give the nano.specs a try.

Thanks
Paul

Revision history for this message
Paul Manners (paulmanners) said :
#3

Ahah, the nano.specs works!

Would still like to know why it isn't working with the destructors... but maybe another day. :-)