一、安装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进行调试)