使用backtrace打印函数调用栈

转载自:http://bbs.chinaunix.net/thread-950357-1-1.html

backtrace

backtrace_symbols
试验了一下,好像只能打印出地址,但是有函数名更方便些
在11楼的提示下在网上找了篇文章,自己裁减了一下

  1. //funstack.c
  2. #define _GNU_SOURCE
  3. #include <memory.h>
  4. #include <stdlib.h>
  5. #include <stdio.h>
  6. #include <signal.h>
  7. #include <ucontext.h>
  8. #include <dlfcn.h>
  9. #include <execinfo.h>

  10. #if defined(REG_RIP)
  11. # define SIGSEGV_STACK_IA64
  12. # define REGFORMAT "%016lx"
  13. #elif defined(REG_EIP)
  14. # define SIGSEGV_STACK_X86
  15. # define REGFORMAT "%08x"
  16. #else
  17. # define SIGSEGV_STACK_GENERIC
  18. # define REGFORMAT "%x"
  19. #endif

  20. static void signal_segv(int signum, siginfo_t* info, void*ptr) {
  21.         static const char *si_codes[3] = {"", "SEGV_MAPERR", "SEGV_ACCERR"};

  22.         size_t i;
  23.         ucontext_t *ucontext = (ucontext_t*)ptr;

  24. #if defined(SIGSEGV_STACK_X86) || defined(SIGSEGV_STACK_IA64)
  25.         int f = 0;
  26.         Dl_info dlinfo;
  27.         void **bp = 0;
  28.         void *ip = 0;
  29. #else
  30.         void *bt[20];
  31.         char **strings;
  32.         size_t sz;
  33. #endif

  34. #if defined(SIGSEGV_STACK_X86) || defined(SIGSEGV_STACK_IA64)
  35. # if defined(SIGSEGV_STACK_IA64)
  36.         ip = (void*)ucontext->uc_mcontext.gregs[REG_RIP];
  37.         bp = (void**)ucontext->uc_mcontext.gregs[REG_RBP];
  38. # elif defined(SIGSEGV_STACK_X86)
  39.         ip = (void*)ucontext->uc_mcontext.gregs[REG_EIP];
  40.         bp = (void**)ucontext->uc_mcontext.gregs[REG_EBP];
  41. # endif

  42.         fprintf(stderr, "Stack trace:\n");
  43.         while(bp && ip) {
  44.                 if(!dladdr(ip, &dlinfo))
  45.                         break;

  46.                 const char *symname = dlinfo.dli_sname;

  47.                 fprintf(stderr, "% 2d: %p %s+%u (%s)\n",
  48.                                 ++f,
  49.                                 ip,
  50.                                 symname,
  51.                                 (unsigned)(ip - dlinfo.dli_saddr),
  52.                                 dlinfo.dli_fname);

  53.                 if(dlinfo.dli_sname && !strcmp(dlinfo.dli_sname, "main"))
  54.                         break;

  55.                 ip = bp[1];
  56.                 bp = (void**)bp[0];
  57.         }
  58. #else
  59.         fprintf(stderr, "Stack trace (non-dedicated):\n");
  60.         sz = backtrace(bt, 20);
  61.         strings = backtrace_symbols(bt, sz);

  62.         for(i = 0; i < sz; ++i)
  63.                 fprintf(stderr, "%s\n", strings[i]);
  64. #endif
  65.         fprintf(stderr, "End of stack trace\n");
  66.         return;
  67. }
  68. int setup_sigsegv() {
  69.         struct sigaction action;
  70.         memset(&action, 0, sizeof(action));
  71.         action.sa_sigaction = signal_segv;
  72.         action.sa_flags = SA_SIGINFO;
  73.         if(sigaction(SIGUSR1, &action, NULL) < 0) {
  74.                 perror("sigaction");
  75.                 return 0;
  76.         }

  77.         return 1;
  78. }



  79. void func1()
  80. {
  81.         raise(SIGUSR1);
  82.         return ;

  83. }
  84. void func2()
  85. {
  86.         raise(SIGUSR1);
  87.         return ;

  88. }

  89. void entry()
  90. {
  91.         func1();
  92.         func2();
  93.         return;
  94. }
  95. int main()
  96. {
  97.         setup_sigsegv();
  98.         entry();
  99. }
复制代码

gcc -o funstack -rdynamic -ldl funstack.c
初步看来还不错有空加到我原来俄内存检测程序中看看效果
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值