项目阶段工作#
第一阶段:2022-2023#
核心目标:从零构建操作系统源代码级调试工具,打通内核/用户态联合调试的基本链路。
基础框架搭建#
- 基于 WebFreak001/code-debug(一个开源的 GDB/LLDB 调试前端)进行 fork,在其基础上扩展操作系统调试能力
- 实现 VS Code 扩展的基本架构:通过 DAP 协议与 VS Code 调试界面交互,通过 GDB/MI 接口控制 GDB
- 支持 QEMU 虚拟机环境下的远程调试
内核态/用户态联合断点调试#
- 提出并实现断点组的核心概念:将用户设置的 GDB 断点按所在的地址空间分组,在任意时刻下只有当前地址空间对应的断点组生效
- 实现断点组切换时的符号表动态加载/卸载:切换地址空间时自动卸载旧符号表、加载新符号表
- 实现内核态 ↔ 用户态的边界检测与自动切换
- 以 rCore-Tutorial 作为首个适配目标,验证联合调试的可行性
eBPF 动态跟踪调试#
- 实现 eBPF 调试面板(WebView)
- 实现基于 eBPF 的内核态、用户态代码动态跟踪,与 GDB 静态断点调试形成互补
调试界面与交互#
- 实现 WebView 面板,提供 eBPF 调试的可视化操作界面
- 实现内存读写功能,寄存器查看功能(RISC-V 寄存器),在侧边栏 TreeView 中展示
- 实现断点表的可视化展示
本阶段遗留的问题#
在完成核心功能验证的同时,也暴露出了很多问题:
- 调试器自动设置的断点不会在 VS Code 中显示出来
- 边界断点的实现逻辑不具有普适性(与内核符号表耦合)
- 代码实现复杂,不易维护和扩展
- 没有实现单步步进功能,Continue 按钮不能适用于所有情况
- 控制台输出杂乱且不完整
- 编译后的插件包体积过大
- 配置文件中存在大量硬编码
第二阶段:2023-2024#
核心目标:全面完善调试器的可用性和通用性,扩展对不同语言(C 语言)和不同运行环境(真实硬件)的支持。
A. 调试器功能完善#
针对第一阶段遗留的问题逐一修复:
1. 断点显示问题
- 利用 VS Code 新增的
debug.addBreakpointsAPI,使调试器自动设置的断点能够在 VS Code 界面中正确显示,解决了插件与 VS Code 的断点同步问题
2. 边界断点重构
- 将边界断点从独立模块改为断点组的属性,逻辑上独立但数据结构上附属于断点组
- 支持通过
customRequest动态设置/取消边界断点 - 新增右键菜单操作:在行号右键即可将断点设为边界断点或取消边界
3. 状态机架构重构
- 引入
OSStateMachine状态机架构,将复杂的内核/用户态切换流程建模为 4 种状态和 5 种事件的状态转移图 - 定义明确的
DebuggerActions(8 种动作),每次状态转移触发对应的动作序列 - 显著提升了代码的可读性、可维护性和可扩展性
4. 单步步进
- 实现
step、stepInstruction、stepOut等单步操作 - 支持在内核/用户态边界自动执行逐指令单步(consecutive single steps),直到 PC 进入目标地址空间
5. Continue 按钮适配
- 改进不依赖跳板页的调试策略
- 通过内存地址范围判断当前所处的特权级(内核态/用户态),自动检测特权级变化
6. 控制台输出优化
- 改进 GDB/MI 输出的解析和展示
- 提供清晰的停止原因提示和状态信息
7. 插件包瘦身
- 在打包时排除
docs/文件夹、演示视频等大型文件 - 通过
.vscodeignore配置,大幅减小.vsix安装包体积
8. 配置文件去硬编码
- 支持
${workspaceFolder}等 VS Code 变量的自动替换 - 将硬编码的文件路径、行号等移入
launch.json,由用户自行配置 - 引入
filePathToBreakpointGroupNames和breakpointGroupNameToDebugFilePaths两个映射函数,用户可在launch.json中自定义文件路径与断点组的对应关系
B. 新增功能#
钩子断点(Hook Breakpoints)
- 实现可在断点触发时执行自定义 JavaScript 函数的钩子断点机制
- 核心用途:在内核进程调度代码处设置钩子,自动获取下一个即将被调度的用户进程名称
- 钩子函数的返回值用于设置
nextBreakpointGroup,使调试器知道即将切换到哪个用户进程
SSH 远程调试
- 恢复并完善 SSH 远程调试功能
- 支持密钥/密码认证、X11 转发
- 实现远程/本地源文件路径自动映射
多进程调试
- 实现 initproc-usershell 多进程调试支持
- 断点组可以动态创建,支持同时调试多个用户态进程
发布到扩展市场
- 更名为 “OS Debugger”,发布到 VS Code Extension Marketplace
- 配置 GitHub Actions 自动化构建和发布流程
- 发布 v2.0.0 里程碑版本
C. C 语言操作系统(xv6)适配#
将调试器的适用范围从 Rust (rCore) 扩展到 C 语言 (xv6):
界面适配
- 修改
package.json,使调试工具栏对所有语言可见(不再局限于 Rust 文件)
多边界断点支持
- xv6 在
usys.S中有多个ecall指令(多个用户态出口),不同于 rCore 的单一出口 - 将边界断点数据结构从单个对象扩展为数组,支持一个断点组拥有多个边界断点
xv6 调试配置
- 编写针对 xv6 的
launch.json配置模板 - 适配 xv6 的 QEMU 启动参数(
virt机器、128M内存、2SMP 核心、virtio 块设备) - 适配 xv6 用户程序的命名规则(编译后格式为
_filename)
钩子断点适配
- 将钩子断点设置在 xv6 的
sysfile.cexec 函数调用处 - 通过钩子函数获取下一个用户进程的名称
D. 真实硬件调试支持(昉·星光 2 开发板)#
将调试器从 QEMU 虚拟环境扩展到真实 RISC-V 硬件:
框架搭建
- 通过 JTAG 接口集成 OpenOCD,OpenOCD 作为 GDB 与硬件之间的中间层
- 实现 U-Boot 加载操作系统的调试流程
硬件部署
- 完成 JLink 连接、串口配置等硬件部署工作
- 编写硬件调试的编译和操作流程文档
硬件适配
- 实现内核态单步调试
- 适配 DCSR 寄存器的限制(不支持修改
stepie字段) - 将边界断点调整为设置在
ecall前一条指令(而非 interrupt handler 入口),以规避硬件限制
E. 工程化改进#
- 支持 RISC-V 汇编文件的断点设置
- 引入寄存器查看功能(从上游合并)
- 编写自动化安装脚本(Shell),支持一键安装所有调试所需的工具和库
- 合并上游(WebFreak001/code-debug)的多项改进:静态变量支持、STL 容器解析修复、GDB Frame Filters 支持、变量类型显示修复等
第三阶段:2024-2025#
核心目标:提升调试器的稳定性和实用性,修复实际使用中的关键 bug,整理项目仓库,开展 Rust 异步调试功能的研究与开发。
Bug 修复与稳定性提升#
- 修复"只能调试到一号进程"的问题,使多进程调试能力真正可用
- 发布 v2.0.1 修复版本
仓库整理#
- 重新组织项目文件结构,整理历史文档和工作记录
- 完善安装说明文档
新方向探索#
- 开展 Rust 异步调试功能的研究与开发