记一次成功搭建arm-gdb调试环境

目录

一、 目的 1

二、 准备工作 1

1)安装gdb 1

2)编译选项-g 2

三、 调试 2

1)配置core 2

2)拷贝core 2

3)调试core 3

四、 问题 4

1)挂载问题 4

2)拷贝core问题 4

 

 

 

  • 目的

前段时间换了一个工作,也是做嵌入式开发的,但工作后发现其开发环境实在是太简陋了,一是没有统一的服务器进行编译,二是没有gdb调试。在做项目过程中如果出现segmentation fault 错误,就很难排查,如果是添加/修改了少量代码,那查起来也相对容易些,但若是几个人同时开发,在最后合并代码编译出来的程序出现这种问题,那就很麻烦了。因为没有gdb调试,所以在出现问题时,只能靠加打印来进行排查(时间花费就多了很多,真不知道他们一直以来是怎么开发的)。终于在做完一个项目后,空出了一段时间来搞这个arm下的gdb调试环境(最后写出了一篇doc文档,但他们好像也没有拿去分享,尴尬了^_^)。

  • 准备工作

1)安装gdb

因为编译程序用的是虚拟机,然而虚拟机上没有安装对应的gdb(如果有安装的,这一步可以忽略),开发板程序用的交叉编译器为:arm-linux-gnueabihf,要调试程序则需要安装对应的arm-linux-gnueabihf-gdb,步骤如下:

  1. 下载源码:wget http://ftp.gnu.org/gnu/gdb/gdb-7.8.1.tar.gz
  2. tar xzvf gdb-7.8.1.tar.gz
  3. cd gdb-7.8.1; ./configure --target=arm-linux-gnueabihf --prefix=/usr/bin/arm-linux-gnueabihf-gdb
  4. make; sudo make install
  5. sudo vim /etc/profile, 添加:export PATH=$PATH:/usr/bin/arm-linux-gnueabihf-gdb/bin

备注:--target=arm-linux-gnueabihf 指定平台(需要跟当前已经安装gcc,g++一样,如虚拟机已经安装的arm-linux-gnueabihf-g++);--prefix 指定生成的目录,可自行创建,最后将gdb添加到系统搜索路径下:PATH=$PATH:/usr/bin/arm-linux-gnueabihf-gdb/bin

2)编译选项-g

因为编译用的是虚拟机里的Eclipse集成开发环境,所以需要添加-g编译选项,如下图所示:

 

  • 调试

1)配置core

若要系统在程序发生Segmentation fault时生成core 文件,需要配置一下,设置生成core文件的大小,若如下图所示,在登录开发板后,输入命令:ulimit –c 进行查看,系统默认不生成core文件。

配置成:ulimit –c unlimited,设置生成的core文件大小不限制。

 

2)拷贝core

在程序出现Segmentation fault时,生成了core文件,如下图:

 

可看到/bin 目录下,已经有了core文件。将core拷贝出来即可进行调试,拷贝方法:自行实现一个TCP客户端和服务端,将服务端放到开发板上运行,用客户端去请求下载文件。具体操作在文末介绍。

3)调试core

在下载了core文件后,就可以结合debugt程序进行调试了,命令:arm-linux-gnueabihf-gdb xxx core,案例1:数组越界导致的死机

 

从打印的调用栈可以看到程序死在HiLink_TopicNameManager.cpp:122行,初始化函数publishTopicInit,查看代码后发现,新定义的枚举类型加在了最后(代码做了简化处理),如:

而定义数组的大小只有DOWNLOAD_MAX_COUNT,如果访问array[DOWNLOAD_XXX]必将导致数组越界造成死机。

 

  • 问题

1)挂载问题

若是能将一个目录挂载到IPBOX上,再将生成的core文件指定到挂载目录里,这样就不用从开发板上拷贝core文件。

命令: mount -t nfs 192.168.2.115:/home/daikin/nfsv4 /home -o rw,nolock,tcp

将虚拟机上的nfsv4目录挂载到开发板的home目录下,mount命令列出所有的挂载分区,可以看到nfsv4已经成功挂载到/home目录下。但出现了一个问题:

挂载后的分区没有写权限。如果有写权限就可以指定core文件的生成路径,可以用 echo "/home/core-%e-%p" > /proc/sys/kernel/core_pattern,指定在/home目录下生成带程序名(%e)和进程号(%p)的core文件。试了网上搜索的方法,没有解决,有兴趣的同学可研究一下,若解决了请告知我一下。

2)拷贝core问题

因挂载方法行不通,就只能自行实现一个简单的TCP客户端和服务端。注意:编译服务端程序时要用: arm-linux-gnueabihf-g++,用wget 方法,获取server:

server即为tcp服务端,用./server ip port,即IPBOX ip地址和端口号。

在虚拟机上用客户端连接服务端进行文件下载即可,如:

./client_get 192.168.2.111:9898/core,命令固定格式为:./client_get 服务端ip:端口号/文件名

但是遇到了一个问题:

在下载core文件过程中,在下载到100M或200M左右,server程序就被kill掉,打印如下:

打印显示没有可用缓存,系统把server程序kill掉了。这样下载的core文件是不完整的,但如果用gdb调试时也能打印出完整的堆栈信息也可以不用再关心。 

解决办法:下载过程中,手动进行缓存释放。即在服务端添加缓存释放操作,添加代码如下

// param[in] :  drop
// 1: 释放页面缓存
// 2: 释放目录文件和inodes 
// 3: 释放所有缓存(页面缓存,目录文件和inodes)
void dropCache(int drop)
{
    int ret = 0;
    int fd = open("/proc/sys/vm/drop_caches", O_RDWR);
    char dropData[4] = {0};
    int dropSize = snprintf(dropData, sizeof(dropData), "%d", drop);
    ret = write(fd, dropData, dropSize);
    close(fd);
}

 

我在服务端添加如下,每发送100M数据后进行一次释放缓存动作,调用如下:

这样就可以成功下载core了。

后记:在这个公司呆了三个多月我就跳到其他公司去了,这个文档也分享给了部门的几个人,不知他们会不会去用^_^。

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值