1. 使用qemu来调试FreeBSD系统内核
为了方便给qemu虚拟机来拷贝编译完后的内核文件,可以使用bochs的bximage来创建一个镜像文件,但要注意的是bximage创建的Flat模式的镜像文件只能有2G的大小。使用Flat模式的镜像文件有一个好处,可以直接通过mdconfig和mount命令来把对应的虚拟机镜像文件挂载到指定的目录下,然后进到虚拟机的boot目录替换内核。Qemu和bochs建议从Port中安装,可以选择安装kqemu来加速,有需要其他配置的同学请运行make config来进行相应的配置,不过一般Port中都是已经给出了一个比较合理选项。
1.1. 准备工作
安装完qemu和bochs并利用bximage来创建虚拟机镜像文件后,使用qemu的下面这些选项来运行虚拟机,给创建的虚拟机安装操作系统。
-hda 指定虚拟机镜像文件
-cdrom 指定要使用的光驱或者ISO文件
-enable-kqemu 使用kqemu
-kernel-kqemu 使用kqemu来进行虚拟加速
-localtime 虚拟机中的时间和本地时间相同
-boot once=d 只在第一次引导的时候使用CDROM
-s 等待gdb连接进来,-s会开放1234这个端口,方便gdb使用remote target的方式来进行远程调试
-m 指定虚拟机需要的内存
-cpu 指定虚拟机要使用的CPU种类,-cpu ?只有在配置完所有的-hda之类的参数之后才会打印出qemu支持的CPU类型,否则的话只会报错。
-M 指定虚拟机要使用的PC类型,-M ?的处理和-cpu ?一样。
-k 使用的语言,这个选项也要影响到键盘的设置。一般建议选择en-us。不选定该选项可能会导致qemu在运行时按键不匹配,我在通过XShell远程FreeBSD8.1时,如果不指定该项,则Enter键之类的无法生效。
我使用的qemu的参数为:
qemu -k en-us -cpu coreduo -boot once=d -m 256M -localtime -kenerl-kqemu -enable-kqemu -hda hd.img -cdrom ../ISO/FreeBSD-8.1-RELEASE-i386-disc1.iso |
如果运行时报没有加载kqemu,则手动加载一下:
1.2. 挂载虚拟机文件
用bochs创建hd.img并用qemu来装完操作系统之后,在FreeBSD中可以使用mdconfig和mount来挂载相应的文件。首先我们先用mdconfig来创建一个md设备:
上面这条命令会创建vnode类型的md设备,命令会返回创建后的设备名(如md0之类)。直接用ls /dev/md0*来查找,可以看到以FreeBSD的Slice来进行区分的文件:
sudo mdconfig -a -t vnode -f hd.img |
根据我在安装FreeBSD操作系统时进行挂载点划分,一共有md0s1[a-f]个设备文件,我把md0s1f划分为/usr挂载点,下面用mount命令来挂载md0s1f:
> ls /dev/md0* /dev/md0 /dev/md0s1 /dev/md0s1a /dev/md0s1b /dev/md0s1d /dev/md0s1e /dev/md0s1f |
用ls命令可以查看到usr/下面的内容:
sudo mount /dev/md0s1f usr/ |
在进行内核调试的时候,我们最需要的是挂载/boot目录下的数据,方便我们拷贝编译后的内核文件,因此上面的命令只作为参考,根据大家自己不同的挂载点划分来mount相应的设备。
1.3. 编译内核文件
进入/usr/src/sys/i386/conf,拷贝并重命名GENERIC内核配置文件为DebugOS,在里面加入
makeoptions DEBUG=-g options DDB options GDB options KDB |
然后在
/usr/src下执行
make buildkernel KERNCONF=DebugOS
进行编译即可。编译后的内核文件会在/usr/obj目录中。拷贝相应的内核文件到虚拟机中的boot目录。Unmount掉相应的虚拟机挂载目录后,准备进行内核调试。
1.4. 开始调试
在qemu的参数中增加-s选项,该选项会让qemu开启1234的tcp端口,并等待gdb连接上来。运行qemu后,可以再运行gdb,通过target remote 127.0.0.1:1234命令来连接qemu虚拟机,然后就可以以源代码级的方式来跟踪内核了。需要跟踪系统调用的同学,可以直接在虚拟机上写个程序,然后用GDB来跟踪系统调用的处理。