免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 1316 | 回复: 0
打印 上一主题 下一主题

一种比较方便的调试内核的方法 [复制链接]

论坛徽章:
2
丑牛
日期:2013-09-29 09:47:222015七夕节徽章
日期:2015-08-21 11:06:17
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2008-03-20 17:23 |只看该作者 |倒序浏览
原理概述
所谓调试,这里指的是debug,是系统有问题需要查找问题原因。怎么查找问题呢,最简单的办法,看看运行在某几个时刻的系统是什么状态,这些状态是怎么
转换的,为什么有问题,改改状态看有什么效果。那么什么是系统的状态呢,我认为比较土的说,就是cpu的状态(比如寄存器的状态),
内存
的状态(比如一些
变量的状态)。所以,简单的说,土土的说,调试,debug,就是在系统运行的时候查看(修改)系统状态。debug的方法,最简单的就是print,这
是最有效最直接的方法,不过,如果想多看几个状态,那就要添加代码,编译,重新运行,很繁琐。比较简洁的方法是使用类似gdb的工具,在运行时按照实际需
要查看各个状态。
对于运行在虚拟机上的系统,我们有机会通过虚拟机提供的接口查看整个虚拟机的状态,自然包括运行的系统的状态,比如,
QEMU
与VMware都提供了这种接口,他们接口对外通信的协议是gdb的远程调试协议。
GDB的远程调试
具体的协议内容可以通过 info gdb 在Remote Protocol部分找到。简单的说,这个协议主要提供了查看(修改)寄存器(内存)等方法。 gdb通过这个协议获得(修改)运行时被调试系统的状态。通过这个协议与gdb合作的另一端称之为gdbstub。
虚拟机内置的gdbstub
QEMU与VMware通过内置的gdbstub与gdb通信,从而我们可以在系统的运行时通过gdb来查看(修改)系统的状态,而且,gdb可以进行源码级的调试,那么,日子就更好过了。
优点
在理想状态下,如果虚拟机没有bug(当然是不可能的),我们通过gdb能像调试普通的应用程序那样调试
内核
,还是源码级的,方便,明了。实际上,虽然现
在QEMU对gdbstub的支持一塌糊涂(VMware没实际尝试过),但是,我们仍然能享受到部分的方便,比如,部分源码级的调试(设置断点,查看结
构体内容,局部变量内容等),如果内核没有打开中断,我们还可以单步执行,等等。
操作步骤安装QEMU

root
用户到/usr/ports/qemu-devel 执行
make
install就可以了。
ports
中的qemu对amd64下的gdbstub是不支持的,但是cvs中最新的代码看上去已经支持amd64,所以,如果想用来调试
amd64系统,最好先make patch然后把cvs上的部分代码合并进来,然后make
install。合并的代码不多,在gdbstub.c中cpu_gdb_read_registers函数内。因为这么做不能保证一定工作,所以这里不
详细介绍。而且,随着ports更新,这个工作应该以后就不需要了。
建立用于调试的基本系统与内核
首先找到你的代码树,比如,我们在 /mnt/fb1/oskernel/fbcur/src
下保存最新代码,确定编译时的中间文件放到/mnt/fb1/cross-dev/fbcurobjs/
最后的系统在/mnt/fb1/fbcurmin/
(注意,这里的目录只是用于举例,你可以自由选择目录结构),那么首先buildworld,虽然我的pc是amd64但是因为qemu支持的问题,我希
望调试i386系统,所以我用下面命令来buildworld
$exportMAKEOBJDIRPREFIX=/mnt/fb1/cross-dev/fbcurobjs
$ makeTARGET=i386DESTDIR=/mnt/fb1/fbcurmin buildworld
$ makeTARGET=i386DESTDIR=/mnt/fb1/fbcurminKERNCONF=VBOX buildkernel
$ su
Password:
# makeTARGET=i386DESTDIR=/mnt/fb1/fbcurmin installworld
# makeTARGET=i386DESTDIR=/mnt/fb1/fbcurminKERNCONF=VBOX installkernel
其中VBOX是我的内核配置文件,这是第一次,所以总是痛苦一些

以后只是修改内核编译内核就不必如此麻烦了。下面我们需要把这个基本系统
安装
到虚拟机里。
建立一个虚拟机用的
硬盘
,大小先用1G吧
$cd/mnt/fb1
$ qemu-img create dbgfbsd.img 1024M
初始化这个虚拟硬盘
按照handbook地说明在这块虚拟硬盘上用虚拟机装好一个基本系统,然后可以直接更新虚拟硬盘上的文件
# mdconfig -a -t vnode -f dbgfbsd.img
md0
# mount /dev/md0s1a /mnt/tmp
下面我们可以开始了,运行QEMU,注意 -s 参数 然后开始调试
调试步骤$cd/mnt/fb1/cross-dev/fbcurobjs/i386/mnt/fb1/oskernel/fbcur/src/sys/VBOX/
$ gdb kernel.debug
GNU gdb6.1.1[
FreeBSD
]
Copyright2004Free 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 warrantyforGDB.  Type"show warranty"fordetails.
This GDB was configured as"amd64-marcel-freebsd"...
(gdb)target remote amd64box:1234
Remote debugging using amd64box:1234
pmap_pte_quick(pmap=Variable"pmap"is not available.
)at /mnt/fb1/oskernel/fbcur/src/sys/i386/i386/pmap.c:947
947if(PMAP1cpu != PCPU_GET(cpuid)){
warning: Unable to find dynamic linker breakpointfunction.
GDB will be unable to debug shared library initializers
and track explicitly loaded dynamic code.
warning: shared library handler failed toenablebreakpoint
(gdb)bt
#0pmap_pte_quick(pmap=Variable"pmap"is not available.
)at /mnt/fb1/oskernel/fbcur/src/sys/i386/i386/pmap.c:947
#10xc072a3e1inpmap_copy(dst_pmap=0xc16cf08c,src_pmap=0xc16d008c,dst_addr=135081984,len=135168,src_addr=135081984)
at /mnt/fb1/oskernel/fbcur/src/sys/i386/i386/pmap.c:2856
#20xc06d8465invmspace_fork(vm1=0xc16d0000)at /mnt/fb1/oskernel/fbcur/src/sys/vm/vm_map.c:2530
#30xc04f70aainfork1(td=0xc16ce000,flags=Variable"flags"is not available.
)at /mnt/fb1/oskernel/fbcur/src/sys/kern/kern_fork.c:280
#40xc04f85a9infork(td=0xc16ce000,uap=0xc7b21cfc)at /mnt/fb1/oskernel/fbcur/src/sys/kern/kern_fork.c:94
#50xc072d943insyscall(frame=0xc7b21d38)at /mnt/fb1/oskernel/fbcur/src/sys/i386/i386/trap.c:1008
#60xc0713cc0inXint0x80_syscall()at /mnt/fb1/oskernel/fbcur/src/sys/i386/i386/exception.s:196
#70xc7b21d38in??()
#80x0000003bin??()
#90x0000003bin??()
#100x0000003bin??()
#110x08049db0in??()
#120xbfbfee24in??()
#130xbfbfe9b8in??()
#140xc7b21d64in??()
#150x00000040in??()
#160x080c33f8in??()
#170x00000002in??()
#180x00000002in??()
#190x0000000cin??()
#200x00000002in??()
#210x08054543in??()
#220x00000033in??()
#230x00080286in??()
#240xbfbfe8ecin??()
#250x0000003bin??()
#260x00000000in??()
#270x00000000in??()
#280x00000000in??()
#290x00000000in??()
#300x07c9a000in??()
#310x00000000in??()
#320xc16ce000in??()
#330xc7b21adcin??()
#340xc7b21aa8in??()
#350xc16ce1e4in??()
#360xc0533cbbinsched_switch(td=0xbfbfeed8,newtd=Variable"newtd"is not available.
)at /mnt/fb1/oskernel/fbcur/src/sys/kern/sched_ule.c:1902
Previous frame inner to this frame(corrupt stack?)
(gdb)q
The program is running.  Exit anyway?(y or n)y
虽然我用amd64上面的gdb来调试i386的系统看上去是work的,但是我不确定这样是否可靠,请达人告知。
下次我只是修改了一点内核,编译那么多岂不是浪费,我们这样做
exportMAKEOBJDIRPREFIX=/mnt/fb1/cross-dev/fbcurobjs/
cd/mnt/fb1/oskernel/fbcur/src
make buildkernelKERNCONF=VBOXTARGET=i386DESTDIR=/mnt/fb1/fbcurmin -DNO_KERNELCLEAN -DNO_KERNELCONFIG -DNO_KERNELDEPENDNO_MODULES=1
然后直接把得到的kernel拷贝到虚拟机里面就可以了
存在的问题
理论上说,这种调试方法是很完美的,可惜天公不作美,好事多魔,这种方法并非太可靠,而且存在很多问题,下面粗略列举几种。总之,这种调试方法只能算作借鉴,辅助,当你发现了问题,或者解决了问题时,除了在虚拟机上测试通过,还要在真实环境中通过。
虚拟机存在bug
某人曾说,人类之所以区别动物是因为会使用工具,又有古人云,君子生非异也,善假于物也。然而,倘使你使用的工具存在问题,对你的伤害可能比不使用工具更
加严重。QEMU存在各种严重的bug,或者说还不成熟稳定,在前面的版本中(现在cvs版没有尝试)对于i386下的double-fault的反应是
自己死掉,所以,如果代码会产生double-fault就无法调试;再比如,直到最近不久,gdbstub才支持amd64,而ports中的版本还不
支持;再比如,如果没有关闭中断,那么单步中断总是进入中断处理函数,等等
虚拟环境与真实环境的差异
虚拟环境与真实环境有许多差别,最明显的大概是中断,比如时钟中断等。另外,出于性能的考虑,有些虚拟机可能对硬件的模拟并不全面,仅仅是模拟常用的功能。所以有些在真实机器上运行很好的代码死在虚拟机上是正常的。
MP 的支持
对这部分了解不深,期待达人补充。简单的说,对于虚拟机调试是否支持MP我抱怀疑态度,而且,我确实遇到过代码在真实MP机器上运行的很好而在虚拟机上而没有效果的事情,不管是否进行调试。
               
               
               

本文来自ChinaUnix博客,如果查看原文请点:http://blog.chinaunix.net/u/4206/showart_501237.html
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP