如何使用QEMU和GDB在ARM64内核启动入口点设置断点
ARM64 QEMU内核调试:head.S入口断点设置方案
问题核心原因
- 软件断点失效:MMU未启用阶段,内核运行在物理地址空间,内存处于只读状态(未完成映射/初始化),软件断点需要修改内存写入断点指令,无法生效,必须使用硬件断点。
- 地址匹配问题:
/proc/iomem中显示的内核代码物理地址是MMU开启后的映射基址,并非内核启动时的入口物理地址(内核启动阶段可能存在自迁移操作)。
正确调试步骤
方法一:直接获取启动入口物理地址(最可靠)
QEMU启动参数加了-S,会自动停在CPU初始执行地址(即head.S的_entry入口),连接GDB后直接读取PC寄存器即可得到物理地址:
# 启动GDB并加载符号文件 aarch64-none-linux-gnu-gdb vmlinux # 连接QEMU调试端口 target remote :1234 # 查看当前PC值,即为内核启动入口的物理地址 info registers pc
输出示例:pc 0x40008000 0x40008000
接着设置硬件断点并继续执行:
# 替换为上一步得到的PC值 hbreak *0x40008000 # 继续运行 continue
方法二:通过符号计算物理地址
如果想提前计算入口物理地址,可通过内核符号文件推导:
- 在主机上查看
_entry的虚拟地址:
aarch64-none-linux-gnu-nm vmlinux | grep _entry # 输出示例:ffff000040210000 T _entry
- 计算物理地址:ARM64内核默认虚拟地址偏移(
PAGE_OFFSET)为0xffff000000000000,物理地址 = 虚拟地址 -PAGE_OFFSET,即0xffff000040210000 - 0xffff000000000000 = 0x40210000。 - 启动GDB设置硬件断点:
aarch64-none-linux-gnu-gdb vmlinux # 设置硬件断点 hbreak *0x40210000 target remote :1234 continue
额外注意事项
- 硬件断点数量有限(ARM64架构通常支持最多4个),调试完成后可使用
delete命令清除。 - 确保
Image内核镜像与vmlinux符号文件为同一编译版本,否则会出现地址不匹配问题。
内容的提问来源于stack exchange,提问作者Alan
相关产品推荐
相关产品推荐

