第三视点: 简易调试器
简易调试器是monitor的一项重要功能. 我们知道NEMU是一个用来执行其它用户程序的程序, 这意味着, NEMU可以随时了解用户程序执行的所有信息. 然而这些信息对外面的调试器(例如GDB)来说, 是不容易获取的. 例如在通过GDB调式NEMU的时候, 你将很难在NEMU中运行的用户程序中设置断点, 但对于NEMU来说, 这是一件不太困难的事情.
我们需要在monitor中实现一个具有如下功能的简易调试器(相关部分的代码在 nemu/src/monitor/debug
目录下), 如果你不清楚命令的格式和功能, 请参考如下表格:
命令 | 格式 | 使用举例 | 说明 |
---|---|---|---|
帮助(1) | help |
help |
打印命令的帮助信息 |
继续运行(1) | c |
c |
继续运行被暂停的程序 |
退出(1) | q |
q |
退出NEMU |
单步执行 | si [N] |
si 10 |
让程序单步执行 N 条指令后暂停执行, 当 N 没有给出时, 缺省为 1 |
打印程序状态 | info SUBCMD |
info r info w |
打印寄存器状态 打印监视点信息 |
表达式求值 | p EXPR |
p $eax + 1 |
求出表达式 EXPR 的值, EXPR 支持的运算请见调试中的表达式求值小节 |
扫描内存(2) | x N EXPR |
x 10 $esp |
求出表达式 EXPR 的值, 将结果作为起始内存地址, 以十六进制形式输出连续的 N 个4字节 |
设置监视点 | w EXPR |
w *0x2000 |
当表达式 EXPR 的值发生变化时, 暂停程序执行 |
删除监视点 | d N |
d 2 |
删除序号为 N 的监视点 |
打印栈帧链(3) | bt |
bt |
打印栈帧链 |
备注:
- (1) 命令已实现
- (2) 与GDB相比, 我们在这里做了简化, 更改了命令的格式
- (3) 在PA2中实现
总有一天会找上门来的bug
你需要在将来的PA中使用这些功能来帮助你进行NEMU的调试, 如果你的实现是有问题的, 将来你有可能会面临以下悲惨的结局: 你实现了某个新功能之后, 打算对它进行测试, 通过扫描内存的功能来查看一段内存, 发现输出并非预期结果. 你认为是刚才实现的新功能有问题, 于是对它进行调试. 经过了几天几夜的调试之后, 你泪流满面地发现, 原来是扫描内存的功能有bug!
如果你想避免类似的悲惨结局, 你需要在实现一个功能之后对它进行充分的测试. 随着时间的推移, 发现同一个bug所需要的代价会越来越大.