libbacktrace integration for _GLIBCXX_DEBUG mode
Jonathan Wakely
jwakely@redhat.com
Wed May 29 23:05:00 GMT 2019
On 23/05/19 07:39 +0200, François Dumont wrote:
>Hi
>
>Â Â Â So here what I come up with.
>
>Â Â Â _GLIBCXX_DEBUG_BACKTRACE controls the feature. If the user define
>it and there is a detectable issue with libbacktrace then I generate a
>compilation error. I want to avoid users defining it but having no
>backtrace in the end in the debug assertion.
>
>Â Â Â With this new setup I manage to run testsuite with it like that:
>
>export LD_LIBRARY_PATH=/home/fdt/dev/gcc/install/lib/
>make CXXFLAGS='-D_GLIBCXX_DEBUG_BACKTRACE
>-I/home/fdt/dev/gcc/install/include -lbacktrace' check-debug
>
>Â Â Â An example of result:
>
>/home/fdt/dev/gcc/build/x86_64-pc-linux-gnu/libstdc++-v3/include/debug/vector:606:
>In function:
>Â Â Â std::__debug::vector<_Tp, _Allocator>::iterator
>Â Â Â std::__debug::vector<_Tp,
>_Allocator>::insert(std::__debug::vector<_Tp,
>Â Â Â _Allocator>::const_iterator, _InputIterator, _InputIterator) [with
>Â Â Â _InputIterator = int*; <template-parameter-2-2> = void; _Tp = int;
>Â Â Â _Allocator = std::allocator<int>; std::__debug::vector<_Tp,
>Â Â Â _Allocator>::iterator =
>__gnu_debug::_Safe_iterator<__gnu_cxx::__normal_iterator<int*, std::
>Â Â Â vector<int> >, std::__debug::vector<int>,
>Â Â Â std::random_access_iterator_tag>; typename
>std::iterator_traits<typename
>Â Â Â std::vector<_Tp, _Alloc>::iterator>::iterator_category =
>Â Â Â std::random_access_iterator_tag; typename std::vector<_Tp,
>Â Â Â _Alloc>::iterator = __gnu_cxx::__normal_iterator<int*,
>std::vector<int>
>Â Â Â >; std::__debug::vector<_Tp, _Allocator>::const_iterator =
>__gnu_debug::_Safe_iterator<__gnu_cxx::__normal_iterator<const int*,
>Â Â Â std::vector<int> >, std::__debug::vector<int>,
>Â Â Â std::random_access_iterator_tag>; typename
>std::iterator_traits<typename
>Â Â Â std::vector<_Tp, _Alloc>::const_iterator>::iterator_category =
>Â Â Â std::random_access_iterator_tag; typename std::vector<_Tp,
>Â Â Â _Alloc>::const_iterator = __gnu_cxx::__normal_iterator<const int*,
>std::
>Â Â Â vector<int> >]
>
>Backtrace:
>Â Â Â 0x402718
>__gnu_debug::_Safe_iterator<__gnu_cxx::__normal_iterator<int*,
>std::vector<int> >> std::__debug::vector<int>::insert<int*,
>void>(__gnu_debug::_Safe_iterator<__gnu_cxx::__normal_iterator<int
>const*, std::vector<int> >>, int*, int*)
>/home/fdt/dev/gcc/build/x86_64-pc-linux-gnu/libstdc++-v3/include/debug/vector:606
>Â Â Â 0x402718 test01()
>/home/fdt/dev/gcc/git/libstdc++-v3/testsuite/23_containers/vector/debug/57779_neg.cc:29
>Â Â Â 0x401428 main
>/home/fdt/dev/gcc/git/libstdc++-v3/testsuite/23_containers/vector/debug/57779_neg.cc:34
>
>Error: attempt to insert with an iterator range [__first, __last) from this
>container.
>
>Objects involved in the operation:
>Â Â Â iterator "__first" @ 0x0x7fff730b96b0 {
>Â Â Â Â Â type = int* (mutable iterator);
>Â Â Â }
>Â Â Â iterator "__last" @ 0x0x7fff730b96b8 {
>Â Â Â Â Â type = int* (mutable iterator);
>Â Â Â }
>Â Â Â sequence "this" @ 0x0x7fff730b9720 {
>Â Â Â Â Â type = std::__debug::vector<int>;
>Â Â Â }
>XFAIL: 23_containers/vector/debug/57779_neg.cc execution test
>
>
>Â Â Â * include/debug/formatter.h [_GLIBCXX_DEBUG_BACKTRACE]: Include
>Â Â Â <backtrace-supported.h> and <backtrace.h>.
>Â Â Â [!_GLIBCXX_DEBUG_BACKTRACE]: Include <stdint.h>.
>Â Â Â [!_GLIBCXX_DEBUG_BACKTRACE](backtrace_error_callback): New.
>Â Â Â [!_GLIBCXX_DEBUG_BACKTRACE](backtrace_full_callback): New.
>Â Â Â [!_GLIBCXX_DEBUG_BACKTRACE](struct backtrace_state): New declaration.
>Â Â Â (_Error_formatter::_Bt_full_t): New function pointer type.
>Â Â Â (_Error_formatter::_M_print_backtrace): New.
>Â Â Â (_Error_formatter::_M_backtrace_state): New.
>Â Â Â (_Error_formatter::_M_backtrace_full_func): New.
>Â Â Â * src/c++11/debug.cc: Include <cstring> and <string>.
>Â Â Â (PrintContext::_M_demangle_name): New.
>Â Â Â (_Print_func_t): New.
>Â Â Â (print_word(PrintContext&, const char*)): New.
>Â Â Â (print_raw(PrintContext&, const char*)): New.
>Â Â Â (print_function(PrintContext&, const char*, _Print_func_t)): New.
>Â Â Â (print_type): Use latter.
>Â Â Â (print_string(PrintContext&, const char*)): New.
>Â Â Â (print_backtrace(void*, uintptr_t, const char*, int, const char*)):
>Â Â Â New.
>Â Â Â (_Error_formatter::_M_error()): Adapt.
>Â Â Â * doc/xml/manual/debug_mode.xml: Document _GLIBCXX_DEBUG_BACKTRACE.
>
>Tested under Linux x86_64.
>
>Ok to commit ?
>
>François
>
>
>On 12/21/18 10:03 PM, Jonathan Wakely wrote:
>>On 21/12/18 22:47 +0200, Ville Voutilainen wrote:
>>>On Fri, 21 Dec 2018 at 22:35, Jonathan Wakely <jwakely@redhat.com>
>>>wrote:
>>>>>Â Â Â I also explcitely define BACKTRACE_SUPPORTED to 0 to make sure
>>>>>libstdc++ has no libbacktrace dependency after usual build.
>>>
>>>>I'm concerned about the requirement to link to libbacktrace
>>>>explicitly (which will break existing makefiles and build systems that
>>>>currently use debug mode in testing).
>>>
>>>But see what Francois wrote, "I also explcitely define
>>>BACKTRACE_SUPPORTED to 0 to make sure
>>>libstdc++ has no libbacktrace dependency after usual build."
>>
>>Yes, but if you happen to install libbacktrace headers, the behaviour
>>for users building their own code changes. I agree that if you install
>>those headers, it's probably for a reason, but it might be a different
>>reason to "so that libstdc++ prints better backtraces".
>>
>>>>Also, some of the glibc team pointed out to me that running *any*
>>>>extra code after undefined behaviour has been detected is a potential
>>>>risk. The less that you do between detecting UB and calling abort(),
>>>>the better. Giving the users more information is helpful, but comes
>>>>with some additional risk.
>>>
>>>Ditto. Having said those things, I think we need to figure out a good
>>>way to provide this sensibly
>>>as an opt-in. The backtrace support is bloody useful, and dovetails
>>>into a possible Contracts-aware
>>>implementation of our library, but I think we need to do some more
>>>thought-work on this, thus I agree
>>>that it's not stage3 material. I do think it's something that we need
>>>to keep in mind, thanks
>>>for working on it, Francois!
>>
>>Yes, I agree that making it available via a more explicit opt-in would
>>be good. Maybe require users to define _GLIBCXX_DEBUG_BACKTRACE as well
>>as _GLIBCXX_DEBUG, or something like that.
>>
>>
>>
>
>diff --git a/libstdc++-v3/doc/xml/manual/debug_mode.xml b/libstdc++-v3/doc/xml/manual/debug_mode.xml
>index 570c17ba28a..27873151dae 100644
>--- a/libstdc++-v3/doc/xml/manual/debug_mode.xml
>+++ b/libstdc++-v3/doc/xml/manual/debug_mode.xml
>@@ -104,9 +104,11 @@
> <para>The following library components provide extra debugging
> capabilities in debug mode:</para>
> <itemizedlist>
>+ <listitem><para><code>std::array</code> (no safe iterators)</para></listitem>
> <listitem><para><code>std::basic_string</code> (no safe iterators and see note below)</para></listitem>
> <listitem><para><code>std::bitset</code></para></listitem>
> <listitem><para><code>std::deque</code></para></listitem>
>+ <listitem><para><code>std::forward_list</code></para></listitem>
> <listitem><para><code>std::list</code></para></listitem>
> <listitem><para><code>std::map</code></para></listitem>
> <listitem><para><code>std::multimap</code></para></listitem>
>@@ -160,6 +162,13 @@ which always works correctly.
> <code>GLIBCXX_DEBUG_MESSAGE_LENGTH</code> can be used to request a
> different length.</para>
>
>+<para>Starting with GCC 10 libstdc++ has integrated
>+ <link xmlns:xlink="http://www.w3.org/1999/xlink"
>+ xlink:href="https://github.com/ianlancetaylor/libbacktrace">libbacktrace</link>
>+ to produce backtrace on error. Use <code>-D_GLIBCXX_DEBUG_BACKTRACE</code> to
>+ activate it. Note that if not properly installed or if libbacktrace is not
>+ supported compilation will fail. You'll also have to use the
>+ <code>-lbacktrace</code> 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/include/debug/formatter.h b/libstdc++-v3/include/debug/formatter.h
>index 220379994c0..690750f42be 100644
>--- a/libstdc++-v3/include/debug/formatter.h
>+++ b/libstdc++-v3/include/debug/formatter.h
>@@ -31,6 +31,29 @@
>
> #include <bits/c++config.h>
>
>+#if defined(_GLIBCXX_DEBUG_BACKTRACE)
>+# if !defined(BACKTRACE_SUPPORTED)
>+# if defined(__has_include) && !__has_include(<backtrace-supported.h>)
>+# error No libbacktrace backtrace-supported.h file found.
>+# endif
>+# include <backtrace-supported.h>
>+# endif
>+# if !BACKTRACE_SUPPORTED
>+# error libbacktrace not supported.
>+# endif
>+# include <backtrace.h>
>+#else
>+# include <stdint.h> // For uintptr_t.
Please use <cstdint> and std::uintptr_t.
>+// Extracted from libbacktrace.
>+typedef void (*backtrace_error_callback) (void*, const char*, int);
>+
>+typedef int (*backtrace_full_callback) (void*, uintptr_t, const char*, int,
>+ const char*);
These typedefs should use __reserved_names.
>+struct backtrace_state;
Although this one can't use a reserved name, unless we're going to
create opaque wrappers around the libbacktrace type. Introducing t his
non-reserved name means that defining _GLIBCXX_DEBUG makes the library
non-conforming.
It would be possible to avoid declaring this struct, by making
_M_backtrace_state a void* and creating a wrapper function for
backtrace_create_state, and a weak symbol in the library. I'll have to
think about this more.
More information about the Libstdc++
mailing list