2011年10月6日 星期四

如何使用Bochs來Debug GRUB2 & Kernel

参考以下文章:
http://www.linuxsir.org/bbs/thread356982.html
http://man.he.net/man8/grub-setup
http://blog.csdn.net/zhouyelihua/article/details/6683437
http://www.gnu.org/software/grub/manual/grub.html#Installing-GRUB-using-grub_002dinstall
http://read.pudn.com/downloads153/ebook/675818/linux-0.11-040304/bochsrc-hd-new.bxrc__.htm

由於bochs內建調試功能, 且支援gdb, 用它調試內核會很方便.
假設你已經build好grub,這裡我舉的例子是使用grub1.99,若還沒有Build,現在正是時候:
1 ./configure CFLAGS=-g
2 make
3 sudo make install 
在ubuntu下預設是安裝到usr/local/lib/grub/i386-pc,別擔心會影響到您的開機MBR,因為make install只是將一些GRUB的各個executable Binary及mod模組存放到指定的prefix,除非你執行grub-install和update-grub 等指令才有可能去動到MBR。
以下指令請使用Root身份執行
1.1構建磁碟影像檔dd if=/dev/zero of=hd0.img count=$((63*16*100))
用這個命令可以構建一個50MB左右的磁片鏡像, 輸出結果如下:
100800+0 records in
100800+0 records out
51609600 bytes (52 MB) copied, 0.734578 s, 70.3 MB/s
注意count必須為63*16的倍數, 否則bochs識別硬碟會有問題.
1.2 掛載磁碟影像losetup /dev/loop0 hd0.img
這個命令可以將檔綁定到一個loop設備. 如果/dev/loop0不存在, 可以嘗試 modprobe loop.
然後進行設備初始化:cfdisk -s 63 -h 16 /dev/loop0
畫面如下橘色文字:
                         cfdisk (util-linux-ng 2.17.2)

                               硬碟: /dev/loop0
                      大小: 51609600 位元組(B), 51 MB
           磁頭: 16   每一磁軌的磁區數: 63   磁柱數: 100

    分割區名稱  屬性旗標   分割區型態 檔案系統型態     標記名稱       大小 (MB)
 ------------------------------------------------------------------------------
                            主要/邏輯 剩餘空間                            51.61

     [  說明  ]    [  新增  ]    [  列印  ]    [  離開  ]    [  單位  ]
     [  寫入  ]

                    由剩餘空間切一個新的分割區

只創建一個主要磁碟分割就可以,並設定 [使可開機] , 寫入後, 用命令fdisk檢查結果。
指令:fdisk -lu /dev/loop0 結果畫面如下:當然Linux版本不同,畫面難免大同小異
磁碟 /dev/loop0: 51 MB,51609600 位元組
16 磁頭,63 磁區/磁軌,100 磁柱,總計 100800 磁區
單位 = 磁區 之於 1 * 512 = 512 位元組
磁區大小 (邏輯/實體):512 位元組 / 512 位元組
I/O 大小 (最小/最佳化):512 位元組 / 512 位元組
磁碟識別碼:0x00000000

所用裝置 開機      開始         結束      區塊   識別號  系統
/dev/loop0p1   *          63      100799       50368+  83  Linux
接著將分區1掛載到/dev/loop1:losetup /dev/loop1 hd0.img -o $((63*512))
格式化/dev/loop1ext3格式.:mkfs.ext3 /dev/loop1
mnt下創建img目錄, 做以後維護用:mkdir -p /mnt/img
loop1掛載到/mnt/img:mount /dev/loop1 /mnt/img/
安裝引導程式. 因為我狂熱傾向於模組化架構, 所以選擇GRUB2.
mkdir /mnt/img/boot
cp -r /usr/lib/grub/i386-pc/ /mnt/img/boot/grub
這個/usr/lib/grub/i386-pc是你的GRUB2安裝路徑,像我的1.98及1.99版在ubuntu下是安裝在以下路徑:/usr/local/lib/grub/i386-pc
接著生成一個core.img, biosdisk模組負責讀取磁片, part_msdos模組負責處理MBR,ext2模組負責讀取ext3分區:
cd /mnt/img/boot/grub/
grub-mkimage -o core.img biosdisk part_msdos ext2   #1.98版使用這個指令
grub-mkimage -O i386-pc -o core.img biosdisk part_msdos ext2  #1.99版使用這個指令
注意,這個core.img還不是個可開機用的影像檔。它並未包含boot.img及diskboot.img。
接著安裝grub2(hd0), 根目錄在(hd0,1)
echo "(hd0)   /dev/loop0" > ./device.map
grub-setup -m ./device.map -d /mnt/img/boot/grub/ -r '(hd0,1)' '(hd0)'
其實上面這2行也可以用下面一行取代
grub-setup -d /mnt/img/boot/grub/ --force /dev/loop0
檢查一下/dev/loop0安裝成果:
hexdump -C /dev/loop0 | less
00000180  7d e8 2e 00 cd 18 eb fe  47 52 55 42 20 00 47 65  |}.......GRUB .Ge|
00000190  6f 6d 00 48 61 72 64 20  44 69 73 6b 00 52 65 61  |om.Hard Disk.Rea|
清理一下
離開終端,重新開一個終端,否則umount會失敗,若你不是以root執行的話
umount /mnt/img
losetup -d /dev/loop1
losetup -d /dev/loop0
2.1建立.bochsrc檔如下:說明一下,在linux下預設是讀取.bochsrc這個檔名,所以你若創建一個叫bochs.bxrc或其他檔名,則等一下開啟bochs時,指令如下:
bochs -q -f bochs.bxrc,否則只須下bochs -q
###############################################################
# bochsrc.bxrc file for kenos disk image.
###############################################################
megs: 32
romimage: file=/usr/share/bochs/BIOS-bochs-legacy, address=0xf0000
vgaromimage: file=/usr/share/bochs/VGABIOS-lgpl-latest
# hard disk
ata0-master: type=disk, mode=flat, path="/home/benson/working_benson/DBG_grub/hd0.img", cylinders=100, heads=16, spt=63
#ata0-slave: type=cdrom, path="/home/marc/setups/slax-6.0.9.iso", status=inserted
# choose the boot disk.
boot: c
# where do we send log messages?
log: bochsout.txt
# disable the mouse, since DLX is text only
mouse: enabled=0
keyboard_mapping: enabled=1, map=/usr/share/bochs/keymaps/x11-pc-us.map
#keyboard_mapping: enabled=1, map=$BXSHARE/keymaps/x11-pc-fr.map
#keyboard_mapping: enabled=1, map=$BXSHARE/keymaps/x11-pc-de.map
#keyboard_mapping: enabled=1, map=$BXSHARE/keymaps/x11-pc-es.map
#cpu: count=1, ips=10000000
# Make the PIT emulated by bochs tick at the correct interval. Note that
# enabling this feature sacrifices reproducibility, which may be a problem
# at times when tracking a specific bug.
#clock: sync=realtime, time0=utc
# For debugging with gdb.
# Keep this line when using bochs-gdb.
# Comment it out when using bochs-dbg
# See http://bochs.sourceforge.net/doc/docbook/user/bochsrc.html#BOCHSOPT-GDBSTUB
#gdbstub: enabled=1, port=1234, text_base=0, data_base=0, bss_base=0
使用bochs開啟hd0.img
bochs -f bochsrc.bxrc 雖然會顯示unknown filesystem
















解決辦法:
grub rescue>set prefix=(hd0,1)/boot/grub
grub rescue>root=(hd0,1)
grub rescue>insmod normal
grub rescue>normal
這樣就可以回到grub> 或選單狀態了。
此時也可以輸入help及其他command line指令了。
接著我們來試試如何使用gdb來debug GRUB2:
先在bochsrc.bxrc最後面加入幾行來使gdb connect to Bochs:

# Attach ne2000 to PCI bus, so that GRUB Legacy detects it automatically

i440fxsupport: enabled=1, slot1=ne2k
# Enable the ne2000 NIC and the builtin TFTP server
ne2k: ioaddr=0x240, irq=9, mac=b0:c4:20:00:00:01, ethmod=vnet, ethdev="/"
# Enable the GDB remote stub
gdbstub: enabled=1

現在先開啟另一個終端輸入gdb,並重新啟動bochs -qf bochsrc.bxrc指令
gdb會出現如下畫面:藍色字為輸入指令
GNU gdb (Ubuntu/Linaro 7.2-1ubuntu11) 7.2
Copyright (C) 2010 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-linux-gnu".
For bug reporting instructions, please see:
(gdb) target remote localhost:1234
Remote debugging using localhost:1234
0x0000fff0 in ?? ()
(gdb)file kernel.exec
A program is being debugged already.
Are you sure you want to change the file? (y or n) y
Reading symbols from /home/benson/kernel.exec...done.

(gdb) b
No default breakpoint address now.
(gdb) b main
Breakpoint 1 at 0xc4fd: file kern/main.c, line 175.
(gdb) c
Continuing.
Program received signal SIGTRAP, Trace/breakpoint trap.
0x0000e05c in ?? ()
(gdb) c
Continuing.
Breakpoint 1, grub_main () at kern/main.c:175
warning: Source file is more recent than executable.
175
(gdb) list
170 void
171 grub_main (void)
172 {
173  /* First of all, initialize the machine.  */
174  grub_machine_init ();
175
176  /* Hello.  */
177  grub_setcolorstate (GRUB_TERM_COLOR_HIGHLIGHT);
178  grub_printf ("Welcome to GRUB!Benson Debug Here!\n\n");
179  grub_setcolorstate (GRUB_TERM_COLOR_STANDARD);
(gdb) 
執行過程如下圖所示:














這張圖是修改過source code,所以下一張圖會多出Benson Debug Here!字樣。















若是你的gdb無法connect到bochs,可能你須要重新build一次Bochs,動作如下:
註:--enable-gdb-stub和--enable-debugger是互斥的
1 ./configure --enable-gdb-stub
2 make
3 sudo make install
update.....

--> 閱讀更多...