Skip to content

Commit ce63533

Browse files
committed
Hide exception machinery internals from stacktrace output
1 parent bdec6c9 commit ce63533

File tree

3 files changed

+33
-2
lines changed

3 files changed

+33
-2
lines changed

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -393,6 +393,7 @@ namespace cpptrace {
393393
formatter& filter(std::function<bool(const stacktrace_frame&)>);
394394
formatter& transform(std::function<stacktrace_frame(stacktrace_frame)>);
395395
formatter& break_before_filename(bool do_break = true);
396+
formatter& hide_exception_machinery(bool do_hide = true);
396397

397398
std::string format(const stacktrace_frame&) const;
398399
std::string format(const stacktrace_frame&, bool color) const;
@@ -432,6 +433,7 @@ Options:
432433
| `filter` | A predicate to filter frames with | None |
433434
| `transform` | A transformer which takes a stacktrace frame and modifies it | None |
434435
| `break_before_filename` | Print symbol and line source location on different lines | `false` |
436+
| `hide_exception_machinery` | Hide exception internals for current exception traces | `true` |
435437
436438
The `automatic` color mode attempts to detect if a stream that may be attached to a terminal. As such, it will not use
437439
colors for the `formatter::format` method and it may not be able to detect if some ostreams correspond to terminals or

include/cpptrace/formatting.hpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ CPPTRACE_BEGIN_NAMESPACE
5757
formatter& filter(std::function<bool(const stacktrace_frame&)>);
5858
formatter& transform(std::function<stacktrace_frame(stacktrace_frame)>);
5959
formatter& break_before_filename(bool do_break = true);
60+
formatter& hide_exception_machinery(bool do_hide = true);
6061

6162
std::string format(const stacktrace_frame&) const;
6263
std::string format(const stacktrace_frame&, bool color) const;

src/formatting.cpp

Lines changed: 30 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
#include "utils/replace_all.hpp"
77
#include "snippets/snippet.hpp"
88

9+
#include <algorithm>
910
#include <cstdio>
1011
#include <string>
1112
#include <functional>
@@ -69,6 +70,7 @@ CPPTRACE_BEGIN_NAMESPACE
6970
bool columns = true;
7071
symbol_mode symbols = symbol_mode::full;
7172
bool show_filtered_frames = true;
73+
bool hide_exception_machinery = true;
7274
std::function<bool(const stacktrace_frame&)> filter;
7375
std::function<stacktrace_frame(stacktrace_frame)> transform;
7476
} options;
@@ -110,6 +112,9 @@ CPPTRACE_BEGIN_NAMESPACE
110112
void break_before_filename(bool do_break) {
111113
options.break_before_filename = do_break;
112114
}
115+
void hide_exception_machinery(bool do_hide) {
116+
options.hide_exception_machinery = do_hide;
117+
}
113118

114119
std::string format(
115120
const stacktrace_frame& frame,
@@ -213,6 +218,25 @@ CPPTRACE_BEGIN_NAMESPACE
213218
return do_color;
214219
}
215220

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+
216240
void print_internal(std::ostream& stream, const stacktrace_frame& input_frame, detail::optional<bool> color_override, size_t col_indent) const {
217241
bool color = should_do_color(stream, color_override);
218242
maybe_ensure_virtual_terminal_processing(stream, color);
@@ -235,14 +259,14 @@ CPPTRACE_BEGIN_NAMESPACE
235259
if(!options.header.empty()) {
236260
stream << options.header << '\n';
237261
}
238-
std::size_t counter = 0;
239262
const auto& frames = trace.frames;
240263
if(frames.empty()) {
241264
stream << "<empty trace>";
242265
return;
243266
}
244267
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) {
246270
detail::optional<stacktrace_frame> transformed_frame;
247271
if(options.transform) {
248272
transformed_frame = options.transform(frames[i]);
@@ -429,6 +453,10 @@ CPPTRACE_BEGIN_NAMESPACE
429453
pimpl->break_before_filename(do_break);
430454
return *this;
431455
}
456+
formatter& formatter::hide_exception_machinery(bool do_hide) {
457+
pimpl->hide_exception_machinery(do_hide);
458+
return *this;
459+
}
432460

433461
std::string formatter::format(const stacktrace_frame& frame) const {
434462
return pimpl->format(frame);

0 commit comments

Comments
 (0)