Debugging the Linux Kernel with QEMU and GDB

Environment Preparation

Environment

openEuler 24.03-LTS

Installing QEMU

yum install -y qemu-system-x86_64 qemu

Creating the File System

# Format the file system
dd if=/dev/zero of=myrootfs.img bs=1M count=4096
mkfs.ext4 myrootfs.img
# Install packages
mkdir rootfs
mount myrootfs.img rootfs/
dnf --installroot=$(pwd)/rootfs install systemd passwd

Compiling the Kernel

# Download the openEuler kernel source package
yumdownloader --source kernel
# Extract the source package
mkdir kernel
cd kernel
rpm2cpio < ../kernel-*.rpm | cpio -idmtar -zxf kernel.tar.gz
cd kernel
# Install compilation dependencies
yum-builddep kernel -y
# Set compilation options
Symbol: <strong>GDB_SCRIPTS</strong> [=y]                                                                                                                x    x Type  : bool                                                                                                                            x    x Defined at lib/Kconfig.debug:423                                                                                                        x    x   Prompt: Provide <strong>GDB</strong> scripts for kernel debugging                                                                                      x    x   Depends on: DEBUG_INFO [=y]                                                                                                           x    x   Location:                                                                                                                             x    x     -> Kernel hacking                                                                                                                   x    x       -> Compile-time checks and compiler options                                                                                       x    x         -> Provide <strong>GDB</strong> scripts for kernel debugging (GDB_SCRIPTS [=y]) 
# After modifying, save and exit, start compiling the kernel
make -j16

Creating initrd

# Generate an initrd locally
dracut -f initrd
mkdir initfs
cd initfs
# Extract initrd
zcat ../initrd | cpio -idm
# Replace drivers
rm -rf lib/modules/*
# Enter the root directory of the kernel code, at this point the kernel has been compiled
make modules_install INSTALL_MOD_PATH=initrd所在的目录 INSTALL_MOD_STRIP=1 
# Enter the initfs directory, compress initrd
find . | cpio -o -H newc 2>/dev/null | gzip > ../initramfs

Installing Drivers in the File System

# Mount the file system
mkdir fsmount
mount rootfs.img /fs
make modules_install INSTALL_MOD_PATH=./fs INSTALL_MOD_STRIP=1
# Set login password
chroot fs
passwd
exit

Starting the Kernel with QEMU

Start the kernel

qemu-system-x86_64 \
-cpu max \
-m 2048M \
-smp 2 \
-kernel kernel/arch/x86/boot/bzImage \
-initrd ./initramfs \
-hda ./rootfs.img \
-append "root=/dev/sda rw console=ttyS0 nokaslr selinux=0" \
-s -S \
-nographic

Open another window and navigate to the directory where the kernel is located

[root@MS-CMFLBWVCLQRG kernel]# gdb vmlinux -q
Reading symbols from vmlinux...(gdb) target remote :1234
Remote debugging using :1234
warning: Remote gdbserver does not support determining executable automatically.
RHEL <=6.8 and <=7.2 versions of gdbserver do not support such automatic executable detection.
The following versions of gdbserver support it:
- Upstream version of gdbserver (unsupported) 7.10 or later
- Red Hat Developer Toolset (DTS) version of gdbserver from DTS 4.0 or later (only on x86_64)
- RHEL-7.3 versions of gdbserver (on any architecture)
0x000000000000fff0 in exception_stacks ()
(gdb) c
Continuing.

At this point, the kernel is running, and you can use GDB for debugging.

Leave a Comment