form : http://www.oldlinux.org/oldlinux/viewthread.php?tid=4352
这是我写的linux-0.11调试向导,其中有个文件
linux-0.11-debug.tar.gz是在赵博的linux-0.11-040327-rh9.tar.gz基础上修改的
,专门用来调试内核。
Linux 0.11调试向导
Harold Lee
Last Updated: 2005-11-2
一、介绍
赵炯的《Linux内核完全注释》对于想要学习内核的人来说,是本非常好的入门书。但是对于内核这样的系统软件,只是限于看书还远远不够,要想进一步提高,就必须得亲自调试内核。好在所需的工具都有了,现在就只剩下如何把这些工具组合起来,搭建一个调试系统,本文旨在帮助读者达到这个目地。
二、需要的东西
* 赵炯的《Linux内核完全注释》这本书是必需的,纸版或电子版的都可以。电子版可以到以下地址下载http://oldlinux.org/download/clk011c-1.9.5.pdf
oldlinux论坛也是个好地方,可以得到赵博的亲自指点,而且也有很多内核爱好者可以共同讨论。
http://www.oldlinux.org/cgi-bin/leoboard.cgi
* wxWindows-2.4.2
这是一个图形库,因为bochs对于X的支持不如对wxwindows的支持,为了能够顺利编译bochs,所以还是需要它。本文所使用的版本需为 2.4.2或以上。下载地址:
* bochs-2.2:
一个能完全仿真x86的软件,本文所需版本为2.2或以上。
http://oldlinux.org/Linux.old/bochs/bochs-2.2/bochs-2.2.tar.gz
* linux-0.11的bochs image文件。
http://oldlinux.org/Linux.old/bochs/linux-0.11-devel-040923.zip
* 用于调试的linux-0.11
http://oldlinux.org/Linux.old/bochs/linux-0.11-debug.tar.gz
* Linux分发版本
基于你所在的平台,可以分为linux平台和windows平台,本文讨论 linux平台下的搭建。
linux平台先找一个目前流行的任何一个linux分发版本,记住把所有的开发包都装上。
三、编译
本节假设您都是在当前家目录下,解包,编译,安装。
(1)wxWindows
1. 解包
如果正常下载,应该会得到一个类似wxGTK-2.4.2.tar.bz2这样的包,通过下列命令解开它:
tar xvfj wxGTK-2.4.2.tar.bz2
在你的家目录下会有一个wxGTK-2.4.2的目录
2. 配置
进入刚解开的wxGTK-2.4.2目录,按照以下命令配置
./configure –prefix=/usr –with-gtk
3. 编译
接着在当前目录下运行这个命令:
make
4. 安装
首先切换到root用户下,如果你已经是root则不用切换,切换命令为:
su
输入你的root密码就可以切换到root用户下了。然后输入命令:
make install
你的wxWindows就安装好了。
(2)bochs
虽然bochs也提供已编译好的包,但是本文推荐自己编译。因为需要编译两个不同版本,后面会用到。编译bochs可能会遇到各种不同的问题,本文尽量把所有问题都交待清楚,以便您一次就能编译成功。
1. 解包
如果你按照正常下载,应该会获得一个名字为bochs-2.2.tar.gz的软件包,通过以下命令解开:
tar xvfz bochs-2.2.tar.gz
接着在你的家目录下就会有个bochs-2.2的目录了。
2. 配置
进入你刚才解开的bochs-2.2目录,在这个目录下,你会看到一个名叫configure的脚本文件,这个是unix世界软件包的标准配置文件。如何使用它,可以通过以下命令查看所有的配置选项:
./configure –help
这样你会得到一份详细的配置选项清单。本文打算编译两份不同的配置的版本。
第一个的版本为使用bochs自带的内部调试器。配置命令为
./configure –prefix=/opt/bochs/debug –with-wx –without-x –enable-plugins \
–enable-debugger –enable-disasm
配置注释:
* –prefix=/opt/bochs/debug
这个选项的意思是软件将被安装到哪个目录下
* –with-wx
这个选项的意思是使用wxWindows图形库,用作bochs的gui。
* –without-x
这个选项的意思是不要使用X图形库
* –enable-plugins
这个选项是必须要的
* –enable-debugger
这个选项是打开bochs的自带调试器
* –enbale-disasm
这个选项允许反汇编
3. 编译
接着在当前目录下运行命令:
make
4. 安装
首先切换到root用户下,如果你已经是root则不用切换,切换命令为:
su
输入你的root密码就可以切换到root用户下了。然后输入命令:
make install
这样你的bochs自带调试器的版本就编译好了。用以下命令作一个符号链接
ln -s /opt/bochs/debug/bin/bochs /usr/bin/bochsdbg
第二个版本为使用gdb-stub的版本
1. 清理
在配置第二个版本之前,需要把刚才编译的东西清理掉,输入以下命令:
make clean
2. 配置
然后配置,配置命令为
./configure –prefix=/opt/bochs/gdbstub –with-wx –without-x \
–enable-plugins –enable-disasm –enable-gdb-stub
配置注释:
* –enable-gdb-stub
这个选项打开gdb stub支持
* 其他选项同上,注意这个不同版本会安装到不同的目录下。
3. 编译
接着在当前目录下运行命令:
make
4. 安装
切换到root用户下,如果你已经是root则不用切换,切换命令为:
su
输入你的root密码就可以切换到root用户下了。然后输入命令:
make install
这样你的bochs使用外部调试器gdb的版本就编译好了。用以下命令作一个符号链接
ln -s /opt/bochs/gdbstub/bin/bochs /usr/bin/bochs
四、环境的搭建
(1). bochs的配置
使用bochs,还需要相应的image文件,linux-0.11-devel- 040923.zip这个包提供了我們需要的image文件,把这个包解开。会有一个linux-0.11-devel-040923目录产生,进入这个目录,因为里面的bochs配置文件是基于windows平台的,要想在linux平台用,还需要修改。输入以下命令:
find -name ‘*.bxrc’ | xargs sed -i -e ‘s@\(.*romimage.*\)\\\(.*\)@\1/\2@’ -e ‘s@^vgaromimage: \(.*\)@vgaromimage: file=\1@’
cp bochsrc-fdb.bxrc bochsrc-debug.bxrc
sed -i ‘s@\(^floppya: 1_44=\).*\(, status=inserted\)@\1″linux/Image”\2@’ bochsrc-debug.bxrc
cp bochsrc-fdb.bxrc bochsrc-gdbstub.bxrc
sed -i ‘s@\(^floppya: 1_44=\).*\(, status=inserted\)@\1″linux/Image”\2@’ bochsrc-gdbstub.bxrc
在bochsrc-gdbstub.bxrc中添加一行:
gdbstub: enabled=1, port=1234, text_base=0, data_base=0, bss_base=0
(2). linux-0.11调试版本
进入linux-0.11-devel-040923目录解开linux-0.11-debug.tar.gz,输入以下命令:
tar xvfz ../linux-0.11-debug.tar.gz
会有一个linux目录产生,这是一个经过修改可以在当前linux环境下编译,产生可调试的linux 0.11
内核。进入该linux目录,输入命令:
make
就开始编译内核了。
到此为止,所有的搭建工作都已做完了,剩下的就是开始调试了。
五、调试内核
调试工作主要在linux-0.11-devel-040923这个目录下进行,有两种调试方法:
第一种:使用bochs自带的调试器调试,输入命令:
bochsdbg -f bochsrc-debug.bxrc
首先,选择Debug菜单中的Debug Console子菜单,然后选择Simulate菜单的Start子菜单。可以开始调试
第二种:使用外部调试器gdb调试,输入命令:
bochs -f bochsrc-gdbstub.bxrc
只需选择Simulate菜单的Start子菜单,它会提示
Waiting for gdb connection on localhost:1234
端口是基于你的bochs配置文件的设置,然后另开一个终端,进入linux目录下的debug目录,输入命令:
gdb system
进入gdb调试界面,首先设置断点,比如
(gdb) b main
Breakpoint 1 at 0x6631: file init/main.c, line 110
然后远程调试
(gdb) target remote localhost:1234
Remote debugging using localhost:1234
0x0000fff0 in sys_mkdir (pathname=0x0, mode=0) at namei.c:496
496 inode->i_mtime = inode->i_atime = CURRENT_TIME;
让程序跑起来
(gdb) c
Continuing.
Breakpoint 1, main () at init/main.c:110
110 ROOT_DEV = ORIG_ROOT_DEV;
OK,现在已经进入调试状态了。
在实际调试当中,常常需要把这两种方法结合起来,能够达到很好的效果。因为第一种方法非常直观所有的寄存器一目了然,
但是却是全汇编而且都单步的,对于内核后期的c语言文件,这样一步步走效率太低,所以需要第二种方法快速找到c语言文件
函数或语句的地址,然后在第一种方法中在该地址设置断点,可以直接跳到该地址执行,这样效率就高很多了。