昨天听别人讲使用Qemu和gdb来实现源码级内核调试,今天试了一下,果然非常方便,现简单的记录一下。
Qemu是一个开源的虚拟机软件,能够提供全系统的仿真,可以运行在多个平台上,并仿真多个别的平台。Qemu虚拟机是采用动态翻译来实现CPU的仿真的,对硬件的依赖程度低,通过它提供的众多参数,你能够对虚拟的机器进行定制以满足你的需求。
要想对内核进行调试,那自然需要重新编译内核了,编译内核的具体方法这里就不罗嗦了,需要注意的是在配置内核时,要将“kernel hacking"中的“compile the kernel with debug info"选上,否则没有调试信息,gdb也难为无米之炊。
编译好内核之后,我们还需要制作一个rootfs作为Qemu虚拟机的硬盘,这个步骤可以通过Qemu来完成,大致的步骤如下:
1. 创建一个虚拟的硬盘
# qemu-img create foobar.img 8G # 创建一个8G的虚拟硬盘
2. 在虚拟的硬盘上安装一个Linux系统
# qemu -hda foobar.img -cdrom xxx.iso -boot d -m 512 -enable-audio -localtime
# xxx.iso为某linux的发行版本的iso,该命令就是要从iso启动,并将系统安装到foobar.img中
当然,其实也可以将init ram disk作为Qemu的rootfs,但这时需要对initrd进行修改,如果你对initrd不熟悉的话,最好还是花点时间,做个rootfs,这个可以省去一些麻烦。
Qemu虚拟机只是提供了一个虚拟的机器,使得程序运行在虚拟机中如同运行真实的物理机器上一样,除此以外,Qemu还必须能够对虚拟机进行完全的控制,但Qemu和gdb又是怎么扯上关系的呢?这是因为Qemu中内置了gdbserver,这使得Qemu能够和远程的gdb进行通讯,通过远程的gdb来控制Qemu虚拟机的执行,从而达到调试的目的。具体的操作如下:
1. 切换到刚刚编译的内核的路径,然后启动Qemu
# qemu -kernel arch/x86/boot/bzImage -initrd /boot/initrd.img-2.6.31-22-generic -gdb tcp::1234 -S
# -kernel 用来指定内核,注arch/x86/bzImage是不带调试信息的内核,vmlinux是带有调试信息的内核
# -initrd 用来指定内核启动时使用的ram disk,
# -gdb tcp::1234表示启动gdbserver,并在tcp的1234端口监听,-S表示在开始的时候冻结CPU直到远程的gdb输入相应的控制命令
2. 启动gdb,并和Qemu进行联系,然后你就可以像调试应用程序那些调试内核了
# gdb
(gdb) file vmlinux
(gdb) target remote :1234
(gdb) b start_kernel
(gdb) c
x:查看内存,通过相应的参数来执行内存的地址和要显示多少数据