Correct way to initialise C library in newlib nano build?

Asked by S. Mäki-Mantila on 2017-09-08

I'm having trouble setting up newlib nano build for STM32F409 Cortex-M4 to call C library initialisations.

I used minimum.c as base edited linker script nokeep.ld:

MEMORY
{
  FLASH (rx) : ORIGIN = 0x00000000, LENGTH = 0x20000 /* 128K */
  RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 0x10000 /* 64K */
}

With this minimum example compiles and I can run it.

Now if I try to modify example to call library initialisations. I suspect that call to _start should do that? In original example (startup_ARMCM4.S) __START is defined to main. I tried minimum example without __START defined and added call to main:

#ifndef __START
#define __START _start
#endif
 bl __START

 bl main

Now what happens is that CPU gets to signal handler HardFault or UsageFault when running _start function.

   0x0000007c <+56>: cmp r0, #0
   0x0000007e <+58>: beq.n 0x86 <_start+66>
   0x00000080 <+60>: ldr r0, [pc, #48] ; (0xb4 <_start+112>)
   0x00000082 <+62>: nop.w
   0x00000086 <+66>: bl 0x154 <__libc_init_array>
   0x0000008a <+70>: movs r0, r4
   0x0000008c <+72>: movs r1, r5
   0x0000008e <+74>: bl 0xc4 <main>

I can run code to *0x86 and somewhere in __libc_init_array it will get signal handler called. I can't get to breakpoint in *0x8a:

Program received signal SIGINT, Interrupt.
UsageFault_Handler () at startup_ARMCM4.S:237
237 b .
(gdb) bt
#0 UsageFault_Handler () at startup_ARMCM4.S:237
#1 <signal handler called>
#2 0x000001bc in ?? ()
#3 0x0000016c in __libc_init_array ()
#4 0x20000060 in impure_data ()
Backtrace stopped: previous frame identical to this frame (corrupt stack?)

Should I even call _start? I can call __libc_init_array instead of _start directly but it wont call any constructors, should it?

This won't get called:
__attribute__((constructor))
void init_test_var(void) {
 test_var = 0x10;
}

To summarize. How should one call C library init on newlib nano build? And should __libc_init_array handle all constructors?

Question information

Language:
English Edit question
Status:
Open
For:
GNU ARM Embedded Toolchain Edit question
Assignee:
No assignee Edit question
Last query:
2017-09-08
Last reply:
S. Mäki-Mantila (smantila) said : #1

There might be bug or something fishy happening in the linker state.

I have tracked the problem to _init function that gets called from: _start -> __libc_init_array -> _init. And the issue seems to come from '-Wl,--gc-sections' that is used in linker stage.

Minimum sample code and others too use GC=-Wl,--gc-sections flag for linker but if this is not used code is generated correctly and version works correctly (without -Wl,--gc-sections):
00000210 <_init>:
 210: b5f8 push {r3, r4, r5, r6, r7, lr}
 212: bf00 nop
 214: bcf8 pop {r3, r4, r5, r6, r7}
 216: bc08 pop {r3}
 218: 469e mov lr, r3
 21a: 4770 bx lr

Now if one compiles with the flag 'GC=-Wl,--gc-sections' for linker it will crash. As these functions seem to be linked wrong and
CPU will execute straight over to 0x194 and crash:

0000018c <_init>:
 18c: b5f8 push {r3, r4, r5, r6, r7, lr}
 18e: bf00 nop

00000190 <_fini>:
 190: b5f8 push {r3, r4, r5, r6, r7, lr}
 192: bf00 nop

00000194 <_global_impure_ptr>:
 194: 0000 2000

I tested this with the latest 6-2017-q2-update and also (gcc 5.4.1) 5-2016-q3-update. Both seem to work the same.

Can you help with this problem?

Provide an answer of your own, or ask S. Mäki-Mantila for more information if necessary.

To post a message you must log in.