主题 : 使用qemu调试linux内核 复制链接 | 浏览器收藏 | 打印
级别: 侠客
UID: 40508
精华: 1
发帖: 44
金钱: 270 两
威望: 54 点
贡献值: 1 点
综合积分: 108 分
注册时间: 2011-03-19
最后登录: 2018-04-21
楼主  发表于: 2012-05-26 16:22

 使用qemu调试linux内核

1:     安装ubuntu Server系统:
           kvm-img create -f raw disk.img 8G
                      kvm -m 512 -cdrom ubuntu-10.10-server-i386.iso -drive file=disk.img,if=scsi,index=0 -boot d -net nic -net user
    安装完系统之后启动(普通方式):
    kvm -m 512 -drive file=disk.img,if=scsi,index=0,boot=on -boot c -net nic -net user
    
2:    提取boot文件
    sudo losetup -f disk.img
    sudo losetup -a
    此时输出:
    /dev/loop0: [0801]:16908388 ($/path/to/disk.img)
    找出partition 的起始setctor:
    sudo fdisk -c -u -l /dev/loop0
    输出:
    Disk /dev/loop0: 8589 MB, 8589934592 bytes
    255 heads, 63 sectors/track, 1044 cylinders, total 16777216 sectors
    Units = sectors of 1 * 512 = 512 bytes
    Sector size (logical/physical): 512 bytes / 512 bytes
    I/O size (minimum/optimal): 512 bytes / 512 bytes
    Disk identifier: 0x000411b5

          Device Boot      Start         End      Blocks   Id  System
    /dev/loop0p1   *        2048    15958015     7977984   83  Linux
    
    Unmount loop0 设备:
    sudo losetup -d /dev/loop0

    挂载disk.img的分区(/dev/loop0p1):
    sudo losetup -f -o 1048576 disk.img        
    (1048576 = 2048*512)
    
    sudo losetup -a
    此时的输出应当是:    
    /dev/loop0: [0801]:16908388 ($/path/to/disk.img) offset 1048576

    拷贝整个partition到新的raw文件:
    sudo dd if=/dev/loop0 of=diskout.img

    Unmount loop0 设备:
    sudo losetup -d /dev/loop0

    挂载diskout.img:
    sudo mount -o loop diskout.img /mnt
    
    从/mnt/boot中拷贝kernel和initrd:
    sudo cp /mnt/boot/vmlinuz-2.6.35-22-generic .
    sudo cp /mnt/boot/initrd.img-2.6.35-22-generic  .
    
    Unmount Loop :
    sudo umount /mnt
    
    用拷贝出的文件启动 :
    kvm -m 512 -kernel vmlinuz-2.6.35-22-generic -append "root=/dev/sda" -boot c -hda diskout.img     -k en-us -initrd initrd.img-2.6.35-22-generic -net nic -net user
    
3:    编译新内核
    下载内核:linux-2.6.35.9.tar.bz2
    解压后进入内核:cd linux-2.6.35.9
    生成配置文件:
    Make defconfig

    配置编译选项:
    DEBUG_RODATA  建议关闭该选项:
    位置:     -> Kernel hacking      ->Write protect kernel read-only data structures

    KGDB_SERIAL_CONSOLE  打开该选项:使用串口进行通信
    位置:    -> Kernel hacking          
                -> KGDB: kernel debugger
                              -> KGDB: use kgdb over the serial console

    KGDB_LOW_LEVEL_TRAP  使能该选项可以kgdb不依赖notifier_call_chain()机制来获取        断点异常, 这样就可以对notifier_call_chain()机制实现相关的函数进行单步调试。
    依赖: KGDB [=y] && (X86 [=y] || MIPS [=MIPS])
    位置:      -> Kernel hacking      
                -> KGDB: kernel debugger (KGDB [=y])
                           ->KGDB: Allow debugging with traps in notifiers

    DEBUG_INFO    该选项可以使得编译的内核包含一些调试信息,使得调试更容易。
    位置:
        -> Kernel hacking
             ->compile the kernel with debuginfo

    FRAME_POINTER  使能该选项将使得内核使用帧指针寄存器来维护堆栈,从而就可以正            确地执行堆栈回溯,即函数调用栈信息。
    位置:  
             -> Kernel hacking
                    ->Compile the kernel with frame pointers

    MAGIC_SYSRQ  (如果你选择了KGDB_SERIAL_CONSOLE,这个选项将自动被选上) 激活"魔    术 SysRq"键. 该选项对kgdboc调试非常有用,kgdb向其注册了‘g’魔术键来激活kgdb 。
      位置:  
             -> Kernel hacking
                   ->magic SysRq key
当你想手动激活kgdb时,你可以触发SysRq的g键, 如:
$ echo "g" > /proc/sysrq-trigger

    配置内核版本信息:
    打开Makefile在 EXTRAVERSION =  后面加入:-kgdb    
    修改编译优化等级:
     打开根目录下Makefile文件修改内核Makefile优化选项将KBUILD_CFLAGS += -O2,修改    为:KBUILD_CFLAGS += -O。
    编译内核:
    make && make modules
4:    安装内核:    
    将编译的内核拷贝到diskout.img里边:
    sudo mount -o loop diskout.img  /mnt/
    sudo cp -r linux-2.6.35.9 /mnt/home/gudujian/
    sudo umount /mnt
    启动虚拟机:
    kvm -m 512 -kernel vmlinuz-2.6.35-22-generic -append "root=/dev/sda" -boot c -hda diskout.img
    -k en-us -initrd initrd.img-2.6.35-22-generic -net nic -net user
    在虚拟机中安装:
    cd linux-2.6.35.9
    sudo make modules_install
    sudo make install    
    制作initramfs
    cd /lib/modules
    sudo mkinitramfs -o /boot/initrd.img-2.6.35.9-kgdb
    
    关闭虚拟机,拷贝新安装的内核文件:
    sudo mount -o loop diskout.img  /mnt/
    sudo cp /mnt/boot/vmlinuz-2.6.35.9-kgdb .
    sudo cp /mnt/boot/initrd.img-2.6.35.9-kgdb  .
    sudo umount /mnt

    使用新安装的内核来启动:
    kvm -m 512 -kernel vmlinuz-2.6.35.9-kgdb -append "root=/dev/sda" -boot c -hda diskout.img
    -k en-us -initrd initrd.img-2.6.35.9-kgdb -net nic -net user
    此时如果能正常启动了那么改变启动参数来调试内核:    
    kvm -m 512 -kernel vmlinuz-2.6.35.9-kgdb -append "root=/dev/sda kgdboc=ttyS0,115200 kgdbwait" -boot c -hda diskout.img -k en-us -initrd initrd.img-2.6.35.9-kgdb -serial tcp::4321,server -net nic -net user 1
虚拟机的终端将提示等待远程连接到本地端口4321:
    QEMU waiting for connection on: tcp:0.0.0.0:4321,server    
    这时使用另外一个控制台执行:
    $gdb  vmlinux
    (gdb) target remote localhost:4321    
然后虚拟机就可以继续正常运行下去,最后停止内核,并显示如下信息:
kgdb: Waiting for connection from remote gdb…
这时gdb这边就可以看到如下的提示:
(gdb) target remote localhost:4321
    Remote debugging using localhost:4321
    kgdb_breakpoint () at kernel/debug/debug_core.c:983
    983        wmb();

从这里就可以开始下断点调试内核。



级别: 侠客
UID: 40508
精华: 1
发帖: 44
金钱: 270 两
威望: 54 点
贡献值: 1 点
综合积分: 108 分
注册时间: 2011-03-19
最后登录: 2018-04-21
1楼  发表于: 2012-05-26 16:24
     终于有时间把这些整理一下发出来了。

入门级水平,高手勿笑哇。。

级别: 侠客
UID: 40508
精华: 1
发帖: 44
金钱: 270 两
威望: 54 点
贡献值: 1 点
综合积分: 108 分
注册时间: 2011-03-19
最后登录: 2018-04-21
2楼  发表于: 2016-05-04 21:12
小弟以前整理的:

linux内核调试环境搭建-1 Ubuntu10 .10下编译安装qemu
http://blog.csdn.net/xsckernel/article/details/8159548


linux内核调试环境搭建-2 用busybox搭建、
http://blog.csdn.net/xsckernel/article/details/8159560

linux内核调试环境搭建-3 调试内核模块
http://blog.csdn.net/xsckernel/article/details/8159568

linux内核调试环境搭建-4 调试模块初始化函数
http://blog.csdn.net/xsckernel/article/details/8159576

用GDB反汇编调试linux内核
http://blog.csdn.net/xsckernel/article/details/8254562