所使用的实验环境:
操作系统:OpenEuler22.03
内核版本:5.18.14
在进行实验二之前,请先确认已经完成实验一。
- 检查是否装有GDB
以下摘自Wikipedia
GDB ,GUN Debugger
The GNU Debugger (GDB) is a portable debugger that runs on many Unix-like systems and works for many programming languages, including Ada, C, C++, Objective-C, Free Pascal, Fortran, Go,[2] and partially others.[3]
在命令行输入gdb,查看能否直接进入。一般来说都是系统会有自带的。
有如下显示:
quit 退出
- 安装依赖和下载Qemu源码
如果你在实验一安装过则跳过此步,依赖详解在实验一有说明
安装依赖
yum -y install ncurses-devel openssl-devel elfutils-libelf-devel bc rsync rpmdevtools python3 gcc gtk2-devel
yum install ninja-build -y
yum install gtk2-devel -y
yum install liburing-devel.x86_64 liburing.x86_64 -y
yum install libaio-devel.x86_64 -y
通过wget下载源码,稍微有点慢,可以选择在windows上找好资源传过去
wget https://download.qemu.org/qemu-6.2.0.tar.xz
tar xvJf qemu-6.2.0.tar.xz
cd qemu-6.2.0
./configure
make -j 8
make install
校验是否安装成功 qemu-system-x86_64 –version
显示如下则安装成功:
- 下载并编译Linux源码
将实验一所使用的压缩包复制到root目录下,或者使用其他用户编译,要保证有足够的磁盘空间。
笔者这里移至root目录下:
cp /opt/linux-5.18.14.tar.xz /root
tar -xvJf linux-5.18.14.tar.xz
cd linux-5.18.14/
设置架构环境变量:
export ARCH=x86
生成编译配置文件:
make x86_64_defconfig
对配置文件进行一些必要的修改:
make menuconfig
在配置菜单中,启用内核debug,关闭地址随机化,不然断点处无法停止。
Processor type and features ---->
[] Randomize the address of the kernel image (KASLR)
Kernel hacking --->
[*] Kernel debugging
Compile-time checks and compiler options --->
[*] Provide GDB scripts for kernel debuggin (允许GDB调试)
进入Debug information选项:
笔者这里选择version4
可能没有如上显示,可能是下面这样,勾选Compile the kernel with debug info即可
DWARF介绍:dwarf调试信息格式入门 - zengkefu - 博客园dwarf调试信息格式入门 - zengkefu - 博客园
保存好配置退出
make -j8
将编译生成的vmlinux内核文件进行压缩。
objcopy -O binary vmlinux vmlinux.bin
vmliunx与vmlinuz介绍:
vmlinux是一个包含linux kernel的静态链接的可执行文件,文件类型是linux接受的可执行文件格式之一(ELF、COFF或a.out)。
vmlinuz是可引导的,压缩的linux内核,“vm”代表的“virtual memory”。vmlinuz是vmlinux经过gzip和objcopy(*)制作出来的压缩文件。vmlinuz不仅是一个压缩文件,而且在文件的开头部分内嵌有gzip解压缩代码。所以你不能用gunzip 或 gzip –dc解包vmlinuz。vmlinuz是一个统称,有两种具体的表现形式:zImage和bzImage(big zImage)。
zImage是vmlinuz经过gzip压缩后的文件,适用于小内核
bzImage是vmlinuz经过gzip压缩后的文件,适用于大内核
ls -hl /opt/linux-5.14.16/arch/x86/boot/bzImage
四、使用busybox构建根文件系统镜像
使用root用户,执行下面的命令创建一个文件,用该文件来仿真一块硬盘,它被用作虚拟机的操作系统盘:
cd /opt
dd if=/dev/zero of=./rootfs.img bs=1G count=10
了解dd命令:https://zh.m.wikipedia.org/zh-cn/Dd_(Unix)
mkfs.ext4 /opt/rootfs.img
使用root用户,执行下面的命令,挂载rootfs镜像:
mkdir -p /mnt/rootfs
mount /opt/rootfs.img /mnt/rootfs
cd /mnt/rootfs
下载busybox
cd /opt
wget https://busybox.net/downloads/busybox-1.32.1.tar.bz2
tar -xjf busybox-1.32.1.tar.bz2
编译busybox
cd /opt/busybox-1.32.1/
make defconfig
make menuconfig
Notice:Check Build static binary, can build binary without dependence library.
Settings --->
[*] Build static binary (no shared libs)
make install CONFIG_PREFIX=/mnt/rootfs
创建虚拟系统的目录
cd /mnt/rootfs/
mkdir proc dev etc home mnt
cd /opt/busybox-1.32.1/
cp -r ./examples/bootfloppy/etc/* /mnt/rootfs/etc/
查看是否成功:ls /mnt/rootfs
bin dev etc home linuxrc lost+found mnt proc sbin usr
卸载新创建的根文件系统
umount /mnt/rootfs
五、启动Qemu虚拟机
qemu-system-x86_64 -kernel /root/linux-5.18.14/arch/x86_64/boot/bzImage \
-hda /opt/rootfs.img \
-append "root=/dev/sda console=ttyS0" \
-nographic
-kernel # 指定编译好的内核镜像
-hda # 指定硬盘
-append “root=/dev/sda” 指示根文件系统 console=ttyS0 把QEMU的输入输出定向到当前终端上
-nographic 不使用图形输出窗口
关机:poweroff
六、在Qemu中调试内核
运行Qemu
qemu-system-x86_64 -kernel /root/linux-5.18.14/arch/x86_64/boot/bzImage
-hda /opt/rootfs.img \
console=ttyS0 nokaslr
-s -S \
-smp 2 \
-nographic
nokaslr:防止内核起始地址随机化,这样会导致 gdb 断点不能命中
-S:启动时冻结CPU(挂起),等待 gdb 连接,在gdb中使用子目录c开始执行;
-s :shorthand for -gdb tcp::1234,在GDB中通过target remote localhost:1234连接
-nographic:不启动图形界面,调试信息输出到终端,与参数console=ttyS0组合使用
-smp [[cpus=]n][,maxcpus=maxcpus][,sockets=sockets][,dies=dies][,cores=cores][,threads=threads]
运行时的效果,不是卡住了
启动GDB远程调试:
新开一个终端,不要关闭原来的终端,在新终端里使用GDB
cd /opt/linux-5.18.14
gdb vmlinux
target remote localhost:1234
可能会有警告,不影响调试
设置内核断点:b start_kernel
继续运行到内核断点:c
显示断点附件的代码:list
结束调试:quit 关闭Qemu虚拟机:poweroff