gdb+gdbserver调试详解

2023-05-16

1、gdb+gdbserver总体介绍

远程调试环境由宿主机GDB和目标机调试stub共同构成,两者通过串口或TCP连接。使用 GDB标准串行协议协同工作,实现对目标机上的系统内核和上层应用的监控和调试功能。调试stub是嵌入式系统中的一段代码,作为宿主机GDB和目标机调试程序间的一个媒介而存在。

就目前而言,嵌入式Linux系统中,主要有三种远程调试方法,分别适用于不同场合的调试工作:

  • 普通项目用ROM Monitor调试目标机程序
  • KGDB调试系统内核
  • gdbserver调试用户空间程序

这三种调试方法的区别主要在于,目标机远程调试stub 的存在形式的不同,而其设计思路和实现方法则是大致相同的。我们最常用的是调试应用程序就是采用gdb+gdbserver的方式进行调试。

在很多情况下,用户需要对一个应用程序进行反复调试,特别是复杂的程序。采用GDB方法调试,由于嵌入式系统资源有限性,一般不能直接在目标系统上进行调试,通常采用gdb+gdbserver的方式进行调试。

2、gdb下载、配置、编译和安装

2.1 gdb源代码下载

嵌入式Linux的GDB调试环境由主机和开发板两部分组成,主机端使用arm-linux-gdb,开发板端使用gdbserver(在主机上针对特定硬件平台编译成功后下载到目标机上)。

因为应用程序是在开发板上运行,而gdb调试是在主机端,所以需要采用远程调试(remote)的方法。

一般Linux发行版中都有一个可以运行的GDB,但开发人员不能直接使用该发行版中的GDB来做远程调试,而是要获取GDB的源代码包,针对arm 平台作一个简单配置,重新编译得到相应GDB。

当然,如果芯片商提供的交叉编译套件中已经包含了arm-linux-gdb,我们就不用重新编译gdb了,直接用它即可。不管怎么说,gdbserver还是需要用目标板的toolchain重新编译一遍,因为芯片商提供的交叉开发套件通常不包括gdbserver。

GDB的源代码包可以从GNU官网中下载。

2.2 配置编译及安装

假设源代码已经下载到/opt目录,解压:

cd /opt
tar xzvf /tmp/gdb-6.8.tar.gz

2.2.1 arm-linux-gdb编译

cd /opt
mkdir arm-gdb/
cd gdb-6.8
./configure --target=arm-linux --prefix=/opt/arm-gdb
make
make install

上面命令中,–target配置gdb的目标平台,–prefixp指定了编译结果的存放位置,也就是安装目录。

编译完后可以在/opt/arm-gdb/bin目录下找到可执行的arm-linux-gdb。拷贝arm-linux-gdb 到/usr/bin目录:

cd /opt/arm-gdb/bin/
cp arm-linux-gdb /usr/bin/
cd
arm-linux-gdb -v	//	查看是不是自己编译版本的gdb,或者使用绝对路径

2.2.2 gdbserver编译

下面把 gdbserver 移植到ARM平台。要点是指定目标平台的交叉编译链(gcc和ar)。我们创建一个临时的编译目录,以避免弄脏原代码。

cd gdb-6.8/gdb/gdbserver
./configure  --host=arm-linux
make

上面命令中,–host=arm-linux表示运行在ARM目标平台上,不需要配置—prefix,因为gdbserver不在主机端安装运行。

  • 可能的错误:提示缺少头文件

image-20210825235819312

通过执行搜索命令:grep “PTRACE_GETSIGINFO” * -nR,发现未定义的宏位于头文件位于<linux/ptrace.h>中,于是将其添加到linux-arm-low.c文件的头文件声明语句中。
image-20210825235929148

没有错误的话就在当前目录下生成了gdbserver可执行文件.

注意此时要更改其属性,否则可能会出现无法访问的情况,chmod 777 gdbserver将其更改为任何人都可以读写执行;

使用arm-linux-strip命令处理一下gdbserver,将多余的符号信息删除,可让elf文件更精简,通常在应用程序的最后发布时使用;

然后把它烧写到flash的根文件系统分区的/usr/bin(在此目录下,系统可以自动找到应用程序,否则必须到gdbserver所在目录下运行之),或通过nfs mount的方式都可以,只要保证gdbserver能在开发板上运行就行。

编译好gdbserver后,把它拷贝到目标板上的 /usr/bin 目录下,运行后,如果能显示帮助信息,则交叉编译成功,如:

gdbserver
Usage:  gdbserver [OPTIONS] COMM PROG [ARGS ...]
        gdbserver [OPTIONS] --attach COMM PID
        gdbserver [OPTIONS] --multi COMM

COMM may either be a tty device (for serial debugging), or 
HOST:PORT to listen for a TCP connection.

Options:
  --debug               Enable general debugging output.
  --remote-debug        Enable remote protocol debugging output.
  --version             Display version information and exit.
  --wrapper WRAPPER --  Run WRAPPER to start new programs.
  --once                Exit after the first connection has closed.

如果提示其它错误信息,如二进制文件无法执行,则表示编译不成功。注意我们交叉编出来的gdbserver是无法在开发主机上运行的。

3、命令行远程调试

  • 在目标板上,运行 gdbserver 命令启动测试程序的调试,并指定目标板的IP和监听端口号,如:
gdbserver 192.168.1.120:1234 ./test_file(要调试的程序)
Process test_file created; pid = 625
Listening on port 1234

我们看到gdbserver已经正常启动了,正在等待客户端程序gdb的连接。

  • 在开发主机上运行 arm-linux-gdb,指定gdbserver的IP和端口,连接上去,如:
arm-linux-gdb ./test_file
...
(gdb) target remote 192.168.1.120:1234
Remote debugging using 192.168.1.120:1234
0x400b57f0 in ?? ()

显示“0x400b57f0 in ?? ()”表示已经连接到远端的gdbserver并且开始调试了,此时目标板终端会显示“Remote debugging from host 192.168.1.201”,再次确认远程调试连接成功。接下来的调试方法与普通本机的gdb使用相同。

4、本地调试

  • 基本原理:在开发板上运行待调试程序,待其发生错误产生core dump文件(需要设置允许产生dump文件)后,将dump文件复制到主机上,利用gdb程序对其进行调试。

  • 步骤

    • 开发板上执行:

    • ulimite -c unlimited
      ./test_file						//应用出错,产生core dump文件
      cp ./core dir(主机上的待调试文件test_file所在目录)
      
    • 主机上执行:

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

gdb+gdbserver调试详解 的相关文章

  • 在 Linux 的 gdb 中启用 memleak 选项

    我试图查看哪个进程导致内存泄漏 并转储导致它的堆以查看问题所在 我应该在 gdb 中使用哪个命令来设置内存泄漏并检查堆 I tried gdb check leaks checkpoint can t find fork function
  • 如何在 gdb 中附加进程

    我有一个简单的 C 程序 它分叉一个进程 然后运行一个可执行文件 我想将子进程附加到 gdb 我在控制台中运行主程序并打开另一个控制台来查找子进程的 pid 然后使用以下命令启动 gdb gdb attach 12271 where 122
  • 用于 RHEL 的 gdb-multiarch

    我正在尝试寻找方法来运行gdb 多架构RHEL 中的命令 我已经安装了用于 ARM 处理的 QEMU 模拟器 我想安装GDB进行调试 我能够安装GDB 多体系结构在 Ubuntu 中运行命令成功 sudo apt get GDB multi
  • 如何在 gdb 中打印长字符串的完整值?

    我想在 GDB 中打印 C 字符串的完整长度 默认情况下它是缩写的 如何强制 GDB 打印整个字符串 set print elements 0 来自GDB手册 https sourceware org gdb onlinedocs gdb
  • gdb:“未加载符号表”

    尝试在 gdb 中添加断点时 我不断收到此错误消息 我使用这些命令来编译 gcc g main c utmpib2 c o main o and cc g main c utmpib2 c o main o and also g g mai
  • GDB可以杀死一个特定的线程吗?

    我正在运行一个应用程序 firefox 我想知道是否可以使用 GDB 附加到进程并杀死特定线程 有没有办法做到这一点 我知道此操作可能会使应用程序崩溃 EDIT 在此调试会话中 ps ax显示firefox pid是1328 gdb App
  • gdb 输入文件中的十六进制值

    我正在尝试通过使用 gdb 内的 run 我可以成功地溢出程序 但在将十六进制值附加到字符串时遇到问题 我尝试过引用 将 mem addr 的值转换为 ascii 以及各种转义尝试 但没有成功 输入文件示例 AAAA x42 在上面的示例中
  • 在运行时从应用程序读取调试信息

    除了调试之外 我还有一些关于调试符号以及可以用它们做什么的问题 我最感兴趣的是有关 GCC 的答案 但我也很高兴知道它在其他编译器 包括 MSVC 下的样子 首先 调试符号的常见格式 类型有哪些 它们与编译器和平台有何关系 GCC 和 Mi
  • 分离Gdb而不恢复劣质

    Gdb 与任何其他程序一样 并不完美 我时不时会遇到导致当前 Gdb 实例无法使用的错误 此时 如果我有一个调试会话 其中有很多有价值的状态 我希望能够在其上启动一个新的 Gdb 会话 也就是说 分离 退出 Gdb 并启动一个新的 Gdb
  • 在 gdb 中设置应用程序关联

    有没有一种简单的方法可以设置我正在调试的应用程序的亲和力 而无需将 gdb 锁定到同一核心 我问的原因是应用程序以实时优先级运行 并且需要在单核上运行 目前我使用这个命令行 taskset c 3 gdbserver 1234 app ou
  • 有什么方法可以判断我的 iPhone 应用程序在运行时是否在调试器下运行?

    如果我的错误处理代码在调试器下运行 我希望它的行为有所不同 具体来说 如果我在手机上运行 未连接到调试器并且断言失败 我想将错误发送到我的服务器 当我在gdb下时 我想闯入调试器 虽然我可以想象苹果将如何编写代码 但我找不到任何关于测试调试
  • GDB/bin/bash 无法在 Eclipse CDT 中执行应用程序?

    在 Mac OS X Mojave 上使用 Eclipse CDT 运行 GDB 时遇到困难 当我尝试调试项目时 GDB 表现得很混乱 我能够调试几次 但随后它在下一个调试会话开始时开始停止 并显示消息 配置 GDB 可执行文件是 User
  • Eclipse 调试模式下的 GDB 找不到 stdlib/rand.c

    我试图让 gdb 在 ubuntu 上与 eclipse cdt 一起运行 以开始调试一些简单的程序 所以我做了我认为必要的步骤来让它运行 1 创建可执行项目 2 Compile 3 Run 4 创建文件 gdbinit 并将其放在主项目文
  • gdb 中的 是什么意思?

    gdb n 134 a b c 0xdeadbeef uint32 t length initval gdb n gdb p a 30
  • gdb 不会从外部架构读取核心文件

    我正在尝试在 Linux 桌面上读取 ARM 核心文件 但似乎无法找出我的核心文件 有什么方法可以指示 gdb 我的核心文件是什么类型吗 file daemon daemon ELF 32 bit LSB executable ARM ve
  • 如何模拟ARM处理器运行环境并加载Linux内核模块?

    我尝试加载我的vmlinux into gdb并使用 ARM 内核模拟器 但我不明白为什么我会得到Undefined target command sim 这是外壳输出 arm eabi gdb vmlinux GNU gdb GDB 7
  • gdb查找行号的内存地址

    假设我已将 gdb 附加到一个进程 并且在其内存布局中有一个文件和行号 我想要其内存地址 如何获取文件x中第n行的内存地址 这是在 Linux x86 上 gdb info line test c 56 Line 56 of test c
  • 在 Linux 上,在 Eclipse CDT 中使用 gdb 调试 C++ 应用程序,如何向 stdin 输入内容?

    在 Linux 上 我尝试在 Eclipse CDT 中使用 gdb 调试 C 应用程序 例如应用程序applic exe接受一些命令行参数arg1 and arg2它期望一些数据stdin 比如说 取自文件input txt 通常 要在控
  • 评估 gdb 中的变量/函数

    我有以下代码 char seg mmap 0 printf seg x n seg 该程序打印seg b7ffd000 而在 gdb 中 对于相同的执行 当使用p x seg 它打印 2 0x0 我在这里很困惑 这不是同一个var吗seg
  • 使用 GDB 远程调试 MPI

    我正在尝试从 pi 的远程访问组中调试我使用 MPI 编写的代码 我无法直接访问 Pi 以便能够使用 GUI 来调试代码 我已经尝试过使用屏幕显示的内容question https stackoverflow com questions 3

随机推荐

  • 数据类型对应字节数(32位,64位 int 占字节数)

    一 程序运行平台 不同的平台上对不同数据类型分配的字节数是不同的 个人对平台的理解是CPU 43 OS 43 Compiler xff0c 是因为 xff1a 1 64位机器也可以装32位系统 xff08 x64装XP xff09 xff1
  • 【JAVA】03版本excle导出数据

    03版本excle导出list lt Object gt 数据 前端页面请求 使用流返回 public static String exportExcel HttpServletRequest request HttpServletResp
  • C++码农要读的经典

    刚大四 xff0c 还在忙着找工作 xff0c 读过的书不是很多 xff0c 还有一些好书在读 xff0c 还有一些书将来必读 C语言程序设计 谭浩强版本 这个版本一致被人说误导子弟 xff0c 当然还有很多人推崇 我觉得这本书不是什么好书
  • 进阶训练赛(四)题解

    A 交换a b的值 直接输出b a void solve int a b cin gt gt a gt gt b cout lt lt b lt lt 34 34 lt lt a B 素数回文数的个数 从11 n遍历一遍找出满足即是回文数又
  • AtCoder Beginner Contest 285(A~E)

    A Edge Checker 2 在满二叉树中 xff0c 判断两个两个点是否是父子关系 void solve int a b cin gt gt a gt gt b if b 61 61 2 a b 61 61 2 a 43 1 puts
  • 进阶训练赛(十二)

    目录 问题 A 符文宗师的魔方阵 问题 B APP的成绩单 问题 C 6 1 4 1 最大的节点 问题 D 6 2 2 1 油田 问题 E 6 3 2 1 电话网络 问题 F 7 1 4 1 重型运输 问题 G 打怪兽version 3 问
  • 进阶训练赛(二十)

    目录 问题 A 计算矩阵边缘元素之和 问题 B 图像旋转 问题 C 最长最短单词 问题 D 输出亲朋字符串 问题 E 蓝桥杯2022初赛 李白打酒加强版 1 朴素版dfs 2 dfs 43 记忆化搜索 43 剪枝 问题 F 蓝桥杯2022初
  • 用EditPlus配置MASM汇编

    最开始写汇编程序 xff0c 是打开一个记事本就写 但是记事本不是专门的程序编辑器 xff0c 格式不好控制 xff0c 更容易写错程序 于是想到 xff0c 能有一个简单的文本编辑器 xff0c 能控制好ASM的格式 xff0c 有关键字
  • Codeforces Round #852(A~D)

    比赛原地址 xff1a Dashboard Codeforces Round 852 Div 2 Codeforces A Yet Another Promotion 买a种商品会买m送1 xff0c b种则不会 那么当a种商品单价小于等于
  • 动态联编和静态联编

    基本概念 1 静态联编 xff08 早联编 xff09 xff1a 在程序被编译时进行联编 程序执行快 xff0c 但灵活性较小 2 动态联编 xff08 晚联编 xff0c 滞后联编 xff09 xff1a 编译时无法确定要调用的函数 x
  • 函数重载常见问题

    问题一 cannot bind non const lvalue reference of type 39 Complex amp 39 to an rvalue of type 39 Complex 39 该错误提示出现的原因是 xff0
  • 输入输出流

    iomanip的控制符 resetiosflags long f 关闭由参数f指定的格式标志 xff0c 用于输入输出 setprecision int n 设置数据小数位数 xff0c 缺省时为6 xff0c 用于输入输出 setw in
  • 解决TIME_WAIT过多造成的问题

    看到TIME WAIT状态是在tcp断开链接时产生的 xff0c 因为TCP连接是双向的 xff0c 所以在关闭连接的时候 xff0c 两个方向各自都需要关闭 先发FIN包的一方执行的是主动关闭 xff1b 后发FIN包的一方执行的是被动关
  • linux后台开发常用调试工具

    一 编译阶段 nm 获取二进制文件包含的符号信息 strings 获取二进制文件包含的字符串常量 strip 去除二进制文件包含的符号 readelf 显示目标文件详细信息 objdump 尽可能反汇编出源代码 addr2line 根据地址
  • 将Ubuntu 8.04 Live CD Desktop放在硬盘上启动

    将Ubuntu 8 04 Live CD Desktop放在硬盘上启动 最近下了一个Ubuntu 8 04 Live CD Desktop 镜象文件 xff0c 放在VMWere虚拟机里试用了一下 xff0c 觉的还不错 于是更想把它放在硬
  • 如何在Android项目中使用Kotlin

    本文是作者阅读How to Use Kotlin in Your Android Projects xff0c 按照文章实现了一遍 xff0c 并将实现过程中碰到的坑总结出来的文章 简介 Kotlin是由JetBrains设计的开源编程语言
  • Android中使用log4j、android-logging-log4j-1.0

    Android中使用log4j android logging log4j 1 0 3 1 下载相关资源包 资源包下载路径 xff1a log4j xff1a http logging apache org log4j 1 2 downlo
  • 8G内存机器JVM设置模版

    Xms4096m Xmx4096m Xmn3072m XX MetaspaceSize 61 256m XX MaxMetaspaceSize 61 256m XX 43 UseParNewGC XX 43 UseConcMarkSweep
  • Java文件名及其他命名规则

    http bbs csdn net topics 70157841 关于JAVA 源文件命名的问题 Java文件命名 xff1a java程序是由类组成的 xff1b java应用程序必须有一个包含main方法的public类 xff0c
  • gdb+gdbserver调试详解

    1 gdb 43 gdbserver总体介绍 远程调试环境由宿主机GDB和目标机调试stub共同构成 xff0c 两者通过串口或TCP连接 使用 GDB标准串行协议协同工作 xff0c 实现对目标机上的系统内核和上层应用的监控和调试功能 调