首页 > 系统相关 >用 kGDB 调试 Linux 内核

用 kGDB 调试 Linux 内核

时间:2023-09-10 17:46:00浏览次数:48  
标签:kGDB Linux gdb 内核 串口 serial CONFIG 调试

1 简介

这个文档记录了用 kGDB 调试 Linux 内核的全过程,都是在前人工作基础上的一些总结。以下操作都是基于特定板子来进行,但是大部分都能应用于其他平台。

要使用 KGDB 来调试内核,首先需要修改 config 配置文件,打开相应的配置,配置内核启动参数,甚至修改串口驱动添加 poll 支持,然后才能通过串口远程调试内核。

2 配置内核

2.1 基本配置

在内核配置文件 .config 中,需要打开如下选项:

CONFIG_KGDB 加入KGDB支持
CONFIG_KGDB_SERIAL_CONSOLE 使KGDB通过串口与主机通信(打开这个选项,默认会打开CONFIG_CONSOLE_POLL和CONFIG_MAGIC_SYSRQ)
CONFIG_KGDB_KDB 加入KDB支持
CONFIG_DEBUG_KERNEL 包含驱动调试信息
CONFIG_DEBUG_INFO 使内核包含基本调试信息
CONFIG_DEBUG_RODATA=n 关闭这个,能在只读区域设置断点

2.2 可选选项

CONFIG_PANIC_TIMEOUT=5 x
CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=1
CONFIG_BOOTPARAM_HUNG_TASK_PANIC_VALUE=1
CONFIG_S3C2410_WATCHDOG_ATBOOT=0
CONFIG_FRAME_POINTER 使KDB能够打印更多的栈信息
CONFIG_KALLSYMS 加入符号信息
CONFIG_KDB_KEYBOARD 如果是通过目标版的键盘与KDB通信,需要把这个打开,且键盘不能是USB接口
CONFIG_KGDB_TESTS

2.3 启动参数

打开相应的选项后,需要配置 kernel 启动参数,使 KGDB 和内核能够找到正确的通信接口。如果是使用串口,则需要配置如下选项:

console=ttySAC3,115200 kgdboc=ttySAC3,115200

如果需要调试内核的启动过程,则需要在 kgdboc 后面加入 kgdbwait 。

在其他板子上,若使用以太网口来和 KGDB 进行通信,则要把 kgdboc 换成 kgdboe(kgdb over ethernet) )。

配置完后,就可以正常编译,然后把内核下载到目标板上面。

3 串口驱动修改

如果在内核启动的过程中出现如下错误提示:

kgdb: Unregistered I/O driver, debugger disabled.

则需要根据这一部分,修改串口驱动程序,若能正常进入 kgdb ,则忽略该节,直接进入下一节使用 KGDB 。

在 drivers/tty/serial/kgdboc.c 中的 configure_kgdboc 函数,会通过 tty_find_polling_driver(cptr, &tty_line) 来找寻内核启动参数中指定的串口驱动。然后通过 kgdboc_get_char() 和 kgdboc_put_char() 来和主机串口正常通信。

可以看到在 config 配置文件的 CONFIG_CONSOLE_POLL 就是使能串口与 kgdboc 的接口。如果 tty_find_polling_driver 没有找到对应的串口通信接口,则会调用 kernel/debug/debug_core.c 中的 kgdb_unregister_io_module 进行错误处理。

有的板子的串口驱动并没有加入对 kgdboc 通信的支持,例如 Samsung 的串口驱动需要在 drivers/tty/serial/samsung.c 中手动添加。 添加与 kgdboc 通信的接口,只需添加一个发送函数和接收函数,然后在驱动操作结构体中加入对应的函数就可以了。具体的 PATCH 如下:

drivers/tty/serial/samsung.c | 22 ++++++++++++++++++++++
1 files changed, 22 insertions(+), 0 deletions(-)
diff --git a/drivers/tty/serial/samsung.c b/drivers/tty/serial/samsung.c
index ff6a4f8..5ceb7d7 100755
--- a/drivers/tty/serial/samsung.c
+++ b/drivers/tty/serial/samsung.c
@@ -893,7 +893,29 @@ static struct console s3c24xx_serial_console;
#define S3C24XX_SERIAL_CONSOLE NULL
#endif
+#ifdef CONFIG_CONSOLE_POLL
+static void s3c24xx_serial_poll_put_char(struct uart_port *port, unsigned char c)
+{
+    while (!(rd_regl(port, S3C2410_UTRSTAT) & S3C2410_UTRSTAT_TXE))
+       ;
+
+    wr_regl(port, S3C2410_UTXH, c);
+}
+
+static int s3c24xx_serial_poll_get_char(struct uart_port *port)
+{
+    while (!(rd_regl(port, S3C2410_UTRSTAT) & S3C2410_UTRSTAT_RXDR))
+        ;
+
+    return rd_regl(port, S3C2410_URXH);
+}
+#endif
+
static struct uart_ops s3c24xx_serial_ops = {
+#ifdef CONFIG_CONSOLE_POLL
+    .poll_get_char = s3c24xx_serial_poll_get_char,
+    .poll_put_char = s3c24xx_serial_poll_put_char,
+#endif
     .pm = s3c24xx_serial_pm,
     .tx_empty = s3c24xx_serial_tx_empty,
     .get_mctrl = s3c24xx_serial_get_mctrl,
--
1.7.5.4

加入这个 patch ,重新编译内核,之后就能正常进入 kgdb

4 gdb 远程调试

如果在内核启动参数中加入了 kgdbwait ,则内核会在完成基本的初始化之后,停留在 kgdb 的调试陷阱中,等待主机的 gdb 的远程连接。

由于大部分的板子只有一个调试串口,所以你需要把之前与串口通信的 minicom 退出来,然后在内核源码的目录下,执行以下命令:

$ arm-linux-gnueabi-gcc vmlinux
(gdb) target remote /dev/ttyUSB0
(gdb) set detach-on-fork on
(gdb) b panic()
(gdb) c

当然,你也可以 agent-proxy 来复用一个串口,通过虚拟出两个 TCP 端口。这时候, gdb 就需要用 target remote 命令连接 kgdb ,例如:

(gdb) target remote localhost:5551

agent-proxy 可这样下载:

git clone git://git.kernel.org/pub/scm/utils/kernel/kgdb/agent-proxy.git

具体用法,请看该 repo 下的 README 。

在用 gdb 来调试内核的时候,由于内核在初始化的时候,会创建很多子线程。而默认 gdb 会接管所有的线程,如果你从一个线程切换到另外一个线程, gdb 会马上把原先的线程暂停。但是这样很容易导致 kernel 死掉,所以需要设置一下 gdb 。一般用 gdb 进行多线程调试,需要注意两个参数: follow-fork-mode 和 detach-on-fork。

detach-on-fork 参数,指示 GDB 在 fork 之后是否断开(detach)某个进程的调试,或者都交由 GDB 控制: set detach-on-fork [on|off]

  • on: 断开调试 follow-fork-mode 指定的进程。
  • off: gdb将控制父进程和子进程。

follow-fork-mode 指定的进程将被调试,另一个进程置于暂停(suspended)状态。follow-fork-mode 的用法为:set follow-fork-mode [parent|child]

  • parent: fork之后继续调试父进程,子进程不受影响。
  • child: fork之后调试子进程,父进程不受影响。

标签:kGDB,Linux,gdb,内核,串口,serial,CONFIG,调试
From: https://www.cnblogs.com/linhaostudy/p/17691559.html

相关文章

  • linux7.X二进制方式安装MySQL5.7.X
    概述系统环境服务器型号VMwareVirtualPlatform操作系统版本RHEL7.6x86_64主机名linuxpg51PubIP192.168.115.51数据库安装版本mysqlVer14.14Distrib5.7.30,forlinux-glibc2.12(x86_64)usingEditLinewrapper安装路径规划[mysql@linuxpg51/]$tree-L1/mysql/mysq......
  • Linux : FinalShell连不上LinuxCentOS-7 (connection time out)
    依赖于一的二三系统连接不上。后想起更改了系统名称将系统通过快照更改到上一个状态即可 ......
  • Unix/Linux 系统编程学习记录
    Unix/Linux系统编程学习记录不定期更新学习笔记、心得与操作过程chapter1引言第一章学习笔记博客链接安装Linux操作系统,学习Linux基础chapter2编程背景第二章学习笔记博客链接课程来源:2021-2022-1信息安全系统设计与实现(上)的平行课程推荐好友20211120destiny......
  • linux常用命令大全
    lessless工具也是对文件或其它输出进行分页显示的工具,应该说是linux正统查看文件内容的工具,功能极其强大。less的用法比起more更加的有弹性。在more的时候,我们并没有办法向前面翻,只能往后面看,但若使用了less时,就可以使用[pageup][pagedown]等按键的功能来往前往......
  • Linux虚拟机安装及下载
    centos7操作系统下载及安装步骤(仅供参考)下载:1.打开如下网站:先下载镜像文件ping:https://www.centos.org/download/ 2.进入到如下界面 3.然后到如下界面 4.点击下载5.等待下载完成即可安装:这里要用到VMware软件,没有安装的话网址如下:DownloadVMwareWorkstati......
  • Linux平台如何实现采集音视频数据并注入轻量级RTSP服务?
    技术背景好多开发者,问我们最多的问题是,为什么要设计轻量级RTSP服务?轻量级RTSP服务,和RTSP服务有什么区别?针对这个问题,我们的回答是:轻量级RTSP服务解决的核心痛点是避免用户或者开发者单独部署RTSP服务或者RTMP服务,RTSP服务,并发或功能相对强大,数据注入模式一般是外部直接推流到RTSP服......
  • 学习linux系统中的一些笔记(持续更新)
    快捷键: CTRL+ALT+T 打开终端 CTRL+SHIFT+T 新建标签页 ALT+数字N 终端中切换到第N个标签页 TAB 终端中命令补全,输入开头补全 上下键盘 切换命令历史 CTRL+C 中断程序运行Linux命令 命令格式:command[option][arguments](选项和参数) 其中选项(option)是......
  • linux firewall 常用命令
    #1.启动防火墙systemctlstartfirewalld#2.关闭防火墙systemctlstopfirewalld#3.查看防火墙状态systemctlstatusfirewalld#4.开机自动禁用systemctldisablefirewalld#5.开机自动启动systemctlenablefirewalld#6.开放80/tcp端口(--permanent永......
  • linux下运行pycharm
    访问PyCharm官网,下载PyCharm社区版安装包pycharm-community-2022.2.3.tar.gz。放到服务器上去然后,到服务器上切换到放置的目录下,执行如下命令解压安装文件:sudotar-zxvfpycharm-community-2022.2.3.tar.gz-C/usr/local打开一个Linux终端,执行如下命令:cd/usr/local/pycharm-comm......
  • LINUX常见命令一张图
    LINUX常见命令一张图今天先到这儿,希望对云原生,技术领导力,企业管理,系统架构设计与评估,团队管理,项目管理,产品管管,团队建设有参考作用,您可能感兴趣的文章:领导人怎样带领好团队构建创业公司突击小团队国际化环境下系统架构演化微服务架构设计视频直播平台的系统架构演化微......