使用addr2line 打印调用栈信息调试程序崩溃

2023-11-06

首先参考:https://blog.csdn.net/gongmin856/article/details/79192259

接下来是我复制下来的代码,命名ttt.c

#include <stdio.h>
#include <stdlib.h> 
#include <signal.h>       /* for signal */  
#include <execinfo.h>     /* for backtrace() */  
 
 #define BACKTRACE_SIZE   16 
 
int divide(int num)
{
    int ret = 0x00;  
    int *pTemp = NULL;  
      
     if(0 != num)
     {
         printf("num is not 0 !\n");
     }
      
    *pTemp = 0x01;  /* 这将导致一个段错误,致使程序崩溃退出 */  
      
    ret = num + *pTemp;  
      
    return ret;  
    
    return 0;
}

void dump(void)  
{  
    int j, nptrs;  
    void *buffer[BACKTRACE_SIZE];  
    char **strings;  
      
    nptrs = backtrace(buffer, BACKTRACE_SIZE);  
      
    printf("backtrace() returned %d addresses\n", nptrs);  
  
    strings = backtrace_symbols(buffer, nptrs);  
    if (strings == NULL) {  
        perror("backtrace_symbols");  
        exit(EXIT_FAILURE);  
    }  
  
    for (j = 0; j < nptrs; j++)  
        printf("  [%02d] %s\n", j, strings[j]);  
  
    free(strings);  
} 

void signal_handler(int signo)  
{  
      
#if 0     
    char buff[64] = {0x00};  
          
    sprintf(buff,"cat /proc/%d/maps", getpid());  
          
    system((const char*) buff);  
#endif    
  
    printf("\n=========>>>catch signal %d <<<=========\n", signo);  
      
    printf("Dump stack start...\n");  
    dump();  
    printf("Dump stack end...\n");  
  
    signal(signo, SIG_DFL); /* 恢复信号默认处理 */  
    raise(signo);           /* 重新发送信号 */  
} 
 
int main()
{
    
    
    //fprintf(stdout, "input value\n");
    int a = 3, b = 0;
    
    char *p = NULL;
    
    signal(SIGSEGV, signal_handler);  /* 为SIGSEGV信号安装新的处理函数 */ 
    signal(SIGUSR1, signal_handler);  /* 为SIGSEGV信号安装新的处理函数 */ 
    signal(SIGFPE, signal_handler);  /* 为SIGSEGV信号安装新的处理函数 */ 
    signal(SIGILL, signal_handler);  /* 为SIGSEGV信号安装新的处理函数 */ 
    signal(SIGQUIT, signal_handler);  /* 为SIGSEGV信号安装新的处理函数 */ 
    signal(SIGBUS, signal_handler);  /* 为SIGSEGV信号安装新的处理函数 */ 
    signal(SIGABRT, signal_handler);  /* 为SIGSEGV信号安装新的处理函数 */ 
    signal(SIGSYS, signal_handler);  /* 为SIGSEGV信号安装新的处理函数 */ 
    
    //&a = b;
    //memcpy(p , &a, 8);
    
    divide(0);
    //fprintf(stdout, "div value: %d\n", div);
 
    return 0;
}

几个命令:

/opt/toolchain/gcc-linaro-7.5.0-2019.12-x86_64_aarch64-linux-gnu/bin/aarch64-linux-gnu-gcc -g -rdynamic -funwind-tables -fasynchronous-unwind-tables ttt.c -o test_ttt

注:

  -rdynamic  该参数是链接选项,不是编译选项。这主要是对可执行程序(elf)而言的,而编译动态库时,即使没有rdynamic选项,默认也会将非静态函数放入动态符号表中(刻意隐藏的函数除外)。默认情况下,可执行程序(非动态库)文件内我们定义的非静态函数,是不放到动态符号表中的,链接时只有加上"-rdynamic"才能将所有非静态函数加到动态符号表中。这个参数很多文章里都有写。

-funwind-tables -fasynchronous-unwind-tables:这几个参数比较恶心,很多文章里都没提到,其实很重要,作用是为了backtrace这个函数,如果不加这几个参数,那么backtrace函数会返回1,那么程序test_ttt运行时的栈回溯信息里就只有一个了,如下:

=========>>>catch signal 11 <<<=========

Dump stack start...

backtrace() returned 6 addresses

[00] /mnt/usr/zc/temp/RB1/test_ttt(dump+0x14) [0x400be8] //就会仅仅只有这一行了

[01] /mnt/usr/zc/temp/RB1/test_ttt(signal_handler+0x2c) [0x400cb8]

[02] linux-vdso.so.1(__kernel_rt_sigreturn+0) [0x7f9234a270]

[03] /mnt/usr/zc/temp/RB1/test_ttt(divide+0x34) [0x400bb0]

[04] /mnt/usr/zc/temp/RB1/test_ttt(main+0xc0) [0x400da4]

[05] /lib/libc.so.6(__libc_start_main+0xe4) [0x7f921f3824]

Dump stack end...

在使用addr2line查问题的时候就是看0x400bb0这个值了

/opt/toolchain/gcc-linaro-7.5.0-2019.12-x86_64_aarch64-linux-gnu/bin/aarch64-linux-gnu-addr2line -e ~/smba_share/nfs/temp/RB1/test_ttt 0x400bb0

定位行数:

/home/zhaocan/smba_share/nfs/temp/RB1/ttt.c:18

如果此时使用objdump方法:

/opt/toolchain/gcc-linaro-7.5.0-2019.12-x86_64_aarch64-linux-gnu/bin/aarch64-linux-gnu-objdump -S -l ~/smba_share/nfs/temp/RB1/test_ttt > info.txt

注:

-l --line-numbers

  用文件名和行号标注相应的目标代码,仅仅和-d、-D或者-r一起使用使用-ld和使用-d的区别不是很大,在源码级调试的时候有用,要求编译时使用了-g之类的调试编译选项。

-S --source

  尽可能反汇编出源代码,尤其当编译的时候指定了-g这种调试参数时,效果比较明显。隐含了-d参数。

由上面可以看出问题发生在divide函数里,打开info.txt文件,从下往上看

0000000000400b7c <divide>: //0x400b7c + 0X34 = 0x400bb0

divide():

/home/zhaocan/smba_share/nfs/temp/RB1/ttt.c:9

#include <execinfo.h> /* for backtrace() */

#define BACKTRACE_SIZE 16

int divide(int num)

{

400b7c:a9bd7bfd stpx29, x30, [sp, #-48]!

400b80:910003fd movx29, sp

400b84:b9001fa0 strw0, [x29, #28]

/home/zhaocan/smba_share/nfs/temp/RB1/ttt.c:10

int ret = 0x00;

400b88:b9002fbf strwzr, [x29, #44]

/home/zhaocan/smba_share/nfs/temp/RB1/ttt.c:11

int *pTemp = NULL;

400b8c:f90013bf strxzr, [x29, #32]

/home/zhaocan/smba_share/nfs/temp/RB1/ttt.c:13

if(0 != num)

400b90:b9401fa0 ldrw0, [x29, #28]

400b94:7100001f cmpw0, #0x0

400b98:54000080 b.eq400ba8 <divide+0x2c> // b.none

/home/zhaocan/smba_share/nfs/temp/RB1/ttt.c:15

{

printf("num is not 0 !\n");

400b9c:90000000 adrpx0, 400000 <_init-0x988>

400ba0:91398000 addx0, x0, #0xe60

400ba4:97ffffa7 bl400a40 <puts@plt>

/home/zhaocan/smba_share/nfs/temp/RB1/ttt.c:18 //行数和addr2line查出来的一致

}

*pTemp = 0x01; /* 这将导致一个段错误,致使程序崩溃退出 */

400ba8:f94013a0 ldrx0, [x29, #32]

400bac:52800021 movw1, #0x1 // #1

400bb0:b9000001 strw1, [x0]

/home/zhaocan/smba_share/nfs/temp/RB1/ttt.c:20

ret = num + *pTemp;

400bb4:f94013a0 ldrx0, [x29, #32]

400bb8:b9400000 ldrw0, [x0]

400bbc:b9401fa1 ldrw1, [x29, #28]

400bc0:0b000020 addw0, w1, w0

400bc4:b9002fa0 strw0, [x29, #44]

/home/zhaocan/smba_share/nfs/temp/RB1/ttt.c:22

return ret;

400bc8:b9402fa0 ldrw0, [x29, #44]

/home/zhaocan/smba_share/nfs/temp/RB1/ttt.c:25

return 0;

}

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

使用addr2line 打印调用栈信息调试程序崩溃 的相关文章

  • SONAR - 使用 Cobertura 测量代码覆盖率

    我正在使用声纳来测量代码质量 我不知道的一件事是使用 Cobertura 测量代码覆盖率的步骤 我按照以下步骤操作http cobertura sourceforge net anttaskreference html http cober
  • .NET Core 中的跨平台文件名处理

    如何处理文件名System IO以跨平台方式运行类以使其在 Windows 和 Linux 上运行 例如 我编写的代码在 Windows 上完美运行 但它不会在 Ubuntu Linux 上创建文件 var tempFilename Dat
  • 为什么我收到的数据包数据大小大于mss?

    我在两台 PC 上使用 ifconfig ethX mtu 300 修改了 MTU 并使用 netperf 测试网络 我用 WireShark 嗅探了 SYN 数据包中的 MSS 260 但我得到了一些大于 260 的数据包 为什么 嗅探器
  • Unix 命令列出包含字符串但*不*包含另一个字符串的文件

    如何递归查看包含一个字符串且不包含另一个字符串的文件列表 另外 我的意思是评估文件的文本 而不是文件名 结论 根据评论 我最终使用了 find name html exec grep lR base maps xargs grep L ba
  • 为什么我收到“无法进行二进制日志记录”的信息。在我的 MySQL 服务器上?

    当我今天启动 MySQL 服务器并尝试使用以下命令进行一些更改时用于 MySQL 的 Toad http www quest com toad for mysql 我收到此消息 MySQL 数据库错误 无法进行二进制日志记录 消息 交易级别
  • 创建 jar 文件 - 保留文件权限

    我想知道如何创建一个保留其内容的文件权限的 jar 文件 我将源代码和可执行文件打包在一个 jar 文件中 该文件将在使用前提取 人们应该能够通过运行批处理 shell 脚本文件立即运行示例和演示 然后他们应该能够修改源代码并重新编译所有内
  • Android:ANT 构建失败,并显示 google-play-services-lib:“解析为没有项目的 project.properties 文件的路径”

    我正在尝试使用 ANT 构建我的应用程序 但在包含 google play services lib 库项目后 我惨遭失败 Step 1 我在 project properties 文件中设置了对库项目的引用 android library
  • 抑制 makefile 中命令调用的回显?

    我为一个作业编写了一个程序 该程序应该将其输出打印到标准输出 分配规范需要创建一个 Makefile 当调用它时make run gt outputFile应该运行该程序并将输出写入一个文件 该文件的 SHA1 指纹与规范中给出的指纹相同
  • 如何通过替换为空页映射来取消映射 mmap 文件

    Linux 用户空间有没有办法用空页面 映射自 dev null 或者可能是一个空页面 重复映射到从文件映射的页面的顶部 对于上下文 我想找到这个 JDK bug 的修复 https bugs openjdk java net browse
  • 跟踪 Linux 程序中活跃使用的内存

    我想跟踪各种程序在特定状态下接触了多少内存 例如 假设我有一个图形程序 最小化时 它可能会使用更少的内存 因为它不会重新绘制窗口 这需要读取图像和字体并执行大量库函数 这些对象仍然可以在内存中访问 但实际上并没有被使用 类似的工具top它们
  • 如何在 Linux 中编写文本模式 GUI? [关闭]

    Closed 这个问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 当我编写脚本 程序时 我经常想弹出一个简单的文本 gui 来提示输入 我该怎么做 例如 来自 Shel
  • 如何禁用 GNOME 桌面屏幕锁定? [关闭]

    Closed 这个问题不符合堆栈溢出指南 help closed questions 目前不接受答案 如何阻止 GNOME 桌面在几分钟空闲时间后锁定屏幕 我已经尝试过官方手册了在红帽 https access redhat com doc
  • nginx 上的多个网站和可用网站

    通过 nginx 的基本安装 您的sites available文件夹只有一个文件 default 怎么样sites available文件夹的工作原理以及如何使用它来托管多个 单独的 网站 只是为了添加另一种方法 您可以为您托管的每个虚拟
  • 如何在bash中使用jq从变量中包含的json中提取值

    我正在编写一个 bash 脚本 其中存储了一个 json 值 现在我想使用 Jq 提取该 json 中的值 使用的代码是 json val code lyz1To6ZTWClDHSiaeXyxg redirect to http examp
  • 如何在 shell 脚本中并行运行多个实例以提高时间效率[重复]

    这个问题在这里已经有答案了 我正在使用 shell 脚本 它读取 16000 行的输入文件 运行该脚本需要8个多小时 我需要减少它 所以我将其划分为 8 个实例并读取数据 其中我使用 for 循环迭代 8 个文件 并在其中使用 while
  • gdb查找行号的内存地址

    假设我已将 gdb 附加到一个进程 并且在其内存布局中有一个文件和行号 我想要其内存地址 如何获取文件x中第n行的内存地址 这是在 Linux x86 上 gdb info line test c 56 Line 56 of test c
  • 我可以从命令行打印 html 文件(带有图像、css)吗?

    我想从脚本中打印带有图像的样式化 html 页面 谁能建议一个开源解决方案 我使用的是 Linux Ubuntu 8 04 但也对其他操作系统的解决方案感兴趣 你可以给html2ps http user it uu se jan html2
  • linux perf:如何解释和查找热点

    我尝试了linux perf https perf wiki kernel org index php Main Page今天很实用 但在解释其结果时遇到了困难 我习惯了 valgrind 的 callgrind 这当然是与基于采样的 pe
  • vector 超出范围后不清除内存

    我遇到了以下问题 我不确定我是否错了或者它是一个非常奇怪的错误 我填充了一个巨大的字符串数组 并希望在某个点将其清除 这是一个最小的例子 include
  • 如何在 Linux shell 中将十六进制转换为 ASCII 字符?

    假设我有一个字符串5a 这是 ASCII 字母的十六进制表示Z 我需要找到一个 Linux shell 命令 它将接受一个十六进制字符串并输出该十六进制字符串代表的 ASCII 字符 所以如果我这样做 echo 5a command im

随机推荐

  • COOC软件一款用于文献计量和知识图谱绘制的新软件

    以前论文写作中做一个共现矩阵 二模矩阵 聚类图谱 词云图 邻接表 相异矩阵 同义词批量合并 研究热点追踪等分析需要一小时 一天 对于小白甚至需要一周 一个月 但是利用COOC这款软件 你会体会到什么叫方法比努力更重要 好的工具会让你事半功倍
  • 在浏览器中播放m3u8

    我自己做了个简单的demo地址 https github com onyas vip url resolve 欢迎star或fork 在浏览器上播放m3u8的视频地址有两种方式 html的video标签的方式 这种方式播放很简单
  • 使用element-ui出现的问题——loading加载被弹窗遮挡

    正常显示如下图 loading加载被弹窗遮挡如下图 网上搜了很多的文章 尝试了很多的方法 有说在弹出层上面添加opend方法 在这个方法里面调用接口 试过无效 还有的说在setTimeout里面调用请求 依旧不行 最后用了如下简单粗暴的方式
  • Go by Example-golang操作json

    package main Go by Example 中文 JSON 微信 6686496 import encoding json fmt os type Response1 struct Page int Fruits string t
  • MFC Windows 程序设计[132]之打开按钮的启用与禁用(附源码)

    MFC Windows 程序设计 132 之打开按钮的启用与禁用 程序之美 前言 主体 运行效果 核心代码 逻辑分析 结束语 程序之美 前言 MFC是微软公司提供的一个类库 class libraries 以C 类的形式封装了Windows
  • jaxb demo

    1 generate java class from xml schema in eclipse ide http theopentutorials com examples java jaxb generate java class fr
  • SpringBoot集成ShardingJDBC系列【1】—— 添加依赖

    文章只负责讲解sharding的相关配置 springboot其他的配置自己解决 文章内容将分开发布 便于平时查阅 添加依赖
  • Python,OpenCV进行直方图反投影

    Python OpenCV进行直方图反投影 1 效果图 2 源码 参考 这篇博客将介绍Python OpenCV中的直方图反投影 直方图反投影用于图像分割或在图像中查找感兴趣的对象 简单地说 它创建了一个与输入图像大小相同 但只有一个通道
  • 02 lego spike prime 测试2

    lego spike prime 的砖块可以插轴 进行连接 跟以往有所不同 特此记录
  • c 语言让两个数组合并,C 语言,将两个数组合并到另外一个数组中,并且合并之后的数组是有序的。...

    int a 10 0 int b 10 0 int c 20 0 printf a数组为 for int i 0 i lt 10 i a i arc4random 40 20 1 1 为数组生成随机元素 printf d a i print
  • 页面上下左右滑动事件

    1 下载插件 npm install vue touch next S 2 main js加入以下代码 import VueTouch from vue touch Vue use VueTouch name v touch VueTouc
  • Kotlin的型变解析(协变、逆变和不变)

    一 首先来看一个例子 import java util author wangdong description 型变 fun main args Array
  • linux运维面试题1

    一 填空题 1 在Linux 系统 中 以文件方式访问设备 2 Linux 内核引导时 从文件 etc fstab中读取要加载的文件系统 3 Linux 文件系统中每个文件用indoe节点来标识 4 全部磁盘块由四个部分组成 分别为引导块
  • 大数据(七):Pandas的基础应用详解(四)

    专栏介绍 结合自身经验和内部资料总结的Python教程 每天3 5章 最短1个月就能全方位的完成Python的学习并进行实战开发 学完了定能成为大佬 加油吧 卷起来 全部文章请访问专栏 Python全栈教程 0基础 再推荐一下最近热更的 大
  • 统计学的基本概念

    转 浅谈协方差矩阵 一 统计学的基本概念 统计学里最基本的概念就是样本的均值 方差 标准差 首先 我们给定一个含有n个样本的集合 下面给出这些概念的公式描述 均值 标准差 方差 均值描述的是样本集合的中间点 它告诉我们的信息是有限的 而标准
  • QT5.15在线安装下载速度慢的解决办法(包括qt6.0beta版)

    下载加速需要使用清华源QT地址 QT软件清华源地址 https mirrors tuna tsinghua edu cn qt一 安装代理软件Fiddler5 1 安装并打开Fiddler5 软件自动启用代理 Fiddler5软件百度搜索
  • 张筑生老师:真正的教授,学术的典范,应该给这类人最好的环境

    今日 偶然浏览一篇博客 张老师的朋友王恳先生博文 关于张筑生老师的 很受感动 张老师已然离去 但其 把数学作为宗教信仰 的观点 以及其勤奋 踏踏实实的做事风格 相信可以影响一批批人 不仅仅是做数学研究的人 中国应该还再多一些像张老师这种人
  • javaweb响应内容类型分析工具(tomcat)

    javaweb响应内容类型分析工具 tomcat 文章目录 javaweb响应内容类型分析工具 tomcat 前言 一 tomcat目录下的配置 二 生成工具 总结 前言 在模仿spring的MVC时 发现返回类型需要设置 不然默认返回te
  • socket阻塞与非阻塞,同步与异步、I/O模型

    socket阻塞与非阻塞 同步与异步 作者 huangguisu 1 概念理解 在进行网络编程时 我们常常见到同步 Sync 异步 Async 阻塞 Block 非阻塞 Unblock 四种调用方式 同步 所谓同步 就是在发出一个功能调用时
  • 使用addr2line 打印调用栈信息调试程序崩溃

    首先参考 https blog csdn net gongmin856 article details 79192259 接下来是我复制下来的代码 命名ttt c include