backtrace

【用途】用户态或者内核态程序异常退出时回溯堆栈信息

【原理】通过对当前堆栈的分析,回溯上层函数在当前栈中的帧地址,直至顶层函数。帧地址是指在栈中存在局部变量、上一级函数返回地址、寄存器值的内存空间。由于不同处理器堆栈实现不同(向上增长和向下增长),此功能的具体实现是编译器内建的__buildin_frame_address及__buildin_return_address函数。如果编译器不支持此函数,也可以自己实现该函数。

【接口说明】具体说明可以参考man backtrace帮助文档

execinfo.h

int backtrace (void **buffer, int size)
The backtrace function obtains a backtrace for the current thread, as a list of pointers, and places the information into buffer.

char ** backtrace_symbols (void *const *buffer, int size)

The backtrace_symbols function translates the information obtained from the backtrace function into an array of strings. The argument buffer should be a pointer to an array of addresses obtained via the backtrace function, and size is the number of entries in that array (the return value of backtrace).

void backtrace_symbols_fd(void *const *buffer, int size, int fd)

【实例】

#include <signal.h>

#include <stdio.h>

#include <stdlib.h>

#include <execinfo.h>

#include <fcntl.h>

#include <string.h>

#include <unistd.h>

#include <sys/types.h>

#include <sys/stat.h>

#define PRINT_DEBUG

#define MAX_BACKTRACE_LEVEL 10

#define BACKTRACE_LOG_NAME "backtrace.log"

static void show_reason(int sig, siginfo_t *info, void *secret){

void *array[MAX_BACKTRACE_LEVEL];

size_t size;

#ifdef PRINT_DEBUG

char **strings;

size_t i;

size = backtrace(array, MAX_BACKTRACE_LEVEL);

strings = backtrace_symbols(array, size);

printf("Obtain %zd stack frames.\n", size);

for(i = 0; i < size; i++)

    printf("%s\n", strings[i]);

free(strings);

#else

int fd = open(BACKSTRACE_LOG_NAME, O_CREAT | O_WRONLY);

size = backtrace(array, MAX_BACKTRACE_LEVEL);

backtrace_symbols_fd(array, size, fd);

close(fd);

#endif

exit(0);

}

void die() {

char *str1;

char *str2;

char *str3;

char *str4 = NULL;

strcpy(str4, "ab");

}

void let_it_die() {

die();

}

int main(int argc, char **argv){

struct sigaction act;

act.sa_sigaction = show_reason;

sigemptyset(&act.sa_mask);

act.sa_flags = SA_RESTART | SA_SIGINFO;

sigaction(SIGSEGV, &act, NULL);

sigaction(SIGUSR1, &act, NULL);

sigaction(SIGFPE, &act, NULL);

  sigaction(SIGILL, &act, NULL);

sigaction(SIGBUS, &act, NULL);

sigaction(SIGABRT, &act, NULL);

sigaction(SIGSYS, &act, NULL);

let_it_die();

return  0;

}

【调试】

1) 编译

huawei@WUH1000002965:~/test$ gcc backtrace_test.c -o backtrace_test -g –rdynamic

(注:-rdynamic,这个option是传递给linker的,linker会将symbol放到.dydym table中,这样backtrace_symbols才能获取到地址对应的symbol。所以即使是使用了-g来编译程序,如果不使用-rdynamic的话,backtrace_symbols也找不到地址对应的symbol。这是backtrace系列函数的一个缺陷)

2) 运行

huawei@WUH1000002965:~/test$ ./backtrace_test

Obtain 7 stack frames.

./backtrace_test() [0x40096e]

/lib/x86_64-linux-gnu/libc.so.6(+0x364a0) [0x7f2ff171c4a0]

./backtrace_test(die+0x18) [0x400a03]

./backtrace_test(let_it_die+0xe) [0x400a1d]

./backtrace_test(main+0xf6) [0x400b15]

/lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0xed) [0x7f2ff170776d]

./backtrace_test() [0x400889]

Linux内核调试方法总结之backtrace的更多相关文章

  1. Linux内核调试方法总结

    Linux内核调试方法总结 一  调试前的准备 二  内核中的bug 三  内核调试配置选项 1  内核配置 2  调试原子操作 四  引发bug并打印信息 1  BUG()和BUG_ON() 2   ...

  2. Linux内核调试方法总结之反汇编

    Linux反汇编调试方法 Linux内核模块或者应用程序经常因为各种各样的原因而崩溃,一般情况下都会打印函数调用栈信息,那么,这种情况下,我们怎么去定位问题呢?本文档介绍了一种反汇编的方法辅助定位此类 ...

  3. Linux内核调试方法总结之栈帧

    栈帧 栈帧和指针可以说是C语言的精髓.栈帧是一种特殊的数据结构,在C语言函数调用时,栈帧用来保存当前函数的父一级函数的栈底指针,当前函数的局部变量以及被调用函数返回后下一条汇编指令的地址.如下图所示: ...

  4. Linux内核调试方法总结【转】

    转自:http://my.oschina.net/fgq611/blog/113249 内核开发比用户空间开发更难的一个因素就是内核调试艰难.内核错误往往会导致系统宕机,很难保留出错时的现场.调试内核 ...

  5. 【转】Linux内核调试方法总结

    目录[-] 一  调试前的准备 二  内核中的bug 三  内核调试配置选项 1  内核配置 2  调试原子操作 四  引发bug并打印信息 1  BUG()和BUG_ON() 2  dump_sta ...

  6. Linux内核调试方法【转】

    转自:http://www.cnblogs.com/shineshqw/articles/2359114.html kdb:只能在汇编代码级进行调试: 优点是不需要两台机器进行调试. gdb:在调试模 ...

  7. Linux内核调试方法总结之序言

    本系列主要介绍Linux内核死机.异常重启类稳定性问题的调试方法. 在Linux系统中,一切皆为文件,而系统运行的载体,是一类特殊的文件,即进程.因此,我尝试从进程的角度分析Linux内核的死机.异常 ...

  8. Linux内核调试方法总结之coredump

    什么是core dump? 分析core dump是Linux应用程序调试的一种有效方式,像内核调试抓取ram dump一样,core dump主要是获取应用程序崩溃时的现场信息,如程序运行时的内存. ...

  9. Linux内核调试方法总结之ddebug

    [用途] Linux内核动态调试特性,适用于驱动和内核各子系统调试.动态调试的主要功能就是允许你动态的打开或者关闭内核代码中的各种提示信息.适用于驱动和内核线程功能调试. [使用方法] 依赖于CONF ...

随机推荐

  1. Centos7Yum安装PHP7.2流程

    Centos7Yum安装PHP7.21.安装源 安装php72w,是需要配置额外的yum源地址的,否则会报错不能找到相关软件包. php高版本的yum源地址,有两部分,其中一部分是epel-relea ...

  2. 通过编写串口助手工具学习MFC过程——(八)遇到的一些问题

    通过编写串口助手工具学习MFC过程 因为以前也做过几次MFC的编程,每次都是项目完成时,MFC基本操作清楚了,但是过好长时间不再接触MFC的项目,再次做MFC的项目时,又要从头开始熟悉.这次通过做一个 ...

  3. [51Nod1623] 完美消除

    link $solution:$ 首先我们可以发现一个结论,对于一个数 $x$ ,它的最低修改次数为它每位与前去中是否都比此位上的数大,有则答案 $-1$ .因为若有小数则没有办法将其答案贡献变低. ...

  4. P3190 [HNOI2007]神奇游乐园

    传送门 第一道插头 $dp$ 由于讲不清楚所以假装各位早就会插头 $dp$ 了 首先要的是一个闭合回路,所以可以用括号表示法表示状态,然后大力分类讨论 $1.$ 没有右插头和下插头 那么我们可以啥也不 ...

  5. 完整ASP.Net Excel导入

    //把EXCEL文件上传到服务器并返回文件路径        private String typename(FileUpload fileloads)        {            str ...

  6. 前端开发HTML&css入门——HTML

    HTML究竟为何物?其实HTML就是一种标记语言,英文全称为Hypertext Markup Language,翻译过来就叫超文本标记语言.它的作用就是负责负责网页的三个要素之中的结构. HTML使用 ...

  7. Java8 将List转变为逗号分隔的字符串

    import java.util.Arrays; import java.util.List; import java.util.stream.Collectors; public class Tes ...

  8. Linux学习--第二天--分区、格式化、系统安装、vmware、远程管理工具

    分区 主分区加上扩展分区只能有四个,其中扩展分区只能有一个,扩展分区不能写入数据,不能格式化,只能包含逻辑分区.这是硬盘的限制. 格式化 分为高级与低级.文件系统是高级格式化.低级是硬盘操作. 扩展分 ...

  9. Mongo--04 Mongo分片集群

    目录 一.分片的概念 二. 分片工作原理 三.IP端口目录规划 1.IP端口规划 2.目录规划 四.分片集群搭建副本集步骤 1.安装软件 2.创建目录 3.创建配置文件 4.优化警告 5.启动服务 6 ...

  10. centos 系统查看raid信息

    一.MegaCli命令介绍 MegaCli是一款管理维护硬件RAID软件,可以用来查看raid信息等MegaCli 的Media Error Count: 0 Other Error Count: 0 ...