1111#include " utils/microfmt.hpp"
1212#include " utils/utils.hpp"
1313#include " logging.hpp"
14+ #include " unwind/unwind.hpp"
1415
1516#ifndef _MSC_VER
1617 #include < string.h>
@@ -44,8 +45,7 @@ namespace detail {
4445 return rethrow_switch;
4546 }
4647
47- CPPTRACE_FORCE_NO_INLINE void collect_current_trace (std::size_t skip) {
48- auto trace = cpptrace::generate_raw_trace (skip + 1 );
48+ void save_current_trace (raw_trace trace) {
4949 if (get_rethrow_switch ()) {
5050 saved_rethrow_trace = lazy_trace_holder (std::move (trace));
5151 } else {
@@ -54,6 +54,33 @@ namespace detail {
5454 }
5555 }
5656
57+ #if defined(_MSC_VER) && defined(CPPTRACE_UNWIND_WITH_DBGHELP)
58+ CPPTRACE_FORCE_NO_INLINE void collect_current_trace (std::size_t skip, EXCEPTION_POINTERS * exception_ptrs) {
59+ try {
60+ #if defined(_M_IX86) || defined(__i386__)
61+ // skip one frame, first is CxxThrowException
62+ (void )skip;
63+ auto trace = raw_trace{detail::capture_frames (1 , SIZE_MAX , exception_ptrs)};
64+ #else
65+ (void )exception_ptrs;
66+ auto trace = raw_trace{detail::capture_frames (skip + 1 , SIZE_MAX )};
67+ #endif
68+ save_current_trace (std::move (trace));
69+ } catch (...) {
70+ detail::log_and_maybe_propagate_exception (std::current_exception ());
71+ }
72+ }
73+ #else
74+ CPPTRACE_FORCE_NO_INLINE void collect_current_trace (std::size_t skip) {
75+ try {
76+ auto trace = raw_trace{detail::capture_frames (skip + 1 , SIZE_MAX )};
77+ save_current_trace (std::move (trace));
78+ } catch (...) {
79+ detail::log_and_maybe_propagate_exception (std::current_exception ());
80+ }
81+ }
82+ #endif
83+
5784 #ifdef _MSC_VER
5885 // https://www.youtube.com/watch?v=COEv2kq_Ht8
5986 // https://github.com/tpn/pdfs/blob/master/2018%20CppCon%20Unwinding%20the%20Stack%20-%20Exploring%20how%20C%2B%2B%20Exceptions%20work%20on%20Windows%20-%20James%20McNellis.pdf
@@ -66,7 +93,7 @@ namespace detail {
6693 // - https://github.com/ecatmur/stacktrace-from-exception/blob/main/stacktrace-from-exception.cpp
6794 // - https://github.com/catboost/catboost/blob/master/contrib/libs/cxxsupp/libcxx/src/support/runtime/exception_pointer_msvc.ipp
6895 // - https://www.geoffchappell.com/studies/msvc/language/predefined/index.htm
69- #if defined _WIN64
96+ #ifdef _WIN64
7097 #pragma pack(push, 4)
7198 struct CatchableType {
7299 std::uint32_t properties;
@@ -85,19 +112,20 @@ namespace detail {
85112 };
86113 #pragma warning(disable:4200)
87114 #if IS_CLANG
88- #pragma clang diagnostic push
89- #pragma clang diagnostic ignored "-Wc99-extensions"
115+ #pragma clang diagnostic push
116+ #pragma clang diagnostic ignored "-Wc99-extensions"
90117 #endif
91118 struct CatchableTypeArray {
92119 uint32_t nCatchableTypes;
93120 int32_t arrayOfCatchableTypes[];
94121 };
95122 #if IS_CLANG
96- #pragma clang diagnostic pop
123+ #pragma clang diagnostic pop
97124 #endif
98125 #pragma warning (pop)
99126 #pragma pack(pop)
100127 #else
128+ using CatchableTypeArray = ::_CatchableTypeArray;
101129 using CatchableType = ::_CatchableType;
102130 using ThrowInfo = ::_ThrowInfo;
103131 #endif
@@ -583,14 +611,27 @@ CPPTRACE_BEGIN_NAMESPACE
583611 CPPTRACE_POP_EXTENSION_WARNINGS
584612 return false ;
585613 }
614+ CPPTRACE_FORCE_NO_INLINE
615+ void maybe_collect_trace (EXCEPTION_POINTERS * exception_ptrs, const std::type_info& type_info) {
616+ if (matches_exception (exception_ptrs, type_info)) {
617+ #ifdef CPPTRACE_UNWIND_WITH_DBGHELP
618+ collect_current_trace (2 , exception_ptrs);
619+ #else
620+ collect_current_trace (2 );
621+ #endif
622+ }
623+ }
586624 #else
587- bool check_can_catch (
625+ CPPTRACE_FORCE_NO_INLINE
626+ void maybe_collect_trace (
588627 const std::type_info* type,
589628 const std::type_info* throw_type,
590629 void ** throw_obj,
591630 unsigned outer
592631 ) {
593- return detail::can_catch (type, throw_type, throw_obj, outer);
632+ if (detail::can_catch (type, throw_type, throw_obj, outer)) {
633+ collect_current_trace (2 );
634+ }
594635 }
595636
596637 void do_prepare_unwind_interceptor (const std::type_info& type_info, bool (*can_catch)(const std::type_info*, const std::type_info*, void **, unsigned )) {
0 commit comments