gcc4.4下实现backtrace代码

 最近在一块新的板子下作开发, 有些变量发生异常(就是我们不想到的值),可以加上backtrace,知道是哪个函数调用它,导致出现异常, 就像死机了,你可以gdb和core文件用bt 命令,查看死机在哪里(有一种 情况 不能看见, 就是发生信号异常不在本文范围 ), 本人感觉还有用, 关说不炼、假把式,下面是实现代码:

首先实现核心代码backtrace函数:

 

[html] view plaincopyprint
  1. extern void * __libc_stack_end;
  2. # define BOUNDED_N(PTR, N) (PTR)
  3. #define BOUNDED_1(PTR) BOUNDED_N (PTR, 1)
  4. /* Get some notion of the current stack. Need not be exactly the top
  5. of the stack, just something somewhere in the current frame. */
  6. #ifndef CURRENT_STACK_FRAME
  7. # define CURRENT_STACK_FRAME ({ char __csf; &__csf; })
  8. #endif
  9. /* By default we assume that the stack grows downward. */
  10. #ifndef INNER_THAN
  11. # define INNER_THAN <
  12. #endif
  13. /* By default assume the `next' pointer in struct layout points to the
  14. next struct layout. */
  15. #ifndef ADVANCE_STACK_FRAME
  16. # define ADVANCE_STACK_FRAME(next) BOUNDED_1 ((struct layout *) (((int)next) - 4))
  17. #endif
  18. /* By default, the frame pointer is just what we get from gcc. */
  19. #ifndef FIRST_FRAME_POINTER
  20. # define FIRST_FRAME_POINTER (__builtin_frame_address (0) - 4)
  21. #endif
  22. int backtrace (void **array, int size)
  23. {
  24. struct layout *current;
  25. void *top_frame;
  26. void *top_stack;
  27. int cnt = 0;
  28. top_frame = FIRST_FRAME_POINTER;
  29. top_stack = CURRENT_STACK_FRAME;
  30. /* We skip the call to this function, it makes no sense to record it. */
  31. current = BOUNDED_1 ((struct layout *) top_frame);
  32. while (cnt <size)
  33. {
  34. if ((void *) current->fp INNER_THAN top_stack
  35. || !((void *) current->fp INNER_THAN __libc_stack_end))
  36. {
  37. /* This means the address is out of range. Note that for the
  38. toplevel we see a frame pointer with value NULL which clearly is
  39. out of range. */
  40. break;
  41. }
  42. array[cnt] = current->lr;
  43. cnt++;
  44. current = ADVANCE_STACK_FRAME (current->fp);
  45. }
  46. /*
  47. * In leaf function
  48. * gcc not push lr when call it
  49. */
  50. printf(" ");
  51. return cnt;
  52. }
extern void * __libc_stack_end;

# define BOUNDED_N(PTR, N) (PTR)
#define BOUNDED_1(PTR) BOUNDED_N (PTR, 1)
/* Get some notion of the current stack.  Need not be exactly the top
   of the stack, just something somewhere in the current frame.  */
#ifndef CURRENT_STACK_FRAME
# define CURRENT_STACK_FRAME  ({ char __csf; &__csf; })
#endif

/* By default we assume that the stack grows downward.  */
#ifndef INNER_THAN
# define INNER_THAN <
#endif

/* By default assume the `next' pointer in struct layout points to the
   next struct layout.  */
#ifndef ADVANCE_STACK_FRAME
# define ADVANCE_STACK_FRAME(next) BOUNDED_1 ((struct layout *) (((int)next) - 4))
#endif

/* By default, the frame pointer is just what we get from gcc.  */
#ifndef FIRST_FRAME_POINTER
# define FIRST_FRAME_POINTER  (__builtin_frame_address (0) - 4)
#endif

int backtrace (void **array, int size)
{
    struct layout *current;
    void *top_frame;
    void *top_stack;
    int cnt = 0;

    top_frame = FIRST_FRAME_POINTER;
    top_stack = CURRENT_STACK_FRAME;

    /* We skip the call to this function, it makes no sense to record it.  */
    current = BOUNDED_1 ((struct layout *) top_frame);
    while (cnt < size)
    {
        if ((void *) current->fp INNER_THAN top_stack
                || !((void *) current->fp INNER_THAN __libc_stack_end))
        {
            /* This means the address is out of range.  Note that for the
               toplevel we see a frame pointer with value NULL which clearly is
               out of range.  */
            break;
        }

        array[cnt] = current->lr;
        cnt++;

        current = ADVANCE_STACK_FRAME (current->fp);
    }
    /*
     * In leaf function
     * gcc not push lr when call it
     */
    printf(" ");
    return cnt;
}


下面就是将她加入一个文件中了

 

 

  1. /**
  2. * @fn writeToFile
  3. * @brief backtrace写入文件
  4. * @param[in] *pIndex: 目录
  5. * *pAppend: 附加信息
  6. * @param[out]
  7. * @return BSTAR_OK BSTAR_FAIL
  8. */
  9. int writeToFile(constchar *pIndex, constchar* pAppend)
  10. {
  11. int j, nptrs = 0;
  12. void *buffer[100];
  13. char str[1024] = {0};
  14. int fd = 0;
  15. if(NULL == pIndex)
  16. {
  17. fprintf(stderr, "the Index is NULL!\n");
  18. return -1;
  19. }
  20. if((fd = open(pIndex, O_RDWR|O_APPEND, 0644)) < 0)
  21. {
  22. fd = open(pIndex, O_RDWR|O_CREAT|O_APPEND, 0644);
  23. }
  24. nptrs = backtrace(buffer, 100);
  25. if(NULL != pAppend)
  26. {
  27. write(fd, pAppend, strlen(pAppend));
  28. memset(str, 0, 1024);
  29. }
  30. for (j = 0; j < nptrs; j++)
  31. {
  32. sprintf(str, "%p\n", buffer[j]);
  33. write(fd, str, strlen(str));
  34. memset(str, 0, 1024);
  35. }
  36. write(fd, "================\n", strlen("================\n"));
  37. close(fd);
  38. return 0;
  39. }
/**
 * @fn          writeToFile
 * @brief       backtrace写入文件
 * @param[in]   *pIndex: 目录
 *              *pAppend: 附加信息
 * @param[out]
 * @return      BSTAR_OK    BSTAR_FAIL
 */
int writeToFile(const char *pIndex, const char* pAppend)
{
    int j, nptrs = 0;
    void *buffer[100];
    char str[1024] = {0};
    int fd = 0;

    if(NULL == pIndex)
    {
       fprintf(stderr, "the Index is NULL!\n");
       return -1;
    }

    if((fd = open(pIndex, O_RDWR|O_APPEND, 0644)) < 0)
    {
        fd = open(pIndex, O_RDWR|O_CREAT|O_APPEND, 0644);
    }

    nptrs = backtrace(buffer, 100);

    if(NULL != pAppend)
    {
        write(fd, pAppend, strlen(pAppend));
        memset(str, 0, 1024);
    }

    for (j = 0; j < nptrs; j++)
    {
        sprintf(str, "%p\n", buffer[j]);
        write(fd, str, strlen(str));
        memset(str, 0, 1024);
    }

    write(fd, "================\n", strlen("================\n"));
    close(fd);

    return 0;
}


好了,就是这些了, 你可以将她编写成so库, 那样就方便调用了

posted @ 2012-11-07 10:26  zhangyoushugz  阅读(544)  评论(0编辑  收藏  举报