您的位置:首页 > 运维架构 > Linux

linux内核调试环境搭建-2 用busybox搭建

2012-11-07 20:57 357 查看
下载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 href="http://www.busybox.net/downloads/" target=_blank>

解压缩:

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服务:
/article/1897799.html
只是在busybox中使用tftp客户端命令有些不一样。见后面介绍。

使用gdb + kgdb调试内核
使能kgdb可以在内核启动时增加使能参数,这里我们采取在内核启动时增加启动参数(kgdboc=ttyS0,115200 kgdbwait)的方式:
qemu -m 512 -kernel bzImage
-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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: