diff options
| author | KyleMiles <krm504@nyu.edu> | 2023-06-29 20:49:26 -0400 |
|---|---|---|
| committer | KyleMiles <krm504@nyu.edu> | 2023-07-10 12:58:24 -0400 |
| commit | 04bc6f11ae0289aae57d63d4cd32f4ef305d1a7a (patch) | |
| tree | 46f06280b13fb80f2aebf0eea9b52f884e698d0c /rust | |
| parent | 7598688466960427890036590239565364310171 (diff) | |
Move binary view loading in to the core; deprecate open_view in favor of load; update examples
Diffstat (limited to 'rust')
| -rw-r--r-- | rust/examples/basic_script/src/main.rs | 2 | ||||
| -rw-r--r-- | rust/examples/decompile/src/main.rs | 2 | ||||
| -rw-r--r-- | rust/examples/template/src/main.rs | 2 | ||||
| -rw-r--r-- | rust/src/headless.rs | 2 | ||||
| -rw-r--r-- | rust/src/lib.rs | 222 | ||||
| -rw-r--r-- | rust/src/metadata.rs | 72 |
6 files changed, 114 insertions, 188 deletions
diff --git a/rust/examples/basic_script/src/main.rs b/rust/examples/basic_script/src/main.rs index e535f15f..85187747 100644 --- a/rust/examples/basic_script/src/main.rs +++ b/rust/examples/basic_script/src/main.rs @@ -6,7 +6,7 @@ fn main() { binaryninja::headless::init(); println!("Loading binary..."); - let bv = binaryninja::open_view("/bin/cat").expect("Couldn't open `/bin/cat`"); + let bv = binaryninja::load("/bin/cat").expect("Couldn't open `/bin/cat`"); println!("Filename: `{}`", bv.file().filename()); println!("File size: `{:#x}`", bv.len()); diff --git a/rust/examples/decompile/src/main.rs b/rust/examples/decompile/src/main.rs index acd3e28b..0865538d 100644 --- a/rust/examples/decompile/src/main.rs +++ b/rust/examples/decompile/src/main.rs @@ -40,7 +40,7 @@ fn main() { binaryninja::headless::init(); eprintln!("Loading binary..."); - let bv = binaryninja::open_view(args.filename).expect("Couldn't open file"); + let bv = binaryninja::load(args.filename).expect("Couldn't open file"); eprintln!("Filename: `{}`", bv.file().filename()); eprintln!("File size: `{:#x}`", bv.len()); diff --git a/rust/examples/template/src/main.rs b/rust/examples/template/src/main.rs index 0c27b6d2..20e082f2 100644 --- a/rust/examples/template/src/main.rs +++ b/rust/examples/template/src/main.rs @@ -11,7 +11,7 @@ fn main() { // Your code here... println!("Loading binary..."); - let bv = binaryninja::open_view("/bin/cat").expect("Couldn't open `/bin/cat`"); + let bv = binaryninja::load("/bin/cat").expect("Couldn't open `/bin/cat`"); println!("Filename: `{}`", bv.file().filename()); println!("File size: `{:#x}`", bv.len()); diff --git a/rust/src/headless.rs b/rust/src/headless.rs index c54e3ec9..0ce24cb3 100644 --- a/rust/src/headless.rs +++ b/rust/src/headless.rs @@ -90,7 +90,7 @@ pub fn shutdown() { /// Prelued-postlued helper function (calls [`init`] and [`shutdown`] for you) /// ```rust /// binaryninja::headless::script_helper(|| { -/// binaryninja::open_view("/bin/cat") +/// binaryninja::load("/bin/cat") /// .expect("Couldn't open `/bin/cat`") /// .iter() /// .for_each(|func| println!(" `{}`", func.symbol().full_name())); diff --git a/rust/src/lib.rs b/rust/src/lib.rs index 06591236..f5d96592 100644 --- a/rust/src/lib.rs +++ b/rust/src/lib.rs @@ -80,7 +80,7 @@ //! binaryninja::headless::init(); //! //! println!("Loading binary..."); -//! let bv = binaryninja::open_view("/bin/cat").expect("Couldn't open `/bin/cat`"); +//! let bv = binaryninja::load("/bin/cat").expect("Couldn't open `/bin/cat`"); //! //! // Your code here... //! @@ -164,13 +164,15 @@ pub mod symbol; pub mod tags; pub mod types; -use std::collections::HashMap; -use std::fs::File; -use std::io::Read; -use std::path::{Path, PathBuf}; +use std::path::PathBuf; +use std::ptr::null_mut; pub use binaryninjacore_sys::BNBranchType as BranchType; pub use binaryninjacore_sys::BNEndianness as Endianness; +use binaryview::BinaryView; +use metadata::Metadata; +use rc::Ref; +use string::BnStrCompatible; // Commented out to suppress unused warnings // const BN_MAX_INSTRUCTION_LENGTH: u64 = 256; @@ -192,198 +194,56 @@ pub use binaryninjacore_sys::BNEndianness as Endianness; const BN_FULL_CONFIDENCE: u8 = 255; const BN_INVALID_EXPR: usize = usize::MAX; -fn open_binary_file( - metadata: &mut filemetadata::FileMetadata, - is_bndb: bool, - with_options: bool, -) -> Result<rc::Ref<binaryview::BinaryView>, String> { - let filename = metadata.filename(); - let path = Path::new(filename.as_str()); - if is_bndb { - let mut file = File::open(path).map_err(|_| "Could not open file".to_string())?; - let mut buf = [0; 15]; - file.read_exact(&mut buf) - .map_err(|_| "Not a valid BNDB (too small)".to_string())?; +pub fn load<S: BnStrCompatible>(filename: S) -> Option<rc::Ref<binaryview::BinaryView>> { + let filename = filename.into_bytes_with_nul(); - if buf.as_slice() != b"SQLite format 3" { - return Err("Not a valid BNDB (invalid magic)".to_string()); - } - if with_options { - metadata.open_database_for_configuration(filename) - } else { - metadata.open_database(filename) - } - } else { - binaryview::BinaryView::from_filename(metadata, filename) - } - .map_err(|_| "Unable to open file".to_string()) -} - -pub fn open_view<F: AsRef<Path>>(filename: F) -> Result<rc::Ref<binaryview::BinaryView>, String> { - use crate::binaryview::BinaryViewExt; - use crate::custombinaryview::BinaryViewTypeExt; - - let filename = filename.as_ref(); - let is_bndb = filename.extension().map_or(false, |ext| ext == "bndb"); - - let mut metadata = filemetadata::FileMetadata::with_filename(filename.to_str().unwrap()); - - let view = open_binary_file(&mut metadata, is_bndb, false)?; - let bv = custombinaryview::BinaryViewType::list_valid_types_for(&view) - .iter() - .find_map(|available_view| { - if available_view.name().as_str() == "Raw" { - None - } else if is_bndb { - match view.file().get_view_of_type(available_view.name()) { - Ok(view) => Some(view), - _ => None, - } - } else { - // TODO : add log prints - println!("Opening view of type: `{}`", available_view.name()); - match available_view.open(&view) { - Ok(view) => Some(view), - _ => None, - } - } - }); - - let bv = match bv { - Some(bv) => bv, - None => { - if is_bndb { - view.file() - .get_view_of_type("Raw") - .map_err(|_| "Could not get raw view from bndb".to_string())? - } else { - custombinaryview::BinaryViewType::by_name("Raw") - .unwrap() - .open(&view) - .map_err(|_| "Could not open raw view".to_string())? - } - } + let handle = unsafe { + binaryninjacore_sys::BNLoadFilename( + filename.as_ref().as_ptr() as *mut _, + true, + None, + null_mut() as *mut _, + ) }; - bv.update_analysis_and_wait(); - Ok(bv) + if handle.is_null() { + None + } else { + Some(unsafe { BinaryView::from_raw(handle) }) + } } -/// This is incomplete, but should work in most cases: /// ```rust -/// let settings = [("analysis.linearSweep.autorun", "false")] -/// .iter() -/// .cloned() -/// .collect(); +/// let settings = [("analysis.linearSweep.autorun", false)].into(); /// -/// let bv = binaryninja::open_view_with_options("/bin/cat", true, Some(settings)) +/// let bv = binaryninja::load_with_options("/bin/cat", true, Some(settings)) /// .expect("Couldn't open `/bin/cat`"); /// ``` -pub fn open_view_with_options<F: AsRef<Path>>( - filename: F, +pub fn load_with_options<S: BnStrCompatible>( + filename: S, update_analysis_and_wait: bool, - options: Option<HashMap<&str, &str>>, -) -> Result<rc::Ref<binaryview::BinaryView>, String> { - use crate::binaryview::BinaryViewExt; - use crate::custombinaryview::{BinaryViewTypeBase, BinaryViewTypeExt}; - - let filename = filename.as_ref(); - let is_bndb = filename.extension().map_or(false, |ext| ext == "bndb"); - - let mut metadata = filemetadata::FileMetadata::with_filename(filename.to_str().unwrap()); + options: Option<Ref<Metadata>>, +) -> Option<rc::Ref<binaryview::BinaryView>> { + let filename = filename.into_bytes_with_nul(); - let view = open_binary_file(&mut metadata, is_bndb, true)?; - let mut universal_view_type = None; - let mut view_type = None; - for available_view in custombinaryview::BinaryViewType::list_valid_types_for(&view).iter() { - if available_view.name().as_ref() == b"Universal" { - universal_view_type = Some(available_view); - } else if view_type.is_none() && available_view.name().as_ref() != b"Raw" { - view_type = Some(available_view); - } - } - - let view_type = - view_type.unwrap_or_else(|| custombinaryview::BinaryViewType::by_name("Mapped").unwrap()); - - let setting_id = format!("{}{}", view_type.name(), "_settings"); - let default_settings = settings::Settings::new(setting_id); - default_settings.deserialize_schema(settings::Settings::new("").serialize_schema()); - default_settings.set_resource_id(view_type.name()); - - let load_settings = match (is_bndb, view.load_settings(view_type.name())) { - (true, Ok(settings)) => settings, - _ => { - if let (Some(universal_view_type), Some(options)) = (universal_view_type, &options) { - if options.contains_key("files.universal.architecturePreference") { - universal_view_type - .load_settings_for_data(view.as_ref()) - .map_err(|_| { - "Could not load settings for universal view_data".to_string() - })? - - // let arch_list = - // settings.get_string("loader.universal.architectures", None, None); - - // TODO : Need json support - // let arch_list = arch_list.as_str(); - // let arch_list = arch_list[1..arch_list.len()].split("'"); - // arch_entry = [entry for entry in arch_list if entry['architecture'] == options['files.universal.architecturePreference'][0]] - // if not arch_entry: - // log.log_error(f"Could not load {options['files.universal.architecturePreference'][0]} from Universal image. Entry not found!") - // return None - - // let settings = settings::Settings::new(BNGetUniqueIdentifierString()); - // settings.deserialize_schema(arch_entry[0]['loadSchema']); - } else { - match view_type.load_settings_for_data(view.as_ref()) { - Ok(settings) => settings, - _ => return Ok(view), - } - } + let handle = unsafe { + binaryninjacore_sys::BNLoadFilename( + filename.as_ref().as_ptr() as *mut _, + update_analysis_and_wait, + None, + if let Some(options) = options { + options.as_ref().handle } else { - match view_type.load_settings_for_data(view.as_ref()) { - Ok(settings) => settings, - _ => return Ok(view), - } - } - } + null_mut() as *mut _ + }, + ) }; - load_settings.set_resource_id(view_type.name()); - view.set_load_settings(view_type.name(), load_settings.as_ref()); - - if let Some(options) = options { - for (setting, value) in options { - if load_settings.contains(setting) { - if !load_settings.set_json(setting, value, Some(view.as_ref()), None) { - return Err(format!("Setting: {} set operation failed!", setting)); - } - } else if default_settings.contains(setting) { - if !default_settings.set_json(setting, value, Some(view.as_ref()), None) { - return Err(format!("Setting: {} set operation failed!", setting)); - } - } else { - return Err(format!("Setting: {} not available!", setting)); - } - } - } - - let bv = if is_bndb { - let view = view - .file() - .open_database(metadata.filename()) - .expect("Couldn't open database"); - let view_type_name = view_type.name(); - view.file().get_view_of_type(view_type_name).unwrap_or(view) + if handle.is_null() { + None } else { - view_type.open(&view).unwrap_or(view) - }; - - if update_analysis_and_wait { - bv.update_analysis_and_wait(); + Some(unsafe { BinaryView::from_raw(handle) }) } - Ok(bv) } pub fn install_directory() -> Result<PathBuf, ()> { diff --git a/rust/src/metadata.rs b/rust/src/metadata.rs index 09c21ec9..1ea8225d 100644 --- a/rust/src/metadata.rs +++ b/rust/src/metadata.rs @@ -379,16 +379,32 @@ impl From<f64> for Ref<Metadata> { } } -impl<S: BnStrCompatible> From<S> for Ref<Metadata> { - fn from(value: S) -> Self { +impl From<String> for Ref<Metadata> { + fn from(value: String) -> Self { unsafe { Metadata::ref_from_raw(BNCreateMetadataStringData( - value.into_bytes_with_nul().as_ref().as_ptr() as *const c_char, + value.into_bytes_with_nul().as_ptr() as *const c_char, )) } } } +impl From<&str> for Ref<Metadata> { + fn from(value: &str) -> Self { + unsafe { + Metadata::ref_from_raw(BNCreateMetadataStringData( + value.into_bytes_with_nul().as_ptr() as *const c_char, + )) + } + } +} + +impl<T: Into<Ref<Metadata>>> From<&T> for Ref<Metadata> { + fn from(value: &T) -> Self { + value.into() + } +} + impl From<&Vec<u8>> for Ref<Metadata> { fn from(value: &Vec<u8>) -> Self { unsafe { Metadata::ref_from_raw(BNCreateMetadataRawData(value.as_ptr(), value.len())) } @@ -442,6 +458,56 @@ impl<S: BnStrCompatible> From<HashMap<S, Ref<Metadata>>> for Ref<Metadata> { } } +impl<S: BnStrCompatible + Copy, T: Into<Ref<Metadata>>> From<&[(S, T)]> for Ref<Metadata> { + fn from(value: &[(S, T)]) -> Self { + let mut key_refs: Vec<S::Result> = vec![]; + let mut keys: Vec<*const c_char> = vec![]; + let mut values: Vec<*mut BNMetadata> = vec![]; + for (k, v) in value.iter() { + key_refs.push(k.into_bytes_with_nul()); + let value_metadata: Ref<Metadata> = v.into(); + values.push(value_metadata.handle); + } + for k in &key_refs { + keys.push(k.as_ref().as_ptr() as *const c_char); + } + + unsafe { + Metadata::ref_from_raw(BNCreateMetadataValueStore( + keys.as_mut_ptr(), + values.as_mut_ptr(), + keys.len(), + )) + } + } +} + +impl<S: BnStrCompatible + Copy, T: Into<Ref<Metadata>>, const N: usize> From<[(S, T); N]> + for Ref<Metadata> +{ + fn from(value: [(S, T); N]) -> Self { + let mut key_refs: Vec<S::Result> = vec![]; + let mut keys: Vec<*const c_char> = vec![]; + let mut values: Vec<*mut BNMetadata> = vec![]; + for (k, v) in value.into_iter() { + key_refs.push(k.into_bytes_with_nul()); + let value_metadata: Ref<Metadata> = v.into(); + values.push(value_metadata.handle); + } + for k in &key_refs { + keys.push(k.as_ref().as_ptr() as *const c_char); + } + + unsafe { + Metadata::ref_from_raw(BNCreateMetadataValueStore( + keys.as_mut_ptr(), + values.as_mut_ptr(), + keys.len(), + )) + } + } +} + impl From<&Vec<bool>> for Ref<Metadata> { fn from(value: &Vec<bool>) -> Self { unsafe { |
