diff options
author | Adam Jackson <ajax@redhat.com> | 2009-08-19 15:42:34 -0400 |
---|---|---|
committer | Adam Jackson <ajax@redhat.com> | 2009-08-19 15:42:34 -0400 |
commit | eb031d4013d36f6aef4aba45840762ae8635cc13 (patch) | |
tree | cffc91992dff8b00a6941f6765fdca71f49e3d7d /os | |
parent | 75b9383d8a4c113ab3c6cfc1d5efcb5d9982a1bf (diff) |
linux: hand-roll a backtrace printer instead of using backtrace_symbols
Why? Because backtrace_symbols calls malloc, which you can't do from a
signal handler. Face? Palm.
Diffstat (limited to 'os')
-rw-r--r-- | os/backtrace.c | 23 |
1 files changed, 16 insertions, 7 deletions
diff --git a/os/backtrace.c b/os/backtrace.c index 3cfae3e16..a8866882b 100644 --- a/os/backtrace.c +++ b/os/backtrace.c @@ -29,19 +29,28 @@ #include "misc.h" #ifdef HAVE_BACKTRACE +#define _GNU_SOURCE +#include <dlfcn.h> #include <execinfo.h> void xorg_backtrace(void) { - void *array[32]; /* deeper nesting than this means something's wrong */ + void *array[64]; + char *mod; int size, i; - char **strings; + Dl_info info; ErrorF("\nBacktrace:\n"); - size = backtrace(array, 32); - strings = backtrace_symbols(array, size); - for (i = 0; i < size; i++) - ErrorF("%d: %s\n", i, strings[i]); - free(strings); + size = backtrace(array, 64); + for (i = 0; i < size; i++) { + dladdr(array[i], &info); + mod = (info.dli_fname && *info.dli_fname) ? info.dli_fname : "(vdso)"; + if (info.dli_saddr) + ErrorF("%d: %s (%s+0x%lx) [%p]\n", i, mod, + info.dli_sname, array[i] - info.dli_saddr, array[i]); + else + ErrorF("%d: %s (%p+0x%lx) [%p]\n", i, mod, + info.dli_fbase, array[i] - info.dli_fbase, array[i]); + } } #else /* not glibc or glibc < 2.1 */ |