Skip to content

Debugging with Qemu GDB

chibicitiberiu edited this page Aug 26, 2023 · 1 revision

Nanobyte OS can be debugged using scons debug or scons debug_stage2. These commands will build the disk image, and then run the scripts from scripts/debug.sh or scripts/debug_stage2.sh. The GDB script is contained in these script files, if you wish to modify them.

General idea

If you want to debug your own operating system using Qemu + GDB, follow the following steps.

  1. Create a GDB script file (e.g. gdbscript.gdb) with the following contents:
set disassembly-flavor intel
target remote | qemu-system-i386 -S -gdb stdio -m 32 -fda your_image.img

You can use your own qemu flags, the important part is -S -gdb stdio.

  1. Run gdb: gdb -x gdbscript.gdb

  2. Debug using gdb commands.

Finding where stuff is

Until you can use debugging symbols, make sure you enable the map file generation in your linker (-Wl,-Map=path_to_map_file). The map contains some really useful information, such as the memory address of each symbol from your code (global variables, functions etc). This will make it much easier to get your bearings when debugging, know where to place breakpoints.

When debugging C/C++ code, you can also use i686-elf-objdump -D -S -m intel an_object_file.o to print the disassembly intermixed with the source code, which makes it easier to follow while debugging.

Debugging symbols

Debugging will be a lot easier if you can load debugging symbols. Instead of looking at assembly code and memory addresses, you can actually inspect variables, see the code that is being executed, and even debug directly from your IDE (or VS Code). To achieve this, you need to use an executable format that supports debugging symbols, which also means adding support for loading such files in the bootloader. I recommend using ELF.

Once you have added executable support, enable symbols in your compiler and linker flags (-g or -ggdb). The executable with symbols might grow pretty large, but you can create a stripped version of your ELF binary using i686-elf-strip that will be much smaller, and that you can put in the disk image. Then add this line at the top of the gdb script:

symbol-file path_to_unstripped_elf.elf

Common GDB commands

Note: in gdb, you can shorten any command by just typing the first 1-2 letters of the command. For example, instead of break you can do b. Instead of info registers you can do i r. A blank command means repeating the last command.

  • break *0x1234 creates a breakpoint at address 0x1234.
  • continue continue running the program
  • step step in
  • ni step over to the next (assembly) instruction
  • finish step out (not sure how well it works with assembly)
  • info registers shows CPU registers. You can also specify a specific register to show.
  • <Ctrl+X><Ctrl+A> (or use -tui gdb flag) enables text user interface, so you can see the disassembly and some other stuff

More GDB commands: https://darkdust.net/files/GDB%20Cheat%20Sheet.pdf

Clone this wiki locally