From: Bruno Haible Date: Fri, 17 May 2024 20:05:46 +0000 (+0200) Subject: New module 'abort-debug'. X-Git-Url: https://gitweb.git.savannah.gnu.org/gitweb/?a=commitdiff_plain;h=cf692362ba3ac21a9553e88b37fa9f0b4d73f7af;p=gnulib.git New module 'abort-debug'. * lib/stdlib.in.h (abort): New declaration. * lib/abort-debug.c: New file. * m4/abort-debug.m4: New file. * modules/abort-debug: New file. * m4/stdlib_h.m4 (gl_STDLIB_H_REQUIRE_DEFAULTS): Initialize GNULIB_ABORT_DEBUG. (gl_STDLIB_H_DEFAULTS): Initialize REPLACE_ABORT. * modules/stdlib (Makefile.am): Substitute GNULIB_ABORT_DEBUG, REPLACE_ABORT. --- diff --git a/ChangeLog b/ChangeLog index 40c8667ea4..25c95d2aba 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,16 @@ +2024-05-17 Bruno Haible + + New module 'abort-debug'. + * lib/stdlib.in.h (abort): New declaration. + * lib/abort-debug.c: New file. + * m4/abort-debug.m4: New file. + * modules/abort-debug: New file. + * m4/stdlib_h.m4 (gl_STDLIB_H_REQUIRE_DEFAULTS): Initialize + GNULIB_ABORT_DEBUG. + (gl_STDLIB_H_DEFAULTS): Initialize REPLACE_ABORT. + * modules/stdlib (Makefile.am): Substitute GNULIB_ABORT_DEBUG, + REPLACE_ABORT. + 2024-05-17 Bruno Haible execinfo: Update doc. diff --git a/lib/abort-debug.c b/lib/abort-debug.c new file mode 100644 index 0000000000..2ca8f81169 --- /dev/null +++ b/lib/abort-debug.c @@ -0,0 +1,65 @@ +/* abort() function that prints a stack trace before aborting. + Copyright (C) 2024 Free Software Foundation, Inc. + + This file is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of the + License, or (at your option) any later version. + + This file is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . */ + +#include + +/* Specification. */ +#include + +#include + +#if HAVE_EXECINFO_H + +# include + +# include "execinfo.h" + +static inline void +# if (__GNUC__ >= 3) || (__clang_major__ >= 4) +__attribute__ ((always_inline)) +# endif +print_stack_trace (FILE *stream) +{ + void *buffer[100]; + int max_size = sizeof (buffer) / sizeof (buffer[0]); + int size = backtrace (buffer, max_size); + if (size > 0) + { + char **symbols = backtrace_symbols (buffer, size); + if (symbols != NULL) + { + int i; + + fprintf (stream, "Stack trace:\n"); + for (i = 0; i < size; i++) + fprintf (stream, "%s\n", symbols[i]); + fflush (stream); + + free (symbols); + } + } +} + +#endif + +void +rpl_abort (void) +{ +#if HAVE_EXECINFO_H + print_stack_trace (stderr); +#endif + raise (SIGABRT); +} diff --git a/lib/stdlib.in.h b/lib/stdlib.in.h index e74e7c18d1..1888d3ee31 100644 --- a/lib/stdlib.in.h +++ b/lib/stdlib.in.h @@ -216,6 +216,23 @@ _GL_WARN_ON_USE (_Exit, "_Exit is unportable - " #endif +#if @GNULIB_ABORT_DEBUG@ +# if @REPLACE_ABORT@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef abort +# define abort rpl_abort +# endif +_GL_FUNCDECL_RPL (abort, _Noreturn void, (void)); +_GL_CXXALIAS_RPL (abort, void, (void)); +# else +_GL_CXXALIAS_SYS (abort, void, (void)); +# endif +# if __GLIBC__ >= 2 +_GL_CXXALIASWARN (abort); +# endif +#endif + + #if @GNULIB_FREE_POSIX@ # if @REPLACE_FREE@ # if !(defined __cplusplus && defined GNULIB_NAMESPACE) diff --git a/m4/abort-debug.m4 b/m4/abort-debug.m4 new file mode 100644 index 0000000000..e819d58dcb --- /dev/null +++ b/m4/abort-debug.m4 @@ -0,0 +1,52 @@ +# abort-debug.m4 +# serial 1 +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, +dnl with or without modifications, as long as this notice is preserved. + +AC_DEFUN([gl_ABORT_DEBUG_EARLY], +[ + AC_MSG_CHECKING([whether to enable debugging facilities on abort]) + AC_ARG_ENABLE([debug-abort], + [AS_HELP_STRING([[--disable-debug-abort]], + [turn off debugging facilities])], + [case "$enableval" in + yes | no) ;; + *) AC_MSG_WARN([invalid argument supplied to --enable-debug-abort]) + enable_debug_abort=yes + ;; + esac + ], + [enable_debug_abort=yes]) + AC_MSG_RESULT([$enable_debug_abort]) + + 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 + fi +]) + +AC_DEFUN([gl_ABORT_DEBUG], +[ + AC_REQUIRE([AC_C_INLINE]) +]) diff --git a/m4/stdlib_h.m4 b/m4/stdlib_h.m4 index a4662f2995..bb5a646041 100644 --- a/m4/stdlib_h.m4 +++ b/m4/stdlib_h.m4 @@ -1,5 +1,5 @@ # stdlib_h.m4 -# serial 77 +# serial 78 dnl Copyright (C) 2007-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, @@ -110,6 +110,7 @@ AC_DEFUN([gl_STDLIB_H_REQUIRE_DEFAULTS], [ m4_defun(GL_MODULE_INDICATOR_PREFIX[_STDLIB_H_MODULE_INDICATOR_DEFAULTS], [ gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB__EXIT]) + gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_ABORT_DEBUG]) gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_ALIGNED_ALLOC]) gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_ATOLL]) gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_CALLOC_GNU]) @@ -218,6 +219,7 @@ AC_DEFUN([gl_STDLIB_H_DEFAULTS], HAVE_UNLOCKPT=1; AC_SUBST([HAVE_UNLOCKPT]) HAVE_DECL_UNSETENV=1; AC_SUBST([HAVE_DECL_UNSETENV]) REPLACE__EXIT=0; AC_SUBST([REPLACE__EXIT]) + REPLACE_ABORT=0; AC_SUBST([REPLACE_ABORT]) REPLACE_ALIGNED_ALLOC=0; AC_SUBST([REPLACE_ALIGNED_ALLOC]) REPLACE_CALLOC_FOR_CALLOC_GNU=0; AC_SUBST([REPLACE_CALLOC_FOR_CALLOC_GNU]) REPLACE_CALLOC_FOR_CALLOC_POSIX=0; AC_SUBST([REPLACE_CALLOC_FOR_CALLOC_POSIX]) diff --git a/modules/abort-debug b/modules/abort-debug new file mode 100644 index 0000000000..56cbdac5be --- /dev/null +++ b/modules/abort-debug @@ -0,0 +1,33 @@ +Description: +abort() function that prints a stack trace before aborting. + +Files: +lib/abort-debug.c +m4/abort-debug.m4 + +Depends-on: +stdlib +execinfo + +configure.ac-early: +AC_REQUIRE([gl_ABORT_DEBUG_EARLY]) +export LDFLAGS + +configure.ac: +gl_ABORT_DEBUG +gl_CONDITIONAL([GL_COND_OBJ_ABORT_DEBUG], [test $REPLACE_ABORT = 1]) +gl_STDLIB_MODULE_INDICATOR([abort-debug]) + +Makefile.am: +if GL_COND_OBJ_ABORT_DEBUG +lib_SOURCES += abort-debug.c +endif + +Include: + + +License: +LGPLv2+ + +Maintainer: +all diff --git a/modules/stdlib b/modules/stdlib index 7b0194db41..4e2b0ff32a 100644 --- a/modules/stdlib +++ b/modules/stdlib @@ -37,6 +37,7 @@ stdlib.h: stdlib.in.h $(top_builddir)/config.status $(CXXDEFS_H) \ -e 's|@''PRAGMA_COLUMNS''@|@PRAGMA_COLUMNS@|g' \ -e 's|@''NEXT_STDLIB_H''@|$(NEXT_STDLIB_H)|g' \ -e 's/@''GNULIB__EXIT''@/$(GNULIB__EXIT)/g' \ + -e 's/@''GNULIB_ABORT_DEBUG''@/$(GNULIB_ABORT_DEBUG)/g' \ -e 's/@''GNULIB_ALIGNED_ALLOC''@/$(GNULIB_ALIGNED_ALLOC)/g' \ -e 's/@''GNULIB_ATOLL''@/$(GNULIB_ATOLL)/g' \ -e 's/@''GNULIB_CALLOC_GNU''@/$(GNULIB_CALLOC_GNU)/g' \ @@ -139,6 +140,7 @@ stdlib.h: stdlib.in.h $(top_builddir)/config.status $(CXXDEFS_H) \ < $@-t1 > $@-t2 $(AM_V_at)sed \ -e 's|@''REPLACE__EXIT''@|$(REPLACE__EXIT)|g' \ + -e 's|@''REPLACE_ABORT''@|$(REPLACE_ABORT)|g' \ -e 's|@''REPLACE_ALIGNED_ALLOC''@|$(REPLACE_ALIGNED_ALLOC)|g' \ -e 's|@''REPLACE_CALLOC_FOR_CALLOC_GNU''@|$(REPLACE_CALLOC_FOR_CALLOC_GNU)|g' \ -e 's|@''REPLACE_CALLOC_FOR_CALLOC_POSIX''@|$(REPLACE_CALLOC_FOR_CALLOC_POSIX)|g' \