#ifdef CPPTRACE_UNWIND_WITH_UNWIND #include "unwind.hpp" #include "../utils/common.hpp" #include "../utils/error.hpp" #include "../utils/utils.hpp" #include #include #include #include #include namespace cpptrace { namespace detail { struct unwind_state { std::size_t skip; std::size_t max_depth; std::vector& vec; }; _Unwind_Reason_Code unwind_callback(_Unwind_Context* context, void* arg) { unwind_state& state = *static_cast(arg); if(state.skip) { state.skip--; if(_Unwind_GetIP(context) == frame_ptr(0)) { return _URC_END_OF_STACK; } else { return _URC_NO_REASON; } } ASSERT( state.vec.size() < state.max_depth, "Somehow cpptrace::detail::unwind_callback is being called beyond the max_depth" ); int is_before_instruction = 0; frame_ptr ip = _Unwind_GetIPInfo(context, &is_before_instruction); if(!is_before_instruction && ip != frame_ptr(0)) { ip--; } if (ip == frame_ptr(0)) { return _URC_END_OF_STACK; } else { state.vec.push_back(ip); if(state.vec.size() >= state.max_depth) { return _URC_END_OF_STACK; } else { return _URC_NO_REASON; } } } CPPTRACE_FORCE_NO_INLINE std::vector capture_frames(std::size_t skip, std::size_t max_depth) { std::vector frames; unwind_state state{skip + 1, max_depth, frames}; _Unwind_Backtrace(unwind_callback, &state); // presumably thread-safe return frames; } CPPTRACE_FORCE_NO_INLINE std::size_t safe_capture_frames(frame_ptr*, std::size_t, std::size_t, std::size_t) { // Can't safe trace with _Unwind return 0; } } } #endif