MIT操作系统课程CS6.828实验(2) —— 实验工具指导

熟悉开发环境,对开发和调试非常关键,本节对JOS环境进行一个简单的概述,以及对GDB和QEMU的有用命令进行介绍。除了这些之外,还需要阅读GDB和QEMU手册。这些都是非常强大的工具,非常有必要去熟悉如何使用它们

1. 调试技巧

1.1 内核
GDB是一个非常好的工具,在JOS实验中,使用qemu-gdb目标(或者qemu-gdb-nox变体)让QEMU等待GDB工具连接。参考GDB中下面介绍的一些命令来调试内核。
如果出现了不期望的中断,异常,或者其他错误。可以使用-d参数让QEMU产生一些更加详细的关于错误中断的Log

但调试虚拟地址问题时,可以尝试使用QEMU监视命令 info mem(对于高级别的概述)或者info pg(对于更多的细节),注意,这些命令只显示当前的页表。
(Lab 4+)为了调试多CPU场景,可以使用GDB的线程相关的命令,像thread和info threads

1.2 用户环境(Lab 3+)
GDB也可以用于调试用户环境程序,但是需要注意一些事情,因为GDB本身不知道多个用户环境之间或用户和内核之间的差别。

通过使用make run-name(或直接编辑kern/init.c)对一特定的用户环境启动JOS。为了让QEMU等待GDB连接,使用run-name-gdb变体。

可以通过符号表来调试用户代码,就是调试内核代码一样,但是需要GDB使用symbol-file命令告诉GDB用的是哪个符号表,由于一次只能使用一个符号表, 默认提供的.gdbinit加载的是内核符号表 obj/kern/kernel。用户环境的符号表在ELF二进制文件中,因此可以使用symbol-file obj/user/name来加载对应的符号表。 不要从.o文件中加载符号,因为.o文件并没有被链接器(链接到JOS用户二进制的静态库,因此这些符号都已经包含在各个用户库中)进行重定位处理。确保获得了正确的用户库;库函数在不同二进制文件中被链接到不同的EIPs,所以GDB不知道。

(Lab 4+)因为GDB整个的连接到虚拟机,可以看到时钟中断作为另一个控制转移。这样基本上不可能逐步调试用户代码,由于一个时钟中断确保让VM再一次运行的时刻, stepi命令起作用,由于其禁止了中断,但是它只能逐步调试汇编指令。断点通过是起作用的,但是需要注意,可能在不同的环境下(不同的二进制)命中相同的EIP。

2. JOS makfile介绍

JOS GNUmakefile文件包含很多的伪目标(Phony Target),用以不同的方式运行JOS。 所有的这些目标配置QEMU来监听GDB连接(*-gdb目标也是等到GDB连接),一旦启动了QEMU,只要在当前的lab目录下运行gdb即可。在代码中提供了.gdbinit文件自动在QEMU中指向GDB,加载内核符号表,以及在16-bit和32-bit模式之间切换,退出GDB将关闭QEMU。

以下命令构建所有,并启动QEMU(包括在新窗口中启动VGA终端和当前终端中启动串口终端)。退出的话,要么通过关闭VGA窗口或者在串口中断中通过按Ctrl-c或者Ctrl-a x退出。

$ make qemu

以下命令类似make qemu,但只在串口终端中启动Qemu,退出的话,按Ctrl-a x。这对于ssh方式登录非常有用,因为VGA窗口会消耗很大的带宽

$ make qemu-nox


以下命令类似make qemu,但是并不是在任何时间被动地接受GDB连接,该命令停止在第一条机器命令,然后等待GDB连接。

$ make qemu-gdb

以下结合qemu-nox和qemu-gdb目标

$ make qemu-nox-gdb

(Lab 3+)运行用户程序name,例如,make run-hello运行user/hello.c

$ make run-name


(Lab 3+)run-name的变体,用来响应qemu目标的变体。

$ make run-name-nox, run-name-gdb, run-name-gdb-nox

makefile也可以接收一些有用的变量,例如:

以下命令V=1表示verbose模式,打印出每条命令的执行,包括参数。

$ make V=1 ...


以下命令表示当任何评分测试fail的时候即停止,然后把Qemu输出到jos.out中用于检查

$ make V=1 grade


指定额外的参数,传递给QEMU

$ make QEMUEXTRA='args' ...

3. JOS生成文件

当构建JOS,makefile同时会产生一些额外的输出文件,在进行代码调试时非常的有用。

obj/boot/boot.asmobj/kern/kernel.asmobj/user/hello.asm, 等等

bootloader,kernel,和用户程序的汇编代码


obj/kern/kernel.symobj/user/hello.sym,等等
kernel和user程序的符号表


obj/boot/boot.out, obj/kern/kernel, obj/user/hello等等

kernel和user程序的ELF镜像,这些包含的符号信息可以被GDB使用

4. GDB常用命令介绍

更多的关于GDB的详细用法,可以参考GDB手册。以下只介绍6.828课程中用到的一些特定的GDB命令。其中的一些GDB命令在OS开发完很少使用。

Ctrl-c
停止当前机器,以及在GDB当前的指令处中断,若QEMU有很多虚拟CPU,将终止它们。


c(或者continue)
继续执行直到下一个断点或者Ctrl-c


si(或者 stepi)
执行一条机器指令


b function或b file:line(或breakpoint)
在给定的函数或者行设置断点


b *addr(或breakpoint)
在EIP地址设置断点


set print pretty
确保数组和结构体的完美的打印


info registers
打印通用目的寄存器,eip,eflags和段选择子,对于更多的关于机器寄存器状态输出,参见QEMU info registers命令。


x/Nx addr
显示从虚拟地址addr开始的N个words的16进制输出,若N忽略,缺省为1,addr可以是任何的表达式。


x/Ni addr
显示从addr地址开始的N个汇编指令,使用$eip作为addr将显示当前指令指针的指令。


symbol-file file
(Lab 3+)切换符号文件file,当GDB连接到Qemu,在虚拟机中没有进程边界的概念,所以需要告诉它使用哪个符号,缺省情况下,配置GDB使用内核符号表,obj/kern/kernel,若机器正在运行用户代码,比如hello.c,可以使用symbol-file obj/user/hello,切换到hello符号文件中。


Qemu中各个虚拟的CPU在GDB中作为一个线程,所以可以使用所有的GDB的线程相关的命令来观察和管理Qemu的虚拟CPUs。

thread n
GDB一次只关注一个线程(e.g. CPUs),该命令切换到线程n,线程编号从0开始


info threads
列出所有的线程(例如,CPUs),包括它们的状态(活动的还是终止的),以及它们处在哪个函数中。

5. QEMU常用命令介绍

Qemu包含一个内置的监视器用来观察和修改机器状态,进入monitor模式后,在终端中按下Ctrl-a c运行Qemu, 再次按下Ctrl-a c切换到串口控制台。

对于完整的monitor命令,可以参考Qemu手册,以下是一些常用的比较有用的命令:
xp/Nx paddr
显示从物理地址paddr开始的N个words的十六进制输出。若N忽略,缺省值为1,这个是物理内存,可对比与GDB的x命令

info registers
显示机器内部寄存器状态的所有输出,尤其包括对于段选择子的隐藏段状态,以及局部的,全局的和中断描述符表, 外加task寄存器,这些隐藏的状态是虚拟CPU当加载段选择子时从GDT/LDT从读取的信息。但运行Lab1中的Jos内核,如下是寄存器CS的各个域的意思
CS =0008 10000000 ffffffff 10cf9a00 DPL=0 CS32 [-R-]


info mem

info pg

make QEMUEXTRA='-d int' ...


6. 参考

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值