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 Interrupt,
151 UnsupportedIntrinsic(Box<str>),
154 InterceptError(Box<str>),
156 StepBudgetExceeded(usize),
158 UnsupportedMnemonic(&'static str),
162 EmptyBlock(BlockId),
166 PoisonRead,
171}
172
173impl std::fmt::Display for EmulatorErrorKind {
174 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
175 match self {
176 Self::InvalidBlockAddress(addr) => write!(f, "invalid block address {addr:#x}"),
177 Self::EmptyFunctionRoot(func) => write!(f, "function {func:?} has no root block"),
178 Self::UnresolvedMintedCallee(slot) => {
179 write!(f, "minted callee placeholder #{slot} is not executable")
180 }
181 Self::UnknownAddress(addr) => write!(f, "unknown address {addr:#x}"),
182 Self::AddressOverflow(addr, size) => {
183 write!(f, "address overflow at {addr:#x} with size {size}")
184 }
185 Self::MemoryReadError(addr) => write!(f, "memory read error at address {addr:#x}"),
186 Self::MemoryWriteError(addr) => write!(f, "memory write error at address {addr:#x}"),
187 Self::ValueError(value) => write!(f, "value {value} is too large to represent"),
188 Self::UnknownRegister(reg) => write!(f, "register {reg:?} not found in context"),
189 Self::UnknownSpace(space) => write!(f, "memory space {space:?} not initialised"),
190 Self::UnsupportedPCodeOp(op) => write!(f, "unsupported p-code operation `{op}`"),
191 Self::Interrupt => write!(f, "vm.interrupt"),
192 Self::UnsupportedIntrinsic(op) => write!(f, "unsupported intrinsic `{op}`"),
193 Self::InterceptError(message) => write!(f, "call interceptor failed: {message}"),
194 Self::StepBudgetExceeded(budget) => {
195 write!(f, "emulation exceeded step budget of {budget}")
196 }
197 Self::UnsupportedMnemonic(op) => write!(f, "unsupported mnemonic `{op}`"),
198 Self::EmptyBlock(block) => write!(f, "block {block:?} has no instructions"),
199 Self::PoisonRead => write!(f, "read of a poison value (undefined bits)"),
200 }
201 }
202}
203
204impl std::fmt::Display for EmulatorError {
205 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
206 write!(f, "emulator error: {}", self.kind)?;
207 write!(f, " (context: {})", self.ctx)?;
208 Ok(())
209 }
210}
211
212impl std::error::Error for EmulatorError {}
213
214pub type Result<T> = std::result::Result<T, EmulatorError>;
215
216pub trait DomainValue: Clone + Copy {
219 fn size(&self) -> std::result::Result<usize, EmulatorErrorKind>;
221
222 fn value(&self) -> std::result::Result<u64, EmulatorErrorKind>;
224
225 fn from_u64(value: u64) -> Self;
226
227 fn zero(_size: usize) -> Self {
231 Self::from_u64(0)
232 }
233
234 fn is_float_nan(&self) -> std::result::Result<Self, EmulatorErrorKind>;
235 fn int_to_float(&self, size: usize) -> std::result::Result<Self, EmulatorErrorKind>;
236 fn float_to_float(&self, size: usize) -> std::result::Result<Self, EmulatorErrorKind>;
237 fn float_to_int(&self, size: usize) -> std::result::Result<Self, EmulatorErrorKind>;
238 fn zext(&self, size: usize) -> std::result::Result<Self, EmulatorErrorKind>;
239 fn sext(&self, size: usize) -> std::result::Result<Self, EmulatorErrorKind>;
240 fn range(&self, start: usize, size: usize) -> std::result::Result<Self, EmulatorErrorKind>;
241 fn byte_swap(&self) -> std::result::Result<Self, EmulatorErrorKind>;
242
243 fn intrinsic(
246 id: qcode::value::insn::IntrinsicId,
247 args: &[Self],
248 out_size: usize,
249 ) -> std::result::Result<Self, EmulatorErrorKind>;
250
251 fn pop_count(&self) -> std::result::Result<Self, EmulatorErrorKind>;
252 fn lz_count(&self) -> std::result::Result<Self, EmulatorErrorKind>;
253 fn carry(&self, other: &Self) -> std::result::Result<Self, EmulatorErrorKind>;
254 fn scarry(&self, other: &Self) -> std::result::Result<Self, EmulatorErrorKind>;
255 fn sborrow(&self, other: &Self) -> std::result::Result<Self, EmulatorErrorKind>;
256
257 fn int_not(&self) -> std::result::Result<Self, EmulatorErrorKind>;
258 fn int_negate(&self) -> std::result::Result<Self, EmulatorErrorKind>;
259 fn float_negate(&self) -> std::result::Result<Self, EmulatorErrorKind>;
260 fn float_abs(&self) -> std::result::Result<Self, EmulatorErrorKind>;
261 fn float_sqrt(&self) -> std::result::Result<Self, EmulatorErrorKind>;
262 fn float_ceil(&self) -> std::result::Result<Self, EmulatorErrorKind>;
263 fn float_floor(&self) -> std::result::Result<Self, EmulatorErrorKind>;
264 fn float_round(&self) -> std::result::Result<Self, EmulatorErrorKind>;
265
266 fn int_equal(&self, other: &Self) -> std::result::Result<Self, EmulatorErrorKind>;
267 fn int_not_equal(&self, other: &Self) -> std::result::Result<Self, EmulatorErrorKind>;
268 fn int_less(&self, other: &Self) -> std::result::Result<Self, EmulatorErrorKind>;
269 fn int_sless(&self, other: &Self) -> std::result::Result<Self, EmulatorErrorKind>;
270 fn int_less_equal(&self, other: &Self) -> std::result::Result<Self, EmulatorErrorKind>;
271 fn int_sless_equal(&self, other: &Self) -> std::result::Result<Self, EmulatorErrorKind>;
272 fn int_add(&self, other: &Self) -> std::result::Result<Self, EmulatorErrorKind>;
273 fn int_sub(&self, other: &Self) -> std::result::Result<Self, EmulatorErrorKind>;
274 fn int_xor(&self, other: &Self) -> std::result::Result<Self, EmulatorErrorKind>;
275 fn int_and(&self, other: &Self) -> std::result::Result<Self, EmulatorErrorKind>;
276 fn int_or(&self, other: &Self) -> std::result::Result<Self, EmulatorErrorKind>;
277 fn int_shift_left(&self, other: &Self) -> std::result::Result<Self, EmulatorErrorKind>;
278 fn int_shift_right(&self, other: &Self) -> std::result::Result<Self, EmulatorErrorKind>;
279 fn int_sshift_right(&self, other: &Self) -> std::result::Result<Self, EmulatorErrorKind>;
280 fn int_mul(&self, other: &Self) -> std::result::Result<Self, EmulatorErrorKind>;
281 fn int_div(&self, other: &Self) -> std::result::Result<Self, EmulatorErrorKind>;
282 fn int_rem(&self, other: &Self) -> std::result::Result<Self, EmulatorErrorKind>;
283 fn int_sdiv(&self, other: &Self) -> std::result::Result<Self, EmulatorErrorKind>;
284 fn int_srem(&self, other: &Self) -> std::result::Result<Self, EmulatorErrorKind>;
285
286 fn float_add(&self, other: &Self) -> std::result::Result<Self, EmulatorErrorKind>;
287 fn float_sub(&self, other: &Self) -> std::result::Result<Self, EmulatorErrorKind>;
288 fn float_mul(&self, other: &Self) -> std::result::Result<Self, EmulatorErrorKind>;
289 fn float_div(&self, other: &Self) -> std::result::Result<Self, EmulatorErrorKind>;
290 fn float_equal(&self, other: &Self) -> std::result::Result<Self, EmulatorErrorKind>;
291 fn float_not_equal(&self, other: &Self) -> std::result::Result<Self, EmulatorErrorKind>;
292 fn float_less(&self, other: &Self) -> std::result::Result<Self, EmulatorErrorKind>;
293 fn float_less_equal(&self, other: &Self) -> std::result::Result<Self, EmulatorErrorKind>;
294}
295
296pub trait DomainMemory {
297 type V: DomainValue;
298
299 fn read(
302 &self,
303 space: MemorySpaceId,
304 addr: Self::V,
305 size: usize,
306 ) -> std::result::Result<Self::V, EmulatorErrorKind>;
307
308 fn write(
311 &mut self,
312 space: MemorySpaceId,
313 addr: Self::V,
314 size: usize,
315 data: Self::V,
316 ) -> std::result::Result<(), EmulatorErrorKind>;
317}
318
319pub trait Interpreter {
320 type V: DomainValue;
321 type M: DomainMemory<V = Self::V>;
322
323 fn ctx(&self) -> &Context<'_>;
324
325 fn memory(&mut self) -> &mut Self::M;
326
327 fn get_value(&mut self, id: ValueId) -> std::result::Result<Self::V, EmulatorErrorKind>;
329
330 fn get_varnode_value(
332 &mut self,
333 id: VarnodeId,
334 ) -> std::result::Result<Self::V, EmulatorErrorKind> {
335 let varnode = Varnode::from_id(self.ctx(), id);
336 let space = varnode.space().id;
337 let addr = Self::V::from_u64(varnode.address() as u64);
338 let size = varnode.size();
339 self.memory().read(space.into(), addr, size)
340 }
341
342 fn set_varnode_value(
344 &mut self,
345 id: VarnodeId,
346 value: Self::V,
347 ) -> std::result::Result<(), EmulatorErrorKind> {
348 let varnode = Varnode::from_id(self.ctx(), id);
349 let space = varnode.space().id;
350 let addr = Self::V::from_u64(varnode.address() as u64);
351 let size = varnode.size();
352 self.memory().write(space.into(), addr, size, value)?;
353 Ok(())
354 }
355
356 fn get_register_value(
358 &mut self,
359 reg_id: RegisterId,
360 ) -> std::result::Result<Self::V, EmulatorErrorKind> {
361 let id = *self
362 .ctx()
363 .shared
364 .registers
365 .get(®_id)
366 .ok_or(EmulatorErrorKind::UnknownRegister(reg_id))?;
367 self.get_varnode_value(id)
368 }
369
370 fn set_register_value(
372 &mut self,
373 reg_id: RegisterId,
374 value: Self::V,
375 ) -> std::result::Result<(), EmulatorErrorKind> {
376 let id = *self
377 .ctx()
378 .shared
379 .registers
380 .get(®_id)
381 .ok_or(EmulatorErrorKind::UnknownRegister(reg_id))?;
382 self.set_varnode_value(id, value)
383 }
384
385 fn interpret_(
388 &mut self,
389 insn: &InstructionRef<'_, '_>,
390 mnemonic: &Mnemonic,
391 ) -> std::result::Result<Option<Self::V>, EmulatorErrorKind> {
392 let func = insn.id.func;
395 let v = match mnemonic {
398 &Mnemonic::Load(Load { space, ptr, size }) => {
400 let addr = self.get_value(ptr.qualify(func))?;
401 Some(self.memory().read(space.qualify(func), addr, size)?)
402 }
403
404 &Mnemonic::Store(Store {
405 space,
406 ptr,
407 size,
408 src,
409 }) => {
410 let addr = self.get_value(ptr.qualify(func))?;
411 let value = self.get_value(src.qualify(func))?;
412 self.memory()
413 .write(space.qualify(func), addr, size, value)?;
414 None
415 }
416
417 Mnemonic::Branch(_)
419 | Mnemonic::CBranch(_)
420 | Mnemonic::BranchInd(_)
421 | Mnemonic::Call(_)
422 | Mnemonic::CallInd(_)
423 | Mnemonic::Return(_)
424 | Mnemonic::ReturnValue(_)
425 | Mnemonic::Apply(_) => None,
426
427 Mnemonic::Unop(Unary { op, src }) => {
429 let value = self.get_value(src.qualify(func))?;
430 let v = match op {
431 Unop::IntNegate => value.int_negate(),
432 Unop::IntNot => value.int_not(),
433 Unop::FloatNegate => value.float_negate(),
434 Unop::FloatAbs => value.float_abs(),
435 Unop::FloatSqrt => value.float_sqrt(),
436 Unop::FloatCeil => value.float_ceil(),
437 Unop::FloatFloor => value.float_floor(),
438 Unop::FloatRound => value.float_round(),
439 _ => todo!("unimplemented unary operation: {:?}", op),
440 }?;
441 Some(v)
442 }
443
444 Mnemonic::Binop(Binary { op, lhs, rhs }) => {
446 let value1 = self.get_value(lhs.qualify(func))?;
447 let value2 = self.get_value(rhs.qualify(func))?;
448 let v = match *op {
449 Binop::Int(IntBinop::Equal) => value1.int_equal(&value2),
450 Binop::Int(IntBinop::NotEqual) => value1.int_not_equal(&value2),
451 Binop::Int(IntBinop::Less) => value1.int_less(&value2),
452 Binop::Int(IntBinop::SLess) => value1.int_sless(&value2),
453 Binop::Int(IntBinop::LessEqual) => value1.int_less_equal(&value2),
454 Binop::Int(IntBinop::SLessEqual) => value1.int_sless_equal(&value2),
455 Binop::Int(IntBinop::Add) => value1.int_add(&value2),
456 Binop::Int(IntBinop::Sub) => value1.int_sub(&value2),
457 Binop::Int(IntBinop::Xor) => value1.int_xor(&value2),
458 Binop::Int(IntBinop::And) => value1.int_and(&value2),
459 Binop::Int(IntBinop::Or) => value1.int_or(&value2),
460 Binop::Int(IntBinop::ShiftLeft) => value1.int_shift_left(&value2),
461 Binop::Int(IntBinop::ShiftRight) => value1.int_shift_right(&value2),
462 Binop::Int(IntBinop::SShiftRight) => value1.int_sshift_right(&value2),
463 Binop::Int(IntBinop::Mul) => value1.int_mul(&value2),
464 Binop::Int(IntBinop::Div) => value1.int_div(&value2),
465 Binop::Int(IntBinop::Rem) => value1.int_rem(&value2),
466 Binop::Int(IntBinop::Sdiv) => value1.int_sdiv(&value2),
467 Binop::Int(IntBinop::Srem) => value1.int_srem(&value2),
468
469 Binop::Float(FloatBinop::Add) => value1.float_add(&value2),
470 Binop::Float(FloatBinop::Sub) => value1.float_sub(&value2),
471 Binop::Float(FloatBinop::Mul) => value1.float_mul(&value2),
472 Binop::Float(FloatBinop::Div) => value1.float_div(&value2),
473 Binop::Float(FloatBinop::Equal) => value1.float_equal(&value2),
474 Binop::Float(FloatBinop::NotEqual) => value1.float_not_equal(&value2),
475 Binop::Float(FloatBinop::Less) => value1.float_less(&value2),
476 Binop::Float(FloatBinop::LessEqual) => value1.float_less_equal(&value2),
477 _ => todo!("unimplemented binary operation: {:?}", op),
478 }?;
479 Some(v)
480 }
481
482 &Mnemonic::PopCount(PopCount { src }) => {
484 let value = self.get_value(src.qualify(func))?;
485 Some(value.pop_count()?)
486 }
487
488 &Mnemonic::LzCount(LzCount { src }) => {
489 let value = self.get_value(src.qualify(func))?;
490 Some(value.lz_count()?)
491 }
492
493 &Mnemonic::Carry(Carry { lhs, rhs }) => {
494 let value1 = self.get_value(lhs.qualify(func))?;
495 let value2 = self.get_value(rhs.qualify(func))?;
496 Some(value1.carry(&value2)?)
497 }
498
499 &Mnemonic::SCarry(SCarry { lhs, rhs }) => {
500 let value1 = self.get_value(lhs.qualify(func))?;
501 let value2 = self.get_value(rhs.qualify(func))?;
502 Some(value1.scarry(&value2)?)
503 }
504
505 &Mnemonic::SBorrow(SBorrow { lhs, rhs }) => {
506 let value1 = self.get_value(lhs.qualify(func))?;
507 let value2 = self.get_value(rhs.qualify(func))?;
508 Some(value1.sborrow(&value2)?)
509 }
510
511 &Mnemonic::IsFloatNaN(IsFloatNaN { src }) => {
513 let value = self.get_value(src.qualify(func))?;
514 Some(value.is_float_nan()?)
515 }
516 &Mnemonic::IntToFloat(IntToFloat { src, size }) => {
517 let value = self.get_value(src.qualify(func))?;
518 Some(value.int_to_float(size)?)
519 }
520 &Mnemonic::FloatToFloat(FloatToFloat { src, size }) => {
521 let value = self.get_value(src.qualify(func))?;
522 Some(value.float_to_float(size)?)
523 }
524 &Mnemonic::FloatToInt(FloatToInt { src, size }) => {
525 let value = self.get_value(src.qualify(func))?;
526 Some(value.float_to_int(size)?)
527 }
528 &Mnemonic::Zext(Zext { src, size }) => {
529 let value = self.get_value(src.qualify(func))?;
530 Some(value.zext(size)?)
531 }
532 &Mnemonic::Sext(Sext { src, size }) => {
533 let value = self.get_value(src.qualify(func))?;
534 Some(value.sext(size)?)
535 }
536 &Mnemonic::Range(Range { src, start, size }) => {
537 let value = self.get_value(src.qualify(func))?;
538 Some(value.range(start, size)?)
539 }
540
541 &Mnemonic::Gep(Gep { base, offset }) => {
546 let base = self.get_value(base.qualify(func))?;
547 let offset = Self::V::from_u64(offset as u64);
548 Some(base.int_add(&offset)?)
549 }
550
551 Mnemonic::PCodeOp(op) => {
553 let name = self.ctx().shared.pcode_ops[op.id].clone();
554 match (name.as_ref(), op.args.as_slice()) {
555 ("swap_bytes", [src]) => Some(self.get_value(src.qualify(func))?.byte_swap()?),
556 ("undef", []) => Some(Self::V::zero(insn.size())),
562 ("LOCK" | "UNLOCK", []) => None,
568 (qcode::value::insn::VM_INTERRUPT, _) => {
572 return Err(EmulatorErrorKind::Interrupt);
573 }
574 _ => return Err(EmulatorErrorKind::UnsupportedPCodeOp(name)),
575 }
576 }
577
578 Mnemonic::Intrinsic(intr) => {
579 let out_size = insn.size();
580 let mut args = Vec::with_capacity(intr.args.len());
581 for &arg in &intr.args {
582 args.push(self.get_value(arg.qualify(func))?);
583 }
584 Some(Self::V::intrinsic(intr.id, &args, out_size)?)
585 }
586
587 Mnemonic::Map(_) => return Err(EmulatorErrorKind::UnsupportedMnemonic("map")),
593
594 _ => todo!("unimplemented mnemonic: {mnemonic:?}"),
595 };
596
597 Ok(v)
598 }
599
600 fn interpret(
601 &mut self,
602 insn: InstructionRef<'_, '_>,
603 mnemonic: &Mnemonic,
604 ) -> Result<Option<Self::V>> {
605 self.interpret_(&insn, mnemonic)
606 .map_err(|kind| EmulatorError::new(kind, &insn))
607 }
608}