From: Bruno Haible Date: Sun, 19 May 2024 13:55:21 +0000 (+0200) Subject: abort-debug: Prefer libbacktrace to execinfo. X-Git-Url: https://gitweb.git.savannah.gnu.org/gitweb/?a=commitdiff_plain;h=55d036b9db33c5f40ad636ed6ebb83d906157c37;p=gnulib.git abort-debug: Prefer libbacktrace to execinfo. * lib/abort-debug.c: Include . (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/ChangeLog b/ChangeLog index a4ed70af32..1e8cc94054 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,13 @@ +2024-05-18 Bruno Haible + + abort-debug: Prefer libbacktrace to execinfo. + * lib/abort-debug.c: Include . + (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 mkfifoat: Work around a macOS 14 bug. 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 -#if HAVE_EXECINFO_H +#if HAVE_LIBBACKTRACE + +# include + +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 . */ + fprintf (stream, "Stack trace:\n"); + backtrace_print (state, 0, stream); +} + +#elif HAVE_EXECINFO_H # include @@ -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 + ]], + [[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 ])