用 gdb 和 qemu 调试 grub

由于qemu内置了gdbserver,因此咱们能够用gdb调试qemu虚拟机上执行的代码,并且不受客户机系统限制。ios

如下内容是我调试 grub 0.97 时的一份笔记。sass

准备架构

qemu, gdb,以及一份带grub的虚拟机镜像,一份grub源码。spa

调试过程调试

启动虚拟机code

$ sudo qemu-system-x86_64 -s -S -m 256 -hda test.img

而后使用gdb链接server

$ gdb (gdb) target remote localhost:1234 (gdb) set architecture i8086 (gdb) break *0x7c00 (gdb) cont

一开始CPU是工做在实模式下,为了gdb显示正常咱们把架构设置为i8086blog

BIOS会把MBR加载到内存0x7c00处,咱们在这里下断点,而后执行内存

查看一下当前的反汇编代码rem

(gdb) x/4i $pc =>  0x7c00:        jmp        0x7c4a
    0x7c02: nop 0x7c03:        add        %al,(%bx,%si) 0x7c05:        add        %al,(%bx,%si)

显示的是 att 风格的汇编代码,若是不习惯能够切换成 intel 风格的。

(gdb) set disassembly-flavor intel (gdb) x/4i $pc =>  0x7c00:        jmp        0x7c4a
    0x7c02: nop 0x7c03:        add        BYTE PTR [bx+si],al 0x7c05:        add        BYTE PTR [bx+si],al

上来就是一个无条件跳转,咱们先执行一步,再查看下代码。

(gdb) ni (gdb) x/8i $pc =>  0x7c4a: cli 0x7c4b: nop 0x7c4c: nop 0x7c4d:        test       dl,0x80
    0x7c50:        jne        0x7c54
    0x7c52:        mov        dl,0x80
    0x7c54:        jmp        0x0:0x7c59
    0x7c59:        xor        ax,ax

在gdb里查看汇编代码不够方便,咱们试着把MBR提取出来,再用IDA打开。

$ sudo dd if=/dev/sda of=mbr.hex bs=512 count=1

对照一下grub的源码,大体能推断出这个就是stage1的代码。

其余几个经常使用的gdb命令

单步步入
(gdb) si
查看断点
(gdb) info breakpoints
删除断点
(gdb) delete

grub 启动过程总结

阶段:stage1
数据来源:MBR
内存地址:0x7c00
源码:/stage1/stage1.S
这段代码的做用就是加载MBR以后的1个扇区到0x2000处。

阶段:stage1.5
数据来源:MBR以后的几个扇区
内存地址:0x2000
源码:/stage2/start.S
这段代码的做用是把stage1.5剩余的扇区加载到0x2200,由于stage1只加载了stage1.5的第一个扇区。
源码:/stage2/asm.S
这段代码的做用是初始化部分环境,最后调用 init_bios_info
源码:/stage2/common.c
这段代码的做用是初始化c语音环境,最后调用 cmain
源码:/stage2/stage1_5.c
这段代码的做用是加载stage2到0x8000处,而后跳转到0x8200执行。

阶段:stage2数据来源:/boot/grub/stage2内存地址:0x8000源码:/stage2/stage2.c等后面就是grub的主要功能,显示菜单,启动客户系统等。客户机的Linux内核是加载到0x100000内存地址。

相关文章
相关标签/搜索