binaryninja/
external_library.rs

1use crate::project::file::ProjectFile;
2use crate::rc::{CoreArrayProvider, CoreArrayProviderInner, Guard, Ref, RefCountable};
3use crate::string::{BnString, IntoCStr};
4use crate::symbol::Symbol;
5use binaryninjacore_sys::*;
6use std::fmt::Debug;
7use std::ptr::NonNull;
8
9/// An ExternalLibrary is an abstraction for a library that is optionally backed
10/// by a [ProjectFile].
11#[repr(transparent)]
12pub struct ExternalLibrary {
13    pub(crate) handle: NonNull<BNExternalLibrary>,
14}
15
16impl ExternalLibrary {
17    pub(crate) unsafe fn from_raw(handle: NonNull<BNExternalLibrary>) -> Self {
18        Self { handle }
19    }
20
21    pub(crate) unsafe fn ref_from_raw(handle: NonNull<BNExternalLibrary>) -> Ref<Self> {
22        Ref::new(Self { handle })
23    }
24
25    /// Get the name of this external library
26    pub fn name(&self) -> String {
27        let result = unsafe { BNExternalLibraryGetName(self.handle.as_ptr()) };
28        assert!(!result.is_null());
29        unsafe { BnString::into_string(result) }
30    }
31
32    /// Get the file backing this external library
33    pub fn backing_file(&self) -> Option<Ref<ProjectFile>> {
34        let result = unsafe { BNExternalLibraryGetBackingFile(self.handle.as_ptr()) };
35        let handle = NonNull::new(result)?;
36        Some(unsafe { ProjectFile::ref_from_raw(handle) })
37    }
38
39    /// Set the file backing this external library
40    pub fn set_backing_file(&self, file: Option<&ProjectFile>) {
41        let file_handle = file
42            .map(|x| x.handle.as_ptr())
43            .unwrap_or(std::ptr::null_mut());
44        unsafe { BNExternalLibrarySetBackingFile(self.handle.as_ptr(), file_handle) }
45    }
46}
47
48impl ToOwned for ExternalLibrary {
49    type Owned = Ref<Self>;
50
51    fn to_owned(&self) -> Self::Owned {
52        unsafe { RefCountable::inc_ref(self) }
53    }
54}
55
56unsafe impl RefCountable for ExternalLibrary {
57    unsafe fn inc_ref(handle: &Self) -> Ref<Self> {
58        Ref::new(Self {
59            handle: NonNull::new(BNNewExternalLibraryReference(handle.handle.as_ptr())).unwrap(),
60        })
61    }
62
63    unsafe fn dec_ref(handle: &Self) {
64        BNFreeExternalLibrary(handle.handle.as_ptr());
65    }
66}
67
68impl Debug for ExternalLibrary {
69    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
70        f.debug_struct("ExternalLibrary")
71            .field("name", &self.name())
72            .field("backing_file", &self.backing_file())
73            .finish()
74    }
75}
76
77impl CoreArrayProvider for ExternalLibrary {
78    type Raw = *mut BNExternalLibrary;
79    type Context = ();
80    type Wrapped<'a> = Guard<'a, ExternalLibrary>;
81}
82
83unsafe impl CoreArrayProviderInner for ExternalLibrary {
84    unsafe fn free(raw: *mut Self::Raw, count: usize, _context: &Self::Context) {
85        BNFreeExternalLibraryList(raw, count)
86    }
87
88    unsafe fn wrap_raw<'a>(raw: &'a Self::Raw, context: &'a Self::Context) -> Self::Wrapped<'a> {
89        let raw_ptr = NonNull::new(*raw).unwrap();
90        Guard::new(Self::from_raw(raw_ptr), context)
91    }
92}
93
94/// An [`ExternalLocation`] is an association from a source symbol in a binary view
95/// to a target symbol and/or address in an [`ExternalLibrary`].
96#[repr(transparent)]
97pub struct ExternalLocation {
98    handle: NonNull<BNExternalLocation>,
99}
100
101impl ExternalLocation {
102    pub(crate) unsafe fn from_raw(handle: NonNull<BNExternalLocation>) -> Self {
103        Self { handle }
104    }
105
106    pub(crate) unsafe fn ref_from_raw(handle: NonNull<BNExternalLocation>) -> Ref<Self> {
107        Ref::new(Self { handle })
108    }
109
110    /// Get the source symbol for this ExternalLocation
111    pub fn source_symbol(&self) -> Ref<Symbol> {
112        let result = unsafe { BNExternalLocationGetSourceSymbol(self.handle.as_ptr()) };
113        assert!(!result.is_null());
114        unsafe { Symbol::ref_from_raw(result) }
115    }
116
117    /// Get the ExternalLibrary that this ExternalLocation targets
118    pub fn library(&self) -> Option<Ref<ExternalLibrary>> {
119        let result = unsafe { BNExternalLocationGetExternalLibrary(self.handle.as_ptr()) };
120        let handle = NonNull::new(result)?;
121        Some(unsafe { ExternalLibrary::ref_from_raw(handle) })
122    }
123
124    /// Set the ExternalLibrary that this ExternalLocation targets
125    pub fn set_external_library(&self, lib: Option<&ExternalLibrary>) {
126        let lib_handle = lib
127            .map(|x| x.handle.as_ptr())
128            .unwrap_or(std::ptr::null_mut());
129        unsafe { BNExternalLocationSetExternalLibrary(self.handle.as_ptr(), lib_handle) }
130    }
131
132    /// Check if this ExternalLocation has a target address
133    pub fn has_target_address(&self) -> bool {
134        unsafe { BNExternalLocationHasTargetAddress(self.handle.as_ptr()) }
135    }
136
137    /// Check if this ExternalLocation has a target symbol
138    pub fn has_target_symbol(&self) -> bool {
139        unsafe { BNExternalLocationHasTargetSymbol(self.handle.as_ptr()) }
140    }
141
142    /// Get the address pointed to by this ExternalLocation, if any
143    pub fn target_address(&self) -> Option<u64> {
144        self.has_target_address()
145            .then(|| unsafe { BNExternalLocationGetTargetAddress(self.handle.as_ptr()) })
146    }
147
148    /// Set the address pointed to by this ExternalLocation.
149    /// ExternalLocations must have a valid target address and/or symbol set.
150    pub fn set_target_address(&self, address: Option<u64>) -> bool {
151        match address {
152            Some(mut addr) => unsafe {
153                BNExternalLocationSetTargetAddress(self.handle.as_ptr(), &mut addr)
154            },
155            None => unsafe {
156                BNExternalLocationSetTargetAddress(self.handle.as_ptr(), std::ptr::null_mut())
157            },
158        }
159    }
160
161    /// Get the symbol pointed to by this ExternalLocation, if any
162    pub fn target_symbol(&self) -> Option<BnString> {
163        let result = unsafe { BNExternalLocationGetTargetSymbol(self.handle.as_ptr()) };
164        (!result.is_null()).then(|| unsafe { BnString::from_raw(result) })
165    }
166
167    /// Set the symbol pointed to by this ExternalLocation.
168    /// ExternalLocations must have a valid target address and/or symbol set.
169    pub fn set_target_symbol(&self, symbol: Option<&str>) -> bool {
170        match symbol {
171            Some(sym) => {
172                let raw_sym = sym.to_cstr();
173                unsafe { BNExternalLocationSetTargetSymbol(self.handle.as_ptr(), raw_sym.as_ptr()) }
174            }
175            None => unsafe {
176                BNExternalLocationSetTargetSymbol(self.handle.as_ptr(), std::ptr::null())
177            },
178        }
179    }
180}
181
182impl Debug for ExternalLocation {
183    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
184        f.debug_struct("ExternalLocation")
185            .field("source_symbol", &self.source_symbol())
186            .field("library", &self.library())
187            .field("target_address", &self.target_address())
188            .field("target_symbol", &self.target_symbol())
189            .finish()
190    }
191}
192
193impl ToOwned for ExternalLocation {
194    type Owned = Ref<Self>;
195
196    fn to_owned(&self) -> Self::Owned {
197        unsafe { RefCountable::inc_ref(self) }
198    }
199}
200
201unsafe impl RefCountable for ExternalLocation {
202    unsafe fn inc_ref(handle: &Self) -> Ref<Self> {
203        Ref::new(Self {
204            handle: NonNull::new(BNNewExternalLocationReference(handle.handle.as_ptr())).unwrap(),
205        })
206    }
207
208    unsafe fn dec_ref(handle: &Self) {
209        BNFreeExternalLocation(handle.handle.as_ptr());
210    }
211}
212
213impl CoreArrayProvider for ExternalLocation {
214    type Raw = *mut BNExternalLocation;
215    type Context = ();
216    type Wrapped<'a> = Guard<'a, Self>;
217}
218
219unsafe impl CoreArrayProviderInner for ExternalLocation {
220    unsafe fn free(raw: *mut Self::Raw, count: usize, _context: &Self::Context) {
221        BNFreeExternalLocationList(raw, count)
222    }
223
224    unsafe fn wrap_raw<'a>(raw: &'a Self::Raw, context: &'a Self::Context) -> Self::Wrapped<'a> {
225        let raw_ptr = NonNull::new(*raw).unwrap();
226        Guard::new(Self::from_raw(raw_ptr), context)
227    }
228}