转自:https://blog.csdn.net/littlefang/article/details/42295803

有四种方法可以获得Linux的函数调用堆栈,参见CALL STACK TRACE GENERATION。

在这里简单罗列一下文中提到的四个方案:

方法1 GCC内置函数__builtin_return_address

方法2 Glibc中的backtrace函数

方法3 Jeff Muizelaar实现的增强backtrace,除了函数名,还能获得代码行号

方法4 libunwind

这里面的方法2和方法4都尝试过,方法2的backtrace函数是通过读取操作系统的一个全局信息区,在多线程并发调用时,会造成严重的锁冲突。

方法4的libunwind也存在开销较大的问题。

最终采用了下面的方案:

#define STACKCALL __attribute__((regparm(1),noinline))
void ** STACKCALL getEBP(void){
void **ebp=NULL;
__asm__ __volatile__("mov %%rbp, %0;\n\t"
:"=m"(ebp) /* 输出 */
: /* 输入 */
:"memory"); /* 不受影响的寄存器 */
return (void **)(*ebp);
}
int my_backtrace(void **buffer,int size){

int frame=0;
void ** ebp;
void **ret=NULL;
unsigned long long func_frame_distance=0;
if(buffer!=NULL && size >0)
{
ebp=getEBP();
func_frame_distance=(unsigned long long)(*ebp) - (unsigned long long)ebp;
while(ebp&& frame<size
&&(func_frame_distance< (1ULL<<24))//assume function ebp more than 16M
&&(func_frame_distance>0))
{
ret=ebp+1;
buffer[frame++]=*ret;
ebp=(void**)(*ebp);
func_frame_distance=(unsigned long long)(*ebp) - (unsigned long long)ebp;
}
}
return frame;
}

my_backtrace返回的内容和glibc的backtrace相同,可以用《使用backtrace获得动态链接库的调用地址》中的方法获得可读的调用栈。

局限性:

如果源代码编译时使用了-O1或-O2优化选项,可执行代码会把ebp/rbp/rsp寄存器当作普通寄存器使用,导致backtrace失败。为了防止这种情况发生,可以在编译时使用-O2  -fno-omit-frame-pointer  或-Og 来避免优化中使用上述寄存器。

文中的关于my_backtrace的实现主要归功于WangPeng同学。

参考文献

http://blog.chinaunix.net/uid-24774106-id-3457205.html

http://www.linuxidc.com/Linux/2011-08/41641.htm
---------------------
作者:镇关西
来源:CSDN
原文:https://blog.csdn.net/littlefang/article/details/42295803
版权声明:本文为博主原创文章,转载请附上博文链接!

高效获得Linux函数调用栈/backtrace的方法【转】的更多相关文章

  1. 嵌入式 linux下利用backtrace追踪函数调用堆栈以及定位段错误

    嵌入式 linux下利用backtrace追踪函数调用堆栈以及定位段错误 2015-05-27 14:19 184人阅读 评论(0) 收藏 举报  分类: 嵌入式(928)  一般察看函数运行时堆栈的 ...

  2. linux下利用backtrace追踪函数调用堆栈以及定位段错误

    一般察看函数运行时堆栈的方法是使用GDB(bt命令)之类的外部调试器,但是,有些时候为了分析程序的BUG,(主要针对长时间运行程序的分析),在程序出错时打印出函数的调用堆栈是非常有用的. 在glibc ...

  3. Linux下利用backtrace追踪函数调用堆栈以及定位段错误【转】

    转自:https://www.linuxidc.com/Linux/2012-11/73470p2.htm 通常情况系,程序发生段错误时系统会发送SIGSEGV信号给程序,缺省处理是退出函数.我们可以 ...

  4. 在linux代码中打印函数调用的堆栈的方法

    之前一直有这样的需求,当时问到,也没搜到方法,现在竟然既问到了,也搜到了,哎,世事真是不能强求啊! 在Linux内核调试中,经常用到的打印函数调用堆栈的方法非常简单,只需在需要查看堆栈的函数中加入: ...

  5. Linux Debugging(一): 使用反汇编理解C++程序函数调用栈

    拿到CoreDump后,如果看到的地址都是????,那么基本上可以确定,程序的栈被破坏掉了.GDB也是使用函数的调用栈去还原"事故现场"的.因此理解函数调用栈,是使用GDB进行现场 ...

  6. 理解 Linux 网络栈(1):Linux 网络协议栈简单总结

    本系列文章总结 Linux 网络栈,包括: (1)Linux 网络协议栈总结 (2)非虚拟化Linux环境中的网络分段卸载技术 GSO/TSO/UFO/LRO/GRO (3)QEMU/KVM + Vx ...

  7. (转)Java里的堆(heap)栈(stack)和方法区(method)(精华帖,多读读)

    [color=red][/color]<一> 基础数据类型直接在栈空间分配, 方法的形式参数,直接在栈空间分配,当方法调用完成后从栈空间回收.   引用数据类型,需要用new来创建,既在栈 ...

  8. C语言函数调用栈(一)

    程序的执行过程可看作连续的函数调用.当一个函数执行完毕时,程序要回到调用指令的下一条指令(紧接call指令)处继续执行.函数调用过程通常使用堆栈实现,每个用户态进程对应一个调用栈结构(call sta ...

  9. Java里的堆(heap)栈(stack)和方法区(method)

    基础数据类型直接在栈空间分配, 方法的形式参数,直接在栈空间分配,当方法调用完成后从栈空间回收.   引用数据类型,需要用new来创建,既在栈空间分配一个地址空间,又在堆空间分配对象的类变量 . 方法 ...

随机推荐

  1. go 实现用户特权判断的例子

    需求:实现用户特权,可以满足下面1个或多个条件 红名 达人 vip会员 vip超级会员 蓝钻用户 红钻用户 1.实现方法一:可以根据数据库字段,每个特权用一个字段,进行判断缺点:每增加一个特权,要进行 ...

  2. docker 基础之网络管理

    docker网络基础. docker使用到的与linux网络有关的主要技术 Network Namespace(网络命名空间) Veth设备对 Iptables/NetFilter 网桥 路由 标准的 ...

  3. OS + Linux RedHat 7 / redhat 7 configuration

    s redhat 7.2 tracker-store CPU消耗高的问题 http://www.cnblogs.com/exiahan/archive/2013/07/08/3177971.html ...

  4. 记录一次php连接mssql的配置

    记录一次php连接mssql的配置 在现有php环境中,php连接mssql数据库失败,tsql 连接正常. 确认问题在php环境上. 网上有个同仁总结的很好,https://blog.csdn.ne ...

  5. Neo4j社区版配置文件

    #*****************************************************************# Neo4j configuration## For more d ...

  6. python django基础五 ORM多表操作

    首先在创建表的时候看下分析一下 1.作者表和作者详细地址表  一对一关系 理论上谁都能当主表 把Author设置成主表 au=models.OneToOneField(to='AuthorDetail ...

  7. 使用C#的HttpWebRequest模拟登陆网站

    很久没有写新的东西了,今天在工作中遇到的一个问题,感觉很有用,有种想记下来的冲动. 这篇文章是有关模拟登录网站方面的. 实现步骤: 启用一个web会话 发送模拟数据请求(POST或者GET) 获取会话 ...

  8. 从零开始搭建高性能高可用Tomcat服务器

    目标: Tomcat+Nginx+Memcached Ubuntu 16.04 64位测试通过 动静分类.负载均衡.集群.Javolution序列化.高性能.高可用 配置环境(目前均为最新稳定版): ...

  9. 02-Unity深入浅出(二)

    一. Unity声明周期 Unity容器为我们提供了6种生命周期,便于我们根据项目需求来选择使用. (1). 瞬时.默认省略即为瞬时,无论单线程还是多线程,每次都重新创建对象.new Transien ...

  10. Mac 建PHP 环境 及 配置 apache 默认目录

    网上找的帮助,试一下,记录在此: 在Mac下配置php开发环境:Apache+php+MySql  https://www.imooc.com/article/15705?block_id=tuiji ...