diff options
| author | Rubens Brandao <git@rubens.io> | 2023-11-18 15:58:33 -0300 |
|---|---|---|
| committer | Kyle Martin <krm504@nyu.edu> | 2023-11-21 15:18:50 -0500 |
| commit | 8c9cdd38c3302280087c9e6d94f7f57083885edd (patch) | |
| tree | 8bccf380b4470e0de8ac11c23b164e0acf6ffbb0 /rust/src/mlil/operation.rs | |
| parent | b040fcfce48db861600eeb122cd0e2ff802fac96 (diff) | |
add mlil to rust
Diffstat (limited to 'rust/src/mlil/operation.rs')
| -rw-r--r-- | rust/src/mlil/operation.rs | 2170 |
1 files changed, 2170 insertions, 0 deletions
diff --git a/rust/src/mlil/operation.rs b/rust/src/mlil/operation.rs new file mode 100644 index 00000000..4b234bf1 --- /dev/null +++ b/rust/src/mlil/operation.rs @@ -0,0 +1,2170 @@ +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::{SSAVariable, Variable}; + +use super::{MediumLevelILFunction, MediumLevelILInstruction, MediumLevelILLiftedInstruction}; + +pub enum MediumLevelILOperand { + //TODO + //ConstantData(!), + //TODO + //Intrinsic(!), + Expr(MediumLevelILInstruction), + ExprList(OperandExprList), + Float(f64), + Int(u64), + IntList(OperandList), + TargetMap(OperandDubleList), + Var(Variable), + VarList(OperandVariableList), + VarSsa(SSAVariable), + VarSsaList(OperandSSAVariableList), +} + +// Iterator for the get_list, this is better then a inline iterator because +// this also implement ExactSizeIterator, what a inline iterator does not. +pub struct OperandList { + function: Ref<MediumLevelILFunction>, + remaining: usize, + next_node_idx: Option<usize>, + + current_node: core::array::IntoIter<u64, 4>, +} +impl OperandList { + fn new(function: &MediumLevelILFunction, idx: usize, number: usize) -> Self { + // alternative to core::array::IntoIter::empty(); + let mut iter = [0; 4].into_iter(); + for _ in 0..4 { + let _ = iter.next(); + } + Self { + function: function.to_owned(), + remaining: number, + next_node_idx: Some(idx), + current_node: iter, + } + } + fn duble(self) -> OperandDubleList { + assert_eq!(self.len() % 2, 0); + OperandDubleList(self) + } + fn map_expr(self) -> OperandExprList { + OperandExprList(self) + } + fn map_var(self) -> OperandVariableList { + OperandVariableList(self) + } + fn map_ssa_var(self) -> OperandSSAVariableList { + OperandSSAVariableList(self.duble()) + } +} +impl Iterator for OperandList { + type Item = u64; + + fn next(&mut self) -> Option<Self::Item> { + // if there is an item in this node, return it + if let Some(current_node) = self.current_node.next() { + return Some(current_node); + } + + // no more items to fetch + if self.remaining == 0 { + return None; + } + + // otherwise get the next node + let next_idx = self.next_node_idx?; + let node = unsafe { BNGetMediumLevelILByIndex(self.function.handle, next_idx) }; + assert_eq!(node.operation, BNMediumLevelILOperation::MLIL_UNDEF); + + // each node contains at most 4, the last is reserved to next node idx + let consume = if self.remaining > 4 { + // there are more nodes after this one + self.next_node_idx = Some(node.operands[4] as usize); + self.remaining -= 4; + &node.operands[0..4] + } else { + // last part of the list, there is no next node + self.next_node_idx = None; + let nodes = &node.operands[0..self.remaining]; + self.remaining = 0; + nodes + }; + // the iter need to have a space of 4, but we may have less then that, + // solution is create a dummy elements at the start and discard it + let mut nodes = [0; 4]; + let dummy_values = 4 - consume.len(); + nodes[dummy_values..4].copy_from_slice(consume); + self.current_node = nodes.into_iter(); + for _ in 0..dummy_values { + let _ = self.current_node.next(); + } + + self.current_node.next() + } + + fn size_hint(&self) -> (usize, Option<usize>) { + (self.len(), Some(self.len())) + } +} +impl ExactSizeIterator for OperandList { + fn len(&self) -> usize { + self.remaining + self.current_node.len() + } +} + +// Iterator similar to OperationList, but returns two elements +pub struct OperandDubleList(OperandList); +impl Iterator for OperandDubleList { + type Item = (u64, u64); + + fn next(&mut self) -> Option<Self::Item> { + let first = self.0.next()?; + let second = self.0.next().unwrap(); + Some((first, second)) + } + + fn size_hint(&self) -> (usize, Option<usize>) { + (self.len(), Some(self.len())) + } +} +impl ExactSizeIterator for OperandDubleList { + fn len(&self) -> usize { + self.0.len() / 2 + } +} + +pub struct OperandExprList(OperandList); +impl Iterator for OperandExprList { + type Item = MediumLevelILInstruction; + + fn next(&mut self) -> Option<Self::Item> { + self.0 + .next() + .map(|idx| get_operation(&self.0.function, idx as usize)) + } + + fn size_hint(&self) -> (usize, Option<usize>) { + (self.0.len(), Some(self.0.len())) + } +} +impl ExactSizeIterator for OperandExprList { + fn len(&self) -> usize { + self.0.len() + } +} + +pub struct OperandVariableList(OperandList); +impl Iterator for OperandVariableList { + type Item = Variable; + + fn next(&mut self) -> Option<Self::Item> { + self.0.next().map(get_var) + } + + fn size_hint(&self) -> (usize, Option<usize>) { + (self.0.len(), Some(self.0.len())) + } +} +impl ExactSizeIterator for OperandVariableList { + fn len(&self) -> usize { + self.0.len() + } +} + +pub struct OperandSSAVariableList(OperandDubleList); +impl Iterator for OperandSSAVariableList { + type Item = SSAVariable; + + fn next(&mut self) -> Option<Self::Item> { + self.0.next().map(|(id, version)| { + let raw = unsafe { BNFromVariableIdentifier(id) }; + let var = unsafe { Variable::from_raw(raw) }; + SSAVariable::new(var, version as usize) + }) + } + + fn size_hint(&self) -> (usize, Option<usize>) { + (self.len(), Some(self.len())) + } +} +impl ExactSizeIterator for OperandSSAVariableList { + fn len(&self) -> usize { + self.0.len() + } +} + +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), + } +} + +// TODO implement ConstantData +fn get_constant_data( + _function: &MediumLevelILFunction, + _value: u64, + _state: u64, + _size: usize, +) -> ! { + todo!() +} + +// TODO implement Intrinsic +fn get_intrinsic(_function: &MediumLevelILFunction, _idx: usize) -> ! { + todo!() +} + +fn get_operation(function: &MediumLevelILFunction, idx: usize) -> MediumLevelILInstruction { + function.instruction_from_idx(idx) +} + +fn get_raw_operation(function: &MediumLevelILFunction, idx: usize) -> BNMediumLevelILInstruction { + unsafe { BNGetMediumLevelILByIndex(function.handle, idx) } +} + +fn get_var(id: u64) -> Variable { + unsafe { Variable::from_raw(BNFromVariableIdentifier(id)) } +} + +fn get_var_ssa(id: u64, version: usize) -> SSAVariable { + let raw = unsafe { BNFromVariableIdentifier(id) }; + let var = unsafe { Variable::from_raw(raw) }; + SSAVariable::new(var, version as usize) +} + +fn get_call_list( + function: &MediumLevelILFunction, + op_type: BNMediumLevelILOperation, + idx: usize, +) -> OperandVariableList { + let op = unsafe { BNGetMediumLevelILByIndex(function.handle, idx) }; + assert_eq!(op.operation, op_type); + OperandList::new(function, op.operands[1] as usize, op.operands[0] as usize).map_var() +} + +fn get_call_output(function: &MediumLevelILFunction, idx: usize) -> OperandVariableList { + get_call_list(function, BNMediumLevelILOperation::MLIL_CALL_OUTPUT, idx) +} + +fn get_call_params(function: &MediumLevelILFunction, idx: usize) -> OperandVariableList { + get_call_list(function, BNMediumLevelILOperation::MLIL_CALL_PARAM, idx) +} + +fn get_call_list_ssa( + function: &MediumLevelILFunction, + op_type: BNMediumLevelILOperation, + idx: usize, +) -> OperandSSAVariableList { + let op = get_raw_operation(function, idx); + assert_eq!(op.operation, op_type); + OperandList::new(function, op.operands[2] as usize, op.operands[1] as usize).map_ssa_var() +} + +fn get_call_output_ssa(function: &MediumLevelILFunction, idx: usize) -> OperandSSAVariableList { + get_call_list_ssa( + function, + BNMediumLevelILOperation::MLIL_CALL_OUTPUT_SSA, + idx, + ) +} + +fn get_call_params_ssa(function: &MediumLevelILFunction, idx: usize) -> OperandSSAVariableList { + get_call_list_ssa(function, BNMediumLevelILOperation::MLIL_CALL_PARAM_SSA, idx) +} + +// NOP, NORET, BP, UNDEF, UNIMPL +#[derive(Default, Copy, Clone, Debug, Hash, PartialEq, Eq)] +pub struct NoArgs {} + +// IF +#[derive(Copy, Clone)] +pub struct MediumLevelILOperationIf { + condition: usize, + dest_true: u64, + dest_false: u64, +} +#[derive(Clone, Debug, PartialEq)] +pub struct LiftedIf { + pub condition: Box<MediumLevelILLiftedInstruction>, + pub dest_true: u64, + pub dest_false: u64, +} +impl MediumLevelILOperationIf { + pub fn new(condition: usize, dest_true: u64, dest_false: u64) -> Self { + Self { + condition, + dest_true, + dest_false, + } + } + pub fn condition(&self, function: &MediumLevelILFunction) -> MediumLevelILInstruction { + get_operation(function, self.condition) + } + pub fn dest_true(&self) -> u64 { + self.dest_true + } + pub fn dest_false(&self) -> u64 { + self.dest_false + } + pub fn lift(&self, function: &MediumLevelILFunction) -> LiftedIf { + LiftedIf { + condition: Box::new(self.condition(function).lift()), + dest_true: self.dest_true(), + dest_false: self.dest_false(), + } + } + pub fn operands( + &self, + function: &MediumLevelILFunction, + ) -> impl Iterator<Item = (&'static str, MediumLevelILOperand)> { + use MediumLevelILOperand::*; + [ + ("condition", Expr(self.condition(function))), + ("dest_true", Int(self.dest_true())), + ("dest_false", Int(self.dest_false())), + ] + .into_iter() + } +} + +// FLOAT_CONST +#[derive(Copy, Clone, Debug, PartialEq)] +pub struct FloatConst { + pub constant: f64, +} +impl FloatConst { + pub fn new(constant: u64, size: usize) -> Self { + Self { + constant: get_float(constant, size), + } + } + pub fn constant(&self) -> f64 { + self.constant + } + pub fn operands(&self) -> impl Iterator<Item = (&'static str, MediumLevelILOperand)> { + [("constant", MediumLevelILOperand::Float(self.constant()))].into_iter() + } +} + +// CONST, CONST_PTR, IMPORT +#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)] +pub struct Constant { + pub constant: u64, +} +impl Constant { + pub fn new(constant: u64) -> Self { + Self { constant } + } + pub fn constant(&self) -> u64 { + self.constant + } + pub fn operands(&self) -> impl Iterator<Item = (&'static str, MediumLevelILOperand)> { + [("constant", MediumLevelILOperand::Int(self.constant()))].into_iter() + } +} + +// EXTERN_PTR +#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)] +pub struct ExternPtr { + pub constant: u64, + pub offset: u64, +} +impl ExternPtr { + pub fn new(constant: u64, offset: u64) -> Self { + Self { constant, offset } + } + pub fn constant(&self) -> u64 { + self.constant + } + pub fn offset(&self) -> u64 { + self.offset + } + pub fn operands( + &self, + _function: &MediumLevelILFunction, + ) -> impl Iterator<Item = (&'static str, MediumLevelILOperand)> { + [ + ("constant", MediumLevelILOperand::Int(self.constant())), + ("offset", MediumLevelILOperand::Int(self.offset())), + ] + .into_iter() + } +} + +// CONST_DATA +#[derive(Copy, Clone)] +pub struct ConstData { + constant_data: (u64, u64), +} +#[derive(Clone, Debug, Hash, PartialEq, Eq)] +pub struct ConstantData { + //pub constant_data: !, +} +impl ConstData { + pub fn new(constant_data: (u64, u64)) -> Self { + Self { constant_data } + } + pub fn constant_data(&self, function: &MediumLevelILFunction, size: usize) -> ! { + get_constant_data(function, self.constant_data.0, self.constant_data.1, size) + } + pub fn lift(&self, _function: &MediumLevelILFunction) -> ConstantData { + ConstantData { + // TODO + } + } + pub fn operands( + &self, + _function: &MediumLevelILFunction, + ) -> impl Iterator<Item = (&'static str, MediumLevelILOperand)> { + // TODO + [ + //("contant_data", MediumLevelILOperand::ConstData(_self.constant_data(function, self.size))) + ] + .into_iter() + } +} + +// JUMP, RET_HINT +#[derive(Copy, Clone)] +pub struct Jump { + dest: usize, +} +#[derive(Clone, Debug, PartialEq)] +pub struct LiftedJump { + pub dest: Box<MediumLevelILLiftedInstruction>, +} +impl Jump { + pub fn new(dest: usize) -> Self { + Self { dest } + } + pub fn dest(&self, function: &MediumLevelILFunction) -> MediumLevelILInstruction { + get_operation(function, self.dest) + } + pub fn lift(&self, function: &MediumLevelILFunction) -> LiftedJump { + LiftedJump { + dest: Box::new(self.dest(function).lift()), + } + } + pub fn operands( + &self, + function: &MediumLevelILFunction, + ) -> impl Iterator<Item = (&'static str, MediumLevelILOperand)> { + [("dest", MediumLevelILOperand::Expr(self.dest(&function)))].into_iter() + } +} + +// STORE_SSA +#[derive(Copy, Clone)] +pub struct StoreSsa { + dest: usize, + dest_memory: u64, + src_memory: u64, + src: usize, +} +#[derive(Clone, Debug, PartialEq)] +pub struct LiftedStoreSsa { + pub dest: Box<MediumLevelILLiftedInstruction>, + pub dest_memory: u64, + pub src_memory: u64, + pub src: Box<MediumLevelILLiftedInstruction>, +} +impl StoreSsa { + pub fn new(dest: usize, dest_memory: u64, src_memory: u64, src: usize) -> Self { + Self { + dest, + dest_memory, + src_memory, + src, + } + } + pub fn dest(&self, function: &MediumLevelILFunction) -> MediumLevelILInstruction { + get_operation(function, self.dest) + } + pub fn dest_memory(&self) -> u64 { + self.dest_memory + } + pub fn src_memory(&self) -> u64 { + self.src_memory + } + pub fn src(&self, function: &MediumLevelILFunction) -> MediumLevelILInstruction { + get_operation(function, self.src) + } + pub fn lift(&self, function: &MediumLevelILFunction) -> LiftedStoreSsa { + LiftedStoreSsa { + dest: Box::new(self.dest(function).lift()), + dest_memory: self.dest_memory(), + src_memory: self.src_memory(), + src: Box::new(self.src(function).lift()), + } + } + pub fn operands( + &self, + function: &MediumLevelILFunction, + ) -> impl Iterator<Item = (&'static str, MediumLevelILOperand)> { + [ + ("dest", MediumLevelILOperand::Expr(self.dest(&function))), + ("dest_memory", MediumLevelILOperand::Int(self.dest_memory())), + ("src_memory", MediumLevelILOperand::Int(self.src_memory())), + ("src", MediumLevelILOperand::Expr(self.src(&function))), + ] + .into_iter() + } +} + +// STORE_STRUCT_SSA +#[derive(Copy, Clone)] +pub struct StoreStructSsa { + dest: usize, + offset: u64, + dest_memory: u64, + src_memory: u64, + src: usize, +} +#[derive(Clone, Debug, PartialEq)] +pub struct LiftedStoreStructSsa { + pub dest: Box<MediumLevelILLiftedInstruction>, + pub offset: u64, + pub dest_memory: u64, + pub src_memory: u64, + pub src: Box<MediumLevelILLiftedInstruction>, +} +impl StoreStructSsa { + pub fn new(dest: usize, offset: u64, dest_memory: u64, src_memory: u64, src: usize) -> Self { + Self { + dest, + offset, + dest_memory, + src_memory, + src, + } + } + pub fn dest(&self, function: &MediumLevelILFunction) -> MediumLevelILInstruction { + get_operation(function, self.dest) + } + pub fn offset(&self) -> u64 { + self.offset + } + pub fn dest_memory(&self) -> u64 { + self.dest_memory + } + pub fn src_memory(&self) -> u64 { + self.src_memory + } + pub fn src(&self, function: &MediumLevelILFunction) -> MediumLevelILInstruction { + get_operation(function, self.src) + } + pub fn lift(&self, function: &MediumLevelILFunction) -> LiftedStoreStructSsa { + LiftedStoreStructSsa { + dest: Box::new(self.dest(function).lift()), + offset: self.offset(), + dest_memory: self.dest_memory(), + src_memory: self.src_memory(), + src: Box::new(self.src(function).lift()), + } + } + pub fn operands( + &self, + function: &MediumLevelILFunction, + ) -> impl Iterator<Item = (&'static str, MediumLevelILOperand)> { + [ + ("dest", MediumLevelILOperand::Expr(self.dest(function))), + ("offset", MediumLevelILOperand::Int(self.offset())), + ("dest_memory", MediumLevelILOperand::Int(self.dest_memory())), + ("src_memory", MediumLevelILOperand::Int(self.src_memory())), + ("src", MediumLevelILOperand::Expr(self.src(function))), + ] + .into_iter() + } +} + +// STORE_STRUCT +#[derive(Copy, Clone)] +pub struct StoreStruct { + dest: usize, + offset: u64, + src: usize, +} +#[derive(Clone, Debug, PartialEq)] +pub struct LiftedStoreStruct { + pub dest: Box<MediumLevelILLiftedInstruction>, + pub offset: u64, + pub src: Box<MediumLevelILLiftedInstruction>, +} +impl StoreStruct { + pub fn new(dest: usize, offset: u64, src: usize) -> Self { + Self { dest, offset, src } + } + pub fn dest(&self, function: &MediumLevelILFunction) -> MediumLevelILInstruction { + get_operation(function, self.dest) + } + pub fn offset(&self) -> u64 { + self.offset + } + pub fn src(&self, function: &MediumLevelILFunction) -> MediumLevelILInstruction { + get_operation(function, self.src) + } + pub fn lift(&self, function: &MediumLevelILFunction) -> LiftedStoreStruct { + LiftedStoreStruct { + dest: Box::new(self.dest(function).lift()), + offset: self.offset(), + src: Box::new(self.src(function).lift()), + } + } + pub fn operands( + &self, + function: &MediumLevelILFunction, + ) -> impl Iterator<Item = (&'static str, MediumLevelILOperand)> { + [ + ("dest", MediumLevelILOperand::Expr(self.dest(function))), + ("offset", MediumLevelILOperand::Int(self.offset())), + ("src", MediumLevelILOperand::Expr(self.src(function))), + ] + .into_iter() + } +} + +// STORE +#[derive(Copy, Clone)] +pub struct Store { + dest: usize, + src: usize, +} +#[derive(Clone, Debug, PartialEq)] +pub struct LiftedStore { + pub dest: Box<MediumLevelILLiftedInstruction>, + pub src: Box<MediumLevelILLiftedInstruction>, +} +impl Store { + pub fn new(dest: usize, src: usize) -> Self { + Self { dest, src } + } + pub fn dest(&self, function: &MediumLevelILFunction) -> MediumLevelILInstruction { + get_operation(function, self.dest) + } + pub fn src(&self, function: &MediumLevelILFunction) -> MediumLevelILInstruction { + get_operation(function, self.src) + } + pub fn lift(&self, function: &MediumLevelILFunction) -> LiftedStore { + LiftedStore { + dest: Box::new(self.dest(function).lift()), + src: Box::new(self.src(function).lift()), + } + } + pub fn operands( + &self, + function: &MediumLevelILFunction, + ) -> impl Iterator<Item = (&'static str, MediumLevelILOperand)> { + [ + ("dest", MediumLevelILOperand::Expr(self.dest(function))), + ("src", MediumLevelILOperand::Expr(self.src(function))), + ] + .into_iter() + } +} + +// JUMP_TO +#[derive(Copy, Clone)] +pub struct JumpTo { + dest: usize, + targets: (usize, usize), +} +#[derive(Clone, Debug, PartialEq)] +pub struct LiftedJumpTo { + pub dest: Box<MediumLevelILLiftedInstruction>, + pub targets: HashMap<u64, u64>, +} +impl JumpTo { + pub fn new(dest: usize, targets: (usize, usize)) -> Self { + Self { dest, targets } + } + pub fn dest(&self, function: &MediumLevelILFunction) -> MediumLevelILInstruction { + get_operation(function, self.dest) + } + pub fn targets(&self, function: &MediumLevelILFunction) -> OperandDubleList { + OperandList::new(function, self.targets.1, self.targets.0).duble() + } + pub fn lift(&self, function: &MediumLevelILFunction) -> LiftedJumpTo { + LiftedJumpTo { + dest: Box::new(self.dest(function).lift()), + targets: self.targets(function).collect(), + } + } + pub fn operands( + &self, + function: &MediumLevelILFunction, + ) -> impl Iterator<Item = (&'static str, MediumLevelILOperand)> { + use MediumLevelILOperand::*; + [ + ("dest", Expr(self.dest(function))), + ("targets", TargetMap(self.targets(function))), + ] + .into_iter() + } +} + +// GOTO +#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq)] +pub struct Goto { + pub dest: u64, +} +impl Goto { + pub fn new(dest: u64) -> Self { + Self { dest } + } + pub fn dest(&self) -> u64 { + self.dest + } + pub fn operands(&self) -> impl Iterator<Item = (&'static str, MediumLevelILOperand)> { + [("dest", MediumLevelILOperand::Int(self.dest()))].into_iter() + } +} + +// FREE_VAR_SLOT +#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)] +pub struct FreeVarSlot { + pub dest: Variable, +} +impl FreeVarSlot { + pub fn new(dest: u64) -> Self { + Self { + dest: get_var(dest), + } + } + pub fn dest(&self) -> Variable { + self.dest + } + pub fn operands(&self) -> impl Iterator<Item = (&'static str, MediumLevelILOperand)> { + [("dest", MediumLevelILOperand::Var(self.dest()))].into_iter() + } +} + +// SET_VAR_FIELD +#[derive(Copy, Clone)] +pub struct SetVarField { + dest: u64, + offset: u64, + src: usize, +} +#[derive(Clone, Debug, PartialEq)] +pub struct LiftedSetVarField { + pub dest: Variable, + pub offset: u64, + pub src: Box<MediumLevelILLiftedInstruction>, +} +impl SetVarField { + pub fn new(dest: u64, offset: u64, src: usize) -> Self { + Self { dest, offset, src } + } + pub fn dest(&self) -> Variable { + get_var(self.dest) + } + pub fn offset(&self) -> u64 { + self.offset + } + pub fn src(&self, function: &MediumLevelILFunction) -> MediumLevelILInstruction { + get_operation(function, self.src) + } + pub fn lift(&self, function: &MediumLevelILFunction) -> LiftedSetVarField { + LiftedSetVarField { + dest: self.dest(), + offset: self.offset(), + src: Box::new(self.src(function).lift()), + } + } + pub fn operands( + &self, + function: &MediumLevelILFunction, + ) -> impl Iterator<Item = (&'static str, MediumLevelILOperand)> { + [ + ("dest", MediumLevelILOperand::Var(self.dest())), + ("offset", MediumLevelILOperand::Int(self.offset())), + ("src", MediumLevelILOperand::Expr(self.src(function))), + ] + .into_iter() + } +} + +// SET_VAR +#[derive(Copy, Clone)] +pub struct SetVar { + dest: u64, + src: usize, +} +#[derive(Clone, Debug, PartialEq)] +pub struct LiftedSetVar { + pub dest: Variable, + pub src: Box<MediumLevelILLiftedInstruction>, +} +impl SetVar { + pub fn new(dest: u64, src: usize) -> Self { + Self { dest, src } + } + pub fn dest(&self) -> Variable { + get_var(self.dest) + } + pub fn src(&self, function: &MediumLevelILFunction) -> MediumLevelILInstruction { + get_operation(function, self.src) + } + pub fn lift(&self, function: &MediumLevelILFunction) -> LiftedSetVar { + LiftedSetVar { + dest: self.dest(), + src: Box::new(self.src(function).lift()), + } + } + pub fn operands( + &self, + function: &MediumLevelILFunction, + ) -> impl Iterator<Item = (&'static str, MediumLevelILOperand)> { + [ + ("dest", MediumLevelILOperand::Var(self.dest())), + ("src", MediumLevelILOperand::Expr(self.src(function))), + ] + .into_iter() + } +} + +// FREE_VAR_SLOT_SSA +#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)] +pub struct FreeVarSlotSsa { + pub dest: SSAVariable, + pub prev: SSAVariable, +} +impl FreeVarSlotSsa { + pub fn new(dest: (u64, usize), prev: (u64, usize)) -> Self { + Self { + dest: get_var_ssa(dest.0, dest.1), + prev: get_var_ssa(prev.0, prev.1), + } + } + pub fn dest(&self) -> SSAVariable { + self.dest + } + pub fn prev(&self) -> SSAVariable { + self.prev + } + pub fn lift(self) -> FreeVarSlotSsa { + FreeVarSlotSsa { + dest: self.dest(), + prev: self.prev(), + } + } + pub fn operands(&self) -> impl Iterator<Item = (&'static str, MediumLevelILOperand)> { + [ + ("dest", MediumLevelILOperand::VarSsa(self.dest())), + ("prev", MediumLevelILOperand::VarSsa(self.prev())), + ] + .into_iter() + } +} + +// SET_VAR_SSA_FIELD, SET_VAR_ALIASED_FIELD +#[derive(Copy, Clone)] +pub struct SetVarSsaField { + dest: (u64, usize), + prev: (u64, usize), + offset: u64, + src: usize, +} +#[derive(Clone, Debug, PartialEq)] +pub struct LiftedSetVarSsaField { + pub dest: SSAVariable, + pub prev: SSAVariable, + pub offset: u64, + pub src: Box<MediumLevelILLiftedInstruction>, +} +impl SetVarSsaField { + pub fn new(dest: (u64, usize), prev: (u64, usize), offset: u64, src: usize) -> Self { + Self { + dest, + prev, + offset, + src, + } + } + pub fn dest(&self) -> SSAVariable { + get_var_ssa(self.dest.0, self.dest.1) + } + pub fn prev(&self) -> SSAVariable { + get_var_ssa(self.prev.0, self.prev.1) + } + pub fn offset(&self) -> u64 { + self.offset + } + pub fn src(&self, function: &MediumLevelILFunction) -> MediumLevelILInstruction { + get_operation(function, self.src) + } + pub fn lift(&self, function: &MediumLevelILFunction) -> LiftedSetVarSsaField { + LiftedSetVarSsaField { + dest: self.dest(), + prev: self.prev(), + offset: self.offset(), + src: Box::new(self.src(function).lift()), + } + } + pub fn operands( + &self, + function: &MediumLevelILFunction, + ) -> impl Iterator<Item = (&'static str, MediumLevelILOperand)> { + [ + ("dest", MediumLevelILOperand::VarSsa(self.dest())), + ("prev", MediumLevelILOperand::VarSsa(self.prev())), + ("offset", MediumLevelILOperand::Int(self.offset())), + ("src", MediumLevelILOperand::Expr(self.src(function))), + ] + .into_iter() + } +} + +// SET_VAR_ALIASED +#[derive(Copy, Clone)] +pub struct SetVarAliased { + dest: (u64, usize), + prev: (u64, usize), + src: usize, +} +#[derive(Clone, Debug, PartialEq)] +pub struct LiftedSetVarAliased { + pub dest: SSAVariable, + pub prev: SSAVariable, + pub src: Box<MediumLevelILLiftedInstruction>, +} +impl SetVarAliased { + pub fn new(dest: (u64, usize), prev: (u64, usize), src: usize) -> Self { + Self { dest, prev, src } + } + pub fn dest(&self) -> SSAVariable { + get_var_ssa(self.dest.0, self.dest.1) + } + pub fn prev(&self) -> SSAVariable { + get_var_ssa(self.prev.0, self.prev.1) + } + pub fn src(&self, function: &MediumLevelILFunction) -> MediumLevelILInstruction { + get_operation(function, self.src) + } + pub fn lift(&self, function: &MediumLevelILFunction) -> LiftedSetVarAliased { + LiftedSetVarAliased { + dest: self.dest(), + prev: self.prev(), + src: Box::new(self.src(function).lift()), + } + } + pub fn operands( + &self, + function: &MediumLevelILFunction, + ) -> impl Iterator<Item = (&'static str, MediumLevelILOperand)> { + [ + ("dest", MediumLevelILOperand::VarSsa(self.dest())), + ("prev", MediumLevelILOperand::VarSsa(self.prev())), + ("src", MediumLevelILOperand::Expr(self.src(function))), + ] + .into_iter() + } +} + +// SET_VAR_SSA +#[derive(Copy, Clone)] +pub struct SetVarSsa { + dest: (u64, usize), + src: usize, +} +#[derive(Clone, Debug, PartialEq)] +pub struct LiftedSetVarSsa { + pub dest: SSAVariable, + pub src: Box<MediumLevelILLiftedInstruction>, +} +impl SetVarSsa { + pub fn new(dest: (u64, usize), src: usize) -> Self { + Self { dest, src } + } + pub fn dest(&self) -> SSAVariable { + get_var_ssa(self.dest.0, self.dest.1) + } + pub fn src(&self, function: &MediumLevelILFunction) -> MediumLevelILInstruction { + get_operation(function, self.src) + } + pub fn lift(&self, function: &MediumLevelILFunction) -> LiftedSetVarSsa { + LiftedSetVarSsa { + dest: self.dest(), + src: Box::new(self.src(function).lift()), + } + } + pub fn operands( + &self, + function: &MediumLevelILFunction, + ) -> impl Iterator<Item = (&'static str, MediumLevelILOperand)> { + [ + ("dest", MediumLevelILOperand::VarSsa(self.dest())), + ("src", MediumLevelILOperand::Expr(self.src(function))), + ] + .into_iter() + } +} + +// VAR_PHI +#[derive(Copy, Clone)] +pub struct VarPhi { + dest: (u64, usize), + src: (usize, usize), +} +#[derive(Clone, Debug, Hash, PartialEq, Eq)] +pub struct LiftedVarPhi { + pub dest: SSAVariable, + pub src: Vec<SSAVariable>, +} +impl VarPhi { + pub fn new(dest: (u64, usize), src: (usize, usize)) -> Self { + Self { dest, src } + } + pub fn dest(&self) -> SSAVariable { + get_var_ssa(self.dest.0, self.dest.1) + } + pub fn src(&self, function: &MediumLevelILFunction) -> OperandSSAVariableList { + OperandList::new(function, self.src.1, self.src.0).map_ssa_var() + } + pub fn lift(&self, function: &MediumLevelILFunction) -> LiftedVarPhi { + LiftedVarPhi { + dest: self.dest(), + src: self.src(function).collect(), + } + } + pub fn operands( + &self, + function: &MediumLevelILFunction, + ) -> impl Iterator<Item = (&'static str, MediumLevelILOperand)> { + [ + ("dest", MediumLevelILOperand::VarSsa(self.dest())), + ("src", MediumLevelILOperand::VarSsaList(self.src(function))), + ] + .into_iter() + } +} + +// MEM_PHI +#[derive(Copy, Clone)] +pub struct MemPhi { + dest_memory: u64, + src_memory: (usize, usize), +} +#[derive(Clone, Debug, Hash, PartialEq, Eq)] +pub struct LiftedMemPhi { + pub dest_memory: u64, + pub src_memory: Vec<u64>, +} +impl MemPhi { + pub fn new(dest_memory: u64, src_memory: (usize, usize)) -> Self { + Self { + dest_memory, + src_memory, + } + } + pub fn dest_memory(&self) -> u64 { + self.dest_memory + } + pub fn src_memory(&self, function: &MediumLevelILFunction) -> OperandList { + OperandList::new(function, self.src_memory.1, self.src_memory.0) + } + pub fn lift(&self, function: &MediumLevelILFunction) -> LiftedMemPhi { + LiftedMemPhi { + dest_memory: self.dest_memory(), + src_memory: self.src_memory(function).collect(), + } + } + pub fn operands( + &self, + function: &MediumLevelILFunction, + ) -> impl Iterator<Item = (&'static str, MediumLevelILOperand)> { + use MediumLevelILOperand::*; + [ + ("dest_memory", Int(self.dest_memory())), + ("src_memory", IntList(self.src_memory(function))), + ] + .into_iter() + } +} + +// VAR_SPLIT +#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)] +pub struct VarSplit { + pub high: Variable, + pub low: Variable, +} +impl VarSplit { + pub fn new(high: u64, low: u64) -> Self { + Self { + high: get_var(high), + low: get_var(low), + } + } + pub fn high(&self) -> Variable { + self.high + } + pub fn low(&self) -> Variable { + self.low + } + pub fn lift(self) -> VarSplit { + VarSplit { + high: self.high(), + low: self.low(), + } + } + pub fn operands(&self) -> impl Iterator<Item = (&'static str, MediumLevelILOperand)> { + [ + ("high", MediumLevelILOperand::Var(self.high())), + ("low", MediumLevelILOperand::Var(self.low())), + ] + .into_iter() + } +} + +// SET_VAR_SPLIT +#[derive(Copy, Clone)] +pub struct SetVarSplit { + high: u64, + low: u64, + src: usize, +} +#[derive(Clone, Debug, PartialEq)] +pub struct LiftedSetVarSplit { + pub high: Variable, + pub low: Variable, + pub src: Box<MediumLevelILLiftedInstruction>, +} +impl SetVarSplit { + pub fn new(high: u64, low: u64, src: usize) -> Self { + Self { high, low, src } + } + pub fn high(&self) -> Variable { + get_var(self.high) + } + pub fn low(&self) -> Variable { + get_var(self.low) + } + pub fn src(&self, function: &MediumLevelILFunction) -> MediumLevelILInstruction { + get_operation(function, self.src) + } + pub fn lift(&self, function: &MediumLevelILFunction) -> LiftedSetVarSplit { + LiftedSetVarSplit { + high: self.high(), + low: self.low(), + src: Box::new(self.src(function).lift()), + } + } + pub fn operands( + &self, + function: &MediumLevelILFunction, + ) -> impl Iterator<Item = (&'static str, MediumLevelILOperand)> { + [ + ("high", MediumLevelILOperand::Var(self.high())), + ("low", MediumLevelILOperand::Var(self.low())), + ("src", MediumLevelILOperand::Expr(self.src(function))), + ] + .into_iter() + } +} + +// VAR_SPLIT_SSA +#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)] +pub struct VarSplitSsa { + pub high: SSAVariable, + pub low: SSAVariable, +} +impl VarSplitSsa { + pub fn new(high: (u64, usize), low: (u64, usize)) -> Self { + Self { + high: get_var_ssa(high.0, high.1), + low: get_var_ssa(low.0, low.1), + } + } + pub fn high(&self) -> SSAVariable { + self.high + } + pub fn low(&self) -> SSAVariable { + self.low + } + pub fn lift(self) -> VarSplitSsa { + VarSplitSsa { + high: self.high(), + low: self.low(), + } + } + pub fn operands(&self) -> impl Iterator<Item = (&'static str, MediumLevelILOperand)> { + [ + ("high", MediumLevelILOperand::VarSsa(self.high())), + ("low", MediumLevelILOperand::VarSsa(self.low())), + ] + .into_iter() + } +} + +// SET_VAR_SPLIT_SSA +#[derive(Copy, Clone)] +pub struct SetVarSplitSsa { + high: (u64, usize), + low: (u64, usize), + src: usize, +} +#[derive(Clone, Debug, PartialEq)] +pub struct LiftedSetVarSplitSsa { + pub high: SSAVariable, + pub low: SSAVariable, + pub src: Box<MediumLevelILLiftedInstruction>, +} +impl SetVarSplitSsa { + pub fn new(high: (u64, usize), low: (u64, usize), src: usize) -> Self { + Self { high, low, src } + } + pub fn high(&self) -> SSAVariable { + get_var_ssa(self.high.0, self.high.1) + } + pub fn low(&self) -> SSAVariable { + get_var_ssa(self.low.0, self.low.1) + } + pub fn src(&self, function: &MediumLevelILFunction) -> MediumLevelILInstruction { + get_operation(function, self.src) + } + pub fn lift(&self, function: &MediumLevelILFunction) -> LiftedSetVarSplitSsa { + LiftedSetVarSplitSsa { + high: self.high(), + low: self.low(), + src: Box::new(self.src(function).lift()), + } + } + pub fn operands( + &self, + function: &MediumLevelILFunction, + ) -> impl Iterator<Item = (&'static str, MediumLevelILOperand)> { + [ + ("high", MediumLevelILOperand::VarSsa(self.high())), + ("low", MediumLevelILOperand::VarSsa(self.low())), + ("src", MediumLevelILOperand::Expr(self.src(function))), + ] + .into_iter() + } +} + +// ADD, SUB, AND, OR, XOR, LSL, LSR, ASR, ROL, ROR, MUL, MULU_DP, MULS_DP, DIVU, DIVU_DP, DIVS, DIVS_DP, MODU, MODU_DP, MODS, MODS_DP, CMP_E, CMP_NE, CMP_SLT, CMP_ULT, CMP_SLE, CMP_ULE, CMP_SGE, CMP_UGE, CMP_SGT, CMP_UGT, TEST_BIT, ADD_OVERFLOW, FCMP_E, FCMP_NE, FCMP_LT, FCMP_LE, FCMP_GE, FCMP_GT, FCMP_O, FCMP_UO, FADD, FSUB, FMUL, FDIV +#[derive(Copy, Clone)] +pub struct BinaryOp { + left: usize, + right: usize, +} +#[derive(Clone, Debug, PartialEq)] +pub struct LiftedBinaryOp { + pub left: Box<MediumLevelILLiftedInstruction>, + pub right: Box<MediumLevelILLiftedInstruction>, +} +impl BinaryOp { + pub fn new(left: usize, right: usize) -> Self { + Self { left, right } + } + pub fn left(&self, function: &MediumLevelILFunction) -> MediumLevelILInstruction { + get_operation(function, self.left) + } + pub fn right(&self, function: &MediumLevelILFunction) -> MediumLevelILInstruction { + get_operation(function, self.right) + } + pub fn lift(&self, function: &MediumLevelILFunction) -> LiftedBinaryOp { + LiftedBinaryOp { + left: Box::new(self.left(function).lift()), + right: Box::new(self.right(function).lift()), + } + } + pub fn operands( + &self, + function: &MediumLevelILFunction, + ) -> impl Iterator<Item = (&'static str, MediumLevelILOperand)> { + [ + ("left", MediumLevelILOperand::Expr(self.left(function))), + ("right", MediumLevelILOperand::Expr(self.right(function))), + ] + .into_iter() + } +} + +// ADC, SBB, RLC, RRC +#[derive(Copy, Clone)] +pub struct BinaryOpCarry { + left: usize, + right: usize, + carry: usize, +} +#[derive(Clone, Debug, PartialEq)] +pub struct LiftedBinaryOpCarry { + pub left: Box<MediumLevelILLiftedInstruction>, + pub right: Box<MediumLevelILLiftedInstruction>, + pub carry: Box<MediumLevelILLiftedInstruction>, +} +impl BinaryOpCarry { + pub fn new(left: usize, right: usize, carry: usize) -> Self { + Self { left, right, carry } + } + pub fn left(&self, function: &MediumLevelILFunction) -> MediumLevelILInstruction { + get_operation(function, self.left) + } + pub fn right(&self, function: &MediumLevelILFunction) -> MediumLevelILInstruction { + get_operation(function, self.right) + } + pub fn carry(&self, function: &MediumLevelILFunction) -> MediumLevelILInstruction { + get_operation(function, self.carry) + } + pub fn lift(&self, function: &MediumLevelILFunction) -> LiftedBinaryOpCarry { + LiftedBinaryOpCarry { + left: Box::new(self.left(function).lift()), + right: Box::new(self.right(function).lift()), + carry: Box::new(self.carry(function).lift()), + } + } + pub fn operands( + &self, + function: &MediumLevelILFunction, + ) -> impl Iterator<Item = (&'static str, MediumLevelILOperand)> { + [ + ("left", MediumLevelILOperand::Expr(self.left(function))), + ("right", MediumLevelILOperand::Expr(self.right(function))), + ("carry", MediumLevelILOperand::Expr(self.carry(function))), + ] + .into_iter() + } +} + +// CALL, TAILCALL +#[derive(Copy, Clone)] +pub struct Call { + output: (usize, usize), + dest: usize, + params: (usize, usize), +} +#[derive(Clone, Debug, PartialEq)] +pub struct LiftedCall { + pub output: Vec<Variable>, + pub dest: Box<MediumLevelILLiftedInstruction>, + pub params: Vec<MediumLevelILLiftedInstruction>, +} +impl Call { + pub fn new(output: (usize, usize), dest: usize, params: (usize, usize)) -> Self { + Self { + output, + dest, + params, + } + } + pub fn output(&self, function: &MediumLevelILFunction) -> OperandVariableList { + OperandList::new(function, self.output.1, self.output.0).map_var() + } + pub fn dest(&self, function: &MediumLevelILFunction) -> MediumLevelILInstruction { + get_operation(function, self.dest) + } + pub fn params(&self, function: &MediumLevelILFunction) -> OperandExprList { + OperandList::new(function, self.params.1, self.params.0).map_expr() + } + pub fn lift(&self, function: &MediumLevelILFunction) -> LiftedCall { + LiftedCall { + output: self.output(function).collect(), + dest: Box::new(self.dest(function).lift()), + params: self.params(function).map(|instr| instr.lift()).collect(), + } + } + pub fn operands( + &self, + function: &MediumLevelILFunction, + ) -> impl Iterator<Item = (&'static str, MediumLevelILOperand)> { + [ + ( + "output", + MediumLevelILOperand::VarList(self.output(function)), + ), + ("dest", MediumLevelILOperand::Expr(self.dest(function))), + ( + "params", + MediumLevelILOperand::ExprList(self.params(function)), + ), + ] + .into_iter() + } +} + +// SYSCALL +#[derive(Copy, Clone)] +pub struct Syscall { + output: (usize, usize), + params: (usize, usize), +} +#[derive(Clone, Debug, PartialEq)] +pub struct LiftedInnerCall { + pub output: Vec<Variable>, + pub params: Vec<MediumLevelILLiftedInstruction>, +} +impl Syscall { + pub fn new(output: (usize, usize), params: (usize, usize)) -> Self { + Self { output, params } + } + pub fn output(&self, function: &MediumLevelILFunction) -> OperandVariableList { + OperandList::new(function, self.output.1, self.output.0).map_var() + } + pub fn params(&self, function: &MediumLevelILFunction) -> OperandExprList { + OperandList::new(function, self.params.1, self.params.0).map_expr() + } + pub fn lift(&self, function: &MediumLevelILFunction) -> LiftedInnerCall { + LiftedInnerCall { + output: self.output(function).collect(), + params: self.params(function).map(|instr| instr.lift()).collect(), + } + } + pub fn operands( + &self, + function: &MediumLevelILFunction, + ) -> impl Iterator<Item = (&'static str, MediumLevelILOperand)> { + use MediumLevelILOperand::*; + [ + ("output", VarList(self.output(function))), + ("params", ExprList(self.params(function))), + ] + .into_iter() + } +} + +// INTRINSIC +#[derive(Copy, Clone)] +pub struct Intrinsic { + output: (usize, usize), + intrinsic: usize, + params: (usize, usize), +} +#[derive(Clone, Debug, PartialEq)] +pub struct MediumLevelILLiftedIntrinsic { + pub output: Vec<Variable>, + //pub intrinsic: !, + pub params: Vec<MediumLevelILLiftedInstruction>, +} +impl Intrinsic { + pub fn new(output: (usize, usize), intrinsic: usize, params: (usize, usize)) -> Self { + Self { + output, + intrinsic, + params, + } + } + pub fn output(&self, function: &MediumLevelILFunction) -> OperandVariableList { + OperandList::new(function, self.output.1, self.output.0).map_var() + } + pub fn intrinsic(&self, function: &MediumLevelILFunction) -> ! { + get_intrinsic(function, self.intrinsic) + } + pub fn params(&self, function: &MediumLevelILFunction) -> OperandExprList { + OperandList::new(function, self.params.1, self.params.0).map_expr() + } + pub fn lift(&self, function: &MediumLevelILFunction) -> LiftedInnerCall { + LiftedInnerCall { + output: self.output(function).collect(), + //intrinsic: get_intrinsic(function, self.intrinsic), + params: self.params(function).map(|instr| instr.lift()).collect(), + } + } + pub fn operands( + &self, + function: &MediumLevelILFunction, + ) -> impl Iterator<Item = (&'static str, MediumLevelILOperand)> { + use MediumLevelILOperand::*; + [ + ("output", VarList(self.output(function))), + //("intrinsic", VarList(self.output(function))), + ("params", ExprList(self.params(function))), + ] + .into_iter() + } +} + +// INTRINSIC_SSA +#[derive(Copy, Clone)] +pub struct IntrinsicSsa { + output: (usize, usize), + intrinsic: usize, + params: (usize, usize), +} +#[derive(Clone, Debug, PartialEq)] +pub struct LiftedIntrinsicSsa { + pub output: Vec<SSAVariable>, + //pub intrinsic: !, + pub params: Vec<MediumLevelILLiftedInstruction>, +} +impl IntrinsicSsa { + pub fn new(output: (usize, usize), intrinsic: usize, params: (usize, usize)) -> Self { + Self { + output, + intrinsic, + params, + } + } + pub fn output(&self, function: &MediumLevelILFunction) -> OperandSSAVariableList { + OperandList::new(function, self.output.1, self.output.0).map_ssa_var() + } + pub fn intrinsic(&self, function: &MediumLevelILFunction) -> ! { + get_intrinsic(function, self.intrinsic) + } + pub fn params(&self, function: &MediumLevelILFunction) -> OperandExprList { + OperandList::new(function, self.params.1, self.params.0).map_expr() + } + pub fn lift(&self, function: &MediumLevelILFunction) -> LiftedIntrinsicSsa { + LiftedIntrinsicSsa { + output: self.output(function).collect(), + //intrinsic: get_intrinsic(function, self.intrinsic), + params: self.params(function).map(|instr| instr.lift()).collect(), + } + } + pub fn operands( + &self, + function: &MediumLevelILFunction, + ) -> impl Iterator<Item = (&'static str, MediumLevelILOperand)> { + use MediumLevelILOperand::*; + [ + ("output", VarSsaList(self.output(function))), + ("params", ExprList(self.params(function))), + ] + .into_iter() + } +} + +// CALL_SSA, TAILCALL_SSA +#[derive(Copy, Clone)] +pub struct CallSsa { + output: usize, + dest: usize, + params: (usize, usize), + src_memory: u64, +} +#[derive(Clone, Debug, PartialEq)] +pub struct LiftedCallSsa { + pub output: Vec<SSAVariable>, + pub dest: Box<MediumLevelILLiftedInstruction>, + pub params: Vec<MediumLevelILLiftedInstruction>, + pub src_memory: u64, +} +impl CallSsa { + pub fn new(output: usize, dest: usize, params: (usize, usize), src_memory: u64) -> Self { + Self { + output, + dest, + params, + src_memory, + } + } + pub fn output(&self, function: &MediumLevelILFunction) -> OperandSSAVariableList { + get_call_output_ssa(function, self.output) + } + pub fn dest(&self, function: &MediumLevelILFunction) -> MediumLevelILInstruction { + get_operation(function, self.dest) + } + pub fn params(&self, function: &MediumLevelILFunction) -> OperandExprList { + OperandList::new(function, self.params.1, self.params.0).map_expr() + } + pub fn src_memory(&self) -> u64 { + self.src_memory + } + pub fn lift(&self, function: &MediumLevelILFunction) -> LiftedCallSsa { + LiftedCallSsa { + output: self.output(function).collect(), + dest: Box::new(self.dest(function).lift()), + params: self.params(function).map(|instr| instr.lift()).collect(), + src_memory: self.src_memory(), + } + } + pub fn operands( + &self, + function: &MediumLevelILFunction, + ) -> impl Iterator<Item = (&'static str, MediumLevelILOperand)> { + use MediumLevelILOperand::*; + [ + ("output", VarSsaList(self.output(function))), + ("dest", Expr(self.dest(function))), + ("params", ExprList(self.params(function))), + ("src_memory", Int(self.src_memory())), + ] + .into_iter() + } +} + +// CALL_UNTYPED_SSA, TAILCALL_UNTYPED_SSA +#[derive(Copy, Clone)] +pub struct CallUntypedSsa { + output: usize, + dest: usize, + params: usize, + stack: usize, +} +#[derive(Clone, Debug, PartialEq)] +pub struct LiftedCallUntypedSsa { + pub output: Vec<SSAVariable>, + pub dest: Box<MediumLevelILLiftedInstruction>, + pub params: Vec<SSAVariable>, + pub stack: Box<MediumLevelILLiftedInstruction>, +} +impl CallUntypedSsa { + pub fn new(output: usize, dest: usize, params: usize, stack: usize) -> Self { + Self { + output, + dest, + params, + stack, + } + } + pub fn output(&self, function: &MediumLevelILFunction) -> OperandSSAVariableList { + get_call_output_ssa(function, self.output) + } + pub fn dest(&self, function: &MediumLevelILFunction) -> MediumLevelILInstruction { + get_operation(function, self.dest) + } + pub fn params(&self, function: &MediumLevelILFunction) -> OperandSSAVariableList { + get_call_params_ssa(function, self.params) + } + pub fn stack(&self, function: &MediumLevelILFunction) -> MediumLevelILInstruction { + get_operation(function, self.stack) + } + pub fn lift(&self, function: &MediumLevelILFunction) -> LiftedCallUntypedSsa { + LiftedCallUntypedSsa { + output: self.output(function).collect(), + dest: Box::new(self.dest(function).lift()), + params: self.params(function).collect(), + stack: Box::new(self.stack(function).lift()), + } + } + pub fn operands( + &self, + function: &MediumLevelILFunction, + ) -> impl Iterator<Item = (&'static str, MediumLevelILOperand)> { + use MediumLevelILOperand::*; + [ + ("output", VarSsaList(self.output(function))), + ("dest", Expr(self.dest(function))), + ("params", VarSsaList(self.params(function))), + ("stack", Expr(self.stack(function))), + ] + .into_iter() + } +} + +// SYSCALL_SSA +#[derive(Copy, Clone)] +pub struct SyscallSsa { + output: usize, + params: (usize, usize), + src_memory: u64, +} +#[derive(Clone, Debug, PartialEq)] +pub struct LiftedSyscallSsa { + pub output: Vec<SSAVariable>, + pub params: Vec<MediumLevelILLiftedInstruction>, + pub src_memory: u64, +} +impl SyscallSsa { + pub fn new(output: usize, params: (usize, usize), src_memory: u64) -> Self { + Self { + output, + params, + src_memory, + } + } + pub fn output(&self, function: &MediumLevelILFunction) -> OperandSSAVariableList { + get_call_output_ssa(function, self.output) + } + pub fn params(&self, function: &MediumLevelILFunction) -> OperandExprList { + OperandList::new(function, self.params.1, self.params.0).map_expr() + } + pub fn src_memory(&self) -> u64 { + self.src_memory + } + pub fn lift(&self, function: &MediumLevelILFunction) -> LiftedSyscallSsa { + LiftedSyscallSsa { + output: self.output(function).collect(), + params: self.params(function).map(|instr| instr.lift()).collect(), + src_memory: self.src_memory(), + } + } + pub fn operands( + &self, + function: &MediumLevelILFunction, + ) -> impl Iterator<Item = (&'static str, MediumLevelILOperand)> { + use MediumLevelILOperand::*; + [ + ("output", VarSsaList(self.output(function))), + ("params", ExprList(self.params(function))), + ("src_memory", MediumLevelILOperand::Int(self.src_memory())), + ] + .into_iter() + } +} + +// SYSCALL_UNTYPED_SSA +#[derive(Copy, Clone)] +pub struct SyscallUntypedSsa { + output: usize, + params: usize, + stack: usize, +} +#[derive(Clone, Debug, PartialEq)] +pub struct LiftedSyscallUntypedSsa { + pub output: Vec<SSAVariable>, + pub params: Vec<SSAVariable>, + pub stack: Box<MediumLevelILLiftedInstruction>, +} +impl SyscallUntypedSsa { + pub fn new(output: usize, params: usize, stack: usize) -> Self { + Self { + output, + params, + stack, + } + } + pub fn output(&self, function: &MediumLevelILFunction) -> OperandSSAVariableList { + get_call_output_ssa(function, self.output) + } + pub fn params(&self, function: &MediumLevelILFunction) -> OperandSSAVariableList { + get_call_params_ssa(function, self.params) + } + pub fn stack(&self, function: &MediumLevelILFunction) -> MediumLevelILInstruction { + get_operation(function, self.stack) + } + pub fn lift(&self, function: &MediumLevelILFunction) -> LiftedSyscallUntypedSsa { + LiftedSyscallUntypedSsa { + output: self.output(function).collect(), + params: self.params(function).collect(), + stack: Box::new(self.stack(function).lift()), + } + } + pub fn operands( + &self, + function: &MediumLevelILFunction, + ) -> impl Iterator<Item = (&'static str, MediumLevelILOperand)> { + use MediumLevelILOperand::*; + [ + ("output", VarSsaList(self.output(function))), + ("params", VarSsaList(self.params(function))), + ("stack", Expr(self.stack(function))), + ] + .into_iter() + } +} + +// CALL_UNTYPED, TAILCALL_UNTYPED +#[derive(Copy, Clone)] +pub struct CallUntyped { + output: usize, + dest: usize, + params: usize, + stack: usize, +} +#[derive(Clone, Debug, PartialEq)] +pub struct LiftedCallUntyped { + pub output: Vec<Variable>, + pub dest: Box<MediumLevelILLiftedInstruction>, + pub params: Vec<Variable>, + pub stack: Box<MediumLevelILLiftedInstruction>, +} +impl CallUntyped { + pub fn new(output: usize, dest: usize, params: usize, stack: usize) -> Self { + Self { + output, + dest, + params, + stack, + } + } + pub fn output(&self, function: &MediumLevelILFunction) -> OperandVariableList { + get_call_output(function, self.output) + } + pub fn dest(&self, function: &MediumLevelILFunction) -> MediumLevelILInstruction { + get_operation(function, self.dest) + } + pub fn params(&self, function: &MediumLevelILFunction) -> OperandVariableList { + get_call_params(function, self.params) + } + pub fn stack(&self, function: &MediumLevelILFunction) -> MediumLevelILInstruction { + get_operation(function, self.stack) + } + pub fn lift(&self, function: &MediumLevelILFunction) -> LiftedCallUntyped { + LiftedCallUntyped { + output: self.output(function).collect(), + dest: Box::new(self.dest(function).lift()), + params: self.params(function).collect(), + stack: Box::new(self.stack(function).lift()), + } + } + pub fn operands( + &self, + function: &MediumLevelILFunction, + ) -> impl Iterator<Item = (&'static str, MediumLevelILOperand)> { + use MediumLevelILOperand::*; + [ + ("output", VarList(self.output(function))), + ("dest", Expr(self.dest(function))), + ("params", VarList(self.params(function))), + ("stack", Expr(self.stack(function))), + ] + .into_iter() + } +} + +// SYSCALL_UNTYPED +#[derive(Copy, Clone)] +pub struct SyscallUntyped { + output: usize, + params: usize, + stack: usize, +} +#[derive(Clone, Debug, PartialEq)] +pub struct LiftedSyscallUntyped { + pub output: Vec<Variable>, + pub params: Vec<Variable>, + pub stack: Box<MediumLevelILLiftedInstruction>, +} +impl SyscallUntyped { + pub fn new(output: usize, params: usize, stack: usize) -> Self { + Self { + output, + params, + stack, + } + } + pub fn output(&self, function: &MediumLevelILFunction) -> OperandVariableList { + get_call_output(function, self.output) + } + pub fn params(&self, function: &MediumLevelILFunction) -> OperandVariableList { + get_call_params(function, self.params) + } + pub fn stack(&self, function: &MediumLevelILFunction) -> MediumLevelILInstruction { + get_operation(function, self.stack) + } + pub fn lift(&self, function: &MediumLevelILFunction) -> LiftedSyscallUntyped { + LiftedSyscallUntyped { + output: self.output(function).collect(), + params: self.params(function).collect(), + stack: Box::new(self.stack(function).lift()), + } + } + pub fn operands( + &self, + function: &MediumLevelILFunction, + ) -> impl Iterator<Item = (&'static str, MediumLevelILOperand)> { + use MediumLevelILOperand::*; + [ + ("output", VarList(self.output(function))), + ("params", VarList(self.params(function))), + ("stack", Expr(self.stack(function))), + ] + .into_iter() + } +} + +// NEG, NOT, SX, ZX, LOW_PART, BOOL_TO_INT, UNIMPL_MEM, FSQRT, FNEG, FABS, FLOAT_TO_INT, INT_TO_FLOAT, FLOAT_CONV, ROUND_TO_INT, FLOOR, CEIL, FTRUNC, LOAD +#[derive(Copy, Clone)] +pub struct UnaryOp { + src: usize, +} +#[derive(Clone, Debug, PartialEq)] +pub struct LiftedUnaryOp { + pub src: Box<MediumLevelILLiftedInstruction>, +} +impl UnaryOp { + pub fn new(src: usize) -> Self { + Self { src } + } + pub fn src(&self, function: &MediumLevelILFunction) -> MediumLevelILInstruction { + get_operation(function, self.src) + } + pub fn lift(&self, function: &MediumLevelILFunction) -> LiftedUnaryOp { + LiftedUnaryOp { + src: Box::new(self.src(function).lift()), + } + } + pub fn operands( + &self, + function: &MediumLevelILFunction, + ) -> impl Iterator<Item = (&'static str, MediumLevelILOperand)> { + [("src", MediumLevelILOperand::Expr(self.src(function)))].into_iter() + } +} + +// LOAD_STRUCT +#[derive(Copy, Clone)] +pub struct LoadStruct { + src: usize, + offset: u64, +} +#[derive(Clone, Debug, PartialEq)] +pub struct LiftedLoadStruct { + pub src: Box<MediumLevelILLiftedInstruction>, + pub offset: u64, +} +impl LoadStruct { + pub fn new(src: usize, offset: u64) -> Self { + Self { src, offset } + } + pub fn src(&self, function: &MediumLevelILFunction) -> MediumLevelILInstruction { + get_operation(function, self.src) + } + pub fn offset(&self) -> u64 { + self.offset + } + pub fn lift(&self, function: &MediumLevelILFunction) -> LiftedLoadStruct { + LiftedLoadStruct { + src: Box::new(self.src(function).lift()), + offset: self.offset(), + } + } + pub fn operands( + &self, + function: &MediumLevelILFunction, + ) -> impl Iterator<Item = (&'static str, MediumLevelILOperand)> { + [ + ("src", MediumLevelILOperand::Expr(self.src(function))), + ("offset", MediumLevelILOperand::Int(self.offset())), + ] + .into_iter() + } +} + +// LOAD_STRUCT_SSA +#[derive(Copy, Clone)] +pub struct LoadStructSsa { + src: usize, + offset: u64, + src_memory: u64, +} +#[derive(Clone, Debug, PartialEq)] +pub struct LiftedLoadStructSsa { + pub src: Box<MediumLevelILLiftedInstruction>, + pub offset: u64, + pub src_memory: u64, +} +impl LoadStructSsa { + pub fn new(src: usize, offset: u64, src_memory: u64) -> Self { + Self { + src, + offset, + src_memory, + } + } + pub fn src(&self, function: &MediumLevelILFunction) -> MediumLevelILInstruction { + get_operation(function, self.src) + } + pub fn offset(&self) -> u64 { + self.offset + } + pub fn src_memory(&self) -> u64 { + self.src_memory + } + pub fn lift(&self, function: &MediumLevelILFunction) -> LiftedLoadStructSsa { + LiftedLoadStructSsa { + src: Box::new(self.src(function).lift()), + offset: self.offset(), + src_memory: self.src_memory(), + } + } + pub fn operands( + &self, + function: &MediumLevelILFunction, + ) -> impl Iterator<Item = (&'static str, MediumLevelILOperand)> { + [ + ("src", MediumLevelILOperand::Expr(self.src(function))), + ("offset", MediumLevelILOperand::Int(self.offset())), + ("src_memory", MediumLevelILOperand::Int(self.src_memory())), + ] + .into_iter() + } +} + +// LOAD_SSA +#[derive(Copy, Clone)] +pub struct LoadSsa { + src: usize, + src_memory: u64, +} +#[derive(Clone, Debug, PartialEq)] +pub struct LiftedLoadSsa { + pub src: Box<MediumLevelILLiftedInstruction>, + pub src_memory: u64, +} +impl LoadSsa { + pub fn new(src: usize, src_memory: u64) -> Self { + Self { src, src_memory } + } + pub fn src(&self, function: &MediumLevelILFunction) -> MediumLevelILInstruction { + get_operation(function, self.src) + } + pub fn src_memory(&self) -> u64 { + self.src_memory + } + pub fn lift(&self, function: &MediumLevelILFunction) -> LiftedLoadSsa { + LiftedLoadSsa { + src: Box::new(self.src(function).lift()), + src_memory: self.src_memory(), + } + } + pub fn operands( + &self, + function: &MediumLevelILFunction, + ) -> impl Iterator<Item = (&'static str, MediumLevelILOperand)> { + [ + ("src", MediumLevelILOperand::Expr(self.src(function))), + ("src_memory", MediumLevelILOperand::Int(self.src_memory())), + ] + .into_iter() + } +} + +// RET +#[derive(Copy, Clone)] +pub struct Ret { + src: (usize, usize), +} +#[derive(Clone, Debug, PartialEq)] +pub struct LiftedRet { + pub src: Vec<MediumLevelILLiftedInstruction>, +} +impl Ret { + pub fn new(src: (usize, usize)) -> Self { + Self { src } + } + pub fn src(&self, function: &MediumLevelILFunction) -> OperandExprList { + OperandList::new(function, self.src.1, self.src.0).map_expr() + } + pub fn lift(&self, function: &MediumLevelILFunction) -> LiftedRet { + LiftedRet { + src: self.src(function).map(|instr| instr.lift()).collect(), + } + } + pub fn operands( + &self, + function: &MediumLevelILFunction, + ) -> impl Iterator<Item = (&'static str, MediumLevelILOperand)> { + [("src", MediumLevelILOperand::ExprList(self.src(function)))].into_iter() + } +} + +// VAR, ADDRESS_OF +#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)] +pub struct Var { + pub src: Variable, +} +impl Var { + pub fn new(src: u64) -> Self { + Self { src: get_var(src) } + } + pub fn src(&self) -> Variable { + self.src + } + pub fn operands( + &self, + ) -> impl Iterator<Item = (&'static str, MediumLevelILOperand)> { + [("src", MediumLevelILOperand::Var(self.src()))].into_iter() + } +} + +// VAR_FIELD, ADDRESS_OF_FIELD +#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)] +pub struct Field { + pub src: Variable, + pub offset: u64, +} +impl Field { + pub fn new(src: u64, offset: u64) -> Self { + Self { + src: get_var(src), + offset, + } + } + pub fn src(&self) -> Variable { + self.src + } + pub fn offset(&self) -> u64 { + self.offset + } + pub fn operands( + &self, + ) -> impl Iterator<Item = (&'static str, MediumLevelILOperand)> { + [ + ("src", MediumLevelILOperand::Var(self.src())), + ("offset", MediumLevelILOperand::Int(self.offset())), + ] + .into_iter() + } +} + +// VAR_SSA, VAR_ALIASED +#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)] +pub struct VarSsa { + pub src: SSAVariable, +} +impl VarSsa { + pub fn new(src: (u64, usize)) -> Self { + Self { + src: get_var_ssa(src.0, src.1), + } + } + pub fn src(&self) -> SSAVariable { + self.src + } + pub fn operands( + &self, + ) -> impl Iterator<Item = (&'static str, MediumLevelILOperand)> { + [("src", MediumLevelILOperand::VarSsa(self.src()))].into_iter() + } +} + +// VAR_SSA_FIELD, VAR_ALIASED_FIELD +#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)] +pub struct VarSsaField { + pub src: SSAVariable, + pub offset: u64, +} +impl VarSsaField { + pub fn new(src: (u64, usize), offset: u64) -> Self { + Self { + src: get_var_ssa(src.0, src.1), + offset, + } + } + pub fn src(&self) -> SSAVariable { + self.src + } + pub fn offset(&self) -> u64 { + self.offset + } + pub fn operands( + &self, + ) -> impl Iterator<Item = (&'static str, MediumLevelILOperand)> { + [ + ("src", MediumLevelILOperand::VarSsa(self.src())), + ("offset", MediumLevelILOperand::Int(self.offset())), + ] + .into_iter() + } +} + +// TRAP +#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)] +pub struct Trap { + pub vector: u64, +} +impl Trap { + pub fn new(vector: u64) -> Self { + Self { vector } + } + pub fn vector(&self) -> u64 { + self.vector + } + pub fn operands( + &self, + ) -> impl Iterator<Item = (&'static str, MediumLevelILOperand)> { + [("vector", MediumLevelILOperand::Int(self.vector()))].into_iter() + } +} |
