基于backtrace_symbols的栈回溯

测试代码

本文不介绍栈回溯的原理,只对如何实现以及使用栈回溯来定位问题做一个简单的介绍,纯属个人理解!!!

signal_test.c

#include <stdio.h>
#include <execinfo.h>
#include <signal.h>
#include <stdlib.h>
#include <unistd.h>

/*
    编译命令:gcc signal_test.c -rdynamic -fexceptions -g -o signal_test
*/


void signal_func(int sig) {
  void *array[10];
  size_t size;

  // get void*'s for all entries on the stack
  size = backtrace(array, 10);

  // print out all the frames to stderr
  fprintf(stderr, "Error: signal %d:\n", sig);
  backtrace_symbols_fd(array, size, STDERR_FILENO);
  exit(1);
}

int main(int argc, char **argv) {
  signal(SIGSEGV, signal_func);   // install our handler
  
  int *a = NULL; 
  *a = 123;
}





编译命令可以上上图代码中的"gcc signal_test.c -rdynamic -fexceptions -g -o signal_test",编译工具链使用自己测试平台对应的工具链
编译完之后生成signal_test之后直接运行,会有如下打印:


在这里插入图片描述

上图的打印可以看到三个"./signal_test()",
从上至下的第一个表示signal_func中执行backtrace的地址
第二个就是导致出问题的地址
第三个就是之前第二步之前执行命令的地址。如果打印的信息较多就依次类推





如何解读以上地址信息


就拿第二个异常地址来解读: 0x5578aa0ca8就是出异常的地址,如果我们直接使用addr2line命令是得不到对应的结果的,因为这个地址是整个板子的地址,即这个地址是一个绝对地址,而不是一个相对地址。 使用addr2line是需要一个相对地址,相较于signal_test程序启动的偏移地址。也就是我们需要将0x5578aa0ca8减去signal_test程序启动的地址才是对的。

其实(main+0x30)也可以读取偏移地址,这个的含义就是:出异常的地址相较于main函数的起始地址偏移了0x30。我们读出main函数的起始地址,然后进行再偏移0x30就可以得到出异常的相对地址了。









借助编译工具链的相关工具进一步解读(选用与自己平台对应的工具链,x86_64-linux-gnu-、aarch64-linux-gnu-等)


使用readelf命令读取程序的符号表;readelf -s signal_test,下图是使用上述命令的截图,其中main函数的起始地址是0xc78,加上0x30得出0xca8相对的偏移地址

在这里插入图片描述



再借助addr2line工具;addr2line -e ./signal_test 0xca8,根据下图的结果就可以知道是signal_test.c文件的29行出了问题。
在这里插入图片描述

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值