Skip to content

Commit

Permalink
dummy context; eval. testing
Browse files Browse the repository at this point in the history
  • Loading branch information
xorpse committed Mar 28, 2024
1 parent 8a3c81f commit b14cde6
Show file tree
Hide file tree
Showing 5 changed files with 137 additions and 84 deletions.
123 changes: 123 additions & 0 deletions fugue-high/src/eval/dummy.rs
Original file line number Diff line number Diff line change
@@ -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<Address>, 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<usize, EvaluatorError> {
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<BitVec, EvaluatorError> {
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(())
}
}
85 changes: 4 additions & 81 deletions fugue-high/src/eval/mod.rs
Original file line number Diff line number Diff line change
@@ -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};

Expand All @@ -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;

Expand Down Expand Up @@ -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<Address>, 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<usize, EvaluatorError> {
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<BitVec, EvaluatorError> {
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,
Expand Down Expand Up @@ -169,9 +91,10 @@ where

pub fn step(
&mut self,
loc: Location,
loc: impl Into<Location>,
operation: &PCodeData,
) -> Result<EvaluatorTarget, EvaluatorError> {
let loc = loc.into();
match operation.opcode {
Opcode::Copy => {
let val = self.context.read_vnd(&operation.inputs[0])?;
Expand Down
6 changes: 3 additions & 3 deletions fugue-high/src/ir.rs
Original file line number Diff line number Diff line change
Expand Up @@ -84,10 +84,10 @@ impl Location {
}
}

impl From<Address> for Location {
fn from(address: Address) -> Self {
impl<T> From<T> for Location where Address: From<T> {
fn from(value: T) -> Self {
Self {
address,
address: value.into(),
position: 0,
}
}
Expand Down
1 change: 1 addition & 0 deletions fugue-high/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,5 @@ pub mod icfg;
pub mod ir;
pub mod language;
pub mod lifter;
pub mod prelude;
pub mod util;
6 changes: 6 additions & 0 deletions fugue-high/src/prelude.rs
Original file line number Diff line number Diff line change
@@ -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;

0 comments on commit b14cde6

Please sign in to comment.