Debug

This page contains information regarding the debugging process: how to get more information from the compilation system, how to change the way your kernel display debug information, etc.

Environment

If the environment is too quiet for you, turn on the verbose in your user profile as follows such that the operations related to the compilation and linking process are displayed in detail.

_OUTPUT_                        =       ${_OUTPUT_VERBOSE_}

Output

Sometimes, kaneton needs to display so much information that the 80x25 screen is not enough to contain. This often happens in critical times when you need debug information for instance.

An easy way to get more output is to forward the kaneton console output to another machine over a serial line. Although this might sound complicated for real machines, this techniques becomes very easy and efficient with emulatorss such as QEMU.

In order to activate the forward module, you will need to add the forward module by adding the following to your user profile configuration file:

_MODULES_                        +=       forward

Once your kaneton has been recompiled, you can use QEMU to redirect the data received on serial line to the standard console, as shown below:

$> qemu-system-i386 -serial stdio -fda [path-to-your-kaneton-image]

That way, QEMU will be launched as usual but every displayed text will be forwarded by kaneton to the serial line, hence displayed on the console output by QEMU.

Interrupts

Interrupts can be used for debugging as well. For instance, whenever a page fault occurs, the default page fault interrupt handler displays information on the context such as registers etc.

However, depending on the specificity of the situation, one might want to display additional debug information such as the state of the page directory and page tables involved in the error.

Students should make the best of the interrupt handlers in order to speed up the debugging process.

The glue component sets up a default page fault handler which can be modified for example.

QEMU

Basic usage

Qemu implements gdb stubs to debug the software it runs.

$> qemu-system-i386 -fda kaneton.img -s -S
  • -s : shortcut option (for -gdb tcp::1234) to make qemu's gdbserver wait for a connection on port 1234 of the local machine.
  • -S : freeze the CPU at startup so that it can be started from the debugger (or by typing c on qemu's console).

Advanced debugging

When facing tough kernel crashes, it is possible to ask qemu to log in /tmp/qemu.log details about the kernel execution on the emulated machine. -d item{,item}* option turns on the logging of the given items. Use -d ? to list every logging options of qemu. The most useful are :

  • in_asm : log every block of your kernel assembly code being executed by qemu.
  • cpu : log the CPU state (i.e. the CPU registers) after the execution of each kernel code block.
  • int : log interrupts/exceptions in short format.
$> qemu-system-i386 -fda kaneton.img -s -S -d in_asm,cpu

Note that the file grows fastly (several MB/s).

Single step mode

Having logs for each executed block of assembly code can be not granular enough to understand a kernel crash. Turn on the single stepping mode (option -singlestep) to make qemu execute your kernel instruction per instruction. So that you obtain the logs for each single instruction. E.g.: to log the registers for each instruction executed, use:

$> qemu-system-i386 -fda kaneton.img -s -S -d in_asm,cpu -singlestep

KVM

It is advised to ask qemu to use linux's KVM module to make it execute most of your kernel code directly on your host machine. Therefore avoiding as much as possible qemu's emulation mistakes.

$> qemu-system-i386 -enable-kvm -fda kaneton.img -s -S

or

$> qemu-kvm -fda kaneton.img -s -S

Qemu's console

You can still get more information from the console. Type Alt-2 in graphical mode or C-q c otherwise to get the console.

Type info to get the list of informations qemu can give you. E.g.:

  • info tlb : show virtual to physical memory mappings.
  • info registers : show the cpu registers.
  • info cpus : show the list of CPUs and their current progran counter value.

Type help to get the list of commands. E.g.:

  • x : dump the memory at the given virtual address.
  • xp : dump the memory at the given physical address.

Tip

The list of possible arguments of a qemu's option is returned when providing it ? argument.

$> qemu-system-i386 -enable-kvm -fda kaneton.img -s -S -d ?
Log items (comma separated):
out_asm    show generated host assembly code for each compiled TB
in_asm     show target assembly code for each compiled TB
...

GDB

Once qemu is waiting for your gdb connection, simply launch gdb, read the symbols from the ELF file (having compiled with the debug options), connect to the target, and start debugging as usual. E.g.:

$> qemu-system-i386 -enable-kvm -fda kaneton.img -s -S &
$> gdb kaneton -tui
(gdb) target remote :1234
(gdb) b architecture_pt_map
(gdb) c

Random tips

  • Use watchpoints to watch for an expression (watch, rwatch, awatch).
  • You can give gdb a file containing a list of commands with -x option (gdb -x test).
  • Breakpoints can be conditional (break if $eax == 0x33).
  • Commands can be attached to a breakpoint (useful when scripting) :
break myfunction
command
  set myvar = myvalue
  p "Hello"
end