summaryrefslogtreecommitdiff
path: root/rust/src/mlil/operation.rs
diff options
context:
space:
mode:
authorMichael Krasnitski <michael.krasnitski@gmail.com>2024-02-08 19:50:49 -0500
committerKyle Martin <krm504@nyu.edu>2024-03-18 17:46:37 -0400
commit970fe84875e2d6eed918f5bdc9ff689ef37b05ce (patch)
tree31fe9d82a623693c92c5c1fc7d05daf69fad3da3 /rust/src/mlil/operation.rs
parentf535df40f978d221547b45650b75aa1089e197ce (diff)
Make `OperandIter` generic over its function IL
Diffstat (limited to 'rust/src/mlil/operation.rs')
-rw-r--r--rust/src/mlil/operation.rs227
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)]