summaryrefslogtreecommitdiff
path: root/rust/src
diff options
context:
space:
mode:
authorRubens Brandao <git@rubens.io>2024-06-24 10:23:54 -0300
committerJosh Ferrell <josh@vector35.com>2024-07-08 16:04:42 -0400
commitf90f8512135935a182cc805b5e7a3728529f3487 (patch)
treeba22e6f8332eeb87ec292ca61b83bb55b2adeca2 /rust/src
parenteed70ad4d270ca1d134d325362f23c831fe98b0b (diff)
implement rust ExternalLibrary
Diffstat (limited to 'rust/src')
-rw-r--r--rust/src/externallibrary.rs204
-rw-r--r--rust/src/lib.rs1
2 files changed, 205 insertions, 0 deletions
diff --git a/rust/src/externallibrary.rs b/rust/src/externallibrary.rs
new file mode 100644
index 00000000..c7edbbcb
--- /dev/null
+++ b/rust/src/externallibrary.rs
@@ -0,0 +1,204 @@
+use core::{ffi, mem, ptr};
+
+use binaryninjacore_sys::*;
+
+use crate::project::ProjectFile;
+use crate::rc::{CoreArrayProvider, CoreArrayProviderInner};
+use crate::string::{BnStrCompatible, BnString};
+use crate::symbol::Symbol;
+
+/// An ExternalLibrary is an abstraction for a library that is optionally backed
+/// by a [ProjectFile].
+#[repr(transparent)]
+pub struct ExternalLibrary {
+ handle: ptr::NonNull<BNExternalLibrary>,
+}
+
+impl Drop for ExternalLibrary {
+ fn drop(&mut self) {
+ unsafe { BNFreeExternalLibrary(self.as_raw()) }
+ }
+}
+
+impl Clone for ExternalLibrary {
+ fn clone(&self) -> Self {
+ unsafe {
+ Self::from_raw(ptr::NonNull::new(BNNewExternalLibraryReference(self.as_raw())).unwrap())
+ }
+ }
+}
+
+impl ExternalLibrary {
+ pub(crate) unsafe fn from_raw(handle: ptr::NonNull<BNExternalLibrary>) -> Self {
+ Self { handle }
+ }
+
+ pub(crate) unsafe fn ref_from_raw(handle: &*mut BNExternalLibrary) -> &Self {
+ assert!(!handle.is_null());
+ mem::transmute(handle)
+ }
+
+ #[allow(clippy::mut_from_ref)]
+ pub(crate) unsafe fn as_raw(&self) -> &mut BNExternalLibrary {
+ &mut *self.handle.as_ptr()
+ }
+
+ /// Get the name of this external library
+ pub fn name(&self) -> BnString {
+ let result = unsafe { BNExternalLibraryGetName(self.as_raw()) };
+ assert!(!result.is_null());
+ unsafe { BnString::from_raw(result) }
+ }
+
+ /// Get the file backing this external library
+ pub fn backing_file(&self) -> ProjectFile {
+ let result = unsafe { BNExternalLibraryGetBackingFile(self.as_raw()) };
+ unsafe { ProjectFile::from_raw(ptr::NonNull::new(result).unwrap()) }
+ }
+
+ /// Set the file backing this external library
+ pub fn set_backing_file(&self, file: &ProjectFile) {
+ unsafe { BNExternalLibrarySetBackingFile(self.as_raw(), file.as_raw()) }
+ }
+}
+
+impl CoreArrayProvider for ExternalLibrary {
+ type Raw = *mut BNExternalLibrary;
+ type Context = ();
+ type Wrapped<'a> = &'a Self;
+}
+
+unsafe impl CoreArrayProviderInner for ExternalLibrary {
+ unsafe fn free(raw: *mut Self::Raw, count: usize, _context: &Self::Context) {
+ BNFreeExternalLibraryList(raw, count)
+ }
+
+ unsafe fn wrap_raw<'a>(raw: &'a Self::Raw, _context: &'a Self::Context) -> Self::Wrapped<'a> {
+ Self::ref_from_raw(raw)
+ }
+}
+
+/// An ExternalLocation is an association from a source symbol in a binary view
+/// to a target symbol and/or address in an [ExternalLibrary].
+#[repr(transparent)]
+pub struct ExternalLocation {
+ handle: ptr::NonNull<BNExternalLocation>,
+}
+
+impl Drop for ExternalLocation {
+ fn drop(&mut self) {
+ unsafe { BNFreeExternalLocation(self.as_raw()) }
+ }
+}
+
+impl Clone for ExternalLocation {
+ fn clone(&self) -> Self {
+ unsafe {
+ Self::from_raw(
+ ptr::NonNull::new(BNNewExternalLocationReference(self.as_raw())).unwrap(),
+ )
+ }
+ }
+}
+
+impl ExternalLocation {
+ pub(crate) unsafe fn from_raw(handle: ptr::NonNull<BNExternalLocation>) -> Self {
+ Self { handle }
+ }
+
+ pub(crate) unsafe fn ref_from_raw(handle: &*mut BNExternalLocation) -> &Self {
+ assert!(!handle.is_null());
+ mem::transmute(handle)
+ }
+
+ #[allow(clippy::mut_from_ref)]
+ pub(crate) unsafe fn as_raw(&self) -> &mut BNExternalLocation {
+ &mut *self.handle.as_ptr()
+ }
+
+ /// Get the source symbol for this ExternalLocation
+ pub fn source_symbol(&self) -> Symbol {
+ let result = unsafe { BNExternalLocationGetSourceSymbol(self.as_raw()) };
+ assert!(!result.is_null());
+ unsafe { Symbol::from_raw(result) }
+ }
+
+ /// Get the ExternalLibrary that this ExternalLocation targets
+ pub fn library(&self) -> ExternalLibrary {
+ let result = unsafe { BNExternalLocationGetExternalLibrary(self.as_raw()) };
+ unsafe { ExternalLibrary::from_raw(ptr::NonNull::new(result).unwrap()) }
+ }
+
+ /// Set the ExternalLibrary that this ExternalLocation targets
+ pub fn set_external_library(&self, lib: &ExternalLibrary) {
+ unsafe { BNExternalLocationSetExternalLibrary(self.as_raw(), lib.as_raw()) }
+ }
+
+ /// Check if this ExternalLocation has a target address
+ pub fn has_target_address(&self) -> bool {
+ unsafe { BNExternalLocationHasTargetAddress(self.as_raw()) }
+ }
+
+ /// Check if this ExternalLocation has a target symbol
+ pub fn has_target_symbol(&self) -> bool {
+ unsafe { BNExternalLocationHasTargetSymbol(self.as_raw()) }
+ }
+
+ /// Get the address pointed to by this ExternalLocation, if any
+ pub fn target_address(&self) -> Option<u64> {
+ self.has_target_address()
+ .then(|| unsafe { BNExternalLocationGetTargetAddress(self.as_raw()) })
+ }
+
+ /// Set the address pointed to by this ExternalLocation.
+ /// ExternalLocations must have a valid target address and/or symbol set.
+ pub fn set_target_address(&self, mut address: Option<u64>) -> bool {
+ let address_ptr = address
+ .as_mut()
+ .map(|x| x as *mut u64)
+ .unwrap_or(ptr::null_mut());
+ unsafe { BNExternalLocationSetTargetAddress(self.as_raw(), address_ptr) }
+ }
+
+ /// Get the symbol pointed to by this ExternalLocation, if any
+ pub fn target_symbol(&self) -> Option<BnString> {
+ self.has_target_symbol().then(|| unsafe {
+ let result = BNExternalLocationGetTargetSymbol(self.as_raw());
+ assert!(!result.is_null());
+ BnString::from_raw(result)
+ })
+ }
+
+ /// Remove the symbol pointed to by this ExternalLocation.
+ pub fn remove_target_symbol(&self) -> bool {
+ unsafe { BNExternalLocationSetTargetSymbol(self.as_raw(), ptr::null_mut()) }
+ }
+
+ /// Set the symbol pointed to by this ExternalLocation.
+ /// ExternalLocations must have a valid target address and/or symbol set.
+ pub fn set_target_symbol<S: BnStrCompatible>(&self, symbol: S) -> bool {
+ let symbol = symbol.into_bytes_with_nul();
+ unsafe {
+ BNExternalLocationSetTargetSymbol(
+ self.as_raw(),
+ symbol.as_ref().as_ptr() as *const ffi::c_char,
+ )
+ }
+ }
+}
+
+impl CoreArrayProvider for ExternalLocation {
+ type Raw = *mut BNExternalLocation;
+ type Context = ();
+ type Wrapped<'a> = &'a Self;
+}
+
+unsafe impl CoreArrayProviderInner for ExternalLocation {
+ unsafe fn free(raw: *mut Self::Raw, count: usize, _context: &Self::Context) {
+ BNFreeExternalLocationList(raw, count)
+ }
+
+ unsafe fn wrap_raw<'a>(raw: &'a Self::Raw, _context: &'a Self::Context) -> Self::Wrapped<'a> {
+ Self::ref_from_raw(raw)
+ }
+}
diff --git a/rust/src/lib.rs b/rust/src/lib.rs
index 71ae9091..f72ba99b 100644
--- a/rust/src/lib.rs
+++ b/rust/src/lib.rs
@@ -139,6 +139,7 @@ pub mod demangle;
pub mod disassembly;
pub mod component;
pub mod downloadprovider;
+pub mod externallibrary;
pub mod fileaccessor;
pub mod filemetadata;
pub mod flowgraph;