I should say it is really a shame that after more than 5 years of Linux development I still don’t know how to debug linux kernel using GDB.
Yesterday I’ve seen how GodLiang do this, and learned it from him, and finally, 新技能Get:
Debugging Linux Kernel using GDB and QEMU - learn from Liangpig
Here I’ll just skip about how to setup KVM and QEMU, I suppose you’ve already known that.
At first, prepare a virtual machine, and more importantly, you should have the vmlinux
of the VM’s kernel.
The simplest way is downloading a new kernel from here, compile to get the vmlinux
and install the kernel using make install
.
Please use following instructions (for example my kernel is linux-3.2) :
$ sudo aptitude install linux-headers-`uname -r`
$ sudo aptitude install linux-source-3.2
$ cd /usr/src
$ tar zxvf linux-source-3.2.tar.gz
$ cd linux-source-3.2
$ make localmodconfig
$ make menuconfig
$ make -j4; make modules_install; make install
$ mkinitramfs 3.2.57 -o /boot/initrd.img-3.2.57
After above 2 approaches, you can have vmlinux
in the 1st level folder, copy that, as well as the whole source code to the host.
Note: Above operations are all done inside virtual machine, while the following should be done in the host
You may say it is quite simple since we only need to use apt-get install gdb
.
That’s almost right, but the GDB has a bug when it is remotely attached to QEMU on x86-64 arch, as shown in here.
Thus we need to do the patching staff illustrated in the above link.
My current GDB version is 7.6.2, so I download the same version, patch and compile it, and finally install it:
$ wget http://ftp.gnu.org/gnu/gdb/gdb-7.6.2.tar.gz
$ tar zxvf gdb-7.6.2.tar.gz
$ cd gdb-7.6.2
// patch it as what is shown in http://www.cygwin.com/ml/gdb-patches/2012-03/msg00116.html
$ ./configure; make -j4; sudo make install
Now everything is ready, suppose the things we need are in following locations:
/source/to/
/source/to/vm.img
/source/to/vmlinux
/source/to/linux-source/
/source/to/gdb/
$ cat /source/to/boot_gdb_kernel.sh
1 2 3 4 5 6 |
|
As shown in the script, it uses -gdb tcp::1234 -S
to open GDB support in QEMU.
After we execute the script, it will open the virtual machine, but stuck in the black screen, that is because we use the -S
option, which instruct QEMU to stop until we do something.
What we need to do next is executing the GDB in the gdb
directory, which contains the following configuration file:
$ cat /source/to/gdb/.gdbinit
1 2 3 4 |
|
and we also need to add following line to ~/.gdbinit
file:
1
|
|
when we execute gdb
command in this exact directory, it will read the content in .gdbinit file, and attach to the remote 1234
port, and attach to the qemu process:
$ pwd
/source/to/gdb
$ gdb
GNU gdb (GDB) 7.6.2
Copyright (C) 2013 Free Software Foundation, Inc.
.....
0x0000000000000000 in irq_stack_union ()
Hardware assisted breakpoint 1 at 0xffffffff816aa787: file init/main.c, line 469.
(gdb)
Here we need to enter c
to continue the execution, after that, it will stop at the start_kernel
function which we hbreak in the /source/to/gdb/.gdbinit
file:
......
(gdb) c
Continuing.
Breakpoint 1, start_kernel () at init/main.c:469
469 {
(gdb)
Again we enter c
to continue, finally the linux kernel setup. Then we can use gdb to breakpoint any function or address we want to stop, to debug the linux kernel.
Thanks to Liangpig and hope to learn more from him.