northsideknight
northsideknight

Reputation: 1557

Debugging qemu-arm SIGSEGV

Background

I am running the qemu-arm user space emulator inside of a Docker container on Docker for Mac.

I am working on a code base that runs on cortex-m4 processors. I want to be able to cross-compile the code in the docker container to target the cortex-m4 processor and run that code on the qemu-arm user space emulator.

to test this, I have a simple C program (/tmp/program.c):

int main() {
    return 0;
}

I use the debian:stable docker image as a base.

I compile the program with the GNU arm toolchain like so:

arm-none-eabi-gcc -mcpu=cortex-m4 --specs=nosys.specs /tmp/program.c

Then I attempt to run this with qemu-arm in the docker container:

qemu-arm -cpu cortex-m4 -strace ./a.out

But I get the following error:

--- SIGSEGV {si_signo=SIGSEGV, si_code=1, si_addr=0x0007fff0} ---
qemu: uncaught target signal 11 (Segmentation fault) - core dumped
Segmentation fault

From what I understand, SIGSEGV occurs in a few scenarios, the only one that makes sense here is that I am accessing memory that I don't have access to when I attempt to run the binary in the qemu-arm user space.

It would seem that the si_addr=0x0007fff0 is the address that I am accessing that I am not supposed to.

Since my program does very little, I am assuming this inaccessible address might be where qemu-arm is attempting to store the binary to run? But I don't see an option in qemu-arm to specify this.

Questions

So my questions are:

More information

Docker version 20.10.6, build 370c289

Dockerfile to reproduce:

FROM debian:stable

RUN apt-get update
RUN apt-get install -y gcc-arm-none-eabi qemu-user gcc

RUN echo 'int main() {return 0;}' > /tmp/program.c

# running the program on the docker container exits successfully
RUN gcc /tmp/program.c
RUN ./a.out

# running the program in `qemu-arm` errors
RUN arm-none-eabi-gcc -mcpu=cortex-m4 --specs=nosys.specs /tmp/program.c
RUN qemu-arm -cpu cortex-m4 -strace ./a.out

Upvotes: 0

Views: 1078

Answers (1)

Peter Maydell
Peter Maydell

Reputation: 11383

qemu-arm is an emulator for Linux user-space binaries. The program you're compiling seems to be built with a bare-metal toolchain. It's not impossible to compile a bare-metal binary in such a way that it will run as a Linux user-space program as well, but you have to take specific steps to make it work that way.

You should probably think about whether what you really wanted was:

  • build a Linux binary targeting Cortex-M4, and run it on qemu-arm
  • build a bare-metal binary, and run it on qemu-system-arm
  • something else

For example, how are you expecting your program to produce output? Is the program going to want to talk directly to (emulated) hardware like a serial port, or to other devices? Does the program need to run interrupt handlers?

The best way to debug what's happening is to get QEMU to start its gdbstub, and connect an arm-aware gdb to it. Then you can single step through. (This will probably be a confusing introduction to your toolchain's C runtime startup code...)

Upvotes: 1

Related Questions