microfmt
Zero-allocation C++ formatting for constrained environments
Loading...
Searching...
No Matches
Public Types | Static Public Member Functions | Static Public Attributes | List of all members
microfmt::arm_abi_traits Struct Reference

DWARF unwind ABI traits for ARM / Thumb (32-bit EABI). More...

#include <dwarf_abi.hpp>

Public Types

using register_type = uint32_t
 Register value width.
 
using register_traits = dwarf::arm32::register_traits
 Architecture register name/index catalog.
 
using gdb_register_traits = gdb::register_traits< gdb::tags::arm32 >
 GDB-to-DWARF register mapping.
 

Static Public Member Functions

static constexpr bool is_return_address_register (uint32_t reg) noexcept
 Reports whether a register holds the return address.
 
static constexpr bool is_frame_pointer_register (uint32_t reg) noexcept
 Reports whether a register is a frame pointer.
 
static constexpr uintptr_t normalize_pc (uintptr_t raw_ra) noexcept
 
static uint32_t resolve_fp_reg (register_context_ref reg_ctx) noexcept
 Resolves which register actually holds the frame pointer for the current instruction set state.
 
static bool resolve_frame_slot_offsets (register_context_ref reg_ctx, ptrdiff_t &out_fp_slot_offset, ptrdiff_t &out_ra_slot_offset) noexcept
 Resolves the FP-relative saved-FP/saved-RA slot offsets for the current instruction-set state, for fp_unwinder_tag's naive FP-chain walking.
 

Static Public Attributes

static constexpr size_t pointer_size = 4
 Pointer size in bytes.
 
static constexpr uint32_t sp_reg = dwarf::arm32::sp
 SP register number.
 
static constexpr uint32_t lr_reg = dwarf::arm32::lr
 LR register number.
 
static constexpr uint32_t ra_reg = lr_reg
 Return-address register number.
 
static constexpr uint32_t fp_reg = dwarf::arm32::fp
 FP register number.
 
static constexpr ptrdiff_t fp_slot_offset = -4
 
static constexpr ptrdiff_t ra_slot_offset = 0
 

Detailed Description

DWARF unwind ABI traits for ARM / Thumb (32-bit EABI).

Member Typedef Documentation

◆ gdb_register_traits

GDB-to-DWARF register mapping.

◆ register_traits

Architecture register name/index catalog.

◆ register_type

Register value width.

Member Function Documentation

◆ is_frame_pointer_register()

static constexpr bool microfmt::arm_abi_traits::is_frame_pointer_register ( uint32_t  reg)
inlinestaticconstexprnoexcept

Reports whether a register is a frame pointer.

Parameters
regDWARF register number.
Returns
true for R11 and R7 (Thumb frame pointer).

◆ is_return_address_register()

static constexpr bool microfmt::arm_abi_traits::is_return_address_register ( uint32_t  reg)
inlinestaticconstexprnoexcept

Reports whether a register holds the return address.

Parameters
regDWARF register number.
Returns
true for the link register (R14).

◆ normalize_pc()

static constexpr uintptr_t microfmt::arm_abi_traits::normalize_pc ( uintptr_t  raw_ra)
inlinestaticconstexprnoexcept

◆ resolve_fp_reg()

static uint32_t microfmt::arm_abi_traits::resolve_fp_reg ( register_context_ref  reg_ctx)
inlinestaticnoexcept

Resolves which register actually holds the frame pointer for the current instruction set state.

Unlike every other supported architecture, ARM's frame-pointer register is not fixed: GCC/Clang use R11 in ARM (A32) state but R7 in Thumb/Thumb-2 state. Consulting the static fp_reg alone silently mis-decodes any Thumb frame. The definitive source of truth is the Thumb bit (bit 5, 0x20) of CPSR; when the register context cannot supply CPSR (e.g. a synthetic/simulated register file in a test), this falls back to fp_reg (A32/R11).

Parameters
reg_ctxRegister context to consult for CPSR.
Returns
7 (R7) in Thumb state, otherwise fp_reg (11, R11).

◆ resolve_frame_slot_offsets()

static bool microfmt::arm_abi_traits::resolve_frame_slot_offsets ( register_context_ref  reg_ctx,
ptrdiff_t &  out_fp_slot_offset,
ptrdiff_t &  out_ra_slot_offset 
)
inlinestaticnoexcept

Resolves the FP-relative saved-FP/saved-RA slot offsets for the current instruction-set state, for fp_unwinder_tag's naive FP-chain walking.

In ARM (A32) state, fp always ends up pointing directly at the saved-LR word regardless of how many other callee-saved scratch registers (e.g. r4) are pushed alongside {fp, lr} – fp/lr are always the last two, adjacent entries of the push list – so fp_slot_offset (-4) / ra_slot_offset (0) hold universally.

In Thumb/Thumb-2 state this is not true: GCC emits mov r7, sp (or add r7, sp, #0) after allocating the local-variable area whenever any extra scratch register is pushed alongside {r7, lr}, so r7 ends up pointing at the locals base rather than at the {r7, lr} pair, and the true offset then varies per function with its (frame-size-dependent) local allocation. There is no fixed constant that describes this, so this reports failure in Thumb state rather than returning a plausible-looking but wrong offset.

Parameters
reg_ctxRegister context to consult for CPSR.
[out]out_fp_slot_offsetReceives fp_slot_offset when successful.
[out]out_ra_slot_offsetReceives ra_slot_offset when successful.
Returns
true in ARM (A32) state (or when CPSR cannot be read, matching resolve_fp_reg's fallback); false in Thumb/Thumb-2 state, where FP-chain walking cannot be trusted.

Member Data Documentation

◆ fp_reg

constexpr uint32_t microfmt::arm_abi_traits::fp_reg = dwarf::arm32::fp
staticconstexpr

FP register number.

◆ fp_slot_offset

constexpr ptrdiff_t microfmt::arm_abi_traits::fp_slot_offset = -4
staticconstexpr

◆ lr_reg

constexpr uint32_t microfmt::arm_abi_traits::lr_reg = dwarf::arm32::lr
staticconstexpr

LR register number.

◆ pointer_size

constexpr size_t microfmt::arm_abi_traits::pointer_size = 4
staticconstexpr

Pointer size in bytes.

◆ ra_reg

constexpr uint32_t microfmt::arm_abi_traits::ra_reg = lr_reg
staticconstexpr

Return-address register number.

◆ ra_slot_offset

constexpr ptrdiff_t microfmt::arm_abi_traits::ra_slot_offset = 0
staticconstexpr

◆ sp_reg

constexpr uint32_t microfmt::arm_abi_traits::sp_reg = dwarf::arm32::sp
staticconstexpr

SP register number.


The documentation for this struct was generated from the following file: