[Bug 1768125] Re: libnewlib-arm-none-eabi generates wrong code for cortex-m0
Dylan Owens
1768125 at bugs.launchpad.net
Wed Jun 13 01:38:13 UTC 2018
First bug comment, forgive any faux pas.
I also had working Cortex M0 code that broke upon upgrade to 18.04.
Compilation failed with an error message about crt0.o, manually
symlinking as described in link below seemed to resolve it. Apparently
gcc changed its library directory structure, which was not reflected in
newlib.
https://bugs.launchpad.net/gcc-arm-embedded/+bug/1772332
https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=899264
Once compilation worked, programs that made calls to memset would hang
at runtime, as reported above.
** Bug watch added: Debian Bug tracker #899264
https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=899264
--
You received this bug notification because you are a member of Ubuntu
Foundations Bugs, which is subscribed to newlib in Ubuntu.
https://bugs.launchpad.net/bugs/1768125
Title:
libnewlib-arm-none-eabi generates wrong code for cortex-m0
Status in newlib package in Ubuntu:
Confirmed
Bug description:
Since my upgrade to 18.04 last weekend I can't compile a working
firmware for my stm32f0xx based drone flight controller. The mcu halts
at HardFault_Handler and it turns out the generated code for memset is
faulty.
I've managed to narrow the problem down to the following code:
int main(void)
{
int test[4] = { 0, 0, 0, 0 };
while (1);
}
void HardFault_Handler(void)
{
while(1);
}
In which HardFault_Handler(void) was add to prove the HardFault occuring at the array initialisation.
The file is compiled using the following commandline:
arm-none-eabi-gcc -mcpu=cortex-m0 -g -mthumb -fdata-sections
-ffunction-sections -nostartfiles -ffreestanding --specs=nano.specs
--specs=nosys.specs -Wl,-T,flash.ld,-Map,output.map,--gc-sections
-std=gnu99 main.c <includes> -o memset.elf
And uses STM32F0xx_StdPeriph_Driver includes and
CMSIS/Device/ST/STM32F0xx based startfile.
The resulting elf binary is then coverted to a binary using arm-none-
eabi-objcopy -O binary memset.elf memset
output.map mentions memset as:
/usr/lib/gcc/arm-none-eabi/6.3.1/../../../arm-none-eabi/lib/libc_nano.a(lib_a-memset.o)
So I suspect the memset nano libc version is used.
arm-none-eabi-objdump -d memset.elf produces the following code for
main:
080001b8 <main>:
80001b8: b580 push {r7, lr}
80001ba: b084 sub sp, #16
80001bc: af00 add r7, sp, #0
80001be: 003b movs r3, r7
80001c0: 0018 movs r0, r3
80001c2: 2310 movs r3, #16
80001c4: 001a movs r2, r3
80001c6: 2100 movs r1, #0
80001c8: f7ff ff7c bl 80000c4 <memset>
80001cc: e7fe b.n 80001cc <main+0x14>
And memset starts like this:
080000c4 <memset>:
80000c4: e3100003 tst r0, #3
80000c8: e92d4010 push {r4, lr}
80000cc: 0a000037 beq 80001b0 <memset+0xec>
80000d0: e3520000 cmp r2, #0
80000d4: e2422001 sub r2, r2, #1
80000d8: 0a000032 beq 80001a8 <memset+0xe4>
80000dc: e201c0ff and ip, r1, #255 ; 0xff
80000e0: e1a03000 mov r3, r0
...
When I step through the assembly, after arriving at 0x080000c4, the
debugger however shows this assembly:
0x80000c4 <memset> movs r3, r0
0x80000c6 <memset+2> b.n 0x80006ea
0x80000c8 <memset+4> ands r0, r2
0x80000ca <memset+6> stmdb sp!, {r0, r1, r2, r4, r5}
0x80000ce <memset+10> lsrs r0, r0, #8
0x80000d0 <memset+12> movs r0, r0
0x80000d2 <memset+14> b.n 0x800077a
...
This doesn't look like the disassembled code at all, and
0x80006ea contains no valid code:
0x80006ea ; <UNDEFINED> instruction: 0xffffffff
0x80006ee ; <UNDEFINED> instruction: 0xffffffff
0x80006f2 ; <UNDEFINED> instruction: 0xffffffff
0x80006f6 ; <UNDEFINED> instruction: 0xffffffff
0x80006fa ; <UNDEFINED> instruction: 0xffffffff
0x80006fe ; <UNDEFINED> instruction: 0xffffffff
Thus reliably results in the HardFault_Handler()
I'm in no way an experienced cortex developer/debugger. The above
observations are what I managed to research last days since not being
able to compile the firmware anymore.
I noticed that the above dump of memset function from the .elf file
looks to contain valid asm (starts with tst, push and then a beq to a
valid address), but the instructions + operands are all 32bits, where
as the code in main is just 16 bits for each instruction + operand.
That smells fishy to my unexperienced eyes?
This is as far as I understand the arm toolchain and had to give up.
To manage notifications about this bug go to:
https://bugs.launchpad.net/ubuntu/+source/newlib/+bug/1768125/+subscriptions
More information about the foundations-bugs
mailing list