QEMU 88 - Debug with QEMU Monitor
# 前言
尽管在多数情况下,用 gdb 足以定位和解决运行在 QEMU 上的系统软件的错误,但并非总是如此——例如,系统软件中的错误有时会导致 QEMU 神秘地重启,CPU reset 导致你无法获得足够有效的运行时信息。更有甚者,在个别情况下 gdb 对执行环境的变化导致那个错误在 gdb 单步调试时便不会触发,对我们定位错误带来了巨大的困难。在这种情况下,QEMU Monitor 就是我们的下一个选择。
QEMU Monitor 使我们能够监测 QEMU 模拟硬件的状态,包括查看物理内存、获取 CPU reset 时刻的寄存器现场、等等,对调试系统软件能起到巨大的帮助。这也是使用虚拟环境的意义之一,毕竟调试软件总比调试硬件要容易多了。
事实上,QEMU Monitor 还有许多其它的强大功能,但本文只涉及那些能用于缺陷定位和调试的部分。
除非特殊声明,下文的所有命令都是在 QEMU Monitor 中键入的。
# 启动
启动 QEMU Monitor 有多种方法,这里汇总介绍了其中比较常用的三种。
在 QEMU 模拟器界面内,可以通过快捷键 CTRL + ALT + {1, 2, 3}
分别在模拟器主屏幕、QEMU Monitor 和 QEMU Console 之间切换。
在使用 character backend multiplexer 时,可以通过组合快捷键 CTRL + A
then C
在模拟器主屏幕和 QEMU Monitor 之间切换,其中 CTRL + A
实际上是转义字符。
character backend multiplexer 是 QEMU 官方文档中的名词,但我尚不清楚这是什么意思。
在实践中,这是指通过 shell 启动 QEMU 时在 shell 中输入按键,包括通过
-nographic
选项启动 QEMU 的情况。
可以使用 telnet 以便在另外的窗口接入 QEMU Monitor 。这需要在启动时使用如下参数(端口可自设):
-curses -monitor telnet:127.0.0.1:8888,server,nowait
然后在另外的 shell 窗口内用 telnet 接入相同的端口即可:
telnet 127.0.0.1 8888
# 基本命令
help <cmd>
:获取命令 cmd
的帮助信息。
stop
或 s
:暂停仿真。
cont
或 c
:继续仿真。
singlestep [off]
:开启或关闭单步模式。
print/<format> <expr>
或 p/<format> <expr>
:输出表达式 expr
的值。
format
:输出值的格式,可取值为十六进制x
、十进制d
、无符号十进制u
、八进制o
、字符c
、asm 指令i
。expr
可以使用语法$<reg>
获取寄存器reg
的值,例如p/x $esp
。
# 内存相关命令
# 输出内存中的数据
x/<fmt> <addr>
:输出从 addr
开始的虚拟内存中的数据。
xp/<fmt> <addr>
:输出从 addr
开始的物理内存中的数据。
其中 fmt
用于指定命令输出数据的格式,其语法为 /{count}{format}{size}
:
count
:输出的项数。format
:每项的数据格式,可取值为十六进制x
、十进制d
、无符号十进制u
、八进制o
、字符c
、asm 指令i
。size
:每项的内存大小,可取值为 位b
、 位h
、 位w
、 位g
。
下面是官方文档中提供的指令使用示例:
(qemu) x/10i $eip
0x90107063: ret
0x90107064: sti
0x90107065: lea 0x0(%esi,1),%esi
0x90107069: lea 0x0(%edi,1),%edi
0x90107070: ret
(qemu) xp/32hx 0xb8000
0x000b8000: 0x0b50 0x0b6c 0x0b65 0x0b78 0x0b38 0x0b36 0x0b2f 0x0b42
0x000b8010: 0x0b6f 0x0b63 0x0b68 0x0b73 0x0b20 0x0b56 0x0b47 0x0b41
0x000b8020: 0x0b42 0x0b69 0x0b6f 0x0b73 0x0b20 0x0b63 0x0b75 0x0b72
0x000b8030: 0x0b72 0x0b65 0x0b6e 0x0b74 0x0b2d 0x0b63 0x0b76 0x0b73
# 输出内存映射情况
gva2gpa addr
:根据 guest CPU 的映射,输出 guest 中虚拟地址 addr
所映射的物理地址。
# Log 命令
log <item>
:设定自动输出各种指定类型的日志信息,其中 item
的可选项详见下文。
- 亦可同时设定输出多种日志,语法格式为
log <item1>, <item2>, ...
。
logfile <filename>
:将日志信息输出到指定文件。
QEMU Monitor 支持的部分日志信息如下,可以使用 help log
命令查看完整内容:
log item | usage |
---|---|
int | 显示中断和异常信息 |
mmu | 显示 MMU 相关信息 |
cpu_reset | 在 CPU reset 前显示 CPU 状态 |
none | 移除已经设定的所有 log item |
# Info 命令
info <subcommand>
:输出各种有关系统状态的信息,其中 subcommand
的可选项详见下文。
QEMU Monitor 支持的部分 info 信息如下,可以使用 help info
命令查看完整内容,或参阅官方文档:
subcommand | usage |
---|---|
version | 显示 QEMU 的版本信息 |
history | 显示命令行的历史信息 |
cpu | 显示每个 CPU 的信息 |
registers | 显示当前 CPU 的寄存器信息 |
lapic | 显示本地 APIC 的状态 |
tlb | 显示内存映射情况 |
mem | 显示活动的内存映射 |
mtree | 显示内存树 |
# 快照相关命令
savevm <tag>
, loadvm <tag>
, delvm <tag>
:保存、加载和删除标记为 tag
的、整个 QEMU 虚拟机的快照。
- 01
- Reading Papers - Kernel Concurrency06-01
- 02
- Linux Kernel - Source Code Overview05-01
- 03
- Linux Kernel - Per-CPU Storage05-01