Debugging ordinary programs is hard enough; kernel debugging is harder still. The following few paragraphs describes some common debugging tools and strategies that you may find useful.
nm | Dump symbol address, linkage types, and names. Useful for setting break points in Bochs or Qemu. | |
readelf | Dump ELF file metadata | |
objcopy | Translate object file formats | |
objdump | Dump object file metadata and disassembly | |
addr2line | Map pc to source line | |
gdb | ptype | Dump type information |
p sizeof | Type size | |
p &((Foo*)0)->x | Member offset | |
disass 0xaddr | Disassemble code | |
genassym | Export constant C expression to assembly to avoid having to maintain them in two places at once. | |
printf | Printf and primitive CGA console driver for the x86; includes "long long" arithmetic support. |
0xcafebabe
,
0xba5eba11
).
Print machine code in a fault handler or debugging statement and copy that code in to an array in a dummy C program to disassemble it with gdb. The C code looks something like this:
unsigned char code[] = { 0x90, 0x90, 0x90 };Then in gdb disassemble code.
Add trap handlers for undefined opcodes and then drop ud2 instructions at various points. The trap handler can print out the faulting address, providing a cheap debugging print in places that printf cannot safely be called.