Debug Mode ENH 3/4: Add backtrace

Message ID 0dd654b0-6299-766d-e218-d3a5d4f1a886@gmail.com
State New
Headers show
Series
  • Debug Mode ENH 3/4: Add backtrace
Related show

Commit Message

François Dumont May 7, 2018, 8:20 p.m.
Hi

     Here is the patch to add backtrace info to debug assertion failure 
output.

Example:

/home/fdt/dev/gcc/build/x86_64-pc-linux-gnu/libstdc++-v3/include/debug/vector:188:
In function:
     std::__debug::vector<_Tp, _Allocator>::vector(_InputIterator,
     _InputIterator, const _Allocator&) [with _InputIterator =
std::reverse_iterator<__gnu_debug::_Safe_tagged_iterator<__gnu_cxx::__normal_iterator<int*, 

     std::vector<int> >, std::__debug::vector<int>,
     std::random_access_iterator_tag> >; <template-parameter-2-2> = 
void; _Tp
     = int; _Allocator = std::allocator<int>]

Backtrace:
     ./debug_neg.exe() [0x4020c1]
     ./debug_neg.exe() [0x400e59]
     /lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0xf0) 
[0x7f13fc56e830]
     ./debug_neg.exe() [0x400eb9]

I tried to use add2line on the output address and it worked fine.

Tested under Linux x86_64.

I'll commit tomorrow if not told otherwise.

     * src/c++11/debug.cc [_GLIBCXX_HAVE_EXECINFO_H]: Include execinfo.h.
     [_GLIBCXX_HAVE_EXECINFO_H](_Error_formatter::_M_error): Render 
backtrace.

François

Comments

Jonathan Wakely May 8, 2018, 3:27 p.m. | #1
On 07/05/18 22:20 +0200, François Dumont wrote:
>Hi

>

>    Here is the patch to add backtrace info to debug assertion failure 

>output.

>

>Example:

>

>/home/fdt/dev/gcc/build/x86_64-pc-linux-gnu/libstdc++-v3/include/debug/vector:188:

>In function:

>    std::__debug::vector<_Tp, _Allocator>::vector(_InputIterator,

>    _InputIterator, const _Allocator&) [with _InputIterator =

>std::reverse_iterator<__gnu_debug::_Safe_tagged_iterator<__gnu_cxx::__normal_iterator<int*,

>

>    std::vector<int> >, std::__debug::vector<int>,

>    std::random_access_iterator_tag> >; <template-parameter-2-2> = 

>void; _Tp

>    = int; _Allocator = std::allocator<int>]

>

>Backtrace:

>    ./debug_neg.exe() [0x4020c1]

>    ./debug_neg.exe() [0x400e59]

>    /lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0xf0) 

>[0x7f13fc56e830]

>    ./debug_neg.exe() [0x400eb9]

>

>I tried to use add2line on the output address and it worked fine.

>

>Tested under Linux x86_64.

>

>I'll commit tomorrow if not told otherwise.

>

>    * src/c++11/debug.cc [_GLIBCXX_HAVE_EXECINFO_H]: Include execinfo.h.

>    [_GLIBCXX_HAVE_EXECINFO_H](_Error_formatter::_M_error): Render 

>backtrace.


Did you look into using libbacktrace? That resolves the addresses and
prints nice symbols. See the output of AddressSantizer for what it
looks like (I think that uses libbacktrace).
François Dumont May 8, 2018, 7:54 p.m. | #2
On 08/05/2018 17:27, Jonathan Wakely wrote:
> On 07/05/18 22:20 +0200, François Dumont wrote:

>> Hi

>>

>>     Here is the patch to add backtrace info to debug assertion 

>> failure output.

>>

>> Example:

>>

>> /home/fdt/dev/gcc/build/x86_64-pc-linux-gnu/libstdc++-v3/include/debug/vector:188: 

>>

>> In function:

>>     std::__debug::vector<_Tp, _Allocator>::vector(_InputIterator,

>>     _InputIterator, const _Allocator&) [with _InputIterator =

>> std::reverse_iterator<__gnu_debug::_Safe_tagged_iterator<__gnu_cxx::__normal_iterator<int*, 

>>

>>

>>     std::vector<int> >, std::__debug::vector<int>,

>>     std::random_access_iterator_tag> >; <template-parameter-2-2> = 

>> void; _Tp

>>     = int; _Allocator = std::allocator<int>]

>>

>> Backtrace:

>>     ./debug_neg.exe() [0x4020c1]

>>     ./debug_neg.exe() [0x400e59]

>>     /lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0xf0) 

>> [0x7f13fc56e830]

>>     ./debug_neg.exe() [0x400eb9]

>>

>> I tried to use add2line on the output address and it worked fine.

>>

>> Tested under Linux x86_64.

>>

>> I'll commit tomorrow if not told otherwise.

>>

>>     * src/c++11/debug.cc [_GLIBCXX_HAVE_EXECINFO_H]: Include execinfo.h.

>>     [_GLIBCXX_HAVE_EXECINFO_H](_Error_formatter::_M_error): Render 

>> backtrace.

>

> Did you look into using libbacktrace? That resolves the addresses and

> prints nice symbols. See the output of AddressSantizer for what it

> looks like (I think that uses libbacktrace).

>

>

I'll go with this version for now but I'll look into libbacktrace.

It will be perhaps the occasion to play with autoconf & al tools to find 
out if I can use libbacktrace.
Jeff Law via Gcc-patches May 8, 2018, 11:51 p.m. | #3
On Tue, May 8, 2018 at 12:54 PM, François Dumont <frs.dumont@gmail.com> wrote:
>

> I'll go with this version for now but I'll look into libbacktrace.

>

> It will be perhaps the occasion to play with autoconf & al tools to find out

> if I can use libbacktrace.


In GCC libgo and libgfortran already use libbacktrace, so there are
good examples to copy.

Ian
Jonathan Wakely May 9, 2018, 9:05 a.m. | #4
On 08/05/18 16:51 -0700, Ian Lance Taylor via libstdc++ wrote:
>On Tue, May 8, 2018 at 12:54 PM, François Dumont <frs.dumont@gmail.com> wrote:

>>

>> I'll go with this version for now but I'll look into libbacktrace.

>>

>> It will be perhaps the occasion to play with autoconf & al tools to find out

>> if I can use libbacktrace.

>

>In GCC libgo and libgfortran already use libbacktrace, so there are

>good examples to copy.


And if there are any concerns about adding an extra dependency to
libstdcOO.so or increasing the size of libstdc++.a we could
conditionally use libbacktrace for the unoptimized versions of libstdc++
installed into $libdir/debug/ when --enable-libstdcxx-debug is used
(which is orthogonal to the Debug Mode).

That would allow getting nicer backtraces by linking to the debug
libs, without adding an unconditional dependency that is only used by
code compiled with _GLIBCXX_DEBUG.

Patch

diff --git a/libstdc++-v3/src/c++11/debug.cc b/libstdc++-v3/src/c++11/debug.cc
index 3a1558b..cd1b43d 100644
--- a/libstdc++-v3/src/c++11/debug.cc
+++ b/libstdc++-v3/src/c++11/debug.cc
@@ -40,6 +40,10 @@ 
 
 #include <cxxabi.h> // for __cxa_demangle
 
+#if defined _GLIBCXX_HAVE_EXECINFO_H
+# include <execinfo.h> // for backtrace
+#endif
+
 #include "mutex_pool.h"
 
 using namespace std;
@@ -1048,6 +1052,29 @@  namespace __gnu_debug
 	print_literal(ctx, "\n");
       }
 
+#if defined _GLIBCXX_HAVE_EXECINFO_H
+    {
+      void* stack[32];
+      int nb = backtrace(stack, 32);
+
+      // Note that we skip current method symbol.
+      if (nb > 1)
+	{
+	  print_literal(ctx, "Backtrace:\n");
+	  auto symbols = backtrace_symbols(stack, nb);
+	  for (int i = 1; i < nb; ++i)
+	    {
+	      print_word(ctx, symbols[i]);
+	      print_literal(ctx, "\n");
+	    }
+
+	  free(symbols);
+	  ctx._M_first_line = true;
+	  print_literal(ctx, "\n");
+	}
+    }
+#endif
+
     print_literal(ctx, "Error: ");
 
     // Print the error message