compositor: Use libunwind if available for better backtraces
libunwind has a dwarf parser and automatically queries the dlinfo for location of dlopened modules. The resulting backtrace is much better and includes stack frames in dynamically loaded modules. krh: Originally submitted for Xorg, adapted for weston: http://lists.x.org/archives/xorg-devel/2013-February/035493.html Note this require libunwind at least 1.1 to get the pkg-config files. Signed-off-by: Marcin Slusarz <marcin.slusarz@gmail.com>
This commit is contained in:
parent
1cc9e08d2f
commit
554a0da74a
|
@ -281,6 +281,13 @@ if test "x$GCC" = "xyes"; then
|
||||||
fi
|
fi
|
||||||
AC_SUBST(GCC_CFLAGS)
|
AC_SUBST(GCC_CFLAGS)
|
||||||
|
|
||||||
|
PKG_CHECK_MODULES(LIBUNWIND, libunwind,
|
||||||
|
[have_libunwind=yes], [have_libunwind=no])
|
||||||
|
if test "x$have_libunwind" = xyes; then
|
||||||
|
AC_DEFINE(HAVE_LIBUNWIND, 1, [Have libunwind support])
|
||||||
|
fi
|
||||||
|
AM_CONDITIONAL(HAVE_LIBUNWIND, [test "x$have_libunwind" = xyes])
|
||||||
|
|
||||||
if test "x$WESTON_NATIVE_BACKEND" = "x"; then
|
if test "x$WESTON_NATIVE_BACKEND" = "x"; then
|
||||||
WESTON_NATIVE_BACKEND="drm-backend.so"
|
WESTON_NATIVE_BACKEND="drm-backend.so"
|
||||||
fi
|
fi
|
||||||
|
|
|
@ -8,8 +8,9 @@ AM_CPPFLAGS = \
|
||||||
-DIN_WESTON
|
-DIN_WESTON
|
||||||
|
|
||||||
weston_LDFLAGS = -export-dynamic
|
weston_LDFLAGS = -export-dynamic
|
||||||
weston_CFLAGS = $(GCC_CFLAGS) $(COMPOSITOR_CFLAGS)
|
weston_CFLAGS = $(GCC_CFLAGS) $(COMPOSITOR_CFLAGS) $(LIBUNWIND_CFLAGS)
|
||||||
weston_LDADD = $(COMPOSITOR_LIBS) $(DLOPEN_LIBS) -lm ../shared/libshared.la
|
weston_LDADD = $(COMPOSITOR_LIBS) $(LIBUNWIND_LIBS) \
|
||||||
|
$(DLOPEN_LIBS) -lm ../shared/libshared.la
|
||||||
|
|
||||||
weston_SOURCES = \
|
weston_SOURCES = \
|
||||||
git-version.h \
|
git-version.h \
|
||||||
|
|
|
@ -49,6 +49,11 @@
|
||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
|
|
||||||
|
#ifdef HAVE_LIBUNWIND
|
||||||
|
#define UNW_LOCAL_ONLY
|
||||||
|
#include <libunwind.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include <wayland-server.h>
|
#include <wayland-server.h>
|
||||||
#include "compositor.h"
|
#include "compositor.h"
|
||||||
#include "../shared/os-compatibility.h"
|
#include "../shared/os-compatibility.h"
|
||||||
|
@ -3051,13 +3056,88 @@ static int on_term_signal(int signal_number, void *data)
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef HAVE_LIBUNWIND
|
||||||
|
|
||||||
static void
|
static void
|
||||||
on_segv_signal(int s, siginfo_t *siginfo, void *context)
|
print_backtrace(void)
|
||||||
|
{
|
||||||
|
unw_cursor_t cursor;
|
||||||
|
unw_context_t context;
|
||||||
|
unw_word_t off;
|
||||||
|
unw_proc_info_t pip;
|
||||||
|
int ret, i = 0;
|
||||||
|
char procname[256];
|
||||||
|
const char *filename;
|
||||||
|
Dl_info dlinfo;
|
||||||
|
|
||||||
|
pip.unwind_info = NULL;
|
||||||
|
ret = unw_getcontext(&context);
|
||||||
|
if (ret) {
|
||||||
|
weston_log("unw_getcontext: %d\n", ret);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = unw_init_local(&cursor, &context);
|
||||||
|
if (ret) {
|
||||||
|
weston_log("unw_init_local: %d\n", ret);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = unw_step(&cursor);
|
||||||
|
while (ret > 0) {
|
||||||
|
ret = unw_get_proc_info(&cursor, &pip);
|
||||||
|
if (ret) {
|
||||||
|
weston_log("unw_get_proc_info: %d\n", ret);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = unw_get_proc_name(&cursor, procname, 256, &off);
|
||||||
|
if (ret && ret != -UNW_ENOMEM) {
|
||||||
|
if (ret != -UNW_EUNSPEC)
|
||||||
|
weston_log("unw_get_proc_name: %d\n", ret);
|
||||||
|
procname[0] = '?';
|
||||||
|
procname[1] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dladdr((void *)(pip.start_ip + off), &dlinfo) && dlinfo.dli_fname &&
|
||||||
|
*dlinfo.dli_fname)
|
||||||
|
filename = dlinfo.dli_fname;
|
||||||
|
else
|
||||||
|
filename = "?";
|
||||||
|
|
||||||
|
weston_log("%u: %s (%s%s+0x%x) [%p]\n", i++, filename, procname,
|
||||||
|
ret == -UNW_ENOMEM ? "..." : "", (int)off, (void *)(pip.start_ip + off));
|
||||||
|
|
||||||
|
ret = unw_step(&cursor);
|
||||||
|
if (ret < 0)
|
||||||
|
weston_log("unw_step: %d\n", ret);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
static void
|
||||||
|
print_backtrace(void)
|
||||||
{
|
{
|
||||||
void *buffer[32];
|
void *buffer[32];
|
||||||
int i, count;
|
int i, count;
|
||||||
Dl_info info;
|
Dl_info info;
|
||||||
|
|
||||||
|
count = backtrace(buffer, ARRAY_LENGTH(buffer));
|
||||||
|
for (i = 0; i < count; i++) {
|
||||||
|
dladdr(buffer[i], &info);
|
||||||
|
weston_log(" [%016lx] %s (%s)\n",
|
||||||
|
(long) buffer[i],
|
||||||
|
info.dli_sname ? info.dli_sname : "--",
|
||||||
|
info.dli_fname);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static void
|
||||||
|
on_segv_signal(int s, siginfo_t *siginfo, void *context)
|
||||||
|
{
|
||||||
/* This SIGSEGV handler will do a best-effort backtrace, and
|
/* This SIGSEGV handler will do a best-effort backtrace, and
|
||||||
* then call the backend restore function, which will switch
|
* then call the backend restore function, which will switch
|
||||||
* back to the vt we launched from or ungrab X etc and then
|
* back to the vt we launched from or ungrab X etc and then
|
||||||
|
@ -3068,14 +3148,7 @@ on_segv_signal(int s, siginfo_t *siginfo, void *context)
|
||||||
|
|
||||||
weston_log("caught segv\n");
|
weston_log("caught segv\n");
|
||||||
|
|
||||||
count = backtrace(buffer, ARRAY_LENGTH(buffer));
|
print_backtrace();
|
||||||
for (i = 0; i < count; i++) {
|
|
||||||
dladdr(buffer[i], &info);
|
|
||||||
weston_log(" [%016lx] %s (%s)\n",
|
|
||||||
(long) buffer[i],
|
|
||||||
info.dli_sname ? info.dli_sname : "--",
|
|
||||||
info.dli_fname);
|
|
||||||
}
|
|
||||||
|
|
||||||
segv_compositor->restore(segv_compositor);
|
segv_compositor->restore(segv_compositor);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue