Linux 内核调试4-Qemu调试Linux内核

通过UML可以方便的在本机调试Linux内核,UML是一种特殊的虚拟机,另外一种更为灵活的虚拟机是Qemu,Qemu是一种完全仿真虚拟机, 可以在i386平台仿真任意其他处理器构架,而且支持GDB调试,这里尝试一下使用Qemu调试Linux内核,Qemu参数-kernel可以直接指定 内核启动,这与UML有相似之处。

首先需要编译安装Qemu,这里并没有什么疑惑之处,直接从官方网站下载源码,使用Linux最常用的编译命令即可:

# 默认选项会编译所有处理器构架虚拟机 # 可以 ./configure --help 查看编译特定平台的配置 cpp@dark:~/qemu-0.12.4$ ./configure --target-list=i386-softmmu cpp@dark:~/qemu-0.12.4$ make cpp@dark:~/qemu-0.12.4$ make install

接下来以默认选项编译内核,不过巨崩溃的是内核默认没有DEBUG_INFO选项,所以虽然能在导出符号部分断下来,但是没有源码,所以需要选则Compile the kernel with debug info选项。

# 默认选项 cpp@dark:~/linux-2.6.34$ make defconfig # 配置菜单,选择调试信息 cpp@dark:~/linux-2.6.34$ make menuconfig # 编译内核 cpp@dark:~/linux-2.6.34$ make

然后使用Qemu加载内核启动

cpp@dark:~/linux-2.6.34$ qemu -s -S -kernel arch/x86/boot/bzImage -hda rootfs.img -append "root=/dev/sda" # 其中一些选项的解释如下 # -s 监听tcp:1234端口以等待GDB连接 # -S 虚拟机启动后停止,以便GDB连接后调试启动过程 # -kernel 压缩内核 # -hda 硬盘 # -appand 启动参数

这里系统很容易启动不了,如果系统由于VFS加载错误无法启动,首先尝试启动参数root=/dev/sda为root=/dev /hda,hda是IDE硬盘标识,sda为SCSI硬盘,这要看内核识别成哪种,如果仍然不行,那要检测rootfs.img根文件系统的格式跟内核所 支持的格式是否匹配,2.6.34支持ext3格式,如果格式错误,可以利用 Linux 内核调试1 里的方法,自己手工创建一个ext3格式的文件,然后mount到临时文件,把其他根文件系统全部拷贝进去即可。

这 样启动Qemu之后,发现系统一片黑屏,这里因为Qemu启动参数被设置为禁止,Qemu本身具有显示窗口和控制窗口,利用 Ctrl+Alt+2 进入控制台,c命令继续虚拟机,Ctrl+Alt+1 返回显示窗口,Qemu的控制台可以控制很多选项,从这点来看要比VMware等要灵活一些,UML本身也支持运行时控制。

接下来使用GDB启动虚拟机,当系统停止在启动之后时,用GDB加载:

# 启动GDB,GDB加载未压缩内核 cpp@dark:~/linux-2.6.34$ gdb vmlinux GNU gdb 6.8 Copyright (C) 2008 Free Software Foundation, Inc. License GPLv3+: GNU GPL version 3 or later This is free software: you are free to change and redistribute it. There is NO WARRANTY, to the extent permitted by law. Type "show copying" and "show warranty" for details. This GDB was configured as "i486-slackware-linux"... (gdb) # 设置断点 (gdb) br start_kernel Breakpoint 1 at 0xc172f5d4: file init/main.c, line 533. # 连接Qemu监听端口1234 (gdb) target remote localhost:1234 Remote debugging using localhost:1234 [New Thread 1] 0x0000fff0 in ?? () # 继续Qemu虚拟机执行 (gdb) c Continuing. # 内核解压之后很快便到达断点 Breakpoint 1, start_kernel () at init/main.c:533 533 smp_setup_processor_id(); (gdb) # 接下来便可任意调试内核 (gdb) list 528 asmlinkage void __init start_kernel(void) 529 { 530 char * command_line; 531 extern struct kernel_param __start___param[], __stop___param[]; 532 533 smp_setup_processor_id(); 534 535 /* 536 * Need to run as early as possible, to initialize the 537 * lockdep hash: (gdb)

Qemu由于是完全仿真实现,所以可以在任意平台调试其他构架内核,理论上甚至可以在Windows平台交叉编译Linux内核,再去由Qemu加载调试(交叉编译比较麻烦,需要先编译目标构架的binutil,而后链接内核)。

相关系列文章:
Linux 内核调试1-UML
Linux 内核调试2-UML调试内核
Linux 内核调试3-UML网络配置
Linux 内核调试4-Qemu调试Linux内核
Linux 内核调试5-UML和Qemu调试模块
Linux 内核调试6-使用KGDB双机调试

linux

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:http://www.heiqu.com/994417a8ac1bf779535e77eb792058a1.html