github.com/searKing/golang/go@v1.2.117/os/signal/cgo/include/boost/stacktrace/detail/collect_unwind.ipp (about) 1 // Copyright Antony Polukhin, 2016-2023. 2 // 3 // Distributed under the Boost Software License, Version 1.0. (See 4 // accompanying file LICENSE_1_0.txt or copy at 5 // http://www.boost.org/LICENSE_1_0.txt) 6 7 #ifndef BOOST_STACKTRACE_DETAIL_COLLECT_UNWIND_IPP 8 #define BOOST_STACKTRACE_DETAIL_COLLECT_UNWIND_IPP 9 10 #include <boost/config.hpp> 11 #ifdef BOOST_HAS_PRAGMA_ONCE 12 # pragma once 13 #endif 14 15 #include <boost/stacktrace/safe_dump_to.hpp> 16 17 // On iOS 32-bit ARM architecture _Unwind_Backtrace function doesn't exist, symbol is undefined. 18 // Forcing libc backtrace() function usage. 19 #include <boost/predef.h> 20 #if defined(BOOST_OS_IOS_AVAILABLE) && defined(BOOST_ARCH_ARM_AVAILABLE) && BOOST_VERSION_NUMBER_MAJOR(BOOST_ARCH_ARM) < 8 21 #define BOOST_STACKTRACE_USE_LIBC_BACKTRACE_FUNCTION 22 #endif 23 24 #if defined(BOOST_STACKTRACE_USE_LIBC_BACKTRACE_FUNCTION) 25 #include <execinfo.h> 26 #include <algorithm> 27 #else 28 #include <unwind.h> 29 #endif 30 #include <cstdio> 31 32 #if !defined(_GNU_SOURCE) && !defined(BOOST_STACKTRACE_GNU_SOURCE_NOT_REQUIRED) && !defined(BOOST_WINDOWS) 33 #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`." 34 #endif 35 36 namespace boost { namespace stacktrace { namespace detail { 37 38 #if !defined(BOOST_STACKTRACE_USE_LIBC_BACKTRACE_FUNCTION) 39 struct unwind_state { 40 std::size_t frames_to_skip; 41 native_frame_ptr_t* current; 42 native_frame_ptr_t* end; 43 }; 44 45 inline _Unwind_Reason_Code unwind_callback(::_Unwind_Context* context, void* arg) { 46 // Note: do not write `::_Unwind_GetIP` because it is a macro on some platforms. 47 // Use `_Unwind_GetIP` instead! 48 unwind_state* const state = static_cast<unwind_state*>(arg); 49 if (state->frames_to_skip) { 50 --state->frames_to_skip; 51 return _Unwind_GetIP(context) ? ::_URC_NO_REASON : ::_URC_END_OF_STACK; 52 } 53 54 *state->current = reinterpret_cast<native_frame_ptr_t>( 55 _Unwind_GetIP(context) 56 ); 57 58 ++state->current; 59 if (!*(state->current - 1) || state->current == state->end) { 60 return ::_URC_END_OF_STACK; 61 } 62 return ::_URC_NO_REASON; 63 } 64 #endif //!defined(BOOST_STACKTRACE_USE_LIBC_BACKTRACE_FUNCTION) 65 66 std::size_t this_thread_frames::collect(native_frame_ptr_t* out_frames, std::size_t max_frames_count, std::size_t skip) noexcept { 67 std::size_t frames_count = 0; 68 if (!max_frames_count) { 69 return frames_count; 70 } 71 skip += 1; 72 73 #if defined(BOOST_STACKTRACE_USE_LIBC_BACKTRACE_FUNCTION) 74 // According to https://opensource.apple.com/source/Libc/Libc-1272.200.26/gen/backtrace.c.auto.html 75 // it looks like the `::backtrace` is async signal safe. 76 frames_count = static_cast<size_t>(::backtrace(const_cast<void **>(out_frames), static_cast<int>(max_frames_count))); 77 78 // NOTE: There is no way to pass "skip" count to backtrace function so we need to perform left shift operation. 79 // If number of elements in result backtrace is >= max_frames_count then "skip" elements are wasted. 80 if (frames_count && skip) { 81 if (skip >= frames_count) { 82 frames_count = 0; 83 } else { 84 std::copy(out_frames + skip, out_frames + frames_count, out_frames); 85 frames_count -= skip; 86 } 87 } 88 #else 89 boost::stacktrace::detail::unwind_state state = { skip, out_frames, out_frames + max_frames_count }; 90 ::_Unwind_Backtrace(&boost::stacktrace::detail::unwind_callback, &state); 91 frames_count = state.current - out_frames; 92 #endif //defined(BOOST_STACKTRACE_USE_LIBC_BACKTRACE_FUNCTION) 93 94 if (frames_count && out_frames[frames_count - 1] == 0) { 95 -- frames_count; 96 } 97 98 return frames_count; 99 } 100 101 102 }}} // namespace boost::stacktrace::detail 103 104 #undef BOOST_STACKTRACE_USE_LIBC_BACKTRACE_FUNCTION 105 106 #endif // BOOST_STACKTRACE_DETAIL_COLLECT_UNWIND_IPP