1. 程式人生 > >linux核心除錯環境搭建-2 用busybox搭建

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時,你可以觸發SysRqg,:

$ 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 

編譯完成後,複製bzImagevmlinux到工作目錄下備用

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

碼字不容易,覺得好請打賞下: