6
6
#include " utils/replace_all.hpp"
7
7
#include " snippets/snippet.hpp"
8
8
9
+ #include < algorithm>
9
10
#include < cstdio>
10
11
#include < string>
11
12
#include < functional>
@@ -69,6 +70,7 @@ CPPTRACE_BEGIN_NAMESPACE
69
70
bool columns = true ;
70
71
symbol_mode symbols = symbol_mode::full;
71
72
bool show_filtered_frames = true ;
73
+ bool hide_exception_machinery = true ;
72
74
std::function<bool (const stacktrace_frame&)> filter;
73
75
std::function<stacktrace_frame(stacktrace_frame)> transform;
74
76
} options;
@@ -110,6 +112,9 @@ CPPTRACE_BEGIN_NAMESPACE
110
112
void break_before_filename (bool do_break) {
111
113
options.break_before_filename = do_break;
112
114
}
115
+ void hide_exception_machinery (bool do_hide) {
116
+ options.hide_exception_machinery = do_hide;
117
+ }
113
118
114
119
std::string format (
115
120
const stacktrace_frame& frame,
@@ -213,6 +218,25 @@ CPPTRACE_BEGIN_NAMESPACE
213
218
return do_color;
214
219
}
215
220
221
+ size_t get_trace_start (const stacktrace& trace) const {
222
+ if (!options.hide_exception_machinery ) {
223
+ return 0 ;
224
+ }
225
+ // Look for c++ exception machinery and skip it if it's present, otherwise start at the beginning
226
+ // On itanium this is identifiable by __cxa_throw
227
+ // https://itanium-cxx-abi.github.io/cxx-abi/abi-eh.html 2.4.1
228
+ // On windows this is identifiable by CxxThrowException (maybe with an underscore?)
229
+ // https://www.youtube.com/watch?v=COEv2kq_Ht8 40:10
230
+ // https://github.com/CppCon/CppCon2018/blob/master/Presentations/unwinding_the_stack_exploring_how_cpp_exceptions_work_on_windows/unwinding_the_stack_exploring_how_cpp_exceptions_work_on_windows__james_mcnellis__cppcon_2018.pdf slide 157
231
+ // https://learn.microsoft.com/en-us/cpp/c-runtime-library/reference/cxxthrowexception?view=msvc-170
232
+ auto it = std::find_if (trace.begin (), trace.end (), [] (const stacktrace_frame& frame) {
233
+ return frame.symbol == " __cxa_throw"
234
+ || frame.symbol == " CxxThrowException"
235
+ || frame.symbol == " _CxxThrowException" ;
236
+ });
237
+ return it == trace.end () ? 0 : it - trace.begin () + 1 ;
238
+ }
239
+
216
240
void print_internal (std::ostream& stream, const stacktrace_frame& input_frame, detail::optional<bool > color_override, size_t col_indent) const {
217
241
bool color = should_do_color (stream, color_override);
218
242
maybe_ensure_virtual_terminal_processing (stream, color);
@@ -235,14 +259,14 @@ CPPTRACE_BEGIN_NAMESPACE
235
259
if (!options.header .empty ()) {
236
260
stream << options.header << ' \n ' ;
237
261
}
238
- std::size_t counter = 0 ;
239
262
const auto & frames = trace.frames ;
240
263
if (frames.empty ()) {
241
264
stream << " <empty trace>" ;
242
265
return ;
243
266
}
244
267
const auto frame_number_width = detail::n_digits (static_cast <int >(frames.size ()) - 1 );
245
- for (size_t i = 0 ; i < frames.size (); ++i) {
268
+ std::size_t counter = 0 ;
269
+ for (size_t i = get_trace_start (trace); i < frames.size (); ++i) {
246
270
detail::optional<stacktrace_frame> transformed_frame;
247
271
if (options.transform ) {
248
272
transformed_frame = options.transform (frames[i]);
@@ -429,6 +453,10 @@ CPPTRACE_BEGIN_NAMESPACE
429
453
pimpl->break_before_filename (do_break);
430
454
return *this ;
431
455
}
456
+ formatter& formatter::hide_exception_machinery (bool do_hide) {
457
+ pimpl->hide_exception_machinery (do_hide);
458
+ return *this ;
459
+ }
432
460
433
461
std::string formatter::format (const stacktrace_frame& frame) const {
434
462
return pimpl->format (frame);
0 commit comments