[Bug 1768125] Re: libnewlib-arm-none-eabi generates wrong code for cortex-m0

mrvanes bugs at mrvanes.com
Mon Apr 30 20:36:47 UTC 2018


** Package changed: chkconfig (Ubuntu) => newlib (Ubuntu)

-- 
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:
  New

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