Bochs调试常用命令

1 简介

Bochs是做系统开发常用的虚拟机,调试系统内核很方便。

安装Bochs一般是从源码编译再安装,而调试器属于可选功能,所以在编译Bochs时需要使用--enable-debugger--enable-disasm标志开启调试模块。例如:

1
./configure --enable-debugger --enable-disasm #后面还有其他选项,此处省略

需要注意调试功能在 2.5.4 版本以上才有,确保下载的代码是高于这个版本的。

2 常见的几个使用场景

2.1 查看寄存器

汇编代码中,调试最常用的功能就是查看寄存器的内容。

  • r 查看通用寄存器
  • sreg 查看段寄存器
  • creg 查看控制寄存器
  • dreg 查看调试寄存器
  • info cpu 查看所有寄存器

2.2 查找和定位代码

次常用的肯定是控制代码执行流程,代码执行到想要仔细跟踪的那个部分。

  • b 内存地址 设置断点

    b 0x7c00,在线性地址0x7c00处设置断点。

  • info break 查看设置过的断点

  • c 继续执行代码

    一般设置断点后,想让代码恢复执行,就使用这个命令。

  • s 单步执行

    单步执行一行代码,和高级语言调试器的step into按钮类似,遇到函数调用会跳转到函数内部执行。单步执行命令也可以带参数,指定执行的次数,如 s 100 就是单步执行100次。

  • n 执行下一行

    它和单步执行类似,单步执行遇到循环和函数时会跳转到内部,而n命令会执行完循环和函数,类似于step over,这样在遇到大量的循环或者较长的函数时,可以用n命令来执行到下一行。

    n命令能跳转到下一行是因为loop或者call执行有明显的结束标记(前者通过cx寄存器,后者通ret指令),如果遇到用jmp语句写的循环这种情况,没有明显结束标记的,可以用下面的u命令反汇编代码的地址,找到循环的下一行指令的地址,然后给该地址加一个断点就能达到同样的效果。

  • u 反汇编代码

    直接使用u命令会反汇编当前执行的指令,它可以加参数, u /反汇编数量 起始地址 ,如 u /20 0x7c00 就是从0x7c00处开始,反汇编20条指令,如果没有起始地址就是从当前地址开始。

    它还可以反汇编一个范围的代码,u 起始地址 结束地址 ,如u 0x7c00 0x7cff 就是反汇编0x7c00到0x7cff的代码。

2.3 查看内存

  • x /nuf 地址 查看线性地址处的内存内容。
  • xp /nuf 地址 查看物理地址处的内存内容。
1
2
3
4
5
6
7
8
9
10
11
n 指定要显示的内存单元的数量
u 显示的内存单元的大小,如下参数之一
b 单个字节
h 半个字(2 字节)
w 一个字(4 字节)
f 打印的格式。如下类型之一:
x 按照十六进制形式打印
d 按照十进制形式打印
u 以无符号的10进制打印
o 按照八进制形式打印
t 按照二进制行是打印

2.4 Tips

Bochs还有一个比较有用的设计就是,当你输入指令后,直接按回车键(Enter Key)会重复上一次的命令。比如上一个命令是单步执行s,此时直接按回车键就相当于s的功能。

3 调试指令手册

3.1 执行控制

命令 解释
c / cont / continue 继续执行
s / step [count] 执行count条指令,如果不指定参数,默认值为1
s / step [cpu] [count] 对于对称多处理器结构模拟,在cpu上执行count条指令,count的默认值为1
s / step all [count] 对于对称多处理器结构模拟,所有cpu上都执行count条指令,count的默认值为1
Ctrl-C 停止执行,返回到命令行提示符
Ctrl-D 如果在空行上执行,则退出调试器
q / quit / exit 退出调试器,继续执行

3.2 断点操作

命令 解释
vbreak / vb segment:offset 设置虚拟地址指令断点,segment和offset指段地址和段内偏移量
lbreak / lb addr 在线性地址指令上设置断点
pbreak / bp [*] addr 在物理地址上设置断点
break / b [*] addr 同上。 * 符号是兼容GDB命令,为可选参数
info break 显示当前所有断点状态
bpe n 开启断点
bpd n 关闭断点
delete / del / d n 删除断点

注意:① ② ③ ④ 的命令都可以设置条件,即都可以变成条件断点。具体做法是在命令之后添加if condition ,如vbreak 0x008:0x001 if "条件表达式"

3.3 内存观察点

内存观察点类似于内存的监听器,当指定地址的内存产生读取或者写入事件时,会产生中断。

命令 解释
watch read/r addr 在物理地址addr上插入读观察点
watch write/w addr 在物理地址addr上插入一个写观察点
watch 显示当前内存观察点的状态
watch stop 当遇到观察点时,停止模拟执行(默认)
watch continue 在遇到观察点时,不要停止模拟执行
unwatch addr 移除指定物理地址上的观察点
unwatch 移除所有的观察点
trace-mem on/off 开启/关闭 内存访问追踪

3.4 内存操作

命令 解释
x /nuf addr 在线性地址addr处检查内存内容,nuf的解释在前面列出
xp /nuf addr 在物理地址 addr处查看内存内容,nuf的解释在前面列出
setpmem addr datasize value 在内存位置addr处设置datasize大小内存,值为 value
writemem filepath addr datasize 从线性地addr处dump出datasize个字节到文件filepath中
crc addr1 addr2 显示物理地址范围 addr1到addr2之间内容的 CRC值

3.5 查看信息

命令 解释
r / reg / regs / registers 查看通用寄存器内容
fp / fpu 查看FPU寄存器内容
mmx 查看MMX寄存器内容
sse / xmm 查看SSE寄存器内容
ymm 查看AVX寄存器内容
sreg / dreg / creg 查看 段 / 调试 / 控制 寄存器内容
info cpu 查看所有寄存器内容
info eflags 查看标志寄存器内容
info break 显示当前所有断点状态
info tab 显示分页地址转换
info device 显示指定设备的状态

3.6 寄存器操作

命令 解释
set reg = expr 修改reg寄存器值为expr

注意:只能修改通用寄存器和指令寄存器。不能够修改标志寄存器,段寄存器,浮点寄存器和SIMD寄存器。

3.7 反汇编

命令 解释
u addr1 addr2 在给定的线性地址范围内反汇编指令,包含start处指令,不包含end处指令
u switch-mode 在Intel和 AT&T两种汇编风格之间切换
u size = n 设定反汇编命令的位数,使用0,16,32。值0意思是使用当前的CS段寄存器,默认值是0
set u on 每次停止执行时就自动反汇编当前的指令
set u off 和上一条相反,不自动反汇编

3.8 指令跟踪

命令 解释
trace on 反汇编每一条执行的指令。引起异常的指令都没有真正执行,因此也不会被跟踪
trace off 关闭指令跟踪功能

3.9 指令编程环境

Bochs的instrument功能,提供了运行时的各种钩子函数。它也是可选功能,在编译安装时需要开启--enable-instrumentation选项指定。

1
2
./configure [...] --enable-instrumentation
./configure [...] --enable-instrumentation="instrument/stubs"

自定义的代码要创建一个独立的目录,例如”instrument/myinstrument”,将”instrument/stubs”目录拷贝进去,然后使用如下的指令设定:

1
./configure [...] --enable-instrumentation="instrument/myinstrument"

指令命令:

1
instrument [command]    用[command]调用BX_INSTR_DEBUG_CMD指令回调

3.10 show指令

命令 解释
show 打印当前的符号信息显示模式
show mode 当处理器切换模式时打印
show int 当产生中断时打印
show call 当产生调用时打印
show ret 当函数返回时打印
show off 关闭打印
show dbg-all 开启所有显示标志
show dbg-none 关闭所有显示标志

3.11 其他命令

命令 解释
ptime 打印当前的时间(从开始模拟到现在的ticks)
sb delta 在未来执行中插入一个时间断点delta。delta是一个64位的整数,跟着字母”L”,例如1000L
sba time 在时间time处插入一个时间断点 。time 同上面的delta
print-stack [num] 打印栈顶端的num个字
modebp 触发CPU模式转换断点
ldsym [global] filename [offset] 从文件filename加载符号。

4 参考