KGDB is a set of kernel patches that allows a second machine running a debugger (gdb) to control the target machine over a serial port. This page describes:
- compiling and running KGDB-enabled kernels, for versions 2.4 and 2.6.
- establishing a serial connection between gdb and a virtual machine running under Windows or Linux
Compiling and running a 2.4 kernel with KGDB
- Download the kgdb 1.9 kernel patch for 2.4.23 from: linux-2.4.23-kgdb-1.9.patch
- Apply the patch:
patch -p1 < /tmp/linux-2.4.23-kgdb-1.9.patch
make menuconfig, and under "Kernel Hacking" enable "KGDB" and "KGDB Thread Analysis"
- build your kernel. (since it's 2.4, that means
make dep and
- copy the kernel (bzImage) to the target virtual machine, or alternately copy vmlinux, the kernel executable, to the debugger machine.
- add another lilo entry for the debug kernel, and append the argument "gdb" to get it to stop in the debugger during boot. I added the following lines to my lilo.conf file:
Note that the default image is the first in the file; the "prompt" and "timeout" arguments will allow you to specify which image to use at boot time. Don't forget to run lilo so it can save the parameters from /etc/lilo.conf.
- Boot. It should output about 20 lines and then stop, waiting for the debugger.
Compiling and running a 2.6 kernel with KGDB
- get the kgdb patches for kernel 2.6.15 here: http://kgdb.linsyssoft.com/downloads/kgdb-2/linux-220.127.116.11-kgdb-2.4.tar.bz2
- untar them and then apply them:
patch -b -p1 < ../linux-18.104.22.168-kgdb-2.4/core-lite.patch
patch -b -p1 < ../ ... core.patch
patch -b -p1 < ../ ... i386-lite.patch
- configure and build your kernel. Under "kernel hacking" enable kgdb, set serial port to "0" (i.e. /dev/ttyS0, or COM1 - the default is ttyS1), and enable kernel debug info.
- Add the command "kgdbwait" to the kernel command line for the kgdb kernel, and boot it. After printing "Booting the kernel" it should hang.
Connecting to VMWare KGDB, Linux host
- Power down your virtual machine and click "Edit Virtual Machine Settings". Add a serial port, select "Connect to named pipe", and provide the pipe name "/tmp/com_1". (note that this isn't really a named pipe, but a unix-domain socket) Click "advanced settings" and set "yield CPU on poll". You can also get to this setting from the device list once you finish adding the port.
- GDB can't connect directly to a unix-domain socket, so you'll need to use the
socat ("socket cat") utility. It's installed on the elab machines, or you can install it from FC5 RPM or CentOS 4 RPM.
- If the socket created by VMWare is /tmp/com_1, then invoke socat as:
socat -d -d /tmp/com_1 PTY:
- Find the line in the output identifying the PTY that was created:
-bash-3.00$ socat -d -d /tmp/com_2 PTY:
2006/10/17 10:44:46 socat N successfully connected via
2006/10/17 10:44:46 socat N PTY is '''/dev/pts/7'''
2006/10/17 10:44:46 socat N starting data transfer loop ...
- Start gdb on the vmlinux executable, and connect to the target:
-bash-3.00$ gdb vmlinux.kgdb
GNU gdb Red Hat Linux (22.214.171.124-1.96rh)
(gdb) target remote /dev/pts/7
Remote debugging using /dev/pts/7
0xc012c138 in .text.lock.kgdbstub () at kgdbstub.c:1007
1007 kgdbstub.c: No such file or directory.
warning: shared library handler failed to enable breakpoint
And now you're up and running.
Connecting to KGDB, Windows Hhost
- Add 2 virtual serial ports to your virtual machine. Configure the second one to connect to a named pipe named \\.\pipe\com_2. Under advanced settings, check the box for "yield CPU on poll"
- Download and install the Named Pipe TCP Proxy utility: nptp_setup.zip
- Start the proxy, and establish a connector between some port on the local machine (e.g. 8111) and \\.\pipe\com_2. Check the box to enable non-local systems access.
- In another virtual machine run 'gdb vmlinux'. (you'll have to work out how to share the source tree between the two VMs - clearly you can't use NFS from the VM that you're debugging)
target remote ip_addr:8111 where
ip_addr is the windows host IP address that this virtual machine sees. (e.g. on my machine 192.168.149.1, and the VM gets address 192.168.149.128)
KGDB should connect, and away you go.
Caveats - note that I've had a lot of trouble with the DHCP server in VMWare if I'm running multiple machines at once, as it tends to give the same address to each one. You may wish to hardcode the ip address, route, and DNS resolver instead on each VM.
Connecting to KGDB using VMWare Fusion on Mac OS X
The process is a little long but effective:
- Download socat for mac using the instrcutions on the site http://socat.darwinports.com/
(i) just in case the site is removed, the key idea is to download darwinports on your mac (socat is ported onto mac under this project).
(ii) install socat:
sudo port install socat
(iii) it may take a while (around 10-15 mins) and thus dont cancel the operation; be patient and wait (have faith in Darwin)
(iv) run socat, if mac reports that it cant find socat, dont panic its not in your path; find out its path (like for me its in "/opt/local/bin") and update your path.
- compile the kernel with all those required patches (mentioned above) make sure that you do make install; do the necessary changes in your grub-file:
2.a) make sure that you have an alternate booting option, which means, leave a copy of vanilla-kernel and copy bzImage as another file in /boot
2.b) dont panic if make install fails ... it always fails on my machine ... just copy bzImage and System.map.... and it should work; if it doesnt, you need to do some simple hacking around to get it working (in the sense that the VM should boot with this new kernel)
2.c) if you are planing to debug a loadable module, then its faster to not to put a kgdbwait in the boot option because that, unnecessarily, makes the machine to wait.
- install another virtual machine with linux on it (if you have not already done it); this will be the machine on which you will run gdb. Lets name it gdb-VM
- if you havent figured out how to share the source-code between two virtual machines ... no sweat, you can still start by copying the vmlinux (note that its not vmlinuz) file from the source machine to gdb-VM
- shutdown both the machines
- find the ".vmx" file of the source virtual machine .... for e.g. in my case the VMs name is "Other Linux 2.6.x Kernel 3" ... so for me the file is like this "/Users/upendra/Documents/Virtual\ Machines/Other\ Linux\ 2.6.x\ Kernel\ 3/Other\ Linux\ 2.6.x\ Kernel\ 3.vmx" ... phew .. thats something ...
- open it using vi (because I like vi for such simple work) ...
- make the following changes (or add these lines if they are not there) ... make sure that specify the correct path for the serial0.fileName... the example has the path of my configuration
serial0.present = "TRUE"
serial0.fileType = "pipe"
serial0.yieldOnMsrRead = "TRUE"
serial0.startConnected = "TRUE"
serial0.fileName = "/Users/upendra/tmp/com_1"
- start both the VMs
- run the following command on your mac
socat -d -d /Users/upendra/tmp/com_1 TCP4-LISTEN:8888
- go to your client gdb-VM and run this
target remote <ipaddress of your machine>:8888
so for example, on my machine I run the following command and I think exactly same command should work on your machine also
target remote 192.168.44.1:8888
... your are done ... happy kernel debugging ....
Debugging modules under KGDB
- get the address of the running module by running 'cat /proc/modules' on the target machine.
- in gdb, type add-symbol-file /path/to/module/object.o 0xADDRESS which will load the symbols.