关于 gdbstub-mcp
gdbstub-mcp 是用于调试 QEMU 中裸机内核的 MCP 服务。它直接使用 GDB Remote Serial Protocol 与 QEMU 通信,无需 gdb 二进制文件,并可根据 QEMU 日志解释 x86 崩溃和三重故障。
主要功能
- 01连接 QEMU gdbstub 会话
- 02读写寄存器和内存
- 03设置断点和观察点
- 04单步、继续并检查执行
- 05解析符号、源码行和回溯
- 06根据 QEMU 日志解释 x86 故障
适用场景
- 01调试运行于 QEMU 的内核
- 02通过断点和单步跟踪执行
- 03检查内核内存与寄存器
- 04根据 QEMU 日志诊断三重故障
MCP 相关
作为 MCP 服务运行,向 MCP 客户端提供调试工具。它使用 GDB Remote Serial Protocol 直接连接 QEMU 的 gdbstub,无需 gdb 二进制文件。
配置
本地服务的配置在各客户端中通用,复制后粘贴到客户端的 MCP 配置文件即可。
工具
18收录的工具列表 · 更新于 3 周前
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| elf | any | 否 | |
| host | string | 否 | |
| name | string | 是 | |
| port | integer | 否 | |
| load_bias | integer | 否 | |
| timeout_s | number | 否 |
详细介绍
gdbstub-mcp
让 AI Agent 调试内核,并告诉你它为何发生三重故障。
gdbstub-mcp 是一个 MCP 服务,为 AI Agent
(Claude Code 或任何 MCP 客户端)提供调试器,用于调试在 QEMU 中运行的裸机代码。它会直接与 QEMU 内置的 gdbstub 通信,使用 GDB Remote Serial Protocol,因此你不需要 gdb 二进制文件。这在 Windows 和 macOS 上尤其有用,因为获取跨架构 gdb 很麻烦。
它是 qemu-mcp 的配套工具。qemu-mcp 让 Agent 启动内核并查看崩溃。gdbstub-mcp 则让它查明原因。
效果展示
Agent 正在调试一个自制内核。以下是真实输出,采集自 tests/fixtures/kernel 中的测试
内核:
> debug_break kernel.c:10
#1 sw breakpoint at 0x100029 <add+0x9> at kernel.c:10
> debug_continue
Stopped: SIGTRAP (breakpoint/step) - breakpoint #1 (kernel.c:10)
pc = 0x100029 <add+0x9> at kernel.c:10
next: mov eax, dword ptr [ebp + 8]
> debug_backtrace
#0 0x100029 <add+0x9> at kernel.c:10
#1 0x100071 <compute+0x31> at kernel.c:16
#2 0x1000b2 <kmain+0x12> at kernel.c:28
#3 0x100016 <_start+0xa> at boot.s:21
> debug_registers eip,eflags,cr0
eip = 0x00100029 <add+0x9> at kernel.c:10
eflags = 0x00000093 [SF AF CF]
cr0 = 0x00000011 [ET PE]
当机器悄无声息地重启时,debug_explain_fault 会读取 QEMU 的中断日志并解释
崩溃原因:
> debug_explain_fault
A TRIPLE FAULT occurred: the CPU reset itself.
[0] #UD invalid opcode at triple_fault+0xa (kernel.c:23)
[1] #GP general protection fault at triple_fault+0xa (kernel.c:23)
selector 0x32: IDT entry 6 = #UD
-> the IDT entry for vector 0x6 is missing or invalid - the CPU couldn't
even start your handler. ...
[2] #DF double fault at triple_fault+0xa (kernel.c:23)
Root cause: the chain started with #UD at triple_fault+0xa.
It escalated to a triple fault because the handler for #UD (IDT entry 0x6)
could not be invoked. Fix the IDT entry so the original exception reaches
your handler, then fix the #UD itself.
真实的 QEMU 崩溃日志有数千行定时器中断和寄存器转储。这个工具会筛选出异常链、解码错误码,并 指出原因。
为什么还要做一个调试器 MCP?
现有的 GDB MCP 服务会封装一个 gdb 二进制文件,面向用户态程序或核心
转储。嵌入式调试器则通过 probe-rs 或 OpenOCD 面向微控制器。它们都不是为 osdev 工作流
设计的:你亲手编写的内核在 QEMU 中运行,却在打印任何内容之前就崩溃。
- 无需 gdb。 纯 Python 实现(
pyelftools+capstone)。运行pip install gdbstub-mcp即可。 - 支持 QEMU 支持的任何架构。 寄存器布局来自 stub 自己的
target.xml。x86 上包含控制寄存器(CR0/CR2/CR3/CR4、EFER),并能解码标志 寄存器。 - 符号和源代码行。 可在
kmain、kmain+0x10或kernel.c:42处设置断点,而且 每次停止都会显示function+offset at file:line。也支持带前缀的 ABI:当名称唯一时,kmain会解析为mort_kmain。 - 适用于真实内核的回溯。 它会遍历帧指针链,并能正确处理 x86 函数序言和
尾声。对于不带帧指针的
-O2内核,它也可以改为扫描栈中的返回地址。 - 三重故障诊断。 如上所述,使用
debug_explain_fault。我还没发现 其他工具能做到这一点。
安装
pip install gdbstub-mcp
Claude Code:
claude mcp add gdbstub -- gdbstub-mcp
其他 MCP 客户端也采用相同方式:将 gdbstub-mcp 作为 stdio 服务运行。需要 Python 3.10+。
用法
启动 QEMU,开启 gdbstub,并让 CPU 保持暂停:
qemu-system-i386 -kernel kernel.elf -s -S -d int,cpu_reset -D int.log -no-reboot
-s在tcp::1234上打开 stub。-S在执行第一条指令前暂停 CPU。-d int,cpu_reset -D int.log -no-reboot仅在使用debug_explain_fault时需要。
使用 qemu-mcp 时,将相同标志通过
qemu_boot 的 extra_args 传入:
extra_args="-s -S -d int,cpu_reset -D int.log -no-reboot"。
然后向你的 Agent 提出类似这样的请求:“使用 kernel.elf 连接到内核,在 kmain 处设置断点,并单步执行,直到发生页故障。”
地址可以写成 0x1234、symbol、symbol+0x10、file.c:42 或 $esp+8。
工具
| 工具 | 功能 |
|---|---|
debug_connect | 连接到 gdbstub(port,默认值为 1234),并可选择加载带符号的 elf。可以同时打开多个具名会话。 |
debug_disconnect | 移除断点、分离(来宾继续运行)并关闭会话。 |
debug_sessions | 列出会话:端点、运行中或已暂停、ELF、断点数。 |
debug_registers | 读取寄存器:指定列表、通用寄存器组,或使用 all=True 读取控制、段和 FPU 寄存器。标志会解码,指针会显示符号信息。 |
debug_set_register | 写入寄存器。 |
debug_memory | 以十六进制转储、带符号信息的指针大小 words,或 string 的形式读取内存。 |
debug_write_memory | 写入字节。 |
debug_break | 设置断点(sw;对于分页前或尚未加载的代码,使用 hw),或设置观察点(write、read、access)。 |
debug_delete / debug_breakpoints | 移除断点,或列出所有断点。 |
debug_continue | 恢复运行,并等待最多 timeout_s 以确认暂停。如果没有暂停,目标将继续运行。 |
debug_wait / debug_interrupt | 持续等待暂停,或立即暂停目标(类似 Ctrl-C)。 |
debug_step | 单步执行 N 条指令。 |
debug_backtrace | 通过帧指针链(fp)、栈扫描(scan)或 auto 获取调用栈。 |
debug_disassemble | 在指定地址或 pc 处反汇编。bits=16 会解码实模式代码。 |
debug_symbol | 离线查找地址、符号或行,无需目标。 |
debug_explain_fault | 根据 QEMU -d int,cpu_reset 日志解释崩溃或三重故障(x86)。 |
限制(实话实说)
- 机器级,而非源代码级。 目前没有
next/finish,也不支持局部变量或 C 表达式(参见 BACKLOG.md)。你可以查看符号、行、寄存器、内存和反汇编,这足以应对大多数内核调试场景。 - 栈扫描是一种启发式方法。 它会报告栈中所有指向已知函数内某个
call之后位置的字,因此可能出现过期栈帧。使用-fno-omit-frame-pointer构建,以获得精确的回溯。 debug_explain_fault仅支持 x86 日志。- 已针对 QEMU 的 gdbstub 进行测试。其他 RSP stub(OpenOCD、Bochs、真实硬件探针)使用相同协议,应该也能运行,但尚未测试。
测试
pip install ".[test]" anyio "ruff==0.16.0" "mypy==2.3.0"
ruff check src tests && mypy --strict src
pytest tests
单元测试使用真实 TCP 套接字上的模拟 gdbstub,以及一份真实的 QEMU 三重故障日志,因此无需 QEMU。tests/test_qemu_integration.py 会在真实 QEMU 中启动夹具内核(CI 会安装 qemu-system-x86)。它会检查断点、观察点、行号、4 层深的回溯以及端到端的三重故障;如果未安装 QEMU,则会跳过自身。要重新构建夹具内核,请运行 python tests/fixtures/kernel/build.py,这需要 pip install ziglang。
许可证
MIT
评论
一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。