+2024-07-17 Bruno Haible <bruno@clisp.org>
+
+ stack-trace: New module.
+ * lib/stdlib.in.h (print_stack_trace): Make part of the stack-trace
+ module.
+ * lib/stack-trace-impl.h: New file, based on lib/abort-debug.c.
+ * lib/stack-trace.c: New file, based on lib/abort-debug.c.
+ * lib/abort-debug.c: Include stack-trace-impl.h. Remove definitions
+ moved to stack-trace-impl.h.
+ (print_stack_trace): Remove function.
+ * m4/stdlib_h.m4 (gl_STDLIB_H_REQUIRE_DEFAULTS): Initialize
+ GNULIB_STACK_TRACE.
+ (gl_STDLIB_H_DEFAULTS): Initialize CAN_PRINT_STACK_TRACE.
+ * m4/stack-trace.m4: New file, based on m4/abort-debug.m4.
+ * m4/abort-debug.m4 (gl_ABORT_DEBUG_EARLY): Remove macro.
+ (gl_ABORT_DEBUG): Require gl_STDLIB_H_DEFAULTS, gl_STACK_TRACE_EARLY.
+ Set REPLACE_ABORT here.
+ * modules/stdlib (Makefile.am): Substitute GNULIB_STACK_TRACE,
+ CAN_PRINT_STACK_TRACE.
+ * modules/stack-trace: New file.
+ * modules/abort-debug (Depends-on): Add stack-trace. Remove execinfo.
+ (configure.ac-early): Remove section.
+ * DEPENDENCIES: Update.
+
2024-07-17 Bruno Haible <bruno@clisp.org>
abort-debug: Export the print_stack_trace function.
Various modules work best with certain libraries installed. These are runtime
dependencies that are also build dependencies.
-For module 'abort-debug':
+For modules 'abort-debug' and 'stack-trace':
* libbacktrace
+ Recommended.
Needed for producing C stack traces with source file names and
#include <signal.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_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");
- backtrace_print (state, 0, stream);
-}
-
-#elif HAVE_EXECINFO_H
-
-# include <stdio.h>
-
-# include "execinfo.h"
-
-static inline void
-# if (__GNUC__ >= 3) || (__clang_major__ >= 4)
-__attribute__ ((always_inline))
-# endif
-print_stack_trace_to (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
-print_stack_trace (void)
-{
-#if HAVE_LIBBACKTRACE || HAVE_EXECINFO_H
- print_stack_trace_to (stderr);
-#endif
-}
+#include "stack-trace-impl.h"
/* rpl_abort ();
is equivalent to
--- /dev/null
+/* print_stack_trace() function that prints a stack trace.
+ 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 <https://www.gnu.org/licenses/>. */
+
+#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_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");
+ backtrace_print (state, 0, stream);
+}
+
+#elif HAVE_EXECINFO_H
+
+# include <stdio.h>
+
+# include "execinfo.h"
+
+static inline void
+# if (__GNUC__ >= 3) || (__clang_major__ >= 4)
+__attribute__ ((always_inline))
+# endif
+print_stack_trace_to (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
--- /dev/null
+/* print_stack_trace() function that prints a stack trace.
+ 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 <https://www.gnu.org/licenses/>. */
+
+#include <config.h>
+
+/* Specification. */
+#include <stdlib.h>
+
+#include "stack-trace-impl.h"
+
+void
+print_stack_trace (void)
+{
+#if HAVE_LIBBACKTRACE || HAVE_EXECINFO_H
+ print_stack_trace_to (stderr);
+#endif
+}
_GL_CXXALIASWARN (abort);
# endif
#endif
-#if @GNULIB_ABORT_DEBUG@ && @REPLACE_ABORT@
-_GL_EXTERN_C void print_stack_trace (void);
-#else
-# if !GNULIB_defined_print_stack_trace
-# define print_stack_trace() /* nothing */
-# define GNULIB_defined_print_stack_trace 1
-# endif
-#endif
#if @GNULIB_FREE_POSIX@
# endif
#endif
+#if @GNULIB_STACK_TRACE@ && @CAN_PRINT_STACK_TRACE@
+_GL_EXTERN_C void print_stack_trace (void);
+#else
+# if !GNULIB_defined_print_stack_trace
+# define print_stack_trace() /* nothing */
+# define GNULIB_defined_print_stack_trace 1
+# endif
+#endif
+
#if @GNULIB_STRTOD@
/* Parse a double from STRING, updating ENDP if appropriate. */
# if @REPLACE_STRTOD@
# abort-debug.m4
-# serial 2
+# serial 3
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_DEFUN([gl_ABORT_DEBUG],
[
- 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
- 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
+ AC_REQUIRE([gl_STACK_TRACE_EARLY])
+ if test $CAN_PRINT_STACK_TRACE = 1; then
+ REPLACE_ABORT=1
+ AC_REQUIRE([AC_C_INLINE])
fi
])
-
-AC_DEFUN([gl_ABORT_DEBUG],
-[
- AC_REQUIRE([AC_C_INLINE])
-])
--- /dev/null
+# stack-trace.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_STACK_TRACE_EARLY],
+[
+ AC_MSG_CHECKING([whether to enable debugging facilities])
+ AC_ARG_ENABLE([debug],
+ [AS_HELP_STRING([[--disable-debug]],
+ [turn off debugging facilities])],
+ [case "$enableval" in
+ yes | no) ;;
+ *) AC_MSG_WARN([invalid argument supplied to --enable-debug])
+ enable_debug=yes
+ ;;
+ esac
+ ],
+ [enable_debug=yes])
+ AC_MSG_RESULT([$enable_debug])
+
+ AC_REQUIRE([gl_STDLIB_H_DEFAULTS])
+ if test $enable_debug = yes; then
+ 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.])
+ 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
+ fi
+ fi
+])
+
+AC_DEFUN([gl_STACK_TRACE],
+[
+ AC_REQUIRE([AC_C_INLINE])
+])
# stdlib_h.m4
-# serial 78
+# serial 79
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,
gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_RPMATCH])
gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_SECURE_GETENV])
gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_SETENV])
+ gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_STACK_TRACE])
gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_STRTOD])
gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_STRTOF])
gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_STRTOL])
REPLACE_STRTOULL=0; AC_SUBST([REPLACE_STRTOULL])
REPLACE_UNSETENV=0; AC_SUBST([REPLACE_UNSETENV])
REPLACE_WCTOMB=0; AC_SUBST([REPLACE_WCTOMB])
+ CAN_PRINT_STACK_TRACE=0; AC_SUBST([CAN_PRINT_STACK_TRACE])
])
Depends-on:
stdlib
-execinfo
-
-configure.ac-early:
-AC_REQUIRE([gl_ABORT_DEBUG_EARLY])
-export LDFLAGS
+stack-trace
configure.ac:
gl_ABORT_DEBUG
--- /dev/null
+Description:
+print_stack_trace() function that prints a stack trace.
+
+Files:
+lib/stack-trace-impl.h
+lib/stack-trace.c
+m4/stack-trace.m4
+
+Depends-on:
+stdlib
+execinfo
+
+configure.ac-early:
+AC_REQUIRE([gl_STACK_TRACE_EARLY])
+export LDFLAGS
+
+configure.ac:
+gl_STACK_TRACE
+gl_CONDITIONAL([GL_COND_OBJ_STACK_TRACE], [test $CAN_PRINT_STACK_TRACE = 1])
+gl_STDLIB_MODULE_INDICATOR([stack-trace])
+
+Makefile.am:
+if GL_COND_OBJ_STACK_TRACE
+lib_SOURCES += stack-trace.c
+endif
+
+Include:
+<stdlib.h>
+
+License:
+LGPLv2+
+
+Maintainer:
+all
-e 's/@''GNULIB_RPMATCH''@/$(GNULIB_RPMATCH)/g' \
-e 's/@''GNULIB_SECURE_GETENV''@/$(GNULIB_SECURE_GETENV)/g' \
-e 's/@''GNULIB_SETENV''@/$(GNULIB_SETENV)/g' \
+ -e 's/@''GNULIB_STACK_TRACE''@/$(GNULIB_STACK_TRACE)/g' \
-e 's/@''GNULIB_STRTOD''@/$(GNULIB_STRTOD)/g' \
-e 's/@''GNULIB_STRTOF''@/$(GNULIB_STRTOF)/g' \
-e 's/@''GNULIB_STRTOL''@/$(GNULIB_STRTOL)/g' \
-e 's|@''REPLACE_STRTOULL''@|$(REPLACE_STRTOULL)|g' \
-e 's|@''REPLACE_UNSETENV''@|$(REPLACE_UNSETENV)|g' \
-e 's|@''REPLACE_WCTOMB''@|$(REPLACE_WCTOMB)|g' \
+ -e 's|@''CAN_PRINT_STACK_TRACE''@|$(CAN_PRINT_STACK_TRACE)|g' \
-e '/definitions of _GL_FUNCDECL_RPL/r $(CXXDEFS_H)' \
-e '/definition of _Noreturn/r $(_NORETURN_H)' \
-e '/definition of _GL_ARG_NONNULL/r $(ARG_NONNULL_H)' \