最近在一块新的板子下作开发, 有些变量发生异常(就是我们不想到的值),可以加上backtrace,知道是哪个函数调用它,导致出现异常, 就像死机了,你可以gdb和core文件用bt 命令,查看死机在哪里(有一种 情况 不能看见, 就是发生信号异常不在本文范围 ), 本人感觉还有用, 关说不炼、假把式,下面是实现代码:
首先实现核心代码backtrace函数:
- 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;
- }
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;
}
下面就是将她加入一个文件中了
- /**
- * @fn writeToFile
- * @brief backtrace写入文件
- * @param[in] *pIndex: 目录
- * *pAppend: 附加信息
- * @param[out]
- * @return BSTAR_OK BSTAR_FAIL
- */
- int writeToFile(constchar *pIndex, constchar* 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;
- }
/**
* @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库, 那样就方便调用了