一、安装qemu
这个没有难度,sudo apt-get install qemu-kvm即可。
二、编译内核
1、下载内核源码就不用多说了,网上一大堆,这里假设已经下载好Linux-2.6.63源码,并解压到~/linux-2.6.63/目录下。
2、准备编译环境
①安装g++: sudo apt-get install g++;
②安装build-essiontial: sudo apt-get install build-essential;
③安装libncurses-dev: sudo apt-get install libncurses5-dev;
3、开始编译源码
①进入~/linux-2.6.63/目录,配置内核编译选项,打开调试开关:make menuconfig, 在kernel hacking中选中compile the kernel with debug info;
②开始编译:make bzImage
等待编译完成,会在~/linux-2.6.63/目录下生成vmLinux文件(gdb调试需要),以及在~/linux-2.6.63/arch/x86_64/boot/目录下生成bzImage文件(qemu运行需要)。
三、编译用于内核调试的gdb
当调试开启后gdb vmlinux会出现如下错误:
Remote 'g' packet reply is too long: 00000000000000000020e30100000000000000000000
000060eecf81ffffffff000000010000000048eecf81fffff
...
为了解决这个问题,我们需要重新编译一个gdb。编译步骤如下:
注意这里推荐7.8,网上有用7.4的,但在编译的时候会出现struct signal错误。
2、解压: tar xzvf gdb-7.8.tar.gz
3、编译gdb7.8:之前需要做两件事:
① 为了避免makeinfo错误:missing makeinfo --split-size=5000000 ..
需要安装texinfo库: #$sudo apt-get install texinfo
② 修改gdb-7.8/gdb/remote.c文件中的部分代码:
static void
process_g_packet (struct regcache *regcache)
{
struct gdbarch *gdbarch = get_regcache_arch (regcache);
struct remote_state *rs = get_remote_state ();
struct remote_arch_state *rsa = get_remote_arch_state ();
int i, buf_len;
char *p;
char *regs;
buf_len = strlen (rs->buf);
/* Further sanity checks, with knowledge of the architecture. */
/* if (buf_len > 2 * rsa->sizeof_g_packet)
error (_("Remote 'g' packet reply is too long: %s"), rs->buf); //注释掉这个语句
*/
/*modify by xx 添加这部分语句*/
if (buf_len > 2 * rsa->sizeof_g_packet) {
rsa->sizeof_g_packet = buf_len;
for (i = 0; i < gdbarch_num_regs(gdbarch); i++) {
if (rsa->regs[i].pnum == -1)
continue;
if (rsa->regs[i].offset >= rsa->sizeof_g_packet)
rsa->regs[i].in_g_packet = 0;
else
rsa->regs[i].in_g_packet = 1;
}
}
//.......
}
}
}
修改完成后就可以开始编译了。需要注意的是在gdb-7.8/ 目录下并没有Makefile文件,需要使用 ./configure来生产。在配置的时候,如果要指定gdb安装的路径(目录),那么就需要跟上 --prefix=$PATH的相关参数,一般这种情况可能会针对系统已经有一个gdb了但无法使用,同时也未删除,那么新编译的gdb可能需要安装在另外的目录了。当然我自己的是安装在 ../../tools/ 目录下:
./configure --prefix=../../tools/
② make
③ make install
四、开始调试内核
通过前面的步骤,用于内核调试的所有准备工作都已经OK了,下面就是真正的通过gdb开始进行内核调试!
1、通过qemu启动内核。
①在启动之前,我们需要initrd.img文件,至于该文件的作用大家可自行百度。这里我们直接从宿主ubuntu系统中cp过来:
cp /boot/initrd.img-3.13... ~/linux-2.6.63/initrd.img
②开始启动:
qemy-system-x86_64 -kernel ./bzImage -initrd ./initrd.img -m 128 -S
// -m表示非配内存大小为128Mb, -S表示以调试模式启动,暂定在启动界面
注: 这里并没有制作文件系统,大家可以更具自己的需求添加
③准备调试
现在已经通过qemu启动了内核,但是我们需要还需要其他命令才能进行调试。首先在qemu界面按键ctrl + alt + 2进入qemu后台(同理,ctrl + alt + 1进入qemu前台),键入命令:gdbserver tcp::1234 //此命令表示当前qemu虚拟机在本机的1234端口等待调试器连接
然后,另起一个终端,进入~/linux-2.6.63/,使用我们刚编译的../tools/bin/gdb进行调试:
.../tools/bin/gdb vmlinux
进入gdb后连接之前qemu虚拟机的调试端口,在gdb命令窗口中键入如下命令:
target remote tcp::1234
然后就可以开始调试了!
五、补充部分
单纯使用gdb命令行进行调试比较枯燥,这里推荐ddd工具,安装方法很简单: sudo apt-get install ddd
然后在前面启动gdb vmlinux的时候换成ddd即可,命令如下:
cd ~/linux-2.6.63/
ddd -debugger ../tools/bin/gdb vmlinux (-debugger表示使用我们制定的gdb进行调试)