Linux内核调试方法总结之backtrace
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的更多相关文章
- Linux内核调试方法总结
Linux内核调试方法总结 一 调试前的准备 二 内核中的bug 三 内核调试配置选项 1 内核配置 2 调试原子操作 四 引发bug并打印信息 1 BUG()和BUG_ON() 2 ...
- Linux内核调试方法总结之反汇编
Linux反汇编调试方法 Linux内核模块或者应用程序经常因为各种各样的原因而崩溃,一般情况下都会打印函数调用栈信息,那么,这种情况下,我们怎么去定位问题呢?本文档介绍了一种反汇编的方法辅助定位此类 ...
- Linux内核调试方法总结之栈帧
栈帧 栈帧和指针可以说是C语言的精髓.栈帧是一种特殊的数据结构,在C语言函数调用时,栈帧用来保存当前函数的父一级函数的栈底指针,当前函数的局部变量以及被调用函数返回后下一条汇编指令的地址.如下图所示: ...
- Linux内核调试方法总结【转】
转自:http://my.oschina.net/fgq611/blog/113249 内核开发比用户空间开发更难的一个因素就是内核调试艰难.内核错误往往会导致系统宕机,很难保留出错时的现场.调试内核 ...
- 【转】Linux内核调试方法总结
目录[-] 一 调试前的准备 二 内核中的bug 三 内核调试配置选项 1 内核配置 2 调试原子操作 四 引发bug并打印信息 1 BUG()和BUG_ON() 2 dump_sta ...
- Linux内核调试方法【转】
转自:http://www.cnblogs.com/shineshqw/articles/2359114.html kdb:只能在汇编代码级进行调试: 优点是不需要两台机器进行调试. gdb:在调试模 ...
- Linux内核调试方法总结之序言
本系列主要介绍Linux内核死机.异常重启类稳定性问题的调试方法. 在Linux系统中,一切皆为文件,而系统运行的载体,是一类特殊的文件,即进程.因此,我尝试从进程的角度分析Linux内核的死机.异常 ...
- Linux内核调试方法总结之coredump
什么是core dump? 分析core dump是Linux应用程序调试的一种有效方式,像内核调试抓取ram dump一样,core dump主要是获取应用程序崩溃时的现场信息,如程序运行时的内存. ...
- Linux内核调试方法总结之ddebug
[用途] Linux内核动态调试特性,适用于驱动和内核各子系统调试.动态调试的主要功能就是允许你动态的打开或者关闭内核代码中的各种提示信息.适用于驱动和内核线程功能调试. [使用方法] 依赖于CONF ...
随机推荐
- Django使用Celery进行异步任务
Celery Celery是一个功能完备即插即用的异步任务队列系统.它适用于异步处理问题,当发送邮件.或者文件上传, 图像处理等等一些比较耗时的操作,我们可将其异步执行,这样用户不需要等待很久,提高用 ...
- 【vuejs面试题】务必熟知的vuejs面试题「务必收藏」
如果能帮到你,点个赞吧,务必熟知的vuejs面试题「务必收藏」 vuejs 基础必备 1.active-class 是哪个组件的属性?嵌套路由怎么定义 (1).active-class 是 vue-r ...
- MVCC/分布式事务简介
之前我们学习了RocksDB,但这还只是一个最基础的存储引擎.如果想把它在生产环境中用起来,还需要解决很多问题: 如何从单机扩展到分布式? 如何实现事务,并对事务进行并发控制? 用户接口能不能高级一点 ...
- 小程序中页面兼容h5标签的解析
有时候当小程序向后台拿数据是一篇html标签的文章时,把它放进小程序会发现很多标签就不兼容,如果要一个个改又很麻烦,有没有方法可以很快地兼容html标签呢? 有个工具可以做到:wxParse 下载了它 ...
- springmvc,springboot单元测试配置
1. springmvc单元测试配置 <dependency> <groupId>junit</groupId> <artifactId>junit&l ...
- python数据结构:pandas(3)
一.pandas数据操作: 1.处理缺失数据 (1)判断是否存在缺失值 ser_obj.isnull(),df_obj.isnull() (2)dropna:丢弃缺失数据 (3)fillna:填充缺失 ...
- C#批量将数据插入SQLServer数据库
Database db = CreateDatabase(); var varConnnection = db.CreateConnection(); //获取连 ...
- Apple Pay接入详细教程
Apple Pay接入详细教程 来源:Yasin的简书 链接:http://www.jianshu.com/p/738aee78ba52# Apple Pay运行环境:iPhone6以上设备,操作 ...
- 算法学习之二分查找算法的python实现
——参考自<算法图解> 我们假设需要查找的数组是有序的(从大到小或者从小到大),如果无序,可以在第四行后插入一句 my_list.sort() 完整代码如下 def binary_sear ...
- C 调试 gdb常用命令
gdb常用命令: [root@redhat home]#gdb 调试文件:启动gdb (gdb) l :(字母l)从第一行开始列出源码 (gdb) break n :在第n行处设置断点 (gdb) b ...