Search Google

Thursday, June 05, 2008

Debugging Linux Kernel Without KGDB Patch (Qemu + GDB)

1) Get Linux kernel source code & Qemu package
要debug Linux kernel首先當然要先拿到原始碼,可以從官方網頁取得[1],也可以從package repository取得,如[2]中第十個步驟所述。
安裝Qemu套件的指令為:
$ sudo aptitude install qemu qemu-launcher qemubuilder qemuctl
2) Prepare Qemu disk image
接下來是設定debug環境,由於我們借助Qemu進行kernel debugging,因此首先要建立Qemu的磁碟映像檔。


利用Qemu launcher[3]可以很輕鬆的在指定路徑建立磁碟映像檔,這裡我們使用raw格式的磁碟映像以便稍後如果有轉換需要的話可以進行轉換。
此範例將Qemu disk image存放於~/Qemu中(請先行建立此資料夾),命名為kernel-hacking,容量為1000MB,完整路徑為:
~/Qemu/kernel-hacking
3) Prepare debugging environment
磁碟準備好之後我們需要在磁碟中安裝minimum install的Linux,在這裡我們需要下載debian的安裝光碟[4]。
等安裝光碟下載完成之後就可以使用Qemu launcher指定使用CD-ROM開機,當然要記得將CD-ROM指到剛剛下載的安裝光碟。


為了壓低硬碟使用量,安裝過程中我們只要選擇安裝base system即可。安裝完畢之後將開機選項改為使用硬碟開機再重新開機確認安裝完成。


完成此步驟的用意是方便以後置換target Linux kernel (要被debug的Linux kernel)
4) Compile target Linux kernel
* 以下的所有步驟都在原本的機器上進行,非Qemu中。
現在我們要準備編譯即將被debug的Linux kernel,假設我們將Linux kernel source解壓縮至"~/src/linux-source/v2.6.24",而目前正在運行的Linux版本為2.6.24-18。
首先我們需要設定kernel,指令為:
~/src/linux-source/v2.6.24$ cp /boot/config-2.6.24-18-generic .config
~/src/linux-source/v2.6.24$ sudo aptitude install ncurses-dev kernel-package build-essential
~/src/linux-source/v2.6.24$ make menuconfig
設定畫面看起來會像下面這張圖:


我們先到選單最下面選擇Load an Alternate Configuration File,讀取.config中的預設值。
接著在介面中先選擇進入Device Drivers,先將ATA/ATAPI/MFM/RLL support設定為編入kernel中(按空白鍵改變模式直到看到"*"符號)再選擇它(利用TAB鍵將由標移到Select上按Enter)進入下一層選單將Enhanced IDE/MFM/RLL disk/cdrom/tape/floppy support設定為編入kernel中,接著將Include IDE/ATA-2 DISK support也設定為編入kernel中。
最後回到最上層的目錄選擇進入File systems將Ext3 journalling file system support設定為編入kernel中。
現在離開make menuconfig的操作介面,離開時可以選擇儲存設定檔。
將Device Drivers與File systems的那些選項編入kernel中的好處是我們在稍後的作業中可以省去製作ramdisk [5]的步驟。
在編譯kernel之前先將Makefile打開:
~/src/linux-source/v2.6.24$ vim Makefile
將EXTRAVERSION = .3 --改為--> EXTRAVERSION = .3-Qemu
方便之後開機時辨識。
完成以上程序之後便可以開始編譯target Linux kernel,指令為:
~/src/linux-source/v2.6.24$ make
稍微等待一陣子之後我們便可以在~/src/linux-source/v2.6.24/arch/x86/boot下找到bzImage,這便是我們的 target Linux kernel,而我們可以將存在於~/src/linux-source/v2.6.24/下的vmlinux視為稍後debug過程中使用到的 symbol table。
5) Copy target Linux kernel to Qemu disk image
現在我們先在家目錄下建立名為tmp的空資料夾,然後將Qemu disk image掛載到tmp上讓我們可以將步驟4最後產生出來的target Linux kernel複製到Qemu disk image中並且修改掌控開機選單的menu.list,指令為:
~/src/linux-source/v2.6.24$ mkdir ~/tmp
~/src/linux-source/v2.6.24$ sudo mount -o loop,offset=32256 ~/Qemu/kernel-hacking ~/tmp
~/src/linux-source/v2.6.24$ sudo cp arch/x86/boot/bzImage ~/tmp/boot/bzImage-2.6.24.3
~/src/linux-source/v2.6.24$ sudo vim ~/tmp/boot/grub/menu.list
在menu.list中(放在## ## End Default Options ##的下一行)新增:
title Qemu Linux, kernel 2.6.24
root (hd0,0)
kernel /boot/bzImage-2.6.24.3 root=/dev/hda1 ro
savedefault
存檔離開之後啟動Qemu launcher選擇使用硬碟開機,開機的時候選擇剛剛複製的Qemu Linux, kernel 2.6.24,開機完成之後輸入uname -a確認版本無誤,如下圖:


6) Attach GDB to Qemu
最後一個步驟是開啟Qemu並讓它等候GDB連線進行除錯,開啟Qemu launcher之後點選Emulator頁面,在Additonal arguments中輸入-S -s如下圖:


點選Launch之後會看到名為QEMU [Stopped]的新console出現,如下圖:


這時候在剛剛編譯target Linux kernel的那個console中輸入指令:
~/src/linux-source/v2.6.24$ gdb ./vmlinux
以下為進入GDB之後的指令對話:
(gdb) target remote localhost:1234
Remote debugging using localhost:1234
0x0000fff0 in ?? ()
(gdb) c
Continuing.

Continuing出現之後原本一片漆黑的QEMU [Stopped]視窗開始運作最後出現kernel選單,如下圖:

若是在GDB環境中在最後一個指令c之前插入設定breakpoint指令如b start_kernel,則在我們選擇kernel版本之後Qemu會停在start_kernel函式的第一行程式碼,如下圖:



恭喜你已經可以進行source code level Linux kernel debugging!



[1] http://www.kernel.org/
[2] http://memyselfandtaco.blogspot.com/2008/06/technical-writings-rule-of-thumb-local.html
[3] http://memyselfandtaco.blogspot.com/2008/06/qemu-and-its-launcher.html
[4] http://cdimage.debian.org/debian-cd/4.0_r3/i386/iso-cd/debian-40r3-i386-CD-1.iso
[5] http://www.ibm.com/developerworks/linux/library/l-initrd.html

4 comments:

Anonymous said...

補充 kgdb + qemu 的使用:
http://blog.linux.org.tw/~jserv/archives/002045.html

Have Fun!

t@c0 said...

久聞jserv大名,我會好好拜讀的 :-)

Unknown said...

t@c0,您好,我参考你的这篇文章完成了lxr源代码检索服务器的配置,现在我想请教您另外一个问题:
在建立lxr源代码检索的时候我使用的是kernel.org上面下载的原始的干净内核2.6.26,现在我有一个经过重大修改的内核2.6.10需要添加到lxr检索服务器里面,请问我应该怎么做?希望能够得到您的指点,谢谢!

t@c0 said...

我想您配置lxr時參考的應該是這篇"http://memyselfandtaco.blogspot.com/2008/06/technical-writings-rule-of-thumb-local.html"
我想如果你要將新的Linux src加入lxr的話可以修改步驟(7),(8),(10),(11),(12),將正確的路徑帶入,然後在瀏覽器中輸入新的URL即可。