I just spent a while debugging an issue with ARM GCC toolchain, and I'm a bit confused by the results:
$ arm-none-eabi-gcc --version
arm-none-eabi-gcc (GNU Arm Embedded Toolchain 9-2020-q2-update) 9.3.1 20200408 (release)
Copyright (C) 2019 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
I was compiling for an STM chip using
arm-none-eabi-gcc -mthumb -mcpu=cortex-m4 -mfloat-abi=softfp -mfpu=fpv4-sp-d16
and for some reason I was getting a hard fault during the execution of __libc_init_array
. I did some digging and I saw that the fault occurred after __libc_init_array
called _init
. So, I took a look at the contents of crti.o
:
$ arm-none-eabi-gcc -mthumb -mcpu=cortex-m4 -mfloat-abi=softfp -mfpu=fpv4-sp-d16 -print-file-name=crti.o
/opt/gcc-arm/bin/../lib/gcc/arm-none-eabi/9.3.1/thumb/v7e-m+fp/softfp/crti.o
$ arm-none-eabi-objdump -xD /opt/gcc-arm/bin/../lib/gcc/arm-none-eabi/9.3.1/thumb/v7e-m+fp/softfp/crti.o
/opt/gcc-arm/bin/../lib/gcc/arm-none-eabi/9.3.1/thumb/v7e-m+fp/softfp/crti.o: file format elf32-littlearm
/opt/gcc-arm/bin/../lib/gcc/arm-none-eabi/9.3.1/thumb/v7e-m+fp/softfp/crti.o
architecture: armv7e-m, flags 0x00000010:
HAS_SYMS
start address 0x00000000
private flags = 5000000: [Version5 EABI]
Sections:
Idx Name Size VMA LMA File off Algn
0 .text 00000000 00000000 00000000 00000034 2**1
CONTENTS, ALLOC, LOAD, READONLY, CODE
1 .data 00000000 00000000 00000000 00000034 2**0
CONTENTS, ALLOC, LOAD, DATA
2 .bss 00000000 00000000 00000000 00000034 2**0
ALLOC
3 .init 00000004 00000000 00000000 00000034 2**2
CONTENTS, ALLOC, LOAD, READONLY, CODE
4 .fini 00000004 00000000 00000000 00000038 2**2
CONTENTS, ALLOC, LOAD, READONLY, CODE
5 .ARM.attributes 0000001e 00000000 00000000 0000003c 2**0
CONTENTS, READONLY
SYMBOL TABLE:
00000000 l d .text 00000000 .text
00000000 l d .data 00000000 .data
00000000 l d .bss 00000000 .bss
00000000 l d .init 00000000 .init
00000000 l d .fini 00000000 .fini
00000000 l d .ARM.attributes 00000000 .ARM.attributes
00000000 g F .init 00000000 _init
00000000 g F .fini 00000000 _fini
Disassembly of section .init:
00000000 <_init>:
0: b5f8 push {r3, r4, r5, r6, r7, lr}
2: bf00 nop
Disassembly of section .fini:
00000000 <_fini>:
0: b5f8 push {r3, r4, r5, r6, r7, lr}
2: bf00 nop
Disassembly of section .ARM.attributes:
00000000 <.ARM.attributes>:
0: 00001d41 andeq r1, r0, r1, asr #26
4: 61656100 cmnvs r5, r0, lsl #2
8: 01006962 tsteq r0, r2, ror #18
c: 00000013 andeq r0, r0, r3, lsl r0
10: 2d453705 stclcs 7, cr3, [r5, #-20] ; 0xffffffec
14: 0d06004d stceq 0, cr0, [r6, #-308] ; 0xfffffecc
18: 02094d07 andeq r4, r9, #448 ; 0x1c0
1c: Address 0x000000000000001c is out of bounds.
I was pretty dumbfounded when I saw the contents of _init
. PC is never restored, and so execution spilled over to _fini
and eventually to some FreeRTOS functions, causing the fault. To fix this, it sufficed to stop linking crti.o
and define by own _init
and _fini
functions with no bodies.
Is this a bug? I don't see any reasonable explanation for _init
and _fini
to be defined this way.
User contributions licensed under CC BY-SA 3.0