IT博客汇
  • 首页
  • 精华
  • 技术
  • 设计
  • 资讯
  • 扯淡
  • 权利声明
  • 登录 注册

    Debugging Linux Kernel using GDB and QEMU

    Liu Yutao发表于 2014-10-22 11:00:00
    love 0

    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.

    Prepare virtual machine and its vmlinux

    At first, prepare a virtual machine, and more importantly, you should have the vmlinux of the VM’s kernel.

    But how?

    The simplest way is downloading a new kernel from here, compile to get the vmlinux and install the kernel using make install.

    But what if you want to keep the current kernel?

    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

    Prepare GDB environment

    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 to the point

    Now everything is ready, suppose the things we need are in following locations:

    • Main directory: /source/to/
    • VM image: /source/to/vm.img
    • vmlinux: /source/to/vmlinux
    • linux-source: /source/to/linux-source/
    • GDB directory: /source/to/gdb/
    Prepare the bash script for qemu setup
    $ cat /source/to/boot_gdb_kernel.sh
    
    /source/to/boot_gdb_kernel.sh
    1
    2
    3
    4
    5
    6
    
    #!/bin/bash
    
    qemu=qemu-system-x86_64
    img=/source/to/vm.img
    
    ${qemu} --enable-kvm -smp 1 -m 1024 -drive file=${img} -netdev "user,id=user.0,hostfwd=tcp:0.0.0.0:2222-:22" -device e1000,netdev=user.0 -gdb tcp::1234 -S $@
    

    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.

    Prepare GDB configuration file

    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
    
    /source/to/gdb/.gdbinit
    1
    2
    3
    4
    
    file /source/to/vmlinux
    directory /source/to/linux-source
    target remote :1234
    hbreak start_kernel
    

    and we also need to add following line to ~/.gdbinit file:

    ~/.gdbinit
    1
    
    add-auto-load-safe-path /source/to/gdb/.gdbinit
    
    Begin to debug

    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.



沪ICP备19023445号-2号
友情链接