binaryninja/
references.rs

1#![allow(dead_code)]
2use crate::architecture::CoreArchitecture;
3use crate::function::Function;
4use crate::rc::{CoreArrayProvider, CoreArrayProviderInner, Ref};
5use binaryninjacore_sys::{BNFreeCodeReferences, BNFreeDataReferences, BNReferenceSource};
6
7/// A struct representing a single code cross-reference.
8#[derive(Debug)]
9pub struct CodeReference {
10    pub arch: Option<CoreArchitecture>,
11    pub func: Option<Ref<Function>>,
12    pub address: u64,
13}
14
15impl CodeReference {
16    pub(crate) fn from_raw(value: &BNReferenceSource) -> Self {
17        Self {
18            func: match value.func.is_null() {
19                false => Some(unsafe { Function::from_raw(value.func) }.to_owned()),
20                true => None,
21            },
22            arch: match value.func.is_null() {
23                false => Some(unsafe { CoreArchitecture::from_raw(value.arch) }),
24                true => None,
25            },
26            address: value.addr,
27        }
28    }
29
30    pub(crate) fn from_owned_raw(value: BNReferenceSource) -> Self {
31        let owned = Self::from_raw(&value);
32        Self::free_raw(value);
33        owned
34    }
35
36    pub(crate) fn into_raw(value: Self) -> BNReferenceSource {
37        BNReferenceSource {
38            func: match value.func {
39                Some(func) => unsafe { Ref::into_raw(func) }.handle,
40                None => std::ptr::null_mut(),
41            },
42            arch: value.arch.map(|a| a.handle).unwrap_or(std::ptr::null_mut()),
43            addr: value.address,
44        }
45    }
46
47    pub(crate) fn into_owned_raw(value: &Self) -> BNReferenceSource {
48        BNReferenceSource {
49            func: match &value.func {
50                Some(func) => func.handle,
51                None => std::ptr::null_mut(),
52            },
53            arch: value.arch.map(|a| a.handle).unwrap_or(std::ptr::null_mut()),
54            addr: value.address,
55        }
56    }
57
58    pub(crate) fn free_raw(value: BNReferenceSource) {
59        let _ = unsafe { Function::ref_from_raw(value.func) };
60    }
61
62    pub fn new(address: u64, func: Option<Ref<Function>>, arch: Option<CoreArchitecture>) -> Self {
63        Self {
64            func,
65            arch,
66            address,
67        }
68    }
69}
70
71// Code Reference Array<T> boilerplate
72
73impl CoreArrayProvider for CodeReference {
74    type Raw = BNReferenceSource;
75    type Context = ();
76    type Wrapped<'a> = Self;
77}
78
79unsafe impl CoreArrayProviderInner for CodeReference {
80    unsafe fn free(raw: *mut Self::Raw, count: usize, _context: &Self::Context) {
81        BNFreeCodeReferences(raw, count)
82    }
83
84    unsafe fn wrap_raw<'a>(raw: &'a Self::Raw, _context: &'a Self::Context) -> Self::Wrapped<'a> {
85        CodeReference::from_raw(raw)
86    }
87}
88
89// TODO: This only exists so that Array can free.
90// TODO: Is there any way we can have this instead be Array<Location> of some sort?
91/// A struct representing a single data cross-reference.
92/// Data references have no associated metadata, so this object has only
93/// a single [`DataReference::address`] attribute.
94pub struct DataReference {
95    pub address: u64,
96}
97
98impl CoreArrayProvider for DataReference {
99    type Raw = u64;
100    type Context = ();
101    type Wrapped<'a> = DataReference;
102}
103
104unsafe impl CoreArrayProviderInner for DataReference {
105    unsafe fn free(raw: *mut Self::Raw, _count: usize, _context: &Self::Context) {
106        BNFreeDataReferences(raw)
107    }
108
109    unsafe fn wrap_raw<'a>(raw: &'a Self::Raw, _context: &'a Self::Context) -> Self::Wrapped<'a> {
110        DataReference { address: *raw }
111    }
112}