ARM Baremetal debug with QEMU and GDB

ARM Baremetal debug with QEMU and GDB

So you want to learn ARM assembly programming ? I've found this wonderful resource compiled by Vijay Kumar. It explains in a lucid style everything you need to know to get started with Embedded System programming with the GNU tools.

This post compliments those contents. Here I show you how to debug your baremetal application using GDB and QEMU.

Make your application

Okay lets get started. I assume that you have your basic application ready. For example, lets call this file main.S, a simple source file, in ASM. You would assemble this using the GNU assembler, like always, but take a note at the extra options used:

arm-none-eabi-as -o main.o main.S -ggdb  

-ggdb switch asks as to include some debuggin information in the resulting main.o file. This info will be later picked by GDB to help you debug your application. So now link your application with the ld, take our the binary content and flash it on to a dd image. Steps for doing that, is mentioned in BraveGNU website.

Run it in Qemu!

So again, you can find the instruction in the page I just mentioned, but, for debugging requirement, there is just one extra switch you need to add:

qemu-system-arm -S -M connex -drive file=flash.bin,if=pflash,format=raw  -nographic -serial /dev/null  

That is just the -S you added. It tells Qemu to pause the execution once its ready to execute the very first instruction. Now you will be dropped to a Qemu prompt, much like the GDB prompt:

QEMU 2.4.1 monitor - type 'help' for more information  

Bring in GDB

At the prompt, you should type in gdbserver. You should be seeing the output as:

~/o/arm ❯❯❯ qemu-system-arm -S -M connex -drive file=flash.bin,if=pflash,format=raw  -nographic -serial /dev/null
QEMU 2.4.1 monitor - type 'help' for more information  
(qemu) gdbserver
Waiting for gdb connection on device 'tcp::1234'  

What it says is that GDB is listening on that port of your system. Now you can launch a new terminal and connect to this port.

Load the main.o with gdb so that it can read the debugging symbols:

~/o/arm ❯❯❯ gdb main.o
GNU gdb (GDB) Fedora 7.10.1-30.fc23  
Copyright (C) 2015 Free Software Foundation, Inc.  
License GPLv3+: GNU GPL version 3 or later <>  
This is free software: you are free to change and redistribute it.  
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"  
and "show warranty" for details.  
This GDB was configured as "x86_64-redhat-linux-gnu".  
Type "show configuration" for configuration details.  
For bug reporting instructions, please see:  
Find the GDB manual and other documentation resources online at:  
For help, type "help".  
Type "apropos word" to search for commands related to "word"...  
Reading symbols from main.o...done.  

Now you can connect to the port Qemu mentioned its listening on:

(gdb) target remote localhost:1234
Remote debugging using localhost:1234  
_start () at main.S:12  
12    _start:  b entry  

There you go! Now you use all the features provided by GDB to debug whats happening!

Related Article