]> Savannah Git Hosting - gnulib.git/commitdiff
stack-trace: Use libasan as an alternative to libbacktrace.
authorBruno Haible <bruno@clisp.org>
Thu, 18 Jul 2024 02:58:39 +0000 (04:58 +0200)
committerBruno Haible <bruno@clisp.org>
Thu, 18 Jul 2024 02:58:39 +0000 (04:58 +0200)
* m4/stack-trace.m4 (gl_STACK_TRACE_EARLY): As a second choice, use
libasan.
* lib/stack-trace-impl.h (print_stack_trace_to) [HAVE_LIBASAN]:
Implement using libasan.
* lib/stack-trace.c (print_stack_trace): Test also HAVE_LIBASAN.
* lib/abort-debug.c (rpl_abort): Likewise.

ChangeLog
lib/abort-debug.c
lib/stack-trace-impl.h
lib/stack-trace.c
m4/stack-trace.m4

index b1ee1b8e6203029d1f4495ae1b8b0198eec8e840..55ee80723e39c8b017c3c699785a3a4c4db56526 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,13 @@
+2024-07-17  Bruno Haible  <bruno@clisp.org>
+
+       stack-trace: Use libasan as an alternative to libbacktrace.
+       * m4/stack-trace.m4 (gl_STACK_TRACE_EARLY): As a second choice, use
+       libasan.
+       * lib/stack-trace-impl.h (print_stack_trace_to) [HAVE_LIBASAN]:
+       Implement using libasan.
+       * lib/stack-trace.c (print_stack_trace): Test also HAVE_LIBASAN.
+       * lib/abort-debug.c (rpl_abort): Likewise.
+
 2024-07-17  Bruno Haible  <bruno@clisp.org>
 
        stack-trace: Add tests.
index ac5ddf15cd75e6d31c9c034e3ea2259166d00f57..2457ef07c29295efb6119e19ef500d22257ad093 100644 (file)
@@ -31,7 +31,7 @@
 void
 rpl_abort (void)
 {
-#if HAVE_LIBBACKTRACE || HAVE_EXECINFO_H
+#if HAVE_LIBBACKTRACE || HAVE_LIBASAN || HAVE_EXECINFO_H
   print_stack_trace_to (stderr);
 #endif
   raise (SIGABRT);
index 018563e4ccf870800fbbc17bbfa0a4ec4d94f509..529afad7a6fb3d127196caa36aeb9e37516f8317 100644 (file)
@@ -28,11 +28,33 @@ print_stack_trace_to (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");
+  /* Pass skip=0, to work around <https://github.com/ianlancetaylor/libbacktrace/issues/60>.  */
   backtrace_print (state, 0, stream);
 }
 
+#elif HAVE_LIBASAN
+
+# include <stdio.h>
+
+/* We need only one declaration from <sanitizer/asan_interface.h>.  */
+extern
+# ifdef __cplusplus
+"C"
+# endif
+void __sanitizer_print_stack_trace (void);
+
+/* The only supported stream, in this case, is stderr.  */
+static inline void
+# if (__GNUC__ >= 3) || (__clang_major__ >= 4)
+__attribute__ ((always_inline))
+# endif
+print_stack_trace_to (FILE *stream)
+{
+  fprintf (stream, "Stack trace:\n");
+  __sanitizer_print_stack_trace ();
+}
+
 #elif HAVE_EXECINFO_H
 
 # include <stdio.h>
index b4ad37bf786f58d5fe78ddf76911075a95c59cfc..b08a97706448dfeeb81d28ad682e579fdcafe5b7 100644 (file)
@@ -24,7 +24,7 @@
 void
 print_stack_trace (void)
 {
-#if HAVE_LIBBACKTRACE || HAVE_EXECINFO_H
+#if HAVE_LIBBACKTRACE || HAVE_LIBASAN || HAVE_EXECINFO_H
   print_stack_trace_to (stderr);
 #endif
 }
index 7184ca7eb20d08aa75137e9e0904eb609ed23ec4..e102484e0fd96e8133f6d4f92dd8c68afb88c078 100644 (file)
@@ -1,5 +1,5 @@
 # stack-trace.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,
@@ -48,29 +48,56 @@ AC_DEFUN([gl_STACK_TRACE_EARLY],
       CAN_PRINT_STACK_TRACE=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.
-          CAN_PRINT_STACK_TRACE=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
+      dnl The second choice is GCC's libasan, installed as part of GCC.
+      dnl It produces source file names and line numbers, if the binary
+      dnl is compiled with debug information.
+      AC_CACHE_CHECK([for libasan], [gl_cv_lib_asan], [
+        gl_saved_LIBS="$LIBS"
+        LIBS="$gl_saved_LIBS -lasan"
+        AC_LINK_IFELSE(
+          [AC_LANG_PROGRAM(
+             [[extern
+               #ifdef __cplusplus
+               "C"
+               #endif
+               void __sanitizer_print_stack_trace (void);
+             ]],
+             [[__sanitizer_print_stack_trace ();
+             ]])],
+          [gl_cv_lib_asan=yes],
+          [gl_cv_lib_asan=no])
+        LIBS="$gl_saved_LIBS"
+      ])
+      if test $gl_cv_lib_asan = yes; then
+        AC_DEFINE([HAVE_LIBASAN], [1],
+          [Define if you have the libasan library.])
+        CAN_PRINT_STACK_TRACE=1
+        LIBS="$LIBS -lasan"
+      else
+        dnl The third 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.
+            CAN_PRINT_STACK_TRACE=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
   fi
 ])