linux调试之函数调用堆栈

最近要实现程序打印函数调用信息,就研究了一下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、待定

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值