1: 安装ubuntu Server系统:
kvm-img create -f raw disk.img 8G
kvm -m 512 -cdrom ubuntu-10.10-server-i386.iso -drive file=disk.img,if=scsi,index=0 -boot d -net nic -net user
安装完系统之后启动(普通方式):
kvm -m 512 -drive file=disk.img,if=scsi,index=0,boot=on -boot c -net nic -net user
2: 提取boot文件
sudo losetup -f disk.img
sudo losetup -a
此时输出:
/dev/loop0: [0801]:16908388 ($/path/to/disk.img)
找出partition 的起始setctor:
sudo fdisk -c -u -l /dev/loop0
输出:
Disk /dev/loop0: 8589 MB, 8589934592 bytes
255 heads, 63 sectors/track, 1044 cylinders, total 16777216 sectors
Units = sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk identifier: 0x000411b5
Device Boot Start End Blocks Id System
/dev/loop0p1 * 2048 15958015 7977984 83 Linux
Unmount loop0 设备:
sudo losetup -d /dev/loop0
挂载disk.img的分区(/dev/loop0p1):
sudo losetup -f -o 1048576 disk.img
(1048576 = 2048*512)
sudo losetup -a
此时的输出应当是:
/dev/loop0: [0801]:16908388 ($/path/to/disk.img) offset 1048576
拷贝整个partition到新的raw文件:
sudo dd if=/dev/loop0 of=diskout.img
Unmount loop0 设备:
sudo losetup -d /dev/loop0
挂载diskout.img:
sudo mount -o loop diskout.img /mnt
从/mnt/boot中拷贝kernel和initrd:
sudo cp /mnt/boot/vmlinuz-2.6.35-22-generic .
sudo cp /mnt/boot/initrd.img-2.6.35-22-generic .
Unmount Loop :
sudo umount /mnt
用拷贝出的文件启动 :
kvm -m 512 -kernel vmlinuz-2.6.35-22-generic -append "root=/dev/sda" -boot c -hda diskout.img -k en-us -initrd initrd.img-2.6.35-22-generic -net nic -net user
3: 编译新内核
下载内核:linux-2.6.35.9.tar.bz2
解压后进入内核:cd linux-2.6.35.9
生成配置文件:
Make defconfig
配置编译选项:
DEBUG_RODATA 建议关闭该选项:
位置: -> Kernel hacking ->Write protect kernel read-only data structures
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
配置内核版本信息:
打开Makefile在 EXTRAVERSION = 后面加入:-kgdb
修改编译优化等级:
打开根目录下Makefile文件修改内核Makefile优化选项将KBUILD_CFLAGS += -O2,修改 为:KBUILD_CFLAGS += -O。
编译内核:
make && make modules
4: 安装内核:
将编译的内核拷贝到diskout.img里边:
sudo mount -o loop diskout.img /mnt/
sudo cp -r linux-2.6.35.9 /mnt/home/gudujian/
sudo umount /mnt
启动虚拟机:
kvm -m 512 -kernel vmlinuz-2.6.35-22-generic -append "root=/dev/sda" -boot c -hda diskout.img
-k en-us -initrd initrd.img-2.6.35-22-generic -net nic -net user
在虚拟机中安装:
cd linux-2.6.35.9
sudo make modules_install
sudo make install
制作initramfs
cd /lib/modules
sudo mkinitramfs -o /boot/initrd.img-2.6.35.9-kgdb
关闭虚拟机,拷贝新安装的内核文件:
sudo mount -o loop diskout.img /mnt/
sudo cp /mnt/boot/vmlinuz-2.6.35.9-kgdb .
sudo cp /mnt/boot/initrd.img-2.6.35.9-kgdb .
sudo umount /mnt
使用新安装的内核来启动:
kvm -m 512 -kernel vmlinuz-2.6.35.9-kgdb -append "root=/dev/sda" -boot c -hda diskout.img
-k en-us -initrd initrd.img-2.6.35.9-kgdb -net nic -net user
此时如果能正常启动了那么改变启动参数来调试内核:
kvm -m 512 -kernel vmlinuz-2.6.35.9-kgdb -append "root=/dev/sda kgdboc=ttyS0,115200 kgdbwait" -boot c -hda diskout.img -k en-us -initrd initrd.img-2.6.35.9-kgdb -serial tcp::4321,server -net nic -net user 1
虚拟机的终端将提示等待远程连接到本地端口4321:
QEMU waiting for connection on: tcp:0.0.0.0:4321,server
这时使用另外一个控制台执行:
$gdb vmlinux
(gdb) target remote localhost:4321
然后虚拟机就可以继续正常运行下去,最后停止内核,并显示如下信息:
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();
从这里就可以开始下断点调试内核。