前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >linux内核断点调试入门

linux内核断点调试入门

作者头像
KINGYT
修改2020-05-18 16:27:48
3.3K0
修改2020-05-18 16:27:48
举报

上篇文章 编译一个默认输出hello world的linux内核 中,我们已经知道如何编译一个可以自运行的linux内核,这篇文章我们来看下如何对内核进行断点调试。

1. 还是先进入内核目录,执行下面的命令,确保内核代码是干净的。

代码语言:javascript
复制
$ make mrproper

2. 执行以下命令,开始对内核进行配置。

代码语言:javascript
复制
$ make nconfig

3. 选中以下选项,对应选项的路径及意义如下图所示。

4. 保存上述配置后,按照上一篇文章中的方法,将我们写的hello world程序设置为内核默认使用的init程序。

代码语言:javascript
复制

$ 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. 编译内核。

代码语言:javascript
复制

$ make -j4
省略部分输出
Kernel: arch/x86/boot/bzImage is ready  (#1)

6. 内核编译完毕后,执行下面命令,设置方便内核调试的一些gdb脚本(如果之前执行过该命令,则不用重复执行)。

代码语言:javascript
复制
$ echo "add-auto-load-safe-path $(pwd)/vmlinux-gdb.py" >> ~/.gdbinit

7. 至此,准备工作都已就绪,执行下面的命令,在qemu中运行内核,并使其处于等待调试状态。

代码语言:javascript
复制
$ qemu-system-x86_64 -kernel arch/x86_64/boot/bzImage -nographic -append "console=ttyS0 nokaslr" -s -S

8. 打开另一个终端,启动gdb。

代码语言:javascript
复制
$ gdb vmlinux
省略部分输出
Reading symbols from vmlinux...
(gdb)

9. 在gdb环境下,执行下面的命令,连接qemu中启动的内核。

代码语言:javascript
复制
(gdb) target remote :1234
Remote debugging using :1234
0x000000000000fff0 in exception_stacks ()

10. 设置断点并使内核执行到断点处。

代码语言:javascript
复制

(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. 查看堆栈信息。

代码语言:javascript
复制

(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. 随便执行一些命令。

代码语言:javascript
复制

(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. 放开断点,让内核继续执行。

代码语言:javascript
复制

(gdb) c
Continuing.

14. 此时在另一个终端,内核最终输出了hello world。

代码语言:javascript
复制
[    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/

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2020-04-11,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 Linux内核及JVM底层相关技术研究 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档