Debug Kernel Code using Bochs
This small tutorial will describe the process for debugging kernel code
using bochs x86 emulator and the ominOS, kernel I wrote, as an example.
Requirments: As far as i know, in my example, you must be booting with GRUB
using an elf kernel. gdb must obviously be installed as well.
first download the bochs source code from
http://sourceforge.net/project/showfiles.php?group_id=12580
(current release at the time of writing this is 2.3,
but I will be using 2.2.6 in this example.
unpack the sourcecode and configure it then compile and install like this:
./configure --enable-gdb-stub
make
make install
At this point you will have bochs installed. Now you will need to edit your
bochsrc and add this line:
gdbstub: enabled=1, port=1234, text_base=0, data_base=0, bss_base=0
at this point when you start up bochs, you will see this:
Waiting for gdb connection on localhost:1234
open another terminal and open your kernel with gdb. My kernel's filename is
kernel32 in this example.
anthony@rupert:~/code/os/ominos$ gdb -q kernel32
Using host libthread_db library "/lib/tls/i686/cmov/libthread_db.so.1".
(gdb)
at the gdb prompt enter the command:
target remote localhost:1234
(gdb) target remote localhost:1234
Remote debugging using localhost:1234
0x0000fff0 in ?? ()
warning: shared library handler failed to enable breakpoint
Reply contains invalid hex digit 78
(gdb)
I always get that warning. but it has never affected anything. at this point
you can set break points. The code we will be stepping through is located in vfs.c from my kernel's source. Have a gander if you'd like to compare. I will set a breakpoint on vfsMount.
(gdb) break vfsMount
Breakpoint 1 at 0xc0208078: file vfs.c, line 324.
(gdb)
Then run the continue command at the gdb prompt to start bochs.
(gdb) continue
Continuing.
Breakpoint 1, vfsMount (device=0x0, mountpoint=0x2c9c0 "�a", fstype=0x0)
at vfs.c:324
324 {
(gdb)
I will run through a few lines of code printing variables and whatnot to show
that you can debug your kernel this way
(gdb) c
Continuing.
Breakpoint 1, vfsMount (device=0x0, mountpoint=0x2c9c0 "�a", fstype=0x0)
at vfs.c:324
324 {
(gdb) next
330 kprintf("%s: mounting '%s' on '%s', fstype='%s'n", __FUNCTION__, mountpoint, device?device:"NULL", fstype);
(gdb) next
331 mount = kmalloc(sizeof(mount_t));
(gdb) print fstype
$1 = 0xc020c434 "rootfs"
(gdb) next
332 if(mount == NULL)
(gdb) print/x mount
$2 = 0xd00020fa
(gdb) next
335 memset(mount, 0, sizeof(mount_t));
(gdb) next
337 mount->fs = getFileSystem(fstype);
(gdb) next
338 if(mount->fs == NULL)
(gdb) print *mount->fs
$3 = {name = 0xd00020ac "rootfs", blocksize = 0, blockCount = 0,
fscalls = 0xc0209a14, fsInfo = 0x0, next = 0xd00020c2}
(gdb) next
345 if(device != NULL)
(gdb) next
354 mount->mountpoint = kstrdup(mountpoint);
(gdb) step
kstrdup (s=0xc020c43b "/") at kstrdup.c:6
6 char *ret = (char *)kmalloc(strlen(s)+1);
(gdb) next
7 if(ret == NULL)
(gdb) next
9 memset(ret, 0, strlen(s)+1);
(gdb) next
10 strncpy(ret, s, strlen(s));
(gdb) next
11 return ret;
(gdb) next
12 }
(gdb) next
vfsMount (device=0x0, mountpoint=0xc020c43b "/", fstype=0xc020c434 "rootfs")
at vfs.c:355
355 if(mount->mountpoint == NULL)
(gdb) print mount->mountpoint
$4 = 0xd0002122 "/"
(gdb) print *mount
$5 = {device = 0, fs = 0xd0002088, mountpoint = 0xd0002122 "/",
rootVnode = 0x0, mountCover = 0x0, vTable = 0x0, next = 0x0}
(gdb)
There you go. That is all there is to debugging with gdb and bochs. Look on
the internet for more in depth tutorials on actually using gdb and all its
available commands.