31 uint32_t frame_index{0};
45 [[nodiscard]]
constexpr bool is_null() const noexcept {
return fp == 0 && pc == 0; }
78 uintptr_t &next_pc)
noexcept;
90 std::enable_if_t<std::is_void_v<typename Traits::context_type>,
int> = 0>
91 constexpr explicit
frame_unwinder_ref(ArchTag) noexcept : ctx_(
nullptr), vtbl_(&s_vtbl<ArchTag>) {}
96 template <
typename ArchTag,
typename Context,
typename Traits = frame_unwinder_traits<ArchTag>,
97 std::enable_if_t<!std::is_
void_v<
typename Traits::context_type> &&
98 std::is_convertible_v<const Context *, const
typename Traits::context_type *>,
101 const Context &ctx RELOCO_LIFETIMEBOUND RELOCO_LIFETIME_CAPTURE_BY_THIS) noexcept
102 : ctx_(&ctx), vtbl_(&s_vtbl<ArchTag>) {}
104 template <
typename ArchTag,
typename Context, std::enable_if_t<!std::is_lvalue_reference_v<Context>,
int> = 0>
107 template <
typename ArchTag,
typename Traits = frame_unwinder_traits<ArchTag>,
108 std::enable_if_t<std::is_
void_v<
typename Traits::context_type>,
int> = 0>
113 template <
typename ArchTag,
typename Context,
typename Traits = frame_unwinder_traits<ArchTag>,
114 std::enable_if_t<!std::is_
void_v<
typename Traits::context_type>,
int> = 0>
119 template <
typename ArchTag,
typename Context, std::enable_if_t<!std::is_lvalue_reference_v<Context>,
int> = 0>
136 uintptr_t &next_pc)
const noexcept {
139 return vtbl_->step(ctx_.get(), reg_ctx, current_pc, next_fp, next_pc);
142 [[nodiscard]]
constexpr explicit operator bool() const noexcept {
return vtbl_ !=
nullptr; }
145 template <
typename ArchTag>
146 static bool step_entry(
const void *context,
register_context_ref registers, uintptr_t current_pc, uintptr_t &next_fp,
147 uintptr_t &next_pc)
noexcept {
149 if constexpr (std::is_void_v<context_type>) {
152 const auto &typed_context = *
static_cast<const context_type *
>(context);
153 return frame_unwinder_traits<ArchTag>::step(value_ref<const context_type>(typed_context), registers, current_pc,
158 template <
typename ArchTag>
static constexpr vtable s_vtbl{&step_entry<ArchTag>};
160 value_ptr<const void> ctx_{};
161 const vtable *vtbl_{
nullptr};
164template <typename Tag, bool Stateless = std::is_void_v<typename frame_unwinder_traits<Tag>::context_type>>
174 [[nodiscard]]
constexpr value_ref<context_type>
context() &
noexcept RELOCO_LIFETIMEBOUND {
175 return value_ref<context_type>(context_);
178 [[nodiscard]]
constexpr value_ref<const context_type>
context() const & noexcept RELOCO_LIFETIMEBOUND {
179 return value_ref<const context_type>(context_);
186 value_ref<context_type>
context() && =
delete;
187 value_ref<const context_type>
context() const && = delete;
224 uintptr_t initial_pc) noexcept
225 : unwinder_(unwinder), reg_ctx_(reg_ctx), frame_{0, initial_fp, initial_pc},
226 is_valid_(initial_fp != 0 && initial_pc != 0) {}
231 [[nodiscard]]
constexpr bool has_value() const noexcept {
return is_valid_; }
232 [[nodiscard]]
constexpr explicit operator bool() const noexcept {
return is_valid_; }
242 uintptr_t next_fp = 0;
243 uintptr_t next_pc = 0;
245 if (!unwinder_.step(reg_ctx_, frame_.pc, next_fp, next_pc)) {
250 frame_.frame_index++;
261 template <
typename Visitor>
void for_each_frame(Visitor &&visitor, uint32_t max_depth = 64) noexcept {
262 while (is_valid_ && frame_.frame_index < max_depth) {
263 if (!visitor(frame_)) {
272 register_context_ref reg_ctx_{};
273 stack_frame frame_{};
274 bool is_valid_{
false};
295 uint32_t max_depth = 16) noexcept
296 : iter_(iter), resolver_(resolver), symbol_context_(&symbol_context), max_depth_(max_depth) {}
309 return *symbol_context_;
315 [[nodiscard]]
constexpr uint32_t
max_depth() const noexcept {
return max_depth_; }
321 symbol_resolver_ref resolver_{};
323 value_ptr<symbol_resolution_context> symbol_context_{};
325 uint32_t max_depth_{16};
345 auto spec = ctx.spec();
346 if (!spec.empty() && spec.front() ==
'#') {
369 remote_fn_ptr fn_sym(frame.
pc, view.resolver(), view.symbol_context());
Type-erased remote address-space access and remote string/object views.
Definition microfmt.hpp:881
Forward-only cursor iterating over a stack walk backed by register context.
Definition frame_pointer.hpp:207
constexpr bool has_value() const noexcept
Definition frame_pointer.hpp:231
void for_each_frame(Visitor &&visitor, uint32_t max_depth=64) noexcept
Definition frame_pointer.hpp:261
constexpr const stack_frame * operator->() const noexcept RELOCO_LIFETIMEBOUND
Definition frame_pointer.hpp:229
frame_pointer_iterator & operator++() noexcept
Definition frame_pointer.hpp:256
bool next() noexcept
Steps to the next (caller) frame using the unwinder and register context.
Definition frame_pointer.hpp:238
constexpr const stack_frame & operator*() const noexcept RELOCO_LIFETIMEBOUND
Definition frame_pointer.hpp:228
constexpr frame_pointer_iterator() noexcept=default
constexpr frame_unwinder_ref ref() const &noexcept RELOCO_LIFETIMEBOUND
Definition frame_pointer.hpp:182
value_ref< context_type > context() &&=delete
constexpr frame_unwinder(context_type context) noexcept
Definition frame_pointer.hpp:172
constexpr value_ref< context_type > context() &noexcept RELOCO_LIFETIMEBOUND
Definition frame_pointer.hpp:174
typename traits_type::context_type context_type
Definition frame_pointer.hpp:170
value_ref< const context_type > context() const &&=delete
constexpr value_ref< const context_type > context() const &noexcept RELOCO_LIFETIMEBOUND
Definition frame_pointer.hpp:178
static constexpr frame_unwinder_ref ref() noexcept
Definition frame_pointer.hpp:196
Type-erased, two-word handle to a frame unwinder.
Definition frame_pointer.hpp:68
constexpr frame_unwinder_ref(ArchTag, const Context &ctx RELOCO_LIFETIMEBOUND RELOCO_LIFETIME_CAPTURE_BY_THIS) noexcept
Constructs a handle for a stateful unwinder tag.
Definition frame_pointer.hpp:100
static constexpr frame_unwinder_ref make() noexcept
Definition frame_pointer.hpp:109
bool step(register_context_ref reg_ctx, uintptr_t current_pc, uintptr_t &next_fp, uintptr_t &next_pc) const noexcept
Advances from the current frame to its caller using register_context_ref.
Definition frame_pointer.hpp:135
static constexpr frame_unwinder_ref make(const Context &ctx RELOCO_LIFETIMEBOUND) noexcept
Definition frame_pointer.hpp:115
constexpr frame_unwinder_ref() noexcept=default
Constructs an empty (invalid) handle.
static frame_unwinder_ref make(Context &&)=delete
constexpr frame_unwinder_ref(ArchTag, Context &&)=delete
Definition frame_pointer.hpp:165
Zero-allocation, type-erased handle for inspecting and modifying CPU registers from a frame context.
Definition register_context.hpp:118
Formattable view rendering a remote backtrace.
Definition frame_pointer.hpp:284
constexpr frame_pointer_iterator iterator() const noexcept
Returns the underlying frame cursor.
Definition frame_pointer.hpp:302
constexpr symbol_resolver_ref resolver() const noexcept
Returns the symbol resolver handle.
Definition frame_pointer.hpp:307
constexpr uint32_t max_depth() const noexcept
Returns the maximum frame depth.
Definition frame_pointer.hpp:315
constexpr symbol_resolution_context & symbol_context() const noexcept RELOCO_LIFETIMEBOUND
Definition frame_pointer.hpp:308
constexpr remote_backtrace_view(frame_pointer_iterator iter, symbol_resolver_ref resolver, symbol_resolution_context &symbol_context RELOCO_LIFETIMEBOUND, uint32_t max_depth=16) noexcept
Constructs a backtrace view.
Definition frame_pointer.hpp:293
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
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
Remote fault formatting and diagnostics-aware remote pointer/struct views.
Virtual table of unwinder operations.
Definition frame_pointer.hpp:73
Static customization point describing a frame unwinder backend.
Definition frame_pointer.hpp:56
One frame record produced during stack unwinding.
Definition frame_pointer.hpp:27
uint32_t frame_index
Zero-based frame index (depth).
Definition frame_pointer.hpp:31
uintptr_t pc
Program counter (return address) of the frame.
Definition frame_pointer.hpp:39
uintptr_t fp
Frame/saved-stack pointer of the frame.
Definition frame_pointer.hpp:35
constexpr bool is_null() const noexcept
Reports whether the record is an empty sentinel.
Definition frame_pointer.hpp:45
Caller-owned temporary storage for one symbol resolution.
Definition symbol_resolver.hpp:100
Type-erased symbol resolution for remote addresses and formattable symbol views.