-
Notifications
You must be signed in to change notification settings - Fork 77
Debugging with Qemu GDB
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.
If you want to debug your own operating system using Qemu + GDB, follow the following steps.
- 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
.
-
Run gdb:
gdb -x gdbscript.gdb
-
Debug using gdb commands.
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 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
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