Skip to content

Debugging Baremetal Applications Using QEMU

Yuriy Kolerov edited this page Jun 17, 2023 · 14 revisions

Building QEMU

Install all necessary prerequisites which are necessary for building QEMU: https://wiki.qemu.org/Hosts/Linux. Then prepare sources and a build directory:

git clone https://github.com/foss-for-synopsys-dwc-arc-processors/qemu
mkdir -p qemu/build
cd qemu/build

Configure QEMU (use your own --prefix value):

../configure --target-list=arc-softmmu,arc64-softmmu,arc-linux-user,arc64-linux-user \
             --enable-debug --enable-debug-tcg --prefix=/tools/qemu

Build an install:

make
make install

Configure your environment:

export QEMU_HOME="/tools/qemu"
export PATH="${QEMU_HOME}/bin:$PATH"

Building and Debugging Applications

CPU family Toolchain QEMU binary ARC-specific QEMU options
ARC HS3x/HS4x arc-elf32-gcc qemu-system-arc -M arc-sim -cpu archs
ARC HS5x arc64-elf-gcc qemu-system-arc -M arc-sim -cpu hs5x
ARC HS6x arc64-elf-gcc qemu-system-arc64 -M arc-sim -cpu hs6x

Building and Running "Hello, World!"

Consider a simple example code (save it as main.c):

#include <stdio.h>

int main()
{
    printf("Hello, World!\n");
    return 0;
}

You need to use -specs=qemu.specs to use input/output features and pass -serial stdio to link a virtual character device with host's stdio:

$ arc-elf32-gcc -mcpu=archs -specs=qemu.specs main.c -o main.elf
$ qemu-system-arc -M arc-sim -cpu archs -monitor none -display none -nographic \
                  -no-reboot -serial stdio -kernel main.elf
Hello, World!

By default, QEMU creates a character device for arc-sim board on hard coded 0x90000000 address. A program built with -specs=qemu.specs uses this address for all input/output operations. However, if -semihosting option is passed to QEMU, then it uses the same input/output interface as nSIM with -on nsim_emt option. It allows to use the same binary for running both on QEMU and nSIM:

$ arc-elf32-gcc -mcpu=archs -specs=nsim.specs main.c -o main.elf
$ qemu-system-arc -M arc-sim -cpu archs -monitor none -display none -nographic \
                  -no-reboot -serial stdio -semihosting -kernel main.elf
Hello, World!

Building and Running "Hello, World!" Using MetaWare Development Toolkit

MetaWare’s standard runtime library does not support input/output interfaces of QEMU for ARC. But it is possible to implement your own basic hostlink library for MetaWare to meet QEMU's requirements. You have to implement at least one function to add support of simple output:

int _write (int handle, const char *buf, unsigned int count)
{
    unsigned int i = 0;
    while (i < count)
    {
        *(char *) 0x90000000 = buf[i++];
    }
    return count;
}

It's a slightly modified _write from libqemu.a for Newlib. Save it as write.c file and compile it along with main.c:

# For ARC HS3x/HS4x
ccac -av2hs -Hhostlib= main.c write.c -o main.elf

# For ARC HS5x
ccac -av3hs -Hhostlib= main.c write.c -o main.elf

# For ARC HS6x
ccac -arc64 -Hhostlib= main.c write.c -o main.elf

Run it using QEMU:

# For ARC HS3x/HS4x
qemu-system-arc -M arc-sim -cpu archs -monitor none -display none -nographic \
                -no-reboot -serial stdio -kernel main.elf

# For ARC HS5x
qemu-system-arc -M arc-sim -cpu hs5x -monitor none -display none -nographic \
                -no-reboot -serial stdio -kernel main.elf

# For ARC HS6x
qemu-system-arc64 -M arc-sim -cpu hs6x -monitor none -display none -nographic \
                  -no-reboot -serial stdio -kernel main.elf
Clone this wiki locally