3.4bochs的调试方法
bochs个开源x86 虚拟机软件。 在它的实现中定义了各种数据结构来模拟硬件, 用软件模拟硬件 缺点是速度比较慢。
bochs的硬件调试体现在:
(l) 调试时可以查看页表、 gdt、 idt等数据结构
(2) 可以查看栈中数据
(3) 可以反汇编任意内存
(4)实模式、 保护模式互相变换时提醒
(5) 中断发生时提醒
1.打开bochs
h|help - show list of debugger commands
h|help command - show short command description
2.在打开bochs终端中输入help将出现调试bochs的指令,可分为以下四种:
在 bochs_提供的命令中, 大部分调试命令都有简写和缩写, 它们用或运算字符‘|’分隔 所以它们
都是同一个功能, 只是不同的别名, 用哪个都可以。
1.-- Debugger control --调试控制类
help, q|quit|exit, set, instrument, show, trace, trace-reg, trace-mem, u|disasm, ldsym, slist\
1.u|disasm将内存数据反汇编成指令
例如输入 u/1 0xffff0 这样可反汇编查看0xffff0处的指令。
2.q|quit|exit,左边三个任意一个都能退出调试状态,关闭虚拟机。
3.set是指令族,通常用set设置寄存器的值,常用以下两种用法。set reg = val,可以设置寄存器包括通用寄存器和段寄存器。也可以设置每次停止执行时,是否反汇编指令,set u on|off
4.show也是指令族,常用以下三个:
show model 每次CPU变换模式的时候就提示,模式变换指的是实模式转换到保护模式
show int 每次有中断就提示,同时显示三种中断类型,包括“softint” “extint” “iret”
show call 每次有函数调用时就提醒
5.愤ceon|off如果此项设为 on。 每次执行一条指令’ bochs 都会将反汇编的代码打印到控制台, 这样在
单步调试时免得看源码了。
2.-- Execution control --执行控制类
c|cont|continue, s|step, p|n|next, modebp, vmexitbp
1.c|cont|continue, 左边列出的三个命令都意为向下持续执行, 若没断点则一直运行下去。 最常用的是c。
2.s|step [count] 执行 count条指令, count 是指定单步执行的指令数 若不指定, count 默认为l 此指
令若遇到函数调用 则会进入函数中去执行。 最常用的是s。
3.pln|next 执行l条指令, 若待执行的指令是函数调用_不管函数内有多少指令, 把整个函数当作一个
整体来执行 最常用的是n
3.-- Breakpoint management --
vb|vbreak, lb|lbreak, pb|pbreak|b|break, sb, sba, blist, bpe, bpd, d|del|delete, watch, unwatch
1.vb|vbreak[seg= o迂] 以虚拟地址添加断点 程序执行到此虚拟地址时停下来, 注意虚拟地址是 “段”:段内偏移″ 的形式。 最常用的是vb。
2.lb|break[addI]以线性地址添加断点 程序执行到此线性地址时停下来。 最常用的是lb。
3.pblpbreak|blbreal([addr]以物理地址添加断点。 程序执行到此物理地址时停下来。 b 比较常用。
4.sb [delta] delta 表示增量, 意味再执行 delta条指令程序就中断
5.sba[tune] CPU 从运行开始, 执行第 time条指令时中断, 从0开始的指令数
6.watch 也有子命令, 常用的是这两个。
watchr|read[phy_addr] 设置读断点, 如果物理地址phy_addr有读操作则停止运行。
watchWIwrite [phy_addr] 设置写断点,如果物理地址phy_addr有写操作则停止运行。此命令非常有用,
如果某块内存不知何时被改写了, 可以设置此中断。
watch 显示所有读写断点。
unwatch清除所有断点。
unwatch [phy_addr] 清除在此地址上的读写断点。
7.blist 显示所有断点信息, 功能等同于 info b
8.bpdlbpe [n] 禁用断点 〈break point disabe) /启用断点 (break point enable), n是断点号′ 可以用blist
命令先检查出来
9.d|de1|delete[n] 删除某断点 n是断点号, 可以用 blist断令先检查出来 D最常用。
4. -- CPU and memory contents --
x, xp, setpmem, writemem, crc, info, r|reg|regs|registers, fp|fpu, mmx, sse, sreg, dreg, creg, page, set, ptime, print-stack, ?|calc
1.x、 xp 命令。 这两个命令是用来查看内存的, 它们的区别是x命令后接线性地址, xp命令后接physieal物理地址。 在目前的实模式中, 只能通过物理地址来查看内存,先看看xp命令′是怎么用的, 一会咱们用 xp命令来做个测试。 键入help xp 回车
h是指半个字, 2个字节。 W是指一个字, 4个字节。 g是指双字, 8字节。
x/nuf[Ime_addr] 显示线性地址的内容n、 u f是三个参数 都是可选的, 如果没有指定 则n为 l,
u是4字节′f是十六进制。 解释如下 n显示的单元数 _
u每个显示单元的太小,_u可以是下列之一=
(1) b 1字节
(2)h 2字节
〈3〉w 4字节
(4〉 g 8 字节
f 显示格式, f可以是下列之一:
(1) x按照十六进制显示
〈2) d十进制显示
(3) u按照无符号十进制显示
(4〉 o按照八进制显示
(5) t按照二进制显示
(6) c按照字符显示
(7) s按照 ASCIIz 显示
〈8) i按照instr显示。
xp/nuf[phy_addr] 显示物理地址phy一addr处的内容’ 注意和x的区别, x是线性地址。
2.setpmem〔phy_addr] [size] [val] ` 以物理内存phy_addr为起始点连续 size个字节的内容为val。 此命令非常
有用, 在某些情况下不易调试时, 可以在程序中通过某个地址的值来判断分支, 需要用 setpmem来配合。
3.r|reg丨regs丨registers 任意四个命令之_便可以显示8个通用寄存器的值+enags 寄存器+eip 寄存器。 r是
我常用的查看寄存器的命令。
4.ptiIne 显示 Bochs 自启动之后, 总执行指令数。 其实这个命令不常用, 感兴趣的同学可以用 ptime和
“sb 指令数” 来验证结果是否正确。
5.print-stack[num] 显示堆栈, num默认为 16, 表示打印的栈条目数。 输出的栈内容是栈顶在上, 低地
址在上, 高地址在下。 这和栈的实际扩展方向相反, 这一点请注意。
6.info 是个指令族, 执行 helpinfo 时可查看其所有支持的子命令 如下
info pb|pbreak|b|break 查看断点信息 等同于 blist。 _ ′
info CPU 显示CPU所有寄存器的值, 包括不可见寄存器。
info fpu 显示 FPU 状态
info idt显示中断向量表IDT
info gdt[num]显示全局描述符表GDT 如果加了 num, 只显示 gdt中第num项描述符
info ldt显示局部描述符表LDT。
info tss显示任务状态段TSS。
inf ivt [num] 显示中断向量表IvT
-- Working with bochs param tree --
show "param", restore