kgdb调试aarch64内核模块

2023-10-28

0 开发环境

  • 笔记本:ubuntu18.04.5,内核版本为5.3
  • 开发板:imx8mp-evk
  • 内核版本:Linux5.4.24
  • 交叉编译工具链:fsl-imx-xwayland-glibc-x86_64-imx-image-core-aarch64-imx8mpevk-toolchain-5.4-zeus.sh

注:下面的可能会遗漏部分细节,但主要的部分基本都写出来了,应该无大碍。
注:以下步骤虽然针对的imx8mp-evk,但只要是aarch64架构的芯片,大部分操作都通用的。
注:这是个人的踩坑记录,虽然可以解决问题,但估计不是最好的解决方案,欢迎评论区一起探讨。

1 完善被调试终端的KGDB

远端的 gdb 连上 linux 的 kgdb 之后,在断点处执行单步调式(step/next)的时候,调式器并不是执行断点处的语句,而是每次都陷入到下面的代码段:

arch/arm64/kernel/entry.S:356
el1_irq:
        kernel_entry 1
        enable_dbg

社区也有人碰到这个问题,并提交了如下 patch 来修复这个问题。这个问题并不是在所有的 arm64 平台上都会碰到,patch 还在讨论并没有合进 upstream,Patch 如下:
[v3,2/4] arm64: kgdb: disable interrupts while a software step is enabled

注:至少我在Linux5.4.24中发现并没有解决这个问题,更不用说大部分嵌入式板子还用的4.x的内核。

diff --git a/arch/arm64/kernel/kgdb.c b/arch/arm64/kernel/kgdb.c
index b9176b324e5a..fddbc6be3780 100644
--- a/arch/arm64/kernel/kgdb.c
+++ b/arch/arm64/kernel/kgdb.c
@@ -28,6 +28,7 @@ 
 
 #include <asm/debug-monitors.h>
 #include <asm/insn.h>
+#include <asm/ptrace.h>
 #include <asm/traps.h>
 
 struct dbg_reg_def_t dbg_reg_def[DBG_MAX_REG_NUM] = {
@@ -111,6 +112,8 @@  struct dbg_reg_def_t dbg_reg_def[DBG_MAX_REG_NUM] = {
 	{ "fpcr", 4, -1 },
 };
 
+static DEFINE_PER_CPU(unsigned int, kgdb_pstate);
+
 char *dbg_get_reg(int regno, void *mem, struct pt_regs *regs)
 {
 	if (regno >= DBG_MAX_REG_NUM || regno < 0)
@@ -200,6 +203,10 @@  int kgdb_arch_handle_exception(int exception_vector, int signo,
 		err = 0;
 		break;
 	case 's':
+		/* mask interrupts while single stepping */
+		__this_cpu_write(kgdb_pstate, linux_regs->pstate);
+		linux_regs->pstate |= PSR_I_BIT;
+
 		/*
 		 * Update step address value with address passed
 		 * with step packet.
@@ -242,11 +249,20 @@  NOKPROBE_SYMBOL(kgdb_compiled_brk_fn);
 
 static int kgdb_step_brk_fn(struct pt_regs *regs, unsigned int esr)
 {
+	unsigned int pstate;
+
 	if (!kgdb_single_step)
 		return DBG_HOOK_ERROR;
 
 	kernel_disable_single_step();
 
+	/* restore interrupt mask status */
+	pstate = __this_cpu_read(kgdb_pstate);
+	if (pstate & PSR_I_BIT)
+		regs->pstate |= PSR_I_BIT;
+	else
+		regs->pstate &= ~PSR_I_BIT;
+
 	kgdb_handle_exception(1, SIGTRAP, 0, regs);
 	return 0;
 }

2 配置内核

2.1 构建开发环境

source /opt/fsl-imx-xwayland/5.4-zeus/environment-setup-aarch64-poky-linux
make imx_v8_defconfig
make menuconfig

如果在make menuconfig出现如下问题,具体解决方案可以看,我就不在这里多费口舌了。

HOSTLD  scripts/kconfig/mconf
/usr/bin/ld: cannot find -lncursesw
collect2: error: ld returned 1 exit status
scripts/Makefile.host:116: recipe for target 'scripts/kconfig/mconf' failed
make[1]: *** [scripts/kconfig/mconf] Error 1
Makefile:567: recipe for target 'menuconfig' failed
make: *** [menuconfig] Error 2

注:source /opt/fsl-imx-xwayland/5.4-zeus/environment-setup-aarch64-poky-linux为我yocto编译下载后的交叉编译工具链的安装位置

2.2设置内核选项

配置内核KGDB选项
在这里插入图片描述

配置dwmac-imx编译为模块

注:这个是我用于调试的模块,其他模块类似的操作

在这里插入图片描述

2.3 修改对应模块的优化等级

stmac目录下的Makefile添加如下编译优化等级
在这里插入图片描述
O1优化等级会出现如下小问题,不过还好,凑活着用
在这里插入图片描述

我想修改为O0,但是编译不成功,只能用O1了
注:这个地方因勉强可以用,就没有深究下去
在这里插入图片描述

2.4 内核编译

make -j 8

3 代码修改记录总计

<sazczmh 10:27:28@linux-imx>$git log --stat -p
commit 56e89cdadaac0ded943486912afc135b7dc46cf5 (HEAD -> imx_5.4.24_2.1.0)
Author: sazczmh <zmhzc@tju.edu.cn>
Date:   Sat Aug 8 10:24:36 2020 +0800

    Modify the dwmac module compilation aptimization level to O1
---
 drivers/net/ethernet/stmicro/stmmac/Makefile | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/net/ethernet/stmicro/stmmac/Makefile b/drivers/net/ethernet/stmicro/stmmac/Makefile
index 413d2104948d..91d55b92ce88 100644
--- a/drivers/net/ethernet/stmicro/stmmac/Makefile
+++ b/drivers/net/ethernet/stmicro/stmmac/Makefile
@@ -1,6 +1,6 @@
 # SPDX-License-Identifier: GPL-2.0
-# Modify the module compilation aptimization level to O0
-EXTRA_CFLAGS   += -O0
+# Modify the module compilation aptimization level to O1
+EXTRA_CFLAGS   += -O1
 
 obj-$(CONFIG_STMMAC_ETH) += stmmac.o
 stmmac-objs:= stmmac_main.o stmmac_ethtool.o stmmac_mdio.o ring_mode.o \

commit 550c7b51c425418b8122a834e5236592537a22f9
Author: sazczmh <zmhzc@tju.edu.cn>
Date:   Sat Aug 8 09:43:29 2020 +0800

    Modify the code warning!
---
 arch/arm64/kernel/kgdb.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/arm64/kernel/kgdb.c b/arch/arm64/kernel/kgdb.c
index dfe6ffcd71f6..52f5010c1166 100644
--- a/arch/arm64/kernel/kgdb.c
+++ b/arch/arm64/kernel/kgdb.c
@@ -269,7 +269,7 @@ static int kgdb_step_brk_fn(struct pt_regs *regs, unsigned int esr)
     else
         regs->pstate &= ~PSR_I_BIT;
 
-       kgdb_handle_exception(1, SIGTRAP, 0, regs);
+    kgdb_handle_exception(1, SIGTRAP, 0, regs);
        return DBG_HOOK_HANDLED;
 }
 NOKPROBE_SYMBOL(kgdb_step_brk_fn);

commit c92c9abd0aebdc70f9a97f670cfa61cc1fa8e96e
Author: sazczmh <zmhzc@tju.edu.cn>
Date:   Sat Aug 8 09:35:38 2020 +0800

    To reduce unnecessary compilation warnings, only module compilation optomization level is O0
---
 Makefile                                     | 2 +-
 drivers/net/ethernet/stmicro/stmmac/Makefile | 3 +++
 2 files changed, 4 insertions(+), 1 deletion(-)

diff --git a/Makefile b/Makefile
index 02191761c23f..c32c78cf2fe5 100644
--- a/Makefile
+++ b/Makefile
@@ -700,7 +700,7 @@ KBUILD_CFLAGS       += $(call cc-disable-warning, format-overflow)
 KBUILD_CFLAGS  += $(call cc-disable-warning, address-of-packed-member)
 
 ifdef CONFIG_CC_OPTIMIZE_FOR_PERFORMANCE
-KBUILD_CFLAGS += -O1
+KBUILD_CFLAGS += -O2
 else ifdef CONFIG_CC_OPTIMIZE_FOR_PERFORMANCE_O3
 KBUILD_CFLAGS += -O3
 else ifdef CONFIG_CC_OPTIMIZE_FOR_SIZE
diff --git a/drivers/net/ethernet/stmicro/stmmac/Makefile b/drivers/net/ethernet/stmicro/stmmac/Makefile
index ae223ec1b754..413d2104948d 100644
--- a/drivers/net/ethernet/stmicro/stmmac/Makefile
+++ b/drivers/net/ethernet/stmicro/stmmac/Makefile
@@ -1,4 +1,7 @@
 # SPDX-License-Identifier: GPL-2.0
+# Modify the module compilation aptimization level to O0
+EXTRA_CFLAGS   += -O0
+
 obj-$(CONFIG_STMMAC_ETH) += stmmac.o
 stmmac-objs:= stmmac_main.o stmmac_ethtool.o stmmac_mdio.o ring_mode.o \
              chain_mode.o dwmac_lib.o dwmac1000_core.o dwmac1000_dma.o \

commit 11eb493c15b271f00d982985dedca75e98145734
Author: sazczmh <zmhzc@tju.edu.cn>
Date:   Sat Aug 8 09:21:53 2020 +0800

    arm64, kgdb debug: Disable interrupts while a software step is enable
---
 arch/arm64/kernel/kgdb.c | 23 ++++++++++++++++++++---
 1 file changed, 20 insertions(+), 3 deletions(-)

diff --git a/arch/arm64/kernel/kgdb.c b/arch/arm64/kernel/kgdb.c
index 43119922341f..dfe6ffcd71f6 100644
--- a/arch/arm64/kernel/kgdb.c
+++ b/arch/arm64/kernel/kgdb.c
@@ -19,6 +19,11 @@
 #include <asm/insn.h>
 #include <asm/traps.h>
 
+#include <asm/ptrace.h>
+
+static DEFINE_PER_CPU(unsigned int, kgdb_pstate);
+
+
 struct dbg_reg_def_t dbg_reg_def[DBG_MAX_REG_NUM] = {
        { "x0", 8, offsetof(struct pt_regs, regs[0])},
        { "x1", 8, offsetof(struct pt_regs, regs[1])},
@@ -206,7 +211,10 @@ int kgdb_arch_handle_exception(int exception_vector, int signo,
                err = 0;
                break;
        case 's':
-               /*
+        
+        __this_cpu_write(kgdb_pstate, linux_regs->pstate);
+        linux_regs->pstate |= PSR_I_BIT;
+        /*
                 * Update step address value with address passed
                 * with step packet.
                 * On debug exception return PC is copied to ELR
@@ -249,8 +257,17 @@ NOKPROBE_SYMBOL(kgdb_compiled_brk_fn);
 
 static int kgdb_step_brk_fn(struct pt_regs *regs, unsigned int esr)
 {
-       if (!kgdb_single_step)
-               return DBG_HOOK_ERROR;
+    unsigned int pstate;
+
+    if (!kgdb_single_step)
+        return DBG_HOOK_ERROR;
+    kernel_disable_single_step();
+
+    pstate = __this_cpu_read(kgdb_pstate);
+    if (pstate & PSR_I_BIT)
+        regs->pstate |= PSR_I_BIT;
+    else
+        regs->pstate &= ~PSR_I_BIT;
 
        kgdb_handle_exception(1, SIGTRAP, 0, regs);
        return DBG_HOOK_HANDLED;

这个是截图,比较好看些
在这里插入图片描述

在这里插入图片描述

4 文件共享

开发板与PC的文件传输是通过NFS,方便进行开发,具体可以参考【Linux笔记】挂载网络文件系统

我的共享文件夹为~/imx8mp_evk_nfs/,共享模块文件,使用如下命令即可,比较方便

cp ~/linux-imx/drivers/net/ethernet/stmicro/stmmac/dwmac-imx.ko ~/imx8mp_evk_nfs/

注:文件夹挂载之前不要在这个文件夹,否则会没法刷新cd /;cd /mnt 即可解决。
注:我的配置环境是开发板与PC的网络是通过一个路由器进行通信的,网线直连会有所不同。

5 串口复用

为了调试方便使用agent-proxy即可,需要进行编译安装

使用如下命令可以将ttyUSB2复用为两个端口,方便调试。

./agent-proxy  5550^5551 0 /dev/ttyUSB2,115200 -s003

其中一个可以用如下命令连接开发板,与板子进行通信

telnet localhost 5550

另一个端口用于KGDB调试使用

在这里插入图片描述
:这个具体原理我没有深究,大概就是将串口的读取发送数据,通过localhost虚拟出来两个端口来进行使用,很容易上手。
:这个/dev/ttyUSB2需要具体情况具体设置,对于imx8mp来说是从USB插入开始,识别的第三个串口,具体可以用demsg查看

6 GDB优化

Ubuntu18自带的GDB不太好使,调试不方便,需要gdb的界面增强版CGDB,增加了语法高亮等一系列小功能,可以提高调试效率。

使用如下命令即可进行安装

sudo apt install cgdb

下面是我cgdb的调试界面,相对于默认的gdb单色调试界面,这个语法高亮非常实用。
在这里插入图片描述

注:我也尝试使用eclipse进行调试,可是存在着一些问题,因此就先不说那个了。

7 开发板配置

开发板的连接是通过如下命令进行的

./agent-proxy  5550^5551 0 /dev/ttyUSB2,115200 -s003
telnet localhost 5550

使用如下命令即可进入gdb命令行,然后再执行kgdb即可等待主机的连接

mount -t nfs -o nolock,vers=4 192.168.3.5:/home/sazczmh/imx8mp_evk_nfs /mnt

echo ttymxc1 > /sys/module/kgdboc/parameters/kgdboc
echo g  >  /proc/sysrq-trigger

注:这个192.168.3.5:/home/sazczmh/imx8mp_evk_nfs为我的主机共享文件夹,IP以及目录需要根据具体情况进行修改。
注:ttymxc1为imx8mp的调试串口,不同的把板子可能需要进行相应的修改。

8 主机配置

执行如下命令解析vmlinux,准备开始调试

cd ~/linux-imx
cgdb -d gdb-multiarch vmlinux

设置架构为aarch64,再加载被调试模块的信息

set architecture aarch64

add-symbol-file drivers/net/ethernet/stmicro/stmmac/dwmac-imx.ko 0xffff8000090a0000

注:set architecture aarch64的目的是防止出现Remote ‘g’ packet reply is too long (expected 168 bytes, got 788 bytes)这个错误,也可以利用交叉编译工具链的gdb工具,就不会出现这个问题,后续文章会略有涉及。
注:0xffff8000090a0000这个可以提前通过insmod加载对应模块,再通过cat /proc/modules 可以查看,查看之后注意要卸载rmmod。

现在要连接开发板,设置对应的断点,c开始执行调试

target remote localhost:5551
b stmmac_dvr_probe
c

开发板同时要加载模块,触发断点,就可以进行单步调试了。

参考博客

  • ARM64 的 Linux 内核 kgdb/kdb调试
    这个讲解的很全面具体,本文就是大部分是参考这个文章,然后根据个人需求进行魔改优化的。
  • GDB调试利器
    从火哥这个文章知道CGDB这个好东西,对于高效率调试非常有帮助,后面还会有关于它的文章。

注:个人能力有限,欢迎批评指正。



原创不易,严禁剽窃!

在这里插入图片描述

欢迎大家关注我创建的微信公众号——小白仓库
原创经验资料分享:包含但不仅限于FPGA、ARM、RISC-V、Linux、LabVIEW等软硬件开发,另外分享生活中的趣事以及感悟。目的是建立一个平台记录学习过的知识,并分享出来自认为有用的与感兴趣的道友相互交流进步。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

kgdb调试aarch64内核模块 的相关文章

随机推荐

  • React 生命周期&&diff算法

    目录 事件处理 收集表单数据 高阶函数 函数科里化 生命周期 认识生命周期 生命周期流程图 旧 生命周期流程图 新 getSnapshotBeforeUpdate应用场景 生命周期总结 DOM的diff算法 概念 key的值的作用 案例 事
  • 2019大厂Android高级面试题汇总

    前言 金三银四 很多同学心里大概都准备着年后找工作或者跳槽 最近有很多同学都在交流群里求大厂面试题 正好我电脑里面有这方面的整理 于是就发上来分享给大家 这些题目是网友去百度 小米 乐视 美团 58 猎豹 360 新浪 搜狐等一线互联网公司
  • 第一章

    1 写出Java领域的相关技术 答 Java主要有三类 Javase javame javaee JavaSE是Java技术的核心 提供基础的Java开发工具 Javaee主要用于网络程序和企业级应用的开发 2 简述Java程序中的注释的作
  • 软考高项之进度管理——攻坚记忆

    软考高项之进度管理 攻坚记忆 一 进度管理过程 二 规划进度管理和制定进度计划区别 三 重要的工具与技术 四 相关重要概念 一 进度管理过程 1 规划进度管理 需要写一个文档 进度管理计划 里面规定了如何做好进度管理 2 定义活动 识别和记
  • 接口请求之加密参数(用户名和密码),使用md5方法加密

    一 接口请求涉及到一些类似用户名和密码等敏感信息的东西 请求肯定要进行加密 当然首先你得问开发 他们对参数是否加密 用了什么方式进行加密 我这里就用md5加密方式对请求的密码进行加密 二 前端对字符串类型的密码进行加密 输出秘钥 传递时候是
  • MySQL必知必会 学习笔记 第二十六章 管理事务处理

    并非所有引擎都支持事务处理 MyISAM不支持 InnoDB支持 事务处理可用来维护数据库的完整性 它保证成批的MySQL操作要么完全执行 要么完全不执行 如果没有错误发生 整组语句写到数据库表 如果发生错误 将已经执行的部分语句进行回退
  • Linux下快速比较两个目录的不同

    每次更新版本就想要在Linux下比较目录a和目录b中文件列表的差别 然后对目录a比目录b中多出的文件 少掉的文件分别做处理 但是 在网上搜索了多次也都没找到能直接处理好的工具 所以想了很多不少方法 自我感觉都不错 而且网上似乎没有这方面的文
  • IFNULL、ISNULL、NULLIF(SYBASE)

    IFNULL expr1 expr2 如果expr1为NULL 返回值为expr2 假如expr1不为NULL 则IFNULL 的返回值为expr1 ISNULL expr1 expr2 如果expr1值为NULL 则返回值为expr2 如
  • ubuntu不能输入美元符号_听说 90% 的人都在 win10 下使用 ubuntu 子系统了!

    win10下安装 配置与使用ubuntu子系统完全指南 最近 遇到很多Python第三方库不支持Windows系统或则安装很繁琐要不就是要安装vc 环境 都比较麻烦 对于开发者而言 Mac真的是个不错的选择 Linux就更不用说了 一直听过
  • java爬取当当网所有分类的图书信息(ISBN,作者,出版社,价格,所属分类等)

    java爬取当当网所有分类的图书信息 ISBN 作者 出版社 价格 所属分类等 顺手写的 没有建立新项目 放我自己的项目的一个文件夹里了 有兴趣的朋友可以拉下来试试 https gitee com panlufei demo blob ma
  • RN获取屏幕高宽、自适应(rem)设置

    RN获取屏幕高宽 自适应 rem 设置 1 引入Dimensions 2 通过Dimensions get window width height 获取屏幕高宽 pxToDp自适应js文件 import Dimensions from re
  • AD17无法导出外形层gerber文件

    近日在工作的时候发现Keep OUT层导出的gerber文件 后缀为 GKO 中无内容 导致板厂加工时发现无外形层 发现原因 板子外框线我是在Keep OUT层画的 双击线条发现Keepout选项被勾选 当我把其中一条线条的Keepout选
  • Jquery JqGrid常用方法

    记录平时开发中所用到的JqGrid方法 先附上一个jqgrid 详细介绍的链接 http blog mn886 net jqGrid 1 删除多行数据 var selectedId one grid jqGrid getGridParam
  • 怎么检测硬盘是否有坏道

    硬盘是电脑上非常重要的一个部分 硬盘的好坏也决定了电脑运行的稳定 硬盘最常见的就是出现坏道 一旦有了坏道 将会表现出一些异常的状况 如发出怪音 无法完成分区和格式化的操作 读取文件或运行程序时出错 磁盘占用100 甚至蓝屏等 那怎么检测硬盘
  • Windows下快速启动Kafka以及三种发送消息的方式

    目录 一 下载Kafka 二 启动kafka 2 1 启动kafka前得先启动zk 2 2 启动kafka 三 操作Kafka 3 1 创建 Kafka 主题 Topic 3 2 将信息写入主题 Topic 3 3 读取信息 四 Java实
  • linux下 在终端查看并设置串口

    1 查看串口设备 一般为ttyUSB0 ls dev 2 查看串口的波特率等信息 stty F dev ttyUSB0 a 3 设置串口波特率 数据模式 该命令将串口1 dev ttyUSB0 设置成115200波特率 8位数据模式 stt
  • linux设备驱动的实现与理解

    linux设备驱动的实现与理解 在linux中对字符设备的驱动编写 驱动插入以及使用驱动文件进行逻辑控制 其中这份代码写在嵌入式板中 通过控制io来实现灯的亮灭 但是设备驱动的实现流程与灯无关 大致的流程都体现在代码中 我感觉这份博客我自己
  • 重新出发,找回那个丢失的自己

    时隔一年多了 当初不顾一切的过来 就不要再因为眼前的困难而选择逃避 正视自己的不足 解决它 不忘初心 坚定 believe yourself
  • FreeRTOS入门(05):事件组

    文章目录 目的 基础说明 相关函数 使用演示 总结 目的 事件组是RTOS中相对常用的用于任务间交互的功能 这篇文章将对相关内容做个介绍 本文代码测试环境见前面的文章 FreeRTOS入门 01 基础说明与使用演示 基础说明 事件组 Eve
  • kgdb调试aarch64内核模块

    kgdb调试aarch64内核模块 0 开发环境 1 完善被调试终端的KGDB 2 配置内核 2 1 构建开发环境 2 2设置内核选项 2 3 修改对应模块的优化等级 2 4 内核编译 3 代码修改记录总计 4 文件共享 5 串口复用 6