所使用的实验环境:

操作系统: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 AdaCC++Objective-CFree PascalFortranGo,[2] and partially others.[3]

在命令行输入gdb,查看能否直接进入。一般来说都是系统会有自带的。

有如下显示:

openeuler安装redies openEuler安装qemu_服务器

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

显示如下则安装成功:

openeuler安装redies openEuler安装qemu_GDB_02

  • 下载并编译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

openeuler安装redies openEuler安装qemu_GDB_03

       对配置文件进行一些必要的修改:

make menuconfig     

在配置菜单中,启用内核debug,关闭地址随机化,不然断点处无法停止。

Processor type and features ---->

    [] Randomize the address of the kernel image (KASLR)

openeuler安装redies openEuler安装qemu_linux_04

Kernel hacking  --->

openeuler安装redies openEuler安装qemu_GDB_05

    [*] Kernel debugging

    Compile-time checks and compiler options  --->

        [*]   Provide GDB scripts for kernel debuggin (允许GDB调试)

进入Debug information选项:

笔者这里选择version4

openeuler安装redies openEuler安装qemu_linux_06

 

openeuler安装redies openEuler安装qemu_GDB_07

可能没有如上显示,可能是下面这样,勾选Compile the kernel with debug info即可

openeuler安装redies openEuler安装qemu_openeuler安装redies_08

DWARF介绍:dwarf调试信息格式入门 - zengkefu - 博客园dwarf调试信息格式入门 - zengkefu - 博客园

保存好配置退出

openeuler安装redies openEuler安装qemu_GDB_09

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

openeuler安装redies openEuler安装qemu_openeuler安装redies_10

四、使用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

openeuler安装redies openEuler安装qemu_unix_11

-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]

       运行时的效果,不是卡住了 

     

openeuler安装redies openEuler安装qemu_unix_12

启动GDB远程调试:

       新开一个终端,不要关闭原来的终端,在新终端里使用GDB

cd /opt/linux-5.18.14

gdb vmlinux

openeuler安装redies openEuler安装qemu_服务器_13

target remote localhost:1234

可能会有警告,不影响调试

openeuler安装redies openEuler安装qemu_服务器_14

设置内核断点:b start_kernel

继续运行到内核断点:c

显示断点附件的代码:list

 

openeuler安装redies openEuler安装qemu_GDB_15

结束调试:quit          关闭Qemu虚拟机:poweroff