[gimp/gimp-2-10] app: add source location information to the Linux GimpBacktrace backend



commit b065ff7de7fc382c7c78c2c1ae9cfa57c30b01ba
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.
    
    (cherry picked from commit 7cdd1ebeefcbc9e7f48fa4bdeee7ce9c2a7cb436)

 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 3f14db4286..86aec105f2 100644
--- a/app/Makefile.am
+++ b/app/Makefile.am
@@ -180,6 +180,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 766c2b732c..e7191b4483 100644
--- a/app/tests/Makefile.am
+++ b/app/tests/Makefile.am
@@ -136,6 +136,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 29f48c7631..3f07f5136a 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1831,6 +1831,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
 #####################
@@ -1857,7 +1894,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]