zoukankan      html  css  js  c++  java
  • Linux内核调试方法总结之backtrace

    backtrace

    【用途】用户态或者内核态程序异常退出时回溯堆栈信息

    【原理】通过对当前堆栈的分析,回溯上层函数在当前栈中的帧地址,直至顶层函数。帧地址是指在栈中存在局部变量、上一级函数返回地址、寄存器值的内存空间。由于不同处理器堆栈实现不同(向上增长和向下增长),此功能的具体实现是编译器内建的__buildin_frame_address及__buildin_return_address函数。如果编译器不支持此函数,也可以自己实现该函数。

    【接口说明】具体说明可以参考man backtrace帮助文档

    execinfo.h

    int backtrace (void **buffer, int size)
    The backtrace function obtains a backtrace for the current thread, as a list of pointers, and places the information into buffer.

    char ** backtrace_symbols (void *const *buffer, int size)

    The backtrace_symbols function translates the information obtained from the backtrace function into an array of strings. The argument buffer should be a pointer to an array of addresses obtained via the backtrace function, and size is the number of entries in that array (the return value of backtrace).

    void backtrace_symbols_fd(void *const *buffer, int size, int fd)

    【实例】

    #include <signal.h>

    #include <stdio.h>

    #include <stdlib.h>

    #include <execinfo.h>

    #include <fcntl.h>

    #include <string.h>

    #include <unistd.h>

    #include <sys/types.h>

    #include <sys/stat.h>

    #define PRINT_DEBUG

    #define MAX_BACKTRACE_LEVEL 10

    #define BACKTRACE_LOG_NAME "backtrace.log"

    static void show_reason(int sig, siginfo_t *info, void *secret){

        void *array[MAX_BACKTRACE_LEVEL];

        size_t size;

    #ifdef PRINT_DEBUG

        char **strings;

        size_t i;

        size = backtrace(array, MAX_BACKTRACE_LEVEL);

        strings = backtrace_symbols(array, size);

        printf("Obtain %zd stack frames. ", size);

        for(i = 0; i < size; i++)

        printf("%s ", strings[i]);

        free(strings);

    #else

        int fd = open(BACKSTRACE_LOG_NAME, O_CREAT | O_WRONLY);

        size = backtrace(array, MAX_BACKTRACE_LEVEL);

        backtrace_symbols_fd(array, size, fd);

        close(fd);

    #endif

        exit(0);

    }

    void die() {

        char *str1;

        char *str2;

        char *str3;

        char *str4 = NULL;

        strcpy(str4, "ab");

    }

    void let_it_die() {

        die();

    }

    int main(int argc, char **argv){

        struct sigaction act;

        act.sa_sigaction = show_reason;

        sigemptyset(&act.sa_mask);

        act.sa_flags = SA_RESTART | SA_SIGINFO;

        sigaction(SIGSEGV, &act, NULL);

        sigaction(SIGUSR1, &act, NULL);

        sigaction(SIGFPE, &act, NULL);

      sigaction(SIGILL, &act, NULL);

        sigaction(SIGBUS, &act, NULL);

        sigaction(SIGABRT, &act, NULL);

        sigaction(SIGSYS, &act, NULL);

        let_it_die();

       return  0;

    }

                                           

    【调试】

    1) 编译

    huawei@WUH1000002965:~/test$ gcc backtrace_test.c -o backtrace_test -g –rdynamic

    (注:-rdynamic,这个option是传递给linker的,linker会将symbol放到.dydym table中,这样backtrace_symbols才能获取到地址对应的symbol。所以即使是使用了-g来编译程序,如果不使用-rdynamic的话,backtrace_symbols也找不到地址对应的symbol。这是backtrace系列函数的一个缺陷)

    2) 运行

    huawei@WUH1000002965:~/test$ ./backtrace_test

    Obtain 7 stack frames.

    ./backtrace_test() [0x40096e]

    /lib/x86_64-linux-gnu/libc.so.6(+0x364a0) [0x7f2ff171c4a0]

    ./backtrace_test(die+0x18) [0x400a03]

    ./backtrace_test(let_it_die+0xe) [0x400a1d]

    ./backtrace_test(main+0xf6) [0x400b15]

    /lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0xed) [0x7f2ff170776d]

    ./backtrace_test() [0x400889]

  • 相关阅读:
    sql中别名加as和不加as的区别
    easyui 扩展 datagrid 数据网格视图
    asp.net 版本一键升级,后台直接调用升级脚本
    SQLserver 还原数据库报“指定转换无效”的错的解决方案
    sql视图显示数据不对应
    django channels 实现实时通讯,主动推送
    django orm信号机制 + apschedule 定时任务
    django 使用原始SQL语句方式
    Django model 常用查询(搬运来备份的)
    Python3+ Django2.7开发web排坑记006 apache+wsgi部署应用
  • 原文地址:https://www.cnblogs.com/justin-y-lin/p/5424524.html
Copyright © 2011-2022 走看看