diff options
Diffstat (limited to 'boost/stacktrace/detail/collect_unwind.ipp')
-rw-r--r-- | boost/stacktrace/detail/collect_unwind.ipp | 40 |
1 files changed, 37 insertions, 3 deletions
diff --git a/boost/stacktrace/detail/collect_unwind.ipp b/boost/stacktrace/detail/collect_unwind.ipp index f7c1f82f2b..f03aebf5bb 100644 --- a/boost/stacktrace/detail/collect_unwind.ipp +++ b/boost/stacktrace/detail/collect_unwind.ipp @@ -1,4 +1,4 @@ -// Copyright Antony Polukhin, 2016-2018. +// Copyright Antony Polukhin, 2016-2019. // // Distributed under the Boost Software License, Version 1.0. (See // accompanying file LICENSE_1_0.txt or copy at @@ -14,7 +14,19 @@ #include <boost/stacktrace/safe_dump_to.hpp> +// On iOS 32-bit ARM architecture _Unwind_Backtrace function doesn't exist, symbol is undefined. +// Forcing libc backtrace() function usage. +#include <boost/predef.h> +#if defined(BOOST_OS_IOS_AVAILABLE) && defined(BOOST_ARCH_ARM_AVAILABLE) && BOOST_VERSION_NUMBER_MAJOR(BOOST_ARCH_ARM) < 8 +#define BOOST_STACKTRACE_USE_LIBC_BACKTRACE_FUNCTION +#endif + +#if defined(BOOST_STACKTRACE_USE_LIBC_BACKTRACE_FUNCTION) +#include <execinfo.h> +#include <algorithm> +#else #include <unwind.h> +#endif #include <cstdio> #if !defined(_GNU_SOURCE) && !defined(BOOST_STACKTRACE_GNU_SOURCE_NOT_REQUIRED) && !defined(BOOST_WINDOWS) @@ -23,6 +35,7 @@ namespace boost { namespace stacktrace { namespace detail { +#if !defined(BOOST_STACKTRACE_USE_LIBC_BACKTRACE_FUNCTION) struct unwind_state { std::size_t frames_to_skip; native_frame_ptr_t* current; @@ -48,16 +61,35 @@ inline _Unwind_Reason_Code unwind_callback(::_Unwind_Context* context, void* arg } return ::_URC_NO_REASON; } +#endif //!defined(BOOST_STACKTRACE_USE_LIBC_BACKTRACE_FUNCTION) std::size_t this_thread_frames::collect(native_frame_ptr_t* out_frames, std::size_t max_frames_count, std::size_t skip) BOOST_NOEXCEPT { std::size_t frames_count = 0; if (!max_frames_count) { return frames_count; } - - boost::stacktrace::detail::unwind_state state = { skip + 1, out_frames, out_frames + max_frames_count }; + skip += 1; + +#if defined(BOOST_STACKTRACE_USE_LIBC_BACKTRACE_FUNCTION) + // According to https://opensource.apple.com/source/Libc/Libc-1272.200.26/gen/backtrace.c.auto.html + // it looks like the `::backtrace` is async signal safe. + frames_count = static_cast<size_t>(::backtrace(const_cast<void **>(out_frames), static_cast<int>(max_frames_count))); + + // NOTE: There is no way to pass "skip" count to backtrace function so we need to perform left shift operation. + // If number of elements in result backtrace is >= max_frames_count then "skip" elements are wasted. + if (frames_count && skip) { + if (skip >= frames_count) { + frames_count = 0; + } else { + std::copy(out_frames + skip, out_frames + frames_count, out_frames); + frames_count -= skip; + } + } +#else + boost::stacktrace::detail::unwind_state state = { skip, out_frames, out_frames + max_frames_count }; ::_Unwind_Backtrace(&boost::stacktrace::detail::unwind_callback, &state); frames_count = state.current - out_frames; +#endif //defined(BOOST_STACKTRACE_USE_LIBC_BACKTRACE_FUNCTION) if (frames_count && out_frames[frames_count - 1] == 0) { -- frames_count; @@ -69,4 +101,6 @@ std::size_t this_thread_frames::collect(native_frame_ptr_t* out_frames, std::siz }}} // namespace boost::stacktrace::detail +#undef BOOST_STACKTRACE_USE_LIBC_BACKTRACE_FUNCTION + #endif // BOOST_STACKTRACE_DETAIL_COLLECT_UNWIND_IPP |