4. QEMU 日志系统详解:-d 参数选项、日志类别与输出控制
调试 RISC-V 系统,说白了就是跟日志打交道。QEMU 的 -d 参数就像一把瑞士军刀,能帮你切开模拟器的黑盒子,看到里面到底在干什么。我刚开始用 QEMU 的时候,总觉得这参数太复杂,后来踩了几个坑才明白——用好日志,调试效率能翻好几倍。
4.1 -d 参数:日志的开关
-d 是 QEMU 最核心的调试开关。它的用法很简单:
qemu-system-riscv64 -d [日志类别] [其他参数]
你可以指定一个或多个类别,用逗号隔开。比如:
qemu-system-riscv64 -d in_asm,cpu -kernel vmlinux
这行命令会同时输出指令反汇编和 CPU 状态变化。我个人习惯先开 in_asm 看看指令流,再根据情况加其他类别。
-d help 查看完整列表。QEMU 会列出所有支持的类别,非常方便。
4.2 日志类别详解:in_asm、cpu、exec 等
日志类别是 -d 参数的核心。我挑几个最常用的给你讲讲,这些都是我在实际项目中反复用到的。
| 日志类别 | 输出内容 | 适用场景 |
|---|---|---|
in_asm |
每条指令的反汇编(翻译后的代码) | 跟踪指令执行流,检查代码是否按预期运行 |
cpu |
每条指令执行前后的 CPU 寄存器状态 | 调试寄存器值变化,比如 PC、SP、通用寄存器 |
exec |
每条指令的 PC 地址和执行次数 | 统计指令执行频率,定位热点代码 |
int |
中断和异常事件 | 调试中断处理流程,检查中断是否被正确触发 |
mmu |
MMU 地址转换过程 | 调试页表、虚拟地址到物理地址的映射 |
guest_errors |
客户机(Guest)的错误信息 | 快速定位客户机代码中的异常行为 |
举个例子,我曾经调试一个 RISC-V 的启动代码,发现程序跑到某个地址就卡住了。我开了 in_asm 和 cpu,结果发现 PC 值跳到了一个未初始化的内存区域。嗯,原来是链接脚本把代码段放错了位置。
in_asm 看指令流,再根据问题加 cpu 或 int。
4.3 日志级别控制:-d 的进阶用法
你以为 -d 只能开和关?其实它还能控制日志的详细程度。QEMU 支持用 + 和 - 来调整级别。
# 开启 in_asm,并增加详细程度
qemu-system-riscv64 -d in_asm,+in_asm_detail
# 开启 cpu,但减少寄存器输出
qemu-system-riscv64 -d cpu,-cpu_all
你想想看,这有什么用?比如你只想看 PC 和 SP 的变化,不想看所有寄存器,就可以用 -cpu_all 来过滤。我遇到过一种情况:客户机跑着跑着突然崩溃,日志刷了几万行。我加了 -cpu_all 后,只看到 PC 和 SP 的变化,很快就发现 SP 被写成了一个非法地址。
-d help 确认当前版本支持的选项。
4.4 日志文件输出:-D 参数
默认情况下,日志会直接打印到终端。但调试复杂系统时,终端刷屏根本看不过来。这时候就需要 -D 参数把日志输出到文件。
qemu-system-riscv64 -d in_asm,cpu -D qemu.log -kernel vmlinux
这会把所有日志写入 qemu.log 文件。我个人习惯用 -D 配合 -d,这样可以在调试结束后慢慢分析日志,而不是盯着终端看。
还有一个实用技巧:用 -D 输出到文件后,可以用 grep 或 awk 快速过滤关键信息。比如:
# 只查看 CPU 状态变化
grep "cpu" qemu.log
# 统计指令执行次数
grep "exec" qemu.log | wc -l
我曾经用这个方法定位过一个死循环问题。客户机卡在某个循环里,我开了 exec 日志,然后用 grep 统计 PC 地址的出现次数。结果发现某个地址被执行了上百万次,而其他地址几乎没动。嗯,问题就出在那个循环条件上。
in_asm 或 cpu 后。建议先在小规模测试中确认日志类别,再用于完整系统。
4.5 知识结构图:日志系统的核心逻辑
下面这张图展示了 QEMU 日志系统的整体结构。你可以看到从 -d 参数到日志输出的完整流程。
4.6 实战建议:如何高效使用日志
说了这么多,我总结几条实战建议,都是我自己踩坑换来的经验。
- 先小后大: 先在小规模测试中确认日志类别,再用于完整系统。不然日志文件可能大到让你崩溃。
- 组合使用: 不要只开一个类别。比如
in_asm配合cpu,能同时看到指令和寄存器变化,定位问题更快。 - 善用 grep: 日志输出到文件后,用
grep过滤关键信息。比如grep "PC=" qemu.log只看 PC 变化。 - 注意性能: 开日志会降低模拟速度。尤其是
in_asm和cpu,会让 QEMU 慢好几倍。调试时尽量用精简的测试用例。
in_asm 和 cpu,结果日志文件在几分钟内涨到了几个 GB。后来我改用 exec 只记录 PC 地址,才把问题定位到。记住:日志不是越多越好,够用就行。
好了,关于 QEMU 日志系统,核心就是这些。用好 -d 和 -D,你就能像看 X 光片一样,看清模拟器内部的每一个细节。下次遇到奇怪的问题,不妨先开个日志看看。