使用__builtin_return_address获得程序运行栈情况

来源:互联网 发布:linux终端退出服务器 编辑:程序博客网 时间:2024/06/04 11:38

项目中遇到了一个多线程的问题,系统总是莫名其妙的崩溃,而且bug不可重现,后来发现是接收到某些信号的问题,于是乎就加入了信号处理函数,想获得是什么地方触发了这个信号,因为感觉多线程调试比较麻烦,于是就想到了使用利用__builtin_return_address来获得函数运行栈的方法。

直接上测试代码:
 #include <stdio.h>
#include <stdlib.h>
#include <signal.h>

#define MAX_LEVEL 4
void sigfunc(int signo)
{
    printf("%s(0): %p\n", __func__, __builtin_return_address(0));
    printf("%s(1): %p\n", __func__, __builtin_return_address(1));
    printf("%s(2): %p\n", __func__, __builtin_return_address(2));
    printf("%s(3): %p\n", __func__, __builtin_return_address(3));
    printf("%s(4): %p\n", __func__, __builtin_return_address(4));
    exit(1);
}

int b()
{
    printf("%s(0): %p\n", __func__, __builtin_return_address(0));
    while(1)
    {
        sleep(1);
    }
}

int a(int temp)
{
    temp += 1;
    printf("%s(0): %p\n", __func__, __builtin_return_address(0));

    b();

    return temp;
}

int main()
{
    signal(SIGINT, sigfunc);
    a(123);

    return 0;
}
运行结果:
wangyao@wangyao-laptop:~/Test$ ./a.out
a(0): 0x8048554
b(0): 0x804851e
sigfunc(0): 0xb7eef420
sigfunc(1): 0x80484f2
sigfunc(2): 0x804851e
sigfunc(3): 0x8048554
sigfunc(4): 0xb7da2450

我们已经拿到了程序运行轨迹中的逻辑地址,下面的就是在gdb里面l一下那些地址就可以了:
wangyao@wangyao-laptop:~/Test$ gdb -q a.out
(gdb) l *0x804851e
0x804851e is in a (t_return.c:37).
32        temp += 1;
33        printf("%s(0): %p\n", __func__, __builtin_return_address(0));
34   
35        b();
36   
37        return temp;
38    }
39   
40    int main()
41    {
(gdb) q


这样就已经找到了程序运行的轨迹,如果使用一些ELF处理的库直接解析符号表的话,也可以不用gdb来做,直接通过得到的逻辑地址进行定位;-)

原创粉丝点击