bug-gnulib
[Top][All Lists]
Advanced

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

abort-debug: Prefer libbacktrace to execinfo


From: Bruno Haible
Subject: abort-debug: Prefer libbacktrace to execinfo
Date: Sun, 19 May 2024 16:06:09 +0200

The stack traces that I get on the CI machines are not always useful,
in particular because no line number information is included.

With this patch, the abort-debug module uses the libbacktrace instead
of the execinfo facility. The output (on a Debian-based system) before:

../../gltests/test-floor1.c:36: assertion 'floor (0.0) == 3.0' failed
Stack trace:
./test-floor1(rpl_abort+0x3d) [0x559ead41c3ad]
./test-floor1(+0x1189) [0x559ead41c189]
/lib/x86_64-linux-gnu/libc.so.6(+0x29d90) [0x7f2378198d90]
/lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0x80) [0x7f2378198e40]
./test-floor1(_start+0x25) [0x559ead41c1b5]
Aborted (core dumped)

and after the patch:

../../gltests/test-floor1.c:36: assertion 'floor (0.0) == 3.0' failed
Stack trace:
0x557a64e9c5f0 print_stack_trace
        ../../gllib/abort-debug.c:40
0x557a64e9c5f0 rpl_abort
        ../../gllib/abort-debug.c:94
0x557a64e9c458 main
        ../../gltests/test-floor1.c:36
0x7f496331bd8f __libc_start_call_main
        ../sysdeps/nptl/libc_start_call_main.h:58
0x7f496331be3f __libc_start_main_impl
        ../csu/libc-start.c:392
0x557a64e9c484 ???
        ???:0
0xffffffffffffffff ???
        ???:0
Aborted (core dumped)

The lines

0x557a64e9c458 main
        ../../gltests/test-floor1.c:36

are definitely more informative than

./test-floor1(+0x1189) [0x559ead41c189]


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.

diff --git a/lib/abort-debug.c b/lib/abort-debug.c
index ca4dbc7291..8252b66def 100644
--- a/lib/abort-debug.c
+++ b/lib/abort-debug.c
@@ -21,7 +21,26 @@
 
 #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);
diff --git a/m4/abort-debug.m4 b/m4/abort-debug.m4
index e819d58dcb..61716e5a06 100644
--- a/m4/abort-debug.m4
+++ b/m4/abort-debug.m4
@@ -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
 ])
 






reply via email to

[Prev in Thread] Current Thread [Next in Thread]