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


    环境:
    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  //安装
    
    • 1
    • 2
    • 3
    • 4
    • 5

    不出意外的话在~/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
    
    • 1

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

    ls /dev/tty*
    
    • 1

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

    sudo chmod 777 ttyUSB0
    
    • 1

    设置minicom

    sudo minicom -s
    
    • 1

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

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

    查看在开发板中模块信息

    cat /proc/modules
    
    • 1

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

    echo g > /proc/sysrq-trigger
    
    • 1

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

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

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

    yu@yu$ arm-linux-gnueabihf-gdb
    
    • 1

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

    (gdb) set serial baud 115200
    
    • 1

    连接至串口与kgdb通信

    (gdb) target remote /dev/ttyUSB0
    
    • 1

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

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

    这些值的计算方式如下:

    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
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

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

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

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

    按之前的步骤启动gdbserver

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

    • 串口无法使用, 无法查看打印信息
      此时已能正常调试, 但是串口被kgdb占用, 同时内核也在同一个串口输出数据, 导致了串口持续乱码
      解决这个问题要用到工具叫 agent-proxy
      下载地址 : https://git.kernel.org/cgit/utils/kernel/kgdb/agent-proxy.git/

    原理就是 将原来的串口 映射成两个, 让kgdb的输出和内核的输出走不同的映射串口.

    在开发板操作echo g > /proc/sysrq-trigger命令进入等待连接状态之后

    我们要将minicom的终端关闭.

    输入命令 agent-proxy 5550^5551 0 /dev/ttyUSB0,115200
    这个终端不能关闭
    将/dev/ttyUSB0 映射5550 和 5551

    新开启一个终端, 输入命令telnet localhost 5550 这个终端就进入了开发板

    Ubuntu在导入文件头信息 add-symbol-file之后 , 输入命令target remote localhost:5551去连接另一个映射

    只要终端的gdb正常运行之后, 开发板的打印信息也不再乱码了

    在这里插入图片描述

  • 相关阅读:
    某学生宿舍楼设计
    RSLO:自监督激光雷达里程计(实时+高精度,ICRA2022)
    EF7创建模型继承映射篇
    [2023.09.14]: Rust的条件编译
    Bitxhub跨链平台
    2024MathorCup A题 赛后思路代码分享(分赛区一等奖)移动通信网络中 PCI 规划问题
    使用Robot Framework实现多平台自动化测试
    如何配置和使用自己的私有 Docker Registry
    Ubuntu 和 Windows 文件互传
    tensorboard attempted to bind to port 6006,but it was already in use
  • 原文地址:https://blog.csdn.net/qq_40684669/article/details/128051645