QEMU是這兩年相當火熱的一個話題,我第一次看到相關的報導,是在PTT的小軟體版,那時對這個東西的印像其實並沒有這麼深刻,”反正不過又是另一個VMWARE罷了”,我心裡這樣想著

可是後來在搜尋kernel debug相關的文章時,QEMU老是出現在搜尋的列表裡面,看了這些文章,才慢慢開啟我對它的興趣,原來kernel tracing可以這麼簡單

QEMU的特點就是內建GDBSERVER, GDBClient透過stub可以跟QEMU的GDBSERVER交換訊息,所以可以設任意的中斷點在kernel souce的任一個地方,讓使用者觀察cpu register和相關的程式執行狀態

下面這篇文章,就是在講解我做linux kernel tracing實驗的過程

下載QEMU
到官網下載QEMU i386 binary package,並在根目錄解壓縮此檔案,解壓縮完後,可以看到我們的binary可執行檔多了qemu開頭的命令,其中比較特別的是qemu-system-xxx這些指令,根據qemu的說明文件,這些指令可模擬不同cpu的板子,以arm來說,可模擬ARM926E, ARM1026E, ARM946E, ARM1136 or Cortex-A8 CPU系列的板子QEMU都有內建支援,你也可以從官網下載一些熱心網友做好的disk image做一些實驗,至於QEMU的加速器KQEMU可以不用灌,如果你的HOST OS是VMWARE模擬的,那更不可以灌,灌了只會讓QEMU跑更慢

設定網路
這個部份有點難,沒做也沒關係,因為這不影響我們進行kernel tracing,不過如果想讓QEMU跟主機溝通,最好把這部份也設定好,設定的方法請參考此網站,而我設定網路的方法如下

/usr/sbin/brctl addbr br0
/sbin/ifconfig eth2 0.0.0.0 promisc up
/usr/sbin/brctl addif br0 eth2
/sbin/ifconfig br0 192.192.222.133 netmask 255.255.255.0 up
/sbin/route add default gw 192.192.222.254 dev br0

把qemu-ifup擺在/etc資料夾下,qemu-ifup內容如下


#!/bin/sh
sudo /sbin/ifconfig $1 0.0.0.0 promisc up
sudo /usr/sbin/brctl addif br0 $1

核心追縱
下載linux kernel最新的版本,並編譯,記得要在編譯kernel前選擇網卡的driver, QEMU可模擬RTL8139,NE2000…等網卡,選完後輸入make bzImage即可

下載及編譯busybox,製做ramdisk image(root file system),底下是我製作的流程

dd if=/dev/zero of=/home/initrd.img bs=1k count=8192
su root
mke2fs -F -v -m0  /home/initrd.img
mkdir tmp
mount -o loop initrd.img  tmp/
cp /home/busybox/_install/* /home/tmp/ -dpRrf

製作root file system device符號表
mkdir –p /home/tmp/dev
mknod /home/tmp/dev/console c 5 1
mknod /home/tmp/dev/tty0 c 5 0
mknod /home/tmp/dev/mem c 1 1
mknod /home/tmp/dev/null c 1 3
mknod /home/tmp/dev/random c 1 8
umount tmp/

執行編譯好的kernel image,看是否運作正常,執行方式如下

qemu -kernel bzImage -hda initrd.img -m 128 -append “root=/dev/hda” -net nic -net tap,ifname=tap0,script=/etc/qemu-ifup

開始追縱kernel,輸入qemu –s –S –kernel bzImage –hda initrd.img –m 128,執行後qemu畫面會停住並等待gdb連線,接著輸入gdb vmlinux,出現(gdb)提示符號後,輸入target remote localhost:1234,試著在start_kernel掛上中斷點(b start_kernel),再輸入c(continue),可以看到qemu linux 開始運作了,並且在start_kernel的地方hold住

但這邊有個小問題,在start_kernel後可以用next指令往下面追縱,可是在某些printk的地方,就算跑過了,也不會有東西顯示在console上,這點讓我覺的很奇怪,跟我以前用ICE的經驗不大相同,不知是什麼原因,不過我想我會再找找看相關的文件是否有說明到這個問題

最後修改日期: 3 6 月, 2022

作者

留言

撰寫回覆或留言

發佈留言必須填寫的電子郵件地址不會公開。