]> Savannah Git Hosting - gnulib.git/commitdiff
abort-debug: Prefer libbacktrace to execinfo.
authorBruno Haible <bruno@clisp.org>
Sun, 19 May 2024 13:55:21 +0000 (15:55 +0200)
committerBruno Haible <bruno@clisp.org>
Sun, 19 May 2024 13:55:21 +0000 (15:55 +0200)
* lib/abort-debug.c: Include <backtrace.h>.
(state): New variable.
(print_stack_trace): Add another implementation.
(_gl_pre_abort, rpl_abort): Also test HAVE_LIBBACKTRACE.
* m4/abort-debug.m4 (gl_ABORT_DEBUG_EARLY): Check for libbacktrace.
Set LIBS, not LDFLAGS.

ChangeLog
lib/abort-debug.c
m4/abort-debug.m4

index a4ed70af3217865637e5fd4621a54e78e76f3f4a..1e8cc9405421848de3442fb503876c1bf61d35c8 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,13 @@
+2024-05-18  Bruno Haible  <bruno@clisp.org>
+
+       abort-debug: Prefer libbacktrace to execinfo.
+       * lib/abort-debug.c: Include <backtrace.h>.
+       (state): New variable.
+       (print_stack_trace): Add another implementation.
+       (_gl_pre_abort, rpl_abort): Also test HAVE_LIBBACKTRACE.
+       * m4/abort-debug.m4 (gl_ABORT_DEBUG_EARLY): Check for libbacktrace.
+       Set LIBS, not LDFLAGS.
+
 2024-05-18  Bruno Haible  <bruno@clisp.org>
 
        mkfifoat: Work around a macOS 14 bug.
index ca4dbc7291c60933de7dee5a81c396ab999d4f31..8252b66def899617ad9ab8144b49da537df4e017 100644 (file)
 
 #include <signal.h>
 
-#if HAVE_EXECINFO_H
+#if HAVE_LIBBACKTRACE
+
+# include <backtrace.h>
+
+static struct backtrace_state *state /* = NULL */;
+
+static inline void
+# if (__GNUC__ >= 3) || (__clang_major__ >= 4)
+__attribute__ ((always_inline))
+# endif
+print_stack_trace (FILE *stream)
+{
+  if (state == NULL)
+    state = backtrace_create_state (NULL, 0, NULL, NULL);
+  /* Pass skip=0, to work around <https://github.com/ianlancetaylor/libbacktrace/issues/60>.  */
+  fprintf (stream, "Stack trace:\n");
+  backtrace_print (state, 0, stream);
+}
+
+#elif HAVE_EXECINFO_H
 
 # include <stdio.h>
 
@@ -58,7 +77,7 @@ print_stack_trace (FILE *stream)
 void
 _gl_pre_abort (void)
 {
-#if HAVE_EXECINFO_H
+#if HAVE_LIBBACKTRACE || HAVE_EXECINFO_H
   print_stack_trace (stderr);
 #endif
 }
@@ -71,7 +90,7 @@ _gl_pre_abort (void)
 void
 rpl_abort (void)
 {
-#if HAVE_EXECINFO_H
+#if HAVE_LIBBACKTRACE || HAVE_EXECINFO_H
   print_stack_trace (stderr);
 #endif
   raise (SIGABRT);
index e819d58dcbcc2c5d7ee8497276baa5133b99979f..61716e5a0667e7db6b6ea4875fd5f92d7f660b50 100644 (file)
@@ -1,5 +1,5 @@
 # abort-debug.m4
-# serial 1
+# serial 2
 dnl Copyright (C) 2024 Free Software Foundation, Inc.
 dnl This file is free software; the Free Software Foundation
 dnl gives unlimited permission to copy and/or distribute it,
@@ -23,26 +23,55 @@ AC_DEFUN([gl_ABORT_DEBUG_EARLY],
 
   AC_REQUIRE([gl_STDLIB_H_DEFAULTS])
   if test $enable_debug_abort = yes; then
-    AC_REQUIRE([AC_CANONICAL_HOST])
-    case "$host_os" in
-      *-gnu* | gnu* | darwin* | freebsd* | dragonfly* | netbsd* | openbsd* | solaris*)
-        dnl execinfo might be implemented on this platform.
-        REPLACE_ABORT=1
-        dnl On *BSD system, link all programs with -lexecinfo. Cf. m4/execinfo.m4.
-        case "$host_os" in
-          freebsd* | dragonfly* | netbsd* | openbsd*)
-            LDFLAGS="$LDFLAGS -lexecinfo"
-            ;;
-        esac
-        dnl Link all programs in such a way that the stack trace includes the
-        dnl function names. '-rdynamic' is equivalent to '-Wl,-export-dynamic'.
-        case "$host_os" in
-          *-gnu* | gnu* | openbsd*)
-            LDFLAGS="$LDFLAGS -rdynamic"
-            ;;
-        esac
-        ;;
-    esac
+    dnl The first choice is libbacktrace by Ian Lance Taylor.
+    dnl Maintained at https://github.com/ianlancetaylor/libbacktrace,
+    dnl mirrored into GCC, installed as part of GCC by a few distros.
+    dnl It produces source file names and line numbers, if the binary
+    dnl is compiled with debug information.
+    AC_CACHE_CHECK([for libbacktrace], [gl_cv_lib_backtrace], [
+      gl_saved_LIBS="$LIBS"
+      LIBS="$gl_saved_LIBS -lbacktrace"
+      AC_LINK_IFELSE(
+        [AC_LANG_PROGRAM(
+           [[#include <backtrace.h>
+           ]],
+           [[struct backtrace_state *state =
+               backtrace_create_state (NULL, 0, NULL, NULL);
+           ]])],
+        [gl_cv_lib_backtrace=yes],
+        [gl_cv_lib_backtrace=no])
+      LIBS="$gl_saved_LIBS"
+    ])
+    if test $gl_cv_lib_backtrace = yes; then
+      AC_DEFINE([HAVE_LIBBACKTRACE], [1],
+        [Define if you have the libbacktrace library.])
+      REPLACE_ABORT=1
+      LIBS="$LIBS -lbacktrace"
+    else
+      dnl The second choice is libexecinfo.
+      dnl It does not produce source file names and line numbers, only addresses
+      dnl (which are mostly useless due to ASLR) and _sometimes_ function names.
+      AC_REQUIRE([AC_CANONICAL_HOST])
+      case "$host_os" in
+        *-gnu* | gnu* | darwin* | freebsd* | dragonfly* | netbsd* | openbsd* | solaris*)
+          dnl execinfo might be implemented on this platform.
+          REPLACE_ABORT=1
+          dnl On *BSD system, link all programs with -lexecinfo. Cf. m4/execinfo.m4.
+          case "$host_os" in
+            freebsd* | dragonfly* | netbsd* | openbsd*)
+              LIBS="$LIBS -lexecinfo"
+              ;;
+          esac
+          dnl Link all programs in such a way that the stack trace includes the
+          dnl function names. '-rdynamic' is equivalent to '-Wl,-export-dynamic'.
+          case "$host_os" in
+            *-gnu* | gnu* | openbsd*)
+              LDFLAGS="$LDFLAGS -rdynamic"
+              ;;
+          esac
+          ;;
+      esac
+    fi
   fi
 ])