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