linux驱动之调试技巧--- 应用程序远程gdb+vscode调试应用程序, 串口kgdboc调试.ko驱动程序

news2025/2/25 4:05:10

环境:
Ubuntu: Ubuntu 22.04.1
开发板: imx6ull
linux内核版本: Linux4.9.88
虚拟机: vmware15
交叉编译工具gcc版本: 4.9.4 (Linaro GCC 4.9-2017.01)
arm-linux-gdb版本: gdb (Linaro_GDB-2017.01) 7.10.1.20160210

先决条件
开发板 虚拟机 PC 可互通网络 交叉编译环境已经搭建好
开发板IP: 192.168.31.178
虚拟机IP: 192.168.31.158
PC机IP:192.168.31.139

使用kgdboc模式(串口连接)调试驱动, 远程gdb调试(网口连接)应用程序

本文操作能达到的效果 :
在linux中使用vscode进行图形化调试开发板的应用程序, 同时能对驱动代码进行断点调试:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

应用程序远程gdb图形化调试环境搭建

可实现在vscode中直接对应用程序和驱动程序的联调.
搭建环境:
Makefile:
需要对应用程序的编译加上编译选项 -g
对驱动程序的编译加上 EXTRA_CFLAGS +=-g

搭建应用程序的图形化调试环境:
移植GDB
如果交叉编译工具链有 arm-linux-gdb 和 gdbserver可以直接用 不需要编译源码
在这里插入图片描述
获取gdb源码:
gdb官网上获取源码,地址为 http://www.gnu.org/software/gdb/download/

  • 编译 gdb

配置项如下:
–target:目标机交叉编译器前缀,也就是你所使用的交叉编译器前缀,比如在本教程中就
设置为 arm-linux-gnueabihf。
–host:指定编译后的程序在哪里运行,编译 gdb的时候就需用设置,因为我们是需要在 PC
上运行的,编译 gdbserver的时候就要设置为 arm-linux。
–prefix:指定安装目录。
创建一个名为“gdb”的文件夹,用来保存编译后的 gdb和 gdbserver,路径自行选择。

mkdir build  //在 gdb源码下新建 build目录
cd build   //进入到刚刚创建的 build目录下
../configure --target=arm-linux-gnueabihf --prefix=/home/yu/gdb
make    //编译 
make install  //安装

不出意外的话在~/gdb目录下会有 需要arm-linux-gnueabihf-gdb 和 gdbserver

  • 运行./arm-linux-gnueabihf-gdb

在这里插入图片描述
没问题, 如果运行不了,更换交叉工具链再进行源码编译

  • 将gdbserver放到开发板的/bin 目录中

开发板运行命令 gdbserver --version
在这里插入图片描述

  • 配置vscode
    安装远程调试插件"Remote Development"
    点击“调试”->“添加配置”,然后选择“C++(GDB/LLDB)
    在这里插入图片描述
    点击之后,当前文件夹会新建一个名为“launch.json” 的文件,此文件会存放在.vscode目录下

  • 修改launch.json的内容:

{

5 “version”: “0.2.0”,
6 “configurations”: [
7 {
8 “name”: “gdbtest”, //填写应用程序的名字
9 “type”: “cppdbg”,
10 “request”: “launch”,
11 “program”: “ w o r k s p a c e F o l d e r / g d b t e s t " , / / 应 用 程 序 的 路 径 12 " a r g s " : [ ] , 13 " s t o p A t E n t r y " : f a l s e , 14 " c w d " : " {workspaceFolder}/gdbtest", //应用程序的路径 12 "args": [], 13 "stopAtEntry": false, 14 "cwd": " workspaceFolder/gdbtest",//12"args":[],13"stopAtEntry":false,14"cwd":"{workspaceFolder}”,

25 “miDebuggerPath”:
“/home/yu/ToolChain/bin/arm-linux-gnueabihf-gdb”, //指定刚刚编译出来的arm-linux-gnueabihf-gdb的路径
26 “miDebuggerServerAddress”: “192.168.31.178:2001” //填写servergdb的ip地址,端口自定义
27
28 }
29 ]
30 }

  • 测试
    开发板运行测试用例gdbtest(gdbtest自行准备)
    运行 gdbserver 192.168.31.158:2001 gdbtest在这里插入图片描述进入等待远程连接状态

vscode进入代码打上断点直接F5进行调试
在这里插入图片描述
成功运行

至此调试应用程序的环境已经搭建完毕~

构建出支持调试的内核镜像

  • make menuconfig 中搜索以下的选项

在这里插入图片描述
有些可能在自己的开发板上没有, 直接跳过即可, 笔者开发板仅设置了
1, CONFIG_KGDB=y (重要)
Kernel hacking —>KGDB:kernel debugger
2, CONFIG_DEBUG_INFO = y
Kernel hacking —>Compile-time checks and compiler options—>Compile the kernel with debug info

make zImage 编译出内核
更换掉开发板中的内核

  • 在uboot中修改启动参数(要根据自身开发板情况进行修改, 不能盲目跟从复制)
    查看uboot环境变量(这里都是开发板厂商配置的环境变量, 需要稍作修改)
    目的对bootargs环境变量添加kgdboc指令
    将所有环境变量复制出来 搜索以下bootargs变量在哪里被用过
    在这里插入图片描述
    由于板卡是mmc启动模式, mmcargs变量会被调用, 在这里加上kgdboc=${console},${baudrate}
    表明kgdb使用的串口名和波特率

  • 在Ubuntu中搭建直连开发板环境
    需要将usb从主机转移到ubuntu中
    安装 minicom

sudo apt install minicom

将开发板用串口连接到Ubuntu中(vmware右下角有提示)
在这里插入图片描述
查看 usb设备文件

ls /dev/tty*

在这里插入图片描述
已有 ttyUSB0设备
修改设备权限

sudo chmod 777 ttyUSB0

设置minicom

sudo minicom -s

在这里插入图片描述
在这里插入图片描述
运行命令 minicom 可进入开发板
Ubuntu直连开发板完成

  • 开发板进入内核调试模式
    在前面的步骤已经设置好了 kgdboc参数
    现在加载需要调试的ko驱动程序
insmod hello_drv.ko

查看在开发板中模块信息

cat /proc/modules

在这里插入图片描述
在Ubuntu终端中使用
arm-linux-gnueabihf-objdump -h hello_drv.ko
查看驱动文件头信息
会跳出一大串地址信息, 需要关注
.text
在这里插入图片描述
.bss
在这里插入图片描述
.data
在这里插入图片描述
一切准备就绪 开发板中启用命令 (如果这一步骤没成功 是 uboot设置的启动参数 bootargs 没设置 kgdboc)

echo g > /proc/sysrq-trigger

进入KGDB调试模式 等待GDB连接
在这里插入图片描述

  • Ubuntu终端使用GDB连接KGDB
    我们使用vscode中的终端来完成, 更方便查阅代码
    打开vscode, 调出终端窗口 进入驱动程序所在目录

在这里插入图片描述
运行 命令

yu@yu$ arm-linux-gnueabihf-gdb

进入gdb调试模式
设置波特率

(gdb) set serial baud 115200

连接至串口与kgdb通信

(gdb) target remote /dev/ttyUSB0

在这里插入图片描述
使用add-symbol-file导入ko文件符号

(gdb) add-symbol-file hello_drv.ko 0x7f000034 -s .data 0x7f00074c -s .bss 0x7f000a24

这些值的计算方式如下:

add-symbol-file *.ko text_addr –s .section0 section_addr0 -s .section1 section_addr1
Text_addr = install_addr + file_off
.section_addr0 = install_addr + file_off
如:.data 段
Section_addr = install_addr + file_off = 0x7f000000 + 0x74c = 0x7f00074c

在这里插入图片描述
此时输入指令 list 应该是能看到已经进入了 自己写的驱动程序在这里插入图片描述
输入 b 30 指令 设置断点

输入 c指令 开始 运行在这里插入图片描述

  • 一切就绪开始 应用程序 与 驱动的联调
    在pc机使用网口连接 开发板 可以发现开发板已经能正常操作了

按之前的步骤启动gdbserver

在这里插入图片描述
不出意外的话 当应用程序运行到第36行read函数时, 驱动程序的断点会被击中
在这里插入图片描述
果然正如我所料 断点击中, 此时就可以用gdb的命令来调试驱动程序了

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/39743.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

哈希(Hash)

文章目录一、哈希是什么?二、哈希冲突三、开放定址法1.线性探测2.二次探测四、拉链法/哈希桶五、哈希的应用1.位图1.1 面试题1.2 位图概念1.3 位图的应用2.布隆过滤器2.1概念2.2布隆过滤器的查找2.3布隆过滤器的删除一、哈希是什么? Hash,一般…

语音识别系列︱利用达摩院ModelScope进行语音识别+标点修复(四)

终于有时间更新语音识别系列了,之前的几篇: 语音识别系列︱用python进行音频解析(一) 语音识别系列︱paddlehub的开源语音识别模型测试(二) 语音识别系列︱paddlespeech的开源语音识别模型测试(…

1. JVM类加载机制

1. JVM类加载机制图解 下面我们来详细分析一下这个图解 1.1 其中loadClass()方法的调用的类加载的过程有如下几步 加载->验证->准备->解析->初始化->使用->卸载 加载:在硬盘上查找并通过IO读入字节码文件,当使用到这类的时候才会加…

[GYCTF2020]Ezsqli

先试一下万能密码 1 or 11# 发现有过滤,fuzz看一下过滤了什么 if,|,|| 没过滤,过滤了information_schema MySQL5.7新特性: 由于performance_schema过于复杂,所以mysql在5.7版本中新增了sys schemma&#x…

Docker实战之Redis主从集群搭建实战

实战 本实验将练习三主三从的Redis的docker集群快速搭建,实现集群的动态扩容和缩容,主从切换等常见实践项目。 拉取镜像 docker pull redis:6.0.8搭建主从 docker run -d --name redis-node-1 --net host --privilegedtrue -v /data/redis/share/red…

Allegro输出DXF文件操作指导

Allegro输出DXF文件操作指导 Allegro支持输出DXF文件,用于检查PCB的结构,具体操作如下 首先在PCB上打开需要的输出的层面,需要哪层开哪层,如下图所示 点击file-export 弹出一个对话框,输入文件名,格式选择Reversion14 ,单位选择mm,精度选择4 然后点击Edit 会出现一…

视频播放

QMediaPlayer不仅可以播放音频,还可以播放视频,不过要在屏幕上显示的话需要使用QVideoWidget和QGraphicsVideoItrm或自定义的类。QMovie 播放GIF文件QVideoWidget和QGraphicsVideoItrm都属于QMulimedia Widgets模块QVideoWidget 继承自QWiaget&#xff0…

Android Studio下载安装

一、下载 二、安装步骤 点击下载的安装包,选择地址的时候可以自定义,其他按照默认配置即可。 启动应用,开始配置 选择安装类型为标准安装: 选择主题 确认配置 同意协议 开始下载相关组件: 下载完成

SpringCloud - GateWay服务网关

文章目录一. Gateway概述1.Gateway是什么2. Gateway作用3. 微服务架构中网关的位置4. SpringCloud Gateway概念5. SpringCloud Gateway IO 模型二.Gateway的三大核心概念1. Route 路由2. Predicate 断言3. Filter 过滤4. 总结三.Spring Cloud Gateway工作流程四.服务搭建1. 创建…

Android 基础知识3-3(九妹)图怎么用呢?

1.本节引用: 可能有的一些疑问: 1.什么是.9图片? 答:图片后缀名前有.9的图片,如pic1.9.png这样的图片 2. .9图片能干嘛? 答: 在图片拉伸的时候特定的区域不会发生图片失真,而不失真的区域可以…

知识库指南4.0|AIGC Web3 元宇宙发展趋势的学习与实践指引

如何突破信息层面的认知,在 AIGC、Web3 与 元宇宙领域从 “围观” “看热闹” 到真正入门理解,并跟紧行业发展趋势,探索实践落地?(阅读原文领取限量优惠券)Mixlab小杜满足上述学习需求的知识库需要包含四要…

大数据(9f)Flink双流JOIN

文章目录概述开发环境使用状态列表实现 INNER JOIN(双流connect后CoProcessFunction)基于间隔的JOIN(Interval Join)基于窗口的JOIN(Window Join)概述 Flink双流JOIN可用算子或SQL实现,FlinkSQ…

图论基础学习笔记

图论1.简单图2.简单图的补图3.图的同构4.完全图5.偶图6.完全偶图1.简单图 简单图:无环无平行边的图。下图:左环右平行边 平凡图:G(1,0)G(1,0)G(1,0) 零图:G(p,0)G(p,0)G(p,0) 2.简单图的补图 补图:对于 G(V,E)G(V,…

继电器电路分析-继电器放电时间、反向冲击电压

继电器的应用,相信大家都知道,在电路中只要给它供电、断电也就可以工作了。 然而,它的应用细节,不知道大家有没注意 。下面谈谈我的观点。 01 现在流行的接法 如下图: 图中,继电器的线圈经过Q1作为开关…

《丞相好梦中杀人,我喜梦中听课》(1)密码学入门

前言 🍀作者简介:被吉师散养、喜欢前端、学过后端、练过CTF、玩过DOS、不喜欢java的不知名学生。 🍁个人主页:红中 🫒每日emo:等我把脸皮磨厚 🍂专栏地址:网安专栏 今天周日&#xf…

金融开放度指数-世界银行三位数字编码、ISO Alpha-3 Code等多指标数据

1、数据来源:http://web.pdx.edu/~ito/Chinn-Ito_website.htm 2、时间跨度:1970-2019 3、区域范围:全国 4、指标说明: Chinn-Ito指数(KAOPEN)是衡量一个国家资本账户开放程度的指标。 该指数最初是在Chinn和Ito (Journal of D…

并发基础(四):线程池

尺有所短,寸有所长;不忘初心,方得始终。 请关注公众号:星河之码 线程池技术是一种多线程处理形式,将任务添加到队列中,通过线程池中创建出来的现成执行这些任务,省去了创建线程和销毁线程的消耗…

let const var区别

文章目录写在前面1.var关键字1.1 没有块级作用域的概念,有全局作用域、函数作用域的概念1.2 存在变量提升1.3 全局作用域用var声明的变量会挂载到window对象上1.4 同一作用域中允许重复声明1.5 不初始化值默认为undefined2.let关键字2.1 有块级作用域的概念2.2 不存…

HTB靶机:RainyDay

目录介绍主机信息探测网站探测子域名爆破(BurpSuite)目录爆破爆破参数值分析 & 破解hash登录系统反弹shell端口转发内网穿透【很坑】配置socks代理内网扫描换用windows做内网渗透子域名信息收集爆破密钥位置爆破密钥内容JWT攻击进程监控Flag1 & 获取SSH私钥提权python沙…

UE4 通过按键切换不同的HUD

咱们在玩游戏的时候,通常会和界面进行各种各样的互动,而且会动都是在不同的界面上,所以需要在不同的界面上进行切换或者多个HUD重叠显示在一起。 首先创建两个HUD 2.重新定义一个PlayerController类 // Fill out your copyright notice…