gdb+gdbserver远程调试环境搭建及调试

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

目前而言,嵌入式Linux系统中,主要有三种远程调试方法,分别适用于不同场合的调试工作:用ROM Monitor调试目标机程序、用KGDB调试系统内核和用gdbserver调试用户空间程序。这三种调试方法的区别主要在于,目标机远程调试stub 的存在形式的不同,而其设计思路和实现方法则是大致相同的。而我们最常用的是调试应用程序,就是采用gdb+gdbserver的方式进行调试。

本文针对博主近期搭建gdb+gdbserver远程调试环境的一个总结。gdbserver在目标机中运行,gdb则在宿主机上运行。

1、交叉编译器

博主使用的交叉编译器信息如下:(如未安装交叉编译器,需先安装编译器)

如下介绍安装交叉编译工具链,如果已安装工具链则略过。

(1) 下载交叉编译工具链

官网下载:Downloads | GNU-A Downloads – Arm Developer

第三方资源网下载:广州友善电子计算机科技有限公司 (friendlyelec.com.cn)

(2)安装交叉编译工具链

如果是window系统下载的,则需要将下载的压缩包放进Linux内:(根据需求选择工具链版本下载)

执行解压命令,解压arm-linux-gcc-4.4.3-20100728.tar.gz到当前目录下

tar -xvzf arm-linux-gcc-4.4.3-20100728.tar.gz

你也可以通过-C指令解压到指定目录下,例如:

tar -xvzf arm-linux-gcc-4.4.3-20100728.tar.gz -C /home/tanglg/arm-linux

解压完成后,可以在/home/tanglg/my_tmp_file/opt/FriendlyARM/toolschain/4.4.3目录下看到一个bin目录,里面包含了各种编译工具文。

我们习惯把工具链安装在/usr/local目录下,故我们在/usr/local/目录下创建一个目录存放交叉工具链的文件:

sudo mkdir /usr/local/arm

将/home/tanglg/my_tmp_file/opt/FriendlyARM/toolschain/目录下的4.4.3目录拷贝到刚新建的/usr/local/arm目录下:

 sudo cp ./4.4.3/ /usr/local/arm/ -r

 设置环境变量PATH,使其可以在任意的目录下都可以访问到交叉工具链。

vim /etc/profile

export PATH=$PATH:/usr/local/arm/4.4.3/bin   //将其加在文件末尾处

 输入如下命令立即使新的环境变量生效。

source /etc/profile

输入如下命令,如果显示内容含有/usr/local/arm/4.4.3/bin则表示已经添加成功。

echo $PATH

 输入命令测试检查arm-linux-gcc -v 是否安装完成。显示了版本号即表示安装成功。

如果arm-linux-gcc -v命令后没有输出工具链的版本号,反而是输出No such file or directory 的错误提示,则说明你下载的工具链是32位的,而你的Linux系统是64位的。

如果需要让其32位的应用程序兼容到64位的系统中,则只需要依次安装如下两个依赖库即可:

基础依赖库:

        sudo yum install glibc.i686 -y

libstdc++依赖库:

        sudo yum install libstdc++.i686 -y

至此,交叉工具链安装结束咯,下面就可以大展伸手去安装gdb和gdbserver啦!!! 

2、GDB源码包下载

对于嵌入式软件开发调试工具没有现成的,且嵌入式系统比较繁杂,gdbserver需要根据目标系统单独编译。gdb的源码包下载地址为:Index of /gnu/gdb

3、安装arm-linux-gdb

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

(1)解压源码包

tar -zxvf gdb-7.12.tar.gz  

 (2)生成Makefile

cd gdb-7.12/                                                                                  //进入源码目录

mkdir /usr/local/arm-gdb                                                             //创建一个安装目录

./configure --target=arm-linux --prefix=/usr/local/arm-gdb      //执行配置文件

注意:

--target: 指定编译环境,一般设置为交叉编译器前缀。

--prefix:指定安装路径,可自己任意指定合法路径

 (3)编译与安装

make                 //编译

make install      //安装

安装结束后会在你指定的安装目录下生成三个文件夹,里面包含可执行文件、头文件、动态库文件等,如下图所示:

(4)填加到环境变量

将生成的bin文件添加到环境变量中:

vim /etc/profile

export PATH=$PATH:/usr/local/arm-gdb/bin         //添加在文件末尾

source /etc/profile            //生效环境变量

echo $PATH                      //检查环境变量

注意:

(1)你也可以放在其它环境变量下,例如:/usr/local/bin、/usr/bin等

(2)生成的文件可删除不需要用到的,比如,此处只需要使用arm-linu-gdb可执行文件,则你可只需将此文件添加到环境变量即可,其他文件可直接删除。

4、安装gdbserver

 (1)生成Makefile

cd gdb-7.12/gdb/gdbserver/                                                        //进入源码目录

./configure --target=arm-linux-gnueabi --host=arm-linux        //执行配置文件    

注意:

--target:指定目标平台,博主的目标平台为ARM。

--host:   指定宿主机运行的是arm-linux-gdb

(2)编译与安装

make

编译gdbserver不需要执行make install命令,因为make之后在当前目录下会生成可执行程序gdbserver。

(3)拷贝到目标平台

拷贝之前先更改gdbserver读写权限:chmod 777 gdbserver 

将可执行文件gdbserver拷贝到目标平台的/usr/local/bin/目录下。

至此,远程调试环境已经搭建完成。

5、gdb+gdbserver调试流程

(1)检查网络是否正常

打开MobaXterm登入虚拟机和开发板的Linux系统,执行如下操作:

开发板ping主机

开发板ping虚拟机

主机ping开发板

虚拟机ping开发板

保证相互之间均可以ping通。

注意:主机ip、开发板ip和虚拟机ip地址设置在同一个网段内。

(2)编辑和编译测试代码

1)测试代码

#include <iostream>
#include <string>

using namespace std;

void fun(int &a, int &b)
{
     a = b = 10;
}

void my_fun(int &a, int &b)
{

    a > b ? (a += b) : (b -= a);

    fun(a, b);
 }
 
int main()
{

    int a = 13, b = 16;

    my_fun(a,b);

    cout<< "a = " << a << endl;
    cout<< "b = " << b << endl;

    return(0);
}                        

2)编译代码

-g : 设置带调试信息的程序

3)设置读写权限

修改可执行二进制文件test读写权限:chmod 777 test

4)下载文件到开发板

下载可执行二进制文件到开发板的工作目录下。(自己指定一个合法的工作目录)

文件下载方法:在Linux系统编译好的可执行文件先下载到window,然后再从window下载到开发板。(下载操作方式众多,选择自己习惯的就行)

(3)启动调试环境

宿主机IP:192.168.xxx.xxx
开发板IP:192.168.xxx.xxx

1)开发板上运行gdbserver

gdbserver 192.168.xxx.xxx:2001 test

其中 192.168.xxx.xxx 是宿主机的地址,2001是调试端口(该值建议设在2000以上),test是需要调试的可执行程序。gdbserver启动之后打印出下面内容:

2)执行gdbserver脚本

以上操作也可以通过自己编写一个shell脚本去执行,如下:

 该脚本执行时需要输入一个参数,即需要调试的可执行文件名。执行时如果没有输入参数会有一个提示信息打印。执行命令如下:

./gdbserver test      //这样就不需要每次都输入宿主机IP和端口号等信息了,直接执行脚本就搞定。

3)宿主机上运行arm-linux-gdb

arm-linux-gdb test

启动之后会打印如下信息:

最后一行(gdb) 表示arm-linux-gdb在等待输入指令,现在需要输入指令来连接gdbserver,如下所示:

(gdb) target remote 192.168.xxx.xxx:2001

其中 192.168.xxx.xxx 是开发板的IP地址,2001是调试端口(必须与gdbserver端保持一致)

4).gdbinit脚本

每次启动gdb时都要在gdb命令行上手动输入指令,去连接目标机,操作上显得及其麻烦。而使用.gdbinit脚本则可以轻松解决此事。

gdb在启动的时候,会在你的当前工作目录下查找 ".gdbinit" 这个文件,并把它的内容作为gdb命令进行解释,所以如果我把脚本命名为".gdbinit",这样在启动的时候就会处理一些你常用的命令。

第一步:在”~"目录下添加一个.gdbinit, 默认gdb初始化时会调用这个文件。

第二步:编辑该.gdbinit, 在文件中加上 set auto-load safe-path xxx

set auto-load safe-path  /home/tanglg/workspace_tlg/
指定了/home/tanglg/workspace_tlg/路径为gdb的安全加载路径,即后续你可在该路径下的任何子路径下均可加载.gdbinit文件并解释文件内容。

如果不在“~”目录下指定一个安全路径的话,会在使用.gdbinit时,报如下错误:

File "/home/tanglg/workspace_tlg/myapp/test/.gdbinit" auto-loading has been declined by your `auto-load safe-path' set to "$debugdir:$datadir/auto-load".

第三步:在/home/tanglg/workspace_tlg/myapp/test/(即你要Debug的目录)下,同样添加一个.gdbinit

第四步:编辑该.gdbinit,添加你需要的一些指令,例如:

当然在.gdbinit文件中你还可以添加别的指令。

.gdbinit编写好并保存后,你就可以直接输入arm-linux-gdb test 开始gdb调试了,中途就不用再次主动去连接目标机的gdbserver了。如果你需要更改目标机的IP和端口号,只需修改.gdbinit文件。

至此开发板和虚拟机(宿主机)远程连接起来了。

(4)开始调试

建立链接后,就可以进行调试了。调试在宿主机端,跟gdb调试方法相同。注意的是要用“c”来执行命令,不能用“r”。因为程序已经在Target Board上面由gdbserver启动了,结果输出是在Target Board端,用SSH(或超级终端)查看。

按”c“全速运行后,在目标端查看运行结果:

至此,远程调试环境和调试步骤结束。

(5)调试常用命令

c      -->    continue的缩写,作用是程序继续往下执行。

l      -->     list的缩写,作用是查看程序代码,按回车可显示剩余未显示的代码。

b    -->      break的缩写,作用是设置断点。如:b xxx.cpp:4表示在xxx.cpp的4行设置断点。

b i  -->      break info的缩写,作用是查看所有断点信息。

q    -->     quit的缩写,作用是退出调试  

6、安装调试中遇到的问题

(1)‘__NR_sigreturn’ was not declared in this scope

安装交叉编译器gdbserver 可能报该错:

解决方案:

 //在这个linux-arm-low.c文件添加如下内容:

#ifndef __NR_sigreturn

#include <asm/unistd.h>

#endif

如果仍然不行,则再加上#define __NR_sigreturn 0

(2)Remote 'g' packet reply is too long: 40100100dc890000acfdffbe问题

在gdb调试过程中可能出现如下图所示错误:

解决方案:

修改gdb/remote.c文件,屏蔽process_g_packet函数中的下列两行:

if (buf_len > 2 * rsa->sizeof_g_packet)
     error (_(“Remote ‘g’ packet reply is too long: %s”), rs->buf);

在其后添加:

if (buf_len > 2 * rsa->sizeof_g_packet) {
      rsa->sizeof_g_packet = buf_len ;
      for (i = 0; i < gdbarch_num_regs (gdbarch); i++)
      {
         if (rsa->regs[i].pnum == -1)
         continue;

         if (rsa->regs[i].offset >= rsa->sizeof_g_packet)
         rsa->regs[i].in_g_packet = 0;
         else
         rsa->regs[i].in_g_packet = 1;
      }
   }

(3)arm-linux-gdb加载目标系统库出错

arm-linux-gdb在调试的时候会加载目标系统的库文件,如果出错时便无法调试,如下图所示:

解决方案:

可通过指令[set solib-search-path+库文件路径]来手动加载目标系统库文件,如下为我的设置:

set solib-search-path /usr/local/arm/4.4.3/arm-none-linux-gnueabi/lib/

(4)Reading symbols from target:/lib/ld-linux.so.3...(no debugging symbols found)...done.问题

网上说错误的原因是:代码编译时,未添加-g选项。

亲测发现,加了-g选项且选项加载-o之前编译,仍会有这个问题。但目前来看不影响调试,也恳请知道该问题原因的大佬能给予留言解答!!!

(5)“libc.so.6: version `GLIBC_2.14‘ not found“问题

此类错误一般是由于glibc库的版本过低或缺少相关版本造成,需要进行升级补充。

解决方案:

可以将自己安装的编译器中的该文件拷贝到开发板对应得路径下,去替换低版本得包就行。

比如我安装得编译器下对应该文件如下:

 libc.so.6文件是由libc-2.9.so创建的软连接。

故我们把里,在通过该文件在开发板创建一个新的软连接。具体如下:

1)方法一:将libc-2.9.so文件拷贝到开发板的"/lib"目录下

      方法二:将libc.so.6文件压缩后,再从目标平台解压,此时软连接就会被成功拷贝。

2)将原来的libc.so.6文件备份。 (千万别直接将原来的文件名改掉,否则会出大问题,详情见后文。)

3)ln -s  libc-2.9.so libc.so.6    //创建软连接

注意:以上操作有个问题,你把原有的libc.so.6文件更改为其它名字后,你就无法使用ls,mv等shell命令了,会报如下错误:

因此就无法使用ln命令,也无法在重新更改libc.so.6文件名了。因此在此处你要么在宿主机上编译一个libc.so.6 文件进来,要么就是利用SSH的图形界面,先创建libc.so.6 软连接,但连接的名字不能为libc.so.6 ,而是要与原文件有所区别,否则会有冲突,利用图形界面,将原来的libc.so.6 文件名改掉,再把前面新建的libc.so.6xxx 软连接改名为libc.so.6 即可。

在图形界面修改文件名称:

最终效果如下:

7、参考博客 

gdb+gdbserver远程调试技术(一)——调试环境搭建_Ahren.zhao的博客-CSDN博客
gdb+gdbserver安装及调试(总结) - 飞速网 (feisuxs.com)

‘__NR_sigreturn’ was not declared in this scope_蜜汁辣酱^_^的博客-CSDN博客

“libc.so.6: version `GLIBC_2.14‘ not found“类错误处理-CSDN博客

Gdbinit 无法调用的问题_auto-loading has been declined by your `auto-load _申小白的博客-CSDN博客

结束语】因技术能力有限,文章如有不妥之处,恳请各位技术大佬留言指正!

  • 3
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
### 回答1: gdbgdbserver远程调试技术的意义在于提供了一种方便有效的方式来调试运行在远程目标设备上的程序。这对于嵌入式系统或远程服务器等分布式系统的开发和调试非常有用。 首先,gdbgdbserver远程调试技术允许开发人员在不在本地环境下的目标设备上进行调试。这意味着开发人员可以通过网络连接到远程设备,并使用本地的gdb客户端来远程控制和调试目标设备上的程序。这样,不再需要将全部的代码和调试环境放在开发人员的本地机器上,大大节省了开发人员的时间和资源。 其次,远程调试技术提供了实时调试的能力。开发人员可以监控目标设备上的程序执行过程,并在运行时观察程序的状态和变量的值。这对于发现和解决运行时错误和异常非常重要。通过远程调试,开发人员可以更直接地了解程序在实际环境下的行为,从而更有效地修复问题。 此外,远程调试技术还提供了一个更加安全且可靠的调试方法。使用gdbgdbserver进行远程调试,可以避免将敏感的代码或数据复制到本地环境中,减少了潜在的安全风险。同时,由于远程调试是通过网络进行的,即使目标设备处于远程位置,也能够进行调试,减少了物理上接触设备的需求,提高了效率。 总而言之,gdbgdbserver远程调试技术的意义在于提供了一种方便、实时、安全的方法来远程控制和调试目标设备上的程序,使开发人员能够更有效地进行嵌入式系统和分布式系统的开发和调试工作。 ### 回答2: gdb gdbserver远程调试技术是一种用于在线调试嵌入式系统的工具。它的意义在于提供了一种便捷和高效的方式来调试远程的嵌入式设备。 首先,gdb gdbserver远程调试技术可以节省时间和资源。在传统的调试方式中,如果想要调试远程的嵌入式设备,通常需要将设备连接到开发服务器并使用串口进行调试。这种方式不仅繁琐,还占用了宝贵的硬件资源。而gdb gdbserver远程调试技术可以直接在目标设备上运行gdbserver,并通过网络连接到开发服务器上的gdb,使得调试变得更加方便快捷。 其次,gdb gdbserver远程调试技术可以提高团队协作效率。在实际的嵌入式系统项目中,通常会有多个开发人员同时开展工作。使用gdb gdbserver远程调试技术,不同的开发人员可以同时连接到同一个目标设备上进行调试,而不会相互干扰。这样可以提高团队成员之间的协作效率,加快问题解决和软件开发的速度。 此外,gdb gdbserver远程调试技术还提供了更灵活的调试方式。通过gdb gdbserver的支持,开发人员可以在目标设备上进行远程程序的调试,包括断点设置、变量查看、程序运行控制等。这种方式可以更加直观地观察到程序的实际执行情况,帮助开发人员更好地理解和解决问题。 总之,gdb gdbserver远程调试技术的意义在于提供了一种便捷、高效和灵活的嵌入式系统调试方式,节省了时间和资源,提高了团队协作效率,同时也方便开发人员更好地理解和解决问题。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值