Path: blob/main/crates/unwinder/src/arch/aarch64.rs
1693 views
//! Arm64-specific definitions of architecture-specific functions in Wasmtime.12#[inline]3pub fn get_stack_pointer() -> usize {4let stack_pointer: usize;5unsafe {6core::arch::asm!(7"mov {}, sp",8out(reg) stack_pointer,9options(nostack,nomem),10);11}12stack_pointer13}1415// The aarch64 calling conventions save the return PC one i64 above the FP and16// the previous FP is pointed to by the current FP:17//18// > Each frame shall link to the frame of its caller by means of a frame record19// > of two 64-bit values on the stack [...] The frame record for the innermost20// > frame [...] shall be pointed to by the frame pointer register (FP). The21// > lowest addressed double-word shall point to the previous frame record and the22// > highest addressed double-word shall contain the value passed in LR on entry23// > to the current function.24//25// - AAPCS64 section 6.2.3 The Frame Pointer[0]26pub unsafe fn get_next_older_pc_from_fp(fp: usize) -> usize {27unsafe {28let mut pc = *(fp as *mut usize).offset(1);2930// The return address might be signed, so we need to strip the highest bits31// (where the authentication code might be located) in order to obtain a32// valid address. We use the `XPACLRI` instruction, which is executed as a33// no-op by processors that do not support pointer authentication, so that34// the implementation is backward-compatible and there is no duplication.35// However, this instruction requires the LR register for both its input and36// output.37core::arch::asm!(38"mov lr, {pc}",39"xpaclri",40"mov {pc}, lr",41pc = inout(reg) pc,42out("lr") _,43options(nomem, nostack, preserves_flags, pure),44);4546pc47}48}4950pub unsafe fn resume_to_exception_handler(51pc: usize,52sp: usize,53fp: usize,54payload1: usize,55payload2: usize,56) -> ! {57unsafe {58core::arch::asm!(59"mov sp, x2",60"mov fp, x3",61"br x4",62in("x0") payload1,63in("x1") payload2,64in("x2") sp,65in("x3") fp,66in("x4") pc,67options(nostack, nomem, noreturn),68);69}70}7172// And the current frame pointer points to the next older frame pointer.73pub const NEXT_OLDER_FP_FROM_FP_OFFSET: usize = 0;7475// SP of caller is FP in callee plus size of FP/return address pair.76pub const NEXT_OLDER_SP_FROM_FP_OFFSET: usize = 16;7778pub fn assert_fp_is_aligned(_fp: usize) {79// From AAPCS64, section 6.2.3 The Frame Pointer[0]:80//81// > The location of the frame record within a stack frame is not specified.82//83// So this presumably means that the FP can have any alignment, as its84// location is not specified and nothing further is said about constraining85// alignment.86//87// [0]: https://github.com/ARM-software/abi-aa/blob/2022Q1/aapcs64/aapcs64.rst#the-frame-pointer88}899091