From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: by sourceware.org (Postfix, from userid 1720) id 4D2E73858413; Wed, 31 Aug 2022 18:55:14 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 4D2E73858413 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gcc.gnu.org; s=default; t=1661972114; bh=QBqoHGbzfFtc0rrvY2QW6dTk7kPVNf1e7dRC0mzJpPU=; h=From:To:Subject:Date:From; b=TAo6iNbhkBvtD2NGm3VamuoSB6WOCRyLFB48hQeWsWPrUxrOGMjWzB9iO11CVIWJT 7G5MWvru7yNyjgU/1OkWXIEJGoq2uyAmgEo5YduIbLOYaxmLJQUI7jXUFJJCkmZw+L IewA1At3tbC+Ch3TLDLqFlCfDzK6JB/eg6iw4gNU= MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Content-Type: text/plain; charset="utf-8" From: =?utf-8?b?RnJhbuCkpeCkiG9pcyBEdW1vbnQ=?= To: gcc-cvs@gcc.gnu.org, libstdc++-cvs@gcc.gnu.org Subject: [gcc r13-2316] libstdc++: [_GLIBCXX_DEBUG] Add backtrace generation on demand X-Act-Checkin: gcc X-Git-Author: =?utf-8?q?Fran=C3=A7ois_Dumont?= X-Git-Refname: refs/heads/master X-Git-Oldrev: de9805c08121a84ce368dccfe043a3f44c3ff13b X-Git-Newrev: 4d5660907c2b4c301fcbdc3dc713879fa31afec0 Message-Id: <20220831185514.4D2E73858413@sourceware.org> Date: Wed, 31 Aug 2022 18:55:14 +0000 (GMT) List-Id: https://gcc.gnu.org/g:4d5660907c2b4c301fcbdc3dc713879fa31afec0 commit r13-2316-g4d5660907c2b4c301fcbdc3dc713879fa31afec0 Author: François Dumont Date: Tue Jan 21 19:33:15 2020 +0100 libstdc++: [_GLIBCXX_DEBUG] Add backtrace generation on demand Add _GLIBCXX_DEBUG_BACKTRACE macro to activate backtrace generation on _GLIBCXX_DEBUG assertions. Prerequisite is to have configure the lib with: --enable-libstdcxx-backtrace=yes libstdc++-v3/ChangeLog: * include/debug/formatter.h [_GLIBCXX_HAVE_STACKTRACE](__glibcxx_backtrace_state): Declare. [_GLIBCXX_HAVE_STACKTRACE](__glibcxx_backtrace_create_state): Declare. [_GLIBCXX_HAVE_STACKTRACE](__glibcxx_backtrace_full_callback): Define. [_GLIBCXX_HAVE_STACKTRACE](__glibcxx_backtrace_error_callback): Define. [_GLIBCXX_HAVE_STACKTRACE](__glibcxx_backtrace_full_func): Define. [_GLIBCXX_HAVE_STACKTRACE](__glibcxx_backtrace_full): Declare. [_GLIBCXX_HAVE_STACKTRACE](_Error_formatter::_M_backtrace_state): New. [_GLIBCXX_HAVE_STACKTRACE](_Error_formatter::_M_backtrace_full): New. * src/c++11/debug.cc [_GLIBCXX_HAVE_STACKTRACE](print_backtrace): New. (_Error_formatter::_M_error()): Adapt. * src/libbacktrace/Makefile.am: Add backtrace.c. * src/libbacktrace/Makefile.in: Regenerate. * src/libbacktrace/backtrace-rename.h (backtrace_full): New. * testsuite/23_containers/vector/debug/assign4_backtrace_neg.cc: New test. * doc/xml/manual/debug_mode.xml: Document _GLIBCXX_DEBUG_BACKTRACE. * doc/xml/manual/using.xml: Likewise. Diff: --- libstdc++-v3/doc/xml/manual/debug_mode.xml | 6 ++ libstdc++-v3/doc/xml/manual/using.xml | 10 +++ libstdc++-v3/include/debug/formatter.h | 44 +++++++++++++ libstdc++-v3/src/c++11/debug.cc | 75 ++++++++++++++++++++-- libstdc++-v3/src/libbacktrace/Makefile.am | 1 + libstdc++-v3/src/libbacktrace/Makefile.in | 12 ++-- libstdc++-v3/src/libbacktrace/backtrace-rename.h | 1 + .../vector/debug/assign4_backtrace_neg.cc | 17 +++++ 8 files changed, 157 insertions(+), 9 deletions(-) diff --git a/libstdc++-v3/doc/xml/manual/debug_mode.xml b/libstdc++-v3/doc/xml/manual/debug_mode.xml index 988c4a93601..dadc0cd1bb4 100644 --- a/libstdc++-v3/doc/xml/manual/debug_mode.xml +++ b/libstdc++-v3/doc/xml/manual/debug_mode.xml @@ -161,6 +161,12 @@ which always works correctly. GLIBCXX_DEBUG_MESSAGE_LENGTH can be used to request a different length. +Note that libstdc++ is able to produce backtraces on error. + It requires that you configure libstdc++ build with + . + Use -D_GLIBCXX_DEBUG_BACKTRACE to activate it. + You'll then have to link with libstdc++_libbacktrace static library + () to build your application.
Using a Specific Debug Container diff --git a/libstdc++-v3/doc/xml/manual/using.xml b/libstdc++-v3/doc/xml/manual/using.xml index 0b9a0c98518..0acdba6b3bd 100644 --- a/libstdc++-v3/doc/xml/manual/using.xml +++ b/libstdc++-v3/doc/xml/manual/using.xml @@ -1144,6 +1144,15 @@ g++ -Winvalid-pch -I. -include stdc++.h -H -g -O2 hello.cc -o test.exe extensions and libstdc++-specific behavior into errors. + _GLIBCXX_DEBUG_BACKTRACE + + + Undefined by default. Considered only if libstdc++ has been configured with + and if _GLIBCXX_DEBUG + is defined. When defined display backtraces on + debug mode assertions. + + _GLIBCXX_PARALLEL Undefined by default. When defined, compiles user code @@ -1650,6 +1659,7 @@ A quick read of the relevant part of the GCC header will remain compatible between different GCC releases.
+
Concurrency diff --git a/libstdc++-v3/include/debug/formatter.h b/libstdc++-v3/include/debug/formatter.h index 748d4fbfea4..b4b72383e22 100644 --- a/libstdc++-v3/include/debug/formatter.h +++ b/libstdc++-v3/include/debug/formatter.h @@ -31,6 +31,37 @@ #include +#if _GLIBCXX_HAVE_STACKTRACE +struct __glibcxx_backtrace_state; + +extern "C" +{ + __glibcxx_backtrace_state* + __glibcxx_backtrace_create_state(const char*, int, + void(*)(void*, const char*, int), + void*); + + typedef int (*__glibcxx_backtrace_full_callback) ( + void*, __UINTPTR_TYPE__, const char *, int, const char*); + + typedef void (*__glibcxx_backtrace_error_callback) ( + void*, const char*, int); + + typedef int (*__glibcxx_backtrace_full_func) ( + __glibcxx_backtrace_state*, int, + __glibcxx_backtrace_full_callback, + __glibcxx_backtrace_error_callback, + void*); + + int + __glibcxx_backtrace_full( + __glibcxx_backtrace_state*, int, + __glibcxx_backtrace_full_callback, + __glibcxx_backtrace_error_callback, + void*); +} +#endif + #if __cpp_rtti # include # define _GLIBCXX_TYPEID(_Type) &typeid(_Type) @@ -576,6 +607,15 @@ namespace __gnu_debug const char* __function) : _M_file(__file), _M_line(__line), _M_num_parameters(0), _M_text(0) , _M_function(__function) +#if _GLIBCXX_HAVE_STACKTRACE +# ifdef _GLIBCXX_DEBUG_BACKTRACE + , _M_backtrace_state( + __glibcxx_backtrace_create_state(nullptr, 0, nullptr, nullptr)) + , _M_backtrace_full(&__glibcxx_backtrace_full) +# else + , _M_backtrace_state() +# endif +#endif { } #if !_GLIBCXX_INLINE_VERSION @@ -591,6 +631,10 @@ namespace __gnu_debug unsigned int _M_num_parameters; const char* _M_text; const char* _M_function; +#if _GLIBCXX_HAVE_STACKTRACE + __glibcxx_backtrace_state* _M_backtrace_state; + __glibcxx_backtrace_full_func _M_backtrace_full; +#endif public: static _Error_formatter& diff --git a/libstdc++-v3/src/c++11/debug.cc b/libstdc++-v3/src/c++11/debug.cc index 8ed61a69913..abc4124c01e 100644 --- a/libstdc++-v3/src/c++11/debug.cc +++ b/libstdc++-v3/src/c++11/debug.cc @@ -611,10 +611,12 @@ namespace void print_raw(PrintContext& ctx, const char* str, ptrdiff_t nbc = -1) { - if (nbc >= 0) - ctx._M_column += fprintf(stderr, "%.*s", (int)nbc, str); - else - ctx._M_column += fprintf(stderr, "%s", str); + if (nbc != 0) + { + ctx._M_column += (nbc > 0) + ? fprintf(stderr, "%.*s", (int)nbc, str) + : fprintf(stderr, "%s", str); + } } void @@ -680,7 +682,7 @@ namespace pos += 2; // advance past "__" if (memcmp(pos, cxx1998, 9) == 0) - pos += 9; // advance part "cxx1998::" + pos += 9; // advance past "cxx1998::" str = pos; } @@ -1093,6 +1095,58 @@ namespace void print_string(PrintContext& ctx, const char* str, ptrdiff_t nbc) { print_string(ctx, str, nbc, nullptr, 0); } + +#if _GLIBCXX_HAVE_STACKTRACE + int + print_backtrace(void* data, __UINTPTR_TYPE__ pc, const char* filename, + int lineno, const char* function) + { + const int bufsize = 64; + char buf[bufsize]; + + PrintContext& ctx = *static_cast(data); + + int written = __builtin_sprintf(buf, "%p ", (void*)pc); + print_word(ctx, buf, written); + + int ret = 0; + if (function) + { + int status; + char* demangled_name = + __cxxabiv1::__cxa_demangle(function, NULL, NULL, &status); + if (status == 0) + pretty_print(ctx, demangled_name, &print_raw); + else + print_word(ctx, function); + + free(demangled_name); + ret = strstr(function, "main") ? 1 : 0; + } + + print_literal(ctx, "\n"); + + if (filename) + { + bool wordwrap = false; + swap(wordwrap, ctx._M_wordwrap); + print_word(ctx, filename); + + if (lineno) + { + written = __builtin_sprintf(buf, ":%u\n", lineno); + print_word(ctx, buf, written); + } + else + print_literal(ctx, "\n"); + swap(wordwrap, ctx._M_wordwrap); + } + else + print_literal(ctx, "???:0\n"); + + return ret; + } +#endif } namespace __gnu_debug @@ -1139,6 +1193,17 @@ namespace __gnu_debug print_literal(ctx, "\n"); } +#if _GLIBCXX_HAVE_STACKTRACE + if (_M_backtrace_state) + { + print_literal(ctx, "Backtrace:\n"); + _M_backtrace_full( + _M_backtrace_state, 1, print_backtrace, nullptr, &ctx); + ctx._M_first_line = true; + print_literal(ctx, "\n"); + } +#endif + print_literal(ctx, "Error: "); // Print the error message diff --git a/libstdc++-v3/src/libbacktrace/Makefile.am b/libstdc++-v3/src/libbacktrace/Makefile.am index 0f1143507f3..52d8f81b97b 100644 --- a/libstdc++-v3/src/libbacktrace/Makefile.am +++ b/libstdc++-v3/src/libbacktrace/Makefile.am @@ -60,6 +60,7 @@ libstdc___libbacktrace_la_SHORTNAME = $(obj_prefix) libstdc___libbacktrace_la_SOURCES = \ atomic.c \ + backtrace.c \ dwarf.c \ fileline.c \ posix.c \ diff --git a/libstdc++-v3/src/libbacktrace/Makefile.in b/libstdc++-v3/src/libbacktrace/Makefile.in index 7545894d59a..5c6b4dd1a0c 100644 --- a/libstdc++-v3/src/libbacktrace/Makefile.in +++ b/libstdc++-v3/src/libbacktrace/Makefile.in @@ -181,10 +181,10 @@ am__uninstall_files_from_dir = { \ am__installdirs = "$(DESTDIR)$(toolexeclibdir)" LTLIBRARIES = $(toolexeclib_LTLIBRARIES) am_libstdc___libbacktrace_la_OBJECTS = $(obj_prefix)-atomic.lo \ - $(obj_prefix)-dwarf.lo $(obj_prefix)-fileline.lo \ - $(obj_prefix)-posix.lo $(obj_prefix)-sort.lo \ - $(obj_prefix)-simple.lo $(obj_prefix)-state.lo \ - $(obj_prefix)-cp-demangle.lo + $(obj_prefix)-backtrace.lo $(obj_prefix)-dwarf.lo \ + $(obj_prefix)-fileline.lo $(obj_prefix)-posix.lo \ + $(obj_prefix)-sort.lo $(obj_prefix)-simple.lo \ + $(obj_prefix)-state.lo $(obj_prefix)-cp-demangle.lo libstdc___libbacktrace_la_OBJECTS = \ $(am_libstdc___libbacktrace_la_OBJECTS) AM_V_lt = $(am__v_lt_@AM_V@) @@ -507,6 +507,7 @@ obj_prefix = std_stacktrace libstdc___libbacktrace_la_SHORTNAME = $(obj_prefix) libstdc___libbacktrace_la_SOURCES = \ atomic.c \ + backtrace.c \ dwarf.c \ fileline.c \ posix.c \ @@ -647,6 +648,9 @@ distclean-compile: $(obj_prefix)-atomic.lo: atomic.c $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libstdc___libbacktrace_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o $(obj_prefix)-atomic.lo `test -f 'atomic.c' || echo '$(srcdir)/'`atomic.c +$(obj_prefix)-backtrace.lo: backtrace.c + $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libstdc___libbacktrace_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o $(obj_prefix)-backtrace.lo `test -f 'backtrace.c' || echo '$(srcdir)/'`backtrace.c + $(obj_prefix)-dwarf.lo: dwarf.c $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libstdc___libbacktrace_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o $(obj_prefix)-dwarf.lo `test -f 'dwarf.c' || echo '$(srcdir)/'`dwarf.c diff --git a/libstdc++-v3/src/libbacktrace/backtrace-rename.h b/libstdc++-v3/src/libbacktrace/backtrace-rename.h index 7a59f166e62..79bdef6309f 100644 --- a/libstdc++-v3/src/libbacktrace/backtrace-rename.h +++ b/libstdc++-v3/src/libbacktrace/backtrace-rename.h @@ -4,6 +4,7 @@ #define backtrace_create_state __glibcxx_backtrace_create_state #define backtrace_dwarf_add __glibcxx_backtrace_dwarf_add #define backtrace_free __glibcxx_backtrace_free +#define backtrace_full __glibcxx_backtrace_full #define backtrace_get_view __glibcxx_backtrace_get_view #define backtrace_initialize __glibcxx_backtrace_initialize #define backtrace_open __glibcxx_backtrace_open diff --git a/libstdc++-v3/testsuite/23_containers/vector/debug/assign4_backtrace_neg.cc b/libstdc++-v3/testsuite/23_containers/vector/debug/assign4_backtrace_neg.cc new file mode 100644 index 00000000000..520788d5cb7 --- /dev/null +++ b/libstdc++-v3/testsuite/23_containers/vector/debug/assign4_backtrace_neg.cc @@ -0,0 +1,17 @@ +// { dg-do run { xfail *-*-* } } +// { dg-options "-D_GLIBCXX_DEBUG_BACKTRACE -lstdc++_libbacktrace" } +// { dg-require-effective-target stacktrace } + +#include +#include + +void test01() +{ + __gnu_test::check_assign1<__gnu_debug::vector >(); +} + +int main() +{ + test01(); + return 0; +}