linux用户程序调用栈打印backtrace
2015-10-14 22:36
369 查看
在调试程序的时候,有时候程序跑到一个分支不知道怎么调用到的/在走到不应该走的分支后希望把整个调用栈打印出现,在linux用户程序里面有一个glibc库函数backtrace可以打印出当前进程栈信息(如果希望进程退出的话可以用ASSERT(),在内核态中有对应的dump_stack()和BUG()/BUG_ON()):
int backtrace(void **buffer, int size);
该函数用于获取当前现场的调用堆栈。函数返回值是指针数组中指针的个数,buffer是用来存放指针的指针数组,size是数组的最大个数。
buffer中的指针实际上是从堆栈获取的函数的返回地址。
char **backtrace_symbols(void *const*buffer, int size);
backtrace_symbols将从backtrace函数获取的信息转化为一个字符串数组. 参数buffer应该是从backtrace函数获取的指针数组,size是该数组中的元素个数(backtrace的返回值)
函数返回值是一个指向字符串数组的指针,它的大小同buffer相同.每个字符串包含了一个相对于buffer中对应元素的可打印信息.它包括函数名,函数的偏移地址,和实际的返回地址。
现在,只有使用ELF二进制格式的程序才能获取函数名称和偏移地址.在其他系统,只有16进制的返回地址能被获取.另外,你可能需要传递相应的符号给链接器,以能支持函数名功能(比如,在使用GNU ld链接器的系统中,你需要传递(-rdynamic), -rdynamic可用来通知链接器将所有符号添加到动态符号表中,如果你的链接器支持-rdynamic的话,建议将其加上!)
该函数的返回值是通过malloc函数申请的空间,因此调用者必须使用free函数来释放指针.
注意:如果不能为字符串获取足够的空间函数的返回值将会为NULL;
backtrace还可以用来定位段错误。例如如果程序发生段错误系统都会发送SIGSEGV信号给程序,缺省处理是程序退出,可以在收到该信号的处理函数中增加通过backtrace把栈信息打印出来。
如下是一个打印的栈信息,包括函数名和对应的偏移地址
Obtained6stackframes.nm
./backstrace_debug(dump+0x45)[0x80487c9]
[0x468400]
./backstrace_debug(func_b+0x8)[0x804888c]
./backstrace_debug(func_a+0x8)[0x8048896]
./backstrace_debug(main+0x33)[0x80488cb]
/lib/i386-linux-gnu/libc.so.6(__libc_start_main+0xf3)[0x129113]
接着可以用objdum反汇编出二进制文件,找到对应的位置。
objdump -d test > test.s
在test.s中搜索func_b然后加上偏移大概找到对应的出错语句。
我们也可以通过addr2line来查看
addr2line 0x804888c -e backstrace_debug -f
输出:
func_b
/home/astrol/c/backstrace_debug.c:57
int backtrace(void **buffer, int size);
该函数用于获取当前现场的调用堆栈。函数返回值是指针数组中指针的个数,buffer是用来存放指针的指针数组,size是数组的最大个数。
buffer中的指针实际上是从堆栈获取的函数的返回地址。
char **backtrace_symbols(void *const*buffer, int size);
backtrace_symbols将从backtrace函数获取的信息转化为一个字符串数组. 参数buffer应该是从backtrace函数获取的指针数组,size是该数组中的元素个数(backtrace的返回值)
函数返回值是一个指向字符串数组的指针,它的大小同buffer相同.每个字符串包含了一个相对于buffer中对应元素的可打印信息.它包括函数名,函数的偏移地址,和实际的返回地址。
现在,只有使用ELF二进制格式的程序才能获取函数名称和偏移地址.在其他系统,只有16进制的返回地址能被获取.另外,你可能需要传递相应的符号给链接器,以能支持函数名功能(比如,在使用GNU ld链接器的系统中,你需要传递(-rdynamic), -rdynamic可用来通知链接器将所有符号添加到动态符号表中,如果你的链接器支持-rdynamic的话,建议将其加上!)
该函数的返回值是通过malloc函数申请的空间,因此调用者必须使用free函数来释放指针.
注意:如果不能为字符串获取足够的空间函数的返回值将会为NULL;
backtrace还可以用来定位段错误。例如如果程序发生段错误系统都会发送SIGSEGV信号给程序,缺省处理是程序退出,可以在收到该信号的处理函数中增加通过backtrace把栈信息打印出来。
如下是一个打印的栈信息,包括函数名和对应的偏移地址
Obtained6stackframes.nm
./backstrace_debug(dump+0x45)[0x80487c9]
[0x468400]
./backstrace_debug(func_b+0x8)[0x804888c]
./backstrace_debug(func_a+0x8)[0x8048896]
./backstrace_debug(main+0x33)[0x80488cb]
/lib/i386-linux-gnu/libc.so.6(__libc_start_main+0xf3)[0x129113]
接着可以用objdum反汇编出二进制文件,找到对应的位置。
objdump -d test > test.s
在test.s中搜索func_b然后加上偏移大概找到对应的出错语句。
我们也可以通过addr2line来查看
addr2line 0x804888c -e backstrace_debug -f
输出:
func_b
/home/astrol/c/backstrace_debug.c:57
相关文章推荐
- linux shell数据重定向(输入重定向与输出重定向)详细分析
- Linux下使用C语言进行检测按键的输入
- 常见 wifi热点的linux 驱动
- linux 显示一个文本的某几行
- linux 使用github
- linux 使用proxychains连接代理服务器
- Linux ssldump命令
- Linux systemd
- Linux下spi驱动开发
- 在linux系统中安装MySQL
- linux下基于smtp协议的C++客户端debug经验
- linux shell 脚本实现tcp/upd协议通讯(重定向应用)
- linux----命令替换
- linux下基于SMTP协议的C++邮件客户端
- linux raid技术
- linux基础整理4
- linux shell命令快捷获得系统帮助(一)[man-pages定义规范]
- LINUX下图形界面切换到文本模式 以及~和/的区别
- linux中memset的正确用法
- 第 三 十 天:Linux 系 统 优 化 扩 展