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/command.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/command.rs')
| -rw-r--r-- | rust/src/command.rs | 263 |
1 files changed, 263 insertions, 0 deletions
diff --git a/rust/src/command.rs b/rust/src/command.rs new file mode 100644 index 00000000..70839f6b --- /dev/null +++ b/rust/src/command.rs @@ -0,0 +1,263 @@ +use binaryninjacore_sys::{BNRegisterPluginCommand, + BNRegisterPluginCommandForAddress, + BNRegisterPluginCommandForRange, + BNRegisterPluginCommandForFunction, + BNBinaryView, + BNFunction}; + +use std::ops::Range; +use std::os::raw::c_void; + +use crate::binaryview::BinaryView; +use crate::function::Function; +use crate::string::BnStrCompatible; + +pub trait Command: 'static + Sync { + fn action(&self, view: &BinaryView); + fn valid(&self, view: &BinaryView) -> bool; +} + +impl<T> Command for T +where + T: 'static + Sync + Fn(&BinaryView), +{ + fn action(&self, view: &BinaryView) { + self(view); + } + + fn valid(&self, _view: &BinaryView) -> bool { + true + } +} + +pub fn register<S, C>(name: S, desc: S, command: C) +where + S: BnStrCompatible, + C: Command, +{ + extern "C" fn cb_action<C>(ctxt: *mut c_void, view: *mut BNBinaryView) + where + C: Command, + { + ffi_wrap!("Command::action", unsafe { + let cmd = &*(ctxt as *const C); + let view = BinaryView::from_raw(view); + + cmd.action(&view); + }) + } + + extern "C" fn cb_valid<C>(ctxt: *mut c_void, view: *mut BNBinaryView) -> bool + where + C: Command, + { + ffi_wrap!("Command::valid", unsafe { + let cmd = &*(ctxt as *const C); + let view = BinaryView::from_raw(view); + + cmd.valid(&view) + }) + } + + let name = name.as_bytes_with_nul(); + let desc = desc.as_bytes_with_nul(); + + let name_ptr = name.as_ref().as_ptr() as *mut _; + let desc_ptr = desc.as_ref().as_ptr() as *mut _; + + let ctxt = Box::into_raw(Box::new(command)); + + unsafe { + BNRegisterPluginCommand(name_ptr, desc_ptr, + Some(cb_action::<C>), Some(cb_valid::<C>), + ctxt as *mut _); + } +} + +pub trait AddressCommand: 'static + Sync { + fn action(&self, view: &BinaryView, addr: u64); + fn valid(&self, view: &BinaryView, addr: u64) -> bool; +} + +impl<T> AddressCommand for T +where + T: 'static + Sync + Fn(&BinaryView, u64), +{ + fn action(&self, view: &BinaryView, addr: u64) { + self(view, addr); + } + + fn valid(&self, _view: &BinaryView, _addr: u64) -> bool { + true + } +} + +pub fn register_for_address<S, C>(name: S, desc: S, command: C) +where + S: BnStrCompatible, + C: AddressCommand, +{ + extern "C" fn cb_action<C>(ctxt: *mut c_void, view: *mut BNBinaryView, addr: u64) + where + C: AddressCommand, + { + ffi_wrap!("AddressCommand::action", unsafe { + let cmd = &*(ctxt as *const C); + let view = BinaryView::from_raw(view); + + cmd.action(&view, addr); + }) + } + + extern "C" fn cb_valid<C>(ctxt: *mut c_void, view: *mut BNBinaryView, addr: u64) -> bool + where + C: AddressCommand, + { + ffi_wrap!("AddressCommand::valid", unsafe { + let cmd = &*(ctxt as *const C); + let view = BinaryView::from_raw(view); + + cmd.valid(&view, addr) + }) + } + + let name = name.as_bytes_with_nul(); + let desc = desc.as_bytes_with_nul(); + + let name_ptr = name.as_ref().as_ptr() as *mut _; + let desc_ptr = desc.as_ref().as_ptr() as *mut _; + + let ctxt = Box::into_raw(Box::new(command)); + + unsafe { + BNRegisterPluginCommandForAddress(name_ptr, desc_ptr, + Some(cb_action::<C>), Some(cb_valid::<C>), + ctxt as *mut _); + } +} + +pub trait RangeCommand: 'static + Sync { + fn action(&self, view: &BinaryView, range: Range<u64>); + fn valid(&self, view: &BinaryView, range: Range<u64>) -> bool; +} + +impl<T> RangeCommand for T +where + T: 'static + Sync + Fn(&BinaryView, Range<u64>), +{ + fn action(&self, view: &BinaryView, range: Range<u64>) { + self(view, range); + } + + fn valid(&self, _view: &BinaryView, _range: Range<u64>) -> bool { + true + } +} + +pub fn register_for_range<S, C>(name: S, desc: S, command: C) +where + S: BnStrCompatible, + C: RangeCommand, +{ + extern "C" fn cb_action<C>(ctxt: *mut c_void, view: *mut BNBinaryView, addr: u64, len: u64) + where + C: RangeCommand, + { + ffi_wrap!("RangeCommand::action", unsafe { + let cmd = &*(ctxt as *const C); + let view = BinaryView::from_raw(view); + + cmd.action(&view, addr .. addr.wrapping_add(len)); + }) + } + + extern "C" fn cb_valid<C>(ctxt: *mut c_void, view: *mut BNBinaryView, addr: u64, len: u64) -> bool + where + C: RangeCommand, + { + ffi_wrap!("RangeCommand::valid", unsafe { + let cmd = &*(ctxt as *const C); + let view = BinaryView::from_raw(view); + + cmd.valid(&view, addr .. addr.wrapping_add(len)) + }) + } + + let name = name.as_bytes_with_nul(); + let desc = desc.as_bytes_with_nul(); + + let name_ptr = name.as_ref().as_ptr() as *mut _; + let desc_ptr = desc.as_ref().as_ptr() as *mut _; + + let ctxt = Box::into_raw(Box::new(command)); + + unsafe { + BNRegisterPluginCommandForRange(name_ptr, desc_ptr, + Some(cb_action::<C>), Some(cb_valid::<C>), + ctxt as *mut _); + } +} + +pub trait FunctionCommand: 'static + Sync { + fn action(&self, view: &BinaryView, func: &Function); + fn valid(&self, view: &BinaryView, func: &Function) -> bool; +} + +impl<T> FunctionCommand for T +where + T: 'static + Sync + Fn(&BinaryView, &Function), +{ + fn action(&self, view: &BinaryView, func: &Function) { + self(view, func); + } + + fn valid(&self, _view: &BinaryView, _func: &Function) -> bool { + true + } +} + +pub fn register_for_function<S, C>(name: S, desc: S, command: C) +where + S: BnStrCompatible, + C: FunctionCommand, +{ + extern "C" fn cb_action<C>(ctxt: *mut c_void, view: *mut BNBinaryView, func: *mut BNFunction) + where + C: FunctionCommand, + { + ffi_wrap!("FunctionCommand::action", unsafe { + let cmd = &*(ctxt as *const C); + let view = BinaryView::from_raw(view); + let func = Function::from_raw(func); + + cmd.action(&view, &func); + }) + } + + extern "C" fn cb_valid<C>(ctxt: *mut c_void, view: *mut BNBinaryView, func: *mut BNFunction) -> bool + where + C: FunctionCommand, + { + ffi_wrap!("FunctionCommand::valid", unsafe { + let cmd = &*(ctxt as *const C); + let view = BinaryView::from_raw(view); + let func = Function::from_raw(func); + + cmd.valid(&view, &func) + }) + } + + let name = name.as_bytes_with_nul(); + let desc = desc.as_bytes_with_nul(); + + let name_ptr = name.as_ref().as_ptr() as *mut _; + let desc_ptr = desc.as_ref().as_ptr() as *mut _; + + let ctxt = Box::into_raw(Box::new(command)); + + unsafe { + BNRegisterPluginCommandForFunction(name_ptr, desc_ptr, + Some(cb_action::<C>), Some(cb_valid::<C>), + ctxt as *mut _); + } +} |
