博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
【软件开发底层知识修炼】六 Binutils辅助工具之- addr2line与strip工具
阅读量:1998 次
发布时间:2019-04-28

本文共 2356 字,大约阅读时间需要 7 分钟。

学习交流加

  • 个人qq:
    1126137994
  • 个人微信:
    liu1126137994
  • 学习交流资源分享qq群:
    962535112

上一篇文章我们学习了gcc编译器的相关内容。点击查看上一篇文章:。本篇文章接着上一篇文章,学习GNU为GCC提供的辅助开发工具集Binutils。Binutils工具集,主要是用于在代码调试的时候,定位bug的一些手段。我们主要学习以下几个工具的使用:

在这里插入图片描述

本篇文章先学习使用addr2line与strip工具。

文章目录

1、addr2line工具

首先我们要知道,gcc编译程序的时候,加上-g选项,表示在目标文件中生成调试信息。几乎所有调试辅助工具,都依赖于程序的调试信息。

addr2line工具。顾名思义,可以将地址转换为行号。它常用于分析定位内存访问错误的问题。以实际例子为例:

test.c程序

#include 
int g_global = 0;int g_test = 1;extern int* g_pointer;extern void func();int main(int argc, char *argv[]){
printf("&g_global = %p\n", &g_global); printf("&g_test = %p\n", &g_test); printf("&g_pointer = %p\n", &g_pointer); printf("g_pointer = %p\n", g_pointer); printf("&func = %p\n", &func); printf("&main = %p\n", &main); func(); return 0;}

func.c程序

#include 
int* g_pointer;void func(){
*g_pointer = (int)"D.T.Software"; return;}

我们在linux下编译以下程序(注意我使用gcc-4.4.5版本编译没有警告显示。但是使用较高版本的gcc编译器,可能会有警告。这里我们忽略警告):

  • gcc -g func.c test.c -o lyy

运行程序

  • ./lyy

显示结果为:

在这里插入图片描述

其实结果也在意料之中。我们分析程序很容易知道,func函数中 *g_pointer = (int)"D.T.Software"; 这句话,使得在0地址赋值了。因为int* g_pointer;只是定义了g_pointer却没有赋值,那么g_pointer实际上一开始是指向0地址,后面又对它进行赋值。相当于对0地址进行操作。

但是我们知道0地址,是不能被操作的。所以会产生段错误。这个程序很短,问题我们很容易发现。但是如果这个歌程序有一千行,一万行的话,那么问题就很难定位到。此时addr2line工具就能够上场。

下面来说明如何使用addr2line工具。

  1. 首先开启core dump选项。使用命令ulimit -c unlimited。开启这个选项后,在运行可执行程序的时候,会将程序崩溃前最后一刻的内存状态信息,转储(保存)到一个core文件。这个文件叫做核心转储文件。我们可以通过读取该文件,获取一些用于调试的信息。

    在这里插入图片描述

  2. 开启core dump选项后,再次运行可执行程序,来生成core文件。

在这里插入图片描述

我们可以看到,段错误后面显示核心已转储。此时查看当前目录的话,就可以看到core文件。

在这里插入图片描述

  1. 读取core文件,获取IP寄存器的值(IP寄存器存的是当前CPU所要执行指令的值,程序崩溃前最后一刻的IP寄存器的值,就是崩溃的指令地址)。使用dmesg core 命令读取core文件的内容,显示内容最后部分如下:

在这里插入图片描述

可以看到,最后一刻IP寄存器的值为0x080483d1.出问题的代码就在这个地址处。但是我们无法知道这个地址处到底是个啥。但是可以利用addr2line工具,将这个地址转换为代码中对应的行号。

  1. 使用addr2line定位对应的代码行。使用命令:addr2line 0x080483d1 -f -e lyy

在这里插入图片描述

很明显,已经找打原因,是func.c程序的第7行。当从两万行大代码中找到这个错误,也是很激动的!!!

2、strip工具

实际上,addr2line能够正常工作,必须依赖于程序的调试信息。而我们在编译程序的时候,也确实让程序生成了调试信息。如上编译的时候带的-g选项。

当可执行程序里面带有大量的调试信息,会导致可执行程序,非常的大。如果在大型的软件中,软件在发布之前,肯定是要将这些调试信息去掉,好让发布出去的程序占用内存空间更小,不然程序太大,对用户来说也是非常不友好的。

其实这就是所谓的release版本的程序。在发布之前,还需要调试的程序,我们称为debug版本程序。

那么如何剔除调试信息?使用strip工具!如下图是release版本的程序大小为9074:

在这里插入图片描述

使用strip将调试信息剔除后大小为5512:

在这里插入图片描述

结果显而易见!!!

还有其他工具,放在下一篇文章学习!!!

3、总结

  • addr2line用于将代码地址转换为对应的行号。常用于定位内存访问错误的问题
  • 理解core dump选项。
  • strip可以剔除目标程序中的调试信息,从而可以减小目标代码的大小,提升目标程序的执行效率。
  • 学会使用上述两个工具。

本文章参考狄泰软件学院相关课程

想学习的可以加狄泰软件学院群,
群聊号码:199546072

学习探讨加个人(可以免费帮忙下载CSDN资源):

qq:1126137994
微信:liu1126137994

转载地址:http://dbytf.baihongyu.com/

你可能感兴趣的文章
SparkSQL数据DataFrame向ElasticSearch写入的优化,亲测提高数倍
查看>>
java单例模式几种常见实现方式
查看>>
shell脚本中$0,$?,$!、$$、$*、$#、$@等的意义
查看>>
Linux正则表达式基础入门+扩展
查看>>
Java实现生产者消费者模式的三种方法
查看>>
Java线程池的四种拒绝策略
查看>>
java线程池常用的阻塞队列
查看>>
Lock 常用的几种方法,和作用
查看>>
[译]Android冰淇淋三明治ICS(4.0+)JNI局部引用的变化
查看>>
Google Map For Android V2 使用方法
查看>>
OpenGL ES四 – 光效
查看>>
OpenGL ES五 – 材质
查看>>
OpenGL ES六 – 纹理及纹理映射
查看>>
OpenGL ES七 – 变换和矩阵
查看>>
OpenGL ES四补遗 – setupView重写
查看>>
OpenGL ES八 - 交叉存取顶点数据
查看>>
OpenGL ES九 -动画基础和关键帧动画
查看>>
OpenGL ES九 - 四元数
查看>>
Android 插件化
查看>>
Android的线程和内存模型
查看>>