xv6-riscv开发调试环境搭建(vscode+ubuntu)
vscode+ubuntu22
ubuntu远程环境
1.安装必要依赖,保证xv6-riscv项目可以运行
这步比较容易
安装gdb调试工具
从以下网址下载,上传到远程Ubuntu主机
https://github.com/sifive/freedom-tools/releases
https://static.dev.sifive.com/dev-tools/freedom-tools/v2020.12/riscv64-unknown-elf-toolchain-10.2.0-2020.12.8-x86_64-linux-ubuntu14.tar.gz
然后:
sudo mkdir -p /opt/riscv
sudo tar -xzf riscv64-unknown-elf-toolchain-*.tar.gz -C /opt/riscv --strip-components=1
echo 'export PATH=/opt/riscv/bin:$PATH' >> ~/.bashrc
source ~/.bashrc
验证安装
riscv64-unknown-elf-gcc --version
riscv64-unknown-elf-gdb --version
windows+vscode端
本地 VSCode 必备插件
在 VSCode 安装:
- ✅ Remote - SSH
- ✅ C/C++ (by Microsoft)
- ✅ CodeLLDB(可选)
- ✅ Native Debug(可选)
远程打开 xv6 项目(把远程的xv6项目同步到本地)
-
在 VSCode 打开命令面板(Ctrl+Shift+P)
-
选择:
Remote-SSH: Connect to Host... -
连接你的云主机。
-
打开
xv6-riscv项目所在目录。
在 VSCode 中创建调试配置
在项目根目录创建(或编辑) .vscode/launch.json:
{"version": "0.2.0","configurations": [{"name": "debug xv6","type": "cppdbg","request": "launch","program": "${workspaceFolder}/kernel/kernel",// "program": "${workspaceFolder}/user/_ls","args": [],"stopAtEntry": true,"cwd": "${workspaceFolder}","miDebuggerServerAddress": "localhost:25000","miDebuggerPath": "/opt/riscv/bin/riscv64-unknown-elf-gdb","environment": [],"externalConsole": false,"MIMode": "gdb","setupCommands": [{"description": "pretty printing","text": "-enable-pretty-printing","ignoreFailures": true}],"logging": {// "engineLogging": true,// "programOutput": true,}}]
}
如果想要调试内核则:
"program": "${workspaceFolder}/kernel/kernel",
如果想要调试用户程序则:
"program": "${workspaceFolder}/user/_ls",
调试流程
-
在 VSCode 中,终端执行:
make clean make qemu-gdb让 QEMU 进入等待调试状态。
-
在 VSCode “运行与调试”面板选择:
Debug xv6 (remote QEMU)然后点 ▶️ 启动调试。
-
在
main.c或trap.c等地方设置断点。 -
现在你可以:
- 单步执行(F10 / F11)
- 查看寄存器、堆栈
- 调用栈浏览
参考
https://www.cnblogs.com/KatyuMarisaBlog/p/13727565.html
https://karthikv1392.github.io/cs3301_osn/slides/Tutorials/xv6_debug_vscode.pdf
调试技巧
可以先单cpu运行,修改makefile
qemu-system-riscv64 -machine virt -bios none -kernel kernel/kernel -m 128M -smp 1 -nographic
可以不启动时钟中断,kernel/start.c
// timerinit(); // 注释掉或暂时禁用
