Debugging QEMU
In Hello eppOS I got a basic Hello World
going
with stdout via UART. This allows us to print messages and have them
appear in the console in much the same as a normal program. Now we should add debugging
capabilities to the mix as well.
GDB and QEMU
The command we haved used so far to launch QEMU has been qemu-system-arm -M lm3s811evb -s -kernel build/eppos
.
This simply starts the emulator and immediately starts running the code. This is less than ideal when we want
to debug our code since we might miss what we actually want to look at. So when debugging we should
use the following command instead: qemu-system-arm -M lm3s811evb -s -S -kernel build/eppos
. Notice the extra
-S
(capital S
), which will freeze the MCU at startup. This allows us to attach a debugger before any code is being run.
The option -s
(lowercase s
) tells QEMU to allow gdb connections on TCP port 1234. So these two options together is
all we need to start debugging.
First connection
For this you will need two terminals available. Start the emulator with the command qemu-system-arm -M lm3s811evb -s -S -kernel build/eppos
in the first terminal. After this, use the second terminal and run the command arm-none-eabi-gdb build/eppos
. This
will open a GDB shell. Now to connect to the emulator enter the following command in the GDB shell: target remote localhost:1234
.
You should now be connected to the program running inside QEMU.
The program can be controlled and inspected as usual via the GDB terminal.
VSCode integration
Now being able to use the GDB terminal for debugging is nice and all, but I like to debug using a GUI. And since
I chose VSCode as an “IDE” for eppOS, we should integrate with this. The only thing we have to do to integrate
with VSCode is to add a launch configuration to the project-local .vscode/launch.json
.
My entire launch.json
file looks like this
{
"version": "0.2.0",
"configurations": [
{
"name": "C++ Launch",
"type": "cppdbg",
"request": "launch",
"program": "${workspaceRoot}/build/eppos",
"miDebuggerServerAddress": "localhost:1234",
"args": [],
"stopAtEntry": false,
"cwd": "${workspaceRoot}",
"environment": [],
"externalConsole": true,
"launchCompleteCommand": "exec-run",
"windows": {
"MIMode": "gdb",
"miDebuggerPath": "C:\\Program Files (x86)\\GNU Tools ARM Embedded\\8 2018-q4-major\\bin\\arm-none-eabi-gdb.exe"
}
}
]
}
The important configurations is "miDebuggerServerAddress": "localhost:1234"
and
"windows": {
"MIMode": "gdb",
"miDebuggerPath": "C:\\Program Files (x86)\\GNU Tools ARM Embedded\\8 2018-q4-major\\bin\\arm-none-eabi-gdb.exe"
}
If you are using Linux you will obviously have to change "windows"
to "linux"
and change the "miDebuggerPath"
value
and so on.
With this simple launch configuration we can again launch QEMU for debugging, but instead of running GDB in a terminal simply start debugging in VSCode. Pretty nifty!
Note thought that we are compiling with -Os
(set in the toolchain file) which means
optimize for size, so even though we have debug symbols available and everything, you might get some weird
debug results, like lines being skipped etc.