首页 > > > Caffeinated 6.828:实验工具指南
熟悉你的环境对高效率的开发和调试来说是至关重要的。本文将为你简单概述一下 JOS 环境和非常有用的 GDB 和 QEMU 命令。话虽如此,但你仍然应该去阅读 GDB 和 QEMU 手册,来理解这些强大的工具如何使用。
内核GDB 是你的朋友。使用 qemu-gdb target(或它的变体 qemu-gdb-nox)使 QEMU 等待 GDB 去绑定。下面在调试内核时用到的一些命令,可以去查看 GDB 的资料。
如果你遭遇意外的中断、异常、或三重故障,你可以使用 -d 参数要求 QEMU 去产生一个详细的中断日志。
调试虚拟内存问题时,尝试 QEMU 的监视命令 info mem(提供内存高级概述)或 info pg(提供更多细节内容)。注意,这些命令仅显示当前页表。
(在实验 4 以后)去调试多个 CPU 时,使用 GDB 的线程相关命令,比如 thread 和 info threads。
用户环境(在实验 3 以后)GDB 也可以去调试用户环境,但是有些事情需要注意,因为 GDB 无法区分开多个用户环境或区分开用户环境与内核环境。
你可以使用 make run-name(或编辑 kern/init.c 目录)来指定 JOS 启动的用户环境,为使 QEMU 等待 GDB 去绑定,使用 run-name-gdb 的变体。
你可以符号化调试用户代码,就像调试内核代码一样,但是你要告诉 GDB,哪个符号表用到符号文件命令上,因为它一次仅能够使用一个符号表。提供的 .gdbinit 用于加载内核符号表 obj/kern/kernel。对于一个用户环境,这个符号表在它的 ELF 二进制文件中,因此你可以使用 symbol-file obj/user/name 去加载它。不要从任何 .o 文件中加载符号,因为它们不会被链接器迁移进去(库是静态链接进 JOS 用户二进制文件中的,因此这些符号已经包含在每个用户二进制文件中了)。确保你得到了正确的用户二进制文件;在不同的二进制文件中,库函数被链接为不同的 EIP,而 GDB 并不知道更多的内容!
(在实验 4 以后)因为 GDB 绑定了整个虚拟机,所以它可以将时钟中断看作为一种控制转移。这使得从底层上不可能实现步进用户代码,因为一个时钟中断无形中保证了片刻之后虚拟机可以再次运行。因此可以使用 stepi 命令,因为它阻止了中断,但它仅可以步进一个汇编指令。断点一般来说可以正常工作,但要注意,因为你可能在不同的环境(完全不同的一个二进制文件)上遇到同一个 EIP。
JOS makefileJOS 的 GNUmakefile 包含了在各种方式中运行的 JOS 的许多假目标。所有这些目标都配置 QEMU 去监听 GDB 连接(*-gdb 目标也等待这个连接)。要在运行中的 QEMU 上启动它,只需要在你的实验目录中简单地运行 gdb 即可。我们提供了一个 .gdbinit 文件,它可以在 QEMU 中自动指向到 GDB、加载内核符号文件、以及在 16 位和 32 位模式之间切换。退出 GDB 将关闭 QEMU。
make qemuCtrl-c 或 Ctrl-a x。make qemu-noxmake qemu 一样,但仅使用串行控制台来运行。想退出时,按下 Ctrl-a x。这种方式在通过 SSH 拨号连接到 Athena 上时非常有用,因为 VGA 窗口会占用许多带宽。make qemu-gdbmake qemu 一样,但它与任意时间被动接受 GDB 不同,而是暂停第一个机器指令并等待一个 GDB 连接。make qemu-nox-gdbqemu-nox 和 qemu-gdb 目标的组合。make run-nammake run-hello 运行 user/hello.c。make run-name-nox,run-name-gdb, run-name-gdb-noxqemu 目标变量对应的 run-name 的变体。makefile 也接受几个非常有用的变量:
make V=1 …make V=1 gradejos.out 文件中以备检查。make QEMUEXTRA=' _args_ ' …JOS obj/在构建 JOS 时,makefile 也产生一些额外的输出文件,这些文件在调试时非常有用:
obj/boot/boot.asm、obj/kern/kernel.asm、obj/user/hello.asm、等等。obj/kern/kernel.sym、obj/user/hello.sym、等等。obj/boot/boot.out、obj/kern/kernel、obj/user/hello、等等。GDB完整的 GDB 命令指南请查看 GDB 手册。下面是一些在 6.828 课程中非常有用的命令,它们中的一些在操作系统开发之外的领域几乎用不到。
Ctrl-cc(或 continue)Ctrl-c。si(或 stepi)b function 或 b file:line(或 breakpoint)b * addr(或 breakpoint)set print prettyinfo registerseip、eflags、和段选择器。更多更全的机器寄存器状态转储,查看 QEMU 自己的 info registers 命令。x/ N x addrx/ N i addr$eip 作为 addr 将显示当前指令指针寄存器中的指令。symbol-file fileobj/kern/kernel。如果机器正在运行用户代码,比如是 hello.c,你就需要使用 symbol-file obj/user/hello 去切换到 hello 的符号文件。QEMU 将每个虚拟 CPU 表示为 GDB 中的一个线程,因此你可以使用 GDB 中所有的线程相关的命令去查看或维护 QEMU 的虚拟 CPU。
thread ninfo threadsQEMUQEMU 包含一个内置的监视器,它能够有效地检查和修改机器状态。想进入到监视器中,在运行 QEMU 的终端中按入 Ctrl-a c 即可。再次按下 Ctrl-a c 将切换回串行控制台。
监视器命令的完整参考资料,请查看 QEMU 手册。下面是 6.828 课程中用到的一些有用的命令:
xp/ N x paddrx 命令模拟的物理内存。info registersCS =000810000000ffffffff10cf9a00DPL=0CS32DS,而对于本地描述符表是 LDT。[-R-]info meminfo pginfo mem,但与页目录条目和页表条目是有区别的,并且为每个条目给了单独的权限。重复的 PTE 和整个页表被折叠为一个单行。例如:QEMU 也有一些非常有用的命令行参数,使用 QEMUEXTRA 变量可以将参数传递给 JOS 的 makefile。
make QEMUEXTRA='-d int' ...qemu.log 文件中。你可以忽略前两个日志条目、“SMM: enter” 和 “SMM: after RMS”,因为这些是在进入引导加载器之前生成的。在这之后的日志条目看起来像下面这样:4: 只是一个日志记录计数器。v 提供了十六进程的向量号。e 提供了错误代码。i=1 表示它是由一个 int 指令(相对一个硬件产生的中断而言)产生的。剩下的行的意思很明显。对于一个寄存器转储而言,接下来看到的就是寄存器信息。/tmp 目录,而不是当前目录下。via: https://pdos.csail.mit.edu/6.828/2018/labguide.html
原文作者:;如有侵权,请联系管理员删除。