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/lib.rs | 171 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 171 insertions(+) create mode 100644 rust/src/lib.rs (limited to 'rust/src/lib.rs') diff --git a/rust/src/lib.rs b/rust/src/lib.rs new file mode 100644 index 00000000..68df9948 --- /dev/null +++ b/rust/src/lib.rs @@ -0,0 +1,171 @@ +#[macro_use] +extern crate log; +#[cfg(feature = "rayon")] +extern crate rayon; +extern crate libc; +extern crate binaryninjacore_sys; + +// TODO +// move some options to results +// replace `fn handle` with `AsRef` bounds +// possible values +// arch rework +// cc possible values +// bv reorg +// core fileaccessor (for bv saving) +// headless wrapper for shutdown +// platform cc + +#[macro_use] +mod ffi; + +pub mod architecture; +pub mod basicblock; +pub mod binaryview; +pub mod segment; +pub mod section; +pub mod symbol; +pub mod callingconvention; +pub mod command; +pub mod fileaccessor; +pub mod filemetadata; +pub mod function; +pub mod platform; +pub mod llil; +pub mod types; +pub mod rc; +pub mod headless; +pub mod string; +pub mod settings; + +pub use binaryninjacore_sys::BNEndianness as Endianness; +pub use binaryninjacore_sys::BNBranchType as BranchType; + +pub mod logger { + use std::os::raw::{c_void, c_char}; + + use log; + + use crate::string::BnStr; + + use binaryninjacore_sys::{BNLogListener, BNUpdateLogListeners}; + pub use binaryninjacore_sys::BNLogLevel as Level; + + struct Logger; + static LOGGER: Logger = Logger; + + impl log::Log for Logger { + fn enabled(&self, _metadata: &log::Metadata) -> bool { + true + } + + fn log(&self, record: &log::Record) { + use binaryninjacore_sys::BNLog; + use std::ffi::CString; + use self::Level::*; + use log::Level; + + let level = match record.level() { + Level::Error => ErrorLog, + Level::Warn => WarningLog, + Level::Info => InfoLog, + Level::Debug | + Level::Trace => DebugLog, + }; + + if let Ok(msg) = CString::new(format!("{}", record.args())) { + unsafe { BNLog(level, msg.as_ptr()); } + }; + } + + fn flush(&self) {} + } + + /// Uses BinaryNinja's logging functionality as the sink for + /// Rust's `log` crate. + pub fn init(filter: log::LevelFilter) -> Result<(), log::SetLoggerError> { + log::set_max_level(filter); + log::set_logger(&LOGGER) + } + + pub trait LogListener: 'static + Sync { + fn log(&self, level: Level, msg: &BnStr); + fn level(&self) -> Level; + fn close(&self) {} + } + + pub struct LogGuard { + ctxt: *mut L, + } + + impl Drop for LogGuard { + fn drop(&mut self) { + use binaryninjacore_sys::BNUnregisterLogListener; + + let mut bn_obj = BNLogListener { + context: self.ctxt as *mut _, + log: Some(cb_log::), + close: Some(cb_close::), + getLogLevel: Some(cb_level::), + }; + + unsafe { + BNUnregisterLogListener(&mut bn_obj); + BNUpdateLogListeners(); + + let _listener = Box::from_raw(self.ctxt); + } + } + } + + pub fn register_listener(listener: L) -> LogGuard { + use binaryninjacore_sys::BNRegisterLogListener; + + let raw = Box::into_raw(Box::new(listener)); + let mut bn_obj = BNLogListener { + context: raw as *mut _, + log: Some(cb_log::), + close: Some(cb_close::), + getLogLevel: Some(cb_level::), + }; + + unsafe { + BNRegisterLogListener(&mut bn_obj); + BNUpdateLogListeners(); + } + + LogGuard { + ctxt: raw, + } + } + + extern "C" fn cb_log(ctxt: *mut c_void, level: Level, msg: *const c_char) + where + L: LogListener, + { + ffi_wrap!("LogListener::log", unsafe { + let listener = &*(ctxt as *const L); + listener.log(level, BnStr::from_raw(msg)); + }) + } + + extern "C" fn cb_close(ctxt: *mut c_void) + where + L: LogListener, + { + ffi_wrap!("LogListener::close", unsafe { + let listener = &*(ctxt as *const L); + listener.close(); + }) + } + + extern "C" fn cb_level(ctxt: *mut c_void) -> Level + where + L: LogListener, + { + ffi_wrap!("LogListener::log", unsafe { + let listener = &*(ctxt as *const L); + listener.level() + }) + } +} -- cgit v1.3.1