On a mips platform, I am trying to get Unwind work. Currently if I issue print_trace manually stack trace is correctly shown as below:
backtrace_helper 0x4b6958
backtrace_helper 0x4b6ab4
backtrace_helper 0x2ac2f628
Obtained 3 stack frames.
./v(print_trace+0x38) [0x4b6958]
./v(main+0x90) [0x4b6ab4]
/lib/libc.so.0(__uClibc_main+0x24c) [0x2ac2f628]
But when a SIGSEGV occurs, stack trace does not show correct function call sequence.
backtrace_helper 0x4b7a74
backtrace_helper 0x2ab9b84c
Obtained 2 stack frames.
./v(getLineIDByPhyIdx+0x3d8) [0x4b7a74]
/lib/libpthread.so.0(__new_sem_post+0x2c8) [0x2ab9b84c]
I am compiling with -g -fexceptions -rdynamic. Also I have seen How to generate a stacktrace when my gcc C++ app crashes in which 2nd answer mentiones about wrong address but when I set as he does but it only changes 2nd frame and rest is the same, code snippet is below:
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);
Code:
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();
        }
    }
}
 
     
    