Chinaunix首页 | 论坛 | 博客
  • 博客访问: 5762289
  • 博文数量: 675
  • 博客积分: 20301
  • 博客等级: 上将
  • 技术积分: 7671
  • 用 户 组: 普通用户
  • 注册时间: 2005-12-31 16:15
文章分类

全部博文(675)

文章存档

2012年(1)

2011年(20)

2010年(14)

2009年(63)

2008年(118)

2007年(141)

2006年(318)

分类: C/C++

2008-12-04 19:16:39

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

直接上测试代码:

#include
#include
#include

#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来做,直接通过得到的逻辑地址进行定位;-)

参考:

http://blog.csdn.net/celestialwy/archive/2006/10/23/1346155.aspx
阅读(7320) | 评论(0) | 转发(1) |
给主人留下些什么吧!~~