File indexing completed on 2025-01-18 09:52:30
0001
0002
0003
0004
0005
0006
0007 #ifndef BOOST_STACKTRACE_DETAIL_COLLECT_UNWIND_IPP
0008 #define BOOST_STACKTRACE_DETAIL_COLLECT_UNWIND_IPP
0009
0010 #include <boost/config.hpp>
0011 #ifdef BOOST_HAS_PRAGMA_ONCE
0012 # pragma once
0013 #endif
0014
0015 #include <boost/stacktrace/safe_dump_to.hpp>
0016
0017
0018
0019 #include <boost/predef.h>
0020 #if defined(BOOST_OS_IOS_AVAILABLE) && defined(BOOST_ARCH_ARM_AVAILABLE) && BOOST_VERSION_NUMBER_MAJOR(BOOST_ARCH_ARM) < 8
0021 #define BOOST_STACKTRACE_USE_LIBC_BACKTRACE_FUNCTION
0022 #endif
0023
0024 #if defined(BOOST_STACKTRACE_USE_LIBC_BACKTRACE_FUNCTION)
0025 #include <execinfo.h>
0026 #include <algorithm>
0027 #else
0028 #include <unwind.h>
0029 #endif
0030 #include <cstdio>
0031
0032 #if !defined(_GNU_SOURCE) && !defined(BOOST_STACKTRACE_GNU_SOURCE_NOT_REQUIRED) && !defined(BOOST_WINDOWS)
0033 #error "Boost.Stacktrace requires `_Unwind_Backtrace` function. Define `_GNU_SOURCE` macro or `BOOST_STACKTRACE_GNU_SOURCE_NOT_REQUIRED` if _Unwind_Backtrace is available without `_GNU_SOURCE`."
0034 #endif
0035
0036 namespace boost { namespace stacktrace { namespace detail {
0037
0038 #if !defined(BOOST_STACKTRACE_USE_LIBC_BACKTRACE_FUNCTION)
0039 struct unwind_state {
0040 std::size_t frames_to_skip;
0041 native_frame_ptr_t* current;
0042 native_frame_ptr_t* end;
0043 };
0044
0045 inline _Unwind_Reason_Code unwind_callback(::_Unwind_Context* context, void* arg) {
0046
0047
0048 unwind_state* const state = static_cast<unwind_state*>(arg);
0049 if (state->frames_to_skip) {
0050 --state->frames_to_skip;
0051 return _Unwind_GetIP(context) ? ::_URC_NO_REASON : ::_URC_END_OF_STACK;
0052 }
0053
0054 *state->current = reinterpret_cast<native_frame_ptr_t>(
0055 _Unwind_GetIP(context)
0056 );
0057
0058 ++state->current;
0059 if (!*(state->current - 1) || state->current == state->end) {
0060 return ::_URC_END_OF_STACK;
0061 }
0062 return ::_URC_NO_REASON;
0063 }
0064 #endif
0065
0066 std::size_t this_thread_frames::collect(native_frame_ptr_t* out_frames, std::size_t max_frames_count, std::size_t skip) noexcept {
0067 std::size_t frames_count = 0;
0068 if (!max_frames_count) {
0069 return frames_count;
0070 }
0071 skip += 1;
0072
0073 #if defined(BOOST_STACKTRACE_USE_LIBC_BACKTRACE_FUNCTION)
0074
0075
0076 frames_count = static_cast<size_t>(::backtrace(const_cast<void **>(out_frames), static_cast<int>(max_frames_count)));
0077
0078
0079
0080 if (frames_count && skip) {
0081 if (skip >= frames_count) {
0082 frames_count = 0;
0083 } else {
0084 std::copy(out_frames + skip, out_frames + frames_count, out_frames);
0085 frames_count -= skip;
0086 }
0087 }
0088 #else
0089 boost::stacktrace::detail::unwind_state state = { skip, out_frames, out_frames + max_frames_count };
0090 ::_Unwind_Backtrace(&boost::stacktrace::detail::unwind_callback, &state);
0091 frames_count = state.current - out_frames;
0092 #endif
0093
0094 if (frames_count && out_frames[frames_count - 1] == 0) {
0095 -- frames_count;
0096 }
0097
0098 return frames_count;
0099 }
0100
0101
0102 }}}
0103
0104 #undef BOOST_STACKTRACE_USE_LIBC_BACKTRACE_FUNCTION
0105
0106 #endif