summaryrefslogtreecommitdiff
path: root/rust/src/mlil/function.rs
diff options
context:
space:
mode:
Diffstat (limited to 'rust/src/mlil/function.rs')
-rw-r--r--rust/src/mlil/function.rs727
1 files changed, 0 insertions, 727 deletions
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()),
- }
- }
-}