From b14cde6fbdc93dfdb095f88545fbd8f4fa1ac731 Mon Sep 17 00:00:00 2001 From: Sam Thomas Date: Thu, 28 Mar 2024 01:24:40 +0000 Subject: [PATCH] dummy context; eval. testing --- fugue-high/src/eval/dummy.rs | 123 +++++++++++++++++++++++++++++++++++ fugue-high/src/eval/mod.rs | 85 ++---------------------- fugue-high/src/ir.rs | 6 +- fugue-high/src/lib.rs | 1 + fugue-high/src/prelude.rs | 6 ++ 5 files changed, 137 insertions(+), 84 deletions(-) create mode 100644 fugue-high/src/eval/dummy.rs create mode 100644 fugue-high/src/prelude.rs diff --git a/fugue-high/src/eval/dummy.rs b/fugue-high/src/eval/dummy.rs new file mode 100644 index 0000000..b1f7367 --- /dev/null +++ b/fugue-high/src/eval/dummy.rs @@ -0,0 +1,123 @@ +use fugue_bv::BitVec; +use fugue_bytes::Endian; +use fugue_ir::{Address, VarnodeData}; + +use crate::lifter::Lifter; + +use super::{EvaluatorContext, EvaluatorError, FixedState}; + +pub struct DummyContext { + base: Address, + endian: Endian, + memory: FixedState, + registers: FixedState, + temporaries: FixedState, +} + +impl DummyContext { + pub fn new(lifter: &Lifter, base: impl Into
, size: usize) -> Self { + let t = lifter.translator(); + + Self { + base: base.into(), + endian: if t.is_big_endian() { + Endian::Big + } else { + Endian::Little + }, + memory: FixedState::new(size), + registers: FixedState::new(t.register_space_size()), + temporaries: FixedState::new(t.unique_space_size()), + } + } + + fn translate(&self, addr: u64) -> Result { + let addr = addr + .checked_sub(self.base.into()) + .ok_or(EvaluatorError::state_with( + "address translation out-of-bounds", + ))?; + + Ok(addr as usize) + } +} + +impl EvaluatorContext for DummyContext { + fn read_vnd(&mut self, var: &VarnodeData) -> Result { + let spc = var.space(); + if spc.is_constant() { + Ok(BitVec::from_u64(var.offset(), var.size() * 8)) + } else if spc.is_register() { + self.registers + .read_val_with(var.offset() as usize, var.size(), self.endian) + .map_err(EvaluatorError::state) + } else if spc.is_unique() { + self.temporaries + .read_val_with(var.offset() as usize, var.size(), self.endian) + .map_err(EvaluatorError::state) + } else { + let addr = self.translate(var.offset())?; + self.memory + .read_val_with(addr, var.size(), self.endian) + .map_err(EvaluatorError::state) + } + } + + fn write_vnd(&mut self, var: &VarnodeData, val: &BitVec) -> Result<(), EvaluatorError> { + let spc = var.space(); + if spc.is_register() { + self.registers + .write_val_with(var.offset() as usize, val, self.endian) + .map_err(EvaluatorError::state) + } else if spc.is_unique() { + self.temporaries + .write_val_with(var.offset() as usize, val, self.endian) + .map_err(EvaluatorError::state) + } else if spc.is_default() { + let addr = self.translate(var.offset())?; + self.memory + .write_val_with(addr, val, self.endian) + .map_err(EvaluatorError::state) + } else { + panic!("cannot write to constant Varnode") + } + } +} + +#[cfg(test)] +mod test { + use crate::eval::Evaluator; + use crate::prelude::*; + + use super::*; + + #[test] + fn test_single_step() -> anyhow::Result<()> { + let lbuilder = LanguageBuilder::new("data")?; + let language = lbuilder.build("ARM:LE:32:v7", "default")?; + + let memory = &[ + 0x03, 0x00, 0x51, 0xE3, 0x0A, 0x00, 0x00, 0x9A, 0x00, 0x30, 0xA0, 0xE3, 0x01, 0x10, + 0x80, 0xE0, 0x03, 0x00, 0x80, 0xE2, 0x01, 0x20, 0xD0, 0xE4, 0x02, 0x30, 0x83, 0xE0, + 0x01, 0x00, 0x50, 0xE1, 0xFF, 0x30, 0x03, 0xE2, 0xFA, 0xFF, 0xFF, 0x1A, 0x00, 0x00, + 0x63, 0xE2, 0xFF, 0x00, 0x00, 0xE2, 0x1E, 0xFF, 0x2F, 0xE1, 0x00, 0x00, 0xA0, 0xE3, + 0x1E, 0xFF, 0x2F, 0xE1, + ]; + + let mut lifter = language.lifter(); + let irb = lifter.irb(1024); + + let pcode = lifter.lift(&irb, 0x15e38u32, memory)?; + + let mut context = DummyContext::new(&lifter, 0x15e38u32, 0x1000); + let mut evaluator = Evaluator::new(&lifter, &mut context); + + evaluator.context.memory.write_bytes(0usize, memory)?; + + for op in pcode.operations() { + evaluator.step(0x15e38u32, &op)?; + } + + Ok(()) + } +} diff --git a/fugue-high/src/eval/mod.rs b/fugue-high/src/eval/mod.rs index 7a69bdf..76c9023 100644 --- a/fugue-high/src/eval/mod.rs +++ b/fugue-high/src/eval/mod.rs @@ -1,6 +1,4 @@ use fugue_bv::BitVec; - -use fugue_bytes::Endian; use fugue_ir::disassembly::{Opcode, PCodeData}; use fugue_ir::{Address, AddressSpace, Translator, VarnodeData}; @@ -9,6 +7,8 @@ use thiserror::Error; use crate::ir::Location; use crate::lifter::Lifter; +pub mod dummy; + pub mod fixed_state; use self::fixed_state::FixedState; @@ -47,84 +47,6 @@ pub trait EvaluatorContext { fn write_vnd(&mut self, var: &VarnodeData, val: &BitVec) -> Result<(), EvaluatorError>; } -pub struct DummyContext { - base: Address, - endian: Endian, - memory: FixedState, - registers: FixedState, - temporaries: FixedState, -} - -impl DummyContext { - pub fn new(lifter: &Lifter, base: impl Into
, size: usize) -> Self { - let t = lifter.translator(); - - Self { - base: base.into(), - endian: if t.is_big_endian() { - Endian::Big - } else { - Endian::Little - }, - memory: FixedState::new(size), - registers: FixedState::new(t.register_space_size()), - temporaries: FixedState::new(t.unique_space_size()), - } - } - - fn translate(&self, addr: u64) -> Result { - let addr = addr - .checked_sub(self.base.into()) - .ok_or(EvaluatorError::state_with( - "address translation out-of-bounds", - ))?; - - Ok(addr as usize) - } -} - -impl EvaluatorContext for DummyContext { - fn read_vnd(&mut self, var: &VarnodeData) -> Result { - let spc = var.space(); - if spc.is_constant() { - Ok(BitVec::from_u64(var.offset(), var.size() * 8)) - } else if spc.is_register() { - self.registers - .read_val_with(var.offset() as usize, var.size(), self.endian) - .map_err(EvaluatorError::state) - } else if spc.is_unique() { - self.temporaries - .read_val_with(var.offset() as usize, var.size(), self.endian) - .map_err(EvaluatorError::state) - } else { - let addr = self.translate(var.offset())?; - self.memory - .read_val_with(addr, var.size(), self.endian) - .map_err(EvaluatorError::state) - } - } - - fn write_vnd(&mut self, var: &VarnodeData, val: &BitVec) -> Result<(), EvaluatorError> { - let spc = var.space(); - if spc.is_register() { - self.registers - .write_val_with(var.offset() as usize, val, self.endian) - .map_err(EvaluatorError::state) - } else if spc.is_unique() { - self.temporaries - .write_val_with(var.offset() as usize, val, self.endian) - .map_err(EvaluatorError::state) - } else if spc.is_default() { - let addr = self.translate(var.offset())?; - self.memory - .write_val_with(addr, val, self.endian) - .map_err(EvaluatorError::state) - } else { - panic!("cannot write to constant Varnode") - } - } -} - pub struct Evaluator<'a, 'b, C> where C: EvaluatorContext, @@ -169,9 +91,10 @@ where pub fn step( &mut self, - loc: Location, + loc: impl Into, operation: &PCodeData, ) -> Result { + let loc = loc.into(); match operation.opcode { Opcode::Copy => { let val = self.context.read_vnd(&operation.inputs[0])?; diff --git a/fugue-high/src/ir.rs b/fugue-high/src/ir.rs index 898d08a..04aaec1 100644 --- a/fugue-high/src/ir.rs +++ b/fugue-high/src/ir.rs @@ -84,10 +84,10 @@ impl Location { } } -impl From
for Location { - fn from(address: Address) -> Self { +impl From for Location where Address: From { + fn from(value: T) -> Self { Self { - address, + address: value.into(), position: 0, } } diff --git a/fugue-high/src/lib.rs b/fugue-high/src/lib.rs index 4f4e2de..7afa53d 100644 --- a/fugue-high/src/lib.rs +++ b/fugue-high/src/lib.rs @@ -4,4 +4,5 @@ pub mod icfg; pub mod ir; pub mod language; pub mod lifter; +pub mod prelude; pub mod util; diff --git a/fugue-high/src/prelude.rs b/fugue-high/src/prelude.rs new file mode 100644 index 0000000..a03d74f --- /dev/null +++ b/fugue-high/src/prelude.rs @@ -0,0 +1,6 @@ +pub use fugue_bv::BitVec; +pub use fugue_bytes::Endian; +pub use fugue_ir::Address; + +pub use crate::language::{Language, LanguageBuilder}; +pub use crate::lifter::Lifter;