内核编译和调试
实验:通过 QEMU 虚拟机调试 ARM Linux 内核
首先安装 gdb-multiarch 工具包。
- tim@tim:~$ sudo apt-get install gdb-multiarch
gdb-multiarch 是一个 GNU 调试器(GDB)的多架构版本,用于调试不同架构的二进制文件。它支持多种 CPU 架构,如 ARM、MIPS、PowerPC 和 x86 等,并允许用户在同一个 GDB 实例中调试多个架构的程序。
接下来,启动 QEMU 虚拟机和远程 GDB 服务。虚拟机已经在之前配置好了,可以看文章 《Linux 系统基础知识》。
- tim@tim:~/runninglinuxkernel_5.0$ ./run_rlk_arm64.sh run debug
从脚本中可以看到是对 QEMU 启动加了 "-s -S" 参数。-s 表示启用 GDB 服务,-S 表示启动时停止 CPU,等待 GDB 连接。
-s 可以指定调试端口,如 -s tcp::8888。
没有指定的默认情况下,端口号是 1234。
接下来另起一个终端启动 GDB:
- tim@tim:~/runninglinuxkernel_5.0$ gdb-multiarch --tui vmlinux
其中,--tui(Text User Interface) 用于启用 TUI 模式,它会在 GDB 命令行界面中显示一个类似于文本图形界面的交互界面,方便用户进行调试操作。vmlinux 是 Linux 内核的符号表文件,包含了内核函数、变量等符号信息。
接着在文本图形界面上进行交互设置:将 GDB 的目标架构设置为 AArch64;连接到远程调试服务器(localhost:1234);在 start_kernel 处下断点;继续执行程序。
- (gdb) set architecture aarch64
- The target architecture is set to "aarch64"
- (gdb) target remote localhost:1234
- Remote debugging using localhost:1234
- (gdb) b start_kernel
- Breakpoint 1 at 0xffff000011bf0470 (2 locations)
- (gdb) c
如图 1 所示,最终成功在 start_kernel 处断下。界面上方显示了断点处的位置。

实验:通过 Eclipse + QEMU 调试内核
先安装 Java 环境:
- tim@tim:~$ sudo apt-get install openjdk-17-jdk-headless
接着在 官网 下载 Eclipse。安装的时候选择安装 C++ 开发环境。
新建工程
我们点击菜单 File - New - Project。如图 2 所示,选择 C/C++ - Makefile Project with Existing Code。

下一步,如图 3 所示,我们选择内核源码目录,并结束。等待工程创建加载。

设置调试选项
我们点击菜单 Run - Debug Configurations。如图 4 所示,我们在 C/C++ Attach to Application 下新建配置。Main 选项卡下设置 C/C++ Application;Build Configuration 选择 Use Active;并勾选 Disable auto build。

我们继续设置 Debugger 选项卡的内容。如图 5 所示,Debugger 选择 gdbserver;GDB debugger 设置为 gdb-multiarch;Port number 设置为 1234。

调试
和之前一样,我们先启动 QEMU 虚拟机和远程 GDB 服务。
- tim@tim:~/runninglinuxkernel_5.0$ ./run_rlk_arm64.sh run debug
上述操作都设置好了之后,我们再点击图 6 中的“虫子”按钮,即可开启调试。

连接上 GDB 服务器之后,我们在 Eclipse 的 Debugger Console 中键入以下命令:读取 vmlinux 符号表文件;将 GDB 的目标架构设置为 AArch64;设置断点。
注意是 Debugger Console,而不是 Console。
- (gdb) file vmlinux
- A program is being debugged already.
- Are you sure you want to change the file? (y or n) y
- Reading symbols from vmlinux...
- (gdb) set architecture aarch64
- The target architecture is set to "aarch64".
- (gdb) b _do_fork
- Breakpoint 1 at 0xffff000010106358: _do_fork. (2 locations)
注意,不要忘记执行 "file vmlinux"。否则符号断点会失效。
继续执行代码。如图 7 所示,成功在 _do_fork 处断下。
