如何使用GDB与QEMU调试Linux内核引导加载程序?
调试Linux引导加载程序:QEMU+GDB常见问题解决
初始地址0xFFF0的说明
- 0x0000fff0是x86架构CPU加电后的BIOS初始执行入口(实模式下映射到物理地址0xFFFF0),此时CPU刚启动,正在执行BIOS的初始化代码,还远未到MBR(0x7C00)的执行阶段。这个地址和栈指针无关,也不代表已经跳过引导加载程序启动点,只是BIOS启动的起始位置。
为什么0x7C00断点不触发?
你用qemu-system-x86_64 -kernel vmlinux启动时,QEMU会直接跳过BIOS的MBR引导流程,把内核镜像加载到内存并启动,MBR的0x7C00代码根本不会被执行,自然断点无法触发。要调试引导加载程序(MBR或Linux自带的bootloader),必须让QEMU从完整的磁盘镜像启动,走正常的BIOS引导流程。
调试引导加载程序的正确步骤
1. 生成包含引导加载程序的磁盘镜像
如果要调试Linux的bootloader(如arch/x86/boot下的代码),先编译内核得到bzImage,然后制作一个可引导的虚拟磁盘:
# 创建空镜像文件 dd if=/dev/zero of=disk.img bs=1M count=10 # 挂载镜像并创建文件系统 sudo losetup /dev/loop0 disk.img sudo mkfs.ext4 /dev/loop0 sudo mount /dev/loop0 /mnt # 复制内核并安装GRUB引导 sudo cp arch/x86/boot/bzImage /mnt/vmlinuz sudo grub-install --root-directory=/mnt /dev/loop0 # 卸载并释放循环设备 sudo umount /mnt sudo losetup -d /dev/loop0
2. 修改QEMU启动命令
去掉-kernel参数,改用磁盘镜像启动,同时保留调试开关:
qemu-system-x86_64 -m 256 -hda disk.img -s -S
3. GDB调试配置
连接QEMU后,需要先切换到实模式架构(BIOS和MBR都在实模式下执行):
target remote :1234 # 切换到8086实模式架构 set architecture i8086 # 设置MBR入口断点 b *0x7C00 continue
触发断点后即可调试MBR代码。如果要调试Linux的bootloader(如setup.S),可以用add-symbol-file加载对应的符号文件:
# 加载setup的符号,地址需要对应bootloader加载到内存的位置 add-symbol-file arch/x86/boot/setup 0x00007e00
当系统进入保护模式后,再切换回x86_64架构:
set architecture i386:x86-64
关于lx-symbols的问题
lx-symbols是Linux内核提供的GDB辅助脚本,它依赖内核已经启动到能访问内核符号表的阶段(比如start_kernel之后)。在引导加载程序的早期阶段(实模式/早期保护模式),内核还未完成初始化,无法访问符号表,所以会出现内存访问错误,这是正常现象。
内容的提问来源于stack exchange,提问作者Jeremy
相关产品推荐
相关产品推荐

