使用信号机制在Linux程序中打印函数调用栈

#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <execinfo.h>
#include <ucontext.h>

void handler(int signo, siginfo_t *info, void *context)
{
        ucontext_t* ctx = (ucontext_t*)context;

        void *trace[16];
        char **messages = (char **)NULL;
        int i, trace_size = 0;

        trace_size = backtrace(trace, 16);

        /* overwrite sigaction with caller's address */
        trace[1] = (void *)ctx->uc_mcontext.gregs[REG_RIP];
        messages = backtrace_symbols(trace, trace_size);

        /* skip first stack frame (points here) */
        printf("[bt] Execution path:\n");
        for (i = 1; i < trace_size; ++i)
        {
                printf("[bt] #%d %s\n", i, messages[i]);

                /* find first occurence of '(' or ' ' in message[i] and assume
                 * everything before that is the file name. (Don't go beyond 0 though
                 * (string terminator)*/
                size_t p = 0;
                while(messages[i][p] != '(' && messages[i][p] != ' ' && messages[i][p] != 0)
                        ++p;

                char syscom[256];

                /* /usr/bin/addr2line */
                sprintf(syscom,"addr2line %p -e %.*s", trace[i], p, messages[i]);

                //last parameter is the file name of the symbol
                system(syscom);
        }

        exit(EXIT_SUCCESS);
}

int func_a(int a, char b) 
{
        char *p = (char *)0xdeadbeef;
        a = a + b;
        *p = 10;  /* CRASH here!! */

        return 2 * a;
}


int func_b() 
{
        int res, a = 5;
        res = 5 + func_a(a, 't');
        return res;
}


int main() 
{
        struct sigaction sa={0} ;

        /* Install our signal handler */
        sa.sa_sigaction = &handler;
        sigemptyset(&sa.sa_mask);
        sa.sa_flags = SA_RESTART;

        sigaction(SIGSEGV, &sa, NULL);
        sigaction(SIGUSR1, &sa, NULL);

        /* Do something */
        printf("%d\n", func_b());
        //raise(SIGSEGV);
}

编译

gcc -g -rdynamic *.cpp -o bs
 

运行

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值