使用 vscode 的 debug 调试功能来进行南大 PA
前提
gdb 是我们进行大型项目开发必不可少的调试工具,但是它原生是运行在命令行中的,对于已经有了图形界面的我们来说,完全可以使用 vscode 的 debug 功能来启动 gdb 从而更方便地进行调试。
vscode 的 debug 功能提供了一套 gui 来显示 gdb 的各种信息、观察点,比直接用命令行方便多了,非常直观。此外还提供了 console 来让你可以使用命令行的方式控制 gdb,可以说是各取所长,两全其美。
1. 安装 gdb、启动项目的调试信息功能
gdb 已经在讲义的 PA0 步骤中安装好了。在命令行中输入指令 gdb -v
如果能够显示 gdb 的版本就代表 gdb 已经安装上了。
而启动项目的调试信息,则在讲义的“为 NEMU 编译时添加 GDB 调试信息”中,也已经让我们配置好了。这一设置的作用是让 gcc 在编译 NEMU 的时候生成额外生成调试所需要的一些信息,gdb 利用这些信息才能够实现定位代码等功能。
2. 配置 vscode
vscode 的 debug 功能在侧边栏的第四个。刚点进来会显示如下界面:
这代表我们现在还没有配置任何调试项目,vscode 并不知道该如何调试。此时点击“Run and Debug”按钮,vscode 会生成一个模板项目来让我们进行配置,不过我们不需要这么做。
配置调试项目相关的文件是 .vscode/tasks.json
和 .vscode/launch.json
,前者的作用是进行项目的编译,后者是启动调试。在项目根目录下建立 .vscode
文件夹后,将以下内容分别复制进去。
tasks.json
:
|
|
"version"
代表 task 的版本,默认 "2.0.0"
就好。"tasks"
则是你定义的各个编译任务,由一个数组传入。
这里我们配置了三个任务,分别用于执行 make clean
、make
和 make run
指令。
在每一个任务中,"lable"
是这个任务的名字,需要唯一,后续需要用这个来标识该任务。"command"
和 "args"
分别是执行这个任务的指令和参数,vscode 会将他们安装顺序拼接成字符串,传入命令行并执行。显然 "args"
是一个数组,因为参数可能不止一个。
举一个例子,"command"
的值为 "make"
,"args"
的值为 ["run", "-j8"]
,则最终传入命令行的指令就是 make run -j8
。
"command"
和 "args"
拼接在一起,那么其实直接把所有的指令都写到 "command"
里也可以,因为本质都是字符串。例如上面提到的例子,其实也可以写成 "command": "make run -j8"
。最后一个 "type"
有两个值可以选,分别为 "shell"
和 "process"
,代表该任务是启动一个命令行来执行还是创建一个线程来执行。创建线程的话我们就没法看到执行的过程了,因此这里选择 "shell"
。
launch.json
:
|
|
"version"
和 "configurations"
不用说了。"name"
就是名字,会显示在选择框中。"type"
代表使用的 debug 工具是什么,这里我们用的就是 gdb,另一常见的是 lldb。
"cppdbg"
不收支持的错误,是因为没有安装/启动 C/C++ 插件。安装并启动就好了。"program"
是我们需要调试的程序。我们使用 make
指令会将 NEMU 编译成一个可执行文件,其路径是 build/$(ISA)-nemu-interpreter
。而当我们在 make 的时候加入 run
参数,也就是执行 make run
的时候,其实就是在编译生成该可执行文件后自动执行。
"program"
参数是我自己使用的路径,ISA 架构是 riscv32,如果你选择了别的 ISA,需要修改为对应的文件。"cwd"
是执行 gdb 时候所在的目录,这里我们设置成项目根目录就好了。"preLaunchTask"
是在启动调试之前需要执行的任务,这里我们设置成前面配置好了的“编译”任务,其 label 是 "make"
,这样在每次启动调试之前,vscode 就会自动执行编译任务,生成最新的项目了。
3. 享受 debug 吧
以上都配置好后,回到 vscode 的调试选项卡就会显示成下图这样:
如果配置了多个调试项目,可以在左上方的下拉框中选择。点击绿色三角形就可以启动调试:
点击代码行左侧出现红色圆点就是添加断点。左侧的面板用于显示信息,例如变量值等。上方的控制板可以控制 gdb 继续、进入、跳出等。切换到 DEBUG CONSOLE 栏还可以以命令行的方式执行 gdb 指令:
结束
享受 PA 吧。