• pthread中如何追踪stack over flow


    通常在程序挂掉的时候我们会catch 他们挂掉的signal,然后在signal中打印出当时的一个stack,来方便问题调查, 但是在stack overflow的情况发生时,会没有拿到stack。signal的stack也是建立在thread的调用栈上的,在overflow的情况下,stack没有足够的空间来执行signal处理函数,signal处理函数就会被忽略。


    示例代码:
    main 主程序

    #include <signal.h>
    #include <pthread.h>
    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    #include <sys/types.h>
    #include "mybacktrace.h"
    
    void recursiondeath()
    {
      char buffer[1024];
      recursiondeath();
      memset(buffer, 0xeb, sizeof(buffer));
      printf("%d", buffer[0]);
    }
    
    void* threadloop(void* args)
    {
      // using sginal stack
      char altstack[SIGSTKSZ];
      addsignalstack(altstack, SIGSTKSZ);
    
      recursiondeath();
      return NULL;
    }
    
    int main(int argc, char const *argv[])
    {
      char altstack[SIGSTKSZ];
      registersignal();
      addsignalstack(altstack, SIGSTKSZ);
    
      pthread_t t;
      pthread_create(&t, NULL, threadloop, NULL);
    
      pthread_join(t, NULL);
    
      return 0;
    }

    mybacktrace.h 头文件

    #include <execinfo.h>
    #include <signal.h>
    #include <assert.h>
    
    void signalhandler(int sig)
    {
        printf("signal revived [%d]
    ", sig);
        // get the back trace
        enum {
            MAX_STACK = 32,
        };
    
        void *stack[MAX_STACK];
        int size = backtrace(stack, MAX_STACK);
        if(size == 0) {
            printf("fail to get backtrace
    ");
        }    
        char** strs = backtrace_symbols(stack, size);
        int i = 0;
        for (i = 0; i < size; ++i) {
            printf("%s
    ", strs[i]);
        }
        free(strs);
    
        signal(sig, SIG_DFL);
    }
    
    void addsignalstack(char *stack, int size)
    {
        assert(stack!=NULL);
        // using sginal stack
        stack_t sigstack;
        sigstack.ss_sp = stack;
        sigstack.ss_size = SIGSTKSZ;
        sigstack.ss_flags = 0;
        if (sigaltstack(&sigstack, 0) < 0) {
            perror("sig stack setting failed");
        }
    }
    
    void registersignal()
    {
        struct sigaction act;
        act.sa_handler = signalhandler;
        act.sa_flags = SA_ONSTACK|SA_RESTART;
    
        int ret = sigaction(SIGSEGV, &act, NULL);
        if (ret < 0) {
            perror("sigaction failed
    ");
        }
    
        ret = sigaction(SIGBUS, &act, NULL);
        if (ret < 0) {
            perror("sigaction failed
    ");
        }
    
        ret = sigaction(SIGILL, &act, NULL);
        if (ret < 0) {
            perror("sigaction failed
    ");
        }
    
    }

    说明:
    添加signal alt stack

    void addsignalstack(char *stack, int size)
    {
        assert(stack!=NULL);
        // using sginal stack
        stack_t sigstack;
        sigstack.ss_sp = stack;
        sigstack.ss_size = SIGSTKSZ;
        sigstack.ss_flags = 0;
        if (sigaltstack(&sigstack, 0) < 0) {
            perror("sig stack setting failed");
        }
    }

    这边由外部传进来的数组作为signal 处理函数执行用的stack
    注册signal函数:
    ```

    void registersignal()
    {
      struct sigaction act;
      act.sa_handler = signalhandler;
      act.sa_flags = SA_ONSTACK|SA_RESTART;
    
      int ret = sigaction(SIGSEGV, &act, NULL);
      if (ret < 0) {
        perror("sigaction failed
    ");
      }
    
      ret = sigaction(SIGBUS, &act, NULL);
      if (ret < 0) {
        perror("sigaction failed
    ");
      }
    
      ret = sigaction(SIGILL, &act, NULL);
      if (ret < 0) {
        perror("sigaction failed
    ");
      }
    }

    注册了signal
    SIGSEGV
    SIGBUS
    SIGILL
    另外sigaction flag添加了SA_ONSTACK,确保当signal发生的时候,
    signal处理函数会将sig atl stack作为函数frame



    主函数:

    int main(int argc, char const *argv[])
    {
        char altstack[SIGSTKSZ];
        registersignal();
        addsignalstack(altstack, SIGSTKSZ);
        
        pthread_t t;
        pthread_create(&t, NULL, threadloop, NULL);
    
        pthread_join(t, NULL);
    
        return 0;
    }

    执行前添加下signal的altstak,这里使用栈上的数组来作为signal处理函数的函数栈,可以通过malloc或者mmap分配.


    线程的主函数

    void* threadloop(void* args)
    {
        // using sginal stack
        char altstack[SIGSTKSZ];
        addsignalstack(altstack, SIGSTKSZ);
    
        recursiondeath();
        return NULL;
    }

    执行前再添加下sig alt stack
    注意:sig alt stack时每个线程自己单独的属性,所以每个线程都需要添加自己的sig alt stack

  • 相关阅读:
    UT斯达康 G680手机那些事儿
    VoIP使用总结
    Test
    Remove "Click here to enable Instant Search"
    常用的在线播放(电台和电视台)
    Sipdroid Error “Registration failed (404 not found)”
    通过Word 2007发布Blog
    【Go反射】读取对象
    【Go反射】修改对象
    【爬虫】callback=jQuery+数字在爬虫中如何模拟
  • 原文地址:https://www.cnblogs.com/zelos/p/3802792.html
Copyright © 2020-2023  润新知