内核调试 --环境搭建篇
在看ceph 源码的时候,一般都是搭建一个环境,然后gbd 到指定函数,边调试边分析,这样很方便,效率也高,前段时间 突然想到 ,系统调用能不能调试呢? 比如 调用个 write 函数,写数据到一个文件,这背后发生了什么?又比如 我们使用 socket 通信 ,然后收数据,这过程我们能不能用gdb 追踪呢? 带着这些问题,在网上摸索一大圈,于是记录下
准备工作 && 预备知识 准备工作 && 预备知识
操作系统也是个程序,同理也可以 gdb,但是内核编译后,在物理机跑有点麻烦,于是这里用 qemu 来模拟硬件,软件模拟硬件,方便调试。
\[!NOTE\] qemu
qmeu: 是一个托管的 虚拟机 镜像,它通过动态的二进制转换,模拟 CPU,并且提供一组设备模型,使它能够运行多种未修改的客户机 OS,可以通过与 KVM(kernel-based virtual machine 开源加速器)一起使用进而接近本地速度运行虚拟机(接近真实电脑的速度)
qmeu能跑内核,但也是裸跑内核,实际上 内核需要挂载到根⽂件系统,内核会将其挂载到根⽬录/下,然后运⾏根⽂件系统中init脚本执⾏⼀些启动任务,为了简便,直接 使用busybox 搭建一个轻量级的文件系统,busybox 功能强大,这里就先拿来使用,后面有时间再研究下
需要用的软件包
sudo apt install build-essential qemu libncurses5-dev bison flex libssl-dev libelf-dev axel -y
编译工作
- 下载内核 源码 && busbox 源码 (以下操作都在 /home 目录执行)
wget https://mirrors.edge.kernel.org/pub/linux/kernel/v5.x/linux-5.4.34.tar.xz
wget https://busybox.net/downloads/busybox-1.31.1.tar.bz2
- 编译linux 内核源码
cd linux-5.4.34
make defconfig #默认配置基于'x86_64_defconfig'
make menuconfig # 这里会弹出配置界面
#打开debug相关选项
Kernel hacking --->
Compile-time checks and compiler options --->
[*] Compile the kernel with debug info
[*] Provide GDB scripts for kernel debugging [*] Kernel debugging
#关闭KASLR,否则会导致打断点失败
Processor type and features ---->
[] Randomize the address of the kernel image (KASLR)
开始编译
make -j$(nproc) #编译内核,需要几分钟的时间 ,$(nproc) 核心数
验证下是否能执行
#进入源码目录
hrp@ubuntu:~$ cd linux-5.4.34/
hrp@ubuntu:~/linux-5.4.34$ pwd
/home/hrp/linux-5.4.34
# 使用 qemu执行 此时会弹出个黑框(PS:我是 ubuntu )
hrp@ubuntu:~/linux-5.4.34$ qemu-system-x86_64 -kernel arch/x86/boot/bzImage
qemu-system-x86_64: warning: TCG doesn't support requested feature: CPUID.01H:ECX.vmx [bit 5]
- 编译busybox
cd busybox-1.31.1
make menuconfig #进入配置项
选择 编译成静态链接
Settings --->
[*] Build static binary (no shared libs)
make -j$(nproc) && make install
制作文件系统
- 创建一个镜像(相当于创建一个盘)
dd if=/dev/zero of=./busybox.img bs=1M count=300
- 格式盘,这里试用 ext3
mkfs.ext3 busybox.img
- 要往镜像里面添加文件,为了方便,直接将镜像挂载到 /mnt 下
sudo mkdir /mnt/disk
sudo mount -o loop busybox.img /mnt/disk
#将文件系统必要的文件 拷贝到挂载目录
sudo cp -rf busybox源码目录/_install/* /mnt/disk
- 创建必要的文件目录
cd /mnt/disk/
sudo mkdir dev sys proc etc lib mnt
- 创建设备点
cd dev/
mknod console c 5 1
mknod null c 1 3
mknod tty2 c 4 2
- busybox默认的设置文件,内核启动后会执行 rcS 脚本,这个脚本我们可以挂载目录,和配置网络
sudo cp -a /dir/to/busybox-1.17.0/examples/bootfloppy/etc/* /mnt/disk/etc
sudo vi /mnt/disk/etc/init.d/rcS
#! /bin/sh
MAC=08:90:90:59:62:21
IP=192.168.100.2
Mask=255.255.255.0
Gateway=192.168.100.1
/sbin/ifconfig lo 127.0.0.1
ifconfig eth0 down
ifconfig eth0 hw ether $MAC
ifconfig eth0 $IP netmask $Mask up
route add default gw $Gateway
/bin/mount -a
/bin/mount -t sysfs sysfs /sys
/bin/mount -t tmpfs tmpfs /dev
/sbin/mdev -s
mount -o remount,rw,noatime -n /dev/root /
- 修改fstab 文件
$ vim etc/fstab
proc /proc proc defaults 0 0
tmpfs /tmp tmpfs defaults 0 0
sysfs /sys sysfs defaults 0 0
tmpfs /dev tmpfs defaults 0 0
var /dev tmpfs defaults 0 0
- 接触挂载
sudo umount /mnt/disk
- 启动内核 ,进入 bash交互
qemu-system-x86_64 -m 512 -kernel /home/hrp/linux-5.4.34/arch/x86_64/boot/bzImage -append "root=/dev/sda rw console=ttyS0 " -nographic -boot c -hda /home/hrp/busybox.img -k en-us -net nic -net tap,ifname=tap0,script=no
#-----------
WARNING: Image format was not specified for '/home/hrp/busybox.img' and probing guessed raw.
Automatically detecting the format is dangerous for raw images, write operations on block 0 will be restricted.
Specify the 'raw' format explicitly to remove the restrictions.
qemu-system-x86_64: warning: TCG doesn't support requested feature: CPUID.01H:ECX.vmx [bit 5]
[ 0.000000] Linux version 5.4.34 (hrp@ubuntu) (gcc version 7.5.0 (Ubuntu 7.5.0-3ubuntu1~18.04)) #3 SMP Fri Jan 26 22:22:23 PST 2024
[ 0.000000] Command line: root=/dev/sda rw console=ttyS0
[ 0.000000] x86/fpu: x87 FPU will use FXSAVE
[ 0.000000] BIOS-provided physical RAM map:
[ 0.000000] BIOS-e820: [mem 0x0000000000000000-0x000000000009fbff] usable
[ 0.000000] BIOS-e820: [mem 0x000000000009fc00-0x000000000009ffff] reserved
[ 0.000000] BIOS-e820: [mem 0x00000000000f0000-0x00000000000fffff] reserved
....
mount: mounting tmpfs on /tmp failed: No such file or directory
mount: mounting sysfs on /sys failed: Device or resource busy
[ 2.702166] EXT4-fs (sda): re-mounted. Opts: (null)
[ 2.702386] ext3 filesystem being remounted at / supports timestamps until 2038 (0x7fffffff)
[ 2.703963] rcS (94) used greatest stack depth: 13424 bytes left
Processing /etc/profile... Done
/ #
调试
- 参数加入 -S -s ,默认端口 1234
qemu-system-x86_64 -m 512 -kernel /home/hrp/linux-5.4.34/arch/x86_64/boot/bzImage -append "root=/dev/sda rw console=ttyS0 " -nographic -boot c -hda /home/hrp/busybox.img -k en-us -net nic -net tap,ifname=tap0,script=no -S -s
WARNING: Image format was not specified for '/home/hrp/busybox.img' and probing guessed raw.
Automatically detecting the format is dangerous for raw images, write operations on block 0 will be restricted.
Specify the 'raw' format explicitly to remove the restrictions.
qemu-system-x86_64: warning: TCG doesn't support requested feature: CPUID.01H:ECX.vmx [bit 5]
## 等待调试
- 新建窗口 开始gdb
root@ubuntu:/mnt/disk# gdb /home/hrp/linux-5.4.34/vmlinux
GNU gdb (Ubuntu 8.1.1-0ubuntu1) 8.1.1
Copyright (C) 2018 Free Software Foundation, Inc.
....
line to your configuration file "/root/.gdbinit".
For more information about this security protection see the
"Auto-loading safe path" section in the GDB manual. E.g., run from the shell:
info "(gdb)Auto-loading safe path"
(gdb)
(gdb) target remote:1234
Remote debugging using :1234
0x000000000000fff0 in entry_stack_storage ()
(gdb) c #键入c ,内核开始执行
Continuing.
qemu 相关参数
-kernel ./bzImage:指定启用的内核镜像;
-initrd ./rootfs.img:指定启动的内存文件系统;
-append "nokaslr console=ttyS0":附加参数,其中 参数必须添加进来,防止内核起始地址随机化,这样会导致 gdb 断点不能命中;参数说明可以参见这里。nokaslr
-s:监听在 gdb 1234 端口;
-S:表示启动后就挂起,等待 gdb 连接;
-nographic:不启动图形界面,调试信息输出到终端与参数 组合使用;console=ttyS0