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