Skip to content

Commit

Permalink
add MediumLevelILFunction::{var_refs, var_refs_from} methods
Browse files Browse the repository at this point in the history
  • Loading branch information
rbran committed May 10, 2024
1 parent de34135 commit 93a8f87
Show file tree
Hide file tree
Showing 3 changed files with 174 additions and 4 deletions.
5 changes: 3 additions & 2 deletions rust/src/function.rs
Original file line number Diff line number Diff line change
Expand Up @@ -226,13 +226,14 @@ impl Function {
/// ```no_run
/// # use binaryninja::function::Function;
/// # let fun: Function = todo!();
/// let blocks = fun.basic_block_containing(0x1000);
/// let blocks = fun.basic_block_containing(0x1000, None);
/// ```
pub fn basic_block_containing(
&self,
arch: &CoreArchitecture,
addr: u64,
arch: Option<CoreArchitecture>,
) -> Option<Ref<BasicBlock<NativeBlock>>> {
let arch = arch.unwrap_or_else(|| self.arch());
unsafe {
let block = BNGetFunctionBasicBlockAtAddress(self.handle, arch.0, addr);
let context = NativeBlock { _priv: () };
Expand Down
172 changes: 171 additions & 1 deletion rust/src/mlil/function.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,12 @@ use core::hash::{Hash, Hasher};

use binaryninjacore_sys::*;

use crate::architecture::CoreArchitecture;
use crate::basicblock::BasicBlock;
use crate::function::{Function, Location};
use crate::rc::{Array, Ref, RefCountable};
use crate::rc::{
Array, CoreArrayProvider, CoreArrayWrapper, CoreOwnedArrayProvider, Ref, RefCountable,
};
use crate::string::BnStrCompatible;
use crate::types::{Conf, PossibleValueSet, Type, UserVariableValues, Variable};

Expand Down Expand Up @@ -299,6 +302,76 @@ impl MediumLevelILFunction {
)
}
}

/// 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()) }
}
}

impl ToOwned for MediumLevelILFunction {
Expand Down Expand Up @@ -360,3 +433,100 @@ impl DoubleEndedIterator for VariableDefinitions<'_> {

impl ExactSizeIterator for VariableDefinitions<'_> {}
impl core::iter::FusedIterator for VariableDefinitions<'_> {}

/////////////////////////
// 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>;
}

unsafe impl CoreOwnedArrayProvider for ILReferenceSource {
unsafe fn free(raw: *mut Self::Raw, count: usize, _context: &Self::Context) {
BNFreeILReferences(raw, count)
}
}

unsafe impl CoreArrayWrapper for ILReferenceSource {
type Wrapped<'a> = Self;

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>;
}

unsafe impl CoreOwnedArrayProvider for VariableReferenceSource {
unsafe fn free(raw: *mut Self::Raw, count: usize, _context: &Self::Context) {
BNFreeVariableReferenceSourceList(raw, count)
}
}

unsafe impl CoreArrayWrapper for VariableReferenceSource {
type Wrapped<'a> = Self;

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()),
}
}
}
1 change: 0 additions & 1 deletion rust/src/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3434,7 +3434,6 @@ impl HighlightColor {
}
}


/////////////////////////
// IntegerDisplayType

Expand Down

0 comments on commit 93a8f87

Please sign in to comment.