public inbox for libstdc++@gcc.gnu.org
 help / color / mirror / Atom feed
* [PATCH] Add _GLIBCXX_DEBUG backtrace generation
@ 2022-07-13 17:26 François Dumont
  2022-08-04 20:46 ` François Dumont
  2022-08-08 13:29 ` Jonathan Wakely
  0 siblings, 2 replies; 8+ messages in thread
From: François Dumont @ 2022-07-13 17:26 UTC (permalink / raw)
  To: libstdc++; +Cc: gcc-patches

[-- Attachment #1: Type: text/plain, Size: 1517 bytes --]

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 (pretty_print): Rename into...
   (print_function): ...that.
   [_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_neg.cc: Add backtrace
     generation.
   * doc/xml/manual/debug_mode.xml: Document _GLIBCXX_DEBUG_BACKTRACE.
   * doc/xml/manual/using.xml: Likewise.

Tested under Linux x86_64 normal and _GLIBCXX_DEBUG modes.

Ok to commit ?

François

[-- Attachment #2: debug_backtrace.patch --]
[-- Type: text/x-patch, Size: 12275 bytes --]

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.
   <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 36b86702d22..26f14fae194 100644
--- a/libstdc++-v3/doc/xml/manual/using.xml
+++ b/libstdc++-v3/doc/xml/manual/using.xml
@@ -1129,6 +1129,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
@@ -1635,6 +1644,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 80e8ba46d1e..f31b44d184a 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)
@@ -565,6 +596,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
@@ -580,6 +620,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 4706defedf1..3e45433be22 100644
--- a/libstdc++-v3/src/c++11/debug.cc
+++ b/libstdc++-v3/src/c++11/debug.cc
@@ -609,10 +609,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
@@ -666,25 +668,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);
+
+	    func = idx + offset;
 
-	    pos += 2; // advance past "__"
-	    if (memcmp(pos, cxx1998, 9) == 0)
-	      pos += 9; // advance part "cxx1998::"
+	    while (*func && isspace((unsigned char)*func))
+	      ++func;
 
-	    str = pos;
+	    if (!*func)
+	      break;
 	  }
 	else
 	  {
-	    print_func(ctx, str, -1);
+	    print_func(ctx, func, -1);
 	    break;
 	  }
       }
@@ -704,7 +716,7 @@ 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());
 	  free(demangled_name);
@@ -735,7 +747,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<typename _Iterator>
@@ -1090,6 +1102,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)
+	  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
@@ -1130,11 +1194,22 @@ 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: ");
 
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..cb1b1740cfe 100644
--- a/libstdc++-v3/testsuite/23_containers/vector/debug/assign4_neg.cc
+++ b/libstdc++-v3/testsuite/23_containers/vector/debug/assign4_neg.cc
@@ -16,6 +16,7 @@
 // <http://www.gnu.org/licenses/>.
 //
 // { dg-do run { xfail *-*-* } }
+// { dg-options "-D_GLIBCXX_DEBUG_BACKTRACE -lstdc++_libbacktrace" }
 
 #include <debug/vector>
 #include <debug/checks.h>

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH] Add _GLIBCXX_DEBUG backtrace generation
  2022-07-13 17:26 [PATCH] Add _GLIBCXX_DEBUG backtrace generation François Dumont
@ 2022-08-04 20:46 ` François Dumont
  2022-08-08 13:29 ` Jonathan Wakely
  1 sibling, 0 replies; 8+ messages in thread
From: François Dumont @ 2022-08-04 20:46 UTC (permalink / raw)
  To: libstdc++; +Cc: gcc-patches

Gentle reminder.

On 13/07/22 19:26, François Dumont wrote:
> 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 (pretty_print): Rename into...
>   (print_function): ...that.
>   [_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_neg.cc: Add backtrace
>     generation.
>   * doc/xml/manual/debug_mode.xml: Document _GLIBCXX_DEBUG_BACKTRACE.
>   * doc/xml/manual/using.xml: Likewise.
>
> Tested under Linux x86_64 normal and _GLIBCXX_DEBUG modes.
>
> Ok to commit ?
>
> François



^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH] Add _GLIBCXX_DEBUG backtrace generation
  2022-07-13 17:26 [PATCH] Add _GLIBCXX_DEBUG backtrace generation François Dumont
  2022-08-04 20:46 ` François Dumont
@ 2022-08-08 13:29 ` Jonathan Wakely
  2022-08-09  8:07   ` François Dumont
  1 sibling, 1 reply; 8+ messages in thread
From: Jonathan Wakely @ 2022-08-08 13:29 UTC (permalink / raw)
  To: François Dumont; +Cc: libstdc++, gcc-patches

On Wed, 13 Jul 2022 at 18:28, François Dumont via Libstdc++
<libstdc++@gcc.gnu.org> wrote:
>
> 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 (pretty_print): Rename into...
>    (print_function): ...that.

This does more than just rename it, what are the other changes for?


>    [_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_neg.cc: Add backtrace
>      generation.
>    * doc/xml/manual/debug_mode.xml: Document _GLIBCXX_DEBUG_BACKTRACE.
>    * doc/xml/manual/using.xml: Likewise.
>
> Tested under Linux x86_64 normal and _GLIBCXX_DEBUG modes.
>
> Ok to commit ?


>--- a/libstdc++-v3/testsuite/23_containers/vector/debug/assign4_neg.cc
>+++ b/libstdc++-v3/testsuite/23_containers/vector/debug/assign4_neg.cc
>@@ -16,6 +16,7 @@
> // <http://www.gnu.org/licenses/>.
> //
> // { dg-do run { xfail *-*-* } }
>+// { dg-options "-D_GLIBCXX_DEBUG_BACKTRACE -lstdc++_libbacktrace" }
>
> #include <debug/vector>
> #include <debug/checks.h>

This will fail to link if the static lib isn't available.


^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH] Add _GLIBCXX_DEBUG backtrace generation
  2022-08-08 13:29 ` Jonathan Wakely
@ 2022-08-09  8:07   ` François Dumont
  2022-08-31  5:05     ` François Dumont
  0 siblings, 1 reply; 8+ messages in thread
From: François Dumont @ 2022-08-09  8:07 UTC (permalink / raw)
  To: Jonathan Wakely; +Cc: libstdc++, gcc-patches

[-- Attachment #1: Type: text/plain, Size: 2587 bytes --]

On 08/08/22 15:29, Jonathan Wakely wrote:
> On Wed, 13 Jul 2022 at 18:28, François Dumont via Libstdc++
> <libstdc++@gcc.gnu.org> wrote:
>> 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 (pretty_print): Rename into...
>>     (print_function): ...that.
> This does more than just rename it, what are the other changes for?

Nothing, I'm starting to remember what you did on this, reverted.


>
>
>>     [_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_neg.cc: Add backtrace
>>       generation.
>>     * doc/xml/manual/debug_mode.xml: Document _GLIBCXX_DEBUG_BACKTRACE.
>>     * doc/xml/manual/using.xml: Likewise.
>>
>> Tested under Linux x86_64 normal and _GLIBCXX_DEBUG modes.
>>
>> Ok to commit ?
>
>> --- a/libstdc++-v3/testsuite/23_containers/vector/debug/assign4_neg.cc
>> +++ b/libstdc++-v3/testsuite/23_containers/vector/debug/assign4_neg.cc
>> @@ -16,6 +16,7 @@
>> // <http://www.gnu.org/licenses/>.
>> //
>> // { dg-do run { xfail *-*-* } }
>> +// { dg-options "-D_GLIBCXX_DEBUG_BACKTRACE -lstdc++_libbacktrace" }
>>
>> #include <debug/vector>
>> #include <debug/checks.h>
> This will fail to link if the static lib isn't available.
>
Good point ! So I am introducing a new test case with the necessary dg 
directive.

It is a 'run' test case even if what is really tested is only the 
compilation/link part. For the run part someone has to look at the log file.

François

[-- Attachment #2: debug_backtrace.patch --]
[-- Type: text/x-patch, Size: 12587 bytes --]

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.
   <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 36b86702d22..26f14fae194 100644
--- a/libstdc++-v3/doc/xml/manual/using.xml
+++ b/libstdc++-v3/doc/xml/manual/using.xml
@@ -1129,6 +1129,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
@@ -1635,6 +1644,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 748d4fbfea4..b4b72383e22 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 8ed61a69913..25129fe94dc 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
@@ -668,7 +670,7 @@ namespace
   }
 
   void
-  pretty_print(PrintContext& ctx, const char* str, _Print_func_t print_func)
+  print_function(PrintContext& ctx, const char* str, _Print_func_t print_func)
   {
     const char cxx1998[] = "cxx1998::";
     for (;;)
@@ -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;
 	  }
@@ -706,7 +708,7 @@ 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());
 	  free(demangled_name);
@@ -737,7 +739,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<typename _Iterator>
@@ -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)
+	  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
@@ -1133,12 +1187,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_backtrace_neg.cc b/libstdc++-v3/testsuite/23_containers/vector/debug/assign4_backtrace_neg.cc
new file mode 100644
index 00000000000..b28c9164365
--- /dev/null
+++ b/libstdc++-v3/testsuite/23_containers/vector/debug/assign4_backtrace_neg.cc
@@ -0,0 +1,34 @@
+// Copyright (C) 2022 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+//
+// This library 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 General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+//
+// { 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;
+}

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH] Add _GLIBCXX_DEBUG backtrace generation
  2022-08-09  8:07   ` François Dumont
@ 2022-08-31  5:05     ` François Dumont
  2022-08-31 10:11       ` Jonathan Wakely
  0 siblings, 1 reply; 8+ messages in thread
From: François Dumont @ 2022-08-31  5:05 UTC (permalink / raw)
  To: Jonathan Wakely; +Cc: libstdc++, gcc-patches

[-- Attachment #1: Type: text/plain, Size: 4484 bytes --]

After a second thought here is an even cleaner version. No more function 
rename, current pretty_print is fine.

     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.
Ok to commit ?

François

On 09/08/22 10:07, François Dumont wrote:
> On 08/08/22 15:29, Jonathan Wakely wrote:
>> On Wed, 13 Jul 2022 at 18:28, François Dumont via Libstdc++
>> <libstdc++@gcc.gnu.org> wrote:
>>> 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 (pretty_print): Rename into...
>>>     (print_function): ...that.
>> This does more than just rename it, what are the other changes for?
>
> Nothing, I'm starting to remember what you did on this, reverted.
>
>
>>
>>
>>> [_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_neg.cc: Add 
>>> backtrace
>>>       generation.
>>>     * doc/xml/manual/debug_mode.xml: Document _GLIBCXX_DEBUG_BACKTRACE.
>>>     * doc/xml/manual/using.xml: Likewise.
>>>
>>> Tested under Linux x86_64 normal and _GLIBCXX_DEBUG modes.
>>>
>>> Ok to commit ?
>>
>>> --- a/libstdc++-v3/testsuite/23_containers/vector/debug/assign4_neg.cc
>>> +++ b/libstdc++-v3/testsuite/23_containers/vector/debug/assign4_neg.cc
>>> @@ -16,6 +16,7 @@
>>> // <http://www.gnu.org/licenses/>.
>>> //
>>> // { dg-do run { xfail *-*-* } }
>>> +// { dg-options "-D_GLIBCXX_DEBUG_BACKTRACE -lstdc++_libbacktrace" }
>>>
>>> #include <debug/vector>
>>> #include <debug/checks.h>
>> This will fail to link if the static lib isn't available.
>>
> Good point ! So I am introducing a new test case with the necessary dg 
> directive.
>
> It is a 'run' test case even if what is really tested is only the 
> compilation/link part. For the run part someone has to look at the log 
> file.
>
> François


[-- Attachment #2: debug_backtrace.patch --]
[-- Type: text/x-patch, Size: 10705 bytes --]

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.
   <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 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.
       </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 748d4fbfea4..b4b72383e22 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 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<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 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 <debug/vector>
+#include <debug/checks.h>
+
+void test01()
+{
+  __gnu_test::check_assign1<__gnu_debug::vector<int> >();
+}
+
+int main()
+{
+  test01();
+  return 0;
+}

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH] Add _GLIBCXX_DEBUG backtrace generation
  2022-08-31  5:05     ` François Dumont
@ 2022-08-31 10:11       ` Jonathan Wakely
  2022-08-31 19:33         ` François Dumont
  0 siblings, 1 reply; 8+ messages in thread
From: Jonathan Wakely @ 2022-08-31 10:11 UTC (permalink / raw)
  To: François Dumont; +Cc: libstdc++, gcc-patches

On Wed, 31 Aug 2022 at 06:05, François Dumont <frs.dumont@gmail.com> wrote:
>
> After a second thought here is an even cleaner version. No more function
> rename, current pretty_print is fine.
>
>      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.
> Ok to commit ?

OK for trunk, thanks.

The small change to print_raw in this patch makes me wonder whether
that function is actually useful.

It supports two modes, print with max precision, and print without.
The only time we use it to print with max precision we pass a string
of exactly the right length, so the precision is not needed (but the
caller has to get the string length correct: if we increase _S_indent
and do not increase the "    " literal passed to print_raw, the
effects would be wrong).

Wouldn't it be better to just use fprintf directly when we want to
print without precision, and use a minimum field width instead of
precision for indenting? i.e. ...

--- a/libstdc++-v3/src/c++11/debug.cc
+++ b/libstdc++-v3/src/c++11/debug.cc
@@ -608,15 +608,6 @@ namespace
    print_literal(PrintContext& ctx, const char(&word)[Length])
    { print_word(ctx, word, Length - 1); }

-  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);
-  }
-
  void
  print_word(PrintContext& ctx, const char* word, ptrdiff_t nbc = -1)
  {
@@ -643,12 +634,9 @@ namespace
       || (ctx._M_column + visual_length < ctx._M_max_length)
       || (visual_length >= ctx._M_max_length && ctx._M_column == 1))
      {
-       // If this isn't the first line, indent
+       // If this isn't the first line, indent.
       if (ctx._M_column == 1 && !ctx._M_first_line)
-         {
-           const char spacing[PrintContext::_S_indent + 1] = "    ";
-           print_raw(ctx, spacing, PrintContext::_S_indent);
-         }
+         ctx._M_column += fprintf(stderr, "%*c", PrintContext::_S_indent, ' ');

       int written = fprintf(stderr, "%.*s", (int)length, word);

@@ -1112,7 +1100,7 @@ namespace __gnu_debug
    PrintContext ctx;
    if (_M_file)
      {
-       print_raw(ctx, _M_file);
+       ctx._M_column += fprintf(stderr, "%s", _M_file);
       print_literal(ctx, ":");
       go_to_next_line = true;
      }


^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH] Add _GLIBCXX_DEBUG backtrace generation
  2022-08-31 10:11       ` Jonathan Wakely
@ 2022-08-31 19:33         ` François Dumont
  2022-08-31 20:07           ` Jonathan Wakely
  0 siblings, 1 reply; 8+ messages in thread
From: François Dumont @ 2022-08-31 19:33 UTC (permalink / raw)
  To: Jonathan Wakely; +Cc: libstdc++, gcc-patches

On 31/08/22 12:11, Jonathan Wakely wrote:
> On Wed, 31 Aug 2022 at 06:05, François Dumont <frs.dumont@gmail.com> wrote:
>> After a second thought here is an even cleaner version. No more function
>> rename, current pretty_print is fine.
>>
>>       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.
>> Ok to commit ?
> OK for trunk, thanks.
>
> The small change to print_raw in this patch makes me wonder whether
> that function is actually useful.
>
> It supports two modes, print with max precision, and print without.
> The only time we use it to print with max precision we pass a string
> of exactly the right length, so the precision is not needed (but the
> caller has to get the string length correct: if we increase _S_indent
> and do not increase the "    " literal passed to print_raw, the
> effects would be wrong).
>
> Wouldn't it be better to just use fprintf directly when we want to
> print without precision, and use a minimum field width instead of
> precision for indenting? i.e. ...
>
> --- a/libstdc++-v3/src/c++11/debug.cc
> +++ b/libstdc++-v3/src/c++11/debug.cc
> @@ -608,15 +608,6 @@ namespace
>      print_literal(PrintContext& ctx, const char(&word)[Length])
>      { print_word(ctx, word, Length - 1); }
>
> -  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);
> -  }
> -
>    void
>    print_word(PrintContext& ctx, const char* word, ptrdiff_t nbc = -1)
>    {
> @@ -643,12 +634,9 @@ namespace
>         || (ctx._M_column + visual_length < ctx._M_max_length)
>         || (visual_length >= ctx._M_max_length && ctx._M_column == 1))
>        {
> -       // If this isn't the first line, indent
> +       // If this isn't the first line, indent.
>         if (ctx._M_column == 1 && !ctx._M_first_line)
> -         {
> -           const char spacing[PrintContext::_S_indent + 1] = "    ";
> -           print_raw(ctx, spacing, PrintContext::_S_indent);
> -         }
> +         ctx._M_column += fprintf(stderr, "%*c", PrintContext::_S_indent, ' ');
I did not know this syntax, it looks definitely better.
>
>         int written = fprintf(stderr, "%.*s", (int)length, word);
>
> @@ -1112,7 +1100,7 @@ namespace __gnu_debug
>      PrintContext ctx;
>      if (_M_file)
>        {
> -       print_raw(ctx, _M_file);
> +       ctx._M_column += fprintf(stderr, "%s", _M_file);
>         print_literal(ctx, ":");
>         go_to_next_line = true;
>        }
>
Do you take care or you prefer I do ?



^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH] Add _GLIBCXX_DEBUG backtrace generation
  2022-08-31 19:33         ` François Dumont
@ 2022-08-31 20:07           ` Jonathan Wakely
  0 siblings, 0 replies; 8+ messages in thread
From: Jonathan Wakely @ 2022-08-31 20:07 UTC (permalink / raw)
  To: François Dumont; +Cc: libstdc++, gcc-patches

On Wed, 31 Aug 2022 at 20:33, François Dumont <frs.dumont@gmail.com> wrote:
>
> On 31/08/22 12:11, Jonathan Wakely wrote:
> > On Wed, 31 Aug 2022 at 06:05, François Dumont <frs.dumont@gmail.com> wrote:
> >> After a second thought here is an even cleaner version. No more function
> >> rename, current pretty_print is fine.
> >>
> >>       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.
> >> Ok to commit ?
> > OK for trunk, thanks.
> >
> > The small change to print_raw in this patch makes me wonder whether
> > that function is actually useful.
> >
> > It supports two modes, print with max precision, and print without.
> > The only time we use it to print with max precision we pass a string
> > of exactly the right length, so the precision is not needed (but the
> > caller has to get the string length correct: if we increase _S_indent
> > and do not increase the "    " literal passed to print_raw, the
> > effects would be wrong).
> >
> > Wouldn't it be better to just use fprintf directly when we want to
> > print without precision, and use a minimum field width instead of
> > precision for indenting? i.e. ...
> >
> > --- a/libstdc++-v3/src/c++11/debug.cc
> > +++ b/libstdc++-v3/src/c++11/debug.cc
> > @@ -608,15 +608,6 @@ namespace
> >      print_literal(PrintContext& ctx, const char(&word)[Length])
> >      { print_word(ctx, word, Length - 1); }
> >
> > -  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);
> > -  }
> > -
> >    void
> >    print_word(PrintContext& ctx, const char* word, ptrdiff_t nbc = -1)
> >    {
> > @@ -643,12 +634,9 @@ namespace
> >         || (ctx._M_column + visual_length < ctx._M_max_length)
> >         || (visual_length >= ctx._M_max_length && ctx._M_column == 1))
> >        {
> > -       // If this isn't the first line, indent
> > +       // If this isn't the first line, indent.
> >         if (ctx._M_column == 1 && !ctx._M_first_line)
> > -         {
> > -           const char spacing[PrintContext::_S_indent + 1] = "    ";
> > -           print_raw(ctx, spacing, PrintContext::_S_indent);
> > -         }
> > +         ctx._M_column += fprintf(stderr, "%*c", PrintContext::_S_indent, ' ');
> I did not know this syntax, it looks definitely better.
> >
> >         int written = fprintf(stderr, "%.*s", (int)length, word);
> >
> > @@ -1112,7 +1100,7 @@ namespace __gnu_debug
> >      PrintContext ctx;
> >      if (_M_file)
> >        {
> > -       print_raw(ctx, _M_file);
> > +       ctx._M_column += fprintf(stderr, "%s", _M_file);
> >         print_literal(ctx, ":");
> >         go_to_next_line = true;
> >        }
> >
> Do you take care or you prefer I do ?


I can do it.


^ permalink raw reply	[flat|nested] 8+ messages in thread

end of thread, other threads:[~2022-08-31 20:08 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-07-13 17:26 [PATCH] Add _GLIBCXX_DEBUG backtrace generation François Dumont
2022-08-04 20:46 ` François Dumont
2022-08-08 13:29 ` Jonathan Wakely
2022-08-09  8:07   ` François Dumont
2022-08-31  5:05     ` François Dumont
2022-08-31 10:11       ` Jonathan Wakely
2022-08-31 19:33         ` François Dumont
2022-08-31 20:07           ` Jonathan Wakely

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).