​​

本机环境 Win7 + VMware 14 Pro

1.安装Qemu,Ubuntu包管理器中的二进制版本比较老了,这里选择源码安装​​2.12.0版本​​。

具体的安装教程可以参考这篇文章《​​QEMU 2.10.1 编译安装​​》,写的非常详细。

2.下载、编译目标的内核版本

这里下载的是4.4.1版本的Linux内核  ​​linux-4.4.1.tar.xz​

解压 编译


Kernel 内核调试【转】_desktop

xz - d   linux-4.4.1.tar.xz

tar -xvf linux-4.4.1.tar

cd linux-4.4.1

make menuconfig

Kernel 内核调试【转】_desktop


 确保以下三个选项是勾选上的:





1

2

3




​kernel hacking –> Kernel debugging​​​​kernel hacking –> Compile-​​​​time​​​​checks and compiler options –> compile the kernel with debug info​​​​kernel hacking –> Compile-​​​​time​​​​checks and compiler options -> compile the kernel with frame pointers​




 在多核平台上使用-j 参数来加快编译





1




​make​​​​-j​




3.制作根文件系统

先了解以下几个文件的区别,参考这篇​​文章​





1

2

3

4

5

6

7




​vmlinux 是ELF文件,即编译出来的最原始的文件。​


​vmlinuz 应该是由ELF文件vmlinux经过OBJCOPY后,并经过压缩后的文件​


​zImage 是vmlinuz经过​​​​gzip​​​​压缩后的文件,适用于小内核​


​bzImage 是vmlinuz经过​​​​gzip​​​​压缩后的文件,适用于大内核​




新建一个目录用于存放生成的内核文件,以及根文件系统:






1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19




​mkdir​​​​~​​​​/Desktop/kernel-debug​


​cp​​​​.​​​​/arch/x86/boot/bzImage​​​​~​​​​/Desktop/kernel-debug​


​cd​​​​~​​​​/Desktop/kernel-debug​


​dd​​​​if​​​​=​​​​/dev/zero​​​​of=rootfs.img bs=1M count=20  ​​​​#新建一个20M的文件​


​mkfs -t ext3 rootfs.img ​​​​#将其格式化为ext3文件系统格式​


​#将其mount 到新创建到目录rootfs上​


​mkdir​​​​rootfs​


​sudo​​​​mount​​​​-t ext3 -o loop rootfs.img rootfs​


​#将挂载后的根文件系统中建立基本的目录结构​


​sudo​​​​mkdir​​​​rootfs​​​​/dev​​​​rootfs​​​​/proc​​​​rootfs​​​​/sys​




给系统安装基本的命令行工具,比如ls,这里选择了BusyBox,下载的​​BusyBox源码​






1

2

3

4

5

6

7

8

9

10




​cd​​​​~​​​​/Desktop/kernel-debug​​​​<br>​​​​tar​​​​-jxvf busybox-1.28.3.​​​​tar​​​​.bz2<br>​​​​cd​​​​busybox-1.28.3<br>​​​​#进行配置,注意这里选择静态连接的方式生成可执行文件,避免对外部lib有依赖​​​​make​​​​menuconfig<br>​​​​#勾选Settings->Build Busybox as a static binary​​​​make​​​​-j​​​​#编译完成后,安装到目标的根文件系统中去,然后unmount掉根文件系统​​​​make​​​​install​​​​CONFIG_PREFIX=~​​​​/Desktop/kernel-debug/rootfs​​​​<br>​​​​sudo​​​​umount​​​​~​​​​/Desktop/kernel-debug/rootfs​






4.启动Qemu虚拟机




1




​sudo​​​​qemu-system-x86_64  -S -kernel ~​​​​/Desktop/kernel-debug/bzImage​​​​-hda ~​​​​/Desktop/kernel-debug/rootfs​​​​.img -append ​​​​"root=/dev/sda init=/bin/ash"​




此时启动的Qemu处于Pasued状态,单机黑色区域,让Qemu接收输入,按下ctrl+ alt + 2,切换到控制台。

注意之后可以通过ctrl + alt + G 来让qemu释放鼠标以及键盘输入。

Kernel 内核调试【转】_desktop_03

启动gdbserver,监听到8888端口,便于用GDB来远程调试。

Kernel 内核调试【转】_linux_04

5.使用GDB连接到gdbserver进行调试

由于GDB用的不太熟悉,这里使用图形化的调试工具DDD,可以通过以下命令安装:




1

2

3

4

5




​sudo​​​​apt-get ​​​​install​​​​ddd​​​​#切换到之前linux编译的目录​​​​cd​​​​linux-4.4.1​​​​#选择未压缩的内核文件,读入符号表​​​​ddd vmlinux​




在GDB命令处,连接到Qemu中的GDB server:target remote 127.0.0.1:8888,这个时候Qemu中的Linux系统是处于Paused状态的。

连接之后可以在菜单栏Status-->BackTrace...中看到堆栈信息。

Kernel 内核调试【转】_根文件系统_05

输入continue,让Qemu中的Linux系统运行起来,可以在Qemu中按下ctrl+Alt+1,切换到虚拟机的命令行界面,可以看到这个时候虚拟机已经正常运行起来了。

Kernel 内核调试【转】_根文件系统_06

这里对Linux创建进程的系统调用下断点,观察调用栈:

在fork.c文件中的_do_fork函数处下断点:

Kernel 内核调试【转】_desktop_07

切换到Qemu,使用ctrl+Alt+1回到Linux的控制台,运行ls,这时候shell会创建ls进程,这个时候ddd就会断下来了:

Kernel 内核调试【转】_根文件系统_08





【作者】​​张昺华​

​​

【新浪微博】 张昺华--sky


【微信公众号】 张昺华