diff options
| author | Michael Krasnitski <michael.krasnitski@gmail.com> | 2024-02-08 19:50:49 -0500 |
|---|---|---|
| committer | Kyle Martin <krm504@nyu.edu> | 2024-03-18 17:46:37 -0400 |
| commit | 970fe84875e2d6eed918f5bdc9ff689ef37b05ce (patch) | |
| tree | 31fe9d82a623693c92c5c1fc7d05daf69fad3da3 /rust/src/mlil/operation.rs | |
| parent | f535df40f978d221547b45650b75aa1089e197ce (diff) | |
Make `OperandIter` generic over its function IL
Diffstat (limited to 'rust/src/mlil/operation.rs')
| -rw-r--r-- | rust/src/mlil/operation.rs | 227 |
1 files changed, 1 insertions, 226 deletions
diff --git a/rust/src/mlil/operation.rs b/rust/src/mlil/operation.rs index 319ba34b..eb0c01ea 100644 --- a/rust/src/mlil/operation.rs +++ b/rust/src/mlil/operation.rs @@ -1,235 +1,10 @@ use std::collections::HashMap; -use binaryninjacore_sys::BNFromVariableIdentifier; -use binaryninjacore_sys::BNGetMediumLevelILByIndex; -use binaryninjacore_sys::BNMediumLevelILInstruction; -use binaryninjacore_sys::BNMediumLevelILOperation; - -use crate::rc::Ref; use crate::types; use crate::types::ILIntrinsic; -use crate::types::RegisterValue; -use crate::types::RegisterValueType; use crate::types::{SSAVariable, Variable}; -use super::{MediumLevelILFunction, MediumLevelILInstruction, MediumLevelILLiftedInstruction}; - -pub struct OperandIter { - function: Ref<MediumLevelILFunction>, - remaining: usize, - next_iter_idx: Option<usize>, - current_iter: OperandIterInner, -} - -impl OperandIter { - pub(crate) fn new(function: &MediumLevelILFunction, idx: usize, number: usize) -> Self { - Self { - function: function.to_owned(), - remaining: number, - next_iter_idx: Some(idx), - current_iter: OperandIterInner::empty(), - } - } - - pub fn as_pairs(self) -> OperandPairIter { - assert_eq!(self.len() % 2, 0); - OperandPairIter(self) - } - - pub fn as_exprs(self) -> OperandExprIter { - OperandExprIter(self) - } - - pub fn as_vars(self) -> OperandVarIter { - OperandVarIter(self) - } - - pub fn as_ssa_vars(self) -> OperandSSAVarIter { - OperandSSAVarIter(self.as_pairs()) - } -} - -impl Iterator for OperandIter { - type Item = u64; - fn next(&mut self) -> Option<Self::Item> { - if let Some(item) = self.current_iter.next() { - self.remaining -= 1; - Some(item) - } else { - // Will short-circuit and return `None` once iter is exhausted - let iter_idx = self.next_iter_idx?; - let node = get_raw_operation(&self.function, iter_idx); - assert_eq!(node.operation, BNMediumLevelILOperation::MLIL_UNDEF); - - let next = if self.remaining > 4 { - self.next_iter_idx = Some(node.operands[4] as usize); - &node.operands[..4] - } else { - self.next_iter_idx = None; - &node.operands[..self.remaining] - }; - - self.current_iter = OperandIterInner::from_slice(next); - self.next() - } - } -} -impl ExactSizeIterator for OperandIter { - fn len(&self) -> usize { - self.remaining + self.current_iter.len() - } -} - -struct OperandIterInner { - arr: [u64; 4], - idx: usize, -} - -impl OperandIterInner { - fn from_slice(slice: &[u64]) -> Self { - assert!(slice.len() <= 4); - let idx = 4 - slice.len(); - let mut arr = [0; 4]; - arr[idx..].copy_from_slice(slice); - Self { arr, idx } - } - - fn empty() -> Self { - Self { - arr: [0; 4], - idx: 4, - } - } -} - -impl Iterator for OperandIterInner { - type Item = u64; - - fn next(&mut self) -> Option<Self::Item> { - if self.idx < 4 { - let val = self.arr[self.idx]; - self.idx += 1; - Some(val) - } else { - None - } - } -} -impl ExactSizeIterator for OperandIterInner { - fn len(&self) -> usize { - 4 - self.idx - } -} - -pub struct OperandPairIter(OperandIter); -impl Iterator for OperandPairIter { - type Item = (u64, u64); - - fn next(&mut self) -> Option<Self::Item> { - let first = self.0.next()?; - let second = self.0.next()?; - Some((first, second)) - } -} -impl ExactSizeIterator for OperandPairIter { - fn len(&self) -> usize { - self.0.len() / 2 - } -} - -pub struct OperandExprIter(OperandIter); -impl Iterator for OperandExprIter { - type Item = MediumLevelILInstruction; - - fn next(&mut self) -> Option<Self::Item> { - self.0 - .next() - .map(|idx| self.0.function.instruction_from_idx(idx as usize)) - } -} -impl ExactSizeIterator for OperandExprIter { - fn len(&self) -> usize { - self.0.len() - } -} - -pub struct OperandVarIter(OperandIter); -impl Iterator for OperandVarIter { - type Item = Variable; - - fn next(&mut self) -> Option<Self::Item> { - self.0.next().map(get_var) - } -} -impl ExactSizeIterator for OperandVarIter { - fn len(&self) -> usize { - self.0.len() - } -} - -pub struct OperandSSAVarIter(OperandPairIter); -impl Iterator for OperandSSAVarIter { - type Item = SSAVariable; - - fn next(&mut self) -> Option<Self::Item> { - self.0 - .next() - .map(|(id, version)| get_var_ssa(id, version as usize)) - } -} -impl ExactSizeIterator for OperandSSAVarIter { - fn len(&self) -> usize { - self.0.len() - } -} - -pub(super) fn get_float(value: u64, size: usize) -> f64 { - match size { - 4 => f32::from_bits(value as u32) as f64, - 8 => f64::from_bits(value), - // TODO how to handle this value? - size => todo!("float size {}", size), - } -} - -fn get_raw_operation(function: &MediumLevelILFunction, idx: usize) -> BNMediumLevelILInstruction { - unsafe { BNGetMediumLevelILByIndex(function.handle, idx) } -} - -pub(super) fn get_var(id: u64) -> Variable { - unsafe { Variable::from_raw(BNFromVariableIdentifier(id)) } -} - -pub(super) fn get_var_ssa(id: u64, version: usize) -> SSAVariable { - SSAVariable::new(get_var(id), version) -} - -pub(super) fn get_call_output(function: &MediumLevelILFunction, idx: usize) -> OperandVarIter { - let op = get_raw_operation(function, idx); - assert_eq!(op.operation, BNMediumLevelILOperation::MLIL_CALL_OUTPUT); - OperandIter::new(function, op.operands[1] as usize, op.operands[0] as usize).as_vars() -} - -pub(super) fn get_call_params(function: &MediumLevelILFunction, idx: usize) -> OperandExprIter { - let op = get_raw_operation(function, idx); - assert_eq!(op.operation, BNMediumLevelILOperation::MLIL_CALL_PARAM); - OperandIter::new(function, op.operands[1] as usize, op.operands[0] as usize).as_exprs() -} - -pub(super) fn get_call_output_ssa( - function: &MediumLevelILFunction, - idx: usize, -) -> OperandSSAVarIter { - let op = get_raw_operation(function, idx); - assert_eq!(op.operation, BNMediumLevelILOperation::MLIL_CALL_OUTPUT_SSA); - OperandIter::new(function, op.operands[2] as usize, op.operands[1] as usize).as_ssa_vars() -} - -pub(super) fn get_call_params_ssa(function: &MediumLevelILFunction, idx: usize) -> OperandExprIter { - let op = get_raw_operation(function, idx); - assert_eq!(op.operation, BNMediumLevelILOperation::MLIL_CALL_PARAM_SSA); - OperandIter::new(function, op.operands[2] as usize, op.operands[1] as usize).as_exprs() -} +use super::MediumLevelILLiftedInstruction; // IF #[derive(Copy, Clone)] |
