固定链接 如何使用cgdb + qemu调试linux内核模块

如何使用cgdb + qemu调试linux内核模块

如何使用cgdb + qemu调试linux内核模块

如何使用cgdb + qemu调试linux内核模块

前言

Linux 代码庞大而繁杂,光看代码会使人头晕目眩,如果能通过调试工具对其代码执行流程进行调试,则对学习Linux kernel以及解决平时遇到的问题会大有帮助。本文将讲解如何使用cgdb + qemu的方式调试Linux内核代码,所使用的测试机操作系统版本是CentOS Linux release 7.2.1511 (Core)

1.编译额内核

1) 获取内核代码

内核代码下载地址:[https://www.kernel.org/] (https://www.kernel.org/),本文以4.9.153版本作为演示. 如下图,点击对应版本的 tarball 链接下载
version

下载完成后将tar文件拷贝到测试机/root目录并进行解压。

2) 编译出支持调试的内核

配置编译选项

定位到Enable loadable module support:

version

按空格键去掉选项Module signature verification,防止加载模块时如下报错:
module verification failed: signature and/or required key missing - tainting kernel

version

定位到Exit按钮,回到上级菜单。

定位到File systems, 按回车键:

version

选中EXT4 debugging supportJBD2 (ext4) debugging support 两项:

version

定位到Exit按钮,回到上级菜单。

定位到Kernel hacking,按回车键:

version

定位到Kernel debugging,按空格键选中。

version

定位到Compile-time checks and compiler options, 按回车键。

version

分别定位到 Compile the kernel with debug infoProvide GDB scripts for kernel debugging , 并按空格键选中。

version

保存,退出

version

version

version

开始编译

-j 30 表示并行编译的CPU核数

2.构建initramfs根文件系统

这里借助Busybox构建极简initramfs提供基本的用户态可执行程序.

1) 编译Busybox

[下载busybox-1.28.0] (https://busybox.net/downloads/busybox-1.28.0.tar.bz2),并拷贝到测试机/root目录下解压。

配置CONFIG_STATIC参数,可编译出静态版Busybox, 使Busybox的可执行文件不依赖动态库,方便构建initramfs

选择Settings, 按回车。

version

选择Build static binary (no shared libs), 按回车。

version

退出,提示保存,选Yes

开始编译

2) 创建initramfs

创建initramfs, 其中包含BusyBox可执行程序,必要的设备文件,启动脚本init和需要调试的模块。在init脚本里只挂载了虚拟文件系统procfs和sysfs,没有挂载磁盘根文件系统,所有调试操作都在内存中进行,不会读写磁盘。本例中使用ext4.ko模块作为演示,所以需要将ext4.ko及其依赖模块一起放到initramfs。

init文件的内容

打包initramfs:

3.启动虚拟机

qemu-system-x86_64 命令用到的参数说明:

  • -s-gdb tcp::1234 的缩写,表示监听1234端口,在gdb中可以通过 target remote localhost:1234 连接;
  • -kernel 指定编译好的调试版内核;
  • -initrd 指定制作好的initramfs;
  • -nographic 取消图形输出窗口,使QEMU成为简单的命令行程序;
  • -append console=ttyS0 将输出重定向到console,将会显示在标准输出中stdio, 注:这里ttyS0中的S大写;
  • -m 1G 设置虚拟机内存大小。

启动完成后可按回车键进入命令行交互界面

4.使用cgdb进行调试

cgdb 是gdb的一个增强版,调试的时候看代码会美观许多。我们将在另外的一个窗口登录测试机,运行cgdb调试内核。

在gdb命令行里输入target remote :1234进行远程调试,在函数register_filesystem里设置断点后输入c回车,然后在虚拟机里运行命令modprobe ext4加载ext4文件系统模块即可进入函数register_filesystem命中断点。命中断点后,我们打印fs->name,发现是ext3,这是因为在ext4的模块初始化函数ext4_init_fs里先调用了register_as_ext3();之后又调用了register_as_ext2();register_filesystem(&ext4_fs_type);

cgdb

作者:贺子一
现在注册滴滴云,得10000元立减红包
8月特惠,1C2G1M云服务器 9.9元/月限时抢
滴滴云使者专属特惠,云服务器低至68元/年
输入大师码【7886】,GPU全线产品9折优惠

您的留言将激励我们越做越好