Ubuntu18.04+Qemu调试Linux内核实验记录
- 实验环境
操作系统:Ubuntu18.04
依赖项安装:
sudo apt-get install texinfo
sudo apt-get install libncurses5-dev
sudo apt-get install m4
sudo apt-get install flex
sudo apt-get install bison
2.编译内核
cd内核源代码目录/
make mrproper //清除编译过程中产生的所有中间文件
make clean //清除上一次产生的编译中间文件
make menuconfig //图形化界面,方便选择一些功能
//内核编译选项配置
//退出并保存配置
//编译内核源代码:make -j2 #-jN会make得更快
//缺少openssl/opensslv.h: No such file or directory
Sudo apt-get install libssl-dev
3.安装busybox
//下载源代码
下载地址:https://busybox.net/
//编译源代码
cd 源代码目录
make clean
make defconfig
make menuconfig
//配置编译选项
//编译与安装
make -j4
sudo make install
#此时可以在内核源代码目录中看到生成的_install目录。通过下面的命令可以验证busybox是否安装正确./busybox ls
//生成initrd
首先将上一步生成的_install文件夹复制到其他位置
cd …
mkdir ramdisk
cd ramdisk
cp -r …/内核源代码目录/_install/* .
//设置初始化进程init(建立一个软链接,一定不能直接复制过去)
#进入刚刚创建的ramdisk目录
cd ramdisk
ln -s bin/busybox init
//设定一些程序运行所需要的文件夹
mkdir -pv {bin,sbin,etc,proc,sys,usr/{bin,sbin},dev}
//编写inittab,指定开机需要启动的所有程序
cd ./etc
vim inittab
// inittab文件的内容如下所示:
::sysinit:/etc/init.d/rcS
::askfirst:-/bin/sh
::restart:/sbin/init
::ctrlaltdel:/sbin/reboot
::shutdown:/bin/umount -a -r
::shutdown:/sbin/swapoff –a
//赋予可执行权限
chmod +x inittab
//编写系统初始化命令
#在ramdisk/etc目录下
mkdir init.d
cd init.d
vim rcS
// rcS文件的内容
#!/bin/sh
mount proc
mount -o remount,rw /
mount -a
clear
echo “My Tiny Linux Start …”
//赋予可执行权限
chmod +x rcS
//在rcS脚本中,mount -a 是自动挂载 /etc/fstab 里面的东西,可以理解为挂//在文件系统,因此我们还需要编写 fstab文件来设置我们的文件系统。
cd ramdisk/etc/
vim fstab
// fstab文件内容
// /etc/fstab
proc /proc proc defaults 0 0
sysfs /sys sysfs defaults 0 0
devtmpfs /dev devtmpfs defaults 0 0
//压缩生成文件镜像
cd ramdisk
find . -print0 | cpio --null -ov --format=newc | gzip -9 > …/initramfs.img
//生成的initramfs.img就是我们的根文件系统
//测试根文件系统
#安装qemu
sudo apt-get install qemu
#测试
qemu-system-x86_64 -kernel Linux内核目录/arch/x86_64/boot/bzImage -initrd 文件系统目录/initramfs.img
4.使用Qemu调试Linux内核
#在linux源码目录下运行以下指令qemu-system-x86_64 -S -kernel arch/x86_64/boot/bzImage -m 1024
// 如果安装了最小文件系统,那么可以使用下面的指令
qemu-system-x86_64 -kernel linux源码目录/arch/x86_64/boot/bzImage -initrd …/initramfs.img -smp 2 -S -s -m 1024
qemu-system-x86_64的参数比较多,这里简单说下:
-kernel 是指定一个大内核文件,当仁不让的是bzImage。
-initrd 是指定一个 initrd.img文件,这个文件就是我们使用busybox生成的initramfs.img。
-smp 可以从名字猜想,它是给qemu指定几个处理器,或者是几个线程<嗯,大概意思就thread吧>。
-gdb则是启动qemu的内嵌gdbserver,监听的是本地tcp端口1234—如果这样写: -gdb tcp:192.168.1.100:1234 ,似乎也是没问题的。
-S 就是挂起gdbserver,让gdb remote connect it。
-s 默认使用1234端口进行远程调试,和-gdb tcp::1234类似。
-m 2048 指定内存大小为2048M
(注意,在自己的实验中不能使用-s,否则内核的启动过程会卡死)
qemu-system-x86_64 -kernel …/Linux_Source_Code/linux-4.14.162/arch/x86_64/boot/bzImage -initrd initramfs.img -smp 2 -S -m 1024
//接下来会出现一个黑色的界面,ctrl+alt+1 与 ctrl+alt+2可以切换,前者是屏幕输出,后者是qemu控制台,运行起来后是黑屏,我们要切换到控制台,用鼠标点击窗口,然后ctrl+alt+2,如下图所示输入,然后回车,ctrl+alt+1切换回来,ctrl+alt切出鼠标。
gdbserver tcp::1234 (等待远端gdb登入)
//在另一个终端中,进入Linux源代码目录
gdb vmlinux
target remote localhost:1234
//设置断点
b start_kernel
//设置硬件断点
hb start_kernel
//运行代码至断点处
c/continue
//出现如下图所示的问题,无法调试内核
//解决方法,在使用Qemu进行调试时添加nokaslr选项
qemu-system-x86_64 -kernel …/Linux_Source_Code/linux-4.14.162/arch/x86_64/boot/bzImage -initrd initramfs.img -smp 2 -S -m 1024 -append nokaslr
#继续运行,系统启动
5.参考资料
https://blog.csdn.net/u012313382/article/details/93381046
https://blog.csdn.net/jasonLee_lijiaqi/article/details/80967912
https://busybox.net/
https://www.zhihu.com/question/270476360