Skip to main content

binaryninja/
references.rs

1#![allow(dead_code)]
2use crate::architecture::CoreArchitecture;
3use crate::function::Function;
4use crate::rc::{CoreArrayProvider, CoreArrayProviderInner, Ref};
5use binaryninjacore_sys::{
6    BNCodeXref, BNDataXref, BNFreeCodeReferences, BNFreeCodeXrefs, BNFreeDataReferences,
7    BNFreeDataXrefs, BNReferenceSource,
8};
9
10/// A struct representing a single code cross-reference.
11#[derive(Debug)]
12pub struct CodeReference {
13    pub arch: Option<CoreArchitecture>,
14    pub func: Option<Ref<Function>>,
15    pub address: u64,
16}
17
18impl CodeReference {
19    pub(crate) fn from_raw(value: &BNReferenceSource) -> Self {
20        Self {
21            func: match value.func.is_null() {
22                false => Some(unsafe { Function::from_raw(value.func) }.to_owned()),
23                true => None,
24            },
25            arch: match value.arch.is_null() {
26                false => Some(unsafe { CoreArchitecture::from_raw(value.arch) }),
27                true => None,
28            },
29            address: value.addr,
30        }
31    }
32
33    pub(crate) fn from_owned_raw(value: BNReferenceSource) -> Self {
34        let owned = Self::from_raw(&value);
35        Self::free_raw(value);
36        owned
37    }
38
39    pub(crate) fn into_raw(value: Self) -> BNReferenceSource {
40        BNReferenceSource {
41            func: match value.func {
42                Some(func) => unsafe { Ref::into_raw(func) }.handle,
43                None => std::ptr::null_mut(),
44            },
45            arch: value.arch.map(|a| a.handle).unwrap_or(std::ptr::null_mut()),
46            addr: value.address,
47        }
48    }
49
50    pub(crate) fn into_owned_raw(value: &Self) -> BNReferenceSource {
51        BNReferenceSource {
52            func: match &value.func {
53                Some(func) => func.handle,
54                None => std::ptr::null_mut(),
55            },
56            arch: value.arch.map(|a| a.handle).unwrap_or(std::ptr::null_mut()),
57            addr: value.address,
58        }
59    }
60
61    pub(crate) fn free_raw(value: BNReferenceSource) {
62        let _ = unsafe { Function::ref_from_raw(value.func) };
63    }
64
65    pub fn new(address: u64, func: Option<Ref<Function>>, arch: Option<CoreArchitecture>) -> Self {
66        Self {
67            func,
68            arch,
69            address,
70        }
71    }
72}
73
74// Code Reference Array<T> boilerplate
75
76impl CoreArrayProvider for CodeReference {
77    type Raw = BNReferenceSource;
78    type Context = ();
79    type Wrapped<'a> = Self;
80}
81
82unsafe impl CoreArrayProviderInner for CodeReference {
83    unsafe fn free(raw: *mut Self::Raw, count: usize, _context: &Self::Context) {
84        BNFreeCodeReferences(raw, count)
85    }
86
87    unsafe fn wrap_raw<'a>(raw: &'a Self::Raw, _context: &'a Self::Context) -> Self::Wrapped<'a> {
88        CodeReference::from_raw(raw)
89    }
90}
91
92// TODO: This only exists so that Array can free.
93// TODO: Is there any way we can have this instead be Array<Location> of some sort?
94/// A struct representing a single data cross-reference.
95/// Data references have no associated metadata, so this object has only
96/// a single [`DataReference::address`] attribute.
97pub struct DataReference {
98    pub address: u64,
99}
100
101impl CoreArrayProvider for DataReference {
102    type Raw = u64;
103    type Context = ();
104    type Wrapped<'a> = DataReference;
105}
106
107unsafe impl CoreArrayProviderInner for DataReference {
108    unsafe fn free(raw: *mut Self::Raw, _count: usize, _context: &Self::Context) {
109        BNFreeDataReferences(raw)
110    }
111
112    unsafe fn wrap_raw<'a>(raw: &'a Self::Raw, _context: &'a Self::Context) -> Self::Wrapped<'a> {
113        DataReference { address: *raw }
114    }
115}
116
117/// A reference made by code, from the instruction at `source` to the address `target`.
118#[derive(Debug)]
119pub struct CodeXref {
120    pub source: CodeReference,
121    pub target: u64,
122}
123
124impl CoreArrayProvider for CodeXref {
125    type Raw = BNCodeXref;
126    type Context = ();
127    type Wrapped<'a> = Self;
128}
129
130unsafe impl CoreArrayProviderInner for CodeXref {
131    unsafe fn free(raw: *mut Self::Raw, count: usize, _context: &Self::Context) {
132        BNFreeCodeXrefs(raw, count)
133    }
134
135    unsafe fn wrap_raw<'a>(raw: &'a Self::Raw, _context: &'a Self::Context) -> Self::Wrapped<'a> {
136        CodeXref {
137            source: CodeReference::from_raw(&raw.source),
138            target: raw.target,
139        }
140    }
141}
142
143/// A reference made by data, from the address `source` to the address `target`.
144#[derive(Debug)]
145pub struct DataXref {
146    pub source: u64,
147    pub target: u64,
148}
149
150impl CoreArrayProvider for DataXref {
151    type Raw = BNDataXref;
152    type Context = ();
153    type Wrapped<'a> = Self;
154}
155
156unsafe impl CoreArrayProviderInner for DataXref {
157    unsafe fn free(raw: *mut Self::Raw, count: usize, _context: &Self::Context) {
158        BNFreeDataXrefs(raw, count)
159    }
160
161    unsafe fn wrap_raw<'a>(raw: &'a Self::Raw, _context: &'a Self::Context) -> Self::Wrapped<'a> {
162        DataXref {
163            source: raw.source,
164            target: raw.target,
165        }
166    }
167}