aboutsummaryrefslogtreecommitdiff
path: root/libstdc++-v3
diff options
context:
space:
mode:
authorFrançois Dumont <fdumont@gcc.gnu.org>2020-01-21 19:33:15 +0100
committerFrançois Dumont <fdumont@gcc.gnu.org>2022-08-31 20:51:10 +0200
commit4d5660907c2b4c301fcbdc3dc713879fa31afec0 (patch)
treef2e5a68fb76ea8103414dad8202aefe25c85a60e /libstdc++-v3
parentde9805c08121a84ce368dccfe043a3f44c3ff13b (diff)
downloadgcc-4d5660907c2b4c301fcbdc3dc713879fa31afec0.zip
gcc-4d5660907c2b4c301fcbdc3dc713879fa31afec0.tar.gz
gcc-4d5660907c2b4c301fcbdc3dc713879fa31afec0.tar.bz2
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.
Diffstat (limited to 'libstdc++-v3')
-rw-r--r--libstdc++-v3/doc/xml/manual/debug_mode.xml6
-rw-r--r--libstdc++-v3/doc/xml/manual/using.xml10
-rw-r--r--libstdc++-v3/include/debug/formatter.h44
-rw-r--r--libstdc++-v3/src/c++11/debug.cc75
-rw-r--r--libstdc++-v3/src/libbacktrace/Makefile.am1
-rw-r--r--libstdc++-v3/src/libbacktrace/Makefile.in12
-rw-r--r--libstdc++-v3/src/libbacktrace/backtrace-rename.h1
-rw-r--r--libstdc++-v3/testsuite/23_containers/vector/debug/assign4_backtrace_neg.cc17
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 988c4a9..dadc0cd 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.
<code>GLIBCXX_DEBUG_MESSAGE_LENGTH</code> can be used to request a
different length.</para>
+<para>Note that libstdc++ is able to produce backtraces on error.
+ It requires that you configure libstdc++ build with
+ <option>--enable-libstdcxx-backtrace=yes</option>.
+ Use <code>-D_GLIBCXX_DEBUG_BACKTRACE</code> to activate it.
+ You'll then have to link with libstdc++_libbacktrace static library
+ (<option>-lstdc++_libbacktrace</option>) to build your application.</para>
</section>
<section xml:id="debug_mode.using.specific" xreflabel="Using Specific"><info><title>Using a Specific Debug Container</title></info>
diff --git a/libstdc++-v3/doc/xml/manual/using.xml b/libstdc++-v3/doc/xml/manual/using.xml
index 0b9a0c9..0acdba6 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.
</para>
</listitem></varlistentry>
+ <varlistentry><term><code>_GLIBCXX_DEBUG_BACKTRACE</code></term>
+ <listitem>
+ <para>
+ Undefined by default. Considered only if libstdc++ has been configured with
+ <option>--enable-libstdcxx-backtrace=yes</option> and if <code>_GLIBCXX_DEBUG</code>
+ is defined. When defined display backtraces on
+ <link linkend="manual.ext.debug_mode">debug mode</link> assertions.
+ </para>
+ </listitem></varlistentry>
<varlistentry><term><code>_GLIBCXX_PARALLEL</code></term>
<listitem>
<para>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.
</para>
</section>
+
</section>
<section xml:id="manual.intro.using.concurrency" xreflabel="Concurrency"><info><title>Concurrency</title></info>
diff --git a/libstdc++-v3/include/debug/formatter.h b/libstdc++-v3/include/debug/formatter.h
index 748d4fb..b4b7238 100644
--- a/libstdc++-v3/include/debug/formatter.h
+++ b/libstdc++-v3/include/debug/formatter.h
@@ -31,6 +31,37 @@
#include <bits/c++config.h>
+#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 <typeinfo>
# 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 8ed61a6..abc4124 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<PrintContext*>(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 0f11435..52d8f81 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 7545894..5c6b4dd 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 7a59f16..79bdef6 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 0000000..520788d
--- /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 <debug/vector>
+#include <debug/checks.h>
+
+void test01()
+{
+ __gnu_test::check_assign1<__gnu_debug::vector<int> >();
+}
+
+int main()
+{
+ test01();
+ return 0;
+}