上篇文章 编译一个默认输出hello world的linux内核 中,我们已经知道如何编译一个可以自运行的linux内核,这篇文章我们来看下如何对内核进行断点调试。
1. 还是先进入内核目录,执行下面的命令,确保内核代码是干净的。
$ make mrproper
2. 执行以下命令,开始对内核进行配置。
$ make nconfig
3. 选中以下选项,对应选项的路径及意义如下图所示。
4. 保存上述配置后,按照上一篇文章中的方法,将我们写的hello world程序设置为内核默认使用的init程序。
$ git status -s
M usr/default_cpio_list
?? a.out
?? hello.c
$ git -P diff usr/default_cpio_list
diff --git a/usr/default_cpio_list b/usr/default_cpio_list
index 37b3864066e8..9c6b452d4c44 100644
--- a/usr/default_cpio_list
b/usr/default_cpio_list
@@ -4,3 4,4 @@
dir /dev 0755 0 0
nod /dev/console 0600 0 0 c 5 1
dir /root 0700 0 0
file /init ./a.out 755 0 0
No newline at end of file
$ cat hello.c
#include <stdio.h>
#include <unistd.h>
int main(int argc, char *argv[])
{
printf("hello world!n");
sleep(1000);
return 0;
}
5. 编译内核。
$ make -j4
省略部分输出
Kernel: arch/x86/boot/bzImage is ready (#1)
6. 内核编译完毕后,执行下面命令,设置方便内核调试的一些gdb脚本(如果之前执行过该命令,则不用重复执行)。
$ echo "add-auto-load-safe-path $(pwd)/vmlinux-gdb.py" >> ~/.gdbinit
7. 至此,准备工作都已就绪,执行下面的命令,在qemu中运行内核,并使其处于等待调试状态。
$ qemu-system-x86_64 -kernel arch/x86_64/boot/bzImage -nographic -append "console=ttyS0 nokaslr" -s -S
8. 打开另一个终端,启动gdb。
$ gdb vmlinux
省略部分输出
Reading symbols from vmlinux...
(gdb)
9. 在gdb环境下,执行下面的命令,连接qemu中启动的内核。
(gdb) target remote :1234
Remote debugging using :1234
0x000000000000fff0 in exception_stacks ()
10. 设置断点并使内核执行到断点处。
(gdb) b start_kernel
Breakpoint 1 at 0xffffffff829e0aa8: file init/main.c, line 786.
(gdb) c
Continuing.
Breakpoint 1, start_kernel () at init/main.c:786
786 {
11. 查看堆栈信息。
(gdb) bt
#0 start_kernel () at init/main.c:786
#1 0xffffffff810000e6 in secondary_startup_64 () at arch/x86/kernel/head_64.S:242
#2 0x0000000000000000 in ?? ()
12. 随便执行一些命令。
(gdb) n
790 set_task_stack_end_magic(&init_task);
(gdb) n
791 smp_setup_processor_id();
(gdb) n
794 cgroup_init_early();
(gdb) n
796 local_irq_disable();
(gdb) n
797 early_boot_irqs_disabled = true;
13. 放开断点,让内核继续执行。
(gdb) c
Continuing.
14. 此时在另一个终端,内核最终输出了hello world。
[ 2.048714] Run /init as init process
hello world!
[ 2.452502] tsc: Refined TSC clocksource calibration: 2904.013 MHz
以上就是linux内核调试的大致流程,有问题欢迎讨论。
参考资料:
https://www.kernel.org/doc/html/latest/dev-tools/gdb-kernel-debugging.html
http://nickdesaulniers.github.io/blog/2018/10/24/booting-a-custom-linux-kernel-in-qemu-and-debugging-it-with-gdb/