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/command.rs | 263 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 263 insertions(+) create mode 100644 rust/src/command.rs (limited to 'rust/src/command.rs') 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 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(name: S, desc: S, command: C) +where + S: BnStrCompatible, + C: Command, +{ + extern "C" fn cb_action(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(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::), Some(cb_valid::), + ctxt as *mut _); + } +} + +pub trait AddressCommand: 'static + Sync { + fn action(&self, view: &BinaryView, addr: u64); + fn valid(&self, view: &BinaryView, addr: u64) -> bool; +} + +impl 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(name: S, desc: S, command: C) +where + S: BnStrCompatible, + C: AddressCommand, +{ + extern "C" fn cb_action(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(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::), Some(cb_valid::), + ctxt as *mut _); + } +} + +pub trait RangeCommand: 'static + Sync { + fn action(&self, view: &BinaryView, range: Range); + fn valid(&self, view: &BinaryView, range: Range) -> bool; +} + +impl RangeCommand for T +where + T: 'static + Sync + Fn(&BinaryView, Range), +{ + fn action(&self, view: &BinaryView, range: Range) { + self(view, range); + } + + fn valid(&self, _view: &BinaryView, _range: Range) -> bool { + true + } +} + +pub fn register_for_range(name: S, desc: S, command: C) +where + S: BnStrCompatible, + C: RangeCommand, +{ + extern "C" fn cb_action(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(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::), Some(cb_valid::), + ctxt as *mut _); + } +} + +pub trait FunctionCommand: 'static + Sync { + fn action(&self, view: &BinaryView, func: &Function); + fn valid(&self, view: &BinaryView, func: &Function) -> bool; +} + +impl 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(name: S, desc: S, command: C) +where + S: BnStrCompatible, + C: FunctionCommand, +{ + extern "C" fn cb_action(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(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::), Some(cb_valid::), + ctxt as *mut _); + } +} -- cgit v1.3.1