[MIT6.S081] 插曲 · 使用gdb调试xv6

1,349 阅读1分钟

使用gdb-multiarch调试xv6

在Lab1中,我们安装了gdb-multiarch。这个工具顾名思义——gdb for multi architecture 是适用于多体系架构的gdb。 在课上,教授使用的是 riscv64-linux-gnu-gdb,然而在ubuntu 20.04的软件源中似乎并没有该工具。

$ sudo apt-get install riscv64-linux-gnu-gdb
Reading package lists... Done
Building dependency tree       
Reading state information... Done
E: Unable to locate package riscv64-linux-gnu-gdb

使用gdb-multiarch来对xv6调试的一般步骤如下:

# 在终端输入
make qemu-gdb
# 在另一个终端进入到xv6根目录后输入
gdb-mulitarch kernel/kernel
# 只需要执行一次,无需每次开启gdb后都设置架构
(gdb) set architecture riscv:rv64
The target architecture is assumed to be riscv:rv64
# 连接到本地tcp端口26000
(gdb) target remote localhost:26000
0x0000000000001000 in ?? ()

使用.gdbinit

但如此一来,每次都得输一大串命令后才能开始调试,实在是有点影响效率,如何才能减少需要输入的命令数量呢?我们可以使用--command参数来使gdb启动后一次执行一个文件里的gdb命令:

# 查看帮助文档
gdb-multiarch --help
# 可以看到-x选项后接可执行文件就可以从文件中执行gdb命令了
--command=FILE, -x Execute GDB commands from FILE. 

因此我们可以编写脚本文件:

# gdb.sh
file kernel/kernel
target remote localhost:26000

以后每次就输入以下命令即可:

gdb-multiarch -x gdb.sh

但在课上,教授输入riscv64-linux-gnu-gdb后,程序就开始运行了,这是什么原理呢?第二天我思考了一下,想起来之前做上交的chcore-lab的时候(是的,我之前还做过chcore这个OS Lab,但我太菜了,卡在了某一环节上,也就没继续往下做了)也是只需要执行命令make gdb就可以连接上了,那是不是只要我修改一下我的MakeFile也能达到完全一致的效果呢?于是我查看了chcore的MakeFile,里面写到:

V := @
QEMU_GDB_PORT := 1234
gdb:
	$(V)gdb-multiarch -x $(PROJECT_DIR)/.gdbinit

这时候我想起来xv6的目录下就有.gdbinit文件。这个文件的原理十分简单,就是在gdb启动的时候会检查当前目录下是否有.gdbinit文件,若有则会自动执行里面的命令。但之前启动gdb后为什么没有执行这个脚本呢?其实在gdb-multiarch启动后就有warning解释了这个问题:

warning: File "/home/<hostname>/Documents/xv6-labs-2020/.gdbinit" auto-loading has been declined by your `auto-load safe-path' set to "$debugdir:$datadir/auto-load".
To enable execution of this file add
        add-auto-load-safe-path /home/<hostname>/Documents/xv6-labs-2020/.gdbinit
line to your configuration file "/home/<hostname>/.gdbinit".
To completely disable this security protection add
        set auto-load safe-path /
line to your configuration file "/home/<hostname>/.gdbinit".
For more information about this security protection see the
"Auto-loading safe path" section in the GDB manual.  E.g., run from the shell:
        info "(gdb)Auto-loading safe path"

所以我们只用按照warning中的提示,在/home/<hostname>/.gdbinit添加相应的语句即可。

这给我的教训就是warning还是得仔细阅读,里面还是有许多有价值的信息的。
还有一个问题就是既然.gdbinit会在gdb启动的时候自动检测执行,为什么chcore的MakeFile中还有加入gdb的段落呢?我想是因为写上之后,我们就不需要在/home/<hostname>/.gdbinit添加safe-path也可以执行.gdbinit文件,也就省去了一些设置的麻烦了。

使用gdb-multiarch 调试用户程序

如果我们需要调试trace程序,则需要在gdb运行后,从trace.o读入符号

file user/trace.o
# 打断点
b trace.c:main 
continue
# xv6的sh运行后再sh中输入trace xxx,运行trace程序
trace 32 grep hello README

参考:
stackoverflow.com/questions/1…
另外,在查找资料的时候还看到了如何使用vscode连接gdb进行调试,后续有需要可以再仔细学习学习:
www.cnblogs.com/KatyuMarisa…