码迷,mamicode.com
首页 > 系统相关 > 详细

搭建基于qemu + eclipse的kernel调试环境(by quqi99)

时间:2016-02-07 02:24:40      阅读:460      评论:0      收藏:0      [点我收藏+]

标签:

作者:张华  发表于:2016-02-06版权声明:可以任意转载,转载时请务必以超链接形式标明文章原始出处和作者信息及本版权声明

( http://blog.csdn.net/quqi99 )

使用qemu结合eclipse或者DDD等gdb的图形前端,跟踪协议栈或者文件系统内存管理等都会非常方便。就是与硬件驱动相关的跟踪可能差点。

编译内核

下载Linux Kernel源码,并编译生成压缩的kernel镜像(/bak/linux/linux-2.6/arch/x86_64/boot/bzImage)与用于gdb的非压缩的kernel ELF文件(/bak/linux/linux-2.6/vmlinux)。  
 cd /bak/linux/ && git clone git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6.git   
如何编译内核参考:编译linux kernel及制作initrd ( by quqi99 )   
sudo apt-get install libncurses5-dev  
make menuconfig   make -j 8 bzImage

制作initrd

制作initrd, 使用initrd时的kernel要使用CONFIG_BLK_DEV_INITRD=y编译。参见我的博客:http://blog.csdn.net/quqi99/article/details/11860241   
sudo apt-get install build-essential initramfs-tools   
sudo make modules_install            #将生成/lib/modules/4.5.0-rc2+   
mkinitramfs -o initrd.img -v 4.5.0-rc2+

使用busybox制作initrd

mkdir -p /bak/linux/initramfs/{bin,sbin,etc,proc,sys,newroot}cd /bak/linuxtouch initramfs/etc/mdev.confwget http://jootamam.net/initramfs-files/busybox-1.10.1-static.bz2 -O - | bunzip2 > initramfs/bin/busyboxchmod +x initramfs/bin/busyboxtouch initramfs/init

chmod +x initramfs/init

initramfs/init文件如下:

#!/bin/sh
#Mount things needed by this script
mount -t proc proc /proc
mount -t sysfs sysfs /sys
#Disable kernel messages from popping onto the screen
echo 0 > /proc/sys/kernel/printk
#Clear the screen
clear
#Create all the symlinks to /bin/busybox
busybox --install -s
#Create device nodes
mknod /dev/null c 1 3
mknod /dev/tty c 5 0
mdev -s
#Function for parsing command line options with "=" in them
# get_opt("init=/sbin/init") will return "/sbin/init"
get_opt() {
	echo "$@" | cut -d "=" -f 2
}
#Defaults
init="/sbin/init"
root="/dev/hda1"
#Process command line options
for i in $(cat /proc/cmdline); do
	case $i in
		root\=*)
			root=$(get_opt $i)
			;;
		init\=*)
			init=$(get_opt $i)
			;;
	esac
done
#Mount the root device
mount "${root}" /newroot
#Check if $init exists and is executable
if [[ -x "/newroot/${init}" ]] ; then
	#Unmount all other mounts so that the ram used by
	#the initramfs can be cleared after switch_root
	umount /sys /proc
	
	#Switch to the new root and execute init
	exec switch_root /newroot "${init}"
fi
#This will only be run if the exec above failed
echo "Failed to switch_root, dropping to a shell"
exec sh

cd initramfs
find . | cpio -H newc -o > ../initramfs.cpio
cd ..
cat initramfs.cpio | gzip > initramfs.igz

但上述busybox-1.10.1-static.bz2似乎没有ext2模块不能识别qemu的-hda参数传进去ext2格式的硬盘,所以最后改成从busybox-1.24.0的源码编译。
wget https://busybox.net/downloads/busybox-1.24.0.tar.bz2
make menuconfig 
   CONFIG_MKFS_EXT2=y
          Busybox Settings  --->  
           Build Options  ---> 
               [*] Build BusyBox as a static binary (no shared libs) //静态方式编译
   make & make install
   cp -avR /bak/linux/busybox-1.24.0/_install/* /bak/linux/initramfs/


qemu加载内核

wget http://www.nongnu.org/qemu/linux-0.2.img.bz2
sudo qemu-system-x86_64 -hda /bak/images/linux-0.2.img -hdb /bak/linux/disk.img -kernel /bak/linux/linux-2.6/arch/x86_64/boot/bzImage -initrd /bak/linux/initramfs.igz -append "root=/dev/sda init=sbin/init console=ttyS0" -nographic -smp 1,cores=1 -S -s 
参数解释如下:
  1.    其中-s为开启GDB的调试端口1234,而-S则表示运行QEMU时冻结待GDB执行(c)ontinue操作。
  2.    console=ttyS0" -nographic表示不开新的图形化窗口,直接使用敲命令的bash窗口
  3.    -append "root=/dev/sda init=sbin/init应该与initrd文件里的init脚本一致。


使用gdb调试内核

   qemu的-s参数会默认在1234端口开启gdbserver。
   hua@node1:~$ sudo netstat -anp |grep 1234
   tcp    0     0 0.0.0.0:1234        0.0.0.0:*          LISTEN      24309/qemu-system-x
   hua@node1:~$ /bak/java/gdb/bin/gdb /bak/linux/linux-2.6/vmlinux 
    ...
   (gdb) target remote localhost:1234
   Remote debugging using localhost:1234
   0x0000000000000000 in irq_stack_union ()
   (gdb) b start_kernel
   Breakpoint 1 at 0xffffffff81d66b09: file init/main.c, line 498.
   (gdb) info registers
   (gdb) bt
   (gdb) c
   (gdb) list
   (gdb) set architecture
   Requires an argument. Valid arguments are i386, i386:x86-64, i386:x64-32, i8086, i386:intel,i386:x86-64:intel, i386:x64-32:intel, auto.

使用eclipse调试内核

1, Linux源码size太大,设置workspace全局禁止使用eclipse去给代码做自动build。索引可以仍然交由eclipse来做,这样方便在eclipse中进行搜索及代码导航。
   - Preferences -> Generl -> Workspace -> Build automatically (Disable)
2, 将Kernel源码导入为eclipse工程, toolChain选为Linux GCC.
      Import -> C/C++ -> Existing Code as Makefile Project
3, 创建一个debug启动器(Debug configurations -> C/C++ Remote Application)
   选择GDB(DSF) Manual Remote Debugging Launcher
   Main TAB -> -C/C++ Application指向实际uncompress kernel: /bak/linux/linux-2.6/vmlinux
   Main TAB -> -Disable auto build
   Debugger TAB -> Stop on startup at ‘start_kernel‘
   Debugger TAB -> connection -> Host Name or IP Address -> = localhost
   Debugger TAB -> connection -> Port number = 1234


编译gdb解决错误“Remote ‘g‘ packet reply is too long”

   cd /bak/java && wget http://ftp.gnu.org/gnu/gdb/gdb-7.7.tar.gz
   修改gdb/remote.c文件,在process_g_packet函数里,将如下代码:
   if (buf_len > 2 * rsa->sizeof_g_packet)
     error (_("Remote ‘g‘ packet reply is too long: %s"), rs->buf);
   修改上两行代码为下面的代码,或者直接注释上两行什么也不加:
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;
  }
}

  ./configure --prefix=/bak/java/gdb && make && make install
   接下来重新配置下Eclipse,点击菜单“Run”->“Debug Configurations…”,在弹出的对话框中,切换到“Debugger”下的“Main”页,修改“GDB debugger:”为刚编译出来的GDB(/bak/java/gdb/bin/gdb),而不是默认的gdb
 

参考

[1] http://blog.chinaunix.net/uid-26009923-id-3825761.html
[2] http://mgalgs.github.io/2012/03/23/how-to-build-a-custom-linux-kernel-for-qemu.html
[3] http://www.kgdb.info/kgdb/use_kgdb/using_kgdb_base_qemu/


附录1, 使用cscope创建索引

1, 创建cscope.files
LNX=/bak/linux/linux-2.6
cd /
find  $LNX                                                                \
-path "$LNX/arch/*" ! -path "$LNX/arch/i386*" -prune -o               \
-path "$LNX/include/asm-*" ! -path "$LNX/include/asm-i386*" -prune -o \
-path "$LNX/tmp*" -prune -o                                           \
-path "$LNX/Documentation*" -prune -o                                 \
-path "$LNX/scripts*" -prune -o                                       \
-path "$LNX/drivers*" -prune -o                                       \
-name "*.[chxsS]" -print >/bak/linux/linux-2.6/cscope/cscope.files
2, 创建索引数据库
cd /bak/linux/linux-2.6/cscope
3, 使用索引数据库
cscope -d




搭建基于qemu + eclipse的kernel调试环境(by quqi99)

标签:

原文地址:http://blog.csdn.net/quqi99/article/details/50640902

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!