diff options
| author | KyleMiles <krm504@nyu.edu> | 2023-12-05 13:05:44 -0500 |
|---|---|---|
| committer | KyleMiles <krm504@nyu.edu> | 2023-12-05 13:05:44 -0500 |
| commit | ae144062dbdb047b924c2071a37a8154864cb07b (patch) | |
| tree | bd4237b33e29dde60ae49ea60cef3e7d4a4abe54 /rust | |
| parent | b02b6584f7da7d22c82f7d9839f55ea38e51de95 (diff) | |
Resolves #3714: Adds core initialization/shutdown wrapper object (to the Rust API) that you can initialize at the top of your script and it'll auto-cleanup at the end of your script. Also some misc doc fixes.
Diffstat (limited to 'rust')
| -rw-r--r-- | rust/README.md | 5 | ||||
| -rw-r--r-- | rust/examples/basic_script/src/main.rs | 9 | ||||
| -rw-r--r-- | rust/examples/mlil_lifter/src/main.rs | 5 | ||||
| -rw-r--r-- | rust/examples/mlil_visitor/src/main.rs | 5 | ||||
| -rw-r--r-- | rust/examples/template/src/main.rs | 9 | ||||
| -rw-r--r-- | rust/src/headless.rs | 56 | ||||
| -rw-r--r-- | rust/src/lib.rs | 13 |
7 files changed, 75 insertions, 27 deletions
diff --git a/rust/README.md b/rust/README.md index 120af814..d2f7f1cc 100644 --- a/rust/README.md +++ b/rust/README.md @@ -46,10 +46,13 @@ See the `./examples/`. Plugin registration commands are in `binaryninja::comman binaryninja = { git = "https://github.com/Vector35/binaryninja-api.git", branch = "dev"} ``` -All standalone binaries should call both `binaryninja::headless::init()` and `binaryninja::headless::shutdown()`. All standalone binaries need to provide a `build.rs`. See [`examples/template`](examples/template) for details. +## Docs + +Docs can be found at https://dev-rust.binary.ninja/ + --- #### Attribution diff --git a/rust/examples/basic_script/src/main.rs b/rust/examples/basic_script/src/main.rs index 85187747..b979c156 100644 --- a/rust/examples/basic_script/src/main.rs +++ b/rust/examples/basic_script/src/main.rs @@ -3,10 +3,12 @@ use binaryninja::binaryview::{BinaryViewBase, BinaryViewExt}; fn main() { println!("Loading plugins..."); // This loads all the core architecture, platform, etc plugins - binaryninja::headless::init(); + let headless_session = binaryninja::headless::Session::new(); println!("Loading binary..."); - let bv = binaryninja::load("/bin/cat").expect("Couldn't open `/bin/cat`"); + let bv = headless_session + .load("/bin/cat") + .expect("Couldn't open `/bin/cat`"); println!("Filename: `{}`", bv.file().filename()); println!("File size: `{:#x}`", bv.len()); @@ -32,7 +34,4 @@ fn main() { } } } - - // Important! You need to call shutdown or your script will hang forever - binaryninja::headless::shutdown(); } diff --git a/rust/examples/mlil_lifter/src/main.rs b/rust/examples/mlil_lifter/src/main.rs index 3ba25630..b827e0cb 100644 --- a/rust/examples/mlil_lifter/src/main.rs +++ b/rust/examples/mlil_lifter/src/main.rs @@ -14,7 +14,7 @@ fn main() { // This loads all the core architecture, platform, etc plugins // Standalone executables probably need to call this, but plugins do not println!("Loading plugins..."); - binaryninja::headless::init(); + let _headless_session = binaryninja::headless::Session::new(); // Your code here... println!("Loading binary..."); @@ -46,7 +46,4 @@ fn main() { } println!(); } - - // Important! Standalone executables need to call shutdown or they will hang forever - binaryninja::headless::shutdown(); } diff --git a/rust/examples/mlil_visitor/src/main.rs b/rust/examples/mlil_visitor/src/main.rs index 3f75708c..f83a7eac 100644 --- a/rust/examples/mlil_visitor/src/main.rs +++ b/rust/examples/mlil_visitor/src/main.rs @@ -235,7 +235,7 @@ fn main() { // This loads all the core architecture, platform, etc plugins // Standalone executables probably need to call this, but plugins do not println!("Loading plugins..."); - binaryninja::headless::init(); + let _headless_session = binaryninja::headless::Session::new(); // Your code here... println!("Loading binary..."); @@ -261,7 +261,4 @@ fn main() { } println!(); } - - // Important! Standalone executables need to call shutdown or they will hang forever - binaryninja::headless::shutdown(); } diff --git a/rust/examples/template/src/main.rs b/rust/examples/template/src/main.rs index 20e082f2..5b21efb3 100644 --- a/rust/examples/template/src/main.rs +++ b/rust/examples/template/src/main.rs @@ -7,11 +7,13 @@ fn main() { // This loads all the core architecture, platform, etc plugins // Standalone executables probably need to call this, but plugins do not println!("Loading plugins..."); - binaryninja::headless::init(); + let headless_session = binaryninja::headless::Session::new(); // Your code here... println!("Loading binary..."); - let bv = binaryninja::load("/bin/cat").expect("Couldn't open `/bin/cat`"); + let bv = headless_session + .load("/bin/cat") + .expect("Couldn't open `/bin/cat`"); println!("Filename: `{}`", bv.file().filename()); println!("File size: `{:#x}`", bv.len()); @@ -37,7 +39,4 @@ fn main() { } } } - - // Important! Standalone executables need to call shutdown or they will hang forever - binaryninja::headless::shutdown(); } diff --git a/rust/src/headless.rs b/rust/src/headless.rs index c5e14eb0..2d3dec6d 100644 --- a/rust/src/headless.rs +++ b/rust/src/headless.rs @@ -12,7 +12,12 @@ // See the License for the specific language governing permissions and // limitations under the License. -use crate::string::BnStrCompatible; +use crate::{ + binaryview, + metadata::Metadata, + rc::{self, Ref}, + string::BnStrCompatible, +}; use std::env; use std::path::PathBuf; @@ -70,6 +75,8 @@ use binaryninjacore_sys::{BNInitPlugins, BNInitRepoPlugins, BNSetBundledPluginDi /// Loads plugins, core architecture, platform, etc. /// /// ⚠️ Important! Must be called at the beginning of scripts. Plugins do not need to call this. ⚠️ +/// +/// You can instead call this through [`Session`] or [`script_helper`] pub fn init() { unsafe { let path = binja_path().join("plugins").into_os_string(); @@ -102,3 +109,50 @@ pub fn script_helper(func: fn()) { func(); shutdown(); } + +/// Wrapper for [`init`] and [`shutdown`]. Instantiating this at the top of your script will initialize everything correctly and then clean itself up at exit as well. +pub struct Session {} + +impl Session { + pub fn new() -> Self { + init(); + Self {} + } + + /// ```rust + /// let headless_session = binaryninja::headless::Session::new(); + /// + /// let bv = headless_session.load("/bin/cat").expect("Couldn't open `/bin/cat`"); + /// ``` + pub fn load(&self, filename: &str) -> Option<rc::Ref<binaryview::BinaryView>> { + crate::load(filename) + } + + /// ```rust + /// let settings = [("analysis.linearSweep.autorun", false)].into(); + /// let headless_session = binaryninja::headless::Session::new(); + /// + /// let bv = headless_session.load_with_options("/bin/cat", true, Some(settings)) + /// .expect("Couldn't open `/bin/cat`"); + /// ``` + pub fn load_with_options( + &self, + filename: &str, + update_analysis_and_wait: bool, + options: Option<Ref<Metadata>>, + ) -> Option<rc::Ref<binaryview::BinaryView>> { + crate::load_with_options(filename, update_analysis_and_wait, options) + } +} + +impl Default for Session { + fn default() -> Self { + Self::new() + } +} + +impl Drop for Session { + fn drop(&mut self) { + shutdown() + } +} diff --git a/rust/src/lib.rs b/rust/src/lib.rs index 3eff5ea1..d6161d53 100644 --- a/rust/src/lib.rs +++ b/rust/src/lib.rs @@ -72,20 +72,17 @@ //! The most up-to-date version of the suggested [`build.rs` is here]. //! //! ### `main.rs` -//! All standalone binaries need to call [`headless::init()`] at start and [`headless::shutdown()`] at shutdown. +//! Standalone binaries need to initialize Binary Ninja before they can work. You can do this through [`headless::Session`], [`headless::script_helper`], or [`headless::init()`] at start and [`headless::shutdown()`] at shutdown. //! ```rust //! fn main() { //! // This loads all the core architecture, platform, etc plugins //! // Standalone executables need to call this, but plugins do not -//! binaryninja::headless::init(); +//! let headless_session = binaryninja::headless::Session::new(); //! //! println!("Loading binary..."); -//! let bv = binaryninja::load("/bin/cat").expect("Couldn't open `/bin/cat`"); +//! let bv = headless_session.load("/bin/cat").expect("Couldn't open `/bin/cat`"); //! //! // Your code here... -//! -//! // Important! Standalone executables need to call shutdown or they will hang forever -//! binaryninja::headless::shutdown(); //! } //! ``` //! @@ -123,7 +120,6 @@ extern crate rayon; // cc possible values // bv reorg // core fileaccessor (for bv saving) -// headless wrapper for shutdown // platform cc #[macro_use] @@ -196,6 +192,7 @@ use string::BnStrCompatible; const BN_FULL_CONFIDENCE: u8 = 255; const BN_INVALID_EXPR: usize = usize::MAX; +/// The main way to open and load files into Binary Ninja. Make sure you've properly initialized the core before calling this function. See [`crate::headless::init()`] pub fn load<S: BnStrCompatible>(filename: S) -> Option<rc::Ref<binaryview::BinaryView>> { let filename = filename.into_bytes_with_nul(); let metadata = Metadata::new_of_type(MetadataType::KeyValueDataType); @@ -216,6 +213,8 @@ pub fn load<S: BnStrCompatible>(filename: S) -> Option<rc::Ref<binaryview::Binar } } +/// The main way to open and load files (with options) into Binary Ninja. Make sure you've properly initialized the core before calling this function. See [`crate::headless::init()`] +/// /// ```rust /// let settings = [("analysis.linearSweep.autorun", false)].into(); /// |
