用 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內存地址。

相關文章
相關標籤/搜索