summaryrefslogtreecommitdiff
path: root/rust/src/command.rs
diff options
context:
space:
mode:
authorRyan Snyder <ryan@vector35.com>2021-01-21 18:27:48 +0000
committerKyleMiles <krm504@nyu.edu>2021-01-21 19:06:55 +0000
commitd3140edec185f47235b9e4642bdd56d6c585a341 (patch)
treea61859c29e4e3539daea2b761bb1439d942beaf4 /rust/src/command.rs
parentc0ddbf0c76d3f1bb7a2b2024f749afc8b9482575 (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.rs263
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 _);
+ }
+}