From 21da3f95b00431f4d10d8b5e67ee402bffde129c Mon Sep 17 00:00:00 2001 From: KyleMiles Date: Tue, 11 May 2021 22:51:38 -0400 Subject: Rust API; More setting support, fix edgecase in open_view_with_options, and fixed using mut for const correctness (mut != ~const) --- rust/src/backgroundtask.rs | 6 +- rust/src/binaryview.rs | 2 +- rust/src/filemetadata.rs | 7 +- rust/src/lib.rs | 33 ++++--- rust/src/settings.rs | 218 ++++++++++++++++++++++++++++++++++++++++++++- rust/src/string.rs | 4 + 6 files changed, 245 insertions(+), 25 deletions(-) (limited to 'rust/src') diff --git a/rust/src/backgroundtask.rs b/rust/src/backgroundtask.rs index d99ec6b1..26480e7e 100644 --- a/rust/src/backgroundtask.rs +++ b/rust/src/backgroundtask.rs @@ -61,15 +61,15 @@ impl BackgroundTask { unsafe { BnString::from_raw(BNGetBackgroundTaskProgressText(self.handle)) } } - pub fn cancel(&mut self) { + pub fn cancel(&self) { unsafe { BNCancelBackgroundTask(self.handle) } } - pub fn finish(&mut self) { + pub fn finish(&self) { unsafe { BNFinishBackgroundTask(self.handle) } } - pub fn set_progress_text(&mut self, text: S) { + pub fn set_progress_text(&self, text: S) { let progress_text = text.as_bytes_with_nul(); unsafe { diff --git a/rust/src/binaryview.rs b/rust/src/binaryview.rs index 98d7c7b4..b2b3dca6 100644 --- a/rust/src/binaryview.rs +++ b/rust/src/binaryview.rs @@ -634,7 +634,7 @@ pub trait BinaryViewExt: BinaryViewBase { } } - fn set_load_settings(&mut self, view_type_name: S, settings: &Settings) { + fn set_load_settings(&self, view_type_name: S, settings: &Settings) { let view_type_name = view_type_name.as_bytes_with_nul(); unsafe { diff --git a/rust/src/filemetadata.rs b/rust/src/filemetadata.rs index 809abea4..8ba25387 100644 --- a/rust/src/filemetadata.rs +++ b/rust/src/filemetadata.rs @@ -176,7 +176,7 @@ impl FileMetadata { } pub fn open_database_for_configuration( - &mut self, + &self, filename: S, ) -> Result, ()> { let filename = filename.as_bytes_with_nul(); @@ -192,10 +192,7 @@ impl FileMetadata { } } - pub fn open_database( - &mut self, - filename: S, - ) -> Result, ()> { + pub fn open_database(&self, filename: S) -> Result, ()> { let filename = filename.as_bytes_with_nul(); let filename_ptr = filename.as_ref().as_ptr() as *mut _; diff --git a/rust/src/lib.rs b/rust/src/lib.rs index b8919fb1..56ca2989 100644 --- a/rust/src/lib.rs +++ b/rust/src/lib.rs @@ -318,7 +318,7 @@ pub fn open_view_with_options>( let mut metadata = filemetadata::FileMetadata::with_filename(filename.to_str().unwrap()); let mut is_bndb = false; - let mut view = match match filename.ends_with(".bndb") { + let view = match match filename.ends_with(".bndb") { true => { match File::open(filename) { Ok(mut file) => { @@ -359,9 +359,8 @@ pub fn open_view_with_options>( Some(view_type) => view_type, }; - // I have no idea why this is needed let setting_id = format!("{}{}", view_type.name(), "_settings"); - let mut default_settings = settings::Settings::new(setting_id); + 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()); @@ -385,10 +384,17 @@ pub fn open_view_with_options>( { Ok(settings) => Some(settings), _ => return Err("Could not load settings for universal view data".to_string()), - } + }; + + // let arch_list = load_settings.as_ref().unwrap().get_string( + // "loader.universal.architectures", + // None, + // None, + // ); - // TODO : finish converting this to Rust - // arch_list = json.loads(load_settings.get_string('loader.universal.architectures')) + // 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!") @@ -401,14 +407,14 @@ pub fn open_view_with_options>( load_settings = match view_type.load_settings_for_data(view.as_ref()) { Ok(settings) => Some(settings), _ => None, - } + }; } } if load_settings.is_none() { // log.log_error(f"Could not get load settings for binary view of type `{bvt.name}`") return Ok(view); } - let mut load_settings = load_settings.unwrap(); + let load_settings = load_settings.unwrap(); load_settings.set_resource_id(view_type.name()); view.set_load_settings(view_type.name(), load_settings.as_ref()); @@ -437,13 +443,12 @@ pub fn open_view_with_options>( .open_database(filename.to_str().unwrap()) .expect("Couldn't open database"); let view_type_name = view_type.name(); - // TODO : handle the case where the view doesn't exist in the bndb - let bv = unsafe { - binaryview::BinaryView::from_raw(binaryninjacore_sys::BNGetFileViewOfType( - view.metadata().handle, - view_type_name.as_ref().as_ptr() as *mut _, - )) + + let bv = match view.metadata().get_view_of_type(view_type_name) { + Ok(bv) => bv, + _ => view, }; + if update_analysis_and_wait { bv.update_analysis_and_wait(); } diff --git a/rust/src/settings.rs b/rust/src/settings.rs index a555cb4c..86904c38 100644 --- a/rust/src/settings.rs +++ b/rust/src/settings.rs @@ -47,7 +47,7 @@ impl Settings { } } - pub fn set_resource_id(&mut self, resource_id: S) { + pub fn set_resource_id(&self, resource_id: S) { let resource_id = resource_id.as_bytes_with_nul(); unsafe { BNSettingsSetResourceId(self.handle, resource_id.as_ref().as_ptr() as *mut _) }; } @@ -74,8 +74,222 @@ impl Settings { unsafe { BNSettingsContains(self.handle, key.as_ref().as_ptr() as *mut _) } } + pub fn get_bool( + &self, + key: S, + view: Option, + scope: Option>, + ) -> bool { + let key = key.as_bytes_with_nul(); + let view_handle = match view { + Some(view) => view.handle, + _ => ptr::null_mut() as *mut _, + }; + let scope_ptr = match scope { + Some(mut scope) => scope.as_mut(), + _ => ptr::null_mut() as *mut _, + }; + unsafe { + BNSettingsGetBool( + self.handle, + key.as_ref().as_ptr() as *mut _, + view_handle, + scope_ptr, + ) + } + } + + pub fn get_double( + &self, + key: S, + view: Option, + scope: Option>, + ) -> f64 { + let key = key.as_bytes_with_nul(); + let view_handle = match view { + Some(view) => view.handle, + _ => ptr::null_mut() as *mut _, + }; + let scope_ptr = match scope { + Some(mut scope) => scope.as_mut(), + _ => ptr::null_mut() as *mut _, + }; + unsafe { + BNSettingsGetDouble( + self.handle, + key.as_ref().as_ptr() as *mut _, + view_handle, + scope_ptr, + ) + } + } + + pub fn get_integer( + &self, + key: S, + view: Option, + scope: Option>, + ) -> u64 { + let key = key.as_bytes_with_nul(); + let view_handle = match view { + Some(view) => view.handle, + _ => ptr::null_mut() as *mut _, + }; + let scope_ptr = match scope { + Some(mut scope) => scope.as_mut(), + _ => ptr::null_mut() as *mut _, + }; + unsafe { + BNSettingsGetUInt64( + self.handle, + key.as_ref().as_ptr() as *mut _, + view_handle, + scope_ptr, + ) + } + } + + pub fn get_string( + &self, + key: S, + view: Option, + scope: Option>, + ) -> BnString { + let key = key.as_bytes_with_nul(); + let view_handle = match view { + Some(view) => view.handle, + _ => ptr::null_mut() as *mut _, + }; + let scope_ptr = match scope { + Some(mut scope) => scope.as_mut(), + _ => ptr::null_mut() as *mut _, + }; + unsafe { + BnString::from_raw(BNSettingsGetString( + self.handle, + key.as_ref().as_ptr() as *mut _, + view_handle, + scope_ptr, + )) + } + } + + // TODO : get_string_list + // TODO : get_json + + pub fn set_bool( + &self, + key: S, + value: bool, + view: Option, + scope: Option, + ) { + let key = key.as_bytes_with_nul(); + let view_handle = match view { + Some(view) => view.handle, + _ => ptr::null_mut() as *mut _, + }; + let scope = match scope { + Some(scope) => scope, + _ => SettingsScope::SettingsAutoScope, + }; + unsafe { + BNSettingsSetBool( + self.handle, + view_handle, + scope, + key.as_ref().as_ptr() as *mut _, + value, + ); + } + } + + pub fn set_double( + &self, + key: S, + value: f64, + view: Option, + scope: Option, + ) { + let key = key.as_bytes_with_nul(); + let view_handle = match view { + Some(view) => view.handle, + _ => ptr::null_mut() as *mut _, + }; + let scope = match scope { + Some(scope) => scope, + _ => SettingsScope::SettingsAutoScope, + }; + unsafe { + BNSettingsSetDouble( + self.handle, + view_handle, + scope, + key.as_ref().as_ptr() as *mut _, + value, + ); + } + } + + pub fn set_integer( + &self, + key: S, + value: u64, + view: Option, + scope: Option, + ) { + let key = key.as_bytes_with_nul(); + let view_handle = match view { + Some(view) => view.handle, + _ => ptr::null_mut() as *mut _, + }; + let scope = match scope { + Some(scope) => scope, + _ => SettingsScope::SettingsAutoScope, + }; + unsafe { + BNSettingsSetUInt64( + self.handle, + view_handle, + scope, + key.as_ref().as_ptr() as *mut _, + value, + ); + } + } + + pub fn set_string( + &self, + key: S, + value: S, + view: Option, + scope: Option, + ) { + let key = key.as_bytes_with_nul(); + let value = value.as_bytes_with_nul(); + let view_handle = match view { + Some(view) => view.handle, + _ => ptr::null_mut() as *mut _, + }; + let scope = match scope { + Some(scope) => scope, + _ => SettingsScope::SettingsAutoScope, + }; + unsafe { + BNSettingsSetString( + self.handle, + view_handle, + scope, + key.as_ref().as_ptr() as *mut _, + value.as_ref().as_ptr() as *mut _, + ); + } + } + + // TODO : set_string_list + pub fn set_json( - &mut self, + &self, key: S1, value: S2, view: Option<&BinaryView>, diff --git a/rust/src/string.rs b/rust/src/string.rs index 5b20532e..e042dbdd 100644 --- a/rust/src/string.rs +++ b/rust/src/string.rs @@ -111,6 +111,10 @@ impl BnString { res } + + pub fn as_str(&self) -> &str { + unsafe { BnStr::from_raw(self.raw).as_str() } + } } impl Drop for BnString { -- cgit v1.3.1