[Mesa-dev] [PATCH 2/2] gallium/util: libunwind support
Thomas Hellstrom
thellstrom at vmware.com
Mon Apr 3 16:56:39 UTC 2017
Hi, Rob,
On 03/24/2017 10:21 PM, Rob Clark wrote:
> It's kinda sad that (a) we don't have debug_backtrace support on !X86
> and that (b) we re-invent our own crude backtrace support in the first
> place. If available, use libunwind instead. The backtrace format is
> based on what xserver and weston use, since it is nice not to have to
> figure out a different format.
>
> Signed-off-by: Rob Clark <robdclark at gmail.com>
Did you consider glibc "backtrace()", I think it's also available on ARM...
Also is the output format the same as before, or at least compatible with
gallium/tools/addr2line.sh?
Thanks,
Thomas
> ---
> configure.ac | 24 ++++++++
> src/gallium/Automake.inc | 1 +
> src/gallium/auxiliary/util/u_debug_stack.c | 91 ++++++++++++++++++++++++++++++
> src/gallium/auxiliary/util/u_debug_stack.h | 15 ++++-
> 4 files changed, 129 insertions(+), 2 deletions(-)
>
> diff --git a/configure.ac b/configure.ac
> index a99684b..5046acb 100644
> --- a/configure.ac
> +++ b/configure.ac
> @@ -1025,6 +1025,30 @@ AC_SUBST([LLVM_LIBS])
> AC_SUBST([LLVM_LDFLAGS])
> AC_SUBST([LLVM_INCLUDEDIR])
>
> +dnl
> +dnl libunwind
> +dnl
> +AC_ARG_ENABLE([libunwind],
> + [AS_HELP_STRING([--enable-libunwind],
> + [Use libunwind for backtracing (default: auto)])],
> + [LIBUNWIND="$enableval"],
> + [LIBUNWIND="auto"])
> +
> +PKG_CHECK_MODULES(LIBUNWIND, libunwind, [HAVE_LIBUNWIND=yes], [HAVE_LIBUNWIND=no])
> +if test "x$LIBUNWIND" = "xauto"; then
> + LIBUNWIND="$HAVE_LIBUNWIND"
> +fi
> +
> +if test "x$LIBUNWIND" = "xyes"; then
> + if test "x$HAVE_LIBUNWIND" != "xyes"; then
> + AC_MSG_ERROR([libunwind requested but not installed.])
> + fi
> + AC_DEFINE(HAVE_LIBUNWIND, 1, [Have libunwind support])
> +fi
> +
> +AM_CONDITIONAL(HAVE_LIBUNWIND, [test "x$LIBUNWIND" = xyes])
> +
> +
> dnl Options for APIs
> AC_ARG_ENABLE([opengl],
> [AS_HELP_STRING([--disable-opengl],
> diff --git a/src/gallium/Automake.inc b/src/gallium/Automake.inc
> index a01fa54..48b5a44 100644
> --- a/src/gallium/Automake.inc
> +++ b/src/gallium/Automake.inc
> @@ -46,6 +46,7 @@ GALLIUM_TARGET_CFLAGS = \
>
> GALLIUM_COMMON_LIB_DEPS = \
> -lm \
> + $(LIBUNWIND_LIBS) \
> $(LIBSENSORS_LIBS) \
> $(CLOCK_LIB) \
> $(PTHREAD_LIBS) \
> diff --git a/src/gallium/auxiliary/util/u_debug_stack.c b/src/gallium/auxiliary/util/u_debug_stack.c
> index f941234..cf05f13 100644
> --- a/src/gallium/auxiliary/util/u_debug_stack.c
> +++ b/src/gallium/auxiliary/util/u_debug_stack.c
> @@ -36,6 +36,95 @@
> #include "u_debug_symbol.h"
> #include "u_debug_stack.h"
>
> +#if defined(HAVE_LIBUNWIND)
> +
> +#ifndef _GNU_SOURCE
> +#define _GNU_SOURCE
> +#endif
> +#include <dlfcn.h>
> +
> +void
> +debug_backtrace_capture(struct debug_stack_frame *backtrace,
> + unsigned start_frame,
> + unsigned nr_frames)
> +{
> + unw_cursor_t cursor;
> + unw_context_t context;
> + unw_proc_info_t pip;
> + unsigned i = 0;
> + int ret;
> +
> + pip.unwind_info = NULL;
> +
> + unw_getcontext(&context);
> + unw_init_local(&cursor, &context);
> +
> + while ((start_frame > 0) && (unw_step(&cursor) > 0))
> + start_frame--;
> +
> + while (unw_step(&cursor) > 0) {
> + char procname[256];
> + const char *filename;
> + unw_word_t off;
> + Dl_info dlinfo;
> +
> + unw_get_proc_info(&cursor, &pip);
> +
> + ret = unw_get_proc_name(&cursor, procname, 256, &off);
> + if (ret && ret != -UNW_ENOMEM) {
> + procname[0] = '?';
> + procname[1] = 0;
> + }
> +
> + if (dladdr((void *)(uintptr_t)(pip.start_ip + off), &dlinfo) && dlinfo.dli_fname &&
> + *dlinfo.dli_fname)
> + filename = dlinfo.dli_fname;
> + else
> + filename = "?";
> +
> + snprintf(backtrace[i].buf, sizeof(backtrace[i].buf),
> + "%u: %s (%s%s+0x%x) [%p]", i, filename, procname,
> + ret == -UNW_ENOMEM ? "..." : "", (int)off,
> + (void *)(uintptr_t)(pip.start_ip + off));
> +
> + i++;
> + }
> +
> + while (i < nr_frames) {
> + backtrace[i].buf[0] = '\0';
> + i++;
> + }
> +}
> +
> +void
> +debug_backtrace_dump(const struct debug_stack_frame *backtrace,
> + unsigned nr_frames)
> +{
> + unsigned i;
> +
> + for (i = 0; i < nr_frames; ++i) {
> + if (backtrace[i].buf[0] == '\0')
> + break;
> + debug_printf("\t%s\n", backtrace[i].buf);
> + }
> +}
> +
> +void
> +debug_backtrace_print(FILE *f,
> + const struct debug_stack_frame *backtrace,
> + unsigned nr_frames)
> +{
> + unsigned i;
> +
> + for (i = 0; i < nr_frames; ++i) {
> + if (backtrace[i].buf[0] == '\0')
> + break;
> + fprintf(f, "\t%s\n", backtrace[i].buf);
> + }
> +}
> +
> +#else /* ! HAVE_LIBUNWIND */
> +
> #if defined(PIPE_OS_WINDOWS)
> #include <windows.h>
> #endif
> @@ -179,3 +268,5 @@ debug_backtrace_print(FILE *f,
> fprintf(f, "%s\n", symbol);
> }
> }
> +
> +#endif /* HAVE_LIBUNWIND */
> diff --git a/src/gallium/auxiliary/util/u_debug_stack.h b/src/gallium/auxiliary/util/u_debug_stack.h
> index 04eba08..0effcbe 100644
> --- a/src/gallium/auxiliary/util/u_debug_stack.h
> +++ b/src/gallium/auxiliary/util/u_debug_stack.h
> @@ -30,6 +30,11 @@
>
> #include <stdio.h>
>
> +#ifdef HAVE_LIBUNWIND
> +#define UNW_LOCAL_ONLY
> +#include <libunwind.h>
> +#endif
> +
> /**
> * @file
> * Stack backtracing.
> @@ -46,15 +51,21 @@ extern "C" {
> /**
> * Represent a frame from a stack backtrace.
> *
> - * XXX: Do not change this.
> +#if defined(PIPE_OS_WINDOWS) && !defined(HAVE_LIBUNWIND)
> + * XXX: Do not change this. (passed to Windows' CaptureStackBackTrace())
> +#endif
> *
> * TODO: This should be refactored as a void * typedef.
> */
> struct debug_stack_frame
> {
> +#ifdef HAVE_LIBUNWIND
> + char buf[128];
> +#else
> const void *function;
> +#endif
> };
> -
> +
>
> void
> debug_backtrace_capture(struct debug_stack_frame *backtrace,
More information about the mesa-dev
mailing list