[gimp] app: add source location information to the Linux GimpBacktrace backend



commit 7cdd1ebeefcbc9e7f48fa4bdeee7ce9c2a7cb436
Author: Ell <ell_se yahoo com>
Date:   Sat Sep 22 22:33:44 2018 -0400

    app: add source location information to the Linux GimpBacktrace backend
    
    When libbacktrace is available, use it to retrieve source location
    information in the Linux GimpBacktrace backend.

 app/Makefile.am                |   1 +
 app/core/gimpbacktrace-linux.c | 159 +++++++++++++++++++++++++++--------------
 app/tests/Makefile.am          |   1 +
 configure.ac                   |  43 ++++++++++-
 4 files changed, 149 insertions(+), 55 deletions(-)
---
diff --git a/app/Makefile.am b/app/Makefile.am
index 114a809caf..fda2e5fafb 100644
--- a/app/Makefile.am
+++ b/app/Makefile.am
@@ -181,6 +181,7 @@ gimpconsoleldadd = \
        $(Z_LIBS)                                               \
        $(JSON_C_LIBS)                                          \
        $(LIBMYPAINT_LIBS)                                      \
+       $(LIBBACKTRACE_LIBS)                                    \
        $(LIBUNWIND_LIBS)                                       \
        $(INTLLIBS)                                             \
        $(RT_LIBS)                                              \
diff --git a/app/core/gimpbacktrace-linux.c b/app/core/gimpbacktrace-linux.c
index 477aa0a096..cef207a43a 100644
--- a/app/core/gimpbacktrace-linux.c
+++ b/app/core/gimpbacktrace-linux.c
@@ -44,6 +44,10 @@
 #include <string.h>
 #include <stdio.h>
 
+#ifdef HAVE_LIBBACKTRACE
+#include <backtrace.h>
+#endif
+
 #ifdef HAVE_LIBUNWIND
 #define UNW_LOCAL_ONLY
 #include <libunwind.h>
@@ -110,6 +114,10 @@ static pid_t             blacklisted_threads[MAX_N_THREADS];
 static gint              n_blacklisted_threads;
 static GimpBacktrace    *handler_backtrace;
 
+#ifdef HAVE_LIBBACKTRACE
+static struct backtrace_state *backtrace_state;
+#endif
+
 static const gchar *blacklisted_thread_names[] =
 {
   "gmain"
@@ -271,6 +279,9 @@ gimp_backtrace_signal_handler (gint signum)
 void
 gimp_backtrace_init (void)
 {
+#ifdef HAVE_LIBBACKTRACE
+  backtrace_state = backtrace_create_state (NULL, 0, NULL, NULL);
+#endif
 }
 
 gboolean
@@ -565,75 +576,115 @@ gimp_backtrace_get_frame_address (GimpBacktrace *backtrace,
   return backtrace->threads[thread].frames[frame];
 }
 
+#ifdef HAVE_LIBBACKTRACE
+static void
+gimp_backtrace_syminfo_callback (GimpBacktraceAddressInfo *info,
+                                 guintptr                  pc,
+                                 const gchar              *symname,
+                                 guintptr                  symval,
+                                 guintptr                  symsize)
+{
+  if (symname)
+    g_strlcpy (info->symbol_name, symname, sizeof (info->symbol_name));
+
+  info->symbol_address = symval;
+}
+
+static gint
+gimp_backtrace_pcinfo_callback (GimpBacktraceAddressInfo *info,
+                                guintptr                  pc,
+                                const gchar              *filename,
+                                gint                      lineno,
+                                const gchar              *function)
+{
+  if (function)
+    g_strlcpy (info->symbol_name, function, sizeof (info->symbol_name));
+
+  if (filename)
+    g_strlcpy (info->source_file, filename, sizeof (info->source_file));
+
+  info->source_line = lineno;
+
+  return 0;
+}
+#endif /* HAVE_LIBBACKTRACE */
+
 gboolean
 gimp_backtrace_get_address_info (guintptr                  address,
                                  GimpBacktraceAddressInfo *info)
 {
-  Dl_info dl_info;
+  Dl_info  dl_info;
+  gboolean result = FALSE;
 
   g_return_val_if_fail (info != NULL, FALSE);
 
-#ifdef HAVE_LIBUNWIND
-  {
-    unw_context_t context = {};
-    unw_cursor_t  cursor;
-    unw_word_t    offset;
-
-    if (dladdr ((gpointer) address, &dl_info) && dl_info.dli_fname)
-      {
-        g_strlcpy (info->object_name, dl_info.dli_fname,
-                   sizeof (info->object_name));
-      }
-    else
-      {
-        info->object_name[0] = '\0';
-      }
-
-    if (unw_init_local (&cursor, &context)         == 0 &&
-        unw_set_reg (&cursor, UNW_REG_IP, address) == 0 &&
-        unw_get_proc_name (&cursor,
-                           info->symbol_name, sizeof (info->symbol_name),
-                           &offset)                == 0)
-      {
-        info->symbol_address = address - offset;
-      }
-    else
-      {
-        info->symbol_name[0] = '\0';
-        info->symbol_address = 0;
-      }
-  }
-#else
-  if (! dladdr ((gpointer) address, &dl_info))
-    return FALSE;
-
-  if (dl_info.dli_fname)
-    {
-      g_strlcpy (info->object_name, dl_info.dli_fname,
-                 sizeof (info->object_name));
-    }
-  else
-    {
-      info->object_name[0] = '\0';
-    }
+  info->object_name[0] = '\0';
+
+  info->symbol_name[0] = '\0';
+  info->symbol_address = 0;
+
+  info->source_file[0] = '\0';
+  info->source_line    = 0;
 
-  if (dl_info.dli_sname)
+  if (dladdr ((gpointer) address, &dl_info))
     {
-      g_strlcpy (info->symbol_name, dl_info.dli_sname,
-                 sizeof (info->symbol_name));
+      if (dl_info.dli_fname)
+        {
+          g_strlcpy (info->object_name, dl_info.dli_fname,
+                     sizeof (info->object_name));
+        }
+
+      if (dl_info.dli_sname)
+        {
+          g_strlcpy (info->symbol_name, dl_info.dli_sname,
+                     sizeof (info->symbol_name));
+        }
+
+      info->symbol_address = (guintptr) dl_info.dli_saddr;
+
+      result = TRUE;
     }
-  else
+
+#ifdef HAVE_LIBBACKTRACE
+  if (backtrace_state)
     {
-      info->symbol_name[0] = '\0';
+      backtrace_syminfo (
+        backtrace_state, address,
+        (backtrace_syminfo_callback) gimp_backtrace_syminfo_callback,
+        NULL,
+        info);
+
+      backtrace_pcinfo (
+        backtrace_state, address,
+        (backtrace_full_callback) gimp_backtrace_pcinfo_callback,
+        NULL,
+        info);
+
+      result = TRUE;
     }
+#endif /* HAVE_LIBBACKTRACE */
 
-  info->symbol_address = (guintptr) dl_info.dli_saddr;
-#endif
+#ifdef HAVE_LIBUNWIND
+  if (! info->symbol_name[0])
+    {
+      unw_context_t context = {};
+      unw_cursor_t  cursor;
+      unw_word_t    offset;
+
+      if (unw_init_local (&cursor, &context)         == 0 &&
+          unw_set_reg (&cursor, UNW_REG_IP, address) == 0 &&
+          unw_get_proc_name (&cursor,
+                             info->symbol_name, sizeof (info->symbol_name),
+                             &offset)                == 0)
+        {
+          info->symbol_address = address - offset;
 
-  info->source_file[0] = '\0';
-  info->source_line    = 0;
+          result = TRUE;
+        }
+    }
+#endif /* HAVE_LIBUNWIND */
 
-  return TRUE;
+  return result;
 }
 
 
diff --git a/app/tests/Makefile.am b/app/tests/Makefile.am
index 55dd04c2c7..3b6076f7c4 100644
--- a/app/tests/Makefile.am
+++ b/app/tests/Makefile.am
@@ -138,6 +138,7 @@ LDADD = \
        $(Z_LIBS)                                                       \
        $(JSON_C_LIBS)                                                  \
        $(LIBMYPAINT_LIBS)                                              \
+       $(LIBBACKTRACE_LIBS)                                            \
        $(LIBUNWIND_LIBS)                                               \
        $(INTLLIBS)                                                     \
        $(RT_LIBS)                                                      \
diff --git a/configure.ac b/configure.ac
index ed6cd74652..6cff17fa28 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1791,6 +1791,43 @@ AC_SUBST(FILE_HEIF)
 AM_CONDITIONAL(HAVE_LIBHEIF, test "x$have_libheif" = xyes)
 
 
+########################
+# Check for libbacktrace
+########################
+
+AC_ARG_WITH(libbacktrace, [  --without-libbacktrace       build without libbacktrace support])
+
+have_libbacktrace=no
+if test "x$with_libbacktrace" != xno; then
+  gimp_save_LIBS=$LIBS
+  LIBS="$LIBS -lbacktrace"
+
+  AC_MSG_CHECKING([for LIBBACKTRACE])
+  AC_LINK_IFELSE(
+    [AC_LANG_PROGRAM(
+      [[#include <stddef.h>
+        #include <backtrace.h>
+        #include <backtrace-supported.h>
+
+        #if ! BACKTRACE_SUPPORTED
+        #error ! BACKTRACE_SUPPORTED
+        #endif
+      ]],
+      [[(void) backtrace_create_state (NULL, 0, NULL, NULL);]])],
+    [AC_MSG_RESULT([yes]); LIBBACKTRACE_LIBS='-lbacktrace'],
+    [AC_MSG_RESULT([no]); have_libbacktrace='no (libbacktrace is not found or not supported)'])
+
+  LIBS=$gimp_save_LIBS
+
+  AC_SUBST(LIBBACKTRACE_LIBS)
+fi
+
+if test "x$have_libbacktrace" = xyes; then
+  AC_DEFINE(HAVE_LIBBACKTRACE, 1,
+            [Define to 1 if libbacktrace is available])
+fi
+
+
 #####################
 # Check for libunwind
 #####################
@@ -1817,7 +1854,11 @@ fi
 
 detailed_backtraces=no
 if test "x$platform_linux" = xyes; then
-  detailed_backtraces=$have_libunwind
+  if test "x$have_libbacktrace" = xyes -o "x$have_libunwind" = xyes; then
+    detailed_backtraces=yes
+  else
+    detailed_backtraces='no (libbacktrace and libunwind are not found or not supported)'
+  fi
 elif test "x$platform_win32" = xyes; then
   detailed_backtraces=$enable_drmingw
 fi


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]