diff options
| author | Ryan Snyder <ryan@vector35.com> | 2021-01-21 18:27:48 +0000 |
|---|---|---|
| committer | KyleMiles <krm504@nyu.edu> | 2021-01-21 19:06:55 +0000 |
| commit | d3140edec185f47235b9e4642bdd56d6c585a341 (patch) | |
| tree | a61859c29e4e3539daea2b761bb1439d942beaf4 /rust/src/llil/function.rs | |
| parent | c0ddbf0c76d3f1bb7a2b2024f749afc8b9482575 (diff) | |
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
Diffstat (limited to 'rust/src/llil/function.rs')
| -rw-r--r-- | rust/src/llil/function.rs | 198 |
1 files changed, 198 insertions, 0 deletions
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: NonSSAVariant>(V); + +pub trait FunctionForm: 'static {} +impl FunctionForm for SSA {} +impl<V: NonSSAVariant> FunctionForm for NonSSA<V> {} + + +pub struct Function<A: Architecture, M: FunctionMutability, F: FunctionForm> { + pub(crate) borrower: A::Handle, + pub(crate) handle: *mut BNLowLevelILFunction, + _arch: PhantomData<*mut A>, + _mutability: PhantomData<M>, + _form: PhantomData<F>, +} + +unsafe impl<A: Architecture, M: FunctionMutability, F: FunctionForm> Send for Function<A, M, F> {} +unsafe impl<A: Architecture, M: FunctionMutability, F: FunctionForm> Sync for Function<A, M, F> {} + +impl<A: Architecture, M: FunctionMutability, F: FunctionForm> Eq for Function<A, M, F> {} +impl<A: Architecture, M: FunctionMutability, F: FunctionForm> PartialEq for Function<A, M, F> { + fn eq(&self, rhs: &Self) -> bool { + self.handle == rhs.handle + } +} + +use std::hash::{Hash, Hasher}; +impl<A: Architecture, M: FunctionMutability, F: FunctionForm> Hash for Function<A, M, F> { + fn hash<H: Hasher>(&self, state: &mut H) { + self.handle.hash(state); + } +} + +impl<'func, A, M, F> Function<A, M, F> +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<L: Into<Location>>(&self, loc: L) -> Option<Instruction<A, M, F>> { + 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<A, M, F> { + 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<A, Finalized, F> +where + A: 'func + Architecture, + F: FunctionForm +{ + pub fn basic_blocks(&self) -> Array<BasicBlock<LowLevelBlock<A, Finalized, F>>> { + 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<A, M, F> +where + A: 'func + Architecture, + M: FunctionMutability, + F: FunctionForm +{ + type Owned = Ref<Self>; + + fn to_owned(&self) -> Self::Owned { + unsafe { RefCountable::inc_ref(self) } + } +} + + +unsafe impl<'func, A, M, F> RefCountable for Function<A, M, F> +where + A: 'func + Architecture, + M: FunctionMutability, + F: FunctionForm +{ + unsafe fn inc_ref(handle: &Self) -> Ref<Self> { + 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<A, M, F> +where + A: 'func + Architecture, + M: FunctionMutability, + F: FunctionForm, +{ + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "<llil func handle {:p}>", self.handle) + } +} |
