首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >SIGSEGV上的mips _Unwind_Backtrace

SIGSEGV上的mips _Unwind_Backtrace
EN

Stack Overflow用户
提问于 2011-06-08 17:15:22
回答 1查看 2.5K关注 0票数 3

在mips平台上,我试着放松工作。目前,如果我手动发出print_trace堆栈跟踪,则正确显示如下所示:

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/libp线程.so.0(__new_sem_post+0x2c8) 0x2ab9b84c

我正在用-g -fexceptions -rdynamic编译。我还看到了How to generate a stacktrace when my gcc C++ app crashes,第二个答案提到了错误的地址,但是当我像他一样设置时,它只改变了第二帧,rest是相同的,代码片段如下所示:

代码语言:javascript
复制
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);

代码:

代码语言:javascript
复制
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();
        }
    }
}
EN

回答 1

Stack Overflow用户

发布于 2013-10-17 21:36:42

框架指针在MIPS上几乎从来没有使用过,而在不挖掘符号的情况下获得回溯需要一些启发。

典型的方法是分析当前指令指针之前的代码,并尝试找到调整SP的函数序言。利用这一信息,我们可以找出前一帧的位置等。

有关一些血淋淋的细节,请参阅这些幻灯片:http://elinux.org/images/0/07/Intricacies_of_a_MIPS_Stack_Backtrace_Implementation.pdf

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/6282627

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档