1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223
use ::std::{thread, time::Duration};
use crate::error::Result;
use crate::mem::{
PhysicalMemory, PhysicalMemoryMapping, PhysicalMemoryMetadata, PhysicalReadMemOps,
PhysicalWriteMemOps,
};
/// The delay middleware introduces delay and jitter into physical reads which allows
/// users to simulate different connectors and setups.
///
/// Since this middleware implements [`PhysicalMemory`] it can be used as a replacement
/// in all structs and functions that require the [`PhysicalMemory`] trait.
pub struct DelayedPhysicalMemory<T> {
mem: T,
delay: Duration,
}
impl<T> Clone for DelayedPhysicalMemory<T>
where
T: Clone,
{
fn clone(&self) -> Self {
Self {
mem: self.mem.clone(),
delay: self.delay,
}
}
}
impl<T: PhysicalMemory> DelayedPhysicalMemory<T> {
/// Constructs a new middleware with the given delay.
///
/// This function is used when manually constructing a middleware inside of the memflow crate itself.
///
/// For general usage it is advised to just use the [builder](struct.DelayedPhysicalMemoryBuilder.html)
/// to construct the delay.
pub fn new(mem: T, delay: Duration) -> Self {
Self { mem, delay }
}
/// Consumes self and returns the containing memory object.
///
/// This function can be useful in case the ownership over the memory object has been given to the cache
/// when it was being constructed.
/// It will destroy the `self` and return back the ownership of the underlying memory object.
///
/// # Examples
/// ```
/// # const MAGIC_VALUE: u64 = 0x23bd_318f_f3a3_5821;
/// use memflow::architecture::x86::x64;
/// use memflow::mem::{PhysicalMemory, DelayedPhysicalMemory, MemoryView};
///
/// fn build<T: PhysicalMemory>(mem: T) -> T {
/// let mut middleware = DelayedPhysicalMemory::builder(mem)
/// .build()
/// .unwrap();
///
/// // use the middleware...
/// let value: u64 = middleware.phys_view().read(0.into()).unwrap();
/// assert_eq!(value, MAGIC_VALUE);
///
/// // retrieve ownership of mem and return it back
/// middleware.into_inner()
/// }
/// # use memflow::dummy::DummyMemory;
/// # use memflow::types::size;
/// # let mut mem = DummyMemory::new(size::mb(4));
/// # mem.phys_write(0.into(), &MAGIC_VALUE).unwrap();
/// # build(mem);
/// ```
pub fn into_inner(self) -> T {
self.mem
}
}
impl<T: PhysicalMemory> DelayedPhysicalMemory<T> {
/// Returns a new builder for the delay middleware with default settings.
pub fn builder(mem: T) -> DelayedPhysicalMemoryBuilder<T> {
DelayedPhysicalMemoryBuilder::new(mem)
}
}
// forward PhysicalMemory trait fncs
impl<T: PhysicalMemory> PhysicalMemory for DelayedPhysicalMemory<T> {
#[inline]
fn phys_read_raw_iter(&mut self, data: PhysicalReadMemOps) -> Result<()> {
thread::sleep(self.delay);
self.mem.phys_read_raw_iter(data)
}
#[inline]
fn phys_write_raw_iter(&mut self, data: PhysicalWriteMemOps) -> Result<()> {
thread::sleep(self.delay);
self.mem.phys_write_raw_iter(data)
}
#[inline]
fn metadata(&self) -> PhysicalMemoryMetadata {
self.mem.metadata()
}
#[inline]
fn set_mem_map(&mut self, mem_map: &[PhysicalMemoryMapping]) {
self.mem.set_mem_map(mem_map)
}
}
/// The builder interface for constructing a `DelayedPhysicalMemory` object.
pub struct DelayedPhysicalMemoryBuilder<T> {
mem: T,
delay: Duration,
}
impl<T: PhysicalMemory> DelayedPhysicalMemoryBuilder<T> {
/// Creates a new `DelayedPhysicalMemory` builder.
/// The memory object is mandatory as the DelayedPhysicalMemory struct wraps around it.
///
/// Without further adjustments this function creates a middleware with a delay of 10 milliseconds
/// for each read and write.
///
/// It is also possible to either let the `DelayedPhysicalMemory` object own or just borrow the underlying memory object.
///
/// # Examples
/// Moves ownership of a mem object and retrieves it back:
/// ```
/// # const MAGIC_VALUE: u64 = 0x23bd_318f_f3a3_5821;
/// use memflow::architecture::x86::x64;
/// use memflow::mem::{PhysicalMemory, DelayedPhysicalMemory, MemoryView};
///
/// fn build<T: PhysicalMemory>(mem: T) {
/// let mut middleware = DelayedPhysicalMemory::builder(mem)
/// .build()
/// .unwrap();
///
/// middleware.phys_write(0.into(), &MAGIC_VALUE);
///
/// let mut mem = middleware.into_inner();
///
/// let value: u64 = mem.phys_view().read(0.into()).unwrap();
/// assert_eq!(value, MAGIC_VALUE);
/// }
/// # use memflow::dummy::DummyMemory;
/// # use memflow::types::size;
/// # let mut mem = DummyMemory::new(size::mb(4));
/// # mem.phys_write(0.into(), &0xffaaffaau64).unwrap();
/// # build(mem);
/// ```
///
/// Borrowing a mem object:
/// ```
/// # const MAGIC_VALUE: u64 = 0x23bd_318f_f3a3_5821;
/// use memflow::architecture::x86::x64;
/// use memflow::mem::{PhysicalMemory, DelayedPhysicalMemory, MemoryView};
/// use memflow::cglue::{Fwd, ForwardMut};
///
/// fn build<T: PhysicalMemory>(mem: Fwd<&mut T>)
/// -> impl PhysicalMemory + '_ {
/// DelayedPhysicalMemory::builder(mem)
/// .build()
/// .unwrap()
/// }
///
/// # use memflow::dummy::DummyMemory;
/// # use memflow::types::size;
/// # let mut mem = DummyMemory::new(size::mb(4));
/// # mem.phys_write(0.into(), &MAGIC_VALUE).unwrap();
/// let mut middleware = build(mem.forward_mut());
///
/// let value: u64 = middleware.phys_view().read(0.into()).unwrap();
/// assert_eq!(value, MAGIC_VALUE);
///
/// middleware.phys_write(0.into(), &0u64).unwrap();
///
/// // We drop the cache and are able to use mem again
/// std::mem::drop(middleware);
///
/// let value: u64 = mem.phys_view().read(0.into()).unwrap();
/// assert_ne!(value, MAGIC_VALUE);
/// ```
pub fn new(mem: T) -> Self {
Self {
mem,
delay: Duration::from_millis(10),
}
}
/// Changes the delay of the middleware.
///
/// # Examples
///
/// ```
/// use memflow::types::size;
/// use memflow::mem::{PhysicalMemory, DelayedPhysicalMemory};
/// use std::time::Duration;
///
/// fn build<T: PhysicalMemory>(mem: T) {
/// let middleware = DelayedPhysicalMemory::builder(mem)
/// .delay(Duration::from_millis(10))
/// .build()
/// .unwrap();
/// }
/// # use memflow::dummy::DummyMemory;
/// # let mut mem = DummyMemory::new(size::mb(4));
/// # build(mem);
/// ```
pub fn delay(mut self, delay: Duration) -> Self {
self.delay = delay;
self
}
/// Builds the `DelayedPhysicalMemory` object or returns an error.
pub fn build(self) -> Result<DelayedPhysicalMemory<T>> {
Ok(DelayedPhysicalMemory::new(self.mem, self.delay))
}
}
#[cfg(feature = "plugins")]
::cglue::cglue_impl_group!(
DelayedPhysicalMemory<T: PhysicalMemory>,
crate::plugins::ConnectorInstance,
{}
);