summaryrefslogtreecommitdiff
path: root/rust/src/references.rs
diff options
context:
space:
mode:
Diffstat (limited to 'rust/src/references.rs')
-rw-r--r--rust/src/references.rs98
1 files changed, 62 insertions, 36 deletions
diff --git a/rust/src/references.rs b/rust/src/references.rs
index d12c33c5..52fb6713 100644
--- a/rust/src/references.rs
+++ b/rust/src/references.rs
@@ -1,53 +1,70 @@
+#![allow(dead_code)]
use crate::architecture::CoreArchitecture;
use crate::function::Function;
-use crate::rc::{CoreArrayProvider, CoreArrayProviderInner, Guard, Ref};
+use crate::rc::{CoreArrayProvider, CoreArrayProviderInner, Ref};
use binaryninjacore_sys::{BNFreeCodeReferences, BNFreeDataReferences, BNReferenceSource};
-use std::mem::ManuallyDrop;
/// A struct representing a single code cross-reference.
-/// Taking a cue from [`crate::linearview::LinearDisassemblyLine`], this struct uses [ManuallyDrop] to
-/// prevent destructors from being run on the [`Function`] object allocated by
-/// the core in `BNGetCodeReferences` (et al). The reference is cleaned up on [Drop] of
-/// the enclosing array object.
#[derive(Debug)]
pub struct CodeReference {
- arch: CoreArchitecture,
- func: ManuallyDrop<Ref<Function>>,
- pub address: u64,
-}
-
-/// A struct representing a single data cross-reference.
-/// Data references have no associated metadata, so this object has only
-/// a single [`DataReference::address`] attribute.
-pub struct DataReference {
+ pub arch: Option<CoreArchitecture>,
+ pub func: Option<Ref<Function>>,
pub address: u64,
}
impl CodeReference {
- pub(crate) unsafe fn new(handle: &BNReferenceSource) -> Self {
- let func = ManuallyDrop::new(Function::from_raw(handle.func));
- let arch = CoreArchitecture::from_raw(handle.arch);
- let address = handle.addr;
+ pub(crate) fn from_raw(value: &BNReferenceSource) -> Self {
Self {
- func,
- arch,
- address,
+ func: match value.func.is_null() {
+ false => Some(unsafe { Function::from_raw(value.func) }.to_owned()),
+ true => None,
+ },
+ arch: match value.func.is_null() {
+ false => Some(unsafe { CoreArchitecture::from_raw(value.arch) }),
+ true => None,
+ },
+ address: value.addr,
+ }
+ }
+
+ pub(crate) fn from_owned_raw(value: BNReferenceSource) -> Self {
+ let owned = Self::from_raw(&value);
+ Self::free_raw(value);
+ owned
+ }
+
+ pub(crate) fn into_raw(value: Self) -> BNReferenceSource {
+ BNReferenceSource {
+ func: match value.func {
+ Some(func) => unsafe { Ref::into_raw(func) }.handle,
+ None => std::ptr::null_mut(),
+ },
+ arch: value.arch.map(|a| a.handle).unwrap_or(std::ptr::null_mut()),
+ addr: value.address,
}
}
-}
-impl<'a> CodeReference {
- /// A handle to the referenced function bound by the [CodeReference] object's lifetime.
- /// A user can call `.to_owned()` to promote this into its own ref-counted struct
- /// and use it after the lifetime of the [CodeReference].
- pub fn function(&'a self) -> &'a Function {
- self.func.as_ref()
+ pub(crate) fn into_owned_raw(value: &Self) -> BNReferenceSource {
+ BNReferenceSource {
+ func: match &value.func {
+ Some(func) => func.handle,
+ None => std::ptr::null_mut(),
+ },
+ arch: value.arch.map(|a| a.handle).unwrap_or(std::ptr::null_mut()),
+ addr: value.address,
+ }
+ }
+
+ pub(crate) fn free_raw(value: BNReferenceSource) {
+ let _ = unsafe { Function::ref_from_raw(value.func) };
}
- /// A handle to the [CodeReference]'s [CoreArchitecture]. This type is [Copy] so reference
- /// shenanigans are not needed here.
- pub fn architecture(&self) -> CoreArchitecture {
- self.arch
+ pub fn new(address: u64, func: Option<Ref<Function>>, arch: Option<CoreArchitecture>) -> Self {
+ Self {
+ func,
+ arch,
+ address,
+ }
}
}
@@ -56,19 +73,27 @@ impl<'a> CodeReference {
impl CoreArrayProvider for CodeReference {
type Raw = BNReferenceSource;
type Context = ();
- type Wrapped<'a> = Guard<'a, CodeReference>;
+ type Wrapped<'a> = Self;
}
unsafe impl CoreArrayProviderInner for CodeReference {
unsafe fn free(raw: *mut Self::Raw, count: usize, _context: &Self::Context) {
BNFreeCodeReferences(raw, count)
}
+
unsafe fn wrap_raw<'a>(raw: &'a Self::Raw, _context: &'a Self::Context) -> Self::Wrapped<'a> {
- Guard::new(CodeReference::new(raw), &())
+ CodeReference::from_raw(raw)
}
}
-// Data Reference Array<T> boilerplate
+// TODO: This only exists so that Array can free.
+// TODO: Is there any way we can have this instead be Array<Location> of some sort?
+/// A struct representing a single data cross-reference.
+/// Data references have no associated metadata, so this object has only
+/// a single [`DataReference::address`] attribute.
+pub struct DataReference {
+ pub address: u64,
+}
impl CoreArrayProvider for DataReference {
type Raw = u64;
@@ -80,6 +105,7 @@ unsafe impl CoreArrayProviderInner for DataReference {
unsafe fn free(raw: *mut Self::Raw, _count: usize, _context: &Self::Context) {
BNFreeDataReferences(raw)
}
+
unsafe fn wrap_raw<'a>(raw: &'a Self::Raw, _context: &'a Self::Context) -> Self::Wrapped<'a> {
DataReference { address: *raw }
}