接博文《Linux内核驱动开发之KGDB单步调试内核(kgdboc方式)》。上篇博文中,仅简单介绍使用串口的Kgbd的流程(kgdboc方式),本文将重点介绍KGDB调试Linux内核的原理。内核版本在2.6.26以前的Linux,kgdb是通过补丁安装的,过程非常复杂,而且问题比较多.Linux内核从 2.6.26开始已经在内部集成kgdb,只需要配置kgdb并重新编译2.6.26(或更高)内核即可.使用kgdb调试需要两台机器,即主机和目标机(一般为开发板),两者通过串口线相连。要调试的内核编译需要配置支持kgbd,它跑在目标机上,主机上使用gdb通过串口线进行远程调试目标机上的内核。另外kgdb还支持网络方式(即kgdboe方式)进行远程调试内核,见本文第三部分。
/**********************************************************************************************************************************/
原创作品,转载时请务必以超链接形式标明文章原始出处:http://blog.csdn.net/gqb666/article/details/9120483,作者:gqb666
/**********************************************************************************************************************************/
一、KGDB原理:
Kgdb相关源码主要实现了主机上gdb远程调试所需的功能,包括命令处理、陷阱处理以及串口通信3个主要部分。Kgdb会在Linux内核中添加一个调试stub,调试stub是Linux内核中的一小段代码,是运行gdb的开发机和目标机内核之间的媒介。gdb和调试stub之间通过gdb串行协议进行通信。Gdb串行协议是一种基于消息的ASCII码协议,包含了各种调试命令。当设置断点时,kgdb将断点的指令替换为一条trap指令,当执行到断点时控制权就转移到调试stub中去。此时,调试stub的任务就是使用远程串行通信协议将当前内核环境传送给gdb,然后从gdb处接收命令。gdb命令告诉调试stub下一步该做什么,当调试stub收到继续执行的命令时,将恢复内核的运行环境,把对cpu的控制权重新交还给内核。
二、KGDB功能部件:
(1)GDB stub。
Gdb stub被称为调试插桩(简称为stub),是kgdb调试器的核心。它是Linux内核中的一小段代码,用来处理主机上gdb发来的各种请求;并且在内核处于被调试状态时,控制目标机上的处理器。
(2)陷阱处理。
当设置断点时,kgdb会提供一个异常处理函数,将断点位置的指令替换成一条异常指令。执行到该断点时该异常会发生,内核则将cpu控制权交给kgdb调试器,程序进入kgdb的提供异常处理函数中。在该异常处理函数中,可以分析内核代码的各种情况。
(3)串口通信。
Gdb和调试stub之间通过gdb串行协议进行通信。它是一种基于消息的ASCII码协议,包含了各种调试命令。
三、KGDBOE方式配置:(参阅博文Linux内核驱动开发之KGDB单步调试内核(kgdboc方式))
最后要说的是除了使用串口外,也可以使用网卡进行通信,也就是kgdboe方式。kgdboe方式要比kgdboc方式优越,上篇kgdboc使用流程中也提到,当u-boot加载内核执行到 kgdb: Waiting for connection from remote gdb... 要手动关闭该串口,因为gdb远程连接时也需要此串口。那么带来的影响就是我们无法看到调试过程中内核的输出信息,而网卡(kgdboe)方式刚可以避免这一缺陷。下面简单介绍下网卡方式(kgdboe)的配置流程:
(1)配置内核:
a) CONFIG_NETCONSOLE (Networking support -> Network console logging support)
b) CONFIG_DEBUG_KERNEL (Kernel hacking -> Kernel Debugging)
c) CONFIG_KGDB (Kernel hacking -> KGDB)
d) CONFIG_KGDB_ETH (Kernel hacking -> KGDB -> Method of KGDB communication -> Ethernet)
(2)修改u-boot的启动参数bootargs以支持kgdb调试(与kgdboc类似):
setenv bootargs 'console=…kgdboe=[target-port]@<target-ip>/[dev][target-macaddr],[host-port]@<host-ip>/[dev] kgdbwait … nfsroot=…
举例:kgdboe=@192.168.1.4/,@192.168.1.3/
主要增加以上红色字体部分,解释下参数的意义:
- target-port (optional): GDB port (default 6443)
- target-ip: target ip address (i.e DVEVM ip address)
- dev (optional): network interface (default eth0)
- host-port (optional): Host port use to send/recieve UDP packets (default 6442)
- host-ip: Host IP address
(3)配置主机上的.gdbinit文件:
在linux内核源码根目录下创建一个.gdbinit文件,其内容为:
- target remote udp:192.168.2.4:6443
(4)开始调试:
开发板侧:
TI DaVinci EMAC: MAC address is deadbeaf
TI DaVinci EMAC Linux version updated 4.0
TI DaVinci EMAC: Installed 1 instances.
netconsole: not configured, aborting
kgdboe: local port 6443
kgdboe: local IP 192.168.1.4
kgdboe: interface eth0
kgdboe: remote port 6442
kgdboe: remote IP 192.168.1.3
kgdboe: remote ethernet address ff:ff:ff:ff:ff:ff
kgdboe: device eth0 not up yet, forcing it
kgdboe: debugging over ethernet enabled
主机侧:
$arm-none-linux-gnueabi-gdb ./vmlinux
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB. Type "show warranty" for details.
This GDB was configured as "--host=i686-pc-linux-gnu --target=arm-none-linux-gnueabi".
warning: The remote protocol may be unreliable over UDP
warning: some events may be lost, rendering further debugging impossible
0xc00533dc in breakpoint () at kernel/kgdb.c:1620
1620 atomic_set(&kgdb_setting_breakpoint,1);
(gdb)