-
Notifications
You must be signed in to change notification settings - Fork 18
The edit debug cycle
When working on SnowflakeOS, how does one go about adding new bugs to it?
It's simple, really.
If you don't know where to begin, you may consider that the code "doesn't work" as you wish it did and skip to the next section.
Then, you open your favorite terminal, which is guake, naturally, and you do one of these things:
-
make strict
, if you want to take it slow and fix warnings one by one, -
make qemu
, to actually run SnowflakeOS and see how things go.
Note that before running anything, you've opened another tmux tab/terminal running tail -F serial.log
; that'll show you the realtime output of SnowflakeOS's serial, i.e. all of your prints. If you don't, you'll see the whole output anyway when exiting qemu.
No way!!
Once you've fixed every single error and warning, and your code looks like it should work, but doesn't for some reason, it's time to debug it. Here, you have a few options:
- building with
make clean; make qemu UBSAN=1
to catch null pointers and undefined behavior, complete with line numbers and stacktrace -
printk
,printke
andprintf
like a crazy person: my go-to if ubsan reveals nothing - placing breakpoints with
BREAK()
and runningmake bochs
: this gets to the bottom of the worst bugs, every time - adding a well-placed
stacktrace_print()
orwhile (1);
: helpful for looking at the page tables, memory or what have you, with either qemu or bochs - remote gdb with qemu is broken for some reason, don't lose time there
- using a tool like ripgrep or your IDE to track references: where is
BREAK
called from ?rg BREAK
.
-
q
quits the whole thing -
info mem
andinfo tlb
show paging information - qemu's fast, that's the main attraction, it's awesome for print-based debugging and a fast edit/run cycle
-
help
shows you a lot -
info tab
gets you page tables -
print-stack
does what it says, and symbols are loaded so you get the backtrace too, when the execution's in kernel -
bt
also gets you a baktrace - pressing enter executes the current instruction
- double-clicking a line sets a breakpoint on it
-
c
continues execution