Ken Werner <[email protected]>
writes:

> Hi,
>
> These patches improve the libunwind support on ARM Linux. The first
> patch implements the unw_is_signal_frame function to enable signal
> frame detection. The second patch implements support for parsing the
> .ARM.exidx and .ARM.extab sections. These sections contain the
> unwind information as specified by the 'Exception Handling ABI for
> the ARM Architecture' document. The third patch adds
> UNW_ARM_METHOD_EXIDX as a new unwind method that uses the
> ARM-specific tables. The fourth patch implements a small unit test
> that uses the new libunwind internals directly - it may be dropped.

Hi, Ken,

We're using libunwind for providing stacktraces on crashes on a
product running on ARMs (TI DaVinci).  Previously, I've been having
problems with libunwind segfaulting if I don't have debugging symbols,
but these patches look very promising indeed.  I can't really get it
working, though.  It appears to not walk the stack at all, but always
find the same frame.

Here's my output:
[hgbsnoopy:/tmp] $ UNW_ARM_UNWIND_METHOD=4 UNW_DEBUG_LEVEL=1111 
LD_LIBRARY_PATH=/tmp ./backtrace 
Signal handlers done
bar(0)
foo(1)
 >_Uarm_init_local: (cursor=0xbe9819e0)
                >access_reg: reg = pc
            >access_reg: pc -> 891c
                >access_reg: reg = sp
            >access_reg: sp -> be9816e0
                >access_reg: reg = sp
            >access_reg: sp -> be9816e0
 >_Uarm_step: (cursor=0xbe9819e0)
                >access_reg: reg = sp
            >access_reg: sp -> be9816e0
 >_Uarm_step: (cursor=0xbe9819e0)
                >access_reg: reg = sp
            >access_reg: sp -> be9816e0
 >_Uarm_step: (cursor=0xbe9819e0)
                >access_reg: reg = sp
            >access_reg: sp -> be9816e0
 >_Uarm_step: (cursor=0xbe9819e0)
                >access_reg: reg = sp
            >access_reg: sp -> be9816e0
 >_Uarm_step: (cursor=0xbe9819e0)
                >access_reg: reg = sp
            >access_reg: sp -> be9816e0
 >_Uarm_step: (cursor=0xbe9819e0)
                >access_reg: reg = sp
            >access_reg: sp -> be9816e0
 >_Uarm_step: (cursor=0xbe9819e0)
                >access_reg: reg = sp
            >access_reg: sp -> be9816e0
 >_Uarm_step: (cursor=0xbe9819e0)
                >access_reg: reg = sp
            >access_reg: sp -> be9816e0
 >_Uarm_step: (cursor=0xbe9819e0)
                >access_reg: reg = sp
            >access_reg: sp -> be9816e0
 >_Uarm_step: (cursor=0xbe9819e0)
                >access_reg: reg = sp
            >access_reg: sp -> be9816e0
 >_Uarm_step: (cursor=0xbe9819e0)
                >access_reg: reg = sp
            >access_reg: sp -> be9816e0
 >_Uarm_step: (cursor=0xbe9819e0)
                >access_reg: reg = sp
            >access_reg: sp -> be9816e0
 >_Uarm_step: (cursor=0xbe9819e0)
                >access_reg: reg = sp
            >access_reg: sp -> be9816e0
 >_Uarm_step: (cursor=0xbe9819e0)
                >access_reg: reg = sp
            >access_reg: sp -> be9816e0
 >_Uarm_step: (cursor=0xbe9819e0)
                >access_reg: reg = sp
            >access_reg: sp -> be9816e0
 >_Uarm_step: (cursor=0xbe9819e0)
                >access_reg: reg = sp
            >access_reg: sp -> be9816e0
 >_Uarm_step: (cursor=0xbe9819e0)
                >access_reg: reg = sp
            >access_reg: sp -> be9816e0
 >_Uarm_step: (cursor=0xbe9819e0)
                >access_reg: reg = sp
            >access_reg: sp -> be9816e0
 >_Uarm_step: (cursor=0xbe9819e0)
                >access_reg: reg = sp
            >access_reg: sp -> be9816e0
 >_Uarm_step: (cursor=0xbe9819e0)
                >access_reg: reg = sp
            >access_reg: sp -> be9816e0
 >_Uarm_step: (cursor=0xbe9819e0)
                >access_reg: reg = sp
            >access_reg: sp -> be9816e0
 >_Uarm_step: (cursor=0xbe9819e0)
                >access_reg: reg = sp
            >access_reg: sp -> be9816e0
 >_Uarm_step: (cursor=0xbe9819e0)
                >access_reg: reg = sp
            >access_reg: sp -> be9816e0
 >_Uarm_step: (cursor=0xbe9819e0)
                >access_reg: reg = sp
            >access_reg: sp -> be9816e0
 >_Uarm_step: (cursor=0xbe9819e0)
                >access_reg: reg = sp
            >access_reg: sp -> be9816e0
 >_Uarm_step: (cursor=0xbe9819e0)
                >access_reg: reg = sp
            >access_reg: sp -> be9816e0
 >_Uarm_step: (cursor=0xbe9819e0)
                >access_reg: reg = sp
            >access_reg: sp -> be9816e0
 >_Uarm_step: (cursor=0xbe9819e0)
                >access_reg: reg = sp
            >access_reg: sp -> be9816e0
 >_Uarm_step: (cursor=0xbe9819e0)
                >access_reg: reg = sp
            >access_reg: sp -> be9816e0
 >_Uarm_step: (cursor=0xbe9819e0)
                >access_reg: reg = sp
            >access_reg: sp -> be9816e0
 >_Uarm_step: (cursor=0xbe9819e0)
                >access_reg: reg = sp
            >access_reg: sp -> be9816e0
 >_Uarm_step: (cursor=0xbe9819e0)
Backtrace:
./backtrace() [0x891c]
./backtrace() [0x891c]
./backtrace() [0x891c]
./backtrace() [0x891c]
./backtrace() [0x891c]
./backtrace() [0x891c]
./backtrace() [0x891c]
./backtrace() [0x891c]
./backtrace() [0x891c]
./backtrace() [0x891c]
./backtrace() [0x891c]
./backtrace() [0x891c]
./backtrace() [0x891c]
./backtrace() [0x891c]
./backtrace() [0x891c]
./backtrace() [0x891c]
./backtrace() [0x891c]
./backtrace() [0x891c]
./backtrace() [0x891c]
./backtrace() [0x891c]
./backtrace() [0x891c]
./backtrace() [0x891c]
./backtrace() [0x891c]
./backtrace() [0x891c]
./backtrace() [0x891c]
./backtrace() [0x891c]
./backtrace() [0x891c]
./backtrace() [0x891c]
./backtrace() [0x891c]
./backtrace() [0x891c]
./backtrace() [0x891c]
./backtrace() [0x891c]
End of backtrace:

The program in question is attached.

It was compiled like this:
arm-unknown-linux-gnueabi-gcc -o /tmp/backtrace /tmp/backtrace.c 
-funwind-tables -lunwind -lunwind-arm -rdynamic -g1 -fomit-frame-pointer 
-fasynchronous-unwind-tables -mapcs

(With appropriate -L and -I paths to find my cross-compiled
libunwind.)

It's gcc-4.5.1 with glibc-2.12.1, built for arm-dm6467.

Any ideas on how to attack this?

#include <libunwind.h>
#include <stddef.h>
#include <stdlib.h>
#include <stdio.h>
#include <execinfo.h>
#include <assert.h>

#define MAX_BACKTRACE 32

static size_t obtain_backtrace(void ** dest, size_t destsize, void * context)
{
    unw_cursor_t cursor;
    unw_context_t uc;
    unw_context_t * ctx;
    size_t i = 0;
    int ret;

    if (!destsize)
        return 0;

    if (context) {
        ctx = context;
    } else {
        if (unw_getcontext(&uc) < 0)
            return 0;
        ctx = &uc;
    }

    if (unw_init_local(&cursor, ctx) < 0)
        return 0;

    do {
        unw_word_t ip;
        unw_word_t sp;

        unw_get_reg(&cursor, UNW_REG_IP, &ip);
        unw_get_reg(&cursor, UNW_REG_SP, &sp);

        /* This shouldn't really happen, since unw_step() is
         * supposed to return 0 in this case, but it's been
         * known to happen anyway, so we take our precautions. */
        if (!ip)
            break;
        dest[i++] = (void*) ip;
    } while ((ret = unw_step(&cursor)) > 0 && i < destsize);

    return i;
}

static void dump_backtrace(void ** trace, size_t trace_size)
{
    char ** strings;
    size_t i;

    assert(trace_size > 0 && trace);

    if (!(strings = backtrace_symbols(trace, trace_size)))
        return;

    fputs("Backtrace:\n", stderr);
    for (i = 0; i < trace_size; ++i)
        fprintf(stderr, "%s\n", strings[i]);
    fputs("End of backtrace:\n", stderr);

    free(strings);
}

static void dump_backtrace_current_task(void)
{
    void *trace[MAX_BACKTRACE];
    size_t trace_size;
    trace_size = obtain_backtrace(trace, sizeof trace / sizeof trace[0], NULL);

    dump_backtrace(trace, trace_size);
}


static int foo(int a)
{
    fprintf(stderr, "foo(%d)\n", a);
    dump_backtrace_current_task();
    return a + 2;
}

static int bar(int a)
{
    fprintf(stderr, "bar(%d)\n", a);
    return foo(a + 1);
}

int main(void)
{
    //register_signal_handlers(NULL);
    fprintf(stderr, "Signal handlers done\n");
    bar(0);
    return 0;
}

-- 
Henrik Grindal Bakken <[email protected]>
PGP ID: 8D436E52
Fingerprint: 131D 9590 F0CF 47EF 7963  02AF 9236 D25A 8D43 6E52
_______________________________________________
Libunwind-devel mailing list
[email protected]
http://lists.nongnu.org/mailman/listinfo/libunwind-devel

Reply via email to