I decided to move local user-type objects to a global scope, which means before an application hits main function, global objects must be initialized. No problem with KEIL, but IAR did not do it.
This is quote from EWARM Development Guide (IAR) [3] which is quite comprehensive manual to understand many options it offers through command line options. But it does not provide details which might be handy.
When using the IAR C/C++ compiler and the standard library, C++ dynamic
initialization is handled automatically.
I though all right, how to track it down and see if dynamic allocation is really executed. Let's check map file of my application:
INIT TABLE Address Size ------- ---- Zero (__iar_zero_init3) 1 destination range, total size 0x2a7: 0x1ffff420 0x2a7 Extra (__iar_cstart_call_ctors)
And here's ENTRY LIST of our interest:
__call_ctors 0x00004775 0x18 Code Gb cppinit.o [4] __iar_cstart_call_ctors 0x00004ae5 0x20 Code Gb cmain_call_ctors.o [7]
A problem is, they are not invoked, startup function just takes care regular things (copying initialized data from ROM to RAM, .bss data, vector table). There's nothing with dynamic initialization. I placed breakpoint inside __call_ctors and it surprisingly was not reached. How to invoke __call_ctors function? What's it declaration? Exactly this details is not in any documentation provided in IAR doc folder (at least I was not able to find it there). Only one link on google was relevant, let's test it.
extern void * __iar_cstart_call_ctors(void *ptr);
No linker errors, correct declaration. Only one parameter, what it should be? The linker created following sections which are the one we are looking for (more info find in section C++ DYNAMIC INITIALIZATION [3] :
.init_array$$Base 0x00004d58 -- Gb - Linker created - .init_array$$Limit 0x00004d5c -- Gb - Linker created -
SHT$$INIT_ARRAY$$Base 0x00004d58 -- Gb - Linker created - SHT$$INIT_ARRAY$$Limit 0x00004d5c -- Gb - Linker created - SHT$$PREINIT_ARRAY$$Base 0x00004d58 -- Gb - Linker created - SHT$$PREINIT_ARRAY$$Limit 0x00004d58 -- Gb - Linker created -
Each section (INIT_ARRAY, PRE_INIT_ARRAY) contain array of pointers to initialization functions. [2] Let's invoke it in the end of an application's startup with a following line:
void *cpp_init = __section_begin(".init_array");
__iar_cstart_call_ctors(cpp_init);
That calls __call_ctors which initializes all global dynamic objects. Thus application works. An unanswered question is why it was not invoked automatically? I hope I'll come with an answer soon :)
References:
[1] cmain.s [http://code.google.com/p/sdp-firmwares]
[2] System V Application Binary Interface [sco.com/developers/gabi]
[3] EWARM Development Guide - IAR installation folder/arm/doc or online