Skip to content

Source Level Debug with XQEMU

Stefan Schmidt edited this page Nov 1, 2020 · 3 revisions

One method to debug your nxdk application is to run it within XQEMU, and connect using GDB, or another debugger which can communicate through the GDB remote protocol. In this example, GDB is used.

Note: this is not an introduction to XQEMU, nor GDB, just a quick-start guide.

Building with Debug Information

Let's start with a simple example and try to build a sample:

cd <path to nxdk>/samples/mesh

We need to explicitly specify that we want debug information to be included in the binary. To do this, specify DEBUG=y (or define it in your project Makefile). For example, to build with debugging symbols:

make clean
make DEBUG=y -j12

Start XQEMU

Run XQEMU as normal, but append to the command line the -s flag to enable the GDB server, and the -S flag to get XQEMU to wait for you to connect before allowing the virtual CPU to execute any code. A GDB server is now running at 127.0.0.1:1234, halted at the reset vector (CPU startup), waiting for you to connect.

Start GDB

Start gdb and run the following commands, or put them in a .gdbinit file to be run automatically whenever you start GDB in this directory:

# Tell GDB that we are using 32-bit x86 architecture
set arch i386

# Tell GDB to load symbols from main.exe
#
# Notice here that we are using the .exe file, not the .xbe file, as
# GDB does not understand the .xbe format.
#
add-symbol-file main.exe

# Use a layout which shows source code
layout src

# Connect to the XQEMU GDB server
target remote 127.0.0.1:1234

# Stop execution at the beginning of the `main` function
b main

# Let XQEMU run until the CPU tries to execute from the address
# we have placed our breakpoint(s)
c

Now XQEMU will run until the CPU begins executing the main function. Once the breakpoint is hit, or if you press Ctrl-C at any time, GDB will present an interactive shell. From here, you can:

  • Print (or modify) variables (p var),
  • Navigate stack frames (up, down),
  • Set additional breakpoints (b, e.g. at line 120 b main.c:120),
  • Step to the next line of source code (n), or
  • Allow the CPU to run normally (c) until the next breakpoint is encountered.