2011-06-08 58 views
3

在mips平臺上,我試圖讓Unwind工作。目前,如果我發出print_trace手動堆棧跟蹤被正確地如下所示:mips _Unwind_Backtrace on SIGSEGV

backtrace_helper 0x4b6958

backtrace_helper 0x4b6ab4

backtrace_helper 0x2ac2f628

得到的3-堆棧幀。

./v(print_trace+0x38)[0x4b6958]

./v(main+0x90)[0x4b6ab4]

/lib/libc.so.0(__uClibc_main+0x24c)[0x2ac2f628]

但是,當發生SIGSEGV時,堆棧跟蹤不會顯示正確的函數調用序列。

backtrace_helper 0x4b7a74

backtrace_helper 0x2ab9b84c

獲得的2-堆棧幀。

./v(getLineIDByPhyIdx+0x3d8)0x4b7a74]

/lib/libpthread.so.0(__new_sem_post+0x2c8)0x2ab9b84c]

我與-g -fexceptions編譯 - rdynamic。此外,我已經看到How to generate a stacktrace when my gcc C++ app crashes其中約錯誤的地址第二個答案mentiones但是當我設置像他那樣,但它只是改變了第2架和休息是一樣的,代碼片斷如下:

caller_address = (void *) uc->uc_mcontext.gregs[30]; // Frame pointer (from wikipedia here) 

fprintf(stderr, "signal %d (%s), address is %p from %p\n", 
    sig_num, strsignal(sig_num), info->si_addr, 
    (void *)caller_address); 

size = backtrace(array, 50); 

/* overwrite sigaction with caller's address */ 
array[1] = caller_address; 

messages = backtrace_symbols(array, size); 

代碼:

int main(int argc, char *argv[]) { 
    registerSignalHandler(signalHandler); 

    print_trace(); 

    { 
     // Seg Fault 
     int *p = NULL; 
     *p = 54; 
    } 
} 

void print_trace(void) { 
    void *array[10]; 
    size_t size; 
    char **strings; 
    size_t i; 

    /* Get the address at the time the signal was raised from the EIP (x86) */ 
    size = backtrace(array, 10); 
    strings = backtrace_symbols(array, size); 

    printf("Obtained %zd stack frames.\n", size); 

    for (i = 0; i < size; i++) 
     printf("%s\n", strings[i]); 

    free(strings); 
} 



static _Unwind_Reason_Code 
backtrace_helper (struct _Unwind_Context *ctx, void *a) 
{ 
    struct trace_arg *arg = a; 

    assert (unwind_getip != NULL); 

    /* We are first called with address in the __backtrace function. Skip it. */ 
    if (arg->cnt != -1) { 
     arg->array[arg->cnt] = (void *) unwind_getip (ctx); 
     printf("backtrace_helper %p \n", arg->array[arg->cnt]); 
    } 
    if (++arg->cnt == arg->size) 
     return _URC_END_OF_STACK; 
    return _URC_NO_REASON; 
} 

/* 
* Perform stack unwinding by using the _Unwind_Backtrace. 
* 
* User application that wants to use backtrace needs to be 
* compiled with -fexceptions option and -rdynamic to get full 
* symbols printed. 
*/ 
int backtrace (void **array, int size) 
{ 
    struct trace_arg arg = { .array = array, .size = size, .cnt = -1 }; 

    if (unwind_backtrace == NULL) 
     backtrace_init(); 

    if (size >= 1) 
     unwind_backtrace (backtrace_helper, &arg); 

    return arg.cnt != -1 ? arg.cnt : 0; 
} 


void signalHandler(int sig, siginfo_t* siginfo, void* notused) 
{ 
    /* Print out the signal info */ 
    signalInfo(sig, siginfo); 

    switch (sig) { 
     case SIGSEGV: 
     { 
      print_trace(); 
      abort(); 
     } 
    } 
} 

回答