#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>
void
_gl_pre_abort (void)
{
-#if HAVE_EXECINFO_H
+#if HAVE_LIBBACKTRACE || HAVE_EXECINFO_H
print_stack_trace (stderr);
#endif
}
void
rpl_abort (void)
{
-#if HAVE_EXECINFO_H
+#if HAVE_LIBBACKTRACE || HAVE_EXECINFO_H
print_stack_trace (stderr);
#endif
raise (SIGABRT);
# 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,
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
])