diff options
Diffstat (limited to 'aarch64-none-linux-gnu/include/c++/13.2.1/stacktrace')
-rw-r--r-- | aarch64-none-linux-gnu/include/c++/13.2.1/stacktrace | 805 |
1 files changed, 805 insertions, 0 deletions
diff --git a/aarch64-none-linux-gnu/include/c++/13.2.1/stacktrace b/aarch64-none-linux-gnu/include/c++/13.2.1/stacktrace new file mode 100644 index 0000000..346c7b1 --- /dev/null +++ b/aarch64-none-linux-gnu/include/c++/13.2.1/stacktrace @@ -0,0 +1,805 @@ +// <stacktrace> -*- C++ -*- + +// Copyright The GNU Toolchain Authors. +// +// 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. + +// 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. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// <http://www.gnu.org/licenses/>. + +#ifndef _GLIBCXX_STACKTRACE +#define _GLIBCXX_STACKTRACE 1 + +#pragma GCC system_header + +#include <bits/requires_hosted.h> // std::string bound + +#include <bits/c++config.h> + +#if __cplusplus > 202002L && _GLIBCXX_HAVE_STACKTRACE +#include <compare> +#include <new> +#include <string> +#include <sstream> +#include <bits/memory_resource.h> +#include <bits/stl_algobase.h> +#include <bits/stl_algo.h> +#include <bits/stl_iterator.h> +#include <bits/stl_uninitialized.h> +#include <ext/numeric_traits.h> + +struct __glibcxx_backtrace_state; +struct __glibcxx_backtrace_simple_data; + +extern "C" +{ +__glibcxx_backtrace_state* +__glibcxx_backtrace_create_state(const char*, int, + void(*)(void*, const char*, int), + void*); + +int +__glibcxx_backtrace_simple(__glibcxx_backtrace_state*, int, + int (*) (void*, __UINTPTR_TYPE__), + void(*)(void*, const char*, int), + void*); +int +__glibcxx_backtrace_pcinfo(__glibcxx_backtrace_state*, __UINTPTR_TYPE__, + int (*)(void*, __UINTPTR_TYPE__, + const char*, int, const char*), + void(*)(void*, const char*, int), + void*); + +int +__glibcxx_backtrace_syminfo(__glibcxx_backtrace_state*, __UINTPTR_TYPE__ addr, + void (*) (void*, __UINTPTR_TYPE__, const char*, + __UINTPTR_TYPE__, __UINTPTR_TYPE__), + void(*)(void*, const char*, int), + void*); +} + +namespace __cxxabiv1 +{ + extern "C" char* + __cxa_demangle(const char* __mangled_name, char* __output_buffer, + size_t* __length, int* __status); +} + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + +#define __cpp_lib_stacktrace 202011L + + // [stacktrace.entry], class stacktrace_entry + class stacktrace_entry + { + using uint_least32_t = __UINT_LEAST32_TYPE__; + using uintptr_t = __UINTPTR_TYPE__; + + public: + using native_handle_type = uintptr_t; + + // [stacktrace.entry.ctor], constructors + + constexpr + stacktrace_entry() noexcept = default; + + constexpr + stacktrace_entry(const stacktrace_entry& __other) noexcept = default; + + constexpr stacktrace_entry& + operator=(const stacktrace_entry& __other) noexcept = default; + + ~stacktrace_entry() = default; + + // [stacktrace.entry.obs], observers + + constexpr native_handle_type + native_handle() const noexcept { return _M_pc; } + + constexpr explicit operator bool() const noexcept { return _M_pc != -1; } + + // [stacktrace.entry.query], query + string + description() const + { + string __s; + _M_get_info(&__s, nullptr, nullptr); + return __s; + } + + string + source_file() const + { + string __s; + _M_get_info(nullptr, &__s, nullptr); + return __s; + } + + uint_least32_t + source_line() const + { + int __line = 0; + _M_get_info(nullptr, nullptr, &__line); + return __line; + } + + // [stacktrace.entry.cmp], comparison + friend constexpr bool + operator==(const stacktrace_entry& __x, + const stacktrace_entry& __y) noexcept + { return __x._M_pc == __y._M_pc; } + + friend constexpr strong_ordering + operator<=>(const stacktrace_entry& __x, + const stacktrace_entry& __y) noexcept + { return __x._M_pc <=> __y._M_pc; } + + private: + native_handle_type _M_pc = -1; + + template<typename _Allocator> friend class basic_stacktrace; + + static void _S_err_handler(void*, const char*, int) { } + + static __glibcxx_backtrace_state* + _S_init() + { + static __glibcxx_backtrace_state* __state + = __glibcxx_backtrace_create_state(nullptr, 1, _S_err_handler, nullptr); + return __state; + } + + friend ostream& + operator<<(ostream&, const stacktrace_entry&); + + bool + _M_get_info(string* __desc, string* __file, int* __line) const + { + if (!*this) + return false; + + struct _Data + { + string* _M_desc; + string* _M_file; + int* _M_line; + } __data = { __desc, __file, __line }; + + auto __cb = [](void* __data, uintptr_t, const char* __filename, + int __lineno, const char* __function) -> int { + auto& __d = *static_cast<_Data*>(__data); + if (__function && __d._M_desc) + *__d._M_desc = _S_demangle(__function); + if (__filename && __d._M_file) + *__d._M_file = __filename; + if (__d._M_line) + *__d._M_line = __lineno; + return __function != nullptr; + }; + const auto __state = _S_init(); + if (::__glibcxx_backtrace_pcinfo(__state, _M_pc, +__cb, _S_err_handler, + &__data)) + return true; + if (__desc && __desc->empty()) + { + auto __cb2 = [](void* __data, uintptr_t, const char* __symname, + uintptr_t, uintptr_t) { + if (__symname) + *static_cast<_Data*>(__data)->_M_desc = _S_demangle(__symname); + }; + if (::__glibcxx_backtrace_syminfo(__state, _M_pc, +__cb2, + _S_err_handler, &__data)) + return true; + } + return false; + } + + static string + _S_demangle(const char* __name) + { + string __s; + int __status; + char* __str = __cxxabiv1::__cxa_demangle(__name, nullptr, nullptr, + &__status); + if (__status == 0) + __s = __str; + else + __s = __name; + __builtin_free(__str); + return __s; + } + }; + + // [stacktrace.basic], class template basic_stacktrace + template<typename _Allocator> + class basic_stacktrace + { + using _AllocTraits = allocator_traits<_Allocator>; + using uintptr_t = __UINTPTR_TYPE__; + + public: + using value_type = stacktrace_entry; + using const_reference = const value_type&; + using reference = value_type&; + using const_iterator + = __gnu_cxx::__normal_iterator<value_type*, basic_stacktrace>; + using iterator = const_iterator; + using reverse_iterator = std::reverse_iterator<iterator>; + using const_reverse_iterator = std::reverse_iterator<const_iterator>; + using difference_type = ptrdiff_t; + using size_type = unsigned short; + using allocator_type = _Allocator; + + // [stacktrace.basic.ctor], creation and assignment + + [[__gnu__::__noinline__]] + static basic_stacktrace + current(const allocator_type& __alloc = allocator_type()) noexcept + { + basic_stacktrace __ret(__alloc); + if (auto __cb = __ret._M_prepare()) [[likely]] + { + auto __state = stacktrace_entry::_S_init(); + if (__glibcxx_backtrace_simple(__state, 1, __cb, + stacktrace_entry::_S_err_handler, + std::__addressof(__ret))) + __ret._M_clear(); + } + return __ret; + } + + [[__gnu__::__noinline__]] + static basic_stacktrace + current(size_type __skip, + const allocator_type& __alloc = allocator_type()) noexcept + { + basic_stacktrace __ret(__alloc); + if (__skip >= __INT_MAX__) [[unlikely]] + return __ret; + if (auto __cb = __ret._M_prepare()) [[likely]] + { + auto __state = stacktrace_entry::_S_init(); + if (__glibcxx_backtrace_simple(__state, __skip + 1, __cb, + stacktrace_entry::_S_err_handler, + std::__addressof(__ret))) + __ret._M_clear(); + } + + return __ret; + } + + [[__gnu__::__noinline__]] + static basic_stacktrace + current(size_type __skip, size_type __max_depth, + const allocator_type& __alloc = allocator_type()) noexcept + { + __glibcxx_assert(__skip <= (size_type(-1) - __max_depth)); + + basic_stacktrace __ret(__alloc); + if (__max_depth == 0) [[unlikely]] + return __ret; + if (__skip >= __INT_MAX__) [[unlikely]] + return __ret; + if (auto __cb = __ret._M_prepare(__max_depth)) [[likely]] + { + auto __state = stacktrace_entry::_S_init(); + int __err = __glibcxx_backtrace_simple(__state, __skip + 1, __cb, + stacktrace_entry::_S_err_handler, + std::__addressof(__ret)); + if (__err < 0) + __ret._M_clear(); + else if (__ret.size() > __max_depth) + { + __ret._M_impl._M_resize(__max_depth, __ret._M_alloc); + + if (__ret._M_impl._M_capacity / 2 >= __max_depth) + { + // shrink to fit + _Impl __tmp = __ret._M_impl._M_clone(__ret._M_alloc); + if (__tmp._M_capacity) + { + __ret._M_clear(); + __ret._M_impl = __tmp; + } + } + } + } + return __ret; + } + + basic_stacktrace() + noexcept(is_nothrow_default_constructible_v<allocator_type>) + { } + + explicit + basic_stacktrace(const allocator_type& __alloc) noexcept + : _M_alloc(__alloc) + { } + + basic_stacktrace(const basic_stacktrace& __other) noexcept + : basic_stacktrace(__other, + _AllocTraits::select_on_container_copy_construction(__other._M_alloc)) + { } + + basic_stacktrace(basic_stacktrace&& __other) noexcept + : _M_alloc(std::move(__other._M_alloc)), + _M_impl(std::__exchange(__other._M_impl, {})) + { } + + basic_stacktrace(const basic_stacktrace& __other, + const allocator_type& __alloc) noexcept + : _M_alloc(__alloc) + { + if (const auto __s = __other._M_impl._M_size) + _M_impl = __other._M_impl._M_clone(_M_alloc); + } + + basic_stacktrace(basic_stacktrace&& __other, + const allocator_type& __alloc) noexcept + : _M_alloc(__alloc) + { + if constexpr (_Allocator::is_always_equal::value) + _M_impl = std::__exchange(__other._M_impl, {}); + else if (_M_alloc == __other._M_alloc) + _M_impl = std::__exchange(__other._M_impl, {}); + else if (const auto __s = __other._M_impl._M_size) + _M_impl = __other._M_impl._M_clone(_M_alloc); + } + + basic_stacktrace& + operator=(const basic_stacktrace& __other) noexcept + { + if (std::__addressof(__other) == this) + return *this; + + constexpr bool __pocca + = _AllocTraits::propagate_on_container_copy_assignment::value; + constexpr bool __always_eq = _AllocTraits::is_always_equal::value; + + const auto __s = __other.size(); + + if constexpr (!__always_eq && __pocca) + { + if (_M_alloc != __other._M_alloc) + { + // Cannot keep the same storage, so deallocate it now. + _M_clear(); + } + } + + if (_M_impl._M_capacity < __s) + { + // Need to allocate new storage. + _M_clear(); + + if constexpr (__pocca) + _M_alloc = __other._M_alloc; + + _M_impl = __other._M_impl._M_clone(_M_alloc); + } + else + { + // Current storage is large enough. + _M_impl._M_resize(0, _M_alloc); + _M_impl._M_assign(__other._M_impl, _M_alloc); + + if constexpr (__pocca) + _M_alloc = __other._M_alloc; + } + + return *this; + } + + basic_stacktrace& + operator=(basic_stacktrace&& __other) noexcept + { + if (std::__addressof(__other) == this) + return *this; + + constexpr bool __pocma + = _AllocTraits::propagate_on_container_move_assignment::value; + + if constexpr (_AllocTraits::is_always_equal::value) + std::swap(_M_impl, __other._M_impl); + else if (_M_alloc == __other._M_alloc) + std::swap(_M_impl, __other._M_impl); + else if constexpr (__pocma) + { + // Free current storage and take ownership of __other's storage. + _M_clear(); + _M_impl = std::__exchange(__other._M_impl, {}); + } + else // Allocators are unequal and don't propagate. + { + const size_type __s = __other.size(); + + if (_M_impl._M_capacity < __s) + { + // Need to allocate new storage. + _M_clear(); + _M_impl = __other._M_impl._M_clone(_M_alloc); + } + else + { + // Current storage is large enough. + _M_impl._M_resize(0, _M_alloc); + _M_impl._M_assign(__other._M_impl, _M_alloc); + } + } + + if constexpr (__pocma) + _M_alloc = std::move(__other._M_alloc); + + return *this; + } + + constexpr ~basic_stacktrace() + { + _M_clear(); + } + + // [stacktrace.basic.obs], observers + allocator_type get_allocator() const noexcept { return _M_alloc; } + + const_iterator + begin() const noexcept + { return const_iterator{_M_impl._M_frames}; } + + const_iterator + end() const noexcept + { return begin() + size(); } + + const_reverse_iterator + rbegin() const noexcept + { return std::make_reverse_iterator(end()); } + + const_reverse_iterator + rend() const noexcept + { return std::make_reverse_iterator(begin()); } + + const_iterator cbegin() const noexcept { return begin(); } + const_iterator cend() const noexcept { return end(); } + const_reverse_iterator crbegin() const noexcept { return rbegin(); }; + const_reverse_iterator crend() const noexcept { return rend(); }; + + [[nodiscard]] bool empty() const noexcept { return size() == 0; } + size_type size() const noexcept { return _M_impl._M_size; } + + size_type + max_size() const noexcept + { return _Impl::_S_max_size(_M_impl._M_alloc); } + + const_reference + operator[](size_type __n) const noexcept + { + __glibcxx_assert(__n < size()); + return begin()[__n]; + } + + const_reference + at(size_type __n) const + { + if (__n >= size()) + __throw_out_of_range("basic_stack_trace::at: bad frame number"); + return begin()[__n]; + } + + // [stacktrace.basic.cmp], comparisons + template<typename _Allocator2> + friend bool + operator==(const basic_stacktrace& __x, + const basic_stacktrace<_Allocator2>& __y) noexcept + { return std::equal(__x.begin(), __x.end(), __y.begin(), __y.end()); } + + template<typename _Allocator2> + friend strong_ordering + operator<=>(const basic_stacktrace& __x, + const basic_stacktrace<_Allocator2>& __y) noexcept + { + if (auto __s = __x.size() <=> __y.size(); __s != 0) + return __s; + return std::lexicographical_compare_three_way(__x.begin(), __x.end(), + __y.begin(), __y.end()); + } + + // [stacktrace.basic.mod], modifiers + void + swap(basic_stacktrace& __other) noexcept + { + std::swap(_M_impl, __other._M_impl); + if constexpr (_AllocTraits::propagate_on_container_swap::value) + std::swap(_M_alloc, __other._M_alloc); + else if constexpr (!_AllocTraits::is_always_equal::value) + { + __glibcxx_assert(_M_alloc == __other._M_alloc); + } + } + + private: + bool + _M_push_back(const value_type& __x) noexcept + { + return _M_impl._M_push_back(_M_alloc, __x); + } + + void + _M_clear() noexcept + { + _M_impl._M_resize(0, _M_alloc); + _M_impl._M_deallocate(_M_alloc); + } + + // Precondition: __max_depth != 0 + auto + _M_prepare(size_type __max_depth = -1) noexcept + -> int (*) (void*, uintptr_t) + { + auto __cb = +[](void* __data, uintptr_t __pc) { + auto& __s = *static_cast<basic_stacktrace*>(__data); + stacktrace_entry __f; + __f._M_pc = __pc; + if (__s._M_push_back(__f)) [[likely]] + return 0; // continue tracing + return -1; // stop tracing due to error + }; + + if (__max_depth > 128) + __max_depth = 64; // soft limit, _M_push_back will reallocate + else + __cb = [](void* __data, uintptr_t __pc) { + auto& __s = *static_cast<basic_stacktrace*>(__data); + stacktrace_entry __f; + __f._M_pc = __pc; + if (__s.size() == __s._M_impl._M_capacity) [[unlikely]] + return 1; // stop tracing due to reaching max depth + if (__s._M_push_back(__f)) [[likely]] + return 0; // continue tracing + return -1; // stop tracing due to error + }; + + if (_M_impl._M_allocate(_M_alloc, __max_depth)) [[likely]] + return __cb; + return nullptr; + } + + struct _Impl + { + using pointer = typename _AllocTraits::pointer; + + pointer _M_frames = nullptr; + size_type _M_size = 0; + size_type _M_capacity = 0; + + static size_type + _S_max_size(const allocator_type& __alloc) noexcept + { + const size_t __size_max = __gnu_cxx::__int_traits<size_type>::__max; + const size_t __alloc_max = _AllocTraits::max_size(__alloc); + return std::min(__size_max, __alloc_max); + } + +#if __has_builtin(__builtin_operator_new) >= 201802L +# define _GLIBCXX_OPERATOR_NEW __builtin_operator_new +# define _GLIBCXX_OPERATOR_DELETE __builtin_operator_delete +#else +# define _GLIBCXX_OPERATOR_NEW ::operator new +# define _GLIBCXX_OPERATOR_DELETE ::operator delete +#endif + + // Precondition: _M_frames == nullptr && __n != 0 + pointer + _M_allocate(allocator_type& __alloc, size_type __n) noexcept + { + if (__n <= _S_max_size(__alloc)) [[likely]] + { + if constexpr (is_same_v<allocator_type, allocator<value_type>>) + { + // For std::allocator we use nothrow-new directly so we + // don't need to handle bad_alloc exceptions. + size_t __nb = __n * sizeof(value_type); + void* const __p = _GLIBCXX_OPERATOR_NEW (__nb, nothrow_t{}); + if (__p == nullptr) [[unlikely]] + return nullptr; + _M_frames = static_cast<pointer>(__p); + } + else + { + __try + { + _M_frames = __alloc.allocate(__n); + } + __catch (const std::bad_alloc&) + { + return nullptr; + } + } + _M_capacity = __n; + return _M_frames; + } + return nullptr; + } + + void + _M_deallocate(allocator_type& __alloc) noexcept + { + if (_M_capacity) + { + if constexpr (is_same_v<allocator_type, allocator<value_type>>) + _GLIBCXX_OPERATOR_DELETE (static_cast<void*>(_M_frames), + _M_capacity * sizeof(value_type)); + else + __alloc.deallocate(_M_frames, _M_capacity); + _M_frames = nullptr; + _M_capacity = 0; + } + } + +#undef _GLIBCXX_OPERATOR_DELETE +#undef _GLIBCXX_OPERATOR_NEW + + // Precondition: __n <= _M_size + void + _M_resize(size_type __n, allocator_type& __alloc) noexcept + { + for (size_type __i = __n; __i < _M_size; ++__i) + _AllocTraits::destroy(__alloc, &_M_frames[__i]); + _M_size = __n; + } + + bool + _M_push_back(allocator_type& __alloc, + const stacktrace_entry& __f) noexcept + { + if (_M_size == _M_capacity) [[unlikely]] + { + _Impl __tmp = _M_xclone(_M_capacity ? _M_capacity : 8, __alloc); + if (!__tmp._M_capacity) [[unlikely]] + return false; + _M_resize(0, __alloc); + _M_deallocate(__alloc); + *this = __tmp; + } + stacktrace_entry* __addr = std::to_address(_M_frames + _M_size++); + _AllocTraits::construct(__alloc, __addr, __f); + return true; + } + + // Precondition: _M_size != 0 + _Impl + _M_clone(allocator_type& __alloc) const noexcept + { + return _M_xclone(_M_size, __alloc); + } + + // Precondition: _M_size != 0 || __extra != 0 + _Impl + _M_xclone(size_type __extra, allocator_type& __alloc) const noexcept + { + _Impl __i; + if (__i._M_allocate(__alloc, _M_size + __extra)) [[likely]] + __i._M_assign(*this, __alloc); + return __i; + } + + // Precondition: _M_capacity >= __other._M_size + void + _M_assign(const _Impl& __other, allocator_type& __alloc) noexcept + { + std::__uninitialized_copy_a(__other._M_frames, + __other._M_frames + __other._M_size, + _M_frames, __alloc); + _M_size = __other._M_size; + } + }; + + [[no_unique_address]] allocator_type _M_alloc{}; + + _Impl _M_impl{}; + }; + + // basic_stacktrace typedef names + using stacktrace = basic_stacktrace<allocator<stacktrace_entry>>; + + // [stacktrace.basic.nonmem], non-member functions + template<typename _Allocator> + inline void + swap(basic_stacktrace<_Allocator>& __a, basic_stacktrace<_Allocator>& __b) + noexcept(noexcept(__a.swap(__b))) + { __a.swap(__b); } + + inline ostream& + operator<<(ostream& __os, const stacktrace_entry& __f) + { + string __desc, __file; + int __line; + if (__f._M_get_info(&__desc, &__file, &__line)) + { + __os.width(4); + __os << __desc << " at " << __file << ':' << __line; + } + return __os; + } + + template<typename _Allocator> + inline ostream& + operator<<(ostream& __os, const basic_stacktrace<_Allocator>& __st) + { + for (stacktrace::size_type __i = 0; __i < __st.size(); ++__i) + { + __os.width(4); + __os << __i << "# " << __st[__i] << '\n'; + } + return __os; + } + + inline string + to_string(const stacktrace_entry& __f) + { + std::ostringstream __os; + __os << __f; + return std::move(__os).str(); + } + + template<typename _Allocator> + string + to_string(const basic_stacktrace<_Allocator>& __st) + { + std::ostringstream __os; + __os << __st; + return std::move(__os).str(); + } + + namespace pmr + { + using stacktrace + = basic_stacktrace<polymorphic_allocator<stacktrace_entry>>; + } + + // [stacktrace.basic.hash], hash support + + template<> + struct hash<stacktrace_entry> + { + size_t + operator()(const stacktrace_entry& __f) const noexcept + { + using __h = hash<stacktrace_entry::native_handle_type>; + return __h()(__f.native_handle()); + } + }; + + template<typename _Allocator> + struct hash<basic_stacktrace<_Allocator>> + { + size_t + operator()(const basic_stacktrace<_Allocator>& __st) const noexcept + { + hash<stacktrace_entry::native_handle_type> __h; + size_t __val = _Hash_impl::hash(__st.size()); + for (const auto& __f : __st) + __val = _Hash_impl::__hash_combine(__h(__f), __val); + return __val; + } + }; + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace std +#endif // C++23 + +#endif /* _GLIBCXX_STACKTRACE */ |