libbacktrace integration for _GLIBCXX_DEBUG mode
Jonathan Wakely
jwakely@redhat.com
Fri Dec 21 20:35:00 GMT 2018
On 11/12/18 00:08 +0100, François Dumont wrote:
>Hi
>
>Â Â Â Here is the integration of libbacktrace to provide the backtrace
>on _GLIBCXX_DEBUG assertions.
>
>Â Â Â I decided to integrate it without impacting the build scripts.
>Users just need to install libbacktrace and once done _GLIBCXX_DEBUG
>will look for it and start using it if supported. The drawback is that
>as soon as libbacktrace is installed users will have to add
>-lbacktrace in order to use _GLIBCXX_DEBUG mode. But I expect that if
>you install libbacktrace it is for a reason.
>
>Â Â Â Note that when libbacktrace is not supported I include stdint.h to
>get uintptr_t, I hope it is the correct way to get it in a portable
>way.
>
>Â Â Â I also explcitely define BACKTRACE_SUPPORTED to 0 to make sure
>libstdc++ has no libbacktrace dependency after usual build.
>
>Â Â Â As it starts to make a lot of information displayed on Debug
>assertion I have created print_function to filter output of functions.
>It removes things like __cxx1998::, std::allocator and greatly
>simplified _Safe_iterator rendering.
>
>Â Â Â Here is an example of output when building
>23_containers/vector/debug/construct3_neg.cc:
>
>/home/fdt/dev/gcc/install/include/c++/9.0.0/debug/safe_iterator.h:321:
>In function:
>Â Â Â __gnu_debug::_Safe_iterator<_Iterator, _Sequence, _Category>&
>Â Â Â __gnu_debug::_Safe_iterator<_Iterator, _Sequence,
>Â Â Â _Category>::operator++() [with _Iterator = std::_List_iterator<int>;
>Â Â Â _Sequence = std::__debug::list<int>; _Category =
>Â Â Â std::forward_iterator_tag]
>
>Backtrace:
>Â Â Â 0x40275f
>__gnu_debug::_Safe_iterator<std::_List_iterator<int>>::operator++()
>/home/fdt/dev/gcc/install/include/c++/9.0.0/debug/safe_iterator.h:321
>Â Â Â 0x402181
>__gnu_debug::_Safe_iterator<std::_List_iterator<int>>::operator++()
>/home/fdt/dev/gcc/install/include/c++/9.0.0/debug/safe_iterator.h:570
>Â Â Â 0x404082 std::iterator_traits<__gnu_debug::_Safe_iterator<std::_List_iterator<int>>
>>::difference_type
>std::__distance<__gnu_debug::_Safe_iterator<std::_List_iterator<int>>
>>(__gnu_debug::_Safe_iterator<std::_List_iterator<int>>,
>__gnu_debug::_Safe_iterator<std::_List_iterator<int>>,
>std::input_iterator_tag)
>/home/fdt/dev/gcc/install/include/c++/9.0.0/bits/stl_iterator_base_funcs.h:89
>Â Â Â 0x403795 std::iterator_traits<__gnu_debug::_Safe_iterator<std::_List_iterator<int>>
>>::difference_type
>std::distance<__gnu_debug::_Safe_iterator<std::_List_iterator<int>>
>>(__gnu_debug::_Safe_iterator<std::_List_iterator<int>>,
>__gnu_debug::_Safe_iterator<std::_List_iterator<int>>)
>/home/fdt/dev/gcc/install/include/c++/9.0.0/bits/stl_iterator_base_funcs.h:141
>Â Â Â 0x4030b9 void std::vector<int>::_M_range_initialize<__gnu_debug::_Safe_iterator<std::_List_iterator<int>>
>>(__gnu_debug::_Safe_iterator<std::_List_iterator<int>>,
>__gnu_debug::_Safe_iterator<std::_List_iterator<int>>,
>std::forward_iterator_tag)
>/home/fdt/dev/gcc/install/include/c++/9.0.0/bits/stl_vector.h:1541
>Â Â Â 0x402a2d std::vector<int>::vector<__gnu_debug::_Safe_iterator<std::_List_iterator<int>>,
>void>(__gnu_debug::_Safe_iterator<std::_List_iterator<int>>,
>__gnu_debug::_Safe_iterator<std::_List_iterator<int>>)
>/home/fdt/dev/gcc/install/include/c++/9.0.0/bits/stl_vector.h:618
>Â Â Â 0x4022ec std::__debug::vector<int>::vector<__gnu_debug::_Safe_iterator<std::_List_iterator<int>>,
>void>(__gnu_debug::_Safe_iterator<std::_List_iterator<int>>,
>__gnu_debug::_Safe_iterator<std::_List_iterator<int>>)
>Â Â Â /home/fdt/dev/gcc/install/include/c++/9.0.0/debug/vector:195
>Â Â Â 0x401e2c void
>__gnu_test::check_construct3<std::__debug::vector<int> >()
>Â Â Â ./util/debug/checks.h:234
>Â Â Â 0x401460 test01()
>Â Â Â /home/fdt/dev/poc/construct3_neg.cc:26
>Â Â Â 0x40146c main
>Â Â Â /home/fdt/dev/poc/construct3_neg.cc:31
>
>Error: attempt to increment a past-the-end iterator.
>
>Objects involved in the operation:
>Â Â Â iterator "this" @ 0x0x7fff068adce0 {
>Â Â Â Â Â type = std::_List_iterator<int> (mutable iterator);
>Â Â Â Â Â state = past-the-end;
>Â Â Â Â Â references sequence with type 'std::__debug::list<int>' @
>0x0x7fff068ae080
>Â Â Â }
>
>Â Â Â * include/debug/formatter.h: Check for backtrace-supported.h access
>Â Â Â and include it.
>Â Â Â [BACKTRACE_SUPPORTED] Include <backtrace.h>
>Â Â Â (_Error_formatter::_Bt_full_t): New function pointer type.
>Â Â Â (_Error_formatter::_M_backtrace_state): New.
>Â Â Â (_Error_formatter::_M_backtrace_full_func): New.
>Â Â Â * src/c++11/debug.cc: Include <cstring>.
>Â Â Â (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.
>
>Tested under Linux x86_64.
>
>Ok to commit ? One day ?
Maybe one day, but not now during stage 3.
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).
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.
More information about the Libstdc++
mailing list