qemu调试edk2
qemu调试edk2
一、正确加载正确加载调试符号文件**SecMainRiscV64.debug
是包含调试符号的文件(.debug
后缀通常为调试符号文件),需通过 GDB 加载它以获得符号支持(如 _ModuleEntryPoint
等函数名)。
在终端中完整输入以下命令(补全目录和文件名):
/opt/riscv/bin/riscv64-unknown-elf-gdb Build/RiscVVirtQemu/RELEASE_GCC5/RISCV64/SecMainRiscV64.debug
执行后会进入 GDB 交互界面,类似:
GNU gdb (GDB) 12.1
Copyright (C) 2022 Free Software Foundation, Inc.
...
Reading symbols from Build/RiscVVirtQemu/RELEASE_GCC5/RISCV64/SecMainRiscV64.debug...
(gdb)
二、连接 QEMU 调试端口
假设你已启动 QEMU 并开启调试端口(如监听 1234 端口):
qemu-system-riscv64 -nographic \-bios Build/RiscVVirtQemu/RELEASE_GCC5/RISCV64/SecMainRiscV64.efi \-s -S # -s: 监听 1234 端口;-S: 启动后暂停等待 GDB 连接
在 GDB 中连接 QEMU:
(gdb) target remote localhost:1234
Remote debugging using localhost:1234
0x0000000000001000 in ?? ()
三、在 SEC 阶段入口设置断点
加载符号后,可直接通过函数名设置断点(如之前提到的 _ModuleEntryPoint
):
(gdb) break ASM_PFX(_ModuleEntryPoint)
Breakpoint 1 at 0xXXXXXXXX: file CpuAsm.asm, line XX. # 若符号正确加载,会显示断点位置
若符号未识别(可能因构建配置问题),可通过地址设置断点:
- 先查看
SecMainRiscV64.debug
的反汇编,找到_ModuleEntryPoint
的地址:
假设输出为/opt/riscv/bin/riscv64-unknown-elf-objdump -d Build/RiscVVirtQemu/RELEASE_GCC5/RISCV64/SecMainRiscV64.debug | grep _ModuleEntryPoint
0x80000100 <ASM_PFX(_ModuleEntryPoint)>: ...
,则:(gdb) break *0x80000100
四、开始调试
-
让 QEMU 继续执行,等待断点命中:
(gdb) continue
-
若断点命中,GDB 会暂停并显示当前执行位置,此时可使用以下命令调试:
si
:单步执行一条汇编指令(进入函数)ni
:单步执行一条汇编指令(不进入函数)info registers
:查看 RISC-V 寄存器(如sp
、pc
)x /10i $pc
:查看当前程序计数器(pc
)附近的汇编指令
五、常见问题解决
-
符号无法识别:
- 确保 EDK II 以
DEBUG
模式构建(-b DEBUG
),RELEASE
模式可能剥离符号; - 检查
SecMainRiscV64.debug
是否存在且完整(可通过file
命令验证:file SecMainRiscV64.debug
)。
- 确保 EDK II 以
-
连接 QEMU 失败:
- 确认 QEMU 已启动且带有
-s
参数; - 检查端口是否被占用(如换用
-gdb tcp::1235
并在 GDB 中连接1235
端口)。
- 确认 QEMU 已启动且带有
-
断点未命中:
- 确认固件加载路径正确(QEMU 的
-bios
参数指向的SecMainRiscV64.efi
与调试符号文件匹配); - 通过 QEMU 监控器(如
info mtree
)确认固件加载地址与 GDB 符号地址一致。
- 确认固件加载路径正确(QEMU 的
通过以上步骤,可验证 QEMU 是否执行到目标汇编代码(_ModuleEntryPoint
),并逐步调试 SEC 阶段的启动流程。