使用 GDB 命令行调试 SylixOS 应用程序

使用 GDB 命令行调试 SylixOS 应用程序

一、简介

SylixOS 在内核中内置了一个标准的 GDB Server。使用 GDB 调试,只有两个步骤:

  1. 在 SylixOS 上启动 GDB Server;
  2. 使用交叉编译工具链中的 GDB 应用程序连接到 SylixOS 上的 GDB Server。

两个步骤完成后,便可以使用 GDB 进行调试了

:SylixOS 的 GDB 不支持 Watch 变量的功能,因为 Stub 不支持数据断点。

二、前提条件

1. 断开硬件调试工具

GDB 依靠 CPU 的陷阱机制来进行调试,需要能够捕获陷阱。

若有硬件调试工具的存在,因为硬件调试工具会也会捕获陷阱,因此使用 GDB 时,需要首先断开硬件调试工具的连接。

以 SPARC 架构处理器常用的 GRMON 硬件调试工具为例,使用如下的操作断开 GRMON 的连接:

  1. 启动 SylixOS;
  2. 在 GRMON 中执行 Control-C,并输入 “detach”,再按回车键。

2. 编译并上传待调试程序,及其所依赖的动态库

强烈建议使用 Debug 优化等级编译应用程序以及其依赖库,并上传到板卡上。

以下几点需要注意:

  1. 保证板卡上应用和库的版本,和 PC 上编译出来的版本一致
    原因是不同优化等级编译出来的程序文件是不一样的。不匹配的程序文件无法调试。

  2. 保证板卡上应用和库的优化等级,和 PC 上编译出来的版本一致
    不能板卡上是 Release,PC 上是 Debug。或者板卡上是 Debug,PC 上是 Release。
    原因是不同优化等级编译出来的程序文件是不一样的。不匹配的程序文件无法调试。

  3. 板卡上可以是 Strip 版本,但是 PC 机上必须有非 Strip 的版本
    例如板卡上可以是 Debug Strip 的二进制,PC 机器上必须有 Debug 的非 Strip 二进制。
    原因是 PC 上的 GDB 程序需要从二进制文件中读取调试符号信息。Strip 版本的二进制中去掉了这个调试信息,因此无法定位符号。
    而 Strip 版本和非 Strip 版本的二进制中,程序机器码的部分是一致的。因此可以上传 Strip 版本到板卡上来减小储存空间占用。

  4. 尽可能使用 Debug 优化等级编译应用和库
    Release 优化等级会有编译器优化的存在,因此实际编译出来的二进制和所编写的代码会有较大差异。
    在实际调试中,Release 版本的程序,往往只能定位到函数,而 Debug 版本可以精确定位到代码行。

3. 选用正确的工具链

请选用对应 CPU 架构的 GDB 程序,来进行调试。

注:SylixOS 工具链中的 GDB 工具一般位于 “RealEvo\compiler\工具链\bin\工具链-gdb.exe”

三、启动 SylixOS 上的 GDB Server

SylixOS 上的 GDB Server 通过 “debug” 命令启动,命令参数如下:

debug CONNECT_OPTIONS PROGRAM ARGUMENTS...
debug --attach CONNECT_OPTIONS PID

第一行用于启动程序调试。第二行用于附加到进程。

1. 启动程序调试

对于启动程序调试,命令行参数解释如下:

  • CONNECT_OPTIONS
    GDB 工具的连接方式。SylixOS 支持使用串口和网络进行调试。可选项有三个:
    ":1234":GDB 使用网络进行连接,1234 是指定的监听端口;
    "/dev/ttyS1":GDB 使用串口连接,/dev/ttyS1 是 GDB 连接所使用的串口;
    "terminal":GDB 使用当前 Shell 所在的串口连接。
  • PROGRAM
    待调试的应用程序路径,可以是绝对路径,或是相对路径。若使用相对路径,则需要以 “./” 开始。

  • ARGUMENTS...
    启动程序时传递的命令行参数。

2. 附加到进程

对于附加到进程调试,命令行参数解释如下:

  • CONNECT_OPTIONS
    GDB 工具的连接方式。SylixOS 支持使用串口和网络进行调试。可选项有三个:
    ":1234":GDB 使用网络进行连接,1234 是指定的监听端口;
    "/dev/ttyS1":GDB 使用串口连接,/dev/ttyS1 是 GDB 连接所使用的串口;
    "terminal":GDB 使用当前 Shell 所在的串口连接。

  • PID
    进程号,可以使用 "ps" 命令查看。

3. 注意事项

  1. 串口调试固定使用 115200 波特率,8 数据位,1 停止位,无校验的配置;
  2. 使用 “terminal” 串口调试时,在执行 "debug" 命令启动 GDB Server 后,SylixOS Shell 将变得不可用。
    同时,关闭 PC 上连接 SylixOS Shell 的串口终端软件,如 SecureCRT,释放 PC 上串口占用,GDB 才能够连接。
    要想再次使用 Shell,则必须在 GDB 中退出调试。
  3. PC 上的 GDB 工具,COM 口的号码仅支持 1 到 9。COM10(含)以上的串口无法使用,需要更改串口号到 1-9 之内。

4. 启动 GDB Server 示例

  • 使用网络调试  /apps/helloworld 应用,GDB Server 使用 1234 端口
    debug :1234 /apps/helloworld

  • 使用 SylixOS Shell 所在的串口,调试 /apps/helloworld 应用,并传递命令行参数 “-c 100”
    debug terminal /apps/helloworld -c 100

  • 使用串口 /dev/ttyS3,附加到进程 2
    debug --attach /dev/ttyS3 2

三、启动并配置 PC 上的 GDB 工具

GDB Server 启动后,需要启动 PC 上的 GDB 工具。

1. 启动 PC 上的 GDB 工具

以 SPARC 工具链的 GDB 举例,使用下面的命令启动 PC 上的 GDB 工具:

sparc-sylixos-elf-gdb.exe D:\workspace\helloworld\Debug\helloworld

命令行参数,是待调试的程序二进制文件路径。这里需要选择非 Strip 的版本。

2. 连接到 GDB Server

使用下面的命令连接到 SylixOS 上的 GDB Server:

(gdb) target remote 10.12.0.167:1234
(gdb) target remote COM3

第一行用于网络调试,10.12.0.167 是板卡 IP,1234 是 GDB Server 端口号。

第二行用于串口调试,COM3 是调试用的串口。(GDB 仅支持 COM1-COM9,COM10(含)以上,请更改串口号到 1-9

3. 设置库搜索路径

SylixOS 应用程序会有依赖的动态库,如至少依赖 libvpmpdm.so。若要在 GDB 中能够跟踪到动态库内的代码,则必须设置库搜索路径。

假设待调试的程序,依赖一个动态库 libabc.so,动态库的二进制文件位于 “D:\workspace\libabc\Debug\libabc.so”,使用下面的命令设置库搜索路径:

(gdb) set solib-search-path D:\workspace\sylixos-base\libsylixos\Debug;D:\workspace\libabc\Debug

set solib-search-path 命令如果多次执行,后设置的搜索路径,会覆盖先前设置的路径。因此若要设置多个路径,则应该像上面一样,将多个路径用英文分号 “;” 隔开。

如上面所示,设置了两个搜索路径:

  • D:\workspace\sylixos-base\libsylixos\Debug,该项是为了能够解析 libvpmpdm.so 中的符号;
  • D:\workspace\libabc\Debug,该项是为了能够解析 libabc.so 中的符号。

4. 开始调试

上述操作完成后,便可以使用 GDB 进行调试了。

三、常见问题(FAQ)

1. 在 GDB 命令行中,使用 b 命令在源文件打点,提示 “No source file”,或是函数打点,提示 “Function not defined”

这代表 PC 上的 GDB 工具并不知道待调试的程序。无法解析符号。

请检查 PC 上启动 GDB 程序的时候,命令行参数有没有传入非 Strip 版本的二进制文件路径。

2. 在 GDB 命令行中,使用 target remote 命令连接串口调试,提示 “No such file or directory”

  1. 请检查指定的 COM 口是否在 “Windows 设备管理器” 中存在;
  2. 请检查指定的 COM 口是否被其他软件占用,例如 SecureCRT 等串口终端软件;
  3. 请检查指定的 COM 口编号是否大于或等于 10。GDB 仅支持 COM1 - COM9,请更改 COM 口编号。

3. 在 GDB 命令行中,使用 info sharedlibrary 命令,看不到应用程序的依赖库

若动态库的链接,是在程序编译时使用 -l 指定,请检查程序编译时,是否链接了这个依赖库。

若动态库的链接,是调用 dlopen(),在程序运行时链接的,则程序必须在执行了 dlopen() 函数后,才能在 info sharedlibrary 中看到链接的库。

若程序还没有运行到 dlopen() 函数的位置,info sharedlibrary 中就看不到应用程序的依赖库。

4. 在 GDB 命令行中,使用 info sharedlibrary 命令,没有读取动态库符号(Syms Read 显示 No)

请检查库搜索路径是否正确配置。若要配置多个库搜索路径,请将多个路径合并成一个字符串,中间用英文分号隔开。

请不要多次执行 set solib-search-path 命令,因为后执行的命令会覆盖先前设置的路径,而不是追加一个新的搜索路径。

5. 在 GDB 命令行中,使用 watch 命令监测变量,变量的值变化后,GDB 没有停下来

SylixOS 的 GDB 不支持 Watch 变量的功能,因为 Stub 不支持数据断点。



    • Related Articles

    • GDB 调试时如何显示浮点寄存器

      Q:GDB 调试时如何显示浮点寄存器? SylixOS 的 IDE 对 64 位浮点寄存器的按 double 类型显示,如果是 float 类型的变量用 info all-reg 来查看:操作是需要选中 mips64-sylixos-elf-gdb 在 debugger console 里输入 info all-reg 或者 info float 如下图所示:                                                                     ...
    • SylixOS 应用程序开发

      SylixOS 应用程序开发 详见:RealEvo-IDE (SylixOS IDE)安装目录如:F:\ACOINFO\RealEvo\doc 中 doc 文件夹下的 《SylixOS应用开发手册》 公开链接:SylixOS 手册获取
    • SylixOS lite 版—基于 STM32F767 资源使用情况

      1、基本概念     代码段(text):顾名思义,代码存放的位置,在 STM32 中代码段一般存放于内置 FLASH 中; 已初始化数据段(data):已初始化数据段会分别体现在 FlASH 中和 RAM 中。因为是全局变量,运行过程中需要进行读写操作,因此占用一段 RAM 空间。又因为有初始值,其初始值需要占用 FlASH 空间。   未初始化的数据段(bss):bss 与 data 相同的地方时它也是全局变量,运行过程中需要进行读写操作,因此占用一段 RAM ...
    • qt5中链接使用.so动态库及相关函数

      Q:如何在qt5中链接使用.so动态库及相关函数 1. 编译生成动态库文件并上传至SylixOS文件系统内(需要上传至qt5的path目录内) 图1 编写并生成动态库工程 图2 上传动态库文件 qt5的path目录可env命令查看,见下图 图2 查看qt5默认库路径 2. 在qt工程pro文件内添加动态库相关本地配置(用于编译) 图4 增加动态库链接配置 3. 部署qt应用程序至SylixOS设备中 4. 运行测试 图5 程序运行测试
    • RealEvo-QtSylixOS 使用手册

      RealEvo-QtSylixOS 使用手册 详见:RealEvo-IDE (SylixOS IDE)安装目录如:F:\ACOINFO\RealEvo\doc 中 doc 文件夹下的 《RealEvo-QtSylixOS使用手册》 公开链接:SylixOS 手册获取