gccarmqemulibm

Function sinf from libm doesn't return on ARM QEMU machine


I'm trying to run following code on ARM machine emulated with QEMU.

#include "math.h"

// Newlib doesn't implement this function.
void _exit(int status) {
    while (1);
}

int main() {
  float a = 1.25;

  float b = sinf(a);
  return 0;
}

Used toolchain:

$ arm-none-eabi-gcc --version
arm-none-eabi-gcc (GNU Tools for ARM Embedded Processors) 4.8.3 20131129 (release) [ARM/embedded-4_8-branch revision 205641]
Copyright (C) 2013 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.

Code is compiled with:

arm-none-eabi-gcc -g -o math.elf math.c -lm

QEMU machine is started as:

$ qemu-system-arm -M realview-pbx-a9 -cpu cortex-a9 -kernel math.elf -nographic -serial /dev/null -s -S

GDB session looks like:

(gdb) target remote localhost:1234
Remote debugging using localhost:1234
0x00008104 in _start ()
(gdb) set $pc = 0x822c
(gdb) break *0x8240
Breakpoint 1 at 0x8240: file math.c, line 10.
(gdb) break *0x824c
Breakpoint 2 at 0x824c: file math.c, line 11.
(gdb) c
Continuing.

Breakpoint 1, main () at math.c:10
10    float b = sinf(a);
(gdb) c
Continuing.

Breakpoint 2 is set at the last line (return 0). As it can be seen from GDB session log the second breakpoint is never reached. Computing is just stuck inside sinf function. Any idea why?

I was experimenting with similar code written directly in ARM assembly and the result was the same.


Solution

  • SP register was not initialized. Here is a working example in ARM assembly:

            .text
    entry:  b start           
    fval:   .single 0e1.25
            .align
    
    start:  mov sp, #0x80000
            ldr r0, fval
            bl sinf 
    stop:   b stop
    

    Result is in R0 register.