gdb+gdbserver调试详解

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
      
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Leon_George

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值