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 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 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 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}