Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
bytecodealliance
GitHub Repository: bytecodealliance/wasmtime
Path: blob/main/crates/unwinder/src/arch/aarch64.rs
1693 views
1
//! Arm64-specific definitions of architecture-specific functions in Wasmtime.
2
3
#[inline]
4
pub fn get_stack_pointer() -> usize {
5
let stack_pointer: usize;
6
unsafe {
7
core::arch::asm!(
8
"mov {}, sp",
9
out(reg) stack_pointer,
10
options(nostack,nomem),
11
);
12
}
13
stack_pointer
14
}
15
16
// The aarch64 calling conventions save the return PC one i64 above the FP and
17
// the previous FP is pointed to by the current FP:
18
//
19
// > Each frame shall link to the frame of its caller by means of a frame record
20
// > of two 64-bit values on the stack [...] The frame record for the innermost
21
// > frame [...] shall be pointed to by the frame pointer register (FP). The
22
// > lowest addressed double-word shall point to the previous frame record and the
23
// > highest addressed double-word shall contain the value passed in LR on entry
24
// > to the current function.
25
//
26
// - AAPCS64 section 6.2.3 The Frame Pointer[0]
27
pub unsafe fn get_next_older_pc_from_fp(fp: usize) -> usize {
28
unsafe {
29
let mut pc = *(fp as *mut usize).offset(1);
30
31
// The return address might be signed, so we need to strip the highest bits
32
// (where the authentication code might be located) in order to obtain a
33
// valid address. We use the `XPACLRI` instruction, which is executed as a
34
// no-op by processors that do not support pointer authentication, so that
35
// the implementation is backward-compatible and there is no duplication.
36
// However, this instruction requires the LR register for both its input and
37
// output.
38
core::arch::asm!(
39
"mov lr, {pc}",
40
"xpaclri",
41
"mov {pc}, lr",
42
pc = inout(reg) pc,
43
out("lr") _,
44
options(nomem, nostack, preserves_flags, pure),
45
);
46
47
pc
48
}
49
}
50
51
pub unsafe fn resume_to_exception_handler(
52
pc: usize,
53
sp: usize,
54
fp: usize,
55
payload1: usize,
56
payload2: usize,
57
) -> ! {
58
unsafe {
59
core::arch::asm!(
60
"mov sp, x2",
61
"mov fp, x3",
62
"br x4",
63
in("x0") payload1,
64
in("x1") payload2,
65
in("x2") sp,
66
in("x3") fp,
67
in("x4") pc,
68
options(nostack, nomem, noreturn),
69
);
70
}
71
}
72
73
// And the current frame pointer points to the next older frame pointer.
74
pub const NEXT_OLDER_FP_FROM_FP_OFFSET: usize = 0;
75
76
// SP of caller is FP in callee plus size of FP/return address pair.
77
pub const NEXT_OLDER_SP_FROM_FP_OFFSET: usize = 16;
78
79
pub fn assert_fp_is_aligned(_fp: usize) {
80
// From AAPCS64, section 6.2.3 The Frame Pointer[0]:
81
//
82
// > The location of the frame record within a stack frame is not specified.
83
//
84
// So this presumably means that the FP can have any alignment, as its
85
// location is not specified and nothing further is said about constraining
86
// alignment.
87
//
88
// [0]: https://github.com/ARM-software/abi-aa/blob/2022Q1/aapcs64/aapcs64.rst#the-frame-pointer
89
}
90
91