36 uint32_t frame_index{0};
73 bool (*match_trap_frame)(
const void *ctx, uintptr_t fp, uintptr_t pc, uintptr_t &out_trap_frame_addr)
noexcept;
88 std::enable_if_t<std::is_convertible_v<const Context *, const typename Traits::context_type *>,
int> = 0>
89 constexpr
exception_matcher_ref(Tag, const Context &ctx RELOCO_LIFETIMEBOUND RELOCO_LIFETIME_CAPTURE_BY_THIS) noexcept
90 : ctx_(&ctx), vtbl_(&s_vtbl<Tag>) {}
92 template <
typename Tag,
typename Context, std::enable_if_t<!std::is_lvalue_reference_v<Context>,
int> = 0>
95 template <
typename Tag,
typename Context,
typename Traits = exception_matcher_traits<Tag>>
100 template <
typename Tag,
typename Context, std::enable_if_t<!std::is_lvalue_reference_v<Context>,
int> = 0>
110 [[nodiscard]]
bool match_trap_frame(uintptr_t fp, uintptr_t pc, uintptr_t &out_trap_frame_addr)
const noexcept {
113 return vtbl_->match_trap_frame(ctx_.get(), fp, pc, out_trap_frame_addr);
120 [[nodiscard]]
constexpr explicit operator bool() const noexcept {
return vtbl_ !=
nullptr; }
123 template <
typename Tag>
124 static constexpr vtable s_vtbl{[](
const void *context, uintptr_t fp, uintptr_t pc, uintptr_t &out_addr)
noexcept {
126 const auto &typed_context = *
static_cast<const context_type *
>(context);
131 value_ptr<const void> ctx_{};
132 const vtable *vtbl_{
nullptr};
145 [[nodiscard]]
constexpr value_ref<context_type>
context() &
noexcept RELOCO_LIFETIMEBOUND {
146 return value_ref<context_type>(context_);
149 [[nodiscard]]
constexpr value_ref<const context_type>
context() const & noexcept RELOCO_LIFETIMEBOUND {
150 return value_ref<const context_type>(context_);
159 value_ref<context_type>
context() && =
delete;
160 value_ref<const context_type>
context() const && = delete;
189 uintptr_t initial_pc) noexcept
190 : fp_unwinder_(fp_unwinder), trap_decoder_(trap_decoder), matcher_(matcher), reg_ctx_(reg_ctx),
191 current_{0, initial_fp, initial_pc, frame_kind::standard, {}}, is_valid_(initial_fp != 0 || initial_pc != 0) {}
208 [[nodiscard]]
constexpr bool has_value() const noexcept {
return is_valid_; }
213 [[nodiscard]]
constexpr explicit operator bool() const noexcept {
return is_valid_; }
228 uintptr_t trap_frame_addr = 0;
229 if (matcher_ && matcher_.match_trap_frame(current_.fp, current_.pc, trap_frame_addr)) {
231 if (trap_decoder_ && trap_decoder_.decode(trap_frame_addr, current_.trap)) {
233 current_.frame_index++;
234 current_.kind = frame_kind::trap_transition;
235 current_.fp = current_.trap.fp;
236 current_.pc = current_.trap.pc;
242 uintptr_t next_fp = 0;
243 uintptr_t next_pc = 0;
244 if (!fp_unwinder_.step(reg_ctx_, current_.pc, next_fp, next_pc)) {
249 current_.frame_index++;
250 current_.kind = frame_kind::standard;
251 current_.fp = next_fp;
252 current_.pc = next_pc;
272 template <
typename Visitor>
void for_each_frame(Visitor &&visitor, uint32_t max_depth = 64) noexcept {
273 while (is_valid_ && current_.frame_index < max_depth) {
274 if (!visitor(current_)) {
285 exception_frame_ref trap_decoder_{};
287 exception_matcher_ref matcher_{};
289 register_context_ref reg_ctx_{};
291 hybrid_frame current_{};
293 bool is_valid_{
false};
315 uint32_t max_depth = 32) noexcept
316 : unwinder_(&unwinder), resolver_(resolver), symbol_context_(&symbol_context), max_depth_(max_depth) {}
329 return *symbol_context_;
335 [[nodiscard]]
constexpr uint32_t
max_depth() const noexcept {
return max_depth_; }
339 value_ptr<hybrid_stack_unwinder> unwinder_;
343 value_ptr<symbol_resolution_context> symbol_context_{};
345 uint32_t max_depth_{32};
366 auto spec = ctx.spec();
367 if (!spec.empty() && spec.front() ==
'#') {
388 if (frame.
kind == frame_kind::trap_transition) {
389 out.write(
" --- [Exception Boundary: ");
390 if (frame.trap.is_user_mode) {
391 out.write(
"User -> Kernel");
393 out.write(
"Nested Fault");
400 remote_fn_ptr fn_sym(frame.
pc, view.resolver(), view.symbol_context());
Type-erased, two-word handle decoding exception/trap frames.
Definition exception_frame.hpp:79
Type-erased hook detecting exception trampolines during unwinding.
Definition hybrid_unwinder.hpp:63
static constexpr exception_matcher_ref make(const Context &ctx RELOCO_LIFETIMEBOUND) noexcept
Definition hybrid_unwinder.hpp:96
constexpr exception_matcher_ref(Tag, Context &&)=delete
static exception_matcher_ref make(Context &&)=delete
bool match_trap_frame(uintptr_t fp, uintptr_t pc, uintptr_t &out_trap_frame_addr) const noexcept
Tests whether (fp, pc) is an exception trampoline.
Definition hybrid_unwinder.hpp:110
constexpr exception_matcher_ref() noexcept=default
Constructs an empty (invalid) matcher.
Typed owner for an exception-matcher traits specialization.
Definition hybrid_unwinder.hpp:138
constexpr value_ref< const context_type > context() const &noexcept RELOCO_LIFETIMEBOUND
Definition hybrid_unwinder.hpp:149
constexpr exception_matcher_ref ref() const &noexcept RELOCO_LIFETIMEBOUND
Definition hybrid_unwinder.hpp:153
value_ref< context_type > context() &&=delete
constexpr value_ref< context_type > context() &noexcept RELOCO_LIFETIMEBOUND
Definition hybrid_unwinder.hpp:145
value_ref< const context_type > context() const &&=delete
typename traits_type::context_type context_type
Definition hybrid_unwinder.hpp:141
constexpr exception_matcher(context_type context) noexcept
Definition hybrid_unwinder.hpp:143
Definition microfmt.hpp:881
Type-erased, two-word handle to a frame unwinder.
Definition frame_pointer.hpp:68
Formattable view rendering a hybrid backtrace.
Definition hybrid_unwinder.hpp:303
constexpr symbol_resolver_ref resolver() const noexcept
Returns the symbol resolver handle.
Definition hybrid_unwinder.hpp:327
constexpr hybrid_stack_unwinder & unwinder() const noexcept RELOCO_LIFETIMEBOUND
Returns the underlying unwinder.
Definition hybrid_unwinder.hpp:322
constexpr symbol_resolution_context & symbol_context() const noexcept RELOCO_LIFETIMEBOUND
Definition hybrid_unwinder.hpp:328
constexpr hybrid_backtrace_view(hybrid_stack_unwinder &unwinder RELOCO_LIFETIMEBOUND, symbol_resolver_ref resolver, symbol_resolution_context &symbol_context RELOCO_LIFETIMEBOUND, uint32_t max_depth=32) noexcept
Constructs a hybrid backtrace view.
Definition hybrid_unwinder.hpp:312
constexpr uint32_t max_depth() const noexcept
Returns the maximum frame depth.
Definition hybrid_unwinder.hpp:335
Forward-only cursor combining frame-pointer stepping with exception/trap transitions.
Definition hybrid_unwinder.hpp:176
constexpr hybrid_stack_unwinder(frame_unwinder_ref fp_unwinder, exception_frame_ref trap_decoder, exception_matcher_ref matcher, register_context_ref reg_ctx, uintptr_t initial_fp, uintptr_t initial_pc) noexcept
Constructs a hybrid unwinder.
Definition hybrid_unwinder.hpp:187
constexpr bool has_value() const noexcept
Reports whether the cursor is positioned on a frame.
Definition hybrid_unwinder.hpp:208
hybrid_stack_unwinder & operator++() noexcept
Pre-increment advancing to the next frame.
Definition hybrid_unwinder.hpp:260
void for_each_frame(Visitor &&visitor, uint32_t max_depth=64) noexcept
Visitor-style traversal over the hybrid frame chain.
Definition hybrid_unwinder.hpp:272
bool next() noexcept
Advances to the next frame.
Definition hybrid_unwinder.hpp:223
constexpr const hybrid_frame & operator*() const noexcept
Returns the current frame record.
Definition hybrid_unwinder.hpp:197
constexpr const hybrid_frame * operator->() const noexcept
Returns the current frame record.
Definition hybrid_unwinder.hpp:202
Zero-allocation, type-erased handle for inspecting and modifying CPU registers from a frame context.
Definition register_context.hpp:118
Symbolic view of a remote function / code pointer.
Definition remote_diagnostics.hpp:82
Type-erased, two-word handle to a symbol resolver.
Definition symbol_resolver.hpp:132
#define MICROFMT_API_CLASS
Definition compat.hpp:181
Trap/exception frame decoding, iteration, and formattable trap summaries.
Type-erased frame unwinder handles, frame cursor iteration, and backtrace views.
reloco::sink sink
Type-erased, zero-allocation output sink.
Definition microfmt.hpp:46
RELOCO_CONSTEXPR20 void format_to(const sink &out, microfmt::string_view fmt, const Args &...args) noexcept
Definition microfmt.hpp:1766
frame_kind
Classifies a hybrid_frame as either a normal stack frame or a trap transition.
Definition hybrid_unwinder.hpp:27
Virtual table of matcher operations.
Definition hybrid_unwinder.hpp:68
Definition hybrid_unwinder.hpp:17
One frame record produced during hybrid unwinding.
Definition hybrid_unwinder.hpp:32
uintptr_t fp
Frame/saved-stack pointer of the frame.
Definition hybrid_unwinder.hpp:40
trap_context trap
Trap context, valid when kind is frame_kind::trap_transition.
Definition hybrid_unwinder.hpp:53
uintptr_t pc
Program counter (return address) of the frame.
Definition hybrid_unwinder.hpp:44
frame_kind kind
Frame classification.
Definition hybrid_unwinder.hpp:48
uint32_t frame_index
Zero-based frame index (depth).
Definition hybrid_unwinder.hpp:36
Caller-owned temporary storage for one symbol resolution.
Definition symbol_resolver.hpp:100
Normalized, architecture-independent snapshot of a trap context.
Definition exception_frame.hpp:27
uint64_t vector_or_reason
Vector number, trap error code, or exception syndrome register.
Definition exception_frame.hpp:55