cancel
Showing results for 
Search instead for 
Did you mean: 

The mysterious __libc_init_array() in Cube IDE - is it only for C++ ??

PHolt.1
Senior III

Supposedly this is only used by C++ but see various threads e.g.

https://www.eevblog.com/forum/microcontrollers/a-question-on-gcc-ld-linker-script-syntax/msg4754165/#msg4754165

https://www.eevblog.com/forum/microcontrollers/how-do-i-enable-link-section-overlap/msg3715957/#msg3715957

https://www.eevblog.com/forum/microcontrollers/mcu-programming-101-writeup/msg5402906/#msg5402906

https://www.eevblog.com/forum/microcontrollers/is-st-cube-ide-a-piece-of-buggy-***/msg5403485/#msg5403485

If you google it, you find a disturbing number of suggestions (nothing concrete!) that in the STM environment, Cube IDE, this function is not only for C++ constructors etc but is also used to initialise some statics in libc.a functions. One suggestion was that malloc() does not work without it. ST does not distribute sources to libc.a although some people on eevblog located probable sources for newlib (dated 1990, IIRC). Much of libc.a is also not re-entrant and needs to be mutexed in any RTOS environment.

Does anyone know the real answer?

21 REPLIES 21
Pavel A.
Evangelist III

This is a feature of GCC runtime library and linker.  Yes, these things can be used to implement C++ constructors and destructors of static objects and also to initialize local data in dynamic libraries. More details in the GCC documentation (for any architecture, not specific to ARM).

 Much of libc.a is also not re-entrant and needs to be mutexed in any RTOS environment.

This was heavily discussed in this forum (before migration). The real answer is that CubeMX/IDE provide a software component for RTOS-aware locks in newlib. Whether to use that or not, and validation, is up to developer.

Apointer to the exact location would be helpfull. Thanks.

PHolt.1
Senior III

"Yes, these things can be used to implement C++ constructors and destructors of static objects and also to initialize local data in dynamic libraries"

OK, same imprecise answer as all over google 😁

So is it C++ only, or not?

Disassembling libc.a should yield the answer. Of course there are 66 (literally; just counted them) different versions of libc.a supplied with Cube IDE, according to the processor. No src for any of them. I am using a 32F417.

I have just stepped through the code (has to be done with Cube switched to displaying assembler) and there is very little code being run. There is a loop which is taken ~3 times.

PHolt.1
Senior III

The code from 306: to 31e: is executed twice. So it is not doing "nothing". My project has no C++ in it.

The whole thing is weird with 1.15.0. The STLINK V3 debugger fails as posted in the EEVBLOG thread. And when that fails, ST Utility, while programming the chip OK, also fails to deliver a running target, suggesting that code generated by 1.15.0 is faulty in some way. But when I reinstall 1.14.1 everything immediately works, including the ST Utility loading working code. And obviously without a working debugger there is no way to track down the problem.

 

I believe the answer is in newlib's sources (and for motivation we should interview is authors). There's probably no ST involvement there.

> The whole thing is weird with 1.15.0. The STLINK V3 debugger fails

How is this __libc_init_array- related?

JW

PHolt.1
Senior III

Yeah but which sources 😁

The debugger issue is unrelated, sorry - for another thread. But it does mean that with Cube IDE v1.15.0 I can't step through any code.

Pavel A.
Evangelist III

So is it C++ only, or not?

Not for C++ only. It can be used in plain C, with compatible compilers that understand  __attribute__((constructor)) and __attribute__((destructor)) .  Example:

https://www.geeksforgeeks.org/__attribute__constructor-__attribute__destructor-syntaxes-c/

 

PHolt.1
Senior III

From above URL:

Write two functions in C using GCC compiler, one of which executes before main function and other executes after the main function.

Why is this needed (in C)? If you want to run some code before main() you just insert it in the startup.s code which calls main() at the end. Actually startup.s, in asm in Cube IDE/MX, could be done wholly in C too, AFAICT.

And if you want a function to run after main() then, ahem, you just call it after main(). I must be missing something totally obvious.

you just insert it in the startup.s code which calls main() at the end. 

Yes, and this is exactly what you've seen in the startup code: it calls array of __attribute__((constructor)) functions, automagically collected by the linker. Yes, in the newer ARM CMSIS releases the startup modules are in C. But ST has not updated to this version yet. Perhaps only to the better.