用 kGDB 调试 Linux 内核

简介

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

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

配置内核

基本配置

在内核配置文件:.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 关闭这个,能在只读区域设置断点

可选选项

CONFIG_PANIC_TIMEOUT=5
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

启动参数

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

console=ttySAC3,115200 kgdboc=ttySAC3,115200

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

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

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

串口驱动修改

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

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

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://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之后调试子进程,父进程不受影响。

REFERENCE

时间: 2024-10-22 09:14:18

用 kGDB 调试 Linux 内核的相关文章

VELT-0.1.5开发:使用kgdb调试Linux内核

VELT的全称是Visual EmbedLinuxTools,它是一个与visual gdb类似的visual studio插件,用以辅助完成Linux开发.利用这个插件,将可以在visual studio的IDE中进行Linux应用程序的开发(包括编译和调试),也可以进行uboot和linux内核的编译,并根据编译时的错误信息正确定位到源码.目前的版本是0.1.4,仅支持vs2013.此插件可以在CSDN下载频道下载(http://download.csdn.net/detail/lights

用KGdb和VMware调试Linux内核,System Call

Linux的内核和System Call不好调试,参考这里: http://stackoverflow.com/questions/5999205/cannot-step-into-system-call-source-code 简单来说,如果想在本机调试system call,那么当你进入system call时,系统已经在挂起状态了,那么它又怎样能响应用户的输入? 所以,有一个UML(http://user-mode-linux.sourceforge.net/)的方式,把内核当成一个进程启

大杀招之使用QEMU调试Linux内核代码

Linux内核代码的调试非常麻烦,一般都是加printk, 或者用JTAG调试. 这里的方法是用QEMU来调试Linux内核.因为QEMU自己实现了一个gdb server, 所以可以非常方便的使用gdb来调内核. 这对内核的学习也非常有帮助. 为了尽量不多花时间在QEMU设置上,这里直接使用以下的内核image: http://free-electrons.com/community/demos/qemu-arm-directfb/ 1. QEMU的安装 这个可以自己去QEMU的官网下载编译,

跟踪调试Linux内核的启动过程

跟踪调试Linux内核的启动过程---使用gdb 符钰婧 原创作品转载请注明出处 <Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-1000029000 ” 本次的实验是使用gdb跟踪调试内核从start_kernel到init进程启动,并分析启动的过程. 1.首先是在实验楼虚拟机上进行调试跟踪的过程. (1) 先构造一个简单的Linux系统 (2) 接下来使用gdb跟踪调试内核 启动(窗口被冻结) 另开一个shell窗口(水平分割)

使用QEMU调试Linux内核代码

Linux内核代码的调试非常麻烦,一般都是加printk, 或者用JTAG调试.这里的方法是用QEMU来调试Linux内核.因为QEMU自己实现了一个gdb server, 所以可以非常方便的使用gdb来调内核. 这对内核的学习也非常有帮助. 为了尽量不多花时间在QEMU设置上,这里直接使用以下的内核image: http://free-electrons.com/community/demos/qemu-arm-directfb/ 1,QEMU的安装 这个可以自己去QEMU的官网下载编译,如果

调试linux内核环境搭建方法(ddd+busybox+qemu+linux3.5.4内核)

环境搭建 1.1.准备工作 (1).qemu虚拟机 (2).busybox软件 (3).linux-3.5.4内核 (4).ddd 调试工具(终端中输入 sudo apt-get install ddd 安装) 1.2.编译内核 (1)建立工作目录:mkdir -p ~/work/qemu (2)切换到此目录:cd ~/work/qemu (3)下载 linux内 核 (4)解压内核:tar -jxvf linux-3.5.4.tar.bz2 (5)切换到linux-3.5.4目录: cd li

【转】TI-Davinci开发系列之六CCS5.2调试Linux内核

上转博文<TI-Davinci开发系列之五CCS5.2使用gdbserver远程调试应用程序> 使用CCS5.2远程调试内核时,只需导入Linux内核源码,而不需要编译内核,也就不会用到交叉编译链,同时不需要使用gdbserver,但需要仿真器XDS560V2,所以Windows和Linux都可以完成,但考虑到Windows CCS5.2软件成熟,bug较少,且Windows易于操作,故本文推荐并主要介绍Windows版CCS5.2调试内核的方法.在介绍远程调试Linux之前,务必保证仿真器X

用qemu调试linux内核

1)dd if=/dev/zero of=./busybox.img bs=1M count=642)mkfs.ext3 busybox.img3)下载busybox,http://www.busybox.net/downloads/#tar jxvf busybox-1.18.0.tar.bz2 (解压busybox压缩包)#cd busybox-1.18.0 (进入到解压后的busybox源码目录)#make menuconfig (配置busybox)注意配置时,一定要选择静态链接选项,该

调试Linux内核环境MenuOS系统

调试Linux内核环境MenuOS系统 一.实验简介 本文采用自己搭建环境的方式对gdb进行了模拟. (1)工具介绍 1)QEMU介绍 QEMU是一个主机上的VMM(virtual machine monitor),通过动态二进制转换来模拟CPU,并提供一系列的硬件模型,使guest os认为自己和硬件直接打交道,其实是同QEMU模拟出来的硬件打交道,QEMU再将这些指令翻译给真正硬件进行操作.通过这种模式,guest os可以和主机上的硬盘,网卡,CPU,CD-ROM,音频设备和USB等设备进