您的位置:首页 > 运维架构 > Linux

linux调试之函数调用堆栈

2015-05-28 11:11 162 查看
最近要实现程序打印函数调用信息,就研究了一下linux下的函数调用堆栈

参考:http://www.360doc.com/content/15/0105/11/982782_438311997.shtml

注:这个里面详细介绍了栈帧(Stack Frame)的结构,每个未完成函数都会占用一个栈帧结构,里面保存了函数的一些相关信息(函数地址、形参、返回值等等)

参考:http://blog.csdn.net/dremi/article/details/6723804

注:这个里面有个代码实现的例子,给出了两种方法:

一、使用libc库里面backtrace函数实现;

二、自己通过分析调用栈信息来实现;

编译问题:

在使用网上的例子时:使用-rdynaminc选项时gcc报错,解决办法使用-export-dynamic代替,成功!

        参考:https://gcc.gnu.org/bugzilla/show_bug.cgi?id=37454

代码部分:

源码网上几乎都是一样就不贴了;

主要是用了libc库的两个函数:

#include <execinfo.h>

int backtrace (void **buffer, int size)

//用来获取堆栈信息。size需要获取的堆栈层次,返回值为实际获得的堆栈层次

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

//size 是backtrace的返回值该函数是用来翻译从bacetrace获得的堆栈信息。返回值为存放各个函数的地址 的二维指针。

void backtrace_symbols_fd (void *const *buffer, int size, int
fd)  //扩展


//该函数的功能和backtrace_symbols一样只是它的返回字符串是写入文件描术符为fd的文件

扩展:

在intel cpu中,寄存器BP(EBP)被用作帧指针,所以读取EBP的值就可以获得栈帧的起始地址. ---其它类型CPU自行查找相关资料

ESP(指针存放于对应的寄存器中)被用来作为栈顶指针,指向当前栈帧顶部(低地址)

获取寄存器的值需要利用内嵌汇编,相关语法可参考:http://blog.csdn.net/pbymw8iwm/article/details/8227839

Linux和windows下汇编语法的区别http://www.docin.com/p-115580288.html,特别是两者语法中源操作数和目的操作数是反过来的。

附:

栈帧结构图 ( 这是主调函数(caller)和被调函数(callee)的栈帧布局 )



总结:

1、完成的函数不会出现在栈帧里面(函数未完成会压栈,完成后出栈)

2、待定
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  linux 调试