diff --git a/libstdc++-v3/include/debug/formatter.h b/libstdc++-v3/include/debug/formatter.h index 80e8ba46d1e..f77912c3fd2 100644 --- a/libstdc++-v3/include/debug/formatter.h +++ b/libstdc++-v3/include/debug/formatter.h @@ -31,6 +31,30 @@ #include +struct __glibcxx_backtrace_state; + +#if _GLIBCXX_HAVE_STACKTRACE +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); + + 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) @@ -560,11 +584,25 @@ namespace __gnu_debug _M_print_string(const char* __string) const _GLIBCXX_DEPRECATED; #endif +#if _GLIBCXX_HAVE_STACKTRACE + int + _M_backtrace_full(__glibcxx_backtrace_state* __st, int __skip, + __glibcxx_backtrace_full_callback __cb, + __glibcxx_backtrace_error_callback __ecb, + void* __data) const; +#endif + private: _Error_formatter(const char* __file, unsigned int __line, const char* __function) : _M_file(__file), _M_line(__line), _M_num_parameters(0), _M_text(0) , _M_function(__function) +#if _GLIBCXX_HAVE_STACKTRACE + , _M_backtrace_state( + __glibcxx_backtrace_create_state(nullptr, 0, nullptr, nullptr)) +#else + , _M_backtrace_state() +#endif { } #if !_GLIBCXX_INLINE_VERSION @@ -580,6 +618,7 @@ namespace __gnu_debug unsigned int _M_num_parameters; const char* _M_text; const char* _M_function; + __glibcxx_backtrace_state* _M_backtrace_state; public: static _Error_formatter& @@ -589,6 +628,16 @@ namespace __gnu_debug return __formatter; } }; + +#if _GLIBCXX_HAVE_STACKTRACE + int + _Error_formatter::_M_backtrace_full(__glibcxx_backtrace_state* __st, int __skip, + __glibcxx_backtrace_full_callback __cb, + __glibcxx_backtrace_error_callback __ecb, + void* __data) const + { return __glibcxx_backtrace_full(__st, __skip, __cb, __ecb, __data); } +#endif + } // namespace __gnu_debug #undef _GLIBCXX_TYPEID diff --git a/libstdc++-v3/src/c++11/debug.cc b/libstdc++-v3/src/c++11/debug.cc index 4706defedf1..39ecc7817b7 100644 --- a/libstdc++-v3/src/c++11/debug.cc +++ b/libstdc++-v3/src/c++11/debug.cc @@ -607,12 +607,12 @@ namespace { print_word(ctx, word, Length - 1); } void - print_raw(PrintContext& ctx, const char* str, ptrdiff_t nbc = -1) + print_raw(PrintContext&, const char* str, ptrdiff_t nbc) { if (nbc >= 0) - ctx._M_column += fprintf(stderr, "%.*s", (int)nbc, str); + fprintf(stderr, "%.*s", (int)nbc, str); else - ctx._M_column += fprintf(stderr, "%s", str); + fprintf(stderr, "%s", str); } void @@ -646,6 +646,7 @@ namespace { const char spacing[PrintContext::_S_indent + 1] = " "; print_raw(ctx, spacing, PrintContext::_S_indent); + ctx._M_column += PrintContext::_S_indent; } int written = fprintf(stderr, "%.*s", (int)length, word); @@ -666,25 +667,35 @@ namespace } void - pretty_print(PrintContext& ctx, const char* str, _Print_func_t print_func) + print_function(PrintContext& ctx, const char* func, _Print_func_t print_func) { - const char cxx1998[] = "cxx1998::"; + const char cxx1998[] = "__cxx1998::"; + const char uglification[] = "__"; for (;;) { - if (auto pos = strstr(str, "__")) + size_t offset; + auto idx = strstr(func, cxx1998); + if (idx) + offset = sizeof(cxx1998) - 1; + else if ((idx = strstr(func, uglification))) + offset = sizeof(uglification) - 1; + + if (idx) { - if (pos != str) - print_func(ctx, str, pos - str); + if (idx != func) + print_func(ctx, func, idx - func); - pos += 2; // advance past "__" - if (memcmp(pos, cxx1998, 9) == 0) - pos += 9; // advance part "cxx1998::" + func = idx + offset; - str = pos; + while (*func && isspace((unsigned char)*func)) + ++func; + + if (!*func) + break; } else { - print_func(ctx, str, -1); + print_func(ctx, func, -1); break; } } @@ -704,9 +715,9 @@ namespace char* demangled_name = __cxxabiv1::__cxa_demangle(info->name(), NULL, NULL, &status); if (status == 0) - pretty_print(ctx, demangled_name, &print_word); + print_function(ctx, demangled_name, &print_word); else - print_word(ctx, info->name()); + print_word(ctx, info->name(), -1); free(demangled_name); } } @@ -735,7 +746,7 @@ namespace print_named_name(PrintContext& ctx, const _Parameter::_Named& named) { assert(named._M_name); - pretty_print(ctx, named._M_name, print_word); + print_function(ctx, named._M_name, print_word); } template @@ -1036,7 +1047,7 @@ namespace // first. if (str != start) { - // Avoid printing the '%'. + // Avoid to print the '%'. if (str - start > 1) print_word(ctx, start, str - start - 1); start = str; @@ -1090,6 +1101,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) + print_function(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 @@ -1109,7 +1172,7 @@ namespace __gnu_debug PrintContext ctx; if (_M_file) { - print_raw(ctx, _M_file); + print_raw(ctx, _M_file, -1); print_literal(ctx, ":"); go_to_next_line = true; } @@ -1130,12 +1193,23 @@ namespace __gnu_debug if (_M_function) { print_literal(ctx, "In function:\n"); - pretty_print(ctx, _M_function, &print_string); + print_function(ctx, _M_function, &print_string); print_literal(ctx, "\n"); ctx._M_first_line = true; 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_neg.cc b/libstdc++-v3/testsuite/23_containers/vector/debug/assign4_neg.cc index 7ab658d0ba1..83dd67b352a 100644 --- a/libstdc++-v3/testsuite/23_containers/vector/debug/assign4_neg.cc +++ b/libstdc++-v3/testsuite/23_containers/vector/debug/assign4_neg.cc @@ -15,6 +15,7 @@ // with this library; see the file COPYING3. If not see // . // +// { dg-options "-lstdc++_libbacktrace" } // { dg-do run { xfail *-*-* } } #include