From d3140edec185f47235b9e4642bdd56d6c585a341 Mon Sep 17 00:00:00 2001 From: Ryan Snyder Date: Thu, 21 Jan 2021 18:27:48 +0000 Subject: This is a combination of 23 commits, the work of Ryan Snyder: Initial fresh repo Add support for recent calling convention API updates and folds the binaryninjacore-sys crate directly into this one. Add support for auto function analysis suppression Finish moving binaryninjacore-sys back into this crate Update for Symbol/Segment core API changes Update for Symbol API cleanup api: advance submodule reference, support Token changes arch/lifting: support for flags in custom architectures arch/lifting: support default flag write behaviors, handle more ops build: enable headless binary support on MacOS via evil hack bv: add BinaryView wrapper support, remove wrong comment api: update to latest binja dev branch support deps: bump dep versions rust: bump to 2018 edition api: bump to avoid cargo submodule brokenness build: improve binaryninja path detection; enable linux linkhack bv: stub for bv load settings arch: fix flag related crash, minor llil update api: update for recent changes macos: disable linkhack briefly --- rust/src/llil/function.rs | 198 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 198 insertions(+) create mode 100644 rust/src/llil/function.rs (limited to 'rust/src/llil/function.rs') diff --git a/rust/src/llil/function.rs b/rust/src/llil/function.rs new file mode 100644 index 00000000..ac50e72c --- /dev/null +++ b/rust/src/llil/function.rs @@ -0,0 +1,198 @@ +use binaryninjacore_sys::BNLowLevelILFunction; +use binaryninjacore_sys::BNNewLowLevelILFunctionReference; +use binaryninjacore_sys::BNFreeLowLevelILFunction; + +use std::borrow::Borrow; +use std::marker::PhantomData; + +use crate::basicblock::BasicBlock; +use crate::rc::*; + +use super::*; + +#[derive(Copy, Clone, Debug)] +pub struct Mutable; +#[derive(Copy, Clone, Debug)] +pub struct Finalized; + +pub trait FunctionMutability: 'static {} +impl FunctionMutability for Mutable {} +impl FunctionMutability for Finalized {} + + +#[derive(Copy, Clone, Debug)] +pub struct LiftedNonSSA; +#[derive(Copy, Clone, Debug)] +pub struct RegularNonSSA; + +pub trait NonSSAVariant: 'static {} +impl NonSSAVariant for LiftedNonSSA {} +impl NonSSAVariant for RegularNonSSA {} + +#[derive(Copy, Clone, Debug)] +pub struct SSA; +#[derive(Copy, Clone, Debug)] +pub struct NonSSA(V); + +pub trait FunctionForm: 'static {} +impl FunctionForm for SSA {} +impl FunctionForm for NonSSA {} + + +pub struct Function { + pub(crate) borrower: A::Handle, + pub(crate) handle: *mut BNLowLevelILFunction, + _arch: PhantomData<*mut A>, + _mutability: PhantomData, + _form: PhantomData, +} + +unsafe impl Send for Function {} +unsafe impl Sync for Function {} + +impl Eq for Function {} +impl PartialEq for Function { + fn eq(&self, rhs: &Self) -> bool { + self.handle == rhs.handle + } +} + +use std::hash::{Hash, Hasher}; +impl Hash for Function { + fn hash(&self, state: &mut H) { + self.handle.hash(state); + } +} + +impl<'func, A, M, F> Function +where + A: 'func + Architecture, + M: FunctionMutability, + F: FunctionForm +{ + pub(crate) unsafe fn from_raw(borrower: A::Handle, handle: *mut BNLowLevelILFunction) -> Self { + debug_assert!(!handle.is_null()); + + Self { + borrower, + handle, + _arch: PhantomData, + _mutability: PhantomData, + _form: PhantomData, + } + } + + pub(crate) fn arch(&self) -> &A { + self.borrower.borrow() + } + + pub fn instruction_at>(&self, loc: L) -> Option> { + use binaryninjacore_sys::BNLowLevelILGetInstructionStart; + use binaryninjacore_sys::BNGetLowLevelILInstructionCount; + + let loc: Location = loc.into(); + let arch_handle = loc.arch.unwrap_or_else(|| *self.arch().as_ref()); + + unsafe { + let instr_idx = BNLowLevelILGetInstructionStart(self.handle, arch_handle.0, loc.addr); + + if instr_idx >= BNGetLowLevelILInstructionCount(self.handle) { + None + } else { + Some(Instruction { + function: self, + instr_idx: instr_idx, + }) + } + } + } + + pub fn instruction_from_idx(&self, instr_idx: usize) -> Instruction { + unsafe { + use binaryninjacore_sys::BNGetLowLevelILInstructionCount; + if instr_idx >= BNGetLowLevelILInstructionCount(self.handle) { + panic!("instruction index {} out of bounds", instr_idx); + } + + Instruction { + function: self, + instr_idx: instr_idx, + } + } + } + + pub fn instruction_count(&self) -> usize { + unsafe { + use binaryninjacore_sys::BNGetLowLevelILInstructionCount; + BNGetLowLevelILInstructionCount(self.handle) + } + } + +} + +// LLIL basic blocks are not available until the function object +// is finalized, so ensure we can't try requesting basic blocks +// during lifting +impl<'func, A, F> Function +where + A: 'func + Architecture, + F: FunctionForm +{ + pub fn basic_blocks(&self) -> Array>> { + use binaryninjacore_sys::BNGetLowLevelILBasicBlockList; + + unsafe { + let mut count = 0; + let blocks = BNGetLowLevelILBasicBlockList(self.handle, &mut count); + let context = LowLevelBlock { function: self }; + + Array::new(blocks, count, context) + } + } +} + +impl<'func, A, M, F> ToOwned for Function +where + A: 'func + Architecture, + M: FunctionMutability, + F: FunctionForm +{ + type Owned = Ref; + + fn to_owned(&self) -> Self::Owned { + unsafe { RefCountable::inc_ref(self) } + } +} + + +unsafe impl<'func, A, M, F> RefCountable for Function +where + A: 'func + Architecture, + M: FunctionMutability, + F: FunctionForm +{ + unsafe fn inc_ref(handle: &Self) -> Ref { + Ref::new(Self { + borrower: handle.borrower.clone(), + handle: BNNewLowLevelILFunctionReference(handle.handle), + _arch: PhantomData, + _mutability: PhantomData, + _form: PhantomData, + }) + } + + unsafe fn dec_ref(handle: &Self) { + BNFreeLowLevelILFunction(handle.handle); + } +} + +impl<'func, A, M, F> fmt::Debug for Function +where + A: 'func + Architecture, + M: FunctionMutability, + F: FunctionForm, +{ + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "", self.handle) + } +} -- cgit v1.3.1