90 uintptr_t &next_fp, uintptr_t &next_pc)
noexcept {
94 if (!context->elf_img_storage || !context->enumerator)
100 typename AbiTraits::register_type current_sp = 0;
101 typename AbiTraits::register_type return_lr = 0;
102 if (!reg_ctx.read_raw(AbiTraits::sp_reg, ¤t_sp, AbiTraits::pointer_size))
104 if (!reg_ctx.read_raw(AbiTraits::ra_reg, &return_lr, AbiTraits::pointer_size))
107 uintptr_t fault_pc = AbiTraits::normalize_pc(current_pc);
108 uintptr_t virtual_sp =
static_cast<uintptr_t
>(current_sp);
109 bool unwind_applied =
false;
115 if (context->enumerator.find_by_pc(fault_pc, img) && img.
has_exidx()) {
118 size_t num_entries = (exidx_end - exidx_start) / 8;
121 size_t high = num_entries;
122 size_t match_index = num_entries;
126 size_t mid = low + (high - low) / 2;
127 uintptr_t entry_addr = exidx_start + (mid * 8);
129 if (!context->space.read_bytes(entry_addr, &prel31, 4))
133 if (fn_addr <= fault_pc) {
141 if (match_index != num_entries) {
142 uintptr_t word2_address = exidx_start + (match_index * 8) + 4;
143 uint32_t raw_unwind_data = 0;
145 if (context->space.read_bytes(word2_address, &raw_unwind_data, 4)) {
146 if (raw_unwind_data == 0x1)
154 if ((raw_unwind_data & 0x80000000U) != 0U) {
155 RELOCO_BEGIN_UNSAFE_BUFFER_USAGE;
160 RELOCO_END_UNSAFE_BUFFER_USAGE;
172 const auto updated_sp =
static_cast<typename AbiTraits::register_type
>(virtual_sp);
173 if (!reg_ctx.write_raw(AbiTraits::sp_reg, &updated_sp, AbiTraits::pointer_size))
179 const uint32_t fp_reg = resolve_fp_register<AbiTraits>(reg_ctx);
180 typename AbiTraits::register_type updated_fp = 0;
181 if (!reg_ctx.read_raw(fp_reg, &updated_fp, AbiTraits::pointer_size)) {
182 updated_fp = updated_sp;
185 typename AbiTraits::register_type updated_lr = 0;
186 if (!reg_ctx.read_raw(AbiTraits::ra_reg, &updated_lr, AbiTraits::pointer_size))
189 next_fp =
static_cast<uintptr_t
>(updated_fp);
190 next_pc = AbiTraits::normalize_pc(
static_cast<uintptr_t
>(updated_lr));
ARM EXIDX inline unwind bytecode decoder.
Binary search over sorted `.ARM.exidx` unwind tables.
Sequential multi-word `.ARM.extab` bytecode stream executor.
Type-erased, two-word handle to a remote address space.
Definition address_space.hpp:204
static RELOCO_UNSAFE_BUFFER_USAGE bool execute_bytecode(address_space_ref space, uint32_t unwind_word, uintptr_t &io_sp, uintptr_t &, register_context_ref reg_ctx) noexcept
Executes up to 3 inline unwind bytes from an exidx/extab word.
Definition arm_exidx_decoder.hpp:34
Type-erased, two-word handle to an ELF image enumerator.
Definition elf_enumerator.hpp:104
static constexpr uintptr_t decode_prel31(uintptr_t entry_addr, uint32_t prel31) noexcept
Decodes a 31-bit program-relative (PREL31) offset.
Definition arm_exidx_search.hpp:26
static bool execute(address_space_ref space, uintptr_t extab_addr, uintptr_t &io_sp, register_context_ref reg_ctx) noexcept
Runs the extab bytecode stream, updating SP and writing restored registers.
Definition arm_extab_stream.hpp:162
Type-erased, two-word handle to a frame unwinder.
Definition frame_pointer.hpp:68
Zero-allocation, type-erased handle for inspecting and modifying CPU registers from a frame context.
Definition register_context.hpp:118
#define MICROFMT_API_CLASS
Definition compat.hpp:181
Per-architecture ABI traits describing registers used during DWARF unwinding.
ELF image introspection, type-erased image enumeration, and fixed-capacity registries.
Type-erased frame unwinder handles, frame cursor iteration, and backtrace views.
One .ARM.exidx table entry.
Definition arm_exidx_unwinder.hpp:27
uint32_t unwind_data
Inline bytecode or pointer to .ARM.extab.
Definition arm_exidx_unwinder.hpp:31
uint32_t prel31_addr_offset
Relative (PREL31) offset to the function start.
Definition arm_exidx_unwinder.hpp:29
Immutable context describing the EXIDX unwinder back to the type-erased handle.
Definition arm_exidx_unwinder.hpp:42
address_space_ref space
Address space to unwind in.
Definition arm_exidx_unwinder.hpp:44
elf_image_enumerator_ref enumerator
ELF image enumerator used to bind PCs to modules.
Definition arm_exidx_unwinder.hpp:46
Self-contained holder owning the EXIDX scratch storage.
Definition arm_exidx_unwinder.hpp:203
arm_exidx_unwinder_holder(address_space_ref space, elf_image_enumerator_ref enumerator) noexcept
Constructs a holder bound to an address space and enumerator.
Definition arm_exidx_unwinder.hpp:214
frame_unwinder_ref make_ref() &noexcept
Builds a type-erased unwinder handle bound to this holder.
Definition arm_exidx_unwinder.hpp:230
arm_exidx_unwinder_holder & operator=(const arm_exidx_unwinder_holder &)=delete
Copy-assignment is disabled to ensure pointer stability.
arm_exidx_unwinder_holder(const arm_exidx_unwinder_holder &)=delete
Copying is disabled to ensure pointer stability.
elf_image_info img_storage
Storage for the located ELF image.
Definition arm_exidx_unwinder.hpp:205
arm_exidx_unwinder_holder & operator=(arm_exidx_unwinder_holder &&)=delete
Move-assignment is disabled to ensure pointer stability.
arm_exidx_unwinder_holder(arm_exidx_unwinder_holder &&)=delete
Moving is disabled to ensure pointer stability.
arm_exidx_unwinder_context ctx
Unwinder context referencing the owned storage.
Definition arm_exidx_unwinder.hpp:207
Tag selecting the EXIDX unwinder in the traits customization point.
Definition arm_exidx_unwinder.hpp:60
Describes a loaded ELF image and the locations of its unwind tables.
Definition elf_enumerator.hpp:30
uintptr_t exidx_end
End of the .ARM.exidx section.
Definition elf_enumerator.hpp:51
uintptr_t exidx_start
Start of the .ARM.exidx section.
Definition elf_enumerator.hpp:47
constexpr bool has_exidx() const noexcept
Reports whether a usable .ARM.exidx section is present.
Definition elf_enumerator.hpp:83
static bool step(value_ref< const context_type > context, register_context_ref reg_ctx, uintptr_t current_pc, uintptr_t &next_fp, uintptr_t &next_pc) noexcept
Unwinds one frame using the module's .ARM.exidx tables and register_context_ref.
Definition arm_exidx_unwinder.hpp:89
Static customization point describing a frame unwinder backend.
Definition frame_pointer.hpp:56