1use std::fmt;
18use std::fmt::Debug;
19use std::hash::{Hash, Hasher};
20use std::ptr;
21
22use crate::rc::*;
23use crate::string::*;
24use binaryninjacore_sys::*;
25
26#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
28pub enum SymbolType {
29 Function,
30 LibraryFunction,
31 ImportAddress,
32 ImportedFunction,
33 Data,
34 ImportedData,
35 External,
36 Symbolic,
37 LocalLabel,
38}
39
40impl From<BNSymbolType> for SymbolType {
41 fn from(bn: BNSymbolType) -> SymbolType {
42 use self::BNSymbolType::*;
43
44 match bn {
45 FunctionSymbol => SymbolType::Function,
46 LibraryFunctionSymbol => SymbolType::LibraryFunction,
47 ImportAddressSymbol => SymbolType::ImportAddress,
48 ImportedFunctionSymbol => SymbolType::ImportedFunction,
49 DataSymbol => SymbolType::Data,
50 ImportedDataSymbol => SymbolType::ImportedData,
51 ExternalSymbol => SymbolType::External,
52 SymbolicFunctionSymbol => SymbolType::Symbolic,
53 LocalLabelSymbol => SymbolType::LocalLabel,
54 }
55 }
56}
57
58impl From<SymbolType> for BNSymbolType {
59 fn from(symbol_type: SymbolType) -> Self {
60 use self::BNSymbolType::*;
61
62 match symbol_type {
63 SymbolType::Function => FunctionSymbol,
64 SymbolType::LibraryFunction => LibraryFunctionSymbol,
65 SymbolType::ImportAddress => ImportAddressSymbol,
66 SymbolType::ImportedFunction => ImportedFunctionSymbol,
67 SymbolType::Data => DataSymbol,
68 SymbolType::ImportedData => ImportedDataSymbol,
69 SymbolType::External => ExternalSymbol,
70 SymbolType::Symbolic => SymbolicFunctionSymbol,
71 SymbolType::LocalLabel => LocalLabelSymbol,
72 }
73 }
74}
75
76#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
77pub enum Binding {
78 None,
79 Local,
80 Global,
81 Weak,
82}
83
84impl From<BNSymbolBinding> for Binding {
85 fn from(bn: BNSymbolBinding) -> Binding {
86 use self::BNSymbolBinding::*;
87
88 match bn {
89 NoBinding => Binding::None,
90 LocalBinding => Binding::Local,
91 GlobalBinding => Binding::Global,
92 WeakBinding => Binding::Weak,
93 }
94 }
95}
96
97impl From<Binding> for BNSymbolBinding {
98 fn from(binding: Binding) -> Self {
99 use self::BNSymbolBinding::*;
100
101 match binding {
102 Binding::None => NoBinding,
103 Binding::Local => LocalBinding,
104 Binding::Global => GlobalBinding,
105 Binding::Weak => WeakBinding,
106 }
107 }
108}
109
110#[must_use]
112pub struct SymbolBuilder {
113 ty: SymbolType,
114 binding: Binding,
115 addr: u64,
116 raw_name: String,
117 short_name: Option<String>,
118 full_name: Option<String>,
119 ordinal: u64,
120}
121
122impl SymbolBuilder {
123 pub fn new<T: Into<String>>(ty: SymbolType, raw_name: T, addr: u64) -> Self {
124 Self {
125 ty,
126 binding: Binding::None,
127 addr,
128 raw_name: raw_name.into(),
129 short_name: None,
130 full_name: None,
131 ordinal: 0,
132 }
133 }
134
135 pub fn binding(mut self, binding: Binding) -> Self {
136 self.binding = binding;
137 self
138 }
139
140 pub fn short_name<T: Into<String>>(mut self, short_name: T) -> Self {
141 self.short_name = Some(short_name.into());
142 self
143 }
144
145 pub fn full_name<T: Into<String>>(mut self, full_name: T) -> Self {
146 self.full_name = Some(full_name.into());
147 self
148 }
149
150 pub fn ordinal(mut self, ordinal: u64) -> Self {
151 self.ordinal = ordinal;
152 self
153 }
154
155 pub fn create(self) -> Ref<Symbol> {
156 let raw_name = self.raw_name.to_cstr();
157 let short_name = self.short_name.map(|s| s.to_cstr());
158 let full_name = self.full_name.map(|s| s.to_cstr());
159
160 let raw_name = raw_name.as_ptr() as _;
162 unsafe {
163 if let Some(short_name) = short_name {
164 if let Some(full_name) = full_name {
165 let res = BNCreateSymbol(
166 self.ty.into(),
167 short_name.as_ptr() as _,
168 full_name.as_ptr() as _,
169 raw_name,
170 self.addr,
171 self.binding.into(),
172 ptr::null_mut(),
173 self.ordinal,
174 );
175 Symbol::ref_from_raw(res)
176 } else {
177 let res = BNCreateSymbol(
178 self.ty.into(),
179 short_name.as_ptr() as _,
180 raw_name,
181 raw_name,
182 self.addr,
183 self.binding.into(),
184 ptr::null_mut(),
185 self.ordinal,
186 );
187 Symbol::ref_from_raw(res)
188 }
189 } else if let Some(full_name) = full_name {
190 let res = BNCreateSymbol(
191 self.ty.into(),
192 raw_name,
193 full_name.as_ptr() as _,
194 raw_name,
195 self.addr,
196 self.binding.into(),
197 ptr::null_mut(),
198 self.ordinal,
199 );
200 Symbol::ref_from_raw(res)
201 } else {
202 let res = BNCreateSymbol(
203 self.ty.into(),
204 raw_name,
205 raw_name,
206 raw_name,
207 self.addr,
208 self.binding.into(),
209 ptr::null_mut(),
210 self.ordinal,
211 );
212 Symbol::ref_from_raw(res)
213 }
214 }
215 }
216}
217
218#[derive(Eq)]
219pub struct Symbol {
220 pub handle: *mut BNSymbol,
221}
222
223impl Symbol {
224 pub(crate) unsafe fn ref_from_raw(raw: *mut BNSymbol) -> Ref<Self> {
225 Ref::new(Self { handle: raw })
226 }
227
228 pub(crate) unsafe fn from_raw(raw: *mut BNSymbol) -> Self {
229 Self { handle: raw }
230 }
231
232 pub fn builder(ty: SymbolType, raw_name: &str, addr: u64) -> SymbolBuilder {
243 SymbolBuilder::new(ty, raw_name, addr)
244 }
245
246 pub fn sym_type(&self) -> SymbolType {
247 unsafe { BNGetSymbolType(self.handle).into() }
248 }
249
250 pub fn binding(&self) -> Binding {
251 unsafe { BNGetSymbolBinding(self.handle).into() }
252 }
253
254 pub fn full_name(&self) -> BnString {
255 unsafe { BnString::from_raw(BNGetSymbolFullName(self.handle)) }
256 }
257
258 pub fn short_name(&self) -> BnString {
259 unsafe { BnString::from_raw(BNGetSymbolShortName(self.handle)) }
260 }
261
262 pub fn raw_name(&self) -> BnString {
263 unsafe { BnString::from_raw(BNGetSymbolRawName(self.handle)) }
264 }
265
266 pub fn address(&self) -> u64 {
267 unsafe { BNGetSymbolAddress(self.handle) }
268 }
269
270 pub fn auto_defined(&self) -> bool {
271 unsafe { BNIsSymbolAutoDefined(self.handle) }
272 }
273
274 pub fn external(&self) -> bool {
276 self.binding() == Binding::Weak || self.binding() == Binding::Global
277 }
278
279 pub fn imported_function_from_import_address_symbol(sym: &Symbol, addr: u64) -> Ref<Symbol> {
280 unsafe {
281 let res = BNImportedFunctionFromImportAddressSymbol(sym.handle, addr);
282 Symbol::ref_from_raw(res)
283 }
284 }
285}
286
287unsafe impl Send for Symbol {}
288unsafe impl Sync for Symbol {}
289
290impl Debug for Symbol {
291 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
292 f.debug_struct("Symbol")
293 .field("type", &self.sym_type())
294 .field("binding", &self.binding())
295 .field("full_name", &self.full_name())
296 .field("short_name", &self.short_name())
297 .field("raw_name", &self.raw_name())
298 .field("address", &self.address())
299 .field("auto_defined", &self.auto_defined())
300 .field("external", &self.external())
301 .finish()
302 }
303}
304
305impl ToOwned for Symbol {
306 type Owned = Ref<Self>;
307
308 fn to_owned(&self) -> Self::Owned {
309 unsafe { RefCountable::inc_ref(self) }
310 }
311}
312
313unsafe impl RefCountable for Symbol {
314 unsafe fn inc_ref(handle: &Self) -> Ref<Self> {
315 Ref::new(Self {
316 handle: BNNewSymbolReference(handle.handle),
317 })
318 }
319
320 unsafe fn dec_ref(handle: &Self) {
321 BNFreeSymbol(handle.handle);
322 }
323}
324
325impl CoreArrayProvider for Symbol {
326 type Raw = *mut BNSymbol;
327 type Context = ();
328 type Wrapped<'a> = Guard<'a, Symbol>;
329}
330
331unsafe impl CoreArrayProviderInner for Symbol {
332 unsafe fn free(raw: *mut Self::Raw, count: usize, _context: &Self::Context) {
333 BNFreeSymbolList(raw, count);
334 }
335
336 unsafe fn wrap_raw<'a>(raw: &'a Self::Raw, context: &'a Self::Context) -> Self::Wrapped<'a> {
337 Guard::new(Symbol::from_raw(*raw), context)
338 }
339}
340
341impl Hash for Symbol {
342 fn hash<H: Hasher>(&self, state: &mut H) {
343 self.handle.hash(state);
344 }
345}
346
347impl PartialEq for Symbol {
348 fn eq(&self, other: &Self) -> bool {
349 self.handle == other.handle
350 }
351}