1. QEMU调试环境搭建:安装QEMU、配置GDB、连接调试器

搭建一个稳定、可复现的QEMU调试环境,是后续模拟启动故障与复现硬件异常场景的基础。本节将指导你完成从QEMU安装、GDB配置到调试器连接的全流程,确保每一环节都可验证、可回退。

1.1 环境概览与版本选型

本课程采用以下软件组合,兼顾稳定性与调试特性支持:

组件 推荐版本 关键特性
QEMU 8.2.x (LTS) 支持 GDB stub、TCG 单步、硬件异常注入
GDB 14.x Python 脚本扩展、多架构支持
目标架构 x86_64 / ARMv8-A 覆盖 PC 与嵌入式场景
宿主机 OS Ubuntu 22.04 / 24.04 APT 源直接安装,依赖完整
版本选择说明:QEMU 8.2 LTS 对 GDB 远程调试协议支持最稳定,且修复了早期版本中 TCG 单步与硬件断点冲突的问题。不建议使用 9.0+ 开发版用于课程实验。

1.2 安装QEMU(源码编译 + 模块化配置)

为获得完整的调试符号和自定义编译选项,推荐从源码编译安装:

# 安装编译依赖
sudo apt update
sudo apt install -y build-essential git python3-pip ninja-build \
    libglib2.0-dev libpixman-1-dev libslirp-dev

# 克隆 QEMU 8.2 LTS 源码
git clone -b stable-8.2 https://gitlab.com/qemu-project/qemu.git
cd qemu

# 配置编译选项(开启 GDB stub、TCG 调试、所有目标架构)
./configure --target-list=x86_64-softmmu,aarch64-softmmu \
            --enable-debug --enable-debug-tcg \
            --enable-gdbstub --enable-slirp \
            --prefix=/opt/qemu-8.2

# 编译并安装(-j$(nproc) 并行编译)
make -j$(nproc)
sudo make install

# 验证安装
/opt/qemu-8.2/bin/qemu-system-x86_64 --version
关键编译选项说明:
  • --enable-debug:编译时加入 -O0 -g,保留完整调试符号
  • --enable-debug-tcg:开启 TCG 翻译器调试支持,允许单条指令级跟踪
  • --enable-gdbstub:启用内置 GDB 远程调试服务器

1.3 配置GDB(多架构 + Python 扩展)

GDB 需要支持目标架构并加载 QEMU 的调试符号:

# 安装 GDB 14.x(多架构版本)
sudo apt install -y gdb-multiarch

# 验证架构支持
gdb-multiarch --configuration | grep -E "targets|configure"

# 创建 GDB 初始化脚本 ~/.gdbinit
cat >> ~/.gdbinit << 'EOF'
set architecture i386:x86-64
set pagination off
set confirm off
set print pretty on
set print elements 0
set debug remote 1
EOF
GDB 配置项 作用 调试场景
set architecture 指定目标 CPU 架构 切换 x86_64 / ARM 时需修改
set debug remote 1 显示 GDB 与 QEMU 之间的远程协议包 排查连接失败、断点失效问题
set pagination off 禁用分页,避免调试中断 长时间自动化调试脚本

1.4 连接调试器:QEMU GDB stub 模式

QEMU 以 -s 和 -S 参数启动 GDB stub 服务器,等待 GDB 连接:

# 启动 QEMU,监听 TCP 1234 端口,暂停 CPU 等待调试器
/opt/qemu-8.2/bin/qemu-system-x86_64 \
    -m 2G -smp 2 \
    -kernel /path/to/bzImage \
    -append "console=ttyS0 nokaslr" \
    -nographic \
    -s -S

# 在另一个终端启动 GDB 并连接
gdb-multiarch -q \
    -ex "target remote localhost:1234" \
    -ex "info registers" \
    -ex "x/10i \$rip"
常见连接失败原因:
  • 端口冲突:检查 netstat -tlnp | grep 1234,确保无其他进程占用
  • 防火墙拦截:sudo ufw allow 1234/tcp 或临时关闭防火墙
  • QEMU 未编译 GDB stub:确认 --enable-gdbstub 已加入编译配置

1.5 调试环境架构总览

下图展示了 QEMU 调试环境的整体架构与数据流:

QEMU 调试环境架构图 宿主机调试环境 GDB 调试器 gdb-multiarch Python 扩展脚本 QEMU 进程 qemu-system-x86_64 GDB stub 服务器 TCP :1234 远程调试协议 QEMU 内部调试组件 TCG 翻译器 硬件异常注入 内存映射 设备模型 内部 API 调用 目标机(Guest) x86_64 / ARMv8-A 内核 + 根文件系统 启动故障 / 硬件异常场景

1.6 环境验证清单

完成安装后,逐项验证以下能力:

  1. QEMU 启动验证:执行 qemu-system-x86_64 -M help 应列出所有支持的机器类型
  2. GDB stub 端口监听:启动 QEMU 后 ss -tlnp | grep 1234 应显示 LISTEN 状态
  3. GDB 连接与寄存器读取:连接后 info registers 应返回 CPU 初始状态
  4. 单步执行:stepi 应能逐条指令前进,QEMU 端无超时断开
  5. 断点测试:在 start_kernel 设置断点,continue 后应命中
快速验证脚本:
# 一键验证调试环境连通性
/opt/qemu-8.2/bin/qemu-system-x86_64 -s -S -nographic -M pc -m 512M &
sleep 2
echo "target remote localhost:1234" | gdb-multiarch -q -batch \
    -ex "target remote localhost:1234" \
    -ex "info registers" \
    -ex "quit"
kill %1 2>/dev/null

1.7 常见问题与排错

现象 原因 解决方案
GDB 连接后立即断开 QEMU 未以 -s 启动 检查 QEMU 命令行是否包含 -s
info registers 显示全零 CPU 处于复位状态,未开始执行 使用 -S 暂停是正常行为,执行 continue 即可
断点无法命中 KASLR 导致地址随机化 内核启动参数添加 nokaslr
单步执行卡死 TCG 调试模式未开启 重新编译 QEMU 加入 --enable-debug-tcg