summaryrefslogtreecommitdiff
path: root/os
diff options
context:
space:
mode:
authorAdam Jackson <ajax@redhat.com>2009-08-19 15:42:34 -0400
committerAdam Jackson <ajax@redhat.com>2009-08-19 15:42:34 -0400
commiteb031d4013d36f6aef4aba45840762ae8635cc13 (patch)
treecffc91992dff8b00a6941f6765fdca71f49e3d7d /os
parent75b9383d8a4c113ab3c6cfc1d5efcb5d9982a1bf (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.c23
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 */