diff --git a/src/backend.rs b/src/backend.rs index 8de199f..ed71c91 100644 --- a/src/backend.rs +++ b/src/backend.rs @@ -8,8 +8,6 @@ pub trait Backend { fn set_ptr(provenance: *mut T, addr: Self) -> Self::Stored; fn get_int(s: Self::Stored) -> Self; - - fn set_int(s: Self::Stored, int: Self) -> Self::Stored; } impl Backend for usize { @@ -26,8 +24,44 @@ impl Backend for usize { fn get_int(s: Self::Stored) -> Self { Strict::addr(s) } +} - fn set_int(s: Self::Stored, int: Self) -> Self::Stored { - Strict::with_addr(s, int) +#[cfg(target_pointer_width = "64")] +/// on 64 bit, we can just treat u64/usize interchangeably, because uintptr_t == size_t in Rust +impl Backend for u64 { + type Stored = *mut T; + + fn get_ptr(s: Self::Stored) -> (*mut T, Self) { + (s, Strict::addr(s) as u64) + } + + fn set_ptr(provenance: *mut T, addr: Self) -> Self::Stored { + Strict::with_addr(provenance, addr as usize) + } + + fn get_int(s: Self::Stored) -> Self { + Strict::addr(s) as u64 + } +} + +#[cfg(target_pointer_width = "64")] +impl Backend for u128 { + // this one keeps the MSB in the pointer address, and the LSB in the integer + + type Stored = (*mut T, u64); + + fn get_ptr(s: Self::Stored) -> (*mut T, Self) { + (s.0, Self::get_int(s)) + } + + fn set_ptr(provenance: *mut T, addr: Self) -> Self::Stored { + let ptr_addr = (addr >> 64) as u64; + let int_addr = addr as u64; // truncate it + (Strict::with_addr(provenance, ptr_addr as usize), int_addr) + } + + fn get_int(s: Self::Stored) -> Self { + let ptr_addr = Strict::addr(s.0) as u64; + (u128::from(ptr_addr) << 64) | u128::from(s.1) } }