diff options
Diffstat (limited to 'rust/src/mlil')
| -rw-r--r-- | rust/src/mlil/block.rs | 63 | ||||
| -rw-r--r-- | rust/src/mlil/function.rs | 727 | ||||
| -rw-r--r-- | rust/src/mlil/instruction.rs | 1585 | ||||
| -rw-r--r-- | rust/src/mlil/lift.rs | 510 | ||||
| -rw-r--r-- | rust/src/mlil/mod.rs | 10 | ||||
| -rw-r--r-- | rust/src/mlil/operation.rs | 581 |
6 files changed, 0 insertions, 3476 deletions
diff --git a/rust/src/mlil/block.rs b/rust/src/mlil/block.rs deleted file mode 100644 index 015c7ba4..00000000 --- a/rust/src/mlil/block.rs +++ /dev/null @@ -1,63 +0,0 @@ -use std::ops::Range; - -use binaryninjacore_sys::BNGetMediumLevelILIndexForInstruction; - -use crate::basicblock::{BasicBlock, BlockContext}; -use crate::rc::Ref; - -use super::{MediumLevelILFunction, MediumLevelILInstruction}; - -pub struct MediumLevelILBlockIter { - function: Ref<MediumLevelILFunction>, - range: Range<u64>, -} - -impl Iterator for MediumLevelILBlockIter { - type Item = MediumLevelILInstruction; - - fn next(&mut self) -> Option<Self::Item> { - self.range - .next() - .map(|i| unsafe { - BNGetMediumLevelILIndexForInstruction(self.function.handle, i as usize) - }) - .map(|i| MediumLevelILInstruction::new(self.function.to_owned(), i)) - } -} - -pub struct MediumLevelILBlock { - pub(crate) function: Ref<MediumLevelILFunction>, -} - -impl core::fmt::Debug for MediumLevelILBlock { - fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result { - write!(f, "mlil_bb {:?}", self.function) - } -} - -impl BlockContext for MediumLevelILBlock { - type Iter = MediumLevelILBlockIter; - type Instruction = MediumLevelILInstruction; - - fn start(&self, block: &BasicBlock<Self>) -> MediumLevelILInstruction { - let expr_idx = unsafe { - BNGetMediumLevelILIndexForInstruction(self.function.handle, block.raw_start() as usize) - }; - MediumLevelILInstruction::new(self.function.to_owned(), expr_idx) - } - - fn iter(&self, block: &BasicBlock<Self>) -> MediumLevelILBlockIter { - MediumLevelILBlockIter { - function: self.function.to_owned(), - range: block.raw_start()..block.raw_end(), - } - } -} - -impl Clone for MediumLevelILBlock { - fn clone(&self) -> Self { - MediumLevelILBlock { - function: self.function.to_owned(), - } - } -} diff --git a/rust/src/mlil/function.rs b/rust/src/mlil/function.rs deleted file mode 100644 index 928f1b6a..00000000 --- a/rust/src/mlil/function.rs +++ /dev/null @@ -1,727 +0,0 @@ -use core::hash::{Hash, Hasher}; -use std::ffi::c_char; - -use binaryninjacore_sys::*; - -use crate::architecture::CoreArchitecture; -use crate::basicblock::BasicBlock; -use crate::disassembly::DisassemblySettings; -use crate::flowgraph::FlowGraph; -use crate::function::{Function, Location}; -use crate::rc::{Array, CoreArrayProvider, CoreArrayProviderInner, Ref, RefCountable}; -use crate::string::BnStrCompatible; -use crate::types::{ - Conf, PossibleValueSet, RegisterValue, SSAVariable, Type, UserVariableValues, Variable, -}; - -use super::{MediumLevelILBlock, MediumLevelILInstruction, MediumLevelILLiftedInstruction}; - -pub struct MediumLevelILFunction { - pub(crate) handle: *mut BNMediumLevelILFunction, -} - -unsafe impl Send for MediumLevelILFunction {} -unsafe impl Sync for MediumLevelILFunction {} - -impl Eq for MediumLevelILFunction {} -impl PartialEq for MediumLevelILFunction { - fn eq(&self, rhs: &Self) -> bool { - self.get_function().eq(&rhs.get_function()) - } -} - -impl Hash for MediumLevelILFunction { - fn hash<H: Hasher>(&self, state: &mut H) { - self.get_function().hash(state) - } -} - -impl MediumLevelILFunction { - pub(crate) unsafe fn ref_from_raw(handle: *mut BNMediumLevelILFunction) -> Ref<Self> { - debug_assert!(!handle.is_null()); - - Self { handle }.to_owned() - } - - pub fn instruction_at<L: Into<Location>>(&self, loc: L) -> Option<MediumLevelILInstruction> { - let loc: Location = loc.into(); - let arch_handle = loc.arch.unwrap(); - - let expr_idx = - unsafe { BNMediumLevelILGetInstructionStart(self.handle, arch_handle.0, loc.addr) }; - - if expr_idx >= self.instruction_count() { - None - } else { - Some(MediumLevelILInstruction::new(self.to_owned(), expr_idx)) - } - } - - pub fn instruction_from_idx(&self, expr_idx: usize) -> MediumLevelILInstruction { - MediumLevelILInstruction::new(self.to_owned(), expr_idx) - } - - pub fn lifted_instruction_from_idx(&self, expr_idx: usize) -> MediumLevelILLiftedInstruction { - self.instruction_from_idx(expr_idx).lift() - } - - pub fn instruction_from_instruction_idx(&self, instr_idx: usize) -> MediumLevelILInstruction { - MediumLevelILInstruction::new(self.to_owned(), unsafe { - BNGetMediumLevelILIndexForInstruction(self.handle, instr_idx) - }) - } - - pub fn lifted_instruction_from_instruction_idx( - &self, - instr_idx: usize, - ) -> MediumLevelILLiftedInstruction { - self.instruction_from_instruction_idx(instr_idx).lift() - } - - pub fn instruction_count(&self) -> usize { - unsafe { BNGetMediumLevelILInstructionCount(self.handle) } - } - - pub fn ssa_form(&self) -> MediumLevelILFunction { - let ssa = unsafe { BNGetMediumLevelILSSAForm(self.handle) }; - assert!(!ssa.is_null()); - MediumLevelILFunction { handle: ssa } - } - - pub fn get_function(&self) -> Ref<Function> { - unsafe { - let func = BNGetMediumLevelILOwnerFunction(self.handle); - Function::from_raw(func) - } - } - - pub fn basic_blocks(&self) -> Array<BasicBlock<MediumLevelILBlock>> { - let mut count = 0; - let blocks = unsafe { BNGetMediumLevelILBasicBlockList(self.handle, &mut count) }; - let context = MediumLevelILBlock { - function: self.to_owned(), - }; - - unsafe { Array::new(blocks, count, context) } - } - - pub fn get_var_definitions<'a>(&'a self, var: &Variable) -> MediumLevelILInstructionList<'a> { - let mut count = 0; - let raw_instrs = - unsafe { BNGetMediumLevelILVariableDefinitions(self.handle, &var.raw(), &mut count) }; - assert!(!raw_instrs.is_null()); - let instrs = unsafe { core::slice::from_raw_parts(raw_instrs, count) }; - MediumLevelILInstructionList { - mlil: self, - ptr: raw_instrs, - instr_idxs: instrs.iter(), - } - } - - pub fn create_user_stack_var<'a, S: BnStrCompatible, C: Into<Conf<&'a Type>>>( - self, - offset: i64, - var_type: C, - name: S, - ) { - let var_type = var_type.into(); - let mut raw_var_type: BNTypeWithConfidence = var_type.into(); - let name = name.into_bytes_with_nul(); - unsafe { - BNCreateUserStackVariable( - self.get_function().handle, - offset, - &mut raw_var_type, - name.as_ref().as_ptr() as *const c_char, - ) - } - } - - pub fn delete_user_stack_var(self, offset: i64) { - unsafe { BNDeleteUserStackVariable(self.get_function().handle, offset) } - } - - pub fn create_user_var<'a, S: BnStrCompatible, C: Into<Conf<&'a Type>>>( - &self, - var: &Variable, - var_type: C, - name: S, - ignore_disjoint_uses: bool, - ) { - let var_type = var_type.into(); - let raw_var_type: BNTypeWithConfidence = var_type.into(); - let name = name.into_bytes_with_nul(); - unsafe { - BNCreateUserVariable( - self.get_function().handle, - &var.raw(), - &raw_var_type as *const _ as *mut _, - name.as_ref().as_ptr() as *const _, - ignore_disjoint_uses, - ) - } - } - - pub fn delete_user_var(&self, var: &Variable) { - unsafe { BNDeleteUserVariable(self.get_function().handle, &var.raw()) } - } - - pub fn is_var_user_defined(&self, var: &Variable) -> bool { - unsafe { BNIsVariableUserDefined(self.get_function().handle, &var.raw()) } - } - - /// Allows the user to specify a PossibleValueSet value for an MLIL - /// variable at its definition site. - /// - /// .. warning:: Setting the variable value, triggers a reanalysis of the - /// function and allows the dataflow to compute and propagate values which - /// depend on the current variable. This implies that branch conditions - /// whose values can be determined statically will be computed, leading to - /// potential branch elimination at the HLIL layer. - /// - /// * `var` - Variable for which the value is to be set - /// * `addr` - Address of the definition site of the variable - /// * `value` - Informed value of the variable - /// - /// # Example - /// ```no_run - /// # use binaryninja::mlil::MediumLevelILFunction; - /// # use binaryninja::types::PossibleValueSet; - /// # let mlil_fun: MediumLevelILFunction = todo!(); - /// let (mlil_var, arch_addr, _val) = mlil_fun.user_var_values().all().next().unwrap(); - /// let def_address = arch_addr.address; - /// let var_value = PossibleValueSet::ConstantValue{value: 5}; - /// mlil_fun.set_user_var_value(&mlil_var, def_address, var_value).unwrap(); - /// ``` - pub fn set_user_var_value( - &self, - var: &Variable, - addr: u64, - value: PossibleValueSet, - ) -> Result<(), ()> { - let Some(_def_site) = self - .get_var_definitions(var) - .find(|def| def.address == addr) - else { - // Error "No definition for Variable found at given address" - return Err(()); - }; - let function = self.get_function(); - let def_site = BNArchitectureAndAddress { - arch: function.arch().0, - address: addr, - }; - let value = value.into_raw(); - - unsafe { BNSetUserVariableValue(function.handle, &var.raw(), &def_site, value.as_ffi()) } - Ok(()) - } - - /// Clears a previously defined user variable value. - /// - /// * `var` - Variable for which the value was informed - /// * `def_addr` - Address of the definition site of the variable - pub fn clear_user_var_value(&self, var: &Variable, addr: u64) -> Result<(), ()> { - let Some(_var_def) = self - .get_var_definitions(var) - .find(|site| site.address == addr) - else { - //error "Could not get definition for Variable" - return Err(()); - }; - - let function = self.get_function(); - let def_site = BNArchitectureAndAddress { - arch: function.arch().0, - address: addr, - }; - - unsafe { BNClearUserVariableValue(function.handle, &var.raw(), &def_site) }; - Ok(()) - } - - /// Returns a map of current defined user variable values. - /// Returns a Map of user current defined user variable values and their definition sites. - pub fn user_var_values(&self) -> UserVariableValues { - let mut count = 0; - let function = self.get_function(); - let var_values = unsafe { BNGetAllUserVariableValues(function.handle, &mut count) }; - assert!(!var_values.is_null()); - UserVariableValues { - vars: core::ptr::slice_from_raw_parts(var_values, count), - } - } - - /// Clear all user defined variable values. - pub fn clear_user_var_values(&self) -> Result<(), ()> { - for (var, arch_and_addr, _value) in self.user_var_values().all() { - self.clear_user_var_value(&var, arch_and_addr.address)?; - } - Ok(()) - } - - pub fn create_auto_stack_var<'a, T: Into<Conf<&'a Type>>, S: BnStrCompatible>( - &self, - offset: i64, - var_type: T, - name: S, - ) { - let var_type: Conf<&Type> = var_type.into(); - let mut var_type = var_type.into(); - let name = name.into_bytes_with_nul(); - let name_c_str = name.as_ref(); - unsafe { - BNCreateAutoStackVariable( - self.get_function().handle, - offset, - &mut var_type, - name_c_str.as_ptr() as *const c_char, - ) - } - } - - pub fn delete_auto_stack_var(&self, offset: i64) { - unsafe { BNDeleteAutoStackVariable(self.get_function().handle, offset) } - } - - pub fn create_auto_var<'a, S: BnStrCompatible, C: Into<Conf<&'a Type>>>( - &self, - var: &Variable, - var_type: C, - name: S, - ignore_disjoint_uses: bool, - ) { - let var_type: Conf<&Type> = var_type.into(); - let mut var_type = var_type.into(); - let name = name.into_bytes_with_nul(); - let name_c_str = name.as_ref(); - unsafe { - BNCreateAutoVariable( - self.get_function().handle, - &var.raw(), - &mut var_type, - name_c_str.as_ptr() as *const c_char, - ignore_disjoint_uses, - ) - } - } - - /// Returns a list of ILReferenceSource objects (IL xrefs or cross-references) - /// that reference the given variable. The variable is a local variable that can be either on the stack, - /// in a register, or in a flag. - /// This function is related to get_hlil_var_refs(), which returns variable references collected - /// from HLIL. The two can be different in several cases, e.g., multiple variables in MLIL can be merged - /// into a single variable in HLIL. - /// - /// * `var` - Variable for which to query the xref - /// - /// # Example - /// ```no_run - /// # use binaryninja::mlil::MediumLevelILFunction; - /// # use binaryninja::types::Variable; - /// # let mlil_fun: MediumLevelILFunction = todo!(); - /// # let mlil_var: Variable = todo!(); - /// let instr = mlil_fun.var_refs(&mlil_var).get(0).expr(); - /// ``` - pub fn var_refs(&self, var: &Variable) -> Array<ILReferenceSource> { - let mut count = 0; - let refs = unsafe { - BNGetMediumLevelILVariableReferences( - self.get_function().handle, - &mut var.raw(), - &mut count, - ) - }; - assert!(!refs.is_null()); - unsafe { Array::new(refs, count, self.to_owned()) } - } - - /// Returns a list of variables referenced by code in the function ``func``, - /// of the architecture ``arch``, and at the address ``addr``. If no function is specified, references from - /// all functions and containing the address will be returned. If no architecture is specified, the - /// architecture of the function will be used. - /// This function is related to get_hlil_var_refs_from(), which returns variable references collected - /// from HLIL. The two can be different in several cases, e.g., multiple variables in MLIL can be merged - /// into a single variable in HLIL. - /// - /// * `addr` - virtual address to query for variable references - /// * `length` - optional length of query - /// * `arch` - optional architecture of query - pub fn var_refs_from( - &self, - addr: u64, - length: Option<u64>, - arch: Option<CoreArchitecture>, - ) -> Array<VariableReferenceSource> { - let function = self.get_function(); - let arch = arch.unwrap_or_else(|| function.arch()); - let mut count = 0; - - let refs = if let Some(length) = length { - unsafe { - BNGetMediumLevelILVariableReferencesInRange( - function.handle, - arch.0, - addr, - length, - &mut count, - ) - } - } else { - unsafe { - BNGetMediumLevelILVariableReferencesFrom(function.handle, arch.0, addr, &mut count) - } - }; - assert!(!refs.is_null()); - unsafe { Array::new(refs, count, self.to_owned()) } - } - - /// Current IL Address - pub fn current_address(&self) -> u64 { - unsafe { BNMediumLevelILGetCurrentAddress(self.handle) } - } - - /// Set the current IL Address - pub fn set_current_address(&self, value: u64, arch: Option<CoreArchitecture>) { - let arch = arch - .map(|x| x.0) - .unwrap_or_else(|| self.get_function().arch().0); - unsafe { BNMediumLevelILSetCurrentAddress(self.handle, arch, value) } - } - - /// Returns the BasicBlock at the given MLIL `instruction`. - pub fn basic_block_containing( - &self, - instruction: &MediumLevelILInstruction, - ) -> Option<BasicBlock<MediumLevelILBlock>> { - let index = instruction.index; - let block = unsafe { BNGetMediumLevelILBasicBlockForInstruction(self.handle, index) }; - (!block.is_null()).then(|| unsafe { - BasicBlock::from_raw( - block, - MediumLevelILBlock { - function: self.to_owned(), - }, - ) - }) - } - /// ends the function and computes the list of basic blocks. - pub fn finalize(&self) { - unsafe { BNFinalizeMediumLevelILFunction(self.handle) } - } - - /// Generate SSA form given the current MLIL - /// - /// * `analyze_conditionals` - whether or not to analyze conditionals - /// * `handle_aliases` - whether or not to handle aliases - /// * `known_not_aliases` - optional list of variables known to be not aliased - /// * `known_aliases` - optional list of variables known to be aliased - pub fn generate_ssa_form( - &self, - analyze_conditionals: bool, - handle_aliases: bool, - known_not_aliases: impl IntoIterator<Item = Variable>, - known_aliases: impl IntoIterator<Item = Variable>, - ) { - let mut known_not_aliases: Box<[_]> = - known_not_aliases.into_iter().map(|x| x.raw()).collect(); - let mut known_aliases: Box<[_]> = known_aliases.into_iter().map(|x| x.raw()).collect(); - let (known_not_aliases_ptr, known_not_aliases_len) = if known_not_aliases.is_empty() { - (core::ptr::null_mut(), 0) - } else { - (known_not_aliases.as_mut_ptr(), known_not_aliases.len()) - }; - let (known_aliases_ptr, known_aliases_len) = if known_not_aliases.is_empty() { - (core::ptr::null_mut(), 0) - } else { - (known_aliases.as_mut_ptr(), known_aliases.len()) - }; - unsafe { - BNGenerateMediumLevelILSSAForm( - self.handle, - analyze_conditionals, - handle_aliases, - known_not_aliases_ptr, - known_not_aliases_len, - known_aliases_ptr, - known_aliases_len, - ) - } - } - - /// Gets the instruction that contains the given SSA variable's definition. - /// - /// Since SSA variables can only be defined once, this will return the single instruction where that occurs. - /// For SSA variable version 0s, which don't have definitions, this will return None instead. - pub fn ssa_variable_definition(&self, var: SSAVariable) -> Option<MediumLevelILInstruction> { - let result = unsafe { - BNGetMediumLevelILSSAVarDefinition(self.handle, &var.variable.raw(), var.version) - }; - (result < self.instruction_count()) - .then(|| MediumLevelILInstruction::new(self.to_owned(), result)) - } - - pub fn ssa_memory_definition(&self, version: usize) -> Option<MediumLevelILInstruction> { - let result = unsafe { BNGetMediumLevelILSSAMemoryDefinition(self.handle, version) }; - (result < self.instruction_count()) - .then(|| MediumLevelILInstruction::new(self.to_owned(), result)) - } - - ///Gets all the instructions that use the given SSA variable. - pub fn ssa_variable_uses(&self, ssa_var: SSAVariable) -> Array<MediumLevelILInstruction> { - let mut count = 0; - let uses = unsafe { - BNGetMediumLevelILSSAVarUses( - self.handle, - &ssa_var.variable.raw(), - ssa_var.version, - &mut count, - ) - }; - assert!(!uses.is_null()); - unsafe { Array::new(uses, count, self.to_owned()) } - } - - pub fn ssa_memory_uses(&self, version: usize) -> Array<MediumLevelILInstruction> { - let mut count = 0; - let uses = unsafe { BNGetMediumLevelILSSAMemoryUses(self.handle, version, &mut count) }; - assert!(!uses.is_null()); - unsafe { Array::new(uses, count, self.to_owned()) } - } - - /// determines if `ssa_var` is live at any point in the function - pub fn is_ssa_variable_live(&self, ssa_var: SSAVariable) -> bool { - unsafe { - BNIsMediumLevelILSSAVarLive(self.handle, &ssa_var.variable.raw(), ssa_var.version) - } - } - - pub fn variable_definitions(&self, variable: Variable) -> Array<MediumLevelILInstruction> { - let mut count = 0; - let defs = unsafe { - BNGetMediumLevelILVariableDefinitions(self.handle, &variable.raw(), &mut count) - }; - unsafe { Array::new(defs, count, self.to_owned()) } - } - - pub fn variable_uses(&self, variable: Variable) -> Array<MediumLevelILInstruction> { - let mut count = 0; - let uses = - unsafe { BNGetMediumLevelILVariableUses(self.handle, &variable.raw(), &mut count) }; - unsafe { Array::new(uses, count, self.to_owned()) } - } - - /// Computes the list of instructions for which `var` is live. - /// If `include_last_use` is false, the last use of the variable will not be included in the - /// list (this allows for easier computation of overlaps in liveness between two variables). - /// If the variable is never used, this function will return an empty list. - /// - /// `var` - the variable to query - /// `include_last_use` - whether to include the last use of the variable in the list of instructions - pub fn live_instruction_for_variable( - &self, - variable: Variable, - include_last_user: bool, - ) -> Array<MediumLevelILInstruction> { - let mut count = 0; - let uses = unsafe { - BNGetMediumLevelILLiveInstructionsForVariable( - self.handle, - &variable.raw(), - include_last_user, - &mut count, - ) - }; - unsafe { Array::new(uses, count, self.to_owned()) } - } - - pub fn ssa_variable_value(&self, ssa_var: SSAVariable) -> RegisterValue { - unsafe { - BNGetMediumLevelILSSAVarValue(self.handle, &ssa_var.variable.raw(), ssa_var.version) - } - .into() - } - - pub fn create_graph(&self, settings: Option<DisassemblySettings>) -> FlowGraph { - let settings = settings.map(|x| x.handle).unwrap_or(core::ptr::null_mut()); - let graph = unsafe { BNCreateMediumLevelILFunctionGraph(self.handle, settings) }; - unsafe { FlowGraph::from_raw(graph) } - } - - /// This gets just the MLIL variables - you may be interested in the union - /// of [MediumLevelILFunction::aliased_variables] and - /// [crate::function::Function::parameter_variables] for all the - /// variables used in the function - pub fn variables(&self) -> Array<Variable> { - let mut count = 0; - let uses = unsafe { BNGetMediumLevelILVariables(self.handle, &mut count) }; - unsafe { Array::new(uses, count, ()) } - } - - /// This returns a list of Variables that are taken reference to and used - /// elsewhere. You may also wish to consider [MediumLevelILFunction::variables] - /// and [crate::function::Function::parameter_variables] - pub fn aliased_variables(&self) -> Array<Variable> { - let mut count = 0; - let uses = unsafe { BNGetMediumLevelILAliasedVariables(self.handle, &mut count) }; - unsafe { Array::new(uses, count, ()) } - } - - /// This gets just the MLIL SSA variables - you may be interested in the - /// union of [MediumLevelILFunction::aliased_variables] and - /// [crate::function::Function::parameter_variables] for all the - /// variables used in the function. - pub fn ssa_variables(&self) -> Array<Array<SSAVariable>> { - let mut count = 0; - let vars = unsafe { BNGetMediumLevelILVariables(self.handle, &mut count) }; - unsafe { Array::new(vars, count, self.to_owned()) } - } -} - -impl ToOwned for MediumLevelILFunction { - type Owned = Ref<Self>; - - fn to_owned(&self) -> Self::Owned { - unsafe { RefCountable::inc_ref(self) } - } -} - -unsafe impl RefCountable for MediumLevelILFunction { - unsafe fn inc_ref(handle: &Self) -> Ref<Self> { - Ref::new(Self { - handle: BNNewMediumLevelILFunctionReference(handle.handle), - }) - } - - unsafe fn dec_ref(handle: &Self) { - BNFreeMediumLevelILFunction(handle.handle); - } -} - -impl core::fmt::Debug for MediumLevelILFunction { - fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result { - write!(f, "<mlil func handle {:p}>", self.handle) - } -} - -#[derive(Clone, Debug)] -pub struct MediumLevelILInstructionList<'a> { - mlil: &'a MediumLevelILFunction, - ptr: *mut usize, - instr_idxs: core::slice::Iter<'a, usize>, -} - -impl Drop for MediumLevelILInstructionList<'_> { - fn drop(&mut self) { - unsafe { BNFreeILInstructionList(self.ptr) }; - } -} - -impl Iterator for MediumLevelILInstructionList<'_> { - type Item = MediumLevelILInstruction; - - fn next(&mut self) -> Option<Self::Item> { - self.instr_idxs - .next() - .map(|i| self.mlil.instruction_from_instruction_idx(*i)) - } -} - -impl DoubleEndedIterator for MediumLevelILInstructionList<'_> { - fn next_back(&mut self) -> Option<Self::Item> { - self.instr_idxs - .next_back() - .map(|i| self.mlil.instruction_from_instruction_idx(*i)) - } -} - -impl ExactSizeIterator for MediumLevelILInstructionList<'_> {} -impl core::iter::FusedIterator for MediumLevelILInstructionList<'_> {} - -///////////////////////// -// FunctionGraphType - -pub type FunctionGraphType = binaryninjacore_sys::BNFunctionGraphType; - -///////////////////////// -// ILReferenceSource - -pub struct ILReferenceSource { - mlil: Ref<MediumLevelILFunction>, - _func: Ref<Function>, - _arch: CoreArchitecture, - addr: u64, - type_: FunctionGraphType, - expr_id: usize, -} - -impl ILReferenceSource { - unsafe fn from_raw(value: BNILReferenceSource, mlil: Ref<MediumLevelILFunction>) -> Self { - Self { - mlil, - _func: Function::from_raw(value.func), - _arch: CoreArchitecture::from_raw(value.arch), - addr: value.addr, - type_: value.type_, - expr_id: value.exprId, - } - } - pub fn addr(&self) -> u64 { - self.addr - } - pub fn graph_type(&self) -> FunctionGraphType { - self.type_ - } - pub fn expr(&self) -> MediumLevelILInstruction { - self.mlil.instruction_from_idx(self.expr_id) - } -} - -impl CoreArrayProvider for ILReferenceSource { - type Raw = BNILReferenceSource; - type Context = Ref<MediumLevelILFunction>; - type Wrapped<'a> = Self; -} -unsafe impl CoreArrayProviderInner for ILReferenceSource { - unsafe fn free(raw: *mut Self::Raw, count: usize, _context: &Self::Context) { - BNFreeILReferences(raw, count) - } - unsafe fn wrap_raw<'a>(raw: &'a Self::Raw, context: &'a Self::Context) -> Self::Wrapped<'a> { - Self::from_raw(*raw, context.to_owned()) - } -} - -///////////////////////// -// VariableReferenceSource - -pub struct VariableReferenceSource { - var: Variable, - source: ILReferenceSource, -} - -impl VariableReferenceSource { - pub fn variable(&self) -> &Variable { - &self.var - } - pub fn source(&self) -> &ILReferenceSource { - &self.source - } -} - -impl CoreArrayProvider for VariableReferenceSource { - type Raw = BNVariableReferenceSource; - type Context = Ref<MediumLevelILFunction>; - type Wrapped<'a> = Self; -} - -unsafe impl CoreArrayProviderInner for VariableReferenceSource { - unsafe fn free(raw: *mut Self::Raw, count: usize, _context: &Self::Context) { - BNFreeVariableReferenceSourceList(raw, count) - } - unsafe fn wrap_raw<'a>(raw: &'a Self::Raw, context: &'a Self::Context) -> Self::Wrapped<'a> { - Self { - var: Variable::from_raw(raw.var), - source: ILReferenceSource::from_raw(raw.source, context.to_owned()), - } - } -} diff --git a/rust/src/mlil/instruction.rs b/rust/src/mlil/instruction.rs deleted file mode 100644 index 88564cc6..00000000 --- a/rust/src/mlil/instruction.rs +++ /dev/null @@ -1,1585 +0,0 @@ -use binaryninjacore_sys::*; - -use crate::architecture::CoreIntrinsic; -use crate::disassembly::InstructionTextToken; -use crate::operand_iter::OperandIter; -use crate::rc::{Array, CoreArrayProvider, CoreArrayProviderInner, Ref}; -use crate::types::{ - Conf, ConstantData, DataFlowQueryOption, ILBranchDependence, PossibleValueSet, - RegisterValue, RegisterValueType, SSAVariable, Type, Variable, -}; - -use super::lift::*; -use super::operation::*; -use super::MediumLevelILFunction; - -#[derive(Clone)] -pub struct MediumLevelILInstruction { - pub function: Ref<MediumLevelILFunction>, - pub address: u64, - pub index: usize, - pub size: usize, - pub kind: MediumLevelILInstructionKind, -} - -#[derive(Copy, Clone)] -pub enum MediumLevelILInstructionKind { - Nop, - Noret, - Bp, - Undef, - Unimpl, - If(MediumLevelILOperationIf), - FloatConst(FloatConst), - Const(Constant), - ConstPtr(Constant), - Import(Constant), - ExternPtr(ExternPtr), - ConstData(ConstData), - Jump(Jump), - RetHint(Jump), - StoreSsa(StoreSsa), - StoreStructSsa(StoreStructSsa), - StoreStruct(StoreStruct), - Store(Store), - JumpTo(JumpTo), - Goto(Goto), - FreeVarSlot(FreeVarSlot), - SetVarField(SetVarField), - SetVar(SetVar), - FreeVarSlotSsa(FreeVarSlotSsa), - SetVarSsaField(SetVarSsaField), - SetVarAliasedField(SetVarSsaField), - SetVarAliased(SetVarAliased), - SetVarSsa(SetVarSsa), - VarPhi(VarPhi), - MemPhi(MemPhi), - VarSplit(VarSplit), - SetVarSplit(SetVarSplit), - VarSplitSsa(VarSplitSsa), - SetVarSplitSsa(SetVarSplitSsa), - Add(BinaryOp), - Sub(BinaryOp), - And(BinaryOp), - Or(BinaryOp), - Xor(BinaryOp), - Lsl(BinaryOp), - Lsr(BinaryOp), - Asr(BinaryOp), - Rol(BinaryOp), - Ror(BinaryOp), - Mul(BinaryOp), - MuluDp(BinaryOp), - MulsDp(BinaryOp), - Divu(BinaryOp), - DivuDp(BinaryOp), - Divs(BinaryOp), - DivsDp(BinaryOp), - Modu(BinaryOp), - ModuDp(BinaryOp), - Mods(BinaryOp), - ModsDp(BinaryOp), - CmpE(BinaryOp), - CmpNe(BinaryOp), - CmpSlt(BinaryOp), - CmpUlt(BinaryOp), - CmpSle(BinaryOp), - CmpUle(BinaryOp), - CmpSge(BinaryOp), - CmpUge(BinaryOp), - CmpSgt(BinaryOp), - CmpUgt(BinaryOp), - TestBit(BinaryOp), - AddOverflow(BinaryOp), - FcmpE(BinaryOp), - FcmpNe(BinaryOp), - FcmpLt(BinaryOp), - FcmpLe(BinaryOp), - FcmpGe(BinaryOp), - FcmpGt(BinaryOp), - FcmpO(BinaryOp), - FcmpUo(BinaryOp), - Fadd(BinaryOp), - Fsub(BinaryOp), - Fmul(BinaryOp), - Fdiv(BinaryOp), - Adc(BinaryOpCarry), - Sbb(BinaryOpCarry), - Rlc(BinaryOpCarry), - Rrc(BinaryOpCarry), - Call(Call), - Tailcall(Call), - Syscall(Syscall), - Intrinsic(Intrinsic), - IntrinsicSsa(IntrinsicSsa), - CallSsa(CallSsa), - TailcallSsa(CallSsa), - CallUntypedSsa(CallUntypedSsa), - TailcallUntypedSsa(CallUntypedSsa), - SyscallSsa(SyscallSsa), - SyscallUntypedSsa(SyscallUntypedSsa), - CallUntyped(CallUntyped), - TailcallUntyped(CallUntyped), - SyscallUntyped(SyscallUntyped), - SeparateParamList(SeparateParamList), - SharedParamSlot(SharedParamSlot), - Neg(UnaryOp), - Not(UnaryOp), - Sx(UnaryOp), - Zx(UnaryOp), - LowPart(UnaryOp), - BoolToInt(UnaryOp), - UnimplMem(UnaryOp), - Fsqrt(UnaryOp), - Fneg(UnaryOp), - Fabs(UnaryOp), - FloatToInt(UnaryOp), - IntToFloat(UnaryOp), - FloatConv(UnaryOp), - RoundToInt(UnaryOp), - Floor(UnaryOp), - Ceil(UnaryOp), - Ftrunc(UnaryOp), - Load(UnaryOp), - LoadStruct(LoadStruct), - LoadStructSsa(LoadStructSsa), - LoadSsa(LoadSsa), - Ret(Ret), - Var(Var), - AddressOf(Var), - VarField(Field), - AddressOfField(Field), - VarSsa(VarSsa), - VarAliased(VarSsa), - VarSsaField(VarSsaField), - VarAliasedField(VarSsaField), - Trap(Trap), -} - -impl core::fmt::Debug for MediumLevelILInstruction { - fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result { - write!( - f, - "<{} at 0x{:08}>", - core::any::type_name::<Self>(), - self.address, - ) - } -} - -impl MediumLevelILInstruction { - pub(crate) fn new(function: Ref<MediumLevelILFunction>, index: usize) -> Self { - let op = unsafe { BNGetMediumLevelILByIndex(function.handle, index) }; - use BNMediumLevelILOperation::*; - use MediumLevelILInstructionKind as Op; - let kind = match op.operation { - MLIL_NOP => Op::Nop, - MLIL_NORET => Op::Noret, - MLIL_BP => Op::Bp, - MLIL_UNDEF => Op::Undef, - MLIL_UNIMPL => Op::Unimpl, - MLIL_IF => Op::If(MediumLevelILOperationIf { - condition: op.operands[0] as usize, - dest_true: op.operands[1], - dest_false: op.operands[2], - }), - MLIL_FLOAT_CONST => Op::FloatConst(FloatConst { - constant: get_float(op.operands[0], op.size), - }), - MLIL_CONST => Op::Const(Constant { - constant: op.operands[0], - }), - MLIL_CONST_PTR => Op::ConstPtr(Constant { - constant: op.operands[0], - }), - MLIL_IMPORT => Op::Import(Constant { - constant: op.operands[0], - }), - MLIL_EXTERN_PTR => Op::ExternPtr(ExternPtr { - constant: op.operands[0], - offset: op.operands[1], - }), - MLIL_CONST_DATA => Op::ConstData(ConstData { - constant_data_kind: op.operands[0] as u32, - constant_data_value: op.operands[1] as i64, - size: op.size, - }), - MLIL_JUMP => Op::Jump(Jump { - dest: op.operands[0] as usize, - }), - MLIL_RET_HINT => Op::RetHint(Jump { - dest: op.operands[0] as usize, - }), - MLIL_STORE_SSA => Op::StoreSsa(StoreSsa { - dest: op.operands[0] as usize, - dest_memory: op.operands[1], - src_memory: op.operands[2], - src: op.operands[3] as usize, - }), - MLIL_STORE_STRUCT_SSA => Op::StoreStructSsa(StoreStructSsa { - dest: op.operands[0] as usize, - offset: op.operands[1], - dest_memory: op.operands[2], - src_memory: op.operands[3], - src: op.operands[4] as usize, - }), - MLIL_STORE_STRUCT => Op::StoreStruct(StoreStruct { - dest: op.operands[0] as usize, - offset: op.operands[1], - src: op.operands[2] as usize, - }), - MLIL_STORE => Op::Store(Store { - dest: op.operands[0] as usize, - src: op.operands[1] as usize, - }), - MLIL_JUMP_TO => Op::JumpTo(JumpTo { - dest: op.operands[0] as usize, - num_operands: op.operands[1] as usize, - first_operand: op.operands[2] as usize, - }), - MLIL_GOTO => Op::Goto(Goto { - dest: op.operands[0], - }), - MLIL_FREE_VAR_SLOT => Op::FreeVarSlot(FreeVarSlot { - dest: get_var(op.operands[0]), - }), - MLIL_SET_VAR_FIELD => Op::SetVarField(SetVarField { - dest: get_var(op.operands[0]), - offset: op.operands[1], - src: op.operands[2] as usize, - }), - MLIL_SET_VAR => Op::SetVar(SetVar { - dest: get_var(op.operands[0]), - src: op.operands[1] as usize, - }), - MLIL_FREE_VAR_SLOT_SSA => Op::FreeVarSlotSsa(FreeVarSlotSsa { - dest: get_var_ssa(op.operands[0], op.operands[1] as usize), - prev: get_var_ssa(op.operands[0], op.operands[2] as usize), - }), - MLIL_SET_VAR_SSA_FIELD => Op::SetVarSsaField(SetVarSsaField { - dest: get_var_ssa(op.operands[0], op.operands[1] as usize), - prev: get_var_ssa(op.operands[0], op.operands[2] as usize), - offset: op.operands[3], - src: op.operands[4] as usize, - }), - MLIL_SET_VAR_ALIASED_FIELD => Op::SetVarAliasedField(SetVarSsaField { - dest: get_var_ssa(op.operands[0], op.operands[1] as usize), - prev: get_var_ssa(op.operands[0], op.operands[2] as usize), - offset: op.operands[3], - src: op.operands[4] as usize, - }), - MLIL_SET_VAR_ALIASED => Op::SetVarAliased(SetVarAliased { - dest: get_var_ssa(op.operands[0], op.operands[1] as usize), - prev: get_var_ssa(op.operands[0], op.operands[2] as usize), - src: op.operands[3] as usize, - }), - MLIL_SET_VAR_SSA => Op::SetVarSsa(SetVarSsa { - dest: get_var_ssa(op.operands[0], op.operands[1] as usize), - src: op.operands[2] as usize, - }), - MLIL_VAR_PHI => Op::VarPhi(VarPhi { - dest: get_var_ssa(op.operands[0], op.operands[1] as usize), - num_operands: op.operands[2] as usize, - first_operand: op.operands[3] as usize, - }), - MLIL_MEM_PHI => Op::MemPhi(MemPhi { - dest_memory: op.operands[0], - num_operands: op.operands[1] as usize, - first_operand: op.operands[2] as usize, - }), - MLIL_VAR_SPLIT => Op::VarSplit(VarSplit { - high: get_var(op.operands[0]), - low: get_var(op.operands[1]), - }), - MLIL_SET_VAR_SPLIT => Op::SetVarSplit(SetVarSplit { - high: get_var(op.operands[0]), - low: get_var(op.operands[1]), - src: op.operands[2] as usize, - }), - MLIL_VAR_SPLIT_SSA => Op::VarSplitSsa(VarSplitSsa { - high: get_var_ssa(op.operands[0], op.operands[1] as usize), - low: get_var_ssa(op.operands[2], op.operands[3] as usize), - }), - MLIL_SET_VAR_SPLIT_SSA => Op::SetVarSplitSsa(SetVarSplitSsa { - high: get_var_ssa(op.operands[0], op.operands[1] as usize), - low: get_var_ssa(op.operands[2], op.operands[3] as usize), - src: op.operands[4] as usize, - }), - MLIL_ADD => Op::Add(BinaryOp { - left: op.operands[0] as usize, - right: op.operands[1] as usize, - }), - MLIL_SUB => Op::Sub(BinaryOp { - left: op.operands[0] as usize, - right: op.operands[1] as usize, - }), - MLIL_AND => Op::And(BinaryOp { - left: op.operands[0] as usize, - right: op.operands[1] as usize, - }), - MLIL_OR => Op::Or(BinaryOp { - left: op.operands[0] as usize, - right: op.operands[1] as usize, - }), - MLIL_XOR => Op::Xor(BinaryOp { - left: op.operands[0] as usize, - right: op.operands[1] as usize, - }), - MLIL_LSL => Op::Lsl(BinaryOp { - left: op.operands[0] as usize, - right: op.operands[1] as usize, - }), - MLIL_LSR => Op::Lsr(BinaryOp { - left: op.operands[0] as usize, - right: op.operands[1] as usize, - }), - MLIL_ASR => Op::Asr(BinaryOp { - left: op.operands[0] as usize, - right: op.operands[1] as usize, - }), - MLIL_ROL => Op::Rol(BinaryOp { - left: op.operands[0] as usize, - right: op.operands[1] as usize, - }), - MLIL_ROR => Op::Ror(BinaryOp { - left: op.operands[0] as usize, - right: op.operands[1] as usize, - }), - MLIL_MUL => Op::Mul(BinaryOp { - left: op.operands[0] as usize, - right: op.operands[1] as usize, - }), - MLIL_MULU_DP => Op::MuluDp(BinaryOp { - left: op.operands[0] as usize, - right: op.operands[1] as usize, - }), - MLIL_MULS_DP => Op::MulsDp(BinaryOp { - left: op.operands[0] as usize, - right: op.operands[1] as usize, - }), - MLIL_DIVU => Op::Divu(BinaryOp { - left: op.operands[0] as usize, - right: op.operands[1] as usize, - }), - MLIL_DIVU_DP => Op::DivuDp(BinaryOp { - left: op.operands[0] as usize, - right: op.operands[1] as usize, - }), - MLIL_DIVS => Op::Divs(BinaryOp { - left: op.operands[0] as usize, - right: op.operands[1] as usize, - }), - MLIL_DIVS_DP => Op::DivsDp(BinaryOp { - left: op.operands[0] as usize, - right: op.operands[1] as usize, - }), - MLIL_MODU => Op::Modu(BinaryOp { - left: op.operands[0] as usize, - right: op.operands[1] as usize, - }), - MLIL_MODU_DP => Op::ModuDp(BinaryOp { - left: op.operands[0] as usize, - right: op.operands[1] as usize, - }), - MLIL_MODS => Op::Mods(BinaryOp { - left: op.operands[0] as usize, - right: op.operands[1] as usize, - }), - MLIL_MODS_DP => Op::ModsDp(BinaryOp { - left: op.operands[0] as usize, - right: op.operands[1] as usize, - }), - MLIL_CMP_E => Op::CmpE(BinaryOp { - left: op.operands[0] as usize, - right: op.operands[1] as usize, - }), - MLIL_CMP_NE => Op::CmpNe(BinaryOp { - left: op.operands[0] as usize, - right: op.operands[1] as usize, - }), - MLIL_CMP_SLT => Op::CmpSlt(BinaryOp { - left: op.operands[0] as usize, - right: op.operands[1] as usize, - }), - MLIL_CMP_ULT => Op::CmpUlt(BinaryOp { - left: op.operands[0] as usize, - right: op.operands[1] as usize, - }), - MLIL_CMP_SLE => Op::CmpSle(BinaryOp { - left: op.operands[0] as usize, - right: op.operands[1] as usize, - }), - MLIL_CMP_ULE => Op::CmpUle(BinaryOp { - left: op.operands[0] as usize, - right: op.operands[1] as usize, - }), - MLIL_CMP_SGE => Op::CmpSge(BinaryOp { - left: op.operands[0] as usize, - right: op.operands[1] as usize, - }), - MLIL_CMP_UGE => Op::CmpUge(BinaryOp { - left: op.operands[0] as usize, - right: op.operands[1] as usize, - }), - MLIL_CMP_SGT => Op::CmpSgt(BinaryOp { - left: op.operands[0] as usize, - right: op.operands[1] as usize, - }), - MLIL_CMP_UGT => Op::CmpUgt(BinaryOp { - left: op.operands[0] as usize, - right: op.operands[1] as usize, - }), - MLIL_TEST_BIT => Op::TestBit(BinaryOp { - left: op.operands[0] as usize, - right: op.operands[1] as usize, - }), - MLIL_ADD_OVERFLOW => Op::AddOverflow(BinaryOp { - left: op.operands[0] as usize, - right: op.operands[1] as usize, - }), - MLIL_FCMP_E => Op::FcmpE(BinaryOp { - left: op.operands[0] as usize, - right: op.operands[1] as usize, - }), - MLIL_FCMP_NE => Op::FcmpNe(BinaryOp { - left: op.operands[0] as usize, - right: op.operands[1] as usize, - }), - MLIL_FCMP_LT => Op::FcmpLt(BinaryOp { - left: op.operands[0] as usize, - right: op.operands[1] as usize, - }), - MLIL_FCMP_LE => Op::FcmpLe(BinaryOp { - left: op.operands[0] as usize, - right: op.operands[1] as usize, - }), - MLIL_FCMP_GE => Op::FcmpGe(BinaryOp { - left: op.operands[0] as usize, - right: op.operands[1] as usize, - }), - MLIL_FCMP_GT => Op::FcmpGt(BinaryOp { - left: op.operands[0] as usize, - right: op.operands[1] as usize, - }), - MLIL_FCMP_O => Op::FcmpO(BinaryOp { - left: op.operands[0] as usize, - right: op.operands[1] as usize, - }), - MLIL_FCMP_UO => Op::FcmpUo(BinaryOp { - left: op.operands[0] as usize, - right: op.operands[1] as usize, - }), - MLIL_FADD => Op::Fadd(BinaryOp { - left: op.operands[0] as usize, - right: op.operands[1] as usize, - }), - MLIL_FSUB => Op::Fsub(BinaryOp { - left: op.operands[0] as usize, - right: op.operands[1] as usize, - }), - MLIL_FMUL => Op::Fmul(BinaryOp { - left: op.operands[0] as usize, - right: op.operands[1] as usize, - }), - MLIL_FDIV => Op::Fdiv(BinaryOp { - left: op.operands[0] as usize, - right: op.operands[1] as usize, - }), - MLIL_ADC => Op::Adc(BinaryOpCarry { - left: op.operands[0] as usize, - right: op.operands[1] as usize, - carry: op.operands[2] as usize, - }), - MLIL_SBB => Op::Sbb(BinaryOpCarry { - left: op.operands[0] as usize, - right: op.operands[1] as usize, - carry: op.operands[2] as usize, - }), - MLIL_RLC => Op::Rlc(BinaryOpCarry { - left: op.operands[0] as usize, - right: op.operands[1] as usize, - carry: op.operands[2] as usize, - }), - MLIL_RRC => Op::Rrc(BinaryOpCarry { - left: op.operands[0] as usize, - right: op.operands[1] as usize, - carry: op.operands[2] as usize, - }), - MLIL_CALL => Op::Call(Call { - num_outputs: op.operands[0] as usize, - first_output: op.operands[1] as usize, - dest: op.operands[2] as usize, - num_params: op.operands[3] as usize, - first_param: op.operands[4] as usize, - }), - MLIL_TAILCALL => Op::Tailcall(Call { - num_outputs: op.operands[0] as usize, - first_output: op.operands[1] as usize, - dest: op.operands[2] as usize, - num_params: op.operands[3] as usize, - first_param: op.operands[4] as usize, - }), - MLIL_SYSCALL => Op::Syscall(Syscall { - num_outputs: op.operands[0] as usize, - first_output: op.operands[1] as usize, - num_params: op.operands[2] as usize, - first_param: op.operands[3] as usize, - }), - MLIL_INTRINSIC => Op::Intrinsic(Intrinsic { - num_outputs: op.operands[0] as usize, - first_output: op.operands[1] as usize, - intrinsic: op.operands[2] as u32, - num_params: op.operands[3] as usize, - first_param: op.operands[4] as usize, - }), - MLIL_INTRINSIC_SSA => Op::IntrinsicSsa(IntrinsicSsa { - num_outputs: op.operands[0] as usize, - first_output: op.operands[1] as usize, - intrinsic: op.operands[2] as u32, - num_params: op.operands[3] as usize, - first_param: op.operands[4] as usize, - }), - MLIL_CALL_SSA => Op::CallSsa(CallSsa { - output: op.operands[0] as usize, - dest: op.operands[1] as usize, - num_params: op.operands[2] as usize, - first_param: op.operands[3] as usize, - src_memory: op.operands[4], - }), - MLIL_TAILCALL_SSA => Op::TailcallSsa(CallSsa { - output: op.operands[0] as usize, - dest: op.operands[1] as usize, - num_params: op.operands[2] as usize, - first_param: op.operands[3] as usize, - src_memory: op.operands[4], - }), - MLIL_CALL_UNTYPED_SSA => Op::CallUntypedSsa(CallUntypedSsa { - output: op.operands[0] as usize, - dest: op.operands[1] as usize, - params: op.operands[2] as usize, - stack: op.operands[3] as usize, - }), - MLIL_TAILCALL_UNTYPED_SSA => Op::TailcallUntypedSsa(CallUntypedSsa { - output: op.operands[0] as usize, - dest: op.operands[1] as usize, - params: op.operands[2] as usize, - stack: op.operands[3] as usize, - }), - MLIL_SYSCALL_SSA => Op::SyscallSsa(SyscallSsa { - output: op.operands[0] as usize, - num_params: op.operands[1] as usize, - first_param: op.operands[2] as usize, - src_memory: op.operands[3], - }), - MLIL_SYSCALL_UNTYPED_SSA => Op::SyscallUntypedSsa(SyscallUntypedSsa { - output: op.operands[0] as usize, - params: op.operands[1] as usize, - stack: op.operands[2] as usize, - }), - MLIL_CALL_UNTYPED => Op::CallUntyped(CallUntyped { - output: op.operands[0] as usize, - dest: op.operands[1] as usize, - params: op.operands[2] as usize, - stack: op.operands[3] as usize, - }), - MLIL_TAILCALL_UNTYPED => Op::TailcallUntyped(CallUntyped { - output: op.operands[0] as usize, - dest: op.operands[1] as usize, - params: op.operands[2] as usize, - stack: op.operands[3] as usize, - }), - MLIL_SYSCALL_UNTYPED => Op::SyscallUntyped(SyscallUntyped { - output: op.operands[0] as usize, - params: op.operands[1] as usize, - stack: op.operands[2] as usize, - }), - MLIL_NEG => Op::Neg(UnaryOp { - src: op.operands[0] as usize, - }), - MLIL_NOT => Op::Not(UnaryOp { - src: op.operands[0] as usize, - }), - MLIL_SX => Op::Sx(UnaryOp { - src: op.operands[0] as usize, - }), - MLIL_ZX => Op::Zx(UnaryOp { - src: op.operands[0] as usize, - }), - MLIL_LOW_PART => Op::LowPart(UnaryOp { - src: op.operands[0] as usize, - }), - MLIL_BOOL_TO_INT => Op::BoolToInt(UnaryOp { - src: op.operands[0] as usize, - }), - MLIL_UNIMPL_MEM => Op::UnimplMem(UnaryOp { - src: op.operands[0] as usize, - }), - MLIL_FSQRT => Op::Fsqrt(UnaryOp { - src: op.operands[0] as usize, - }), - MLIL_FNEG => Op::Fneg(UnaryOp { - src: op.operands[0] as usize, - }), - MLIL_FABS => Op::Fabs(UnaryOp { - src: op.operands[0] as usize, - }), - MLIL_FLOAT_TO_INT => Op::FloatToInt(UnaryOp { - src: op.operands[0] as usize, - }), - MLIL_INT_TO_FLOAT => Op::IntToFloat(UnaryOp { - src: op.operands[0] as usize, - }), - MLIL_FLOAT_CONV => Op::FloatConv(UnaryOp { - src: op.operands[0] as usize, - }), - MLIL_ROUND_TO_INT => Op::RoundToInt(UnaryOp { - src: op.operands[0] as usize, - }), - MLIL_FLOOR => Op::Floor(UnaryOp { - src: op.operands[0] as usize, - }), - MLIL_CEIL => Op::Ceil(UnaryOp { - src: op.operands[0] as usize, - }), - MLIL_FTRUNC => Op::Ftrunc(UnaryOp { - src: op.operands[0] as usize, - }), - MLIL_LOAD => Op::Load(UnaryOp { - src: op.operands[0] as usize, - }), - MLIL_LOAD_STRUCT => Op::LoadStruct(LoadStruct { - src: op.operands[0] as usize, - offset: op.operands[1], - }), - MLIL_LOAD_STRUCT_SSA => Op::LoadStructSsa(LoadStructSsa { - src: op.operands[0] as usize, - offset: op.operands[1], - src_memory: op.operands[2], - }), - MLIL_LOAD_SSA => Op::LoadSsa(LoadSsa { - src: op.operands[0] as usize, - src_memory: op.operands[1], - }), - MLIL_RET => Op::Ret(Ret { - num_operands: op.operands[0] as usize, - first_operand: op.operands[1] as usize, - }), - MLIL_SEPARATE_PARAM_LIST => Op::SeparateParamList(SeparateParamList { - num_params: op.operands[0] as usize, - first_param: op.operands[1] as usize, - }), - MLIL_SHARED_PARAM_SLOT => Op::SharedParamSlot(SharedParamSlot { - num_params: op.operands[0] as usize, - first_param: op.operands[1] as usize, - }), - MLIL_VAR => Op::Var(Var { - src: get_var(op.operands[0]), - }), - MLIL_ADDRESS_OF => Op::AddressOf(Var { - src: get_var(op.operands[0]), - }), - MLIL_VAR_FIELD => Op::VarField(Field { - src: get_var(op.operands[0]), - offset: op.operands[1], - }), - MLIL_ADDRESS_OF_FIELD => Op::AddressOfField(Field { - src: get_var(op.operands[0]), - offset: op.operands[1], - }), - MLIL_VAR_SSA => Op::VarSsa(VarSsa { - src: get_var_ssa(op.operands[0], op.operands[1] as usize), - }), - MLIL_VAR_ALIASED => Op::VarAliased(VarSsa { - src: get_var_ssa(op.operands[0], op.operands[1] as usize), - }), - MLIL_VAR_SSA_FIELD => Op::VarSsaField(VarSsaField { - src: get_var_ssa(op.operands[0], op.operands[1] as usize), - offset: op.operands[2], - }), - MLIL_VAR_ALIASED_FIELD => Op::VarAliasedField(VarSsaField { - src: get_var_ssa(op.operands[0], op.operands[1] as usize), - offset: op.operands[2], - }), - MLIL_TRAP => Op::Trap(Trap { - vector: op.operands[0], - }), - // translated directly into a list for Expression or Variables - // TODO MLIL_MEMORY_INTRINSIC_SSA needs to be handled properly - MLIL_CALL_OUTPUT - | MLIL_CALL_PARAM - | MLIL_CALL_PARAM_SSA - | MLIL_CALL_OUTPUT_SSA - | MLIL_MEMORY_INTRINSIC_OUTPUT_SSA - | MLIL_MEMORY_INTRINSIC_SSA => { - unreachable!() - } - }; - - Self { - function, - address: op.address, - index, - size: op.size, - kind, - } - } - - pub fn lift(&self) -> MediumLevelILLiftedInstruction { - use MediumLevelILInstructionKind::*; - use MediumLevelILLiftedInstructionKind as Lifted; - - let kind = match self.kind { - Nop => Lifted::Nop, - Noret => Lifted::Noret, - Bp => Lifted::Bp, - Undef => Lifted::Undef, - Unimpl => Lifted::Unimpl, - If(op) => Lifted::If(LiftedIf { - condition: self.lift_operand(op.condition), - dest_true: op.dest_true, - dest_false: op.dest_false, - }), - - FloatConst(op) => Lifted::FloatConst(op), - Const(op) => Lifted::Const(op), - ConstPtr(op) => Lifted::ConstPtr(op), - Import(op) => Lifted::Import(op), - ExternPtr(op) => Lifted::ExternPtr(op), - - ConstData(op) => Lifted::ConstData(LiftedConstData { - constant_data: ConstantData::new( - self.function.get_function(), - RegisterValue { - state: RegisterValueType::from_raw_value(op.constant_data_kind).unwrap(), - value: op.constant_data_value, - offset: 0, - size: op.size, - }, - ), - }), - Jump(op) => Lifted::Jump(LiftedJump { - dest: self.lift_operand(op.dest), - }), - RetHint(op) => Lifted::RetHint(LiftedJump { - dest: self.lift_operand(op.dest), - }), - StoreSsa(op) => Lifted::StoreSsa(LiftedStoreSsa { - dest: self.lift_operand(op.dest), - dest_memory: op.dest_memory, - src_memory: op.src_memory, - src: self.lift_operand(op.src), - }), - StoreStructSsa(op) => Lifted::StoreStructSsa(LiftedStoreStructSsa { - dest: self.lift_operand(op.dest), - offset: op.offset, - dest_memory: op.dest_memory, - src_memory: op.src_memory, - src: self.lift_operand(op.src), - }), - StoreStruct(op) => Lifted::StoreStruct(LiftedStoreStruct { - dest: self.lift_operand(op.dest), - offset: op.offset, - src: self.lift_operand(op.src), - }), - Store(op) => Lifted::Store(LiftedStore { - dest: self.lift_operand(op.dest), - src: self.lift_operand(op.src), - }), - JumpTo(op) => Lifted::JumpTo(LiftedJumpTo { - dest: self.lift_operand(op.dest), - targets: OperandIter::new(&*self.function, op.first_operand, op.num_operands) - .pairs() - .collect(), - }), - Goto(op) => Lifted::Goto(op), - FreeVarSlot(op) => Lifted::FreeVarSlot(op), - SetVarField(op) => Lifted::SetVarField(LiftedSetVarField { - dest: op.dest, - offset: op.offset, - src: self.lift_operand(op.src), - }), - SetVar(op) => Lifted::SetVar(LiftedSetVar { - dest: op.dest, - src: self.lift_operand(op.src), - }), - FreeVarSlotSsa(op) => Lifted::FreeVarSlotSsa(op), - SetVarSsaField(op) => Lifted::SetVarSsaField(LiftedSetVarSsaField { - dest: op.dest, - prev: op.prev, - offset: op.offset, - src: self.lift_operand(op.src), - }), - SetVarAliasedField(op) => Lifted::SetVarAliasedField(LiftedSetVarSsaField { - dest: op.dest, - prev: op.prev, - offset: op.offset, - src: self.lift_operand(op.src), - }), - SetVarAliased(op) => Lifted::SetVarAliased(LiftedSetVarAliased { - dest: op.dest, - prev: op.prev, - src: self.lift_operand(op.src), - }), - SetVarSsa(op) => Lifted::SetVarSsa(LiftedSetVarSsa { - dest: op.dest, - src: self.lift_operand(op.src), - }), - VarPhi(op) => Lifted::VarPhi(LiftedVarPhi { - dest: op.dest, - src: OperandIter::new(&*self.function, op.first_operand, op.num_operands) - .ssa_vars() - .collect(), - }), - MemPhi(op) => Lifted::MemPhi(LiftedMemPhi { - dest_memory: op.dest_memory, - src_memory: OperandIter::new(&*self.function, op.first_operand, op.num_operands) - .collect(), - }), - VarSplit(op) => Lifted::VarSplit(op), - SetVarSplit(op) => Lifted::SetVarSplit(LiftedSetVarSplit { - high: op.high, - low: op.low, - src: self.lift_operand(op.src), - }), - VarSplitSsa(op) => Lifted::VarSplitSsa(op), - SetVarSplitSsa(op) => Lifted::SetVarSplitSsa(LiftedSetVarSplitSsa { - high: op.high, - low: op.low, - src: self.lift_operand(op.src), - }), - - Add(op) => Lifted::Add(self.lift_binary_op(op)), - Sub(op) => Lifted::Sub(self.lift_binary_op(op)), - And(op) => Lifted::And(self.lift_binary_op(op)), - Or(op) => Lifted::Or(self.lift_binary_op(op)), - Xor(op) => Lifted::Xor(self.lift_binary_op(op)), - Lsl(op) => Lifted::Lsl(self.lift_binary_op(op)), - Lsr(op) => Lifted::Lsr(self.lift_binary_op(op)), - Asr(op) => Lifted::Asr(self.lift_binary_op(op)), - Rol(op) => Lifted::Rol(self.lift_binary_op(op)), - Ror(op) => Lifted::Ror(self.lift_binary_op(op)), - Mul(op) => Lifted::Mul(self.lift_binary_op(op)), - MuluDp(op) => Lifted::MuluDp(self.lift_binary_op(op)), - MulsDp(op) => Lifted::MulsDp(self.lift_binary_op(op)), - Divu(op) => Lifted::Divu(self.lift_binary_op(op)), - DivuDp(op) => Lifted::DivuDp(self.lift_binary_op(op)), - Divs(op) => Lifted::Divs(self.lift_binary_op(op)), - DivsDp(op) => Lifted::DivsDp(self.lift_binary_op(op)), - Modu(op) => Lifted::Modu(self.lift_binary_op(op)), - ModuDp(op) => Lifted::ModuDp(self.lift_binary_op(op)), - Mods(op) => Lifted::Mods(self.lift_binary_op(op)), - ModsDp(op) => Lifted::ModsDp(self.lift_binary_op(op)), - CmpE(op) => Lifted::CmpE(self.lift_binary_op(op)), - CmpNe(op) => Lifted::CmpNe(self.lift_binary_op(op)), - CmpSlt(op) => Lifted::CmpSlt(self.lift_binary_op(op)), - CmpUlt(op) => Lifted::CmpUlt(self.lift_binary_op(op)), - CmpSle(op) => Lifted::CmpSle(self.lift_binary_op(op)), - CmpUle(op) => Lifted::CmpUle(self.lift_binary_op(op)), - CmpSge(op) => Lifted::CmpSge(self.lift_binary_op(op)), - CmpUge(op) => Lifted::CmpUge(self.lift_binary_op(op)), - CmpSgt(op) => Lifted::CmpSgt(self.lift_binary_op(op)), - CmpUgt(op) => Lifted::CmpUgt(self.lift_binary_op(op)), - TestBit(op) => Lifted::TestBit(self.lift_binary_op(op)), - AddOverflow(op) => Lifted::AddOverflow(self.lift_binary_op(op)), - FcmpE(op) => Lifted::FcmpE(self.lift_binary_op(op)), - FcmpNe(op) => Lifted::FcmpNe(self.lift_binary_op(op)), - FcmpLt(op) => Lifted::FcmpLt(self.lift_binary_op(op)), - FcmpLe(op) => Lifted::FcmpLe(self.lift_binary_op(op)), - FcmpGe(op) => Lifted::FcmpGe(self.lift_binary_op(op)), - FcmpGt(op) => Lifted::FcmpGt(self.lift_binary_op(op)), - FcmpO(op) => Lifted::FcmpO(self.lift_binary_op(op)), - FcmpUo(op) => Lifted::FcmpUo(self.lift_binary_op(op)), - Fadd(op) => Lifted::Fadd(self.lift_binary_op(op)), - Fsub(op) => Lifted::Fsub(self.lift_binary_op(op)), - Fmul(op) => Lifted::Fmul(self.lift_binary_op(op)), - Fdiv(op) => Lifted::Fdiv(self.lift_binary_op(op)), - - Adc(op) => Lifted::Adc(self.lift_binary_op_carry(op)), - Sbb(op) => Lifted::Sbb(self.lift_binary_op_carry(op)), - Rlc(op) => Lifted::Rlc(self.lift_binary_op_carry(op)), - Rrc(op) => Lifted::Rrc(self.lift_binary_op_carry(op)), - - Call(op) => Lifted::Call(self.lift_call(op)), - Tailcall(op) => Lifted::Tailcall(self.lift_call(op)), - - Intrinsic(op) => Lifted::Intrinsic(LiftedIntrinsic { - output: OperandIter::new(&*self.function, op.first_output, op.num_outputs) - .vars() - .collect(), - intrinsic: CoreIntrinsic(self.function.get_function().arch().0, op.intrinsic), - params: OperandIter::new(&*self.function, op.first_param, op.num_params) - .exprs() - .map(|expr| expr.lift()) - .collect(), - }), - Syscall(op) => Lifted::Syscall(LiftedSyscallCall { - output: OperandIter::new(&*self.function, op.first_output, op.num_outputs) - .vars() - .collect(), - params: OperandIter::new(&*self.function, op.first_param, op.num_params) - .exprs() - .map(|expr| expr.lift()) - .collect(), - }), - IntrinsicSsa(op) => Lifted::IntrinsicSsa(LiftedIntrinsicSsa { - output: OperandIter::new(&*self.function, op.first_output, op.num_outputs) - .ssa_vars() - .collect(), - intrinsic: CoreIntrinsic(self.function.get_function().arch().0, op.intrinsic), - params: OperandIter::new(&*self.function, op.first_param, op.num_params) - .exprs() - .map(|expr| expr.lift()) - .collect(), - }), - - CallSsa(op) => Lifted::CallSsa(self.lift_call_ssa(op)), - TailcallSsa(op) => Lifted::TailcallSsa(self.lift_call_ssa(op)), - - CallUntypedSsa(op) => Lifted::CallUntypedSsa(self.lift_call_untyped_ssa(op)), - TailcallUntypedSsa(op) => Lifted::TailcallUntypedSsa(self.lift_call_untyped_ssa(op)), - - SyscallSsa(op) => Lifted::SyscallSsa(LiftedSyscallSsa { - output: get_call_output_ssa(&self.function, op.output).collect(), - params: OperandIter::new(&*self.function, op.first_param, op.num_params) - .exprs() - .map(|expr| expr.lift()) - .collect(), - src_memory: op.src_memory, - }), - SyscallUntypedSsa(op) => Lifted::SyscallUntypedSsa(LiftedSyscallUntypedSsa { - output: get_call_output_ssa(&self.function, op.output).collect(), - params: get_call_params_ssa(&self.function, op.params) - .map(|param| param.lift()) - .collect(), - stack: self.lift_operand(op.stack), - }), - - CallUntyped(op) => Lifted::CallUntyped(self.lift_call_untyped(op)), - TailcallUntyped(op) => Lifted::TailcallUntyped(self.lift_call_untyped(op)), - SyscallUntyped(op) => Lifted::SyscallUntyped(LiftedSyscallUntyped { - output: get_call_output(&self.function, op.output).collect(), - params: get_call_params(&self.function, op.params) - .map(|param| param.lift()) - .collect(), - stack: self.lift_operand(op.stack), - }), - - Neg(op) => Lifted::Neg(self.lift_unary_op(op)), - Not(op) => Lifted::Not(self.lift_unary_op(op)), - Sx(op) => Lifted::Sx(self.lift_unary_op(op)), - Zx(op) => Lifted::Zx(self.lift_unary_op(op)), - LowPart(op) => Lifted::LowPart(self.lift_unary_op(op)), - BoolToInt(op) => Lifted::BoolToInt(self.lift_unary_op(op)), - UnimplMem(op) => Lifted::UnimplMem(self.lift_unary_op(op)), - Fsqrt(op) => Lifted::Fsqrt(self.lift_unary_op(op)), - Fneg(op) => Lifted::Fneg(self.lift_unary_op(op)), - Fabs(op) => Lifted::Fabs(self.lift_unary_op(op)), - FloatToInt(op) => Lifted::FloatToInt(self.lift_unary_op(op)), - IntToFloat(op) => Lifted::IntToFloat(self.lift_unary_op(op)), - FloatConv(op) => Lifted::FloatConv(self.lift_unary_op(op)), - RoundToInt(op) => Lifted::RoundToInt(self.lift_unary_op(op)), - Floor(op) => Lifted::Floor(self.lift_unary_op(op)), - Ceil(op) => Lifted::Ceil(self.lift_unary_op(op)), - Ftrunc(op) => Lifted::Ftrunc(self.lift_unary_op(op)), - Load(op) => Lifted::Load(self.lift_unary_op(op)), - - LoadStruct(op) => Lifted::LoadStruct(LiftedLoadStruct { - src: self.lift_operand(op.src), - offset: op.offset, - }), - LoadStructSsa(op) => Lifted::LoadStructSsa(LiftedLoadStructSsa { - src: self.lift_operand(op.src), - offset: op.offset, - src_memory: op.src_memory, - }), - LoadSsa(op) => Lifted::LoadSsa(LiftedLoadSsa { - src: self.lift_operand(op.src), - src_memory: op.src_memory, - }), - Ret(op) => Lifted::Ret(LiftedRet { - src: OperandIter::new(&*self.function, op.first_operand, op.num_operands) - .exprs() - .map(|expr| expr.lift()) - .collect(), - }), - SeparateParamList(op) => Lifted::SeparateParamList(LiftedSeparateParamList { - params: OperandIter::new(&*self.function, op.first_param, op.num_params) - .exprs() - .map(|expr| expr.lift()) - .collect(), - }), - SharedParamSlot(op) => Lifted::SharedParamSlot(LiftedSharedParamSlot { - params: OperandIter::new(&*self.function, op.first_param, op.num_params) - .exprs() - .map(|expr| expr.lift()) - .collect(), - }), - Var(op) => Lifted::Var(op), - AddressOf(op) => Lifted::AddressOf(op), - VarField(op) => Lifted::VarField(op), - AddressOfField(op) => Lifted::AddressOfField(op), - VarSsa(op) => Lifted::VarSsa(op), - VarAliased(op) => Lifted::VarAliased(op), - VarSsaField(op) => Lifted::VarSsaField(op), - VarAliasedField(op) => Lifted::VarAliasedField(op), - Trap(op) => Lifted::Trap(op), - }; - - MediumLevelILLiftedInstruction { - function: self.function.clone(), - address: self.address, - index: self.index, - size: self.size, - kind, - } - } - - pub fn tokens(&self) -> Array<InstructionTextToken> { - let mut count = 0; - let mut tokens = core::ptr::null_mut(); - assert!(unsafe { - BNGetMediumLevelILExprText( - self.function.handle, - self.function.get_function().arch().0, - self.index, - &mut tokens, - &mut count, - core::ptr::null_mut(), - ) - }); - unsafe { Array::new(tokens, count, ()) } - } - - /// Value of expression if constant or a known value - pub fn value(&self) -> RegisterValue { - unsafe { BNGetMediumLevelILExprValue(self.function.handle, self.index) }.into() - } - - /// Possible values of expression using path-sensitive static data flow analysis - pub fn possible_values(&self, options: Option<&[DataFlowQueryOption]>) -> PossibleValueSet { - let options_ptr = options - .map(|op| op.as_ptr() as *mut DataFlowQueryOption) - .unwrap_or(core::ptr::null_mut()); - let options_len = options.map(|op| op.len()).unwrap_or(0); - let mut value = unsafe { - BNGetMediumLevelILPossibleExprValues( - self.function.handle, - self.index, - options_ptr, - options_len, - ) - }; - let result = unsafe { PossibleValueSet::from_raw(value) }; - unsafe { BNFreePossibleValueSet(&mut value) } - result - } - - pub fn possible_ssa_variable_values( - &self, - ssa_var: SSAVariable, - options: Option<&[DataFlowQueryOption]>, - ) -> PossibleValueSet { - let options_ptr = options - .map(|op| op.as_ptr() as *mut DataFlowQueryOption) - .unwrap_or(core::ptr::null_mut()); - let options_len = options.map(|op| op.len()).unwrap_or(0); - let mut value = unsafe { - BNGetMediumLevelILPossibleSSAVarValues( - self.function.handle, - &ssa_var.variable.raw(), - ssa_var.version, - self.index, - options_ptr, - options_len, - ) - }; - let result = unsafe { PossibleValueSet::from_raw(value) }; - unsafe { BNFreePossibleValueSet(&mut value) } - result - } - - /// return the variable version used at this instruction - pub fn ssa_variable_version(&self, var: Variable) -> SSAVariable { - let version = unsafe { - BNGetMediumLevelILSSAVarVersionAtILInstruction( - self.function.handle, - &var.raw(), - self.index, - ) - }; - SSAVariable::new(var, version) - } - - /// Set of branching instructions that must take the true or false path to reach this instruction - pub fn branch_dependence(&self) -> Array<BranchDependence> { - let mut count = 0; - let deps = unsafe { - BNGetAllMediumLevelILBranchDependence(self.function.handle, self.index, &mut count) - }; - assert!(!deps.is_null()); - unsafe { Array::new(deps, count, self.function.clone()) } - } - - pub fn branch_dependence_at(&self, instruction: MediumLevelILInstruction) -> BranchDependence { - let deps = unsafe { - BNGetMediumLevelILBranchDependence(self.function.handle, self.index, instruction.index) - }; - BranchDependence { - instruction, - dependence: deps, - } - } - - /// Version of active memory contents in SSA form for this instruction - pub fn ssa_memory_version(&self) -> usize { - unsafe { - BNGetMediumLevelILSSAMemoryVersionAtILInstruction(self.function.handle, self.index) - } - } - - /// Type of expression - pub fn expr_type(&self) -> Option<Conf<Ref<Type>>> { - let result = unsafe { BNGetMediumLevelILExprType(self.function.handle, self.index) }; - (!result.type_.is_null()).then(|| { - Conf::new( - unsafe { Type::ref_from_raw(result.type_) }, - result.confidence, - ) - }) - } - - /// Set type of expression - /// - /// This API is only meant for workflows or for debugging purposes, since the changes they make are not persistent - /// and get lost after a database save and reload. To make persistent changes to the analysis, one should use other - /// APIs to, for example, change the type of variables. The analysis will then propagate the type of the variable - /// and update the type of related expressions. - pub fn set_expr_type<'a, T: Into<Conf<&'a Type>>>(&self, value: T) { - let type_: Conf<&'a Type> = value.into(); - let mut type_raw: BNTypeWithConfidence = BNTypeWithConfidence { - type_: type_.contents.handle, - confidence: type_.confidence, - }; - unsafe { BNSetMediumLevelILExprType(self.function.handle, self.index, &mut type_raw) } - } - - pub fn variable_for_register(&self, reg_id: u32) -> Variable { - let result = unsafe { - BNGetMediumLevelILVariableForRegisterAtInstruction( - self.function.handle, - reg_id, - self.index, - ) - }; - unsafe { Variable::from_raw(result) } - } - - pub fn variable_for_flag(&self, flag_id: u32) -> Variable { - let result = unsafe { - BNGetMediumLevelILVariableForFlagAtInstruction( - self.function.handle, - flag_id, - self.index, - ) - }; - unsafe { Variable::from_raw(result) } - } - - pub fn variable_for_stack_location(&self, offset: i64) -> Variable { - let result = unsafe { - BNGetMediumLevelILVariableForStackLocationAtInstruction( - self.function.handle, - offset, - self.index, - ) - }; - unsafe { Variable::from_raw(result) } - } - - pub fn register_value(&self, reg_id: u32) -> RegisterValue { - unsafe { - BNGetMediumLevelILRegisterValueAtInstruction(self.function.handle, reg_id, self.index) - } - .into() - } - - pub fn register_value_after(&self, reg_id: u32) -> RegisterValue { - unsafe { - BNGetMediumLevelILRegisterValueAfterInstruction( - self.function.handle, - reg_id, - self.index, - ) - } - .into() - } - - pub fn possible_register_values( - &self, - reg_id: u32, - options: Option<&[DataFlowQueryOption]>, - ) -> PossibleValueSet { - let options_ptr = options - .map(|op| op.as_ptr() as *mut DataFlowQueryOption) - .unwrap_or(core::ptr::null_mut()); - let options_len = options.map(|op| op.len()).unwrap_or(0); - let mut value = unsafe { - BNGetMediumLevelILPossibleRegisterValuesAtInstruction( - self.function.handle, - reg_id, - self.index, - options_ptr, - options_len, - ) - }; - let result = unsafe { PossibleValueSet::from_raw(value) }; - unsafe { BNFreePossibleValueSet(&mut value) } - result - } - - pub fn possible_register_values_after( - &self, - reg_id: u32, - options: Option<&[DataFlowQueryOption]>, - ) -> PossibleValueSet { - let options_ptr = options - .map(|op| op.as_ptr() as *mut DataFlowQueryOption) - .unwrap_or(core::ptr::null_mut()); - let options_len = options.map(|op| op.len()).unwrap_or(0); - let mut value = unsafe { - BNGetMediumLevelILPossibleRegisterValuesAfterInstruction( - self.function.handle, - reg_id, - self.index, - options_ptr, - options_len, - ) - }; - let result = unsafe { PossibleValueSet::from_raw(value) }; - unsafe { BNFreePossibleValueSet(&mut value) } - result - } - - pub fn flag_value(&self, flag_id: u32) -> RegisterValue { - unsafe { - BNGetMediumLevelILFlagValueAtInstruction(self.function.handle, flag_id, self.index) - } - .into() - } - - pub fn flag_value_after(&self, flag_id: u32) -> RegisterValue { - unsafe { - BNGetMediumLevelILFlagValueAfterInstruction(self.function.handle, flag_id, self.index) - } - .into() - } - - pub fn possible_flag_values( - &self, - flag_id: u32, - options: Option<&[DataFlowQueryOption]>, - ) -> PossibleValueSet { - let options_ptr = options - .map(|op| op.as_ptr() as *mut DataFlowQueryOption) - .unwrap_or(core::ptr::null_mut()); - let options_len = options.map(|op| op.len()).unwrap_or(0); - let mut value = unsafe { - BNGetMediumLevelILPossibleFlagValuesAtInstruction( - self.function.handle, - flag_id, - self.index, - options_ptr, - options_len, - ) - }; - let result = unsafe { PossibleValueSet::from_raw(value) }; - unsafe { BNFreePossibleValueSet(&mut value) } - result - } - - pub fn possible_flag_values_after( - &self, - flag_id: u32, - options: Option<&[DataFlowQueryOption]>, - ) -> PossibleValueSet { - let options_ptr = options - .map(|op| op.as_ptr() as *mut DataFlowQueryOption) - .unwrap_or(core::ptr::null_mut()); - let options_len = options.map(|op| op.len()).unwrap_or(0); - let mut value = unsafe { - BNGetMediumLevelILPossibleFlagValuesAfterInstruction( - self.function.handle, - flag_id, - self.index, - options_ptr, - options_len, - ) - }; - let result = unsafe { PossibleValueSet::from_raw(value) }; - unsafe { BNFreePossibleValueSet(&mut value) } - result - } - - pub fn stack_contents(&self, offset: i64, size: usize) -> RegisterValue { - unsafe { - BNGetMediumLevelILStackContentsAtInstruction( - self.function.handle, - offset, - size, - self.index, - ) - } - .into() - } - - pub fn stack_contents_after(&self, offset: i64, size: usize) -> RegisterValue { - unsafe { - BNGetMediumLevelILStackContentsAfterInstruction( - self.function.handle, - offset, - size, - self.index, - ) - } - .into() - } - - pub fn possible_stack_contents( - &self, - offset: i64, - size: usize, - options: Option<&[DataFlowQueryOption]>, - ) -> PossibleValueSet { - let options_ptr = options - .map(|op| op.as_ptr() as *mut DataFlowQueryOption) - .unwrap_or(core::ptr::null_mut()); - let options_len = options.map(|op| op.len()).unwrap_or(0); - let mut value = unsafe { - BNGetMediumLevelILPossibleStackContentsAtInstruction( - self.function.handle, - offset, - size, - self.index, - options_ptr, - options_len, - ) - }; - let result = unsafe { PossibleValueSet::from_raw(value) }; - unsafe { BNFreePossibleValueSet(&mut value) } - result - } - - pub fn possible_stack_contents_after( - &self, - offset: i64, - size: usize, - options: Option<&[DataFlowQueryOption]>, - ) -> PossibleValueSet { - let options_ptr = options - .map(|op| op.as_ptr() as *mut DataFlowQueryOption) - .unwrap_or(core::ptr::null_mut()); - let options_len = options.map(|op| op.len()).unwrap_or(0); - let mut value = unsafe { - BNGetMediumLevelILPossibleStackContentsAfterInstruction( - self.function.handle, - offset, - size, - self.index, - options_ptr, - options_len, - ) - }; - let result = unsafe { PossibleValueSet::from_raw(value) }; - unsafe { BNFreePossibleValueSet(&mut value) } - result - } - - /// Gets the unique variable for a definition instruction. This unique variable can be passed - /// to [crate::function::Function::split_variable] to split a variable at a definition. The given `var` is the - /// assigned variable to query. - /// - /// * `var` - variable to query - pub fn split_var_for_definition(&self, var: Variable) -> Variable { - let index = unsafe { - BNGetDefaultIndexForMediumLevelILVariableDefinition( - self.function.handle, - &var.raw(), - self.index, - ) - }; - Variable::new(var.t, index, var.storage) - } - - /// alias for [MediumLevelILInstruction::split_var_for_definition] - #[inline] - pub fn get_split_var_for_definition(&self, var: &Variable) -> Variable { - self.split_var_for_definition(*var) - } - - fn lift_operand(&self, expr_idx: usize) -> Box<MediumLevelILLiftedInstruction> { - Box::new(self.function.lifted_instruction_from_idx(expr_idx)) - } - - fn lift_binary_op(&self, op: BinaryOp) -> LiftedBinaryOp { - LiftedBinaryOp { - left: self.lift_operand(op.left), - right: self.lift_operand(op.right), - } - } - - fn lift_binary_op_carry(&self, op: BinaryOpCarry) -> LiftedBinaryOpCarry { - LiftedBinaryOpCarry { - left: self.lift_operand(op.left), - right: self.lift_operand(op.right), - carry: self.lift_operand(op.carry), - } - } - - fn lift_unary_op(&self, op: UnaryOp) -> LiftedUnaryOp { - LiftedUnaryOp { - src: self.lift_operand(op.src), - } - } - - fn lift_call(&self, op: Call) -> LiftedCall { - LiftedCall { - output: OperandIter::new(&*self.function, op.first_output, op.num_outputs) - .vars() - .collect(), - dest: self.lift_operand(op.dest), - params: OperandIter::new(&*self.function, op.first_param, op.num_params) - .exprs() - .map(|expr| expr.lift()) - .collect(), - } - } - - fn lift_call_untyped(&self, op: CallUntyped) -> LiftedCallUntyped { - LiftedCallUntyped { - output: get_call_output(&self.function, op.output).collect(), - dest: self.lift_operand(op.dest), - params: get_call_params(&self.function, op.params) - .map(|expr| expr.lift()) - .collect(), - stack: self.lift_operand(op.stack), - } - } - - fn lift_call_ssa(&self, op: CallSsa) -> LiftedCallSsa { - LiftedCallSsa { - output: get_call_output_ssa(&self.function, op.output).collect(), - dest: self.lift_operand(op.dest), - params: OperandIter::new(&*self.function, op.first_param, op.num_params) - .exprs() - .map(|expr| expr.lift()) - .collect(), - src_memory: op.src_memory, - } - } - - fn lift_call_untyped_ssa(&self, op: CallUntypedSsa) -> LiftedCallUntypedSsa { - LiftedCallUntypedSsa { - output: get_call_output_ssa(&self.function, op.output).collect(), - dest: self.lift_operand(op.dest), - params: get_call_params_ssa(&self.function, op.params) - .map(|param| param.lift()) - .collect(), - stack: self.lift_operand(op.stack), - } - } -} - -impl CoreArrayProvider for MediumLevelILInstruction { - type Raw = usize; - type Context = Ref<MediumLevelILFunction>; - type Wrapped<'a> = Self; -} - -unsafe impl CoreArrayProviderInner for MediumLevelILInstruction { - unsafe fn free(raw: *mut Self::Raw, _count: usize, _context: &Self::Context) { - BNFreeILInstructionList(raw) - } - - unsafe fn wrap_raw<'a>(raw: &'a Self::Raw, context: &'a Self::Context) -> Self::Wrapped<'a> { - context.instruction_from_idx(*raw) - } -} - -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) } -} - -fn get_var(id: u64) -> Variable { - unsafe { Variable::from_identifier(id) } -} - -fn get_var_ssa(id: u64, version: usize) -> SSAVariable { - SSAVariable::new(get_var(id), version) -} - -fn get_call_output(function: &MediumLevelILFunction, idx: usize) -> impl Iterator<Item = Variable> { - 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).vars() -} - -fn get_call_params( - function: &MediumLevelILFunction, - idx: usize, -) -> impl Iterator<Item = MediumLevelILInstruction> { - 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).exprs() -} - -fn get_call_output_ssa( - function: &MediumLevelILFunction, - idx: usize, -) -> impl Iterator<Item = SSAVariable> { - 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).ssa_vars() -} - -fn get_call_params_ssa( - function: &MediumLevelILFunction, - idx: usize, -) -> impl Iterator<Item = MediumLevelILInstruction> { - 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).exprs() -} - -/// Conditional branching instruction and an expected conditional result -pub struct BranchDependence { - pub instruction: MediumLevelILInstruction, - pub dependence: ILBranchDependence, -} - -impl CoreArrayProvider for BranchDependence { - type Raw = BNILBranchInstructionAndDependence; - type Context = Ref<MediumLevelILFunction>; - type Wrapped<'a> = Self; -} - -unsafe impl CoreArrayProviderInner for BranchDependence { - unsafe fn free(raw: *mut Self::Raw, _count: usize, _context: &Self::Context) { - unsafe { BNFreeILBranchDependenceList(raw) }; - } - - unsafe fn wrap_raw<'a>(raw: &'a Self::Raw, context: &'a Self::Context) -> Self::Wrapped<'a> { - Self { - instruction: MediumLevelILInstruction::new(context.clone(), raw.branch), - dependence: raw.dependence, - } - } -} diff --git a/rust/src/mlil/lift.rs b/rust/src/mlil/lift.rs deleted file mode 100644 index 7a5e159b..00000000 --- a/rust/src/mlil/lift.rs +++ /dev/null @@ -1,510 +0,0 @@ -use std::collections::BTreeMap; - -use crate::architecture::CoreIntrinsic; -use crate::rc::Ref; -use crate::types::{ConstantData, SSAVariable, Variable}; - -use super::operation::*; -use super::MediumLevelILFunction; - -#[derive(Clone)] -pub enum MediumLevelILLiftedOperand { - ConstantData(ConstantData), - Intrinsic(CoreIntrinsic), - Expr(MediumLevelILLiftedInstruction), - ExprList(Vec<MediumLevelILLiftedInstruction>), - Float(f64), - Int(u64), - IntList(Vec<u64>), - TargetMap(BTreeMap<u64, u64>), - Var(Variable), - VarList(Vec<Variable>), - VarSsa(SSAVariable), - VarSsaList(Vec<SSAVariable>), -} - -#[derive(Clone, Debug, PartialEq)] -pub struct MediumLevelILLiftedInstruction { - pub function: Ref<MediumLevelILFunction>, - pub address: u64, - pub index: usize, - pub size: usize, - pub kind: MediumLevelILLiftedInstructionKind, -} - -#[derive(Clone, Debug, PartialEq)] -pub enum MediumLevelILLiftedInstructionKind { - Nop, - Noret, - Bp, - Undef, - Unimpl, - If(LiftedIf), - FloatConst(FloatConst), - Const(Constant), - ConstPtr(Constant), - Import(Constant), - ExternPtr(ExternPtr), - ConstData(LiftedConstData), - Jump(LiftedJump), - RetHint(LiftedJump), - StoreSsa(LiftedStoreSsa), - StoreStructSsa(LiftedStoreStructSsa), - StoreStruct(LiftedStoreStruct), - Store(LiftedStore), - JumpTo(LiftedJumpTo), - Goto(Goto), - FreeVarSlot(FreeVarSlot), - SetVarField(LiftedSetVarField), - SetVar(LiftedSetVar), - FreeVarSlotSsa(FreeVarSlotSsa), - SetVarSsaField(LiftedSetVarSsaField), - SetVarAliasedField(LiftedSetVarSsaField), - SetVarAliased(LiftedSetVarAliased), - SetVarSsa(LiftedSetVarSsa), - VarPhi(LiftedVarPhi), - MemPhi(LiftedMemPhi), - VarSplit(VarSplit), - SetVarSplit(LiftedSetVarSplit), - VarSplitSsa(VarSplitSsa), - SetVarSplitSsa(LiftedSetVarSplitSsa), - Add(LiftedBinaryOp), - Sub(LiftedBinaryOp), - And(LiftedBinaryOp), - Or(LiftedBinaryOp), - Xor(LiftedBinaryOp), - Lsl(LiftedBinaryOp), - Lsr(LiftedBinaryOp), - Asr(LiftedBinaryOp), - Rol(LiftedBinaryOp), - Ror(LiftedBinaryOp), - Mul(LiftedBinaryOp), - MuluDp(LiftedBinaryOp), - MulsDp(LiftedBinaryOp), - Divu(LiftedBinaryOp), - DivuDp(LiftedBinaryOp), - Divs(LiftedBinaryOp), - DivsDp(LiftedBinaryOp), - Modu(LiftedBinaryOp), - ModuDp(LiftedBinaryOp), - Mods(LiftedBinaryOp), - ModsDp(LiftedBinaryOp), - CmpE(LiftedBinaryOp), - CmpNe(LiftedBinaryOp), - CmpSlt(LiftedBinaryOp), - CmpUlt(LiftedBinaryOp), - CmpSle(LiftedBinaryOp), - CmpUle(LiftedBinaryOp), - CmpSge(LiftedBinaryOp), - CmpUge(LiftedBinaryOp), - CmpSgt(LiftedBinaryOp), - CmpUgt(LiftedBinaryOp), - TestBit(LiftedBinaryOp), - AddOverflow(LiftedBinaryOp), - FcmpE(LiftedBinaryOp), - FcmpNe(LiftedBinaryOp), - FcmpLt(LiftedBinaryOp), - FcmpLe(LiftedBinaryOp), - FcmpGe(LiftedBinaryOp), - FcmpGt(LiftedBinaryOp), - FcmpO(LiftedBinaryOp), - FcmpUo(LiftedBinaryOp), - Fadd(LiftedBinaryOp), - Fsub(LiftedBinaryOp), - Fmul(LiftedBinaryOp), - Fdiv(LiftedBinaryOp), - Adc(LiftedBinaryOpCarry), - Sbb(LiftedBinaryOpCarry), - Rlc(LiftedBinaryOpCarry), - Rrc(LiftedBinaryOpCarry), - Call(LiftedCall), - Tailcall(LiftedCall), - Intrinsic(LiftedIntrinsic), - Syscall(LiftedSyscallCall), - IntrinsicSsa(LiftedIntrinsicSsa), - CallSsa(LiftedCallSsa), - TailcallSsa(LiftedCallSsa), - CallUntypedSsa(LiftedCallUntypedSsa), - TailcallUntypedSsa(LiftedCallUntypedSsa), - SyscallSsa(LiftedSyscallSsa), - SyscallUntypedSsa(LiftedSyscallUntypedSsa), - CallUntyped(LiftedCallUntyped), - TailcallUntyped(LiftedCallUntyped), - SyscallUntyped(LiftedSyscallUntyped), - SeparateParamList(LiftedSeparateParamList), - SharedParamSlot(LiftedSharedParamSlot), - Neg(LiftedUnaryOp), - Not(LiftedUnaryOp), - Sx(LiftedUnaryOp), - Zx(LiftedUnaryOp), - LowPart(LiftedUnaryOp), - BoolToInt(LiftedUnaryOp), - UnimplMem(LiftedUnaryOp), - Fsqrt(LiftedUnaryOp), - Fneg(LiftedUnaryOp), - Fabs(LiftedUnaryOp), - FloatToInt(LiftedUnaryOp), - IntToFloat(LiftedUnaryOp), - FloatConv(LiftedUnaryOp), - RoundToInt(LiftedUnaryOp), - Floor(LiftedUnaryOp), - Ceil(LiftedUnaryOp), - Ftrunc(LiftedUnaryOp), - Load(LiftedUnaryOp), - LoadStruct(LiftedLoadStruct), - LoadStructSsa(LiftedLoadStructSsa), - LoadSsa(LiftedLoadSsa), - Ret(LiftedRet), - Var(Var), - AddressOf(Var), - VarField(Field), - AddressOfField(Field), - VarSsa(VarSsa), - VarAliased(VarSsa), - VarSsaField(VarSsaField), - VarAliasedField(VarSsaField), - Trap(Trap), -} - -impl MediumLevelILLiftedInstruction { - pub fn name(&self) -> &'static str { - use MediumLevelILLiftedInstructionKind::*; - match self.kind { - Nop => "Nop", - Noret => "Noret", - Bp => "Bp", - Undef => "Undef", - Unimpl => "Unimpl", - If(_) => "If", - FloatConst(_) => "FloatConst", - Const(_) => "Const", - ConstPtr(_) => "ConstPtr", - Import(_) => "Import", - ExternPtr(_) => "ExternPtr", - ConstData(_) => "ConstData", - Jump(_) => "Jump", - RetHint(_) => "RetHint", - StoreSsa(_) => "StoreSsa", - StoreStructSsa(_) => "StoreStructSsa", - StoreStruct(_) => "StoreStruct", - Store(_) => "Store", - JumpTo(_) => "JumpTo", - Goto(_) => "Goto", - FreeVarSlot(_) => "FreeVarSlot", - SetVarField(_) => "SetVarField", - SetVar(_) => "SetVar", - FreeVarSlotSsa(_) => "FreeVarSlotSsa", - SetVarSsaField(_) => "SetVarSsaField", - SetVarAliasedField(_) => "SetVarAliasedField", - SetVarAliased(_) => "SetVarAliased", - SetVarSsa(_) => "SetVarSsa", - VarPhi(_) => "VarPhi", - MemPhi(_) => "MemPhi", - VarSplit(_) => "VarSplit", - SetVarSplit(_) => "SetVarSplit", - VarSplitSsa(_) => "VarSplitSsa", - SetVarSplitSsa(_) => "SetVarSplitSsa", - Add(_) => "Add", - Sub(_) => "Sub", - And(_) => "And", - Or(_) => "Or", - Xor(_) => "Xor", - Lsl(_) => "Lsl", - Lsr(_) => "Lsr", - Asr(_) => "Asr", - Rol(_) => "Rol", - Ror(_) => "Ror", - Mul(_) => "Mul", - MuluDp(_) => "MuluDp", - MulsDp(_) => "MulsDp", - Divu(_) => "Divu", - DivuDp(_) => "DivuDp", - Divs(_) => "Divs", - DivsDp(_) => "DivsDp", - Modu(_) => "Modu", - ModuDp(_) => "ModuDp", - Mods(_) => "Mods", - ModsDp(_) => "ModsDp", - CmpE(_) => "CmpE", - CmpNe(_) => "CmpNe", - CmpSlt(_) => "CmpSlt", - CmpUlt(_) => "CmpUlt", - CmpSle(_) => "CmpSle", - CmpUle(_) => "CmpUle", - CmpSge(_) => "CmpSge", - CmpUge(_) => "CmpUge", - CmpSgt(_) => "CmpSgt", - CmpUgt(_) => "CmpUgt", - TestBit(_) => "TestBit", - AddOverflow(_) => "AddOverflow", - FcmpE(_) => "FcmpE", - FcmpNe(_) => "FcmpNe", - FcmpLt(_) => "FcmpLt", - FcmpLe(_) => "FcmpLe", - FcmpGe(_) => "FcmpGe", - FcmpGt(_) => "FcmpGt", - FcmpO(_) => "FcmpO", - FcmpUo(_) => "FcmpUo", - Fadd(_) => "Fadd", - Fsub(_) => "Fsub", - Fmul(_) => "Fmul", - Fdiv(_) => "Fdiv", - Adc(_) => "Adc", - Sbb(_) => "Sbb", - Rlc(_) => "Rlc", - Rrc(_) => "Rrc", - Call(_) => "Call", - Tailcall(_) => "Tailcall", - Syscall(_) => "Syscall", - Intrinsic(_) => "Intrinsic", - IntrinsicSsa(_) => "IntrinsicSsa", - CallSsa(_) => "CallSsa", - TailcallSsa(_) => "TailcallSsa", - CallUntypedSsa(_) => "CallUntypedSsa", - TailcallUntypedSsa(_) => "TailcallUntypedSsa", - SyscallSsa(_) => "SyscallSsa", - SyscallUntypedSsa(_) => "SyscallUntypedSsa", - CallUntyped(_) => "CallUntyped", - TailcallUntyped(_) => "TailcallUntyped", - SyscallUntyped(_) => "SyscallUntyped", - SeparateParamList(_) => "SeparateParamList", - SharedParamSlot(_) => "SharedParamSlot", - Neg(_) => "Neg", - Not(_) => "Not", - Sx(_) => "Sx", - Zx(_) => "Zx", - LowPart(_) => "LowPart", - BoolToInt(_) => "BoolToInt", - UnimplMem(_) => "UnimplMem", - Fsqrt(_) => "Fsqrt", - Fneg(_) => "Fneg", - Fabs(_) => "Fabs", - FloatToInt(_) => "FloatToInt", - IntToFloat(_) => "IntToFloat", - FloatConv(_) => "FloatConv", - RoundToInt(_) => "RoundToInt", - Floor(_) => "Floor", - Ceil(_) => "Ceil", - Ftrunc(_) => "Ftrunc", - Load(_) => "Load", - LoadStruct(_) => "LoadStruct", - LoadStructSsa(_) => "LoadStructSsa", - LoadSsa(_) => "LoadSsa", - Ret(_) => "Ret", - Var(_) => "Var", - AddressOf(_) => "AddressOf", - VarField(_) => "VarField", - AddressOfField(_) => "AddressOfField", - VarSsa(_) => "VarSsa", - VarAliased(_) => "VarAliased", - VarSsaField(_) => "VarSsaField", - VarAliasedField(_) => "VarAliasedField", - Trap(_) => "Trap", - } - } - - pub fn operands(&self) -> Vec<(&'static str, MediumLevelILLiftedOperand)> { - use MediumLevelILLiftedInstructionKind::*; - use MediumLevelILLiftedOperand as Operand; - match &self.kind { - Nop | Noret | Bp | Undef | Unimpl => vec![], - If(op) => vec![ - ("condition", Operand::Expr(*op.condition.clone())), - ("dest_true", Operand::Int(op.dest_true)), - ("dest_false", Operand::Int(op.dest_false)), - ], - FloatConst(op) => vec![("constant", Operand::Float(op.constant))], - Const(op) | ConstPtr(op) | Import(op) => vec![("constant", Operand::Int(op.constant))], - ExternPtr(op) => vec![ - ("constant", Operand::Int(op.constant)), - ("offset", Operand::Int(op.offset)), - ], - ConstData(op) => vec![( - "constant_data", - Operand::ConstantData(op.constant_data.clone()), - )], - Jump(op) | RetHint(op) => vec![("dest", Operand::Expr(*op.dest.clone()))], - StoreSsa(op) => vec![ - ("dest", Operand::Expr(*op.dest.clone())), - ("dest_memory", Operand::Int(op.dest_memory)), - ("src_memory", Operand::Int(op.src_memory)), - ("src", Operand::Expr(*op.src.clone())), - ], - StoreStructSsa(op) => vec![ - ("dest", Operand::Expr(*op.dest.clone())), - ("offset", Operand::Int(op.offset)), - ("dest_memory", Operand::Int(op.dest_memory)), - ("src_memory", Operand::Int(op.src_memory)), - ("src", Operand::Expr(*op.src.clone())), - ], - StoreStruct(op) => vec![ - ("dest", Operand::Expr(*op.dest.clone())), - ("offset", Operand::Int(op.offset)), - ("src", Operand::Expr(*op.src.clone())), - ], - Store(op) => vec![ - ("dest", Operand::Expr(*op.dest.clone())), - ("src", Operand::Expr(*op.src.clone())), - ], - JumpTo(op) => vec![ - ("dest", Operand::Expr(*op.dest.clone())), - ("targets", Operand::TargetMap(op.targets.clone())), - ], - Goto(op) => vec![("dest", Operand::Int(op.dest))], - FreeVarSlot(op) => vec![("dest", Operand::Var(op.dest))], - SetVarField(op) => vec![ - ("dest", Operand::Var(op.dest)), - ("offset", Operand::Int(op.offset)), - ("src", Operand::Expr(*op.src.clone())), - ], - SetVar(op) => vec![ - ("dest", Operand::Var(op.dest)), - ("src", Operand::Expr(*op.src.clone())), - ], - FreeVarSlotSsa(op) => vec![ - ("dest", Operand::VarSsa(op.dest)), - ("prev", Operand::VarSsa(op.prev)), - ], - SetVarSsaField(op) | SetVarAliasedField(op) => vec![ - ("dest", Operand::VarSsa(op.dest)), - ("prev", Operand::VarSsa(op.prev)), - ("offset", Operand::Int(op.offset)), - ("src", Operand::Expr(*op.src.clone())), - ], - SetVarAliased(op) => vec![ - ("dest", Operand::VarSsa(op.dest)), - ("prev", Operand::VarSsa(op.prev)), - ("src", Operand::Expr(*op.src.clone())), - ], - SetVarSsa(op) => vec![ - ("dest", Operand::VarSsa(op.dest)), - ("src", Operand::Expr(*op.src.clone())), - ], - VarPhi(op) => vec![ - ("dest", Operand::VarSsa(op.dest)), - ("src", Operand::VarSsaList(op.src.clone())), - ], - MemPhi(op) => vec![ - ("dest_memory", Operand::Int(op.dest_memory)), - ("src_memory", Operand::IntList(op.src_memory.clone())), - ], - VarSplit(op) => vec![ - ("high", Operand::Var(op.high)), - ("low", Operand::Var(op.low)), - ], - SetVarSplit(op) => vec![ - ("high", Operand::Var(op.high)), - ("low", Operand::Var(op.low)), - ("src", Operand::Expr(*op.src.clone())), - ], - VarSplitSsa(op) => vec![ - ("high", Operand::VarSsa(op.high)), - ("low", Operand::VarSsa(op.low)), - ], - SetVarSplitSsa(op) => vec![ - ("high", Operand::VarSsa(op.high)), - ("low", Operand::VarSsa(op.low)), - ("src", Operand::Expr(*op.src.clone())), - ], - Add(op) | Sub(op) | And(op) | Or(op) | Xor(op) | Lsl(op) | Lsr(op) | Asr(op) - | Rol(op) | Ror(op) | Mul(op) | MuluDp(op) | MulsDp(op) | Divu(op) | DivuDp(op) - | Divs(op) | DivsDp(op) | Modu(op) | ModuDp(op) | Mods(op) | ModsDp(op) | CmpE(op) - | CmpNe(op) | CmpSlt(op) | CmpUlt(op) | CmpSle(op) | CmpUle(op) | CmpSge(op) - | CmpUge(op) | CmpSgt(op) | CmpUgt(op) | TestBit(op) | AddOverflow(op) | FcmpE(op) - | FcmpNe(op) | FcmpLt(op) | FcmpLe(op) | FcmpGe(op) | FcmpGt(op) | FcmpO(op) - | FcmpUo(op) | Fadd(op) | Fsub(op) | Fmul(op) | Fdiv(op) => vec![ - ("left", Operand::Expr(*op.left.clone())), - ("right", Operand::Expr(*op.right.clone())), - ], - Adc(op) | Sbb(op) | Rlc(op) | Rrc(op) => vec![ - ("left", Operand::Expr(*op.left.clone())), - ("right", Operand::Expr(*op.right.clone())), - ("carry", Operand::Expr(*op.carry.clone())), - ], - Call(op) | Tailcall(op) => vec![ - ("output", Operand::VarList(op.output.clone())), - ("dest", Operand::Expr(*op.dest.clone())), - ("params", Operand::ExprList(op.params.clone())), - ], - Syscall(op) => vec![ - ("output", Operand::VarList(op.output.clone())), - ("params", Operand::ExprList(op.params.clone())), - ], - Intrinsic(op) => vec![ - ("output", Operand::VarList(op.output.clone())), - ("intrinsic", Operand::Intrinsic(op.intrinsic)), - ("params", Operand::ExprList(op.params.clone())), - ], - IntrinsicSsa(op) => vec![ - ("output", Operand::VarSsaList(op.output.clone())), - ("intrinsic", Operand::Intrinsic(op.intrinsic)), - ("params", Operand::ExprList(op.params.clone())), - ], - CallSsa(op) | TailcallSsa(op) => vec![ - ("output", Operand::VarSsaList(op.output.clone())), - ("dest", Operand::Expr(*op.dest.clone())), - ("params", Operand::ExprList(op.params.clone())), - ("src_memory", Operand::Int(op.src_memory)), - ], - CallUntypedSsa(op) | TailcallUntypedSsa(op) => vec![ - ("output", Operand::VarSsaList(op.output.clone())), - ("dest", Operand::Expr(*op.dest.clone())), - ("params", Operand::ExprList(op.params.clone())), - ("stack", Operand::Expr(*op.stack.clone())), - ], - SyscallSsa(op) => vec![ - ("output", Operand::VarSsaList(op.output.clone())), - ("params", Operand::ExprList(op.params.clone())), - ("src_memory", Operand::Int(op.src_memory)), - ], - SyscallUntypedSsa(op) => vec![ - ("output", Operand::VarSsaList(op.output.clone())), - ("params", Operand::ExprList(op.params.clone())), - ("stack", Operand::Expr(*op.stack.clone())), - ], - CallUntyped(op) | TailcallUntyped(op) => vec![ - ("output", Operand::VarList(op.output.clone())), - ("dest", Operand::Expr(*op.dest.clone())), - ("params", Operand::ExprList(op.params.clone())), - ("stack", Operand::Expr(*op.stack.clone())), - ], - SyscallUntyped(op) => vec![ - ("output", Operand::VarList(op.output.clone())), - ("params", Operand::ExprList(op.params.clone())), - ("stack", Operand::Expr(*op.stack.clone())), - ], - Neg(op) | Not(op) | Sx(op) | Zx(op) | LowPart(op) | BoolToInt(op) | UnimplMem(op) - | Fsqrt(op) | Fneg(op) | Fabs(op) | FloatToInt(op) | IntToFloat(op) | FloatConv(op) - | RoundToInt(op) | Floor(op) | Ceil(op) | Ftrunc(op) | Load(op) => { - vec![("src", Operand::Expr(*op.src.clone()))] - } - LoadStruct(op) => vec![ - ("src", Operand::Expr(*op.src.clone())), - ("offset", Operand::Int(op.offset)), - ], - LoadStructSsa(op) => vec![ - ("src", Operand::Expr(*op.src.clone())), - ("offset", Operand::Int(op.offset)), - ("src_memory", Operand::Int(op.src_memory)), - ], - LoadSsa(op) => vec![ - ("src", Operand::Expr(*op.src.clone())), - ("src_memory", Operand::Int(op.src_memory)), - ], - Ret(op) => vec![("src", Operand::ExprList(op.src.clone()))], - SeparateParamList(op) => vec![("params", Operand::ExprList(op.params.clone()))], - SharedParamSlot(op) => vec![("params", Operand::ExprList(op.params.clone()))], - Var(op) | AddressOf(op) => vec![("src", Operand::Var(op.src))], - VarField(op) | AddressOfField(op) => vec![ - ("src", Operand::Var(op.src)), - ("offset", Operand::Int(op.offset)), - ], - VarSsa(op) | VarAliased(op) => vec![("src", Operand::VarSsa(op.src))], - VarSsaField(op) | VarAliasedField(op) => vec![ - ("src", Operand::VarSsa(op.src)), - ("offset", Operand::Int(op.offset)), - ], - Trap(op) => vec![("vector", Operand::Int(op.vector))], - } - } -} diff --git a/rust/src/mlil/mod.rs b/rust/src/mlil/mod.rs deleted file mode 100644 index 8a9103ac..00000000 --- a/rust/src/mlil/mod.rs +++ /dev/null @@ -1,10 +0,0 @@ -mod block; -mod function; -mod instruction; -mod lift; -pub mod operation; - -pub use self::block::*; -pub use self::function::*; -pub use self::instruction::*; -pub use self::lift::*; diff --git a/rust/src/mlil/operation.rs b/rust/src/mlil/operation.rs deleted file mode 100644 index 278d1edb..00000000 --- a/rust/src/mlil/operation.rs +++ /dev/null @@ -1,581 +0,0 @@ -use std::collections::BTreeMap; - -use crate::{architecture::CoreIntrinsic, types::{ConstantData, SSAVariable, Variable}}; - -use super::MediumLevelILLiftedInstruction; - -// IF -#[derive(Copy, Clone)] -pub struct MediumLevelILOperationIf { - pub condition: usize, - pub dest_true: u64, - pub dest_false: u64, -} -#[derive(Clone, Debug, PartialEq)] -pub struct LiftedIf { - pub condition: Box<MediumLevelILLiftedInstruction>, - pub dest_true: u64, - pub dest_false: u64, -} - -// FLOAT_CONST -#[derive(Copy, Clone, Debug, PartialEq)] -pub struct FloatConst { - pub constant: f64, -} - -// CONST, CONST_PTR, IMPORT -#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)] -pub struct Constant { - pub constant: u64, -} - -// EXTERN_PTR -#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)] -pub struct ExternPtr { - pub constant: u64, - pub offset: u64, -} - -// CONST_DATA -#[derive(Copy, Clone)] -pub struct ConstData { - pub constant_data_kind: u32, - pub constant_data_value: i64, - pub size: usize, -} -#[derive(Clone, Debug, Hash, PartialEq)] -pub struct LiftedConstData { - pub constant_data: ConstantData, -} - -// JUMP, RET_HINT -#[derive(Copy, Clone)] -pub struct Jump { - pub dest: usize, -} -#[derive(Clone, Debug, PartialEq)] -pub struct LiftedJump { - pub dest: Box<MediumLevelILLiftedInstruction>, -} - -// STORE_SSA -#[derive(Copy, Clone)] -pub struct StoreSsa { - pub dest: usize, - pub dest_memory: u64, - pub src_memory: u64, - pub 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>, -} - -// STORE_STRUCT_SSA -#[derive(Copy, Clone)] -pub struct StoreStructSsa { - pub dest: usize, - pub offset: u64, - pub dest_memory: u64, - pub src_memory: u64, - pub 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>, -} - -// STORE_STRUCT -#[derive(Copy, Clone)] -pub struct StoreStruct { - pub dest: usize, - pub offset: u64, - pub src: usize, -} -#[derive(Clone, Debug, PartialEq)] -pub struct LiftedStoreStruct { - pub dest: Box<MediumLevelILLiftedInstruction>, - pub offset: u64, - pub src: Box<MediumLevelILLiftedInstruction>, -} - -// STORE -#[derive(Copy, Clone)] -pub struct Store { - pub dest: usize, - pub src: usize, -} -#[derive(Clone, Debug, PartialEq)] -pub struct LiftedStore { - pub dest: Box<MediumLevelILLiftedInstruction>, - pub src: Box<MediumLevelILLiftedInstruction>, -} - -// JUMP_TO -#[derive(Copy, Clone)] -pub struct JumpTo { - pub dest: usize, - pub first_operand: usize, - pub num_operands: usize, -} -#[derive(Clone, Debug, PartialEq)] -pub struct LiftedJumpTo { - pub dest: Box<MediumLevelILLiftedInstruction>, - pub targets: BTreeMap<u64, u64>, -} - -// GOTO -#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)] -pub struct Goto { - pub dest: u64, -} - -// FREE_VAR_SLOT -#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)] -pub struct FreeVarSlot { - pub dest: Variable, -} - -// SET_VAR_FIELD -#[derive(Copy, Clone)] -pub struct SetVarField { - pub dest: Variable, - pub offset: u64, - pub src: usize, -} -#[derive(Clone, Debug, PartialEq)] -pub struct LiftedSetVarField { - pub dest: Variable, - pub offset: u64, - pub src: Box<MediumLevelILLiftedInstruction>, -} - -// SET_VAR -#[derive(Copy, Clone)] -pub struct SetVar { - pub dest: Variable, - pub src: usize, -} -#[derive(Clone, Debug, PartialEq)] -pub struct LiftedSetVar { - pub dest: Variable, - pub src: Box<MediumLevelILLiftedInstruction>, -} - -// FREE_VAR_SLOT_SSA -#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)] -pub struct FreeVarSlotSsa { - pub dest: SSAVariable, - pub prev: SSAVariable, -} - -// SET_VAR_SSA_FIELD, SET_VAR_ALIASED_FIELD -#[derive(Copy, Clone)] -pub struct SetVarSsaField { - pub dest: SSAVariable, - pub prev: SSAVariable, - pub offset: u64, - pub src: usize, -} -#[derive(Clone, Debug, PartialEq)] -pub struct LiftedSetVarSsaField { - pub dest: SSAVariable, - pub prev: SSAVariable, - pub offset: u64, - pub src: Box<MediumLevelILLiftedInstruction>, -} - -// SET_VAR_ALIASED -#[derive(Copy, Clone)] -pub struct SetVarAliased { - pub dest: SSAVariable, - pub prev: SSAVariable, - pub src: usize, -} -#[derive(Clone, Debug, PartialEq)] -pub struct LiftedSetVarAliased { - pub dest: SSAVariable, - pub prev: SSAVariable, - pub src: Box<MediumLevelILLiftedInstruction>, -} - -// SET_VAR_SSA -#[derive(Copy, Clone)] -pub struct SetVarSsa { - pub dest: SSAVariable, - pub src: usize, -} -#[derive(Clone, Debug, PartialEq)] -pub struct LiftedSetVarSsa { - pub dest: SSAVariable, - pub src: Box<MediumLevelILLiftedInstruction>, -} - -// VAR_PHI -#[derive(Copy, Clone)] -pub struct VarPhi { - pub dest: SSAVariable, - pub first_operand: usize, - pub num_operands: usize, -} -#[derive(Clone, Debug, Hash, PartialEq, Eq)] -pub struct LiftedVarPhi { - pub dest: SSAVariable, - pub src: Vec<SSAVariable>, -} - -// MEM_PHI -#[derive(Copy, Clone)] -pub struct MemPhi { - pub dest_memory: u64, - pub first_operand: usize, - pub num_operands: usize, -} -#[derive(Clone, Debug, Hash, PartialEq, Eq)] -pub struct LiftedMemPhi { - pub dest_memory: u64, - pub src_memory: Vec<u64>, -} - -// VAR_SPLIT -#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)] -pub struct VarSplit { - pub high: Variable, - pub low: Variable, -} - -// SET_VAR_SPLIT -#[derive(Copy, Clone)] -pub struct SetVarSplit { - pub high: Variable, - pub low: Variable, - pub src: usize, -} -#[derive(Clone, Debug, PartialEq)] -pub struct LiftedSetVarSplit { - pub high: Variable, - pub low: Variable, - pub src: Box<MediumLevelILLiftedInstruction>, -} - -// VAR_SPLIT_SSA -#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)] -pub struct VarSplitSsa { - pub high: SSAVariable, - pub low: SSAVariable, -} - -// SET_VAR_SPLIT_SSA -#[derive(Copy, Clone)] -pub struct SetVarSplitSsa { - pub high: SSAVariable, - pub low: SSAVariable, - pub src: usize, -} -#[derive(Clone, Debug, PartialEq)] -pub struct LiftedSetVarSplitSsa { - pub high: SSAVariable, - pub low: SSAVariable, - pub src: Box<MediumLevelILLiftedInstruction>, -} - -// 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 { - pub left: usize, - pub right: usize, -} -#[derive(Clone, Debug, PartialEq)] -pub struct LiftedBinaryOp { - pub left: Box<MediumLevelILLiftedInstruction>, - pub right: Box<MediumLevelILLiftedInstruction>, -} - -// ADC, SBB, RLC, RRC -#[derive(Copy, Clone)] -pub struct BinaryOpCarry { - pub left: usize, - pub right: usize, - pub carry: usize, -} -#[derive(Clone, Debug, PartialEq)] -pub struct LiftedBinaryOpCarry { - pub left: Box<MediumLevelILLiftedInstruction>, - pub right: Box<MediumLevelILLiftedInstruction>, - pub carry: Box<MediumLevelILLiftedInstruction>, -} - -// CALL, TAILCALL -#[derive(Copy, Clone)] -pub struct Call { - pub first_output: usize, - pub num_outputs: usize, - pub dest: usize, - pub first_param: usize, - pub num_params: usize, -} -#[derive(Clone, Debug, PartialEq)] -pub struct LiftedCall { - pub output: Vec<Variable>, - pub dest: Box<MediumLevelILLiftedInstruction>, - pub params: Vec<MediumLevelILLiftedInstruction>, -} - -// SYSCALL -#[derive(Copy, Clone)] -pub struct Syscall { - pub first_output: usize, - pub num_outputs: usize, - pub first_param: usize, - pub num_params: usize, -} -#[derive(Clone, Debug, PartialEq)] -pub struct LiftedSyscallCall { - pub output: Vec<Variable>, - pub params: Vec<MediumLevelILLiftedInstruction>, -} - -// INTRINSIC -#[derive(Copy, Clone)] -pub struct Intrinsic { - pub first_output: usize, - pub num_outputs: usize, - pub intrinsic: u32, - pub first_param: usize, - pub num_params: usize, -} -#[derive(Clone, Debug, PartialEq)] -pub struct LiftedIntrinsic { - pub output: Vec<Variable>, - pub intrinsic: CoreIntrinsic, - pub params: Vec<MediumLevelILLiftedInstruction>, -} - -// INTRINSIC_SSA -#[derive(Copy, Clone)] -pub struct IntrinsicSsa { - pub first_output: usize, - pub num_outputs: usize, - pub intrinsic: u32, - pub first_param: usize, - pub num_params: usize, -} -#[derive(Clone, Debug, PartialEq)] -pub struct LiftedIntrinsicSsa { - pub output: Vec<SSAVariable>, - pub intrinsic: CoreIntrinsic, - pub params: Vec<MediumLevelILLiftedInstruction>, -} - -// CALL_SSA, TAILCALL_SSA -#[derive(Copy, Clone)] -pub struct CallSsa { - pub output: usize, - pub dest: usize, - pub first_param: usize, - pub num_params: usize, - pub 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, -} - -// CALL_UNTYPED_SSA, TAILCALL_UNTYPED_SSA -#[derive(Copy, Clone)] -pub struct CallUntypedSsa { - pub output: usize, - pub dest: usize, - pub params: usize, - pub stack: usize, -} -#[derive(Clone, Debug, PartialEq)] -pub struct LiftedCallUntypedSsa { - pub output: Vec<SSAVariable>, - pub dest: Box<MediumLevelILLiftedInstruction>, - pub params: Vec<MediumLevelILLiftedInstruction>, - pub stack: Box<MediumLevelILLiftedInstruction>, -} - -// SYSCALL_SSA -#[derive(Copy, Clone)] -pub struct SyscallSsa { - pub output: usize, - pub first_param: usize, - pub num_params: usize, - pub src_memory: u64, -} -#[derive(Clone, Debug, PartialEq)] -pub struct LiftedSyscallSsa { - pub output: Vec<SSAVariable>, - pub params: Vec<MediumLevelILLiftedInstruction>, - pub src_memory: u64, -} - -// SYSCALL_UNTYPED_SSA -#[derive(Copy, Clone)] -pub struct SyscallUntypedSsa { - pub output: usize, - pub params: usize, - pub stack: usize, -} -#[derive(Clone, Debug, PartialEq)] -pub struct LiftedSyscallUntypedSsa { - pub output: Vec<SSAVariable>, - pub params: Vec<MediumLevelILLiftedInstruction>, - pub stack: Box<MediumLevelILLiftedInstruction>, -} - -// CALL_UNTYPED, TAILCALL_UNTYPED -#[derive(Copy, Clone)] -pub struct CallUntyped { - pub output: usize, - pub dest: usize, - pub params: usize, - pub stack: usize, -} -#[derive(Clone, Debug, PartialEq)] -pub struct LiftedCallUntyped { - pub output: Vec<Variable>, - pub dest: Box<MediumLevelILLiftedInstruction>, - pub params: Vec<MediumLevelILLiftedInstruction>, - pub stack: Box<MediumLevelILLiftedInstruction>, -} - -// SYSCALL_UNTYPED -#[derive(Copy, Clone)] -pub struct SyscallUntyped { - pub output: usize, - pub params: usize, - pub stack: usize, -} -#[derive(Clone, Debug, PartialEq)] -pub struct LiftedSyscallUntyped { - pub output: Vec<Variable>, - pub params: Vec<MediumLevelILLiftedInstruction>, - pub stack: Box<MediumLevelILLiftedInstruction>, -} - -// 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 { - pub src: usize, -} -#[derive(Clone, Debug, PartialEq)] -pub struct LiftedUnaryOp { - pub src: Box<MediumLevelILLiftedInstruction>, -} - -// LOAD_STRUCT -#[derive(Copy, Clone)] -pub struct LoadStruct { - pub src: usize, - pub offset: u64, -} -#[derive(Clone, Debug, PartialEq)] -pub struct LiftedLoadStruct { - pub src: Box<MediumLevelILLiftedInstruction>, - pub offset: u64, -} - -// LOAD_STRUCT_SSA -#[derive(Copy, Clone)] -pub struct LoadStructSsa { - pub src: usize, - pub offset: u64, - pub src_memory: u64, -} -#[derive(Clone, Debug, PartialEq)] -pub struct LiftedLoadStructSsa { - pub src: Box<MediumLevelILLiftedInstruction>, - pub offset: u64, - pub src_memory: u64, -} - -// LOAD_SSA -#[derive(Copy, Clone)] -pub struct LoadSsa { - pub src: usize, - pub src_memory: u64, -} -#[derive(Clone, Debug, PartialEq)] -pub struct LiftedLoadSsa { - pub src: Box<MediumLevelILLiftedInstruction>, - pub src_memory: u64, -} - -// RET -#[derive(Copy, Clone)] -pub struct Ret { - pub first_operand: usize, - pub num_operands: usize, -} -#[derive(Clone, Debug, PartialEq)] -pub struct LiftedRet { - pub src: Vec<MediumLevelILLiftedInstruction>, -} - -// SEPARATE_PARAM_LIST -#[derive(Copy, Clone)] -pub struct SeparateParamList { - pub first_param: usize, - pub num_params: usize, -} -#[derive(Clone, Debug, PartialEq)] -pub struct LiftedSeparateParamList { - pub params: Vec<MediumLevelILLiftedInstruction>, -} - -// SHARED_PARAM_SLOT -#[derive(Copy, Clone)] -pub struct SharedParamSlot { - pub first_param: usize, - pub num_params: usize, -} -#[derive(Clone, Debug, PartialEq)] -pub struct LiftedSharedParamSlot { - pub params: Vec<MediumLevelILLiftedInstruction>, -} - -// VAR, ADDRESS_OF -#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)] -pub struct Var { - pub src: Variable, -} - -// VAR_FIELD, ADDRESS_OF_FIELD -#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)] -pub struct Field { - pub src: Variable, - pub offset: u64, -} - -// VAR_SSA, VAR_ALIASED -#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)] -pub struct VarSsa { - pub src: SSAVariable, -} - -// VAR_SSA_FIELD, VAR_ALIASED_FIELD -#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)] -pub struct VarSsaField { - pub src: SSAVariable, - pub offset: u64, -} - -// TRAP -#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)] -pub struct Trap { - pub vector: u64, -} |
