[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