use core::fmt::Debug;
use crate::display_utils::HexNum;
#[derive(Clone, Copy, PartialEq, Eq)]
pub struct UnwindRegsAarch64 {
lr_mask: PtrAuthMask,
lr: u64,
sp: u64,
fp: u64,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub struct PtrAuthMask(pub u64);
impl PtrAuthMask {
pub fn new_no_strip() -> Self {
Self(u64::MAX)
}
pub fn new_24_40() -> Self {
Self(u64::MAX >> 24)
}
pub fn from_max_known_address(address: u64) -> Self {
Self(u64::MAX >> address.leading_zeros())
}
#[inline(always)]
pub fn strip_ptr_auth(&self, ptr: u64) -> u64 {
ptr & self.0
}
}
impl UnwindRegsAarch64 {
pub fn new(lr: u64, sp: u64, fp: u64) -> Self {
Self {
lr_mask: PtrAuthMask::new_no_strip(),
lr,
sp,
fp,
}
}
pub fn new_with_ptr_auth_mask(
code_ptr_auth_mask: PtrAuthMask,
lr: u64,
sp: u64,
fp: u64,
) -> Self {
Self {
lr_mask: code_ptr_auth_mask,
lr: code_ptr_auth_mask.strip_ptr_auth(lr),
sp,
fp,
}
}
#[inline(always)]
pub fn lr_mask(&self) -> PtrAuthMask {
self.lr_mask
}
#[inline(always)]
pub fn sp(&self) -> u64 {
self.sp
}
#[inline(always)]
pub fn set_sp(&mut self, sp: u64) {
self.sp = sp
}
#[inline(always)]
pub fn fp(&self) -> u64 {
self.fp
}
#[inline(always)]
pub fn set_fp(&mut self, fp: u64) {
self.fp = fp
}
#[inline(always)]
pub fn lr(&self) -> u64 {
self.lr
}
#[inline(always)]
pub fn set_lr(&mut self, lr: u64) {
self.lr = self.lr_mask.strip_ptr_auth(lr)
}
}
impl Debug for UnwindRegsAarch64 {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
f.debug_struct("UnwindRegsAarch64")
.field("lr", &HexNum(self.lr))
.field("sp", &HexNum(self.sp))
.field("fp", &HexNum(self.fp))
.finish()
}
}
#[cfg(test)]
mod test {
use crate::aarch64::PtrAuthMask;
#[test]
fn test() {
assert_eq!(PtrAuthMask::new_24_40().0, u64::MAX >> 24);
assert_eq!(PtrAuthMask::new_24_40().0, (1 << 40) - 1);
assert_eq!(
PtrAuthMask::from_max_known_address(0x0000aaaab54f7000).0,
0x0000ffffffffffff
);
assert_eq!(
PtrAuthMask::from_max_known_address(0x0000ffffa3206000).0,
0x0000ffffffffffff
);
assert_eq!(
PtrAuthMask::from_max_known_address(0xffffffffc05a9000).0,
0xffffffffffffffff
);
assert_eq!(
PtrAuthMask::from_max_known_address(0x000055ba9f07e000).0,
0x00007fffffffffff
);
assert_eq!(
PtrAuthMask::from_max_known_address(0x00007f76b8019000).0,
0x00007fffffffffff
);
assert_eq!(
PtrAuthMask::from_max_known_address(0x000000022a3ccff7).0,
0x00000003ffffffff
);
}
}