Link Search Menu Expand Document

Debugging panics

The Pintos source code contains many ASSERT (condition) statements. When the condition of an assert statement evaluates to false, the kernel will panic and print out some debugging information.

You will usually get a line of output that looks like this:

Call stack: 0xc0106eff 0xc01102fb 0xc010dc22 0xc010cf67 0xc0102319
0xc010325a 0x804812c 0x8048a96 0x8048ac8.

This is a list of instruction addresses, each of which corresponds to a frame on the kernel stack when the panic occurred. You can decode this information into a helpful stack trace by using the backtrace utility that is included in your VM:

cd ~/code/personal/proj-pregame/src/threads/build/
backtrace kernel.o 0xc0106eff 0xc01102fb 0xc010dc22 0xc010cf67 0xc0102319 ...

If you run your tests using make check, the testing framework will run backtrace automatically when it detects a kernel panic.

To debug a kernel panic with GDB, you can usually just set a breakpoint at the inner-most line of code inside the stack trace. However, if your kernel panic occurs inside a function that is called many times, you may need to type continue a bunch of times before you reach the point in the test where the kernel panic occurs.

One trick you can use to improve this technique is to transform the code itself. For example, if you have an assert statement that looks like:

ASSERT (is_thread (next));

You can transform it into this:

if (!is_thread(next)) {
  barrier(); // Set a breakpoint HERE!
ASSERT (is_thread (next));

Then, set a breakpoint at the line containing barrier(). You can use any line of code instead of barrier(), but you must ensure that the compiler cannot reorder or eliminate that line of code. For example, if you created a dummy variable int hello = 1; instead of using barrier(), the compiler could decide that line of code wasn’t needed and omit instructions for it! If you get a compile error while using barrier(), make sure you’ve included the synch.h header file.

You can also use GDB’s conditional breakpoints, but if the assertion makes use of C macros, GDB might not understand what you mean.