[backtrace]在不改变代码的情况下,打印可执行文件的backtrace

1.在Linux上当执行文件出现异常时,通常直接结束,或者生成coredump文件,debug时步骤繁琐,今天看到一种方法,在不改变原程序的情况下打印callstrace。主要做法是在程序执行时,为它注册异常信号处理函数。

2.代码

signal_lib.c

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

#define SIMPLE_WAY
#define ADDR_MAX_NUM 100

void sighandler(intsigno)
{
#ifndef SIMPLE_WAY
    exit(signo);
#else
    printf ("CALLBACK: SIGNAL:\n", iSignalNo);
    void *pBuf[ADDR_MAX_NUM] = {0};
    int iAddrNum = backtrace(pBuf, ADDR_MAX_NUM);
    printf("BACKTRACE: NUMBER OF ADDRESSES IS:%d\n\n", iAddrNum);
    char ** strSymbols = backtrace_symbols(pBuf, iAddrNum);
    if (strSymbols == NULL) {
        printf("BACKTRACE: CANNOT GET BACKTRACE SYMBOLS\n");
        return;
    }
    int ii = 0;
    for (ii = 0; ii < iAddrNum; ii++) {
        printf("%03d %s\n", iAddrNum-ii, strSymbols[ii]);
    }
    printf("\n");
    free(strSymbols);
    strSymbols = NULL;
    exit(1); // QUIT PROCESS. IF NOT, MAYBE ENDLESS LOOP.
#endif

}

__attribute__ ((constructor))voidctor(){

    intsigs[] = {

        SIGILL, SIGFPE, SIGABRT, SIGBUS, SIGSEGV, SIGHUP, SIGINT, IGQUIT, SIGTERM

    };

    int i;

    structsigaction sa;

    sa.sa_handler = sighandler;

    sigemptyset(&sa.sa_mask);

    sa.sa_flags = SA_RESETHAND;

    for(i = 0; i < sizeof(sigs)/sizeof(sigs[0]); ++i) {

        if(sigaction(sigs[i], &sa, NULL) == -1) {

            perror("Could not set signal handler");

        }

    }

}

编译:
gcc -shared -fPIC signal_lib.c -o signal_lib.so

执行:
LD_PRELOAD=./signal_lib.so ./daemon

 

posted @ 2020-05-07 20:42  smilingsusu  阅读(297)  评论(0编辑  收藏  举报