Debugging GNU Smalltalk on NetBSD: Episode II

Posted on February 27, 2011

See also: Episode I

Setting up the NetBSD kernel debugging environment

NetBSD has its own kernel debugger named DDB. As the original documentation states, is useful for gathering crash tracebacks, examining the values of variables, and other minor debugging tasks, but if youre doing serious kernel hacking you will want to setup to work with the remote debugger, KGDB, instead.

There is a few HOWTOs on how to setup remote debugging for NetBSD kernel on the Internet.

The first one is the official NetBSD documentation chapter . It describes how to set up debugging using two computers connected with null-model cable.

The second one is a tutorial by Alexander Shishkin. It involves QEMU to host the debugged system, so the work can be done on a single PC. However, it uses a custom script for generating disk image with kernel and the basic userland. It looks a bit tricky.

I have wanted to use a normal system from the official distribution ISO image. Also I had only one laptop with NetBSD and QEMU was the solution. So, my way is a combination of the both methods mentioned above.

Building the kernel

Building kernel is fairly easy. All we need is just to modify the configuration to enable KGDB and to generate a full symbol table. The following steps are taken from the already referred official documentation:

# cd /usr/src/sys/arch/i386/conf
# cp GENERIC DEBUGGING

GENERIC and DEBUGGING are build configuration files. These files determine what will be included into the kernel, which options will be enabled or disabled and so on. GENERIC is a basic configuration file and the stock NetBSD kernel is built as GENERIC .

I have named a new configuration as “DEBUGGING”. In the DEBUGGING configuration file, the following lines have to be commented with the preceiding pragma ( # ):

#options    DDB                     # in-kernel debugger
#options    DDB_HISTORY_SIZE=100    # enable history editing

and the following lines have to be uncommented by removing the preceiding pragma:

options     KGDB                    # remote debugger
options     "KGDB_DEVNAME=\"com\"",KGDB_DEVADDR=0x3f8,KGDB_DEVRATE=9600
makeoptions DEBUG="-g"              # compile full symbol table

KGDB_DEVADDR option sets the address of the serial port which will be used for debugging. 0x3f8 is tty00 , 0x2f8 is tty01 .

There is just a few things left to build the kernel:

# config DEBUGGING
# cd ../compile/DEBUGGING
# make depend
# make

That is all! After the successful compilation we will get netbsd and netbsd.gdb files in the current directory. It is a new kernel and debugging symbols for GDB respectively.

Preparing the guest system

Now we need to get a basic system working in QEMU. The following commands will create a 2GB QEMU hard disk image and run the NetBSD installer for it:

$ qemu-img create netbsd.img 2G
$ qemu -hda netbsd.img -cdrom i386cd-5.0.2.iso -boot d -m 196 -localtime

All QEMU options in the last command are quite straightforward, the most interesting are:

  • -hda – specifies a hard disk image that we have created a step before (netbsd.img);
  • -cdrom – specifies an installation CD ISO image (i386cd-5.0.2.iso in my case)
  • -boot d – tells QEMU to boot from a virtual CD-ROM instead of the hard disk image;

After the successful installation we will need to restart QEMU with some different options:

$ qemu -hda netbsd.img -boot c -m 196 -localtime \
       -net user -net nic,model=rtl8139 \
       -redir tcp:5555::22

Two -net options will enable networking in the guest. The last -redir option will allow us to connect to the guest with ssh via the localhost port 5555.

After the system will boot, log in as root and run

# dhclient

to obtain an IP address. ping will not work, but pkgsrc will. I have installed Git and OpenSSHd.

Installation of a new kernel is quite simple. With QEMU networking the host machine usually appears as 10.0.2.2 , so the kernel can be transferred with scp :

# mv /netbsd /netbsd.old
# scp user@10.0.2.2:/usr/src/sys/arch/i386/compile/DEBUGGING/netbsd /

Final steps

Again, we will need to restart QEMU in a new configuration:

$ qemu -hda netbsd.img -boot c -m 196 -localtime \
       -net user -net nic,model=rtl8139 \
       -redir tcp:5555::22 \
       -serial tcp::4444,server

The last option -serial tcp::4444,server creates a pipe from a host’s port 4444 to guest’s serial port (remember KGDB options in the kernel configuration).

QEMU will start but will not launch the guest system until we connect to this port. It is time to open gdb :

(gdb) symbol-file /usr/src/sys/arch/i386/compile/DEBUGGING/netbsd.gdb 
(gdb) target remote :4444

QEMU window will appear and we will need to boot the guest system with a different command in the NetBSD bootloader:

boot -d

After some seconds the guest system will enter an initial breakpoint and in the gdb shell we will get something like this:

0xc053556c in breakpoint ()
(gdb)

Great! Now everything is ready for debugging.

(to be continued)