• ubuntu: qemu+gdb 调试linux kernel 学习笔记


    声明:

      本笔记内容并非本人原创,90%来自网络资料的整合。同时,由于自己是刚刚接触qemu & gdbserver remote debug,本文也就算不得教程,仅供有缘人参考而已。

    ------------------------------------------------------------------------------------------------分割线---------------------------------------------------------------------------

    step 1:  kernel 编译环境安装

      

    apt-cache search build-essential
    sudo apt-get install build-essential -y
    
    apt-cache search libncurses-dev
    sudo apt-get install libncurses-dev -y

    当然,可能还需要其他一些工具,如果gcc  g++ make 之类的工具,毕竟build-essential是一个工具箱子,若有洁癖,可能就有点冲突。而ncurses-dev,这个是必须要有的,我记得在fedora上是直接yum install ncurses-dev即可,.deb系列的似乎是加了个前缀。

    step 2:   gdb的安装

      需要告诉的是,build-essential 里应该是包含了一个gdb & gdbsever工具了,但是很抱歉的是无法使用,会出现这个错误:

        

    Remote 'g' packet reply is too long: 000000000000000020000000000000004000000000000000001006000000000000f009000000000028aece81ffffffff981fc081ffffffff901fc081ffffffff0030c1010000000000000000000000000000000000000000f0b926020000000020f1d281ffffffffb01fc081ffffffff00e0e681ffffffff0010e781ffffffff02fbd281ffffffff9600000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007f0300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000801f0000

      于是,我们需要去下载一个比较新的gdb source下来(我使用的是7.8),网址是: http://ftp.gnu.org/gnu/gdb/

      

    http://ftp.gnu.org/gnu/gdb/

      然后按照网络前人们共享出来的资料,修改gdb的源码:  在 gdb-7.8/gdb/remote.c 文件的 static void process_g_packet (struct regcache *regcache)函数里面修改部分内容,如下:

     1 static void
     2 process_g_packet (struct regcache *regcache)
     3 {
     4   struct gdbarch *gdbarch = get_regcache_arch (regcache);
     5   struct remote_state *rs = get_remote_state ();
     6   struct remote_arch_state *rsa = get_remote_arch_state ();
     7   int i, buf_len;
     8   char *p;
     9   char *regs;
    10 
    11   buf_len = strlen (rs->buf);
    12 
    13   /* Further sanity checks, with knowledge of the architecture.  */
    14 /*  if (buf_len > 2 * rsa->sizeof_g_packet)
    15     error (_("Remote 'g' packet reply is too long: %s"), rs->buf);
    16 */
    17   /*modify by xx*/
    18   if (buf_len > 2 * rsa->sizeof_g_packet) {
    19     rsa->sizeof_g_packet = buf_len;
    20     for (i = 0; i < gdbarch_num_regs(gdbarch); i++) {
    21         if (rsa->regs[i].pnum == -1)    
    22             continue;
    23         if (rsa->regs[i].offset >= rsa->sizeof_g_packet)
    24             rsa->regs[i].in_g_packet = 0;
    25         else
    26             rsa->regs[i].in_g_packet = 1;
    27     }
    28   }
    29   //.......
    30     }
    31     }
    32 }

      上面的14-15行是原来文件的,而18-27行是重新添加上的 <为了节约版面,我没有贴后面的,所以,注意 " { } "  可能导致的语法错误>,这样修改的具体原理,本人并不清楚,但确实解决了问题。

      修改完整后,就开始编译gdb吧。在 gdb-7.8/  下执行下面的命令:

    1 ./configure --prefix=../../tools/
    2 make 
    3 make install

      需要注意的是在gdb-7.8/  目录下并没有Makefile文件,需要使用 ./configure来生产。在配置的时候,如果要指定gdb安装的路径(目录),那么就需要跟上  --prefix=$PATH的相关参数,一般这种情况可能会针对系统已经有一个gdb了但无法使用,同时也未删除,那么新编译的gdb可能需要安装在另外的目录了。当然我自己的是安装在 ../../tools/ 目录下。

    step 3: 编译linux kernel

      去 www.kernel.org下载自己需要的版本,待完毕后,对kernel编译生成bzImage  &  vmlinux 文件。如果是和我一样刚入门的,可以参考以下命令&步骤:

      

    cd  linux-3.12.35/
    cp /boot/config-3.13.0-43-generic .config
    make menuconfig
    <save>
    make bzImage

      需要说明的是,具体要看哪些调试信息,应该在make menuconfig的时候去配置,去选择,然后保存好后,就编译。编译后,bzImage这个是被压缩了的,供qemu虚拟机使用,vmlinux里面带了某些信息,没有压缩,供gdb使用。

      当编译结束后,可以将vmlinux bzImage文件copy到一个干净的目录下吧---这个随自己的习惯了,不copy也无所谓了。

      上面忘记了准备最重要的东西了: qemu

    step 4: qemu的使用

      简单说下: qemu 是一款虚拟机,可以模拟x86 & arm 等等硬件平台<似乎可模拟的硬件平台很多...>,而qemu 也内嵌了一个 gdbserver。这个gdbserver于是就可以和gdb构成一个远程合作伙伴,通过ip:port 网络方式或者是通过串口/dev/ttyS*来进行工作,一个在这头,一个在那头。

      至于安装qemu虚拟机,可以通过源码编译,make & make install ,在这里可以下载:http://wiki.qemu.org/Download。也可以直接在ubuntu 软件包里apt-get install  qemu-kvm即可。这里不详细记载了。当安装后,可能的文件是这些:

    1 qemu-system-i386
    2 
    3 qemu-system-x86_64
    4 
    5 qemu-img
    6 
    7 qemu-io
    8 ....

      这个是什么意思呢? 第一行的表示是 i386机器上使用的qemu虚拟机,第二行表示是 x86_64上使用的虚拟机。另外的就没使用过了。具体的请参考官网文档:http://wiki.qemu.org/Main_Page。当然,我自己的系统是 x86_64的,使用的是第二个。

    step 4: 让kernel为你稍带片刻~

      

    1 qemu-system-x86_64 -kernel ./bzImage -initrd ./initrd.img -smp 2 -gdb tcp::1234  -S

      先使用命令启动qemu。

      qemu-system-x86_64的参数比较多,这里简单说下:

      -kernel 是指定一个大内核文件,当仁不让的是bzImage。

      -initrd 是指定一个 initrd.img文件,这个文件可以从   /boot/initrd.img-3.13.0-43-generic  拷贝而来,关于它是什么东西呢? 可以参考这个: http://www.linuxfly.org/post/94/ ,或者是这个 http://blog.csdn.net/chrisniu1984/article/details/3907874  。

      -smp 可以从名字猜想,它是给qemu指定几个处理器,或者是几个线程<嗯,大概意思就thread吧>。

      -gdb则是启动qemu的内嵌gdbserver,监听的是本地tcp端口1234---如果这样写:   -gdb tcp:192.168.1.100:1234 ,似乎也是没问题的。

      -S 就是挂起gdbserver,让gdb remote connect it。还有一个-s,那是另外一种情况要使用了。

      如果自己嫌敲命令麻烦<虽然那很酷>,可以使用以下的方式,将该命令保存到某个文件中,比如 qemu.start:

      

    1 #!/bin/bash
    2 qemu-system-x86_64 -kernel ./bzImage -initrd ./initrd.img -smp 2 -gdb tcp::1234  -S
    3 <save>
    4 chmod  +x qemu.start
    5 
    6 ./qemu.start

      这样就可以启动qemu了 <注意自己的 bzImage & initrd.img 文件的路径>

      提示:  man qemu-system-x86_64,你会获得一些帮助。

    step 5: 使用gdb去连接已将启动了的qemu:

      

     1 ../tools/gdb/bin/gdb vmlinux 
     2 
     3 -----
     4 GNU gdb (GDB) 7.8
     5 Copyright (C) 2014 Free Software Foundation, Inc.
     6 License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
     7 This is free software: you are free to change and redistribute it.
     8 There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
     9 and "show warranty" for details.
    10 This GDB was configured as "x86_64-unknown-linux-gnu".
    11 Type "show configuration" for configuration details.
    12 For bug reporting instructions, please see:
    13 <http://www.gnu.org/software/gdb/bugs/>.
    14 Find the GDB manual and other documentation resources online at:
    15 <http://www.gnu.org/software/gdb/documentation/>.
    16 For help, type "help".
    17 Type "apropos word" to search for commands related to "word"...
    18 Reading symbols from vmlinux...done.
    19 -----
    20 
    21 (gdb) target remote : 1234
    22 Remote debugging using : 1234
    23 0x0000000000000000 in irq_stack_union ()
    24 
    25 (gdb) b start_kernel
    26 Breakpoint 1 at 0xffffffff81d2fb02: file init/main.c, line 476.
    27 
    28 (gdb) c
    29 Continuing.
    30 
    31 Breakpoint 1, start_kernel () at init/main.c:476
    32 476    {
    33 
    34 
    35 (gdb) n
    36 485        smp_setup_processor_id();
    37 (gdb) n
    38 491        boot_init_stack_canary();
    39 (gdb) n
    40 493        cgroup_init_early();

      第一行表明启动我自己编译的gdb,这有两个方式  :  gdb    fileName 启动,或者 gdb启动后,再使用 file   fileName 启动

      第21行表明连接远程gdbserver,由于这是在同一台笔记本上,就没有指定ip地址,仅仅指定了port号码。----当然,如果是连接uart口,也行。

      第25行,是break一个断点,在某个函数的入口处  。

      第28行,应该是发一个命令,让qemu那边继续运行的意思,这个时候,qemu那边的屏幕上会闪现出:"Booting from ROM..."

      后面啊,就是下一步下一步的意思咯: next ...  next ...   当然,也可以选择step   step   s....  直到哪里才会在qemu那边打印消息呢? 要在 console_init();这行代码后才会的。

      做一个稍微重要的说明: 我这里并没有启用文件系统,如果有需要,可以试着用busybox做一个,然后参考qemu kernel调试手册,或者网络资源进行加入调试即可。

    --------------------------------------------------------------------------------------扯淡分割线--------------------------------------------------------------------------------------------

    后记:

      至于gdb 的命令,还有很多很多,如果是new to kernel的话,请点击这里:    http://www.sourceware.org/gdb/   最好的是慢慢啃官网文档,然后再看看别人的理解,应该就差不多了。或者看看这个: http://www.yolinux.com/TUTORIALS/GDB-Commands.html

      这几天也一直在搜索kernel debug的方法,qemu+gdb 是一种,当然也还有其他的方法。不过总结下来,代价以qemu+gdb最小。如果你是大屏幕pc,可以试试将qemu+gdb+eclipse这样,纳入IDE环境。而自己是笔记本,就不凑合IDE了,在vim  shell 下足以。

      稍微夹杂一点想法: 前面也是看了一些操作系统的书+linux kernel的入门读物,但是一直没机会去试着单步运行以下kernel,看看它是怎么走的<书中搭建方式花销比较大:要么就是两台电脑,要么就是搞一半就会放弃的那种>。久而久之,也就懈怠了,更别说再去详细的看代码了。linux kernel是真的很伟大,但没必要神话它。如果对操作系统原理和程序设计的理解达到一定水平,自己也可以整一个OS---尽管那可能会很粗糙。于是,知行合一也就有必要了。

      最后就是,如果真对kernel有兴趣,那起码得把英语搞一搞,然后尽早关注kernel MailList----虽然是万变不离其宗,但世界也是发展变化的。书上多少是有时限的。

     

    关键字: qemu kernel gdb gdbserver 调试

  • 相关阅读:
    后台执行linux命令
    日志
    配置文件
    后台
    后台代码注释
    递归建立文件夹
    图片合成
    java.awt.Font
    java-日期取特定值
    linux乱码
  • 原文地址:https://www.cnblogs.com/chineseboy/p/4216521.html
Copyright © 2020-2023  润新知