- 论坛徽章:
- 0
|
通过串口调试FreeBSD内核的操作示例
这个示例使用的是Windows vmware里的两台虚拟FreeBSD机器,演示通过串口调试FreeBSD内核的操作过程。内核版本为FreeBSD6.1。
1、调试环境的搭建
首先是在vmware里面安装两台FreeBSD机器,并通过用命名管道模拟的“串口”将这两台机器连接起来,具体设置方法请参见vmware随机文档的“Connecting Two Virtual Machines ”一节。
2、FreeBSD调试内核的编译
两台虚拟FreeBSD机器分别作为调试机和目标机。
(1)在调试机上构建自己的内核配置文件,假设名字为DEBUG_KERNEL:
- #cd /usr/src/sys/i386/conf
- #mkdir /root/kernels
- #cp GENERIC /root/kernels/DEBUG_KERNEL
- #ln -s /root/kernels/DEBUG_KERNEL
复制代码
(2)在调试机上编辑上述内核配置文件:
在配置文件中加入以下选项:
- makeoptions DEBUG=-g
- options KDB
- options KDB_TRACE
- options DDB
- options GDB
复制代码
(3)在调试机上编译调试内核:
- #/usr/sbin/config DEBUG_KERNEL
- #cd ../compile/DEBUG_KERNEL
- #make cleandepend
- #make depend
- $make
复制代码
(4)完成上述步骤之后,在调试机的当前目录(/usr/src/sys/i386/compile/DEBUG_KERNEL/)目录下就会生成kernel.debug文件。把这个文件拷贝到目标机上,放到/boot/kernel/目录下,更名为kernel,并使用strip -x去掉其中的调试符号。
3、完成调试机和目标机的远程连接
(1)编辑目标机的/boot/device.hints文件,找到0号串口标志对应的行,为其增加0x80标志,修改后该行如下:
(2)另外,我所使用的FreeBSD6.1版本在进入DDB模式之后会失去键盘响应,这是由于DDB和kbdmux(4)共存还有问题。如果出现这一情况,解决办法是在目标机的/boot/device.hints文件中添加如下这一行:
- hint.kbdmux.0.disabled="1"
复制代码
(3)重启目标机,在启动菜单中选择以下这一项:
- 6. Escape to loader prompt
复制代码
然后在“OK”提示符后输入boot -d :
- Type '?' for a list of commands, 'help' for more detailed help.
- OK boot -d
复制代码
这时就会出现如下画面:
然后再依次输入“gdb”和“s”命令,使其进入等待远端gdb调试连接的状态。
( 4 )在调试机上,输入下述命令:
- #kgdb -r /dev/cuad0 kernel.debug
复制代码
稍等片刻,gdb就会完成和远端目标机的链接,出现如下画面:
- # kgdb -r /dev/cuad0 kernel.debug
- [GDB will not be able to debug user-mode threads: /usr/lib/libthread_db.so: Undefined symbol "ps_pglobal_lookup"]
- GNU gdb 6.1.1 [FreeBSD]
- Copyright 2004 Free Software Foundation, Inc.
- GDB is free software, covered by the GNU General Public License, and you are
- welcome to change it and/or distribute copies of it under certain conditions.
- Type "show copying" to see the conditions.
- There is absolutely no warranty for GDB. Type "show warranty" for details.
- This GDB was configured as "i386-marcel-freebsd".
- Switching to remote protocol
- kdb_enter (msg=0x2a "") at ../../../kern/subr_kdb.c:270
- 270 }
- #0 kdb_enter (msg=0x2a "") at ../../../kern/subr_kdb.c:270
- 270 }
- (kgdb)
复制代码
4、开始调试
现在我们在调试机上用bt命令就可以看到之前的调用序列:
- (kgdb) bt
- #0 kdb_enter (msg=0x2a "") at ../../../kern/subr_kdb.c:270
- #1 0xc0843e92 in init386 (first=12734464) at ../../../i386/i386/machdep.c:2192
- #2 0xc0446ded in begin () at ../../../i386/i386/locore.s:339
- (kgdb)
复制代码
再设个断点试试。选择虚拟映射初始化函数vm_map_init(),设置断点,继续运行,我们就可以看到程序停止在了该函数处。然后继续使用了gdb的bt、s、list命令来测试查看调用栈、单步运行和列出源代码的功能。效果如下:
- (kgdb) b vm_map_init
- Breakpoint 1 at 0xc07c5203: file ../../../vm/vm_map.c, line 525.
- (kgdb) c
- Continuing.
- [New Thread 0]
- [Switching to Thread 0]
- Breakpoint 1, vm_map_init (map=0xc098b3c0, min=0, max=3217031168) at ../../../vm/vm_map.c:525
- 525 _vm_map_init(map, min, max);
- (kgdb) bt
- #0 vm_map_init (map=0xc098b3c0, min=0, max=3217031168) at ../../../vm/vm_map.c:525
- #1 0xc0628120 in proc0_init (dummy=0x0) at ../../../kern/init_main.c:430
- #2 0xc0627d6e in mi_startup () at ../../../kern/init_main.c:208
- #3 0xc0446df5 in begin () at ../../../i386/i386/locore.s:348
- (kgdb) s
- _vm_map_init (map=0xc098b3c0, min=3231233212, max=3231233212) at ../../../vm/vm_map.c:512
- 512 map->header.next = map->header.prev = &map->header;
- (kgdb) list
- 507 */
- 508 static void
- 509 _vm_map_init(vm_map_t map, vm_offset_t min, vm_offset_t max)
- 510 {
- 511
- 512 map->header.next = map->header.prev = &map->header;
- 513 map->needs_wakeup = FALSE;
- 514 map->system_map = 0;
- 515 map->min_offset = min;
- 516 map->max_offset = max;
- (kgdb)
复制代码
现在,我们再来看看目标机的输出信息:
从图中我们可以看到,在遇到了vm_map_init()函数处的断点之后,目标机暂停在了系统初始化过程中。因此,通过这种方式,我们从系统初始化的时候就可以开始内核调试了。
[ 本帖最后由 雨丝风片 于 2006-9-4 13:24 编辑 ] |
|