linux核心除錯環境搭建-2 用busybox搭建
下載linux核心:
$cd ~/work/
$wget http://www.kernel.org/pub/linux/kernel/v2.6/linux-2.6.35.9.tar.bz2
解壓
$tar -jxvf linux-2.6.35.9.tar.bz2
拷貝現有系統的核心配置選項
$ cp /boot/config-2.6.35-22-generic .config
確保如下選項被選中:
在這裡建議關閉一個選項: DEBUG_RODATA CONFIG_DEBUG_RODATA = n該選項是將核心的一些記憶體區域空間設定為只讀,這樣可能導致kgdb的設定軟斷點功能失效。所以推薦將該選項關閉。
Location:
-> Kernel hacking ->Write protect kernel read-only data structures
另外還得關閉掉一個選項:CONFIG_DEBUG_SET_MODULE_RONX
location:
Kernel hacking --->
Set loadable kernel module data as NX and text as RO
關於這個選項的意義不多說,還是看註釋吧:
This option helps catch unintended modifications to loadable kernel module's text and read-only data. It also prevents execution of module data. Such protection may interfere with run-time code patching and dynamic kernel tracing - and they might also protect against certain classes of kernel exploits. If in doubt, say "N".
那些搞linux核心rootkit的則要注意這個選項了!!。 不知能不能在開啟這個選項的時候讓其失效?
上面兩個選項都要去掉,有一個選擇上那麼在除錯核心模組的時候都會導致下斷點錯誤:
Cannot insert breakpoint 4.
Error accessing memory address 0xd0ce8000: 未知的錯誤 4294967295
KGDB_SERIAL_CONSOLE 開啟該選項:使用串列埠進行通訊
位置: > Kernel hacking
-> KGDB: kernel debugger
-> KGDB: use kgdb over the serial console
KGDB_LOW_LEVEL_TRAP 使能該選項可以kgdb不依賴notifier_call_chain()機制來獲取斷點異常,這樣就可以對notifier_call_chain()機制實現相關的函式進行單步除錯。
依賴: KGDB [=y] && (X86 [=y] || MIPS [=MIPS])
位置: -> Kernel hacking
-> KGDB: kernel debugger (KGDB [=y])
->KGDB: Allow debugging with traps in notifiers
DEBUG_INFO 該選項可以使得編譯的核心包含一些除錯資訊,使得除錯更容易。
位置:
-> Kernel hacking
->compile the kernel with debuginfo
FRAME_POINTER 使能該選項將使得核心使用幀指標暫存器來維護堆疊,從而就可以正確地執行堆疊回溯,即函式呼叫棧資訊。
位置:
-> Kernel hacking
->Compile the kernel with frame pointers
MAGIC_SYSRQ (如果你選擇了KGDB_SERIAL_CONSOLE,這個選項將自動被選上)啟用"魔術 SysRq"鍵.該選項對kgdboc除錯非常有用,kgdb向其註冊了‘g’魔術鍵來啟用kgdb。
位置:
-> Kernel hacking
->magic SysRq key
當你想手動啟用kgdb時,你可以觸發SysRq的g鍵,如:
$ echo "g" > /proc/sysrq-trigger
CONFIG_8139CP 選擇這個選項來驅動qemu-kvm的網絡卡裝置,以備以後使用。
位置:
Device Drivers
Network device support
Ethernet (10 or 100Mbit)
RealTek RTL-8139 C+ PCI Fast Ethernet Adapter support (EXPERIMENTAL)
修改編譯優化等級:
開啟根目錄下Makefile檔案修改核心Makefile優化選項將KBUILD_CFLAGS += -O2,修改為:KBUILD_CFLAGS += -O。
編譯核心:
make && make modules
如果在64位系統上編譯32位核心可以用如下的命令:
make ARCH=i386 menuconfig
make ARCH=i386
make ARCH=i386 modules_install
make ARCH=i386 install
編譯完成後,複製bzImage和vmlinux到工作目錄下備用
cp arch/x86/boot/bzImage .
cp vmlinux .
編譯busybox:
cd ~/work/busy/
下載 busybox-1.20.1.tar.bz2:
wget http://www.busybox.net/downloads/busybox-1.20.1.tar.bz2
解壓縮:
tar -jxvf busybox-1.20.1.tar.bz2
進入busybox目錄:
$ cd busybox-1.20.1/
編譯busybox
make menuconfig
Busybox Settings --->
Build Options --->
[ * ] Build BusyBox as a static binary (no shared libs)
Installation Options --->
[ * ] Don't use /usr
注:[ ]表示不選擇
儲存配置檔案後開始編譯和安裝
make
make install
注意如果是在64位下面如果想編譯32位的busybox 需要首先在64bit的環境下make menuconfig然後再到32bit環境下 make即可。 關於32bit編譯環境可參考文章:
http://blog.csdn.net/xsckernel/article/details/38045783
此時在當前目錄下生成了一個_install目錄,裡面就是busybox的執行檔案
製作檔案系統
使用如下命令來建立一個虛擬檔案系統磁碟檔案,
在當前目錄下建立一個名為busybox.img,大小為300M的檔案,並將其格式化為ext3的檔案系統
dd if=/dev/zero of=./busybox.img bs=1M count=300
mkfs.ext3 busybox.img
將這個虛擬磁碟檔案到本地系統中,這樣我們可以像訪問本地檔案一樣訪問它,並將生成好的busybox的檔案拷貝到這個檔案裡。
sudo mkdir /mnt/disk
sudo mount -o loop busybox.img /mnt/disk
sudo cp -rf /dir/to/busybox-1.17.0/_install/* /mnt/disk
建立必須的檔案系統目錄
cd /mnt/disk/
sudo mkdir dev sys proc etc lib mnt
建立裝置節點
$ cd dev/
$sudo mknod console c 5 1
$sudo mknod null c 1 3
$sudo mknod tty2 c 4 2
使用busybox預設的設定檔案
sudo cp -a /dir/to/busybox-1.17.0/examples/bootfloppy/etc/* /mnt/disk/etc
sudo vi /mnt/disk/etc/init.d/rcS
將下面內容拷貝到rcS裡:
#! /bin/sh
MAC=08:90:90:59:62:21
IP=192.168.100.2
Mask=255.255.255.0
Gateway=192.168.100.1
/sbin/ifconfig lo 127.0.0.1
ifconfig eth0 down
ifconfig eth0 hw ether $MAC
ifconfig eth0 $IP netmask $Mask up
route add default gw $Gateway
/bin/mount -a
/bin/mount -t sysfs sysfs /sys
/bin/mount -t tmpfs tmpfs /dev
/sbin/mdev -s
mount -o remount,rw,noatime -n /dev/root /
修改fstab 檔案:
$ vim etc/fstab
proc /proc proc defaults 0 0
tmpfs /tmp tmpfs defaults 0 0
sysfs /sys sysfs defaults 0 0
tmpfs /dev tmpfs defaults 0 0
var /dev tmpfs defaults 0 0
做完上面對工作後,我們就可以解除安裝虛擬磁碟檔案了。
sudo umount /mnt/disk
使用qemu執行自己編譯的核心
qemu -m 512 -kernel bzImage -append “root=/dev/sda rw” -boot c -hda busybox.img -k en-us
執行如下圖所示:
讓qemu與主機之間可以ping通:
在主機放入一指令碼nettap.sh:
$cd ~
$touch nettap.sh
$gedit nettap.sh
指令碼中放入如下內容:
tunctl -u gudujian -t tap0
ifconfig tap0 192.168.100.1 up
echo 1 > /proc/sys/net/ipv4/ip_forward
iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
iptables -I FORWARD 1 -i tap0 -j ACCEPT
iptables -I FORWARD 1 -o tap0 -m state --state RELATED,ESTABLISHED -j ACCEPT
注意上面的 gudujian 和 eth0 要根據自己的情況修改, 開機後用root許可權執行這個指令碼。
安裝tunctl 工具
sudo apt-get install uml-utilities
用如下指令碼啟動虛擬機器:
qemu -m 512 -kernel bzImage -append "root=/dev/sda rw" -boot c -hda busybox.img -k en-us -net nic -net tap,ifname=tap0,script=no
在虛擬機器中ping主機可見可以ping的通:
讓qemu與主機共享檔案(通過tftp方式):
首先在ubuntu10.10中搭建tftp服務:
只是在busybox中使用tftp客戶端命令有些不一樣。見後面介紹。
使用gdb + kgdb除錯核心
使能kgdb可以在核心啟動時增加使能引數,這裡我們採取在核心啟動時增加啟動引數(kgdboc=ttyS0,115200 kgdbwait)的方式:
qemu -m 512 -kernelbzImage -append "root=/dev/sda kgdboc=ttyS0,115200
kgdbwait" -boot c –hda busybox.img -k en-us -serial tcp::4321,server
這時,執行qemu的終端將提示等待遠端連線到本地埠4321:
QEMU waiting for connection on: tcp:0.0.0.0:4321,server
這時使用另外一個控制檯執行:
gdb vmlinux
(gdb) target remote localhost:4321
然後qemu就可以繼續正常執行下去,最後停止核心,並顯示如下資訊:
kgdb: Waiting for connection from remote gdb…
這時gdb這邊就可以看到如下的提示:
(gdb) target remote localhost:4321
Remote debugging using localhost:4321
kgdb_breakpoint () at kernel/debug/debug_core.c:983
983 wmb(); /* Sync point after breakpoint */
(gdb)
開始你的核心之旅吧~~~
如果gdb提示如下資訊:
warning: Invalid remote reply:
可以使用Ctrl+C來終止當前gdb的操作,再次使用下面命令重新連線一次kgdb即可:
(gdb) target remote localhost:4321
碼字不容易,覺得好請打賞下: