metaemu_state/
pcode.rs

1use std::marker::PhantomData;
2use std::sync::Arc;
3
4use fugue::bytes::{ByteCast, Order};
5
6use fugue::ir::convention::Convention;
7use fugue::ir::il::pcode::Operand;
8use fugue::ir::{Address, AddressSpace, Translator};
9
10use thiserror::Error;
11use ux::u24;
12
13use crate::paged::{self, PagedState};
14use crate::register::{self, RegisterState};
15use crate::unique::{self, UniqueState};
16
17use crate::traits::{State, StateOps, StateValue};
18use crate::traits::{FromStateValues, IntoStateValues};
19
20pub const POINTER_8_SIZE: usize = 1;
21pub const POINTER_16_SIZE: usize = 2;
22pub const POINTER_20_SIZE: usize = 3;
23pub const POINTER_32_SIZE: usize = 4;
24pub const POINTER_64_SIZE: usize = 8;
25pub const MAX_POINTER_SIZE: usize = POINTER_64_SIZE;
26
27#[derive(Debug, Error, Clone)]
28pub enum Error {
29    #[error(transparent)]
30    Memory(paged::Error),
31    #[error(transparent)]
32    Register(register::Error),
33    #[error(transparent)]
34    Temporary(unique::Error),
35    #[error("unsupported addess size of `{0}` bytes")]
36    UnsupportedAddressSize(usize),
37}
38
39#[derive(Debug, Clone)]
40pub struct PCodeState<T: StateValue, O: Order> {
41    memory: PagedState<T>,
42    registers: RegisterState<T, O>,
43    temporaries: UniqueState<T>,
44    convention: Convention,
45    marker: PhantomData<O>,
46}
47
48impl<T: StateValue, O: Order> AsRef<Self> for PCodeState<T, O> {
49    fn as_ref(&self) -> &Self {
50        self
51    }
52}
53
54impl<T: StateValue, O: Order> AsMut<Self> for PCodeState<T, O> {
55    fn as_mut(&mut self) -> &mut Self {
56        self
57    }
58}
59
60impl<T: StateValue, O: Order> PCodeState<T, O> {
61    pub fn new(memory: PagedState<T>, translator: &Translator, convention: &Convention) -> Self {
62        Self {
63            memory,
64            registers: RegisterState::new(translator, convention),
65            temporaries: UniqueState::new(translator),
66            convention: convention.clone(),
67            marker: PhantomData,
68        }
69    }
70
71    pub fn convention(&self) -> &Convention {
72        &self.convention
73    }
74
75    pub fn memory(&self) -> &PagedState<T> {
76        &self.memory
77    }
78
79    pub fn memory_mut(&mut self) -> &mut PagedState<T> {
80        &mut self.memory
81    }
82
83    pub fn memory_space(&self) -> Arc<AddressSpace> {
84        self.memory().address_space()
85    }
86
87    pub fn memory_space_ref(&self) -> &AddressSpace {
88        self.memory().address_space_ref()
89    }
90
91    pub fn registers(&self) -> &RegisterState<T, O> {
92        &self.registers
93    }
94
95    pub fn registers_mut(&mut self) -> &mut RegisterState<T, O> {
96        &mut self.registers
97    }
98
99    pub fn temporaries(&self) -> &UniqueState<T> {
100        &self.temporaries
101    }
102
103    pub fn temporaries_mut(&mut self) -> &mut UniqueState<T> {
104        &mut self.temporaries
105    }
106
107    pub fn with_operand_values<U, F>(&self, operand: &Operand, f: F) -> Result<U, Error>
108    where F: FnOnce(&[T]) -> U {
109        match operand {
110            Operand::Address { value, size } => {
111                self.memory()
112                    .view_values(value.offset(), *size)
113                    .map_err(Error::Memory)
114                    .map(f)
115            },
116            Operand::Constant { value, size, .. } => {
117                // max size of value
118                let mut values: [T; 8] = Default::default();
119
120                if O::ENDIAN.is_big() {
121                    for (d, s) in values[..*size].iter_mut().zip(&value.to_be_bytes()[8-*size..]) {
122                        *d = T::from_byte(*s);
123                    }
124                } else {
125                    for (d, s) in values[..*size].iter_mut().zip(&value.to_le_bytes()[..*size]) {
126                        *d = T::from_byte(*s);
127                    }
128                }
129
130                Ok(f(&values[..*size]))
131            },
132            Operand::Register { offset, size, .. } => {
133                self.registers()
134                    .view_values(*offset, *size)
135                    .map_err(Error::Register)
136                    .map(f)
137            },
138            Operand::Variable { offset, size, .. } => {
139                self.temporaries()
140                    .view_values(*offset, *size)
141                    .map_err(Error::Temporary)
142                    .map(f)
143            },
144        }
145    }
146
147    pub fn with_operand_values_mut<U, F>(&mut self, operand: &Operand, f: F) -> Result<U, Error>
148    where F: FnOnce(&mut [T]) -> U {
149        match operand {
150            Operand::Address { value, size } => {
151                self.memory_mut()
152                    .view_values_mut(value.offset(), *size)
153                    .map_err(Error::Memory)
154                    .map(f)
155            },
156            Operand::Register { offset, size, .. } => {
157                self.registers_mut()
158                    .view_values_mut(*offset, *size)
159                    .map_err(Error::Register)
160                    .map(f)
161            },
162            Operand::Variable { offset, size, .. } => {
163                self.temporaries_mut()
164                    .view_values_mut(*offset, *size)
165                    .map_err(Error::Temporary)
166                    .map(f)
167            },
168            Operand::Constant { .. } => {
169                panic!("cannot mutate Operand::Constant");
170            },
171        }
172    }
173
174    pub fn get_operand<V: FromStateValues<T>>(&self, operand: &Operand) -> Result<V, Error> {
175        let res = self.with_operand_values(operand, |values| V::from_values::<O>(values));
176        res
177    }
178
179    pub fn set_operand<V: IntoStateValues<T>>(&mut self, operand: &Operand, value: V) -> Result<(), Error> {
180        self.with_operand_values_mut(operand, |values| value.into_values::<O>(values))
181    }
182
183    #[inline(always)]
184    pub fn view_values_from<A>(&self, address: A) -> Result<&[T], Error>
185    where A: Into<Address> {
186        self.memory.view_values_from(address)
187            .map_err(Error::Memory)
188    }
189}
190
191impl<O: Order> PCodeState<u8, O> {
192    pub fn program_counter_value(&self) -> Result<Address, Error> {
193        self.get_address(&self.registers.program_counter())
194    }
195
196    pub fn stack_pointer_value(&self) -> Result<Address, Error> {
197        self.get_address(&self.registers.stack_pointer())
198    }
199
200    // get the value of a pointer itself at address
201    pub fn get_pointer(&self, address: Address) -> Result<Address, Error> {
202        let opnd = Operand::Address {
203            value: address,
204            size: self.memory_space_ref().address_size(),
205        };
206        self.get_address(&opnd)
207    }
208
209    // get value at address
210    pub fn get_address(&self, operand: &Operand) -> Result<Address, Error> {
211        let mut buf = [0u8; MAX_POINTER_SIZE];
212        let size = operand.size();
213
214        let address = if size == POINTER_64_SIZE {
215            self.with_operand_values(operand, |values| {
216                buf[..size].copy_from_slice(values);
217                u64::from_bytes::<O>(values)
218            })
219        } else if size == POINTER_32_SIZE {
220            self.with_operand_values(operand, |values| {
221                buf[..size].copy_from_slice(values);
222                u32::from_bytes::<O>(values) as u64
223            })
224        } else if size == POINTER_16_SIZE {
225            self.with_operand_values(operand, |values| {
226                buf[..size].copy_from_slice(values);
227                u16::from_bytes::<O>(values) as u64
228            })
229        } else if size == POINTER_8_SIZE {
230            self.with_operand_values(operand, |values| {
231                buf[..size].copy_from_slice(values);
232                u8::from_bytes::<O>(values) as u64
233            })
234        } else if size == POINTER_20_SIZE {
235            self.with_operand_values(operand, |values| {
236                buf[..size].copy_from_slice(values);
237                u64::from(u24::from_bytes::<O>(values))
238            })
239        } else {
240            return Err(Error::UnsupportedAddressSize(size))
241        }?;
242
243        Ok(Address::new(self.memory.address_space_ref(), address))
244    }
245
246    pub fn set_program_counter_value<A>(&mut self, value: A) -> Result<(), Error>
247    where A: Into<Address> {
248        self.set_address(&self.registers.program_counter(), value)
249    }
250
251    pub fn set_stack_pointer_value<A>(&mut self, value: A) -> Result<(), Error>
252    where A: Into<Address> {
253        self.set_address(&self.registers.stack_pointer(), value)
254    }
255
256    pub fn set_address<A>(&mut self, operand: &Operand, value: A) -> Result<(), Error>
257    where A: Into<Address> {
258
259        let size = operand.size();
260        let address = value.into();
261
262        if size == POINTER_64_SIZE {
263            self.with_operand_values_mut(operand, |values| {
264                u64::from(address).into_bytes::<O>(values)
265            })
266        } else if size == POINTER_32_SIZE {
267            self.with_operand_values_mut(operand, |values| {
268                u32::from(address).into_bytes::<O>(values)
269            })
270        } else if size == POINTER_16_SIZE {
271            self.with_operand_values_mut(operand, |values| {
272                u16::from(address).into_bytes::<O>(values)
273            })
274        } else if size == POINTER_8_SIZE {
275            self.with_operand_values_mut(operand, |values| {
276                u8::from(address).into_bytes::<O>(values)
277            })
278        } else if size == POINTER_20_SIZE {
279            self.with_operand_values_mut(operand, |values| {
280                u24::new(u32::from(address)).into_bytes::<O>(values)
281            })
282        } else {
283            return Err(Error::UnsupportedAddressSize(size))
284        }?;
285
286        Ok(())
287    }
288}
289
290impl<V: StateValue, O: Order> State for PCodeState<V, O> {
291    type Error = Error;
292
293    fn fork(&self) -> Self {
294        Self {
295            convention: self.convention.clone(),
296            registers: self.registers.fork(),
297            temporaries: self.temporaries.fork(),
298            memory: self.memory.fork(),
299            marker: self.marker,
300        }
301    }
302
303    fn restore(&mut self, other: &Self) {
304        self.registers.restore(&other.registers);
305        self.temporaries.restore(&other.temporaries);
306        self.memory.restore(&other.memory);
307    }
308}
309
310impl<V: StateValue, O: Order> StateOps for PCodeState<V, O> {
311    type Value = V;
312
313    #[inline(always)]
314    fn copy_values<F, T>(&mut self, from: F, to: T, size: usize) -> Result<(), Self::Error>
315    where F: Into<Address>,
316          T: Into<Address> {
317        self.memory.copy_values(from, to, size)
318            .map_err(Error::Memory)
319    }
320
321    #[inline(always)]
322    fn get_values<A>(&self, address: A, values: &mut [Self::Value]) -> Result<(), Self::Error>
323    where A: Into<Address> {
324        self.memory.get_values(address, values)
325            .map_err(Error::Memory)
326    }
327
328    #[inline(always)]
329    fn view_values<A>(&self, address: A, size: usize) -> Result<&[Self::Value], Self::Error>
330    where A: Into<Address> {
331        self.memory.view_values(address, size)
332            .map_err(Error::Memory)
333    }
334
335    #[inline(always)]
336    fn view_values_mut<A>(&mut self, address: A, size: usize) -> Result<&mut [Self::Value], Self::Error>
337    where A: Into<Address> {
338        self.memory.view_values_mut(address, size)
339            .map_err(Error::Memory)
340    }
341
342    #[inline(always)]
343    fn set_values<A>(&mut self, address: A, values: &[Self::Value]) -> Result<(), Self::Error>
344    where A: Into<Address> {
345        self.memory.set_values(address, values)
346            .map_err(Error::Memory)
347    }
348
349    #[inline(always)]
350    fn len(&self) -> usize {
351        self.memory.len()
352    }
353}