1use qcode::{
57 context::Context,
58 space::MemorySpaceId,
59 value::{
60 BlockId, FunctionId, InstructionId, ValueId, Varnode,
61 insn::{
62 Binary, Binop, Carry, FloatBinop, FloatToFloat, FloatToInt, Gep, InstructionRef,
63 IntBinop, IntToFloat, IsFloatNaN, Load, LzCount, Mnemonic, PopCount, Range, SBorrow,
64 SCarry, Sext, Store, Unary, Unop, Zext,
65 },
66 varnode::{VarnodeId, register::RegisterId},
67 },
68};
69
70mod concrete;
71
72pub use concrete::{
73 BodyArg, EmulatedMemory, Emulator, EmulatorMemory, SizedValue, StandaloneEmulator,
74};
75
76#[derive(Debug, Clone)]
77pub struct CallSite {
78 pub instruction: InstructionId,
79 pub block: BlockId,
80 pub target: FunctionId,
81 pub args: Vec<ValueId>,
82}
83
84#[derive(Debug, Clone, Copy, PartialEq, Eq)]
85pub enum CallContinuation {
86 Block(BlockId),
87 Address(u64),
88}
89
90#[derive(Debug, Clone, PartialEq, Eq)]
91pub enum CallInterception {
92 PassThrough,
93 Handled(CallContinuation),
94}
95
96#[derive(Debug)]
97pub struct EmulatorError {
98 pub kind: EmulatorErrorKind,
100 pub ctx: String,
103
104 pub address: Option<u64>,
106}
107
108impl EmulatorError {
109 pub fn new(kind: EmulatorErrorKind, insn: &InstructionRef<'_, '_>) -> Self {
110 Self {
111 kind,
112 ctx: format!(
113 "Instruction: {}\nBlock: {:?}\nFunction: {:?}",
114 insn.as_statement(),
115 insn.parent().map(|b| b.name()),
116 insn.function().map(|f| f.name())
117 ),
118 address: insn.parent().and_then(|b| b.address()),
119 }
120 }
121}
122
123#[derive(Debug)]
124pub enum EmulatorErrorKind {
125 InvalidBlockAddress(u64),
127 EmptyFunctionRoot(FunctionId),
129 UnresolvedMintedCallee(u32),
131 UnknownAddress(u64),
133 AddressOverflow(u64, usize),
135 MemoryReadError(u64),
137 MemoryWriteError(u64),
139 ValueError(u128),
141 UnknownRegister(RegisterId),
143 UnknownSpace(MemorySpaceId),
145 UnsupportedPCodeOp(Box<str>),
147 UnsupportedIntrinsic(Box<str>),
150 InterceptError(Box<str>),
152 StepBudgetExceeded(usize),
154 UnsupportedMnemonic(&'static str),
158 EmptyBlock(BlockId),
162 PoisonRead,
167}
168
169impl std::fmt::Display for EmulatorErrorKind {
170 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
171 match self {
172 Self::InvalidBlockAddress(addr) => write!(f, "invalid block address {addr:#x}"),
173 Self::EmptyFunctionRoot(func) => write!(f, "function {func:?} has no root block"),
174 Self::UnresolvedMintedCallee(slot) => {
175 write!(f, "minted callee placeholder #{slot} is not executable")
176 }
177 Self::UnknownAddress(addr) => write!(f, "unknown address {addr:#x}"),
178 Self::AddressOverflow(addr, size) => {
179 write!(f, "address overflow at {addr:#x} with size {size}")
180 }
181 Self::MemoryReadError(addr) => write!(f, "memory read error at address {addr:#x}"),
182 Self::MemoryWriteError(addr) => write!(f, "memory write error at address {addr:#x}"),
183 Self::ValueError(value) => write!(f, "value {value} is too large to represent"),
184 Self::UnknownRegister(reg) => write!(f, "register {reg:?} not found in context"),
185 Self::UnknownSpace(space) => write!(f, "memory space {space:?} not initialised"),
186 Self::UnsupportedPCodeOp(op) => write!(f, "unsupported p-code operation `{op}`"),
187 Self::UnsupportedIntrinsic(op) => write!(f, "unsupported intrinsic `{op}`"),
188 Self::InterceptError(message) => write!(f, "call interceptor failed: {message}"),
189 Self::StepBudgetExceeded(budget) => {
190 write!(f, "emulation exceeded step budget of {budget}")
191 }
192 Self::UnsupportedMnemonic(op) => write!(f, "unsupported mnemonic `{op}`"),
193 Self::EmptyBlock(block) => write!(f, "block {block:?} has no instructions"),
194 Self::PoisonRead => write!(f, "read of a poison value (undefined bits)"),
195 }
196 }
197}
198
199impl std::fmt::Display for EmulatorError {
200 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
201 write!(f, "emulator error: {}", self.kind)?;
202 write!(f, " (context: {})", self.ctx)?;
203 Ok(())
204 }
205}
206
207impl std::error::Error for EmulatorError {}
208
209pub type Result<T> = std::result::Result<T, EmulatorError>;
210
211pub trait DomainValue: Clone + Copy {
214 fn size(&self) -> std::result::Result<usize, EmulatorErrorKind>;
216
217 fn value(&self) -> std::result::Result<u64, EmulatorErrorKind>;
219
220 fn from_u64(value: u64) -> Self;
221
222 fn zero(_size: usize) -> Self {
226 Self::from_u64(0)
227 }
228
229 fn is_float_nan(&self) -> std::result::Result<Self, EmulatorErrorKind>;
230 fn int_to_float(&self, size: usize) -> std::result::Result<Self, EmulatorErrorKind>;
231 fn float_to_float(&self, size: usize) -> std::result::Result<Self, EmulatorErrorKind>;
232 fn float_to_int(&self, size: usize) -> std::result::Result<Self, EmulatorErrorKind>;
233 fn zext(&self, size: usize) -> std::result::Result<Self, EmulatorErrorKind>;
234 fn sext(&self, size: usize) -> std::result::Result<Self, EmulatorErrorKind>;
235 fn range(&self, start: usize, size: usize) -> std::result::Result<Self, EmulatorErrorKind>;
236 fn byte_swap(&self) -> std::result::Result<Self, EmulatorErrorKind>;
237
238 fn intrinsic(
241 id: qcode::value::insn::IntrinsicId,
242 args: &[Self],
243 out_size: usize,
244 ) -> std::result::Result<Self, EmulatorErrorKind>;
245
246 fn pop_count(&self) -> std::result::Result<Self, EmulatorErrorKind>;
247 fn lz_count(&self) -> std::result::Result<Self, EmulatorErrorKind>;
248 fn carry(&self, other: &Self) -> std::result::Result<Self, EmulatorErrorKind>;
249 fn scarry(&self, other: &Self) -> std::result::Result<Self, EmulatorErrorKind>;
250 fn sborrow(&self, other: &Self) -> std::result::Result<Self, EmulatorErrorKind>;
251
252 fn int_not(&self) -> std::result::Result<Self, EmulatorErrorKind>;
253 fn int_negate(&self) -> std::result::Result<Self, EmulatorErrorKind>;
254 fn float_negate(&self) -> std::result::Result<Self, EmulatorErrorKind>;
255 fn float_abs(&self) -> std::result::Result<Self, EmulatorErrorKind>;
256 fn float_sqrt(&self) -> std::result::Result<Self, EmulatorErrorKind>;
257 fn float_ceil(&self) -> std::result::Result<Self, EmulatorErrorKind>;
258 fn float_floor(&self) -> std::result::Result<Self, EmulatorErrorKind>;
259 fn float_round(&self) -> std::result::Result<Self, EmulatorErrorKind>;
260
261 fn int_equal(&self, other: &Self) -> std::result::Result<Self, EmulatorErrorKind>;
262 fn int_not_equal(&self, other: &Self) -> std::result::Result<Self, EmulatorErrorKind>;
263 fn int_less(&self, other: &Self) -> std::result::Result<Self, EmulatorErrorKind>;
264 fn int_sless(&self, other: &Self) -> std::result::Result<Self, EmulatorErrorKind>;
265 fn int_less_equal(&self, other: &Self) -> std::result::Result<Self, EmulatorErrorKind>;
266 fn int_sless_equal(&self, other: &Self) -> std::result::Result<Self, EmulatorErrorKind>;
267 fn int_add(&self, other: &Self) -> std::result::Result<Self, EmulatorErrorKind>;
268 fn int_sub(&self, other: &Self) -> std::result::Result<Self, EmulatorErrorKind>;
269 fn int_xor(&self, other: &Self) -> std::result::Result<Self, EmulatorErrorKind>;
270 fn int_and(&self, other: &Self) -> std::result::Result<Self, EmulatorErrorKind>;
271 fn int_or(&self, other: &Self) -> std::result::Result<Self, EmulatorErrorKind>;
272 fn int_shift_left(&self, other: &Self) -> std::result::Result<Self, EmulatorErrorKind>;
273 fn int_shift_right(&self, other: &Self) -> std::result::Result<Self, EmulatorErrorKind>;
274 fn int_sshift_right(&self, other: &Self) -> std::result::Result<Self, EmulatorErrorKind>;
275 fn int_mul(&self, other: &Self) -> std::result::Result<Self, EmulatorErrorKind>;
276 fn int_div(&self, other: &Self) -> std::result::Result<Self, EmulatorErrorKind>;
277 fn int_rem(&self, other: &Self) -> std::result::Result<Self, EmulatorErrorKind>;
278 fn int_sdiv(&self, other: &Self) -> std::result::Result<Self, EmulatorErrorKind>;
279 fn int_srem(&self, other: &Self) -> std::result::Result<Self, EmulatorErrorKind>;
280
281 fn float_add(&self, other: &Self) -> std::result::Result<Self, EmulatorErrorKind>;
282 fn float_sub(&self, other: &Self) -> std::result::Result<Self, EmulatorErrorKind>;
283 fn float_mul(&self, other: &Self) -> std::result::Result<Self, EmulatorErrorKind>;
284 fn float_div(&self, other: &Self) -> std::result::Result<Self, EmulatorErrorKind>;
285 fn float_equal(&self, other: &Self) -> std::result::Result<Self, EmulatorErrorKind>;
286 fn float_not_equal(&self, other: &Self) -> std::result::Result<Self, EmulatorErrorKind>;
287 fn float_less(&self, other: &Self) -> std::result::Result<Self, EmulatorErrorKind>;
288 fn float_less_equal(&self, other: &Self) -> std::result::Result<Self, EmulatorErrorKind>;
289}
290
291pub trait DomainMemory {
292 type V: DomainValue;
293
294 fn read(
297 &self,
298 space: MemorySpaceId,
299 addr: Self::V,
300 size: usize,
301 ) -> std::result::Result<Self::V, EmulatorErrorKind>;
302
303 fn write(
306 &mut self,
307 space: MemorySpaceId,
308 addr: Self::V,
309 size: usize,
310 data: Self::V,
311 ) -> std::result::Result<(), EmulatorErrorKind>;
312}
313
314pub trait Interpreter {
315 type V: DomainValue;
316 type M: DomainMemory<V = Self::V>;
317
318 fn ctx(&self) -> &Context<'_>;
319
320 fn memory(&mut self) -> &mut Self::M;
321
322 fn get_value(&mut self, id: ValueId) -> std::result::Result<Self::V, EmulatorErrorKind>;
324
325 fn get_varnode_value(
327 &mut self,
328 id: VarnodeId,
329 ) -> std::result::Result<Self::V, EmulatorErrorKind> {
330 let varnode = Varnode::from_id(self.ctx(), id);
331 let space = varnode.space().id;
332 let addr = Self::V::from_u64(varnode.address() as u64);
333 let size = varnode.size();
334 self.memory().read(space.into(), addr, size)
335 }
336
337 fn set_varnode_value(
339 &mut self,
340 id: VarnodeId,
341 value: Self::V,
342 ) -> std::result::Result<(), EmulatorErrorKind> {
343 let varnode = Varnode::from_id(self.ctx(), id);
344 let space = varnode.space().id;
345 let addr = Self::V::from_u64(varnode.address() as u64);
346 let size = varnode.size();
347 self.memory().write(space.into(), addr, size, value)?;
348 Ok(())
349 }
350
351 fn get_register_value(
353 &mut self,
354 reg_id: RegisterId,
355 ) -> std::result::Result<Self::V, EmulatorErrorKind> {
356 let id = *self
357 .ctx()
358 .shared
359 .registers
360 .get(®_id)
361 .ok_or(EmulatorErrorKind::UnknownRegister(reg_id))?;
362 self.get_varnode_value(id)
363 }
364
365 fn set_register_value(
367 &mut self,
368 reg_id: RegisterId,
369 value: Self::V,
370 ) -> std::result::Result<(), EmulatorErrorKind> {
371 let id = *self
372 .ctx()
373 .shared
374 .registers
375 .get(®_id)
376 .ok_or(EmulatorErrorKind::UnknownRegister(reg_id))?;
377 self.set_varnode_value(id, value)
378 }
379
380 fn interpret_(
383 &mut self,
384 insn: &InstructionRef<'_, '_>,
385 mnemonic: &Mnemonic,
386 ) -> std::result::Result<Option<Self::V>, EmulatorErrorKind> {
387 let func = insn.id.func;
390 let v = match mnemonic {
393 &Mnemonic::Load(Load { space, ptr, size }) => {
395 let addr = self.get_value(ptr.qualify(func))?;
396 Some(self.memory().read(space.qualify(func), addr, size)?)
397 }
398
399 &Mnemonic::Store(Store {
400 space,
401 ptr,
402 size,
403 src,
404 }) => {
405 let addr = self.get_value(ptr.qualify(func))?;
406 let value = self.get_value(src.qualify(func))?;
407 self.memory()
408 .write(space.qualify(func), addr, size, value)?;
409 None
410 }
411
412 Mnemonic::Branch(_)
414 | Mnemonic::CBranch(_)
415 | Mnemonic::BranchInd(_)
416 | Mnemonic::Call(_)
417 | Mnemonic::CallInd(_)
418 | Mnemonic::Return(_)
419 | Mnemonic::ReturnValue(_)
420 | Mnemonic::Apply(_) => None,
421
422 Mnemonic::Unop(Unary { op, src }) => {
424 let value = self.get_value(src.qualify(func))?;
425 let v = match op {
426 Unop::IntNegate => value.int_negate(),
427 Unop::IntNot => value.int_not(),
428 Unop::FloatNegate => value.float_negate(),
429 Unop::FloatAbs => value.float_abs(),
430 Unop::FloatSqrt => value.float_sqrt(),
431 Unop::FloatCeil => value.float_ceil(),
432 Unop::FloatFloor => value.float_floor(),
433 Unop::FloatRound => value.float_round(),
434 _ => todo!("unimplemented unary operation: {:?}", op),
435 }?;
436 Some(v)
437 }
438
439 Mnemonic::Binop(Binary { op, lhs, rhs }) => {
441 let value1 = self.get_value(lhs.qualify(func))?;
442 let value2 = self.get_value(rhs.qualify(func))?;
443 let v = match *op {
444 Binop::Int(IntBinop::Equal) => value1.int_equal(&value2),
445 Binop::Int(IntBinop::NotEqual) => value1.int_not_equal(&value2),
446 Binop::Int(IntBinop::Less) => value1.int_less(&value2),
447 Binop::Int(IntBinop::SLess) => value1.int_sless(&value2),
448 Binop::Int(IntBinop::LessEqual) => value1.int_less_equal(&value2),
449 Binop::Int(IntBinop::SLessEqual) => value1.int_sless_equal(&value2),
450 Binop::Int(IntBinop::Add) => value1.int_add(&value2),
451 Binop::Int(IntBinop::Sub) => value1.int_sub(&value2),
452 Binop::Int(IntBinop::Xor) => value1.int_xor(&value2),
453 Binop::Int(IntBinop::And) => value1.int_and(&value2),
454 Binop::Int(IntBinop::Or) => value1.int_or(&value2),
455 Binop::Int(IntBinop::ShiftLeft) => value1.int_shift_left(&value2),
456 Binop::Int(IntBinop::ShiftRight) => value1.int_shift_right(&value2),
457 Binop::Int(IntBinop::SShiftRight) => value1.int_sshift_right(&value2),
458 Binop::Int(IntBinop::Mul) => value1.int_mul(&value2),
459 Binop::Int(IntBinop::Div) => value1.int_div(&value2),
460 Binop::Int(IntBinop::Rem) => value1.int_rem(&value2),
461 Binop::Int(IntBinop::Sdiv) => value1.int_sdiv(&value2),
462 Binop::Int(IntBinop::Srem) => value1.int_srem(&value2),
463
464 Binop::Float(FloatBinop::Add) => value1.float_add(&value2),
465 Binop::Float(FloatBinop::Sub) => value1.float_sub(&value2),
466 Binop::Float(FloatBinop::Mul) => value1.float_mul(&value2),
467 Binop::Float(FloatBinop::Div) => value1.float_div(&value2),
468 Binop::Float(FloatBinop::Equal) => value1.float_equal(&value2),
469 Binop::Float(FloatBinop::NotEqual) => value1.float_not_equal(&value2),
470 Binop::Float(FloatBinop::Less) => value1.float_less(&value2),
471 Binop::Float(FloatBinop::LessEqual) => value1.float_less_equal(&value2),
472 _ => todo!("unimplemented binary operation: {:?}", op),
473 }?;
474 Some(v)
475 }
476
477 &Mnemonic::PopCount(PopCount { src }) => {
479 let value = self.get_value(src.qualify(func))?;
480 Some(value.pop_count()?)
481 }
482
483 &Mnemonic::LzCount(LzCount { src }) => {
484 let value = self.get_value(src.qualify(func))?;
485 Some(value.lz_count()?)
486 }
487
488 &Mnemonic::Carry(Carry { lhs, rhs }) => {
489 let value1 = self.get_value(lhs.qualify(func))?;
490 let value2 = self.get_value(rhs.qualify(func))?;
491 Some(value1.carry(&value2)?)
492 }
493
494 &Mnemonic::SCarry(SCarry { lhs, rhs }) => {
495 let value1 = self.get_value(lhs.qualify(func))?;
496 let value2 = self.get_value(rhs.qualify(func))?;
497 Some(value1.scarry(&value2)?)
498 }
499
500 &Mnemonic::SBorrow(SBorrow { lhs, rhs }) => {
501 let value1 = self.get_value(lhs.qualify(func))?;
502 let value2 = self.get_value(rhs.qualify(func))?;
503 Some(value1.sborrow(&value2)?)
504 }
505
506 &Mnemonic::IsFloatNaN(IsFloatNaN { src }) => {
508 let value = self.get_value(src.qualify(func))?;
509 Some(value.is_float_nan()?)
510 }
511 &Mnemonic::IntToFloat(IntToFloat { src, size }) => {
512 let value = self.get_value(src.qualify(func))?;
513 Some(value.int_to_float(size)?)
514 }
515 &Mnemonic::FloatToFloat(FloatToFloat { src, size }) => {
516 let value = self.get_value(src.qualify(func))?;
517 Some(value.float_to_float(size)?)
518 }
519 &Mnemonic::FloatToInt(FloatToInt { src, size }) => {
520 let value = self.get_value(src.qualify(func))?;
521 Some(value.float_to_int(size)?)
522 }
523 &Mnemonic::Zext(Zext { src, size }) => {
524 let value = self.get_value(src.qualify(func))?;
525 Some(value.zext(size)?)
526 }
527 &Mnemonic::Sext(Sext { src, size }) => {
528 let value = self.get_value(src.qualify(func))?;
529 Some(value.sext(size)?)
530 }
531 &Mnemonic::Range(Range { src, start, size }) => {
532 let value = self.get_value(src.qualify(func))?;
533 Some(value.range(start, size)?)
534 }
535
536 &Mnemonic::Gep(Gep { base, offset }) => {
541 let base = self.get_value(base.qualify(func))?;
542 let offset = Self::V::from_u64(offset as u64);
543 Some(base.int_add(&offset)?)
544 }
545
546 Mnemonic::PCodeOp(op) => {
548 let name = self.ctx().shared.pcode_ops[op.id].clone();
549 match (name.as_ref(), op.args.as_slice()) {
550 ("swap_bytes", [src]) => Some(self.get_value(src.qualify(func))?.byte_swap()?),
551 ("undef", []) => Some(Self::V::zero(insn.size())),
557 ("LOCK" | "UNLOCK", []) => None,
563 _ => return Err(EmulatorErrorKind::UnsupportedPCodeOp(name)),
564 }
565 }
566
567 Mnemonic::Intrinsic(intr) => {
568 let out_size = insn.size();
569 let mut args = Vec::with_capacity(intr.args.len());
570 for &arg in &intr.args {
571 args.push(self.get_value(arg.qualify(func))?);
572 }
573 Some(Self::V::intrinsic(intr.id, &args, out_size)?)
574 }
575
576 Mnemonic::Map(_) => return Err(EmulatorErrorKind::UnsupportedMnemonic("map")),
582
583 _ => todo!("unimplemented mnemonic: {mnemonic:?}"),
584 };
585
586 Ok(v)
587 }
588
589 fn interpret(
590 &mut self,
591 insn: InstructionRef<'_, '_>,
592 mnemonic: &Mnemonic,
593 ) -> Result<Option<Self::V>> {
594 self.interpret_(&insn, mnemonic)
595 .map_err(|kind| EmulatorError::new(kind, &insn))
596 }
597}