利用bochs调试内核(主要是在windows下调试)
Bochs具有非常强大的操作系统内核调试功能。这也是本文选择Bochs作为首选实验环境的主要原因之一。有关Bochs调试功能的说明参见前面14.2节,这里基于Linux 0.11内核来说明Windows环境下Bochs系统调试操作的基本方法。
14.8.1 运行Bochs调试程序
我们假设Bochs系统已被安装在目录“C:\Program Files\Bochs-2.1.1\”中,并且Linux 0.11系统的Bochs配置文件名称是bochsrc-hd.bxrc。现在在包含内核Image文件的目录下建立一个简单的批处理文件run.bat,其内容如下:
"C:\Program Files\Bochs-2.1.1\bochsdbg" -q -f bochsrc-hd.bxrc
其中bochsdbg是Bochs系统的调试执行程序。运行该批处理命令即可进入调试环境。此时Bochs的主显示窗口空白,而控制窗口将显示以下类似内容:
C:\Documents and Settings\john1\桌面\Linux-0.11>"C:\Program Files\Bochs-2.1.1\bo
chsdbg" -q -f bochsrc-hd.bxrc
========================================================================
Bochs x86 Emulator 2.1.1
February 08, 2004
========================================================================
00000000000i[ ] reading configuration from bochsrc-hd.bxrc
00000000000i[ ] installing win32 module as the Bochs GUI
00000000000i[ ] Warning: no rc file specified.
00000000000i[ ] using log file bochsout.txt
Next at t=0
(0) context not implemented because BX_HAVE_HASH_MAP=0
[0x000ffff0] f000:fff0 (unk. ctxt): jmp f000:e05b ; ea5be000f0
<bochs:1>
此时Bochs调试系统已经准备好开始运行,CPU执行指针已指向ROM BIOS中地址0x000fffff0处的指令处。其中'<bochs:1>'是命令输入提示符,其中的数字表示当前的命令序列号。在命令提示符'<bochs:1>'后面键入'help'命令,可以列出调试系统的基本命令。若要了解某个命令的具体使用方法,可以键入'help'命令并且后面跟随一个用单引号括住的具体命令,例如:“help 'vbreak'”,如下面所示。
<bochs:1> help
help - show list of debugger commands
help 'command'- show short command description
-*- Debugger control -*-
help, q|quit|exit, set, instrument, show, trace-on, trace-off,
record, playback, load-symbols, slist
-*- Execution control -*-
c|cont, s|step|stepi, p|n|next, modebp
-*- Breakpoint management -*-
v|vbreak, lb|lbreak, pb|pbreak|b|break, sb, sba, blist,
bpe, bpd, d|del|delete
-*- CPU and memory contents -*-
x, xp, u|disas|disassemble, r|reg|registers, setpmem, crc, info, dump_cpu,
set_cpu, ptime, print-stack, watch, unwatch, ?|calc
<bochs:2> help 'vbreak'
help vbreak
vbreak seg:off - set a virtual address instruction breakpoint
<bochs:3>
为了让Bochs直接模拟执行到Linux的引导启动程序开始处,我们可以先使用断点命令在0x7c00处设置一个断点,然后让系统连续运行到0x7c00处停下来。执行的命令序列如下:
<bochs:3> vbreak 0x0000:0x7c00
<bochs:4> c
(0) Breakpoint 1, 0x7c00 (0x0:0x7c00)
Next at t=4409138
(0) [0x00007c00] 0000:7c00 (unk. ctxt): mov ax, 0x7c0 ; b8c007
<bochs:5>
此时,CPU执行到boot.s程序开始处的第1条指令处,Bochs主窗口将显示出“Boot From floppy...”等一些信息。现在,我们可以利用单步执行命令's'或'n'(不跟踪进入子程序)来跟踪调试程序了。在调试时可以使用Bochs的断点设置命令、反汇编命令、信息显示命令等来辅助我们的调试操作。下面是一些常用命令的示例:
<bochs:8> u /10 # 反汇编从当前地址开始的10条指令。
00007c00: ( ): mov ax, 0x7c0 ; b8c007
00007c03: ( ): mov ds, ax ; 8ed8
00007c05: ( ): mov ax, 0x9000 ; b80090
00007c08: ( ): mov es, ax ; 8ec0
00007c0a: ( ): mov cx, 0x100 ; b90001
00007c0d: ( ): sub si, si ; 29f6
00007c0f: ( ): sub di, di ; 29ff
00007c11: ( ): rep movs word ptr [di], word ptr [si] ; f3a5
00007c13: ( ): jmp 9000:0018 ; ea18000090
00007c18: ( ): mov ax, cs ; 8cc8
<bochs:9> info r # 查看当前CPU寄存器的内容
eax 0xaa55 43605
ecx 0x110001 1114113
edx 0x0 0
ebx 0x0 0
esp 0xfffe 0xfffe
ebp 0x0 0x0
esi 0x0 0
edi 0xffe4 65508
eip 0x7c00 0x7c00
eflags 0x282 642
cs 0x0 0
ss 0x0 0
ds 0x0 0
es 0x0 0
fs 0x0 0
gs 0x0 0
<bochs:10> print-stack # 显示当前堆栈的内容
0000fffe [0000fffe] 0000
00010000 [00010000] 0000
00010002 [00010002] 0000
00010004 [00010004] 0000
00010006 [00010006] 0000
00010008 [00010008] 0000
0001000a [0001000a] 0000
...
<bochs:11> dump_cpu # 显示CPU中的所有寄存器和状态值。
eax:0xaa55
ebx:0x0
ecx:0x110001
edx:0x0
ebp:0x0
esi:0x0
edi:0xffe4
esp:0xfffe
eflags:0x282
eip:0x7c00
cs:s=0x0, dl=0xffff, dh=0x9b00, valid=1
ss:s=0x0, dl=0xffff, dh=0x9300, valid=7
ds:s=0x0, dl=0xffff, dh=0x9300, valid=1
es:s=0x0, dl=0xffff, dh=0x9300, valid=1
fs:s=0x0, dl=0xffff, dh=0x9300, valid=1
gs:s=0x0, dl=0xffff, dh=0x9300, valid=1
ldtr:s=0x0, dl=0x0, dh=0x0, valid=0
tr:s=0x0, dl=0x0, dh=0x0, valid=0
gdtr:base=0x0, limit=0x0
idtr:base=0x0, limit=0x3ff
dr0:0x0
dr1:0x0
dr2:0x0
dr3:0x0
dr6:0xffff0ff0
dr7:0x400
tr3:0x0
tr4:0x0
tr5:0x0
tr6:0x0
tr7:0x0
cr0:0x60000010
cr1:0x0
cr2:0x0
cr3:0x0
cr4:0x0
inhibit_mask:0
done
<bochs:12>
由于Linux 0.11内核的32位代码是从绝对物理地址0处开始存放的,因此若想直接执行到32位代码开始处,即head.s程序开始处,我们可以在线性地址0x0000处设置一个断点并运行命令'c'执行到那个位置处。
另外,当直接在命令提示符下打回车键时会重复执行上一个命令;按向上方向键会显示上一命令。其他命令的使用方法请参考'help'命令。
14.8.2 定位内核中的变量或数据结构
在编译内核时会产生一个system.map文件。该文件列出了内核Image (bootimage)文件中全局变量和各个模块中的局部变量的偏移地址位置。在内核编译完成后可以使用前面介绍的文件导出方法把system.map文件抽取到主机环境(windows)中。有关system.map文件的详细功能和作用请参见2.10.3节。system.map样例文件中的部分内容见如下所示。利用这个文件,我们可以在Bochs调试系统中快速地定位某个变量或跳转到指定的函数代码处。
...
Global symbols:
_dup: 0x16e2c
_nmi: 0x8e08
_bmap: 0xc364
_iput: 0xc3b4
_blk_dev_init: 0x10ed0
_open: 0x16dbc
_do_execve: 0xe3d4
_con_init: 0x15ccc
_put_super: 0xd394
_sys_setgid: 0x9b54
_sys_umask: 0x9f54
_con_write: 0x14f64
_show_task: 0x6a54
_buffer_init: 0xd1ec
_sys_settimeofday: 0x9f4c
_sys_getgroups: 0x9edc
...
同样,由于Linux 0.11内核的32位代码是从绝对物理地址0处开始存放的,system.map中全局变量的偏移位置值就是CPU中线性地址位置,因此我们可以直接在感兴趣的变量或函数名位置处设置断点,并让程序连续执行到指定的位置处。例如若我们想调试函数buffer_init(),那么从system.map文件中可以知道它位于0xd1ec处。此时我们可以在该处设置一个线性地址断点,并执行命令'c'让CPU执行到这个指定的函数开始处,见如下所示。
<bochs:12> lb 0xd1ec # 设置线性地址断点。
<bochs:13> c # 连续执行。
(0) Breakpoint 2, 0xd1ec in ?? ()
Next at t=16689666
(0) [0x0000d1ec] 0008:0000d1ec (unk. ctxt): push ebx ; 53
<bochs:14> n # 执行下一指令。
Next at t=16689667
(0) [0x0000d1ed] 0008:0000d1ed (unk. ctxt): mov eax, dword ptr ss:[esp+0x8] ; 8b442408
<bochs:15> n # 执行下一指令。
Next at t=16689668
(0) [0x0000d1f1] 0008:0000d1f1 (unk. ctxt): mov edx, dword ptr [ds:0x19958] ; 8b1558990100
<bochs:16>
程序调试是一种技能,需要多练习才能熟能生巧。上面介绍的一些基本命令需要组合在一起使用才能灵活地观察到内核代码执行的整体环境情况。
Bochs使用简单教程
Bochs是一个开源的虚拟机。它可以实现vpc和vmware的大部分功能。你也可以像使用vmware一样的在Bochs里面安装操作系统。但是,由于它是全模拟的。所以,速度要远远慢于vmware.这样看来Bochs好像没有什么优势.是这样吗?在应用方面的确如此。
但是,在其他一个方面它是处于绝对优势的。那就是它具有调试功能!这是一个让人振奋的功能。这个功能在你调试操作系统或者其他一些在裸机上运行的程序时候,会让你有一种在写windows下运行的应用程序的感觉。有时候它是我们的救命稻草。没了它,也能活,但是肯定要糟糕的多。好了我们开始切入正题。
一、 配置Bochs
实际上配置Bochs是很简单的,为什么很多人不会配置呢?我觉的就是因为他使用和配置方式和普通程序不一样——配置文件。实际上配置文件是和ini文件、bat文件类似的。Bochs没有给我们提供图形界面的配置工具。这就需要我们自己来修改配置文件。
简单的配置就可以让你的操作系统在Bochs里面跑起来。用Bochs跑完整的linux和windows是不现实的。实在是太慢了。一般我们也只能把他当成调试器来使用。现在,我们先看一下如何让dos在他里面跑起来。如果你细心的话你会发现在Bochs文件夹里面有一个Bochsrc-sample.txt的文本文件。里面包含了所有了Bochs参数的信息。这个是官方的教程。可惜是英文的,而且我也没有找到有中文的教程(不然也没有我这篇文章)。在这里我们仅仅介绍最简单的配置选项。好了,废话就不多说了。我们现在就开始。
我们以一个例子来说明,这个例子是我用来跑dos以及我自己的小操作系统的。下面就是我们要用到的最基本的选项:
# 在一行的最前面加上“#”表示这一行是注释行。
# 内存,以MB为单位,对于dos来说最大可以访问16MB
# 的内存,所以我就给了他16MB,你可以根据自己的机器来调整
megs: 16
# 下面两句一般是不可以改的,至于干什么用的就不用我说
# 了。从他们的文件名就可以看出来。
romimage: file=../BIOS-Bochs-latest, address=0xf0000
vgaromimage: file=../VGABIOS-lgpl-latest
# 这个还用说吗?当然是软驱了,我想我们写操作系统肯定是先
# 把操作系统放在软盘(或映像)里面吧?在Bochs里面是可
# 以使用任意大小的软驱映像的。可以是1.44或2.88,我一般使
# 用2.88。还有就是Bochs里面可以使用两个软驱。不过好像
# 我们并不经常这样做。
floppya: 2_88=test.img, status=inserted
#floppyb: 1_44=floppyb.img, status=inserted
# 下面是硬盘,很简单,还有就是Bochs也是可以支持多个硬
# 盘的。那么,硬盘文件是怎么生成的呢?我们可以发现硬盘是
# img格式的。你注意没有在Bochs文件夹里有一个工具叫
# bximage.exe,我想你应该猜出来了。他就是用来生成这个硬盘
# 文件的工具。我在这儿还想说的是硬盘分三种格式的,最好选
#用growing类型。这种有一个好处就是节省硬盘空间,不过使用
#这种类型的硬盘还需要在下面加上mode = growing这个选项。
ata0: enabled=1, ioaddr1=0x1f0, ioaddr2=0x3f0, irq=14
ata0-master: type=disk, path="dos.img", cylinders=306, heads=4, spt=17
# 下面这个就是光驱,没什么好说的。如果你想使用物理光驱,
# 只要让path=E:(我们假设E盘是光驱)
ata0-slave: type=cdrom, path="dos.iso", status=inserted
# 这个是启动设备,可以使用cdrom(光驱)、c(硬盘)或floppy(软
# 驱)。
#boot: cdrom
boot: c
#boot: floppy
# 这一句可以不要,他只是指定用来保存日志的文件。如果不指定的
# 话他就会输出到命令控制台上。
log: Bochsout.txt
# 这一句是设置在开机时是否激活鼠标,Bochs对于鼠标的控制不是# 很好。建议如果不是特别需要的话不要激活他。在运行期间也可以点窗口右上角的鼠标图标来激活他。
mouse: enabled=0
以上这些设置就可以让你的DOS或自己的小操作系统在Bochs里面跑起来了。至于其他的一些高级支持,你可以查看Bochsrc-sample.txt里面的说明。不要害怕他,其实很简单。关键是抛弃恐惧。
二、 启动Bochs
配置文件已经写好了,硬盘文件等也都已经弄好了。那么我们如何来启动Bochs呢?很简单,你右击一下上面写的那个配置文件(例如myos.bxrc,注意:扩展名要是.bxrc。)选择“运行”或双击即可。不过我一般都不这样做,我一般是写一个批处理文件。
很简单,如下所示:
cd "d:\Bochs-2.2.1\dos"
..\Bochs.exe -q -f Bochsrc.bxrc
这样做的好处就是无论这个启动脚本放在哪儿都是可以使用的。那么,我们如何进入调试状态呢?下面我们就来讨论这个问题。
三、 调试功能
新建一个批处理文件,写入一下内容:
cd "d:\Bochs-2.2.1\dos"
..\Bochsdbg.exe -q -f Bochsrc.bxrc
运行这个批处理文件,你就可以进入调试状态了。不过你会发现,程序卡住了。没有想普通运行状态一样进入你的dos操作系统。为什么?因为调试在等待你的命令。你只有给他一个命令他才会继续。我们输入“c”,然后回车。是不是dos已经可是运行了?
如果没有运行说明你输入的窗口不对,你不会把c输入到那个没有光标的窗口了吧?如果真是那样我真是服了你了。真的!但是,dos运行起来了,如何在返回调试状态?很简单,按ctrl+c。什么你正在运行的程序被结束了?谁让你在操作系统窗口中按了,我是说在调试窗口按。至于哪个是调试窗口,哪个是操作系统窗口,我就不说了。如果你不知道你就干脆别使用Bochs了,也不要写什么程序了,更不要开发什么操作系统了。为什么?因为你不可能成功。从这儿就可以看出来。最好是找块豆腐撞死,这样你会很幸福的死去,不然你就会成为教育后代的典范——看到了吗XXX是怎么死的,笨死的。呵呵!开个玩笑。你真要不知道
千万不要来找我,找我我也不告诉你。不好意思,我也不知道。那么,在调试状态下我们可以干哪些事呢?你用过debug吗?它能做的Bochs都能做,它不能做的Bochs也可以做。下面就是一些常用的调试命令。
我最想告诉大家的是这个指令,因为他可以告诉我们一切。古语说:“授之以鱼,不若授之以渔”。我觉的很有道理。但是,有些人就是不想学这种一劳永逸的方法。所以,我还要继续写下去。
输入help,回车。你会得到以下信息:
help - show list of debugger commands
help 'command'- show short command description
-*- Debugger control -*-
help, q|quit|exit, set, instrument, show, trace-on, trace-off,
record, playback, load-symbols, slist
-*- Execution control -*-
c|cont, s|step|stepi, p|n|next, modebp
-*- Breakpoint management -*-
vb|vbreak, lb|lbreak, pb|pbreak|b|break, sb, sba, blist,
bpe, bpd, d|del|delete
-*- CPU and memory contents -*-
x, xp, u|disas|disassemble, r|reg|registers, setpmem, crc, info, dump_cpu,
set_cpu, ptime, print-stack, watch, unwatch, ?|calc
需不需要我翻译一下前两句?那好吧。
help - 现实调试命令列表
help '命令' - 显示某条命令的详细用法。
命令分为哪些?很明显,四类:调试控制,运行控制,断点管理,CPU和内存控制。我不想在这儿一一介绍了。没有必要,我只介绍一下最常用的就可以了。
c:继续,前面我们已经用过了。
s:单步执行。他还有一个扩展用法。
s n :执行n步。
b 0x7c00:在内存0x7c00处设置一个断点.当程序执行到0x7c00处就自动进入到调试状态.后面的这个数指的是内存的线性地址
。也可以使用10进制的数,但是好像没有人会这样做。
x /20 0x7c00: 以16进制的形式从内存的0x7c00开始显示20个字的数据。这个是很常用的命令,但是需要注意的是他的显示顺序和16进制编辑器中的显示顺序有一点小的区别。他的显示是以字为单位的,而且在字中是从低到高显示的.不过也没有什么大不了的。你只要稍微注意一下就可以了。
dump_cpu:这个是我最长用的三个指令之一。他的功能是显示现在的寄存器的状态,详细内容类似于:
eax:0x00000000, ebx:0x00000000, ecx:0x00000000, edx:0x00000683
ebp:0x00000000, esp:0x00000000, esi:0x00000000, edi:0x00000000
eip:0x0000fff0, eflags:0x00000002, inhibit_mask:0
cs:s=0xf000, dl=0x0000ffff, dh=0xff009bff, valid=1
ss:s=0x0000, dl=0x0000ffff, dh=0x00009300, valid=1
ds:s=0x0000, dl=0x0000ffff, dh=0x00009300, valid=1
es:s=0x0000, dl=0x0000ffff, dh=0x00009300, valid=1
fs:s=0x0000, dl=0x0000ffff, dh=0x00009300, valid=1
gs:s=0x0000, dl=0x0000ffff, dh=0x00009300, valid=1
ldtr:s=0x0000, dl=0x00000000, dh=0x00000000, valid=0
tr:s=0x0000, dl=0x00000000, dh=0x00000000, valid=0
gdtr:base=0x00000000, limit=0xffff
idtr:base=0x00000000, limit=0xffff
dr0:0x00000000, dr1:0x00000000, dr2:0x00000000
dr3:0x00000000, dr6:0xffff0ff0, dr7:0x00000400
cr0:0x00000010, cr1:0x00000000, cr2:0x00000000
cr3:0x00000000, cr4:0x00000000
u /20 0x7c00 :反汇编内存0x7c00处,反汇编的长度是20。你想不想知道dos的引导程序是什么样子的?执行一下这个命令就可以了。你还可以使用这样的命令 u /20 cs:0x120a,至于什么意思,我也不说了。
现在,我们已经介绍了6条命令了。够了。对于日常应用已经完全够用了。如果你想了解其他命令的用法只要执行一下help “命令名”就可以了(注意,命令上要带有引号)。好了。现在已经把Bochs的基本功能介绍完了。你是不是感觉Bochs很简单?对于简单的应用来说,确实如此。但是,想让他支持一些高级功能就有点麻烦了。毕竟它是全模拟的虚拟机,所以在有些方面实现起来并不容易。但是,向网络之类的功能还是可以支持的。你只要看一下Bochsrc-sample.txt就知道了。我在这儿就不说了。我还要说的是Bochs不仅仅可以调试操作系统,还可以调试dos下的程序。我们知道dos没有多少好的调试器。那么我们完全可以使用Bochs来调试。你知道在程序的开头输出一下程序的段地址和偏移地址,然后暂定一下,在虚拟机里面设置一下断点就可以了。我一般都是在在程序里面潜入一句汇编:
jmp $
这样在程序死循环的时候在调试窗口按下ctrl+c就可以看到他的段地址和偏移地址了。然后,在去掉这一句,设置一下断点,运行这个程序。是不是在指定位置中断了?
一:配置
bochs.exe是执行模式,不能调试的。Bochs的调试工具是Bochsdbg.exe。同样,调试的时候你仍然需要进行配置。此时如果我们还使用双击.bxrc配置文件的方法显然是不行的(因为此时会运行Bochs.exe而不是Bochsdbg.exe)。所以我copy了《自己动手写操作系统》作者于渊的方法——使用bat批处理文件。
新建一个批处理文件然后进行编辑。以下内容为我的bat文件:
D:\Develop\Bochs-2.2.1\bochsdbg.exe -q -f config.bxrc
显然,首先要指定调试程序的位置,后面 –q –f表示退出配置选择文件配置,后面的config.bxrc就是刚才运行Bochs所使用的配置文件。下面重点看看如何进行调试。
二:调试
感觉Bochs的调试和DOS提供的Debug很相似——毕竟都是命令行式的调试。如果有一个像TurboDebugger这样的可视化调试工具就好了。(这段文章也是我从网上copy下来的,最后总结为表格的形式,以方便以后查阅)
说明:下面的“[]”表示可有可无的参数在写的时候不要写。
执行控制命令
Help 帮助命令,以下的命令都可以通过help命令查到。
c 继续执行,遇到断点将停止
stepi [count] 执行count条指令, 默认为1条
si [count] stepi的缩写
step [count] 执行count条指令, 默认为1条
s [count] step的缩写
Ctrl-C 停止执行,返回命令行
Ctrl-D 执行完所有命令后,退出
quit 退出调试器
q quit缩写
设置断点
vbreak seg:off 在指定的虚拟地址(段+偏移)设置断点,在保护模式下也可以使用
vb seg:off
lbreak addr 在一个线性地址设置断点
lb addr
pbreak [*] addr 在一个物理地址设置断点
pb [*] addr
break [*] addr
b [*] addr
info break 显示所有断点状态
例如:
--------------------------------------
Num Type Disp Enb Address
1 pbreakpoint keep y 0x00007c00
表示在物理地址0x00007c00设置一个断点,该断点目前有效
---------------------------------------
delete n 删除一个断点
del n
d n
关于物理地址,线性地址和虚拟地址的区别,我只能凭我的理解简单说说,可能不准确。物理地址在什么时候都存在,但是在采用分页技术和虚拟内存技术后,你很难确定物理地址在那里,所以建议在实模式下采用物理地址和线性地址形式,这时候物理地址和线性地址其实是一致的。最常用的,比方说,计算机启动后的地址是0xfff0:0000,装载BIOS,然后转移到0x07C0:0000,所以总可以设置一个物理断点0x7C00,开始调试你的bootloader。
查看内存
x /nuf addr 查看一个线性地址的内存
xp /nuf addr 查看一个物理地址的内存
n 显示多少个单位的内存
u 内存单位大小,可以是
b 字节
h 字(2个字节)
w 双字(4个字节)
g 4字(8字节)
注意: 它们不太符合Intel字节命名格式,但是遵守GDB约定。
f 打印格式,可以是
x 16进制格式打印
d 10进制格式打印
u 无符号10进制格式打印
o 8进制格式打印
t 2进制格式打印
n,f,和u是可选参数。U和f默认为你最后使用的参数, 如果是第一次使用,u默认为w,f默认为x, n默认为1。如果没有指定nuf,那么/也可以不要。setpmem addr datasize val 设置物理地址addr,大小datasize的内存单元的值为val.
crc addr1 addr2 对物理地址范围addr1到addr2进行CRC校验?(没用过)info dirty 显示写过的页?(没用过)
Info
info program 查看程序的执行状态
info registers 列举CPU整型寄存器遗迹它们的内容
info break 显示当前断点信息
where 打印当前call stack
寄存器操作
set $reg = val 改变寄存器的内容。可改变的寄存器有:
eax, ecx, edx, ebx, esp, ebp, esi, edi.
不可改变的寄存器有:
eflags, cs, ss, ds, es, fs, gs.
例如 set $eax = 0x01234567
set $edx = 25
info registers 显示寄存器内容
dump_cpu 查看所有与CPU相关的寄存器状态
set_cpu 设置所有与CPU相关的寄存器状态
dump_cpu和set_cpu格式如下:
"eax:0x%x\n"
"ebx:0x%x\n"
"ecx:0x%x\n"
"edx:0x%x\n"
"ebp:0x%x\n"
"esi:0x%x\n"
"edi:0x%x\n"
"esp:0x%x\n"
"eflags:0x%x\n"
"eip:0x%x\n"
"cs:s=0x%x, dl=0x%x, dh=0x%x, valid=%u\n"
"ss:s=0x%x, dl=0x%x, dh=0x%x, valid=%u\n"
"ds:s=0x%x, dl=0x%x, dh=0x%x, valid=%u\n"
"es:s=0x%x, dl=0x%x, dh=0x%x, valid=%u\n"
"fs:s=0x%x, dl=0x%x, dh=0x%x, valid=%u\n"
"gs:s=0x%x, dl=0x%x, dh=0x%x, valid=%u\n"
"ldtr:s=0x%x, dl=0x%x, dh=0x%x, valid=%u\n"
"tr:s=0x%x, dl=0x%x, dh=0x%x, valid=%u\n"
"gdtr:base=0x%x, limit=0x%x\n"
"idtr:base=0x%x, limit=0x%x\n"
"dr0:0x%x\n"
"dr1:0x%x\n"
"dr2:0x%x\n"
"dr3:0x%x\n"
"dr4:0x%x\n"
"dr5:0x%x\n"
"dr6:0x%x\n"
"dr7:0x%x\n"
"tr3:0x%x\n"
"tr4:0x%x\n"
"tr5:0x%x\n"
"tr6:0x%x\n"
"tr7:0x%x\n"
"cr0:0x%x\n"
"cr1:0x%x\n"
"cr2:0x%x\n"
"cr3:0x%x\n"
"cr4:0x%x\n"
"inhibit_int:%u\n"
"done\n"
命令
说明
断
点
相
关
vb seg:off vbreak
在指定的虚拟地址(段+偏移)设置断点,在保护模式下也可以使用
lb addr lbreak
在一个线性地址设置断点
Pb pbreak
在一个物理地址设置断点
info break
显示所有断点状态
del n delete n d n
删除一个断点
步
进
C
继续执行,遇到断点将停止
step [count]
执行count条指令, 默认为1条
内
存
寄
存
器
查
看
x /nuf addr
查看一个线性地址的内存
n 显示多少个单位的内存
u 内存单位大小:
可以是,b字节,h字,w 双字,g 4字
f 打印格式:
可以是:16进制,d 10进制,u 无符号10进制,o 8进制,t 2进制
xp /nuf addr
查看一个物理地址的内存
info registers
列举CPU整型寄存器遗迹它们的内容
反汇编
disassemble start end 反汇编的地址范围
set $disassemble_size = n 告诉调试器,反汇编段的属性(16位或32位,默认32位)。
---http://blog.chinaunix.net/u/15262/showart_411540.html