使用GDB调试Linux内核

如何使用GDB调试Linux内核

编译Linux内核

1
2
3
4
5
6
export ARCH=x86

make menuconfig #首先进行配置

make -j 8 #使用8个cpu进行编译
# 在这一步之后,Linux会在./linux-5.0/arch/x86/boot/目录下生成bgimg文件。

在menuconfig中配置

1
2
3
4
5
6
7
8
9
Kernel hacking  ---> 
[*] Kernel debugging
Compile-time checks and compiler options --->
[*] Compile the kernel with debug info
[*] Provide GDB scripts for kernel debuggin


Processor type and features ---->
[] Randomize the address of the kernel image (KASLR)

安装qume

  1. 下载好qemu后,./configure prefix=/to/path/ 配置好安装路径
  2. make 编译

制作根目录

一个最小的Linux系统需要img文件和一个根目录,制作根目录有很多软件,我们使用busybox。

步骤:

  1. 使用dd命令创建文件,并格式化为ext4文件系统:

    1
    2
    3
    szp@r420-PowerEdge-R420:~/busybox-1.32.0$ dd if=/dev/zero of=rootfs.img bs=1M count=10

    szp@r420-PowerEdge-R420:~/busybox-1.32.0$ mkfs.ext4 rootfs.img
  2. 创建用于挂载该镜像文件的目录fs,挂载后才能往里面写入busybox。 使用mount命令将rootfs.img挂载到fs目录,编译busybox并写入fs目录中。

1
2
3
4
5
szp@r420-PowerEdge-R420:~$ mkdir fs

szp@r420-PowerEdge-R420:~/busybox-1.32.0$ sudo mount -t ext4 -o loop rootfs.img ./fs

szp@r420-PowerEdge-R420:~/busybox-1.32.0$ sudo make install CONFIG_PREFIX=./fs
  1. 接下来对写入的busybox进行补充配置:
1
2
3
4
5
6
szp@r420-PowerEdge-R420:~/busybox-1.32.0/fs$ sudo mkdir proc dev etc home mnt

szp@r420-PowerEdge-R420:~/busybox-1.32.0/fs$ sudo cp -r ../examples/bootfloppy/etc/* etc/

szp@r420-PowerEdge-R420:~/busybox-1.32.0$ sudo chmod -R 777 fs/

  1. 最后,卸载rootfs.img:
1
szp@r420-PowerEdge-R420:~/busybox-1.32.0$ sudo umount fs

至此已经制作好了根文件目录,下面我们启动qemu

启动qemu

1
szp@r420-PowerEdge-R420:~$ qemu-system-x86_64 -kernel ~/linux-4.14.191/arch/x86_64/boot/bzImage  -hda ~/busybox-1.32.0/rootfs.img  -append "root=/dev/sda console=ttyS0" -s -S  -smp 1 -nographic

该命令的参数注释:

  • -kernel # 指定编译好的内核镜像

  • -hda # 指定硬盘

  • -append “root=/dev/sda” 指示根文件系统 console=ttyS0 把QEMU的输入输出定向到当前终端上

  • -nographic 不使用图形输出窗口

  • -s 是-gdb tcp::1234缩写,监听1234端口,在GDB中可以通过target remote localhost:1234连接 **使用-gdb tcp:xxxx命令可以更换端口。

至此我们已经完成了大部分操作只需要,新启动一个shell,然后执行:

1
2
3
4
5
gdb ./linux-5.0/vmlinux 

#开启gdb之后输入:

target remote localhost :1234 #特别注意这里:之前的空格是一定需要的。

查看gdb支持的lx函数或命令:apropos lx

vmlinux 是编译内核时生成的调试文件,在内核源码的根目录中。

参考资料

http://kerneltravel.net/blog/2021/debug_kernel_szp/

https://mazhen.tech/p/%E4%BD%BF%E7%94%A8gdb%E8%B0%83%E8%AF%95linux%E5%86%85%E6%A0%B8/#%E5%86%99%E5%9C%A8%E6%9C%80%E5%90%8E

使用vscode+qemu+gdb调试Linux内核

直接使用物理机进行调试

除开使用虚拟机安装内核后,还可以直接在平台上通过安装内核调试符号包来进行调试。

查询系统的版本

1
uname -r #查看系统版本

下载调试包

已知自己的版本通过这个版本号去这个网站下载调试包,注意的是下载的调试包需要和自己的系统版本对应Ubuntu官方网站下的调试包

linux-image-unsigned-5.13.0-52-generic-dbgsym_5.13.0-52.59~20.04.1_amd64.ddeb 这是我的系统对应的版本。

安装内核源码

这里需要注意的是:amd64就是x86-64也称之intel64

1
2
3
4
5
6
7
8
$ sudo apt-cache search linux-source
linux-source - Linux kernel source with Ubuntu patches
linux-source-5.13.0 - Linux kernel source for version 5.13.0 with Ubuntu patches

$ sudo apt install linux-source-5.13.0
$ sudo cd /usr/src
$ sudo tar -jxvf linux-source-5.13.0.tar.bz2
$ sudo cd /usr/src/linux-source-5.13.0

创建软链接

1
2
3
4
# 需要 gdb 首先获取到 vmlinux-5.13.0-20-generic 的编译目录,使用 list *__x64_sys_mount
# 会提示对应的编译目录,如果我们在 /usr/src 目录已经安装了源码,建立快捷方式即可
$ mkdir -p /build/linux-lpF6wX/
$ ln -s /usr/src/linux-source-5.13.0 /build/linux-lpF6wX/linux-5.13.0

开始调试

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
gdb /usr/lib/debug/boot/vmlinux-5.13.0-20-generic
(gdb) list *__x64_sys_mount
0xffffffff81352ce0 is in __x64_sys_mount (/build/linux-lpF6wX/linux-5.13.0/fs/namespace.c:3451).
warning: Source file is more recent than executable.
3446 /* ... and return the root of (sub)tree on it */
3447 return path.dentry;
3448 }
3449 EXPORT_SYMBOL(mount_subtree);
3450
3451 SYSCALL_DEFINE5(mount, char __user *, dev_name, char __user *, dir_name,
3452 char __user *, type, unsigned long, flags, void __user *, data)
3453 {
3454 int ret;
3455 char *kernel_type;

(gdb) disassemble *__x64_sys_mount
...
0xffffffff81352de3 <+259>: call 0xffffffff813524c0 <path_mount>
0xffffffff81352de8 <+264>: lea -0x40(%rbp),%rdi
0xffffffff81352dec <+268>: movslq %eax,%r12
0xffffffff81352def <+271>: call 0xffffffff813321b0 <path_put>
...

通过在 gdb 工作窗口中 list *__x64_sys_mount 我们就可以看到源码相关的定义,一切准备完成,可以愉快地进行相关工作调试了。

参考资料

http://advdbg.org/blogs/advdbg_system/articles/7147.aspx

https://www.ebpf.top/post/ubuntu-21-10-dbgsym/

https://blog.csdn.net/qq_30952829/article/details/126571506


使用GDB调试Linux内核
https://ysc2.github.io/ysc2.github.io/2023/11/21/使用GDB调试Linux内核/
作者
Ysc
发布于
2023年11月21日
许可协议