1
0
mirror of https://https.git.savannah.gnu.org/git/gnulib.git synced 2026-05-13 15:13:36 +00:00

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.
This commit is contained in:
Bruno Haible
2024-07-18 04:04:23 +02:00
parent 5e21153328
commit 97897a6a42
12 changed files with 261 additions and 147 deletions

View File

@@ -1,3 +1,27 @@
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.

View File

@@ -300,7 +300,7 @@ Libraries
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

View File

@@ -21,66 +21,7 @@
#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

68
lib/stack-trace-impl.h Normal file
View File

@@ -0,0 +1,68 @@
/* 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

30
lib/stack-trace.c Normal file
View File

@@ -0,0 +1,30 @@
/* 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
}

View File

@@ -255,14 +255,6 @@ _GL_CXXALIAS_SYS (abort, void, (void));
_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@
@@ -1608,6 +1600,15 @@ _GL_WARN_ON_USE (setenv, "setenv is unportable - "
# 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@

View File

@@ -1,81 +1,16 @@
# 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_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
fi
])
AC_DEFUN([gl_ABORT_DEBUG],
[
AC_REQUIRE([AC_C_INLINE])
AC_REQUIRE([gl_STDLIB_H_DEFAULTS])
AC_REQUIRE([gl_STACK_TRACE_EARLY])
if test $CAN_PRINT_STACK_TRACE = 1; then
REPLACE_ABORT=1
AC_REQUIRE([AC_C_INLINE])
fi
])

81
m4/stack-trace.m4 Normal file
View File

@@ -0,0 +1,81 @@
# 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])
])

View File

@@ -1,5 +1,5 @@
# 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,
@@ -146,6 +146,7 @@ AC_DEFUN([gl_STDLIB_H_REQUIRE_DEFAULTS],
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])
@@ -261,4 +262,5 @@ AC_DEFUN([gl_STDLIB_H_DEFAULTS],
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])
])

View File

@@ -7,11 +7,7 @@ m4/abort-debug.m4
Depends-on:
stdlib
execinfo
configure.ac-early:
AC_REQUIRE([gl_ABORT_DEBUG_EARLY])
export LDFLAGS
stack-trace
configure.ac:
gl_ABORT_DEBUG

34
modules/stack-trace Normal file
View File

@@ -0,0 +1,34 @@
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

View File

@@ -73,6 +73,7 @@ stdlib.h: stdlib.in.h $(top_builddir)/config.status $(CXXDEFS_H) \
-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' \
@@ -182,6 +183,7 @@ stdlib.h: stdlib.in.h $(top_builddir)/config.status $(CXXDEFS_H) \
-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)' \