1use binaryninjacore_sys::*;
16
17use crate::{
18 architecture::{Architecture, CoreArchitecture, CoreRegister, Register},
19 basic_block::{BasicBlock, BlockContext},
20 binary_view::BinaryView,
21 calling_convention::CoreCallingConvention,
22 component::Component,
23 disassembly::{DisassemblySettings, DisassemblyTextLine},
24 ffi::slice_from_raw_parts,
25 flowgraph::FlowGraph,
26 medium_level_il::FunctionGraphType,
27 platform::Platform,
28 references::CodeReference,
29 string::*,
30 symbol::{Binding, Symbol},
31 tags::{Tag, TagReference, TagType},
32 types::{IntegerDisplayType, QualifiedName, ReturnValue, Type, ValueLocation},
33};
34use crate::{data_buffer::DataBuffer, disassembly::InstructionTextToken, rc::*};
35pub use binaryninjacore_sys::BNAnalysisSkipReason as AnalysisSkipReason;
36pub use binaryninjacore_sys::BNBuiltinType as BuiltinType;
37pub use binaryninjacore_sys::BNFunctionAnalysisSkipOverride as FunctionAnalysisSkipOverride;
38pub use binaryninjacore_sys::BNFunctionUpdateType as FunctionUpdateType;
39pub use binaryninjacore_sys::BNHighlightStandardColor as HighlightStandardColor;
40pub use binaryninjacore_sys::BNInlineDuringAnalysis as InlineDuringAnalysis;
41
42use crate::architecture::{IndirectBranchInfo, RegisterId};
43use crate::binary_view::AddressRange;
44use crate::confidence::Conf;
45use crate::high_level_il::HighLevelILFunction;
46use crate::language_representation::CoreLanguageRepresentationFunction;
47use crate::low_level_il::LowLevelILRegularFunction;
48use crate::medium_level_il::MediumLevelILFunction;
49use crate::metadata::Metadata;
50use crate::variable::{
51 MergedVariable, NamedVariableWithType, RegisterValue, RegisterValueType,
52 StackVariableReference, Variable,
53};
54use crate::workflow::Workflow;
55use std::collections::HashSet;
56use std::ffi::CStr;
57use std::fmt::{Debug, Formatter};
58use std::ptr::NonNull;
59use std::time::Duration;
60use std::{hash::Hash, ops::Range};
61
62#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
64pub struct Location {
65 pub arch: Option<CoreArchitecture>,
66 pub addr: u64,
67}
68
69impl Location {
70 pub(crate) fn from_raw(addr: u64, arch: *mut BNArchitecture) -> Self {
71 Self {
72 addr,
73 arch: Some(unsafe { CoreArchitecture::from_raw(arch) }),
74 }
75 }
76
77 pub fn new(arch: Option<CoreArchitecture>, addr: u64) -> Self {
78 Self { arch, addr }
79 }
80}
81
82impl From<u64> for Location {
83 fn from(addr: u64) -> Self {
84 Location::new(None, addr)
85 }
86}
87
88impl From<(CoreArchitecture, u64)> for Location {
89 fn from(loc: (CoreArchitecture, u64)) -> Self {
90 Location::new(Some(loc.0), loc.1)
91 }
92}
93
94impl From<BNArchitectureAndAddress> for Location {
95 fn from(value: BNArchitectureAndAddress) -> Self {
96 Self::from_raw(value.address, value.arch)
97 }
98}
99
100impl From<&BNArchitectureAndAddress> for Location {
101 fn from(value: &BNArchitectureAndAddress) -> Self {
102 Self::from_raw(value.address, value.arch)
103 }
104}
105
106impl From<Location> for BNArchitectureAndAddress {
107 fn from(value: Location) -> Self {
108 Self {
109 arch: value.arch.map(|a| a.handle).unwrap_or(std::ptr::null_mut()),
110 address: value.addr,
111 }
112 }
113}
114
115impl From<&Location> for BNArchitectureAndAddress {
116 fn from(value: &Location) -> Self {
117 Self::from(*value)
118 }
119}
120
121impl CoreArrayProvider for Location {
122 type Raw = BNArchitectureAndAddress;
123 type Context = ();
124 type Wrapped<'a> = Self;
125}
126
127unsafe impl CoreArrayProviderInner for Location {
128 unsafe fn free(raw: *mut Self::Raw, _count: usize, _context: &Self::Context) {
129 BNFreeArchitectureAndAddressList(raw)
131 }
132
133 unsafe fn wrap_raw<'a>(raw: &'a Self::Raw, _context: &'a Self::Context) -> Self::Wrapped<'a> {
134 Location::from(*raw)
135 }
136}
137
138pub struct NativeBlockIter {
139 arch: CoreArchitecture,
140 bv: Ref<BinaryView>,
141 cur: u64,
142 end: u64,
143}
144
145impl Iterator for NativeBlockIter {
146 type Item = u64;
147
148 fn next(&mut self) -> Option<u64> {
149 let res = self.cur;
150
151 if res >= self.end {
152 None
153 } else {
154 self.bv
155 .instruction_len(&self.arch, res)
156 .map(|x| {
157 self.cur += x as u64;
158 res
159 })
160 .or_else(|| {
161 self.cur = self.end;
162 None
163 })
164 }
165 }
166}
167
168#[derive(Clone, Debug, PartialEq, Eq)]
169pub struct NativeBlock {
170 _priv: (),
171}
172
173impl NativeBlock {
174 pub fn new() -> Self {
175 NativeBlock { _priv: () }
176 }
177}
178
179impl Default for NativeBlock {
180 fn default() -> Self {
181 NativeBlock::new()
182 }
183}
184
185impl BlockContext for NativeBlock {
186 type Instruction = u64;
187 type InstructionIndex = u64;
188 type Iter = NativeBlockIter;
189
190 fn start(&self, block: &BasicBlock<Self>) -> u64 {
191 block.start_index()
192 }
193
194 fn iter(&self, block: &BasicBlock<Self>) -> NativeBlockIter {
195 NativeBlockIter {
196 arch: block.arch(),
197 bv: block.function().view(),
198 cur: block.start_index(),
199 end: block.end_index(),
200 }
201 }
202}
203
204#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
205pub enum FunctionViewType {
206 Normal,
207 LowLevelIL,
208 LiftedIL,
209 LowLevelILSSAForm,
210 MediumLevelIL,
211 MediumLevelILSSAForm,
212 MappedMediumLevelIL,
213 MappedMediumLevelILSSAForm,
214 HighLevelIL,
215 HighLevelILSSAForm,
216 HighLevelLanguageRepresentation(String),
217}
218
219#[allow(unused)]
220impl FunctionViewType {
221 pub(crate) fn from_raw(value: &BNFunctionViewType) -> Option<Self> {
222 match value.type_ {
223 BNFunctionGraphType::InvalidILViewType => None,
224 BNFunctionGraphType::NormalFunctionGraph => Some(FunctionViewType::Normal),
225 BNFunctionGraphType::LowLevelILFunctionGraph => Some(FunctionViewType::LowLevelIL),
226 BNFunctionGraphType::LiftedILFunctionGraph => Some(FunctionViewType::LiftedIL),
227 BNFunctionGraphType::LowLevelILSSAFormFunctionGraph => {
228 Some(FunctionViewType::LowLevelILSSAForm)
229 }
230 BNFunctionGraphType::MediumLevelILFunctionGraph => {
231 Some(FunctionViewType::MediumLevelIL)
232 }
233 BNFunctionGraphType::MediumLevelILSSAFormFunctionGraph => {
234 Some(FunctionViewType::MediumLevelILSSAForm)
235 }
236 BNFunctionGraphType::MappedMediumLevelILFunctionGraph => {
237 Some(FunctionViewType::MappedMediumLevelIL)
238 }
239 BNFunctionGraphType::MappedMediumLevelILSSAFormFunctionGraph => {
240 Some(FunctionViewType::MappedMediumLevelILSSAForm)
241 }
242 BNFunctionGraphType::HighLevelILFunctionGraph => Some(FunctionViewType::HighLevelIL),
243 BNFunctionGraphType::HighLevelILSSAFormFunctionGraph => {
244 Some(FunctionViewType::HighLevelILSSAForm)
245 }
246 BNFunctionGraphType::HighLevelLanguageRepresentationFunctionGraph => {
247 Some(FunctionViewType::HighLevelLanguageRepresentation(
248 raw_to_string(value.name).unwrap(),
249 ))
250 }
251 }
252 }
253
254 pub(crate) fn from_owned_raw(value: BNFunctionViewType) -> Option<Self> {
255 let owned = Self::from_raw(&value);
256 Self::free_raw(value);
257 owned
258 }
259
260 pub(crate) fn into_raw(value: Self) -> BNFunctionViewType {
261 let view_type = match value {
262 FunctionViewType::Normal => BNFunctionGraphType::NormalFunctionGraph,
263 FunctionViewType::LowLevelIL => BNFunctionGraphType::LowLevelILFunctionGraph,
264 FunctionViewType::LiftedIL => BNFunctionGraphType::LiftedILFunctionGraph,
265 FunctionViewType::LowLevelILSSAForm => {
266 BNFunctionGraphType::LowLevelILSSAFormFunctionGraph
267 }
268 FunctionViewType::MediumLevelIL => BNFunctionGraphType::MediumLevelILFunctionGraph,
269 FunctionViewType::MediumLevelILSSAForm => {
270 BNFunctionGraphType::MediumLevelILSSAFormFunctionGraph
271 }
272 FunctionViewType::MappedMediumLevelIL => {
273 BNFunctionGraphType::MappedMediumLevelILFunctionGraph
274 }
275 FunctionViewType::MappedMediumLevelILSSAForm => {
276 BNFunctionGraphType::MappedMediumLevelILSSAFormFunctionGraph
277 }
278 FunctionViewType::HighLevelIL => BNFunctionGraphType::HighLevelILFunctionGraph,
279 FunctionViewType::HighLevelILSSAForm => {
280 BNFunctionGraphType::HighLevelILSSAFormFunctionGraph
281 }
282 FunctionViewType::HighLevelLanguageRepresentation(_) => {
283 BNFunctionGraphType::HighLevelLanguageRepresentationFunctionGraph
284 }
285 };
286 let view_name = match value {
287 FunctionViewType::HighLevelLanguageRepresentation(name) => Some(BnString::new(name)),
288 _ => None,
289 };
290 BNFunctionViewType {
291 type_: view_type,
292 name: view_name
293 .map(|n| BnString::into_raw(n) as *mut _)
294 .unwrap_or(std::ptr::null_mut()),
295 }
296 }
297
298 pub(crate) fn free_raw(value: BNFunctionViewType) {
299 unsafe { BnString::free_raw(value.name as *mut _) };
300 }
301}
302
303impl From<FunctionGraphType> for FunctionViewType {
304 fn from(view_type: FunctionGraphType) -> Self {
305 match view_type {
306 BNFunctionGraphType::LowLevelILFunctionGraph => FunctionViewType::LowLevelIL,
307 BNFunctionGraphType::LiftedILFunctionGraph => FunctionViewType::LiftedIL,
308 BNFunctionGraphType::LowLevelILSSAFormFunctionGraph => {
309 FunctionViewType::LowLevelILSSAForm
310 }
311 BNFunctionGraphType::MediumLevelILFunctionGraph => FunctionViewType::MediumLevelIL,
312 BNFunctionGraphType::MediumLevelILSSAFormFunctionGraph => {
313 FunctionViewType::MediumLevelILSSAForm
314 }
315 BNFunctionGraphType::MappedMediumLevelILFunctionGraph => {
316 FunctionViewType::MappedMediumLevelIL
317 }
318 BNFunctionGraphType::MappedMediumLevelILSSAFormFunctionGraph => {
319 FunctionViewType::MappedMediumLevelILSSAForm
320 }
321 BNFunctionGraphType::HighLevelILFunctionGraph => FunctionViewType::HighLevelIL,
322 BNFunctionGraphType::HighLevelILSSAFormFunctionGraph => {
323 FunctionViewType::HighLevelILSSAForm
324 }
325 BNFunctionGraphType::HighLevelLanguageRepresentationFunctionGraph => {
326 FunctionViewType::HighLevelLanguageRepresentation("Pseudo C".into())
328 }
329 BNFunctionGraphType::InvalidILViewType | BNFunctionGraphType::NormalFunctionGraph => {
330 FunctionViewType::Normal
331 }
332 }
333 }
334}
335
336#[derive(Eq)]
337pub struct Function {
338 pub(crate) handle: *mut BNFunction,
339}
340
341impl Function {
342 pub unsafe fn from_raw(handle: *mut BNFunction) -> Self {
343 debug_assert!(!handle.is_null());
344 Self { handle }
345 }
346
347 pub unsafe fn ref_from_raw(handle: *mut BNFunction) -> Ref<Self> {
348 debug_assert!(!handle.is_null());
349 Ref::new(Self { handle })
350 }
351
352 pub fn arch(&self) -> CoreArchitecture {
353 unsafe {
354 let arch = BNGetFunctionArchitecture(self.handle);
355 CoreArchitecture::from_raw(arch)
356 }
357 }
358
359 pub fn platform(&self) -> Ref<Platform> {
360 unsafe {
361 let plat = BNGetFunctionPlatform(self.handle);
362 Platform::ref_from_raw(plat)
363 }
364 }
365
366 pub fn view(&self) -> Ref<BinaryView> {
367 unsafe {
368 let view = BNGetFunctionData(self.handle);
369 BinaryView::ref_from_raw(view)
370 }
371 }
372
373 pub fn symbol(&self) -> Ref<Symbol> {
377 unsafe {
378 let sym = BNGetFunctionSymbol(self.handle);
379 Symbol::ref_from_raw(sym)
380 }
381 }
382
383 pub fn defined_symbol(&self) -> Option<Ref<Symbol>> {
387 self.view().symbol_by_address(self.start())
388 }
389
390 pub fn is_exported(&self) -> bool {
392 let symbol = self.symbol();
393 matches!(symbol.binding(), Binding::Global | Binding::Weak)
394 }
395
396 pub fn workflow(&self) -> Option<Ref<Workflow>> {
397 unsafe {
398 let workflow = NonNull::new(BNGetWorkflowForFunction(self.handle))?;
399 Some(Workflow::ref_from_raw(workflow))
400 }
401 }
402
403 pub fn start(&self) -> u64 {
404 unsafe { BNGetFunctionStart(self.handle) }
405 }
406
407 pub fn lowest_address(&self) -> u64 {
408 unsafe { BNGetFunctionLowestAddress(self.handle) }
409 }
410
411 pub fn highest_address(&self) -> u64 {
412 unsafe { BNGetFunctionHighestAddress(self.handle) }
413 }
414
415 pub fn address_ranges(&self) -> Array<AddressRange> {
416 unsafe {
417 let mut count = 0;
418 let addresses = BNGetFunctionAddressRanges(self.handle, &mut count);
419 Array::new(addresses, count, ())
420 }
421 }
422
423 pub fn comment(&self) -> String {
424 unsafe { BnString::into_string(BNGetFunctionComment(self.handle)) }
425 }
426
427 pub fn set_comment(&self, comment: &str) {
428 let raw = comment.to_cstr();
429
430 unsafe {
431 BNSetFunctionComment(self.handle, raw.as_ptr());
432 }
433 }
434
435 pub fn set_can_return_auto<T: Into<Conf<bool>>>(&self, can_return: T) {
436 let mut bool_with_confidence = can_return.into().into();
437 unsafe { BNSetAutoFunctionCanReturn(self.handle, &mut bool_with_confidence) }
438 }
439
440 pub fn set_can_return_user<T: Into<Conf<bool>>>(&self, can_return: T) {
441 let mut bool_with_confidence = can_return.into().into();
442 unsafe { BNSetUserFunctionCanReturn(self.handle, &mut bool_with_confidence) }
443 }
444
445 pub fn comment_at(&self, addr: u64) -> String {
446 unsafe { BnString::into_string(BNGetCommentForAddress(self.handle, addr)) }
447 }
448
449 pub fn set_comment_at(&self, addr: u64, comment: &str) {
450 let raw = comment.to_cstr();
451
452 unsafe {
453 BNSetCommentForAddress(self.handle, addr, raw.as_ptr());
454 }
455 }
456
457 pub fn comments(&self) -> Array<Comment> {
459 let mut count = 0;
460 let lines = unsafe { BNGetCommentedAddresses(self.handle, &mut count) };
461 unsafe { Array::new(lines, count, self.to_owned()) }
462 }
463
464 pub fn basic_blocks(&self) -> Array<BasicBlock<NativeBlock>> {
465 unsafe {
466 let mut count = 0;
467 let blocks = BNGetFunctionBasicBlockList(self.handle, &mut count);
468 let context = NativeBlock { _priv: () };
469
470 Array::new(blocks, count, context)
471 }
472 }
473
474 pub fn basic_block_containing(
486 &self,
487 addr: u64,
488 arch: Option<CoreArchitecture>,
489 ) -> Option<Ref<BasicBlock<NativeBlock>>> {
490 let arch = arch.unwrap_or_else(|| self.arch());
491 unsafe {
492 let basic_block_ptr = BNGetFunctionBasicBlockAtAddress(self.handle, arch.handle, addr);
493 let context = NativeBlock { _priv: () };
494 match basic_block_ptr.is_null() {
495 false => Some(BasicBlock::ref_from_raw(basic_block_ptr, context)),
496 true => None,
497 }
498 }
499 }
500
501 pub fn block_annotations(
502 &self,
503 addr: u64,
504 arch: Option<CoreArchitecture>,
505 ) -> Array<Array<InstructionTextToken>> {
506 let arch = arch.unwrap_or_else(|| self.arch());
507 let mut count = 0;
508 let lines =
509 unsafe { BNGetFunctionBlockAnnotations(self.handle, arch.handle, addr, &mut count) };
510 assert!(!lines.is_null());
511 unsafe { Array::new(lines, count, ()) }
512 }
513
514 pub fn block_sort_hint(&self, addr: u64, arch: Option<CoreArchitecture>) -> Option<i64> {
515 let arch = arch.unwrap_or_else(|| self.arch());
516 let mut result = 0;
517 unsafe {
518 BNGetFunctionBlockSortHint(self.handle, arch.handle, addr, &mut result)
519 .then_some(result)
520 }
521 }
522
523 pub fn variable_name(&self, var: &Variable) -> String {
524 unsafe {
525 let raw_var = BNVariable::from(var);
526 let raw_name = BNGetVariableName(self.handle, &raw_var);
527 BnString::into_string(raw_name)
528 }
529 }
530
531 pub fn variable_type(&self, var: &Variable) -> Option<Conf<Ref<Type>>> {
532 let raw_var = BNVariable::from(var);
533 let result = unsafe { BNGetVariableType(self.handle, &raw_var) };
534 match result.type_.is_null() {
535 false => Some(Conf::<Ref<Type>>::from_owned_raw(result)),
536 true => None,
537 }
538 }
539
540 pub fn language_representation(
544 &self,
545 language: &str,
546 ) -> Option<Ref<CoreLanguageRepresentationFunction>> {
547 let lang_name = language.to_cstr();
548 let repr = unsafe { BNGetFunctionLanguageRepresentation(self.handle, lang_name.as_ptr()) };
549 NonNull::new(repr)
550 .map(|handle| unsafe { CoreLanguageRepresentationFunction::ref_from_raw(handle) })
551 }
552
553 pub fn language_representation_if_available(
557 &self,
558 language: &str,
559 ) -> Option<Ref<CoreLanguageRepresentationFunction>> {
560 let lang_name = language.to_cstr();
561 let repr = unsafe {
562 BNGetFunctionLanguageRepresentationIfAvailable(self.handle, lang_name.as_ptr())
563 };
564 NonNull::new(repr)
565 .map(|handle| unsafe { CoreLanguageRepresentationFunction::ref_from_raw(handle) })
566 }
567
568 pub fn high_level_il(&self, full_ast: bool) -> Result<Ref<HighLevelILFunction>, ()> {
569 unsafe {
570 let hlil_ptr = BNGetFunctionHighLevelIL(self.handle);
571 match hlil_ptr.is_null() {
572 false => Ok(HighLevelILFunction::ref_from_raw(hlil_ptr, full_ast)),
573 true => Err(()),
574 }
575 }
576 }
577
578 pub fn high_level_il_if_available(&self) -> Option<Ref<HighLevelILFunction>> {
579 let hlil_ptr = unsafe { BNGetFunctionHighLevelILIfAvailable(self.handle) };
580 match hlil_ptr.is_null() {
581 false => Some(unsafe { HighLevelILFunction::ref_from_raw(hlil_ptr, true) }),
582 true => None,
583 }
584 }
585
586 pub fn mapped_medium_level_il(&self) -> Result<Ref<MediumLevelILFunction>, ()> {
588 let mlil_ptr = unsafe { BNGetFunctionMappedMediumLevelIL(self.handle) };
589 match mlil_ptr.is_null() {
590 false => Ok(unsafe { MediumLevelILFunction::ref_from_raw(mlil_ptr) }),
591 true => Err(()),
592 }
593 }
594
595 pub fn mapped_medium_level_il_if_available(&self) -> Option<Ref<MediumLevelILFunction>> {
596 let mlil_ptr = unsafe { BNGetFunctionMappedMediumLevelILIfAvailable(self.handle) };
597 match mlil_ptr.is_null() {
598 false => Some(unsafe { MediumLevelILFunction::ref_from_raw(mlil_ptr) }),
599 true => None,
600 }
601 }
602
603 pub fn medium_level_il(&self) -> Result<Ref<MediumLevelILFunction>, ()> {
604 unsafe {
605 let mlil_ptr = BNGetFunctionMediumLevelIL(self.handle);
606 match mlil_ptr.is_null() {
607 false => Ok(MediumLevelILFunction::ref_from_raw(mlil_ptr)),
608 true => Err(()),
609 }
610 }
611 }
612
613 pub fn medium_level_il_if_available(&self) -> Option<Ref<MediumLevelILFunction>> {
614 let mlil_ptr = unsafe { BNGetFunctionMediumLevelILIfAvailable(self.handle) };
615 match mlil_ptr.is_null() {
616 false => Some(unsafe { MediumLevelILFunction::ref_from_raw(mlil_ptr) }),
617 true => None,
618 }
619 }
620
621 pub fn low_level_il(&self) -> Result<Ref<LowLevelILRegularFunction>, ()> {
622 unsafe {
623 let llil_ptr = BNGetFunctionLowLevelIL(self.handle);
624 match llil_ptr.is_null() {
625 false => Ok(LowLevelILRegularFunction::ref_from_raw(llil_ptr)),
626 true => Err(()),
627 }
628 }
629 }
630
631 pub fn low_level_il_if_available(&self) -> Option<Ref<LowLevelILRegularFunction>> {
632 let llil_ptr = unsafe { BNGetFunctionLowLevelILIfAvailable(self.handle) };
633 match llil_ptr.is_null() {
634 false => Some(unsafe { LowLevelILRegularFunction::ref_from_raw(llil_ptr) }),
635 true => None,
636 }
637 }
638
639 pub fn lifted_il(&self) -> Result<Ref<LowLevelILRegularFunction>, ()> {
640 unsafe {
641 let llil_ptr = BNGetFunctionLiftedIL(self.handle);
642 match llil_ptr.is_null() {
643 false => Ok(LowLevelILRegularFunction::ref_from_raw(llil_ptr)),
644 true => Err(()),
645 }
646 }
647 }
648
649 pub fn lifted_il_if_available(&self) -> Option<Ref<LowLevelILRegularFunction>> {
650 let llil_ptr = unsafe { BNGetFunctionLiftedILIfAvailable(self.handle) };
651 match llil_ptr.is_null() {
652 false => Some(unsafe { LowLevelILRegularFunction::ref_from_raw(llil_ptr) }),
653 true => None,
654 }
655 }
656
657 pub fn return_type(&self) -> Conf<Ref<Type>> {
658 let raw_return_type = unsafe { BNGetFunctionReturnType(self.handle) };
659 Conf::<Ref<Type>>::from_owned_raw(raw_return_type)
660 }
661
662 pub fn return_value(&self) -> ReturnValue {
663 let raw_return_value = unsafe { BNGetFunctionReturnValue(self.handle) };
664 ReturnValue::from_owned_core_raw(raw_return_value)
665 }
666
667 pub fn set_auto_return_type<'a, C>(&self, return_type: C)
668 where
669 C: Into<Conf<&'a Type>>,
670 {
671 let mut raw_return_type = Conf::<&Type>::into_raw(return_type.into());
672 unsafe { BNSetAutoFunctionReturnType(self.handle, &mut raw_return_type) }
673 }
674
675 pub fn set_auto_is_return_value_default_location(&self, is_default: bool) {
676 unsafe { BNSetAutoIsFunctionReturnValueDefaultLocation(self.handle, is_default) }
677 }
678
679 pub fn set_auto_return_value_location(&self, location: impl Into<Conf<ValueLocation>>) {
680 let mut raw_location = Conf::<ValueLocation>::into_rust_raw(location.into());
681 unsafe { BNSetAutoFunctionReturnValueLocation(self.handle, &mut raw_location) };
682 Conf::<ValueLocation>::free_rust_raw(raw_location);
683 }
684
685 pub fn set_auto_return_value(&self, return_value: impl Into<ReturnValue>) {
686 let mut raw_return_value = ReturnValue::into_rust_raw(&return_value.into());
687 unsafe { BNSetAutoFunctionReturnValue(self.handle, &mut raw_return_value) }
688 ReturnValue::free_rust_raw(raw_return_value);
689 }
690
691 pub fn set_user_return_type<'a, C>(&self, return_type: C)
692 where
693 C: Into<Conf<&'a Type>>,
694 {
695 let mut raw_return_type = Conf::<&Type>::into_raw(return_type.into());
696 unsafe { BNSetUserFunctionReturnType(self.handle, &mut raw_return_type) }
697 }
698
699 pub fn set_user_is_return_value_default_location(&self, is_default: bool) {
700 unsafe { BNSetUserIsFunctionReturnValueDefaultLocation(self.handle, is_default) }
701 }
702
703 pub fn set_user_return_value_location(&self, location: impl Into<Conf<ValueLocation>>) {
704 let mut raw_location = Conf::<ValueLocation>::into_rust_raw(location.into());
705 unsafe { BNSetUserFunctionReturnValueLocation(self.handle, &mut raw_location) };
706 Conf::<ValueLocation>::free_rust_raw(raw_location);
707 }
708
709 pub fn set_user_return_value(&self, return_value: impl Into<ReturnValue>) {
710 let mut raw_return_value = ReturnValue::into_rust_raw(&return_value.into());
711 unsafe { BNSetUserFunctionReturnValue(self.handle, &mut raw_return_value) }
712 ReturnValue::free_rust_raw(raw_return_value);
713 }
714
715 pub fn function_type(&self) -> Ref<Type> {
716 unsafe { Type::ref_from_raw(BNGetFunctionType(self.handle)) }
717 }
718
719 pub fn has_user_type(&self) -> bool {
720 unsafe { BNFunctionHasUserType(self.handle) }
721 }
722
723 pub fn set_user_type(&self, t: &Type) {
724 unsafe { BNSetFunctionUserType(self.handle, t.handle) }
725 }
726
727 pub fn set_auto_type(&self, t: &Type) {
728 unsafe { BNSetFunctionAutoType(self.handle, t.handle) }
729 }
730
731 pub fn stack_layout(&self) -> Array<NamedVariableWithType> {
732 let mut count = 0;
733 unsafe {
734 let variables = BNGetStackLayout(self.handle, &mut count);
735 Array::new(variables, count, ())
736 }
737 }
738
739 pub fn stack_adjustment(&self) -> Conf<i64> {
741 unsafe { BNGetFunctionStackAdjustment(self.handle) }.into()
742 }
743
744 pub fn set_user_stack_adjustment<C>(&self, value: C)
746 where
747 C: Into<Conf<i64>>,
748 {
749 let value: Conf<i64> = value.into();
750 let mut value_raw = value.into();
751 unsafe { BNSetUserFunctionStackAdjustment(self.handle, &mut value_raw) }
752 }
753
754 pub fn set_auto_stack_adjustment<C>(&self, value: C)
756 where
757 C: Into<Conf<i64>>,
758 {
759 let value: Conf<i64> = value.into();
760 let mut value_raw = value.into();
761 unsafe { BNSetAutoFunctionStackAdjustment(self.handle, &mut value_raw) }
762 }
763
764 pub fn call_stack_adjustment(&self, addr: u64, arch: Option<CoreArchitecture>) -> Conf<i64> {
765 let arch = arch.unwrap_or_else(|| self.arch());
766 let result = unsafe { BNGetCallStackAdjustment(self.handle, arch.handle, addr) };
767 result.into()
768 }
769
770 pub fn set_user_call_stack_adjustment<I>(
771 &self,
772 addr: u64,
773 adjust: I,
774 arch: Option<CoreArchitecture>,
775 ) where
776 I: Into<Conf<i64>>,
777 {
778 let arch = arch.unwrap_or_else(|| self.arch());
779 let adjust: Conf<i64> = adjust.into();
780 unsafe {
781 BNSetUserCallStackAdjustment(
782 self.handle,
783 arch.handle,
784 addr,
785 adjust.contents,
786 adjust.confidence,
787 )
788 }
789 }
790
791 pub fn set_auto_call_stack_adjustment<I>(
792 &self,
793 addr: u64,
794 adjust: I,
795 arch: Option<CoreArchitecture>,
796 ) where
797 I: Into<Conf<i64>>,
798 {
799 let arch = arch.unwrap_or_else(|| self.arch());
800 let adjust: Conf<i64> = adjust.into();
801 unsafe {
802 BNSetAutoCallStackAdjustment(
803 self.handle,
804 arch.handle,
805 addr,
806 adjust.contents,
807 adjust.confidence,
808 )
809 }
810 }
811
812 pub fn call_type_adjustment(
813 &self,
814 addr: u64,
815 arch: Option<CoreArchitecture>,
816 ) -> Option<Conf<Ref<Type>>> {
817 let arch = arch.unwrap_or_else(|| self.arch());
818 let result = unsafe { BNGetCallTypeAdjustment(self.handle, arch.handle, addr) };
819 match result.type_.is_null() {
820 false => Some(Conf::<Ref<Type>>::from_owned_raw(result)),
821 true => None,
822 }
823 }
824
825 pub fn set_user_call_type_adjustment<'a, I>(
831 &self,
832 addr: u64,
833 adjust_type: Option<I>,
834 arch: Option<CoreArchitecture>,
835 ) where
836 I: Into<Conf<&'a Type>>,
837 {
838 let arch = arch.unwrap_or_else(|| self.arch());
839 let mut adjust_type = adjust_type.map(|adjust_type| {
840 let adjust_type = adjust_type.into();
841 BNTypeWithConfidence {
842 type_: adjust_type.contents.handle,
843 confidence: adjust_type.confidence,
844 }
845 });
846 let adjust_ptr = adjust_type
847 .as_mut()
848 .map(|x| x as *mut _)
849 .unwrap_or(std::ptr::null_mut());
850 unsafe { BNSetUserCallTypeAdjustment(self.handle, arch.handle, addr, adjust_ptr) }
851 }
852
853 pub fn set_auto_call_type_adjustment<'a, I>(
854 &self,
855 addr: u64,
856 adjust_type: I,
857 arch: Option<CoreArchitecture>,
858 ) where
859 I: Into<Conf<&'a Type>>,
860 {
861 let arch = arch.unwrap_or_else(|| self.arch());
862 let adjust_type: Conf<&Type> = adjust_type.into();
863 unsafe {
864 BNSetAutoCallTypeAdjustment(
865 self.handle,
866 arch.handle,
867 addr,
868 &mut BNTypeWithConfidence {
869 type_: adjust_type.contents.handle,
870 confidence: adjust_type.confidence,
871 },
872 )
873 }
874 }
875
876 pub fn call_reg_stack_adjustment(
877 &self,
878 addr: u64,
879 arch: Option<CoreArchitecture>,
880 ) -> Array<RegisterStackAdjustment> {
881 let arch = arch.unwrap_or_else(|| self.arch());
882 let mut count = 0;
883 let adjust =
884 unsafe { BNGetCallRegisterStackAdjustment(self.handle, arch.handle, addr, &mut count) };
885 assert!(!adjust.is_null());
886 unsafe { Array::new(adjust, count, ()) }
887 }
888
889 pub fn set_user_call_reg_stack_adjustment<I>(
890 self,
891 addr: u64,
892 adjust: I,
893 arch: Option<CoreArchitecture>,
894 ) where
895 I: IntoIterator<Item = RegisterStackAdjustment>,
896 {
897 let arch = arch.unwrap_or_else(|| self.arch());
898 let adjustments: Vec<BNRegisterStackAdjustment> =
899 adjust.into_iter().map(Into::into).collect();
900 unsafe {
901 BNSetUserCallRegisterStackAdjustment(
902 self.handle,
903 arch.handle,
904 addr,
905 adjustments.as_ptr() as *mut _,
906 adjustments.len(),
907 )
908 }
909 }
910
911 pub fn set_auto_call_reg_stack_adjustment<I>(
912 &self,
913 addr: u64,
914 adjust: I,
915 arch: Option<CoreArchitecture>,
916 ) where
917 I: IntoIterator<Item = RegisterStackAdjustment>,
918 {
919 let arch = arch.unwrap_or_else(|| self.arch());
920 let adjustments: Vec<BNRegisterStackAdjustment> =
921 adjust.into_iter().map(Into::into).collect();
922 unsafe {
923 BNSetAutoCallRegisterStackAdjustment(
924 self.handle,
925 arch.handle,
926 addr,
927 adjustments.as_ptr() as *mut _,
928 adjustments.len(),
929 )
930 }
931 }
932
933 pub fn call_reg_stack_adjustment_for_reg_stack(
934 &self,
935 addr: u64,
936 reg_stack_id: u32,
937 arch: Option<CoreArchitecture>,
938 ) -> RegisterStackAdjustment {
939 let arch = arch.unwrap_or_else(|| self.arch());
940 let adjust = unsafe {
941 BNGetCallRegisterStackAdjustmentForRegisterStack(
942 self.handle,
943 arch.handle,
944 addr,
945 reg_stack_id,
946 )
947 };
948 RegisterStackAdjustment::from(adjust)
949 }
950
951 pub fn set_user_call_reg_stack_adjustment_for_reg_stack<I>(
952 &self,
953 addr: u64,
954 reg_stack_id: u32,
955 adjust: I,
956 arch: Option<CoreArchitecture>,
957 ) where
958 I: Into<Conf<i32>>,
959 {
960 let arch = arch.unwrap_or_else(|| self.arch());
961 let adjust: Conf<i32> = adjust.into();
962 unsafe {
963 BNSetUserCallRegisterStackAdjustmentForRegisterStack(
964 self.handle,
965 arch.handle,
966 addr,
967 reg_stack_id,
968 adjust.contents,
969 adjust.confidence,
970 )
971 }
972 }
973
974 pub fn set_auto_call_reg_stack_adjustment_for_reg_stack<I>(
975 &self,
976 addr: u64,
977 reg_stack_id: u32,
978 adjust: I,
979 arch: Option<CoreArchitecture>,
980 ) where
981 I: Into<Conf<i32>>,
982 {
983 let arch = arch.unwrap_or_else(|| self.arch());
984 let adjust: Conf<i32> = adjust.into();
985 unsafe {
986 BNSetAutoCallRegisterStackAdjustmentForRegisterStack(
987 self.handle,
988 arch.handle,
989 addr,
990 reg_stack_id,
991 adjust.contents,
992 adjust.confidence,
993 )
994 }
995 }
996
997 pub fn reg_stack_adjustments(&self) -> Array<RegisterStackAdjustment> {
998 let mut count = 0;
999 let adjust = unsafe { BNGetFunctionRegisterStackAdjustments(self.handle, &mut count) };
1000 assert!(!adjust.is_null());
1001 unsafe { Array::new(adjust, count, ()) }
1002 }
1003
1004 pub fn set_user_reg_stack_adjustments<I>(&self, values: I)
1005 where
1006 I: IntoIterator<Item = RegisterStackAdjustment>,
1007 {
1008 let values: Vec<BNRegisterStackAdjustment> = values.into_iter().map(Into::into).collect();
1009 unsafe {
1010 BNSetUserFunctionRegisterStackAdjustments(
1011 self.handle,
1012 values.as_ptr() as *mut _,
1013 values.len(),
1014 )
1015 }
1016 }
1017
1018 pub fn set_auto_reg_stack_adjustments<I>(&self, values: I)
1019 where
1020 I: IntoIterator<Item = RegisterStackAdjustment>,
1021 {
1022 let values: Vec<BNRegisterStackAdjustment> = values.into_iter().map(Into::into).collect();
1023 unsafe {
1024 BNSetAutoFunctionRegisterStackAdjustments(
1025 self.handle,
1026 values.as_ptr() as *mut _,
1027 values.len(),
1028 )
1029 }
1030 }
1031
1032 pub fn variables(&self) -> Array<NamedVariableWithType> {
1035 let mut count = 0;
1036 let vars = unsafe { BNGetFunctionVariables(self.handle, &mut count) };
1037 assert!(!vars.is_null());
1038 unsafe { Array::new(vars, count, ()) }
1039 }
1040
1041 pub fn split_variables(&self) -> Array<Variable> {
1042 let mut count = 0;
1043 let vars = unsafe { BNGetSplitVariables(self.handle, &mut count) };
1044 assert!(!vars.is_null());
1045 unsafe { Array::new(vars, count, ()) }
1046 }
1047
1048 pub fn parameter_variables(&self) -> Conf<Vec<Variable>> {
1049 unsafe {
1050 let mut raw_variables = BNGetFunctionParameterVariables(self.handle);
1051 let raw_var_list = std::slice::from_raw_parts(raw_variables.vars, raw_variables.count);
1052 let variables: Vec<Variable> = raw_var_list.iter().map(Into::into).collect();
1053 let confidence = raw_variables.confidence;
1054 BNFreeParameterVariables(&mut raw_variables);
1055 Conf::new(variables, confidence)
1056 }
1057 }
1058
1059 pub fn parameter_locations(&self) -> Conf<Vec<ValueLocation>> {
1060 unsafe {
1061 let mut raw_locations = BNGetFunctionParameterLocations(self.handle);
1062 let raw_location_list =
1063 slice_from_raw_parts(raw_locations.locations, raw_locations.count);
1064 let locations: Vec<ValueLocation> = raw_location_list
1065 .iter()
1066 .map(ValueLocation::from_raw)
1067 .collect();
1068 let confidence = raw_locations.confidence;
1069 BNFreeParameterLocations(&mut raw_locations);
1070 Conf::new(locations, confidence)
1071 }
1072 }
1073
1074 pub fn set_user_parameter_locations<I>(&self, values: I, confidence: u8)
1075 where
1076 I: IntoIterator<Item = ValueLocation>,
1077 {
1078 let locations: Vec<BNValueLocation> = values
1079 .into_iter()
1080 .map(|location| ValueLocation::into_rust_raw(&location))
1081 .collect();
1082 unsafe {
1083 BNSetUserFunctionParameterLocations(
1084 self.handle,
1085 &mut BNValueLocationListWithConfidence {
1086 locations: locations.as_ptr() as *mut _,
1087 count: locations.len(),
1088 confidence,
1089 },
1090 )
1091 }
1092 locations.into_iter().for_each(ValueLocation::free_rust_raw);
1093 }
1094
1095 pub fn set_auto_parameter_locations<I>(&self, values: I, confidence: u8)
1096 where
1097 I: IntoIterator<Item = ValueLocation>,
1098 {
1099 let locations: Vec<BNValueLocation> = values
1100 .into_iter()
1101 .map(|location| ValueLocation::into_rust_raw(&location))
1102 .collect();
1103 unsafe {
1104 BNSetAutoFunctionParameterLocations(
1105 self.handle,
1106 &mut BNValueLocationListWithConfidence {
1107 locations: locations.as_ptr() as *mut _,
1108 count: locations.len(),
1109 confidence,
1110 },
1111 )
1112 }
1113 locations.into_iter().for_each(ValueLocation::free_rust_raw);
1114 }
1115
1116 pub fn parameter_at(
1117 &self,
1118 addr: u64,
1119 func_type: Option<&Type>,
1120 i: usize,
1121 arch: Option<CoreArchitecture>,
1122 ) -> RegisterValue {
1123 let arch = arch.unwrap_or_else(|| self.arch());
1124 let func_type = func_type.map(|f| f.handle).unwrap_or(std::ptr::null_mut());
1125 let value = unsafe {
1126 BNGetParameterValueAtInstruction(self.handle, arch.handle, addr, func_type, i)
1127 };
1128 value.into()
1129 }
1130
1131 pub fn parameter_at_low_level_il_instruction(
1132 &self,
1133 instr: usize,
1134 func_type: &Type,
1135 i: usize,
1136 ) -> RegisterValue {
1137 let value = unsafe {
1138 BNGetParameterValueAtLowLevelILInstruction(self.handle, instr, func_type.handle, i)
1139 };
1140 value.into()
1141 }
1142
1143 pub fn apply_imported_types(&self, sym: &Symbol, t: Option<&Type>) {
1144 unsafe {
1145 BNApplyImportedTypes(
1146 self.handle,
1147 sym.handle,
1148 t.map(|t| t.handle).unwrap_or(std::ptr::null_mut()),
1149 );
1150 }
1151 }
1152
1153 pub fn apply_auto_discovered_type(&self, func_type: &Type) {
1154 unsafe { BNApplyAutoDiscoveredFunctionType(self.handle, func_type.handle) }
1155 }
1156
1157 pub fn analysis_skipped(&self) -> bool {
1160 unsafe { BNIsFunctionAnalysisSkipped(self.handle) }
1161 }
1162
1163 pub fn set_analysis_skipped(&self, skip: bool) {
1164 if skip {
1165 unsafe {
1166 BNSetFunctionAnalysisSkipOverride(
1167 self.handle,
1168 BNFunctionAnalysisSkipOverride::AlwaysSkipFunctionAnalysis,
1169 );
1170 }
1171 } else {
1172 unsafe {
1173 BNSetFunctionAnalysisSkipOverride(
1174 self.handle,
1175 BNFunctionAnalysisSkipOverride::NeverSkipFunctionAnalysis,
1176 );
1177 }
1178 }
1179 }
1180
1181 pub fn analysis_skip_reason(&self) -> AnalysisSkipReason {
1182 unsafe { BNGetAnalysisSkipReason(self.handle) }
1183 }
1184
1185 pub fn analysis_skip_override(&self) -> FunctionAnalysisSkipOverride {
1186 unsafe { BNGetFunctionAnalysisSkipOverride(self.handle) }
1187 }
1188
1189 pub fn set_analysis_skip_override(&self, override_: FunctionAnalysisSkipOverride) {
1190 unsafe { BNSetFunctionAnalysisSkipOverride(self.handle, override_) }
1191 }
1192
1193 pub fn inline_during_analysis(&self) -> Conf<bool> {
1195 let result = unsafe { BNIsFunctionInlinedDuringAnalysis(self.handle) };
1196 result.into()
1197 }
1198
1199 pub fn set_auto_inline_during_analysis<C>(&self, value: C)
1200 where
1201 C: Into<Conf<InlineDuringAnalysis>>,
1202 {
1203 let value: Conf<InlineDuringAnalysis> = value.into();
1204 unsafe { BNSetAutoFunctionInlinedDuringAnalysis(self.handle, value.into()) }
1205 }
1206
1207 pub fn set_user_inline_during_analysis<C>(&self, value: C)
1208 where
1209 C: Into<Conf<InlineDuringAnalysis>>,
1210 {
1211 let value: Conf<InlineDuringAnalysis> = value.into();
1212 unsafe { BNSetUserFunctionInlinedDuringAnalysis(self.handle, value.into()) }
1213 }
1214
1215 pub fn analysis_performance_info(&self) -> Array<PerformanceInfo> {
1216 let mut count = 0;
1217 let info = unsafe { BNGetFunctionAnalysisPerformanceInfo(self.handle, &mut count) };
1218 assert!(!info.is_null());
1219 unsafe { Array::new(info, count, ()) }
1220 }
1221
1222 pub fn add_tag(
1256 &self,
1257 tag_type: &TagType,
1258 data: &str,
1259 addr: Option<u64>,
1260 user: bool,
1261 arch: Option<CoreArchitecture>,
1262 ) {
1263 let arch = arch.unwrap_or_else(|| self.arch());
1264
1265 let tag = Tag::new(tag_type, data);
1267 unsafe { BNAddTag(self.view().handle, tag.handle, user) };
1268
1269 unsafe {
1270 match (user, addr) {
1271 (false, None) => BNAddAutoFunctionTag(self.handle, tag.handle),
1272 (false, Some(addr)) => {
1273 BNAddAutoAddressTag(self.handle, arch.handle, addr, tag.handle)
1274 }
1275 (true, None) => BNAddUserFunctionTag(self.handle, tag.handle),
1276 (true, Some(addr)) => {
1277 BNAddUserAddressTag(self.handle, arch.handle, addr, tag.handle)
1278 }
1279 }
1280 }
1281 }
1282
1283 pub fn remove_tag(
1289 &self,
1290 tag: &Tag,
1291 addr: Option<u64>,
1292 user: bool,
1293 arch: Option<CoreArchitecture>,
1294 ) {
1295 let arch = arch.unwrap_or_else(|| self.arch());
1296 unsafe {
1297 match (user, addr) {
1298 (false, None) => BNRemoveAutoFunctionTag(self.handle, tag.handle),
1299 (false, Some(addr)) => {
1300 BNRemoveAutoAddressTag(self.handle, arch.handle, addr, tag.handle)
1301 }
1302 (true, None) => BNRemoveUserFunctionTag(self.handle, tag.handle),
1303 (true, Some(addr)) => {
1304 BNRemoveUserAddressTag(self.handle, arch.handle, addr, tag.handle)
1305 }
1306 }
1307 }
1308 }
1309
1310 pub fn remove_tags_of_type(
1317 &self,
1318 tag_type: &TagType,
1319 addr: Option<u64>,
1320 user: bool,
1321 arch: Option<CoreArchitecture>,
1322 ) {
1323 let arch = arch.unwrap_or_else(|| self.arch());
1324 unsafe {
1325 match (user, addr) {
1326 (false, None) => BNRemoveAutoFunctionTagsOfType(self.handle, tag_type.handle),
1327 (false, Some(addr)) => {
1328 BNRemoveAutoAddressTagsOfType(self.handle, arch.handle, addr, tag_type.handle)
1329 }
1330 (true, None) => BNRemoveUserFunctionTagsOfType(self.handle, tag_type.handle),
1331 (true, Some(addr)) => {
1332 BNRemoveUserAddressTagsOfType(self.handle, arch.handle, addr, tag_type.handle)
1333 }
1334 }
1335 }
1336 }
1337
1338 pub fn add_user_code_ref(&self, from_addr: u64, to_addr: u64, arch: Option<CoreArchitecture>) {
1355 let arch = arch.unwrap_or_else(|| self.arch());
1356 unsafe { BNAddUserCodeReference(self.handle, arch.handle, from_addr, to_addr) }
1357 }
1358
1359 pub fn remove_user_code_ref(
1375 self,
1376 from_addr: u64,
1377 to_addr: u64,
1378 arch: Option<CoreArchitecture>,
1379 ) {
1380 let arch = arch.unwrap_or_else(|| self.arch());
1381 unsafe { BNRemoveUserCodeReference(self.handle, arch.handle, from_addr, to_addr) }
1382 }
1383
1384 pub fn add_user_type_ref<T: Into<QualifiedName>>(
1400 &self,
1401 from_addr: u64,
1402 name: T,
1403 arch: Option<CoreArchitecture>,
1404 ) {
1405 let arch = arch.unwrap_or_else(|| self.arch());
1406 let mut raw_name = QualifiedName::into_raw(name.into());
1407 unsafe { BNAddUserTypeReference(self.handle, arch.handle, from_addr, &mut raw_name) };
1408 QualifiedName::free_raw(raw_name);
1409 }
1410
1411 pub fn remove_user_type_ref<T: Into<QualifiedName>>(
1426 &self,
1427 from_addr: u64,
1428 name: T,
1429 arch: Option<CoreArchitecture>,
1430 ) {
1431 let arch = arch.unwrap_or_else(|| self.arch());
1432 let mut raw_name = QualifiedName::into_raw(name.into());
1433 unsafe { BNRemoveUserTypeReference(self.handle, arch.handle, from_addr, &mut raw_name) };
1434 QualifiedName::free_raw(raw_name);
1435 }
1436
1437 pub fn add_user_type_field_ref<T: Into<QualifiedName>>(
1455 &self,
1456 from_addr: u64,
1457 name: T,
1458 offset: u64,
1459 arch: Option<CoreArchitecture>,
1460 size: Option<usize>,
1461 ) {
1462 let size = size.unwrap_or(0);
1463 let arch = arch.unwrap_or_else(|| self.arch());
1464 let mut raw_name = QualifiedName::into_raw(name.into());
1465 unsafe {
1466 BNAddUserTypeFieldReference(
1467 self.handle,
1468 arch.handle,
1469 from_addr,
1470 &mut raw_name,
1471 offset,
1472 size,
1473 )
1474 };
1475 QualifiedName::free_raw(raw_name);
1476 }
1477
1478 pub fn remove_user_type_field_ref<T: Into<QualifiedName>>(
1495 &self,
1496 from_addr: u64,
1497 name: T,
1498 offset: u64,
1499 arch: Option<CoreArchitecture>,
1500 size: Option<usize>,
1501 ) {
1502 let size = size.unwrap_or(0);
1503 let arch = arch.unwrap_or_else(|| self.arch());
1504 let mut raw_name = QualifiedName::into_raw(name.into());
1505 unsafe {
1506 BNRemoveUserTypeFieldReference(
1507 self.handle,
1508 arch.handle,
1509 from_addr,
1510 &mut raw_name,
1511 offset,
1512 size,
1513 )
1514 }
1515 QualifiedName::free_raw(raw_name);
1516 }
1517
1518 pub fn constant_data(
1519 &self,
1520 state: RegisterValueType,
1521 value: u64,
1522 size: Option<usize>,
1523 ) -> (DataBuffer, BuiltinType) {
1524 let size = size.unwrap_or(0);
1525 let mut builtin_type = BuiltinType::BuiltinNone;
1527 let buffer = DataBuffer::from_raw(unsafe {
1528 BNGetConstantData(self.handle, state, value, size, &mut builtin_type)
1529 });
1530 (buffer, builtin_type)
1531 }
1532
1533 pub fn constants_referenced_by(
1534 &self,
1535 addr: u64,
1536 arch: Option<CoreArchitecture>,
1537 ) -> Array<ConstantReference> {
1538 let arch = arch.unwrap_or_else(|| self.arch());
1539 let mut count = 0;
1540 let refs = unsafe {
1541 BNGetConstantsReferencedByInstruction(self.handle, arch.handle, addr, &mut count)
1542 };
1543 assert!(!refs.is_null());
1544 unsafe { Array::new(refs, count, ()) }
1545 }
1546
1547 pub fn constants_referenced_by_address_if_available(
1548 &self,
1549 addr: u64,
1550 arch: Option<CoreArchitecture>,
1551 ) -> Array<ConstantReference> {
1552 let arch = arch.unwrap_or_else(|| self.arch());
1553 let mut count = 0;
1554 let refs = unsafe {
1555 BNGetConstantsReferencedByInstructionIfAvailable(
1556 self.handle,
1557 arch.handle,
1558 addr,
1559 &mut count,
1560 )
1561 };
1562 assert!(!refs.is_null());
1563 unsafe { Array::new(refs, count, ()) }
1564 }
1565
1566 pub fn function_tags(&self, auto: Option<bool>, tag_type: Option<&str>) -> Array<Tag> {
1571 let mut count = 0;
1572
1573 let tag_type = tag_type.map(|tag_type| self.view().tag_type_by_name(tag_type));
1574
1575 let tags = unsafe {
1576 match (tag_type, auto) {
1577 (Some(None), _) => return Array::new(std::ptr::null_mut(), 0, ()),
1579
1580 (Some(Some(tag_type)), None) => {
1582 BNGetFunctionTagsOfType(self.handle, tag_type.handle, &mut count)
1583 }
1584 (Some(Some(tag_type)), Some(true)) => {
1585 BNGetAutoFunctionTagsOfType(self.handle, tag_type.handle, &mut count)
1586 }
1587 (Some(Some(tag_type)), Some(false)) => {
1588 BNGetUserFunctionTagsOfType(self.handle, tag_type.handle, &mut count)
1589 }
1590 (None, None) => BNGetFunctionTags(self.handle, &mut count),
1592 (None, Some(true)) => BNGetAutoFunctionTags(self.handle, &mut count),
1593 (None, Some(false)) => BNGetUserFunctionTags(self.handle, &mut count),
1594 }
1595 };
1596 assert!(!tags.is_null());
1597
1598 unsafe { Array::new(tags, count, ()) }
1599 }
1600
1601 pub fn tags(&self) -> Array<TagReference> {
1602 let mut count = 0;
1603 let tags = unsafe { BNGetAddressTagReferences(self.handle, &mut count) };
1604 unsafe { Array::new(tags, count, ()) }
1605 }
1606
1607 pub fn tags_at(
1612 &self,
1613 addr: u64,
1614 auto: Option<bool>,
1615 arch: Option<CoreArchitecture>,
1616 ) -> Array<Tag> {
1617 let arch = arch.unwrap_or_else(|| self.arch());
1618 let mut count = 0;
1619
1620 let tags = match auto {
1621 None => unsafe { BNGetAddressTags(self.handle, arch.handle, addr, &mut count) },
1622 Some(true) => unsafe {
1623 BNGetAutoAddressTags(self.handle, arch.handle, addr, &mut count)
1624 },
1625 Some(false) => unsafe {
1626 BNGetUserAddressTags(self.handle, arch.handle, addr, &mut count)
1627 },
1628 };
1629 assert!(!tags.is_null());
1630 unsafe { Array::new(tags, count, ()) }
1631 }
1632
1633 pub fn tags_in_range(
1638 &self,
1639 range: Range<u64>,
1640 auto: Option<bool>,
1641 arch: Option<CoreArchitecture>,
1642 ) -> Array<TagReference> {
1643 let arch = arch.unwrap_or_else(|| self.arch());
1644 let mut count = 0;
1645
1646 let tags = match auto {
1647 None => unsafe {
1648 BNGetAddressTagsInRange(
1649 self.handle,
1650 arch.handle,
1651 range.start,
1652 range.end,
1653 &mut count,
1654 )
1655 },
1656 Some(true) => unsafe {
1657 BNGetAutoAddressTagsInRange(
1658 self.handle,
1659 arch.handle,
1660 range.start,
1661 range.end,
1662 &mut count,
1663 )
1664 },
1665 Some(false) => unsafe {
1666 BNGetUserAddressTagsInRange(
1667 self.handle,
1668 arch.handle,
1669 range.start,
1670 range.end,
1671 &mut count,
1672 )
1673 },
1674 };
1675 assert!(!tags.is_null());
1676 unsafe { Array::new(tags, count, ()) }
1677 }
1678
1679 pub fn indirect_branches(&self) -> Array<IndirectBranchInfo> {
1681 let mut count = 0;
1682 let branches = unsafe { BNGetIndirectBranches(self.handle, &mut count) };
1683 assert!(!branches.is_null());
1684 unsafe { Array::new(branches, count, ()) }
1685 }
1686
1687 pub fn set_user_indirect_branches<I>(
1688 &self,
1689 source: u64,
1690 branches: I,
1691 arch: Option<CoreArchitecture>,
1692 ) where
1693 I: IntoIterator<Item = u64>,
1694 {
1695 let arch = arch.unwrap_or_else(|| self.arch());
1696 let mut branches: Box<[BNArchitectureAndAddress]> = branches
1697 .into_iter()
1698 .map(|address| BNArchitectureAndAddress {
1699 address,
1700 arch: arch.handle,
1701 })
1702 .collect();
1703 unsafe {
1704 BNSetUserIndirectBranches(
1705 self.handle,
1706 arch.handle,
1707 source,
1708 branches.as_mut_ptr(),
1709 branches.len(),
1710 )
1711 }
1712 }
1713
1714 pub fn set_auto_indirect_branches<I>(
1715 &self,
1716 source: u64,
1717 branches: I,
1718 arch: Option<CoreArchitecture>,
1719 ) where
1720 I: IntoIterator<Item = u64>,
1721 {
1722 let arch = arch.unwrap_or_else(|| self.arch());
1723 let mut branches: Box<[BNArchitectureAndAddress]> = branches
1724 .into_iter()
1725 .map(|address| BNArchitectureAndAddress {
1726 address,
1727 arch: arch.handle,
1728 })
1729 .collect();
1730 unsafe {
1731 BNSetAutoIndirectBranches(
1732 self.handle,
1733 arch.handle,
1734 source,
1735 branches.as_mut_ptr(),
1736 branches.len(),
1737 )
1738 }
1739 }
1740
1741 pub fn indirect_branches_at(
1743 &self,
1744 addr: u64,
1745 arch: Option<CoreArchitecture>,
1746 ) -> Array<IndirectBranchInfo> {
1747 let arch = arch.unwrap_or_else(|| self.arch());
1748 let mut count = 0;
1749 let branches =
1750 unsafe { BNGetIndirectBranchesAt(self.handle, arch.handle, addr, &mut count) };
1751 assert!(!branches.is_null());
1752 unsafe { Array::new(branches, count, ()) }
1753 }
1754
1755 pub fn instr_highlight(&self, addr: u64, arch: Option<CoreArchitecture>) -> HighlightColor {
1761 let arch = arch.unwrap_or_else(|| self.arch());
1762 let color = unsafe { BNGetInstructionHighlight(self.handle, arch.handle, addr) };
1763 HighlightColor::from(color)
1764 }
1765
1766 pub fn set_auto_instr_highlight(
1774 &self,
1775 addr: u64,
1776 color: HighlightColor,
1777 arch: Option<CoreArchitecture>,
1778 ) {
1779 let arch = arch.unwrap_or_else(|| self.arch());
1780 unsafe { BNSetAutoInstructionHighlight(self.handle, arch.handle, addr, color.into()) }
1781 }
1782
1783 pub fn set_user_instr_highlight(
1800 &self,
1801 addr: u64,
1802 color: HighlightColor,
1803 arch: Option<CoreArchitecture>,
1804 ) {
1805 let arch = arch.unwrap_or_else(|| self.arch());
1806 unsafe { BNSetUserInstructionHighlight(self.handle, arch.handle, addr, color.into()) }
1807 }
1808
1809 pub fn create_user_stack_var<'a, C: Into<Conf<&'a Type>>>(
1810 &self,
1811 offset: i64,
1812 var_type: C,
1813 name: &str,
1814 ) {
1815 let mut owned_raw_var_ty = Conf::<&Type>::into_raw(var_type.into());
1816 let name = name.to_cstr();
1817 unsafe {
1818 BNCreateUserStackVariable(self.handle, offset, &mut owned_raw_var_ty, name.as_ptr())
1819 }
1820 }
1821
1822 pub fn delete_user_stack_var(&self, offset: i64) {
1823 unsafe { BNDeleteUserStackVariable(self.handle, offset) }
1824 }
1825
1826 pub fn create_user_var<'a, C: Into<Conf<&'a Type>>>(
1827 &self,
1828 var: &Variable,
1829 var_type: C,
1830 name: &str,
1831 ignore_disjoint_uses: bool,
1832 ) {
1833 let raw_var = BNVariable::from(var);
1834 let mut owned_raw_var_ty = Conf::<&Type>::into_raw(var_type.into());
1835 let name = name.to_cstr();
1836 unsafe {
1837 BNCreateUserVariable(
1838 self.handle,
1839 &raw_var,
1840 &mut owned_raw_var_ty,
1841 name.as_ref().as_ptr() as *const _,
1842 ignore_disjoint_uses,
1843 )
1844 }
1845 }
1846
1847 pub fn delete_user_var(&self, var: &Variable) {
1848 let raw_var = BNVariable::from(var);
1849 unsafe { BNDeleteUserVariable(self.handle, &raw_var) }
1850 }
1851
1852 pub fn is_var_user_defined(&self, var: &Variable) -> bool {
1853 let raw_var = BNVariable::from(var);
1854 unsafe { BNIsVariableUserDefined(self.handle, &raw_var) }
1855 }
1856
1857 pub fn create_auto_stack_var<'a, T: Into<Conf<&'a Type>>>(
1858 &self,
1859 offset: i64,
1860 var_type: T,
1861 name: &str,
1862 ) {
1863 let mut owned_raw_var_ty = Conf::<&Type>::into_raw(var_type.into());
1864 let name = name.to_cstr();
1865 unsafe {
1866 BNCreateAutoStackVariable(self.handle, offset, &mut owned_raw_var_ty, name.as_ptr())
1867 }
1868 }
1869
1870 pub fn delete_auto_stack_var(&self, offset: i64) {
1871 unsafe { BNDeleteAutoStackVariable(self.handle, offset) }
1872 }
1873
1874 pub fn create_auto_var<'a, C: Into<Conf<&'a Type>>>(
1875 &self,
1876 var: &Variable,
1877 var_type: C,
1878 name: &str,
1879 ignore_disjoint_uses: bool,
1880 ) {
1881 let raw_var = BNVariable::from(var);
1882 let mut owned_raw_var_ty = Conf::<&Type>::into_raw(var_type.into());
1883 let name = name.to_cstr();
1884 unsafe {
1885 BNCreateAutoVariable(
1886 self.handle,
1887 &raw_var,
1888 &mut owned_raw_var_ty,
1889 name.as_ptr(),
1890 ignore_disjoint_uses,
1891 )
1892 }
1893 }
1894
1895 pub fn instruction_containing_address(
1898 &self,
1899 addr: u64,
1900 arch: Option<CoreArchitecture>,
1901 ) -> Option<u64> {
1902 let arch = arch.unwrap_or_else(|| self.arch());
1903 let mut start = 0;
1904 unsafe { BNGetInstructionContainingAddress(self.handle, arch.handle, addr, &mut start) }
1905 .then_some(start)
1906 }
1907
1908 pub fn int_display_type(
1917 &self,
1918 instr_addr: u64,
1919 value: u64,
1920 operand: usize,
1921 arch: Option<CoreArchitecture>,
1922 ) -> IntegerDisplayType {
1923 let arch = arch.unwrap_or_else(|| self.arch());
1924 unsafe {
1925 BNGetIntegerConstantDisplayType(self.handle, arch.handle, instr_addr, value, operand)
1926 }
1927 }
1928
1929 pub fn set_int_display_type(
1938 &self,
1939 instr_addr: u64,
1940 value: u64,
1941 operand: usize,
1942 display_type: IntegerDisplayType,
1943 arch: Option<CoreArchitecture>,
1944 enum_display_typeid: Option<&str>,
1945 ) {
1946 let arch = arch.unwrap_or_else(|| self.arch());
1947 let enum_display_typeid = enum_display_typeid.map(IntoCStr::to_cstr);
1948 let enum_display_typeid_ptr = enum_display_typeid
1949 .map(|x| x.as_ptr())
1950 .unwrap_or(std::ptr::null());
1951 unsafe {
1952 BNSetIntegerConstantDisplayType(
1953 self.handle,
1954 arch.handle,
1955 instr_addr,
1956 value,
1957 operand,
1958 display_type,
1959 enum_display_typeid_ptr,
1960 )
1961 }
1962 }
1963
1964 pub fn int_enum_display_typeid(
1973 &self,
1974 instr_addr: u64,
1975 value: u64,
1976 operand: usize,
1977 arch: Option<CoreArchitecture>,
1978 ) -> String {
1979 let arch = arch.unwrap_or_else(|| self.arch());
1980 unsafe {
1981 BnString::into_string(BNGetIntegerConstantDisplayTypeEnumerationType(
1982 self.handle,
1983 arch.handle,
1984 instr_addr,
1985 value,
1986 operand,
1987 ))
1988 }
1989 }
1990
1991 pub fn int_display_type_and_typeid(
1998 &self,
1999 instr_addr: u64,
2000 value: u64,
2001 operand: usize,
2002 arch: Option<CoreArchitecture>,
2003 ) -> (IntegerDisplayType, String) {
2004 let arch = arch.unwrap_or_else(|| self.arch());
2005 let name = self.int_enum_display_typeid(instr_addr, value, operand, Some(arch));
2006 let display = self.int_display_type(instr_addr, value, operand, Some(arch));
2007 (display, name)
2008 }
2009
2010 pub fn register_value_at(
2024 &self,
2025 addr: u64,
2026 reg: RegisterId,
2027 arch: Option<CoreArchitecture>,
2028 ) -> RegisterValue {
2029 let arch = arch.unwrap_or_else(|| self.arch());
2030 let register =
2031 unsafe { BNGetRegisterValueAtInstruction(self.handle, arch.handle, addr, reg.0) };
2032 register.into()
2033 }
2034
2035 pub fn register_value_after(
2049 &self,
2050 addr: u64,
2051 reg: RegisterId,
2052 arch: Option<CoreArchitecture>,
2053 ) -> RegisterValue {
2054 let arch = arch.unwrap_or_else(|| self.arch());
2055 let register =
2056 unsafe { BNGetRegisterValueAfterInstruction(self.handle, arch.handle, addr, reg.0) };
2057 register.into()
2058 }
2059
2060 pub fn register_value_at_exit(&self, reg: u32) -> Conf<RegisterValue> {
2061 let register = unsafe { BNGetFunctionRegisterValueAtExit(self.handle, reg) };
2062 Conf::new(register.value.into(), register.confidence)
2063 }
2064
2065 pub fn registers_read_by(
2066 &self,
2067 addr: u64,
2068 arch: Option<CoreArchitecture>,
2069 ) -> Array<CoreRegister> {
2070 let arch = arch.unwrap_or_else(|| self.arch());
2071 let mut count = 0;
2072 let regs =
2073 unsafe { BNGetRegistersReadByInstruction(self.handle, arch.handle, addr, &mut count) };
2074 assert!(!regs.is_null());
2075 unsafe { Array::new(regs, count, arch) }
2076 }
2077
2078 pub fn registers_written_by(
2079 &self,
2080 addr: u64,
2081 arch: Option<CoreArchitecture>,
2082 ) -> Array<CoreRegister> {
2083 let arch = arch.unwrap_or_else(|| self.arch());
2084 let mut count = 0;
2085 let regs = unsafe {
2086 BNGetRegistersWrittenByInstruction(self.handle, arch.handle, addr, &mut count)
2087 };
2088 assert!(!regs.is_null());
2089 unsafe { Array::new(regs, count, arch) }
2090 }
2091
2092 pub fn clobbered_registers(&self) -> Conf<Array<CoreRegister>> {
2094 let result = unsafe { BNGetFunctionClobberedRegisters(self.handle) };
2095
2096 let reg_set = unsafe { Array::new(result.regs, result.count, self.arch().handle()) };
2097 Conf::new(reg_set, result.confidence)
2098 }
2099
2100 pub fn set_user_clobbered_registers<I>(&self, registers: I, confidence: u8)
2101 where
2102 I: IntoIterator<Item = CoreRegister>,
2103 {
2104 let mut regs: Box<[u32]> = registers.into_iter().map(|reg| reg.id().0).collect();
2105 let mut regs = BNRegisterSetWithConfidence {
2106 regs: regs.as_mut_ptr(),
2107 count: regs.len(),
2108 confidence,
2109 };
2110 unsafe { BNSetUserFunctionClobberedRegisters(self.handle, &mut regs) }
2111 }
2112
2113 pub fn set_auto_clobbered_registers<I>(&self, registers: I, confidence: u8)
2114 where
2115 I: IntoIterator<Item = CoreRegister>,
2116 {
2117 let mut regs: Box<[u32]> = registers.into_iter().map(|reg| reg.id().0).collect();
2118 let mut regs = BNRegisterSetWithConfidence {
2119 regs: regs.as_mut_ptr(),
2120 count: regs.len(),
2121 confidence,
2122 };
2123 unsafe { BNSetAutoFunctionClobberedRegisters(self.handle, &mut regs) }
2124 }
2125
2126 pub fn stack_contents_at(
2127 &self,
2128 addr: u64,
2129 offset: i64,
2130 size: usize,
2131 arch: Option<CoreArchitecture>,
2132 ) -> RegisterValue {
2133 let arch = arch.unwrap_or_else(|| self.arch());
2134 let value = unsafe {
2135 BNGetStackContentsAtInstruction(self.handle, arch.handle, addr, offset, size)
2136 };
2137 value.into()
2138 }
2139
2140 pub fn stack_contents_after(
2141 &self,
2142 addr: u64,
2143 offset: i64,
2144 size: usize,
2145 arch: Option<CoreArchitecture>,
2146 ) -> RegisterValue {
2147 let arch = arch.unwrap_or_else(|| self.arch());
2148 let value = unsafe {
2149 BNGetStackContentsAfterInstruction(self.handle, arch.handle, addr, offset, size)
2150 };
2151 value.into()
2152 }
2153
2154 pub fn stack_var_at_frame_offset(
2155 &self,
2156 addr: u64,
2157 offset: i64,
2158 arch: Option<CoreArchitecture>,
2159 ) -> Option<NamedVariableWithType> {
2160 let arch = arch.unwrap_or_else(|| self.arch());
2161 let mut found_value = BNVariableNameAndType::default();
2162 let found = unsafe {
2163 BNGetStackVariableAtFrameOffset(
2164 self.handle,
2165 arch.handle,
2166 addr,
2167 offset,
2168 &mut found_value,
2169 )
2170 };
2171 if !found {
2172 return None;
2173 }
2174 Some(NamedVariableWithType::from_owned_raw(found_value))
2175 }
2176
2177 pub fn stack_var_at_frame_offset_after_instruction(
2178 &self,
2179 addr: u64,
2180 offset: i64,
2181 arch: Option<CoreArchitecture>,
2182 ) -> Option<NamedVariableWithType> {
2183 let arch = arch.unwrap_or_else(|| self.arch());
2184 let mut found_value = BNVariableNameAndType::default();
2185 let found = unsafe {
2186 BNGetStackVariableAtFrameOffsetAfterInstruction(
2187 self.handle,
2188 arch.handle,
2189 addr,
2190 offset,
2191 &mut found_value,
2192 )
2193 };
2194 if !found {
2195 return None;
2196 }
2197 Some(NamedVariableWithType::from_owned_raw(found_value))
2198 }
2199
2200 pub fn stack_variables_referenced_by(
2201 &self,
2202 addr: u64,
2203 arch: Option<CoreArchitecture>,
2204 ) -> Array<StackVariableReference> {
2205 let arch = arch.unwrap_or_else(|| self.arch());
2206 let mut count = 0;
2207 let refs = unsafe {
2208 BNGetStackVariablesReferencedByInstruction(self.handle, arch.handle, addr, &mut count)
2209 };
2210 assert!(!refs.is_null());
2211 unsafe { Array::new(refs, count, ()) }
2212 }
2213
2214 pub fn stack_variables_referenced_by_address_if_available(
2215 &self,
2216 addr: u64,
2217 arch: Option<CoreArchitecture>,
2218 ) -> Array<StackVariableReference> {
2219 let arch = arch.unwrap_or_else(|| self.arch());
2220 let mut count = 0;
2221 let refs = unsafe {
2222 BNGetStackVariablesReferencedByInstructionIfAvailable(
2223 self.handle,
2224 arch.handle,
2225 addr,
2226 &mut count,
2227 )
2228 };
2229 assert!(!refs.is_null());
2230 unsafe { Array::new(refs, count, ()) }
2231 }
2232
2233 pub fn global_pointer_value(&self) -> Conf<RegisterValue> {
2237 self.global_pointer_values()
2238 .into_iter()
2239 .next()
2240 .map(|(_, value)| value)
2241 .unwrap_or_else(|| {
2242 Conf::new(
2243 RegisterValue::new(RegisterValueType::UndeterminedValue, 0, 0, 0),
2244 255,
2245 )
2246 })
2247 }
2248
2249 pub fn global_pointer_values(&self) -> Vec<(RegisterId, Conf<RegisterValue>)> {
2251 unsafe {
2252 let mut count = 0;
2253 let values_ptr = BNGetFunctionGlobalPointerValues(self.handle, &mut count);
2254 if values_ptr.is_null() {
2255 return Vec::new();
2256 }
2257
2258 let values = std::slice::from_raw_parts(values_ptr, count);
2259 let result = values
2260 .iter()
2261 .map(|value| {
2262 (
2263 RegisterId::from(value.reg),
2264 Conf::new(value.value.value.into(), value.value.confidence),
2265 )
2266 })
2267 .collect();
2268 BNFreeRegisterValueWithConfidenceAndRegisterList(values_ptr);
2269 result
2270 }
2271 }
2272
2273 pub fn type_tokens(
2274 &self,
2275 settings: Option<&DisassemblySettings>,
2276 ) -> Array<DisassemblyTextLine> {
2277 let settings = settings.map(|s| s.handle).unwrap_or(std::ptr::null_mut());
2278 let mut count = 0;
2279 let lines = unsafe { BNGetFunctionTypeTokens(self.handle, settings, &mut count) };
2280 assert!(!lines.is_null());
2281 unsafe { Array::new(lines, count, ()) }
2282 }
2283
2284 pub fn is_call_instruction(&self, addr: u64, arch: Option<CoreArchitecture>) -> bool {
2285 let arch = arch.unwrap_or_else(|| self.arch());
2286 unsafe { BNIsCallInstruction(self.handle, arch.handle, addr) }
2287 }
2288
2289 pub fn is_variable_user_defined(&self, var: &Variable) -> bool {
2290 let raw_var = BNVariable::from(var);
2291 unsafe { BNIsVariableUserDefined(self.handle, &raw_var) }
2292 }
2293
2294 pub fn is_pure(&self) -> Conf<bool> {
2295 unsafe { BNIsFunctionPure(self.handle) }.into()
2296 }
2297
2298 pub fn set_user_pure<C>(&self, value: C)
2299 where
2300 C: Into<Conf<bool>>,
2301 {
2302 let value: Conf<bool> = value.into();
2303 let mut value_raw = value.into();
2304 unsafe { BNSetUserFunctionPure(self.handle, &mut value_raw) };
2305 }
2306
2307 pub fn set_auto_pure<C>(&self, value: C)
2308 where
2309 C: Into<Conf<bool>>,
2310 {
2311 let value: Conf<bool> = value.into();
2312 let mut value_raw = value.into();
2313 unsafe { BNSetAutoFunctionPure(self.handle, &mut value_raw) };
2314 }
2315
2316 pub fn is_too_large(&self) -> bool {
2317 unsafe { BNIsFunctionTooLarge(self.handle) }
2318 }
2319
2320 pub fn is_update_needed(&self) -> bool {
2321 unsafe { BNIsFunctionUpdateNeeded(self.handle) }
2322 }
2323
2324 pub fn mark_updates_required(&self, update_type: FunctionUpdateType) {
2328 unsafe { BNMarkUpdatesRequired(self.handle, update_type) }
2329 }
2330
2331 pub fn mark_caller_updates_required(&self, update_type: FunctionUpdateType) {
2335 unsafe { BNMarkCallerUpdatesRequired(self.handle, update_type) }
2336 }
2337
2338 pub fn mark_recent_use(&self) {
2339 unsafe { BNMarkFunctionAsRecentlyUsed(self.handle) }
2340 }
2341
2342 pub fn merged_variables(&self) -> Array<MergedVariable> {
2344 let mut count = 0;
2345 let vars = unsafe { BNGetMergedVariables(self.handle, &mut count) };
2346 assert!(!vars.is_null());
2347 unsafe { Array::new(vars, count, ()) }
2348 }
2349
2350 pub fn merge_variables<'a>(
2356 &self,
2357 target: &Variable,
2358 sources: impl IntoIterator<Item = &'a Variable>,
2359 ) {
2360 let raw_target_var = BNVariable::from(target);
2361 let sources_raw: Vec<BNVariable> = sources.into_iter().copied().map(Into::into).collect();
2362 unsafe {
2363 BNMergeVariables(
2364 self.handle,
2365 &raw_target_var,
2366 sources_raw.as_ptr(),
2367 sources_raw.len(),
2368 )
2369 }
2370 }
2371
2372 pub fn unmerge_variables<'a>(
2378 &self,
2379 target: &Variable,
2380 sources: impl IntoIterator<Item = &'a Variable>,
2381 ) {
2382 let raw_target_var = BNVariable::from(target);
2383 let sources_raw: Vec<BNVariable> = sources.into_iter().copied().map(Into::into).collect();
2384 unsafe {
2385 BNUnmergeVariables(
2386 self.handle,
2387 &raw_target_var,
2388 sources_raw.as_ptr(),
2389 sources_raw.len(),
2390 )
2391 }
2392 }
2393
2394 pub fn split_variable(&self, var: &Variable) {
2413 let raw_var = BNVariable::from(var);
2414 unsafe { BNSplitVariable(self.handle, &raw_var) }
2415 }
2416
2417 pub fn unsplit_variable(&self, var: &Variable) {
2423 let raw_var = BNVariable::from(var);
2424 unsafe { BNUnsplitVariable(self.handle, &raw_var) }
2425 }
2426
2427 pub fn analyze(&self) {
2429 unsafe { BNAnalyzeFunction(self.handle) }
2430 }
2431
2432 pub fn reanalyze(&self, update_type: FunctionUpdateType) {
2443 unsafe { BNReanalyzeFunction(self.handle, update_type) }
2444 }
2445
2446 pub fn request_debug_report(&self, name: &str) {
2455 const DEBUG_REPORT_ALIAS: &[(&str, &CStr)] = &[
2456 ("stack", c"stack_adjust_graph"),
2457 ("mlil", c"mlil_translator"),
2458 ("hlil", c"high_level_il"),
2459 ];
2460
2461 if let Some(alias_idx) = DEBUG_REPORT_ALIAS
2462 .iter()
2463 .position(|(alias, _value)| *alias == name)
2464 {
2465 let name = DEBUG_REPORT_ALIAS[alias_idx].1.as_ptr();
2466 unsafe { BNRequestFunctionDebugReport(self.handle, name) }
2467 } else {
2468 let name = std::ffi::CString::new(name.to_string()).unwrap();
2469 unsafe { BNRequestFunctionDebugReport(self.handle, name.as_ptr()) }
2470 }
2471
2472 self.view().update_analysis()
2473 }
2474
2475 pub fn check_for_debug_report(&self, name: &str) -> bool {
2484 let name = std::ffi::CString::new(name.to_string()).unwrap();
2485 unsafe { BNFunctionCheckForDebugReport(self.handle, name.as_ptr()) }
2486 }
2487
2488 pub fn is_auto(&self) -> bool {
2493 unsafe { BNWasFunctionAutomaticallyDiscovered(self.handle) }
2494 }
2495
2496 pub fn call_sites(&self) -> Array<CodeReference> {
2501 let mut count = 0;
2502 let refs = unsafe { BNGetFunctionCallSites(self.handle, &mut count) };
2503 assert!(!refs.is_null());
2504 unsafe { Array::new(refs, count, ()) }
2505 }
2506
2507 pub fn caller_sites(&self) -> Array<CodeReference> {
2510 self.view().code_refs_to_addr(self.start())
2511 }
2512
2513 pub fn calling_convention(&self) -> Option<Conf<Ref<CoreCallingConvention>>> {
2515 let result = unsafe { BNGetFunctionCallingConvention(self.handle) };
2516 (!result.convention.is_null()).then(|| {
2517 Conf::new(
2518 unsafe { CoreCallingConvention::ref_from_raw(result.convention, self.arch()) },
2519 result.confidence,
2520 )
2521 })
2522 }
2523
2524 pub fn set_user_calling_convention<'a, I>(&self, value: Option<I>)
2526 where
2527 I: Into<Conf<&'a CoreCallingConvention>>,
2528 {
2529 let mut conv_conf = BNCallingConventionWithConfidence::default();
2530 if let Some(value) = value {
2531 let value = value.into();
2532 conv_conf.convention = value.contents.handle;
2533 conv_conf.confidence = value.confidence;
2534 }
2535 unsafe { BNSetUserFunctionCallingConvention(self.handle, &mut conv_conf) }
2536 }
2537
2538 pub fn set_auto_calling_convention<'a, I>(&self, value: Option<I>)
2540 where
2541 I: Into<Conf<&'a CoreCallingConvention>>,
2542 {
2543 let mut conv_conf = BNCallingConventionWithConfidence::default();
2544 if let Some(value) = value {
2545 let value = value.into();
2546 conv_conf.convention = value.contents.handle;
2547 conv_conf.confidence = value.confidence;
2548 }
2549 unsafe { BNSetAutoFunctionCallingConvention(self.handle, &mut conv_conf) }
2550 }
2551
2552 pub fn can_return(&self) -> Conf<bool> {
2553 unsafe { BNCanFunctionReturn(self.handle) }.into()
2554 }
2555
2556 pub fn set_user_can_return<I>(&self, value: I)
2557 where
2558 I: Into<Conf<bool>>,
2559 {
2560 let value: Conf<bool> = value.into();
2561 let mut value_raw: BNBoolWithConfidence = value.into();
2562 unsafe { BNSetUserFunctionCanReturn(self.handle, &mut value_raw) }
2563 }
2564
2565 pub fn set_auto_can_return<I>(&self, value: I)
2566 where
2567 I: Into<Conf<bool>>,
2568 {
2569 let value: Conf<bool> = value.into();
2570 let mut value_raw: BNBoolWithConfidence = value.into();
2571 unsafe { BNSetAutoFunctionCanReturn(self.handle, &mut value_raw) }
2572 }
2573
2574 pub fn has_explicitly_defined_type(&self) -> bool {
2578 unsafe { BNFunctionHasExplicitlyDefinedType(self.handle) }
2579 }
2580
2581 pub fn has_user_annotations(&self) -> bool {
2582 unsafe { BNFunctionHasUserAnnotations(self.handle) }
2583 }
2584
2585 pub fn has_variable_arguments(&self) -> Conf<bool> {
2586 unsafe { BNFunctionHasVariableArguments(self.handle) }.into()
2587 }
2588
2589 pub fn set_user_has_variable_arguments<I>(&self, value: I)
2590 where
2591 I: Into<Conf<bool>>,
2592 {
2593 let bc: Conf<bool> = value.into();
2594 let mut bc = bc.into();
2595 unsafe { BNSetUserFunctionHasVariableArguments(self.handle, &mut bc) }
2596 }
2597
2598 pub fn set_auto_has_variable_arguments<I>(&self, value: I)
2599 where
2600 I: Into<Conf<bool>>,
2601 {
2602 let bc: Conf<bool> = value.into();
2603 let mut bc = bc.into();
2604 unsafe { BNSetAutoFunctionHasVariableArguments(self.handle, &mut bc) }
2605 }
2606
2607 pub fn has_unresolved_indirect_branches(&self) -> bool {
2609 unsafe { BNHasUnresolvedIndirectBranches(self.handle) }
2610 }
2611
2612 pub fn provenance(&self) -> String {
2625 unsafe { BnString::into_string(BNGetProvenanceString(self.handle)) }
2626 }
2627
2628 pub fn return_registers(&self) -> Conf<Array<CoreRegister>> {
2630 let result = unsafe { BNGetFunctionReturnRegisters(self.handle) };
2631 let regs = unsafe { Array::new(result.regs, result.count, self.arch().handle()) };
2632 Conf::new(regs, result.confidence)
2633 }
2634
2635 pub fn unresolved_stack_adjustment_graph(&self) -> Option<Ref<FlowGraph>> {
2637 let graph = unsafe { BNGetUnresolvedStackAdjustmentGraph(self.handle) };
2638 (!graph.is_null()).then(|| unsafe { FlowGraph::ref_from_raw(graph) })
2639 }
2640
2641 pub fn create_graph(
2642 &self,
2643 view_type: FunctionViewType,
2644 settings: Option<&DisassemblySettings>,
2645 ) -> Ref<FlowGraph> {
2646 let settings_raw = settings.map(|s| s.handle).unwrap_or(std::ptr::null_mut());
2647 let raw_view_type = FunctionViewType::into_raw(view_type);
2648 let result = unsafe { BNCreateFunctionGraph(self.handle, raw_view_type, settings_raw) };
2649 FunctionViewType::free_raw(raw_view_type);
2650 unsafe { FlowGraph::ref_from_raw(result) }
2651 }
2652
2653 pub fn create_graph_immediate(
2654 &self,
2655 view_type: FunctionViewType,
2656 settings: Option<&DisassemblySettings>,
2657 ) -> Ref<FlowGraph> {
2658 let settings_raw = settings.map(|s| s.handle).unwrap_or(std::ptr::null_mut());
2659 let raw_view_type = FunctionViewType::into_raw(view_type);
2660 let result =
2661 unsafe { BNCreateImmediateFunctionGraph(self.handle, raw_view_type, settings_raw) };
2662 FunctionViewType::free_raw(raw_view_type);
2663 unsafe { FlowGraph::ref_from_raw(result) }
2664 }
2665
2666 pub fn parent_components(&self) -> Array<Component> {
2667 let mut count = 0;
2668 let result =
2669 unsafe { BNGetFunctionParentComponents(self.view().handle, self.handle, &mut count) };
2670 assert!(!result.is_null());
2671 unsafe { Array::new(result, count, ()) }
2672 }
2673
2674 pub fn query_metadata(&self, key: &str) -> Option<Ref<Metadata>> {
2675 let key = key.to_cstr();
2676 let value: *mut BNMetadata = unsafe { BNFunctionQueryMetadata(self.handle, key.as_ptr()) };
2677 if value.is_null() {
2678 None
2679 } else {
2680 Some(unsafe { Metadata::ref_from_raw(value) })
2681 }
2682 }
2683
2684 pub fn get_metadata(&self) -> Option<Ref<Metadata>> {
2685 let value: *mut BNMetadata = unsafe { BNFunctionGetMetadata(self.handle) };
2686 if value.is_null() {
2687 None
2688 } else {
2689 Some(unsafe { Metadata::ref_from_raw(value) })
2690 }
2691 }
2692
2693 pub fn get_auto_metadata(&self) -> Option<Ref<Metadata>> {
2694 let value: *mut BNMetadata = unsafe { BNFunctionGetAutoMetadata(self.handle) };
2695 if value.is_null() {
2696 None
2697 } else {
2698 Some(unsafe { Metadata::ref_from_raw(value) })
2699 }
2700 }
2701
2702 pub fn store_metadata<V>(&self, key: &str, value: V, is_auto: bool)
2703 where
2704 V: Into<Ref<Metadata>>,
2705 {
2706 let md = value.into();
2707 let key = key.to_cstr();
2708 unsafe { BNFunctionStoreMetadata(self.handle, key.as_ptr(), md.as_ref().handle, is_auto) };
2709 }
2710
2711 pub fn remove_metadata(&self, key: &str) {
2712 let key = key.to_cstr();
2713 unsafe { BNFunctionRemoveMetadata(self.handle, key.as_ptr()) };
2714 }
2715
2716 pub fn guided_source_blocks(&self) -> HashSet<Location> {
2720 let mut count = 0;
2721 let raw = unsafe { BNGetGuidedSourceBlocks(self.handle, &mut count) };
2722 let array: Array<Location> = unsafe { Array::new(raw, count, ()) };
2723 array.into_iter().collect()
2724 }
2725}
2726
2727impl Debug for Function {
2728 fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
2729 f.debug_struct("Function")
2731 .field("start", &self.start())
2732 .field("arch", &self.arch().name())
2733 .field("platform", &self.platform())
2734 .field("symbol", &self.symbol())
2735 .field("is_auto", &self.is_auto())
2736 .field("tags", &self.tags().to_vec())
2737 .field("comments", &self.comments().to_vec())
2738 .finish()
2739 }
2740}
2741
2742unsafe impl Send for Function {}
2743unsafe impl Sync for Function {}
2744
2745impl ToOwned for Function {
2746 type Owned = Ref<Self>;
2747
2748 fn to_owned(&self) -> Self::Owned {
2749 unsafe { RefCountable::inc_ref(self) }
2750 }
2751}
2752
2753unsafe impl RefCountable for Function {
2754 unsafe fn inc_ref(handle: &Self) -> Ref<Self> {
2755 Ref::new(Self {
2756 handle: BNNewFunctionReference(handle.handle),
2757 })
2758 }
2759
2760 unsafe fn dec_ref(handle: &Self) {
2761 BNFreeFunction(handle.handle);
2762 }
2763}
2764
2765impl CoreArrayProvider for Function {
2766 type Raw = *mut BNFunction;
2767 type Context = ();
2768 type Wrapped<'a> = Guard<'a, Function>;
2769}
2770
2771unsafe impl CoreArrayProviderInner for Function {
2772 unsafe fn free(raw: *mut Self::Raw, count: usize, _context: &Self::Context) {
2773 BNFreeFunctionList(raw, count);
2774 }
2775
2776 unsafe fn wrap_raw<'a>(raw: &'a Self::Raw, context: &'a Self::Context) -> Self::Wrapped<'a> {
2777 Guard::new(Self::from_raw(*raw), context)
2778 }
2779}
2780
2781impl Hash for Function {
2782 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
2783 let start_address = self.start();
2784 let architecture = self.arch();
2785 let platform = self.platform();
2786 (start_address, architecture, platform).hash(state)
2787 }
2788}
2789
2790impl PartialEq for Function {
2791 fn eq(&self, other: &Self) -> bool {
2792 if self.handle == other.handle {
2793 return true;
2794 }
2795 self.start() == other.start()
2796 && self.arch() == other.arch()
2797 && self.platform() == other.platform()
2798 }
2799}
2800
2801#[derive(Clone, Debug, Eq, Hash, PartialEq)]
2802pub struct PerformanceInfo {
2803 pub name: String,
2804 pub seconds: Duration,
2805}
2806
2807#[allow(unused)]
2808impl PerformanceInfo {
2809 pub fn new(name: String, seconds: Duration) -> Self {
2810 Self {
2811 name: name.to_string(),
2812 seconds,
2813 }
2814 }
2815
2816 pub(crate) fn from_raw(value: &BNPerformanceInfo) -> Self {
2817 Self {
2818 name: raw_to_string(value.name as *mut _).unwrap(),
2819 seconds: Duration::from_secs_f64(value.seconds),
2820 }
2821 }
2822
2823 pub(crate) fn from_owned_raw(value: BNPerformanceInfo) -> Self {
2824 let owned = Self::from_raw(&value);
2825 Self::free_raw(value);
2826 owned
2827 }
2828
2829 pub(crate) fn into_raw(value: Self) -> BNPerformanceInfo {
2830 let bn_name = BnString::new(value.name);
2831 BNPerformanceInfo {
2832 name: BnString::into_raw(bn_name),
2833 seconds: value.seconds.as_secs_f64(),
2834 }
2835 }
2836
2837 pub(crate) fn free_raw(value: BNPerformanceInfo) {
2838 unsafe { BnString::free_raw(value.name) };
2839 }
2840}
2841
2842impl CoreArrayProvider for PerformanceInfo {
2843 type Raw = BNPerformanceInfo;
2844 type Context = ();
2845 type Wrapped<'a> = Self;
2846}
2847
2848unsafe impl CoreArrayProviderInner for PerformanceInfo {
2849 unsafe fn free(raw: *mut Self::Raw, count: usize, _context: &Self::Context) {
2850 BNFreeAnalysisPerformanceInfo(raw, count);
2851 }
2852
2853 unsafe fn wrap_raw<'a>(raw: &'a Self::Raw, _context: &'a Self::Context) -> Self::Wrapped<'a> {
2854 Self::from_raw(raw)
2855 }
2856}
2857
2858pub struct UnresolvedIndirectBranches(u64);
2860
2861impl UnresolvedIndirectBranches {
2862 pub fn address(&self) -> u64 {
2863 self.0
2864 }
2865}
2866
2867impl CoreArrayProvider for UnresolvedIndirectBranches {
2868 type Raw = u64;
2869 type Context = ();
2870 type Wrapped<'a> = Self;
2871}
2872
2873unsafe impl CoreArrayProviderInner for UnresolvedIndirectBranches {
2874 unsafe fn free(raw: *mut Self::Raw, _count: usize, _context: &Self::Context) {
2875 BNFreeAddressList(raw)
2876 }
2877
2878 unsafe fn wrap_raw<'a>(raw: &'a Self::Raw, _context: &'a Self::Context) -> Self::Wrapped<'a> {
2879 Self(*raw)
2880 }
2881}
2882
2883#[derive(Clone, Copy, Debug, Hash, Eq, PartialEq)]
2884pub struct ConstantReference {
2885 pub value: i64,
2886 pub size: usize,
2887 pub pointer: bool,
2888 pub intermediate: bool,
2889}
2890
2891impl From<BNConstantReference> for ConstantReference {
2892 fn from(value: BNConstantReference) -> Self {
2893 Self {
2894 value: value.value,
2895 size: value.size,
2896 pointer: value.pointer,
2897 intermediate: value.intermediate,
2898 }
2899 }
2900}
2901
2902impl From<ConstantReference> for BNConstantReference {
2903 fn from(value: ConstantReference) -> Self {
2904 Self {
2905 value: value.value,
2906 size: value.size,
2907 pointer: value.pointer,
2908 intermediate: value.intermediate,
2909 }
2910 }
2911}
2912
2913impl CoreArrayProvider for ConstantReference {
2914 type Raw = BNConstantReference;
2915 type Context = ();
2916 type Wrapped<'a> = Self;
2917}
2918
2919unsafe impl CoreArrayProviderInner for ConstantReference {
2920 unsafe fn free(raw: *mut Self::Raw, _count: usize, _context: &Self::Context) {
2921 BNFreeConstantReferenceList(raw)
2922 }
2923
2924 unsafe fn wrap_raw<'a>(raw: &'a Self::Raw, _context: &'a Self::Context) -> Self::Wrapped<'a> {
2925 Self::from(*raw)
2926 }
2927}
2928
2929#[derive(Debug, Copy, Clone)]
2930pub struct RegisterStackAdjustment {
2931 pub register_id: u32,
2932 pub adjustment: Conf<i32>,
2933}
2934
2935impl RegisterStackAdjustment {
2936 pub fn new(register_id: u32, adjustment: impl Into<Conf<i32>>) -> Self {
2937 Self {
2938 register_id,
2939 adjustment: adjustment.into(),
2940 }
2941 }
2942}
2943
2944impl From<BNRegisterStackAdjustment> for RegisterStackAdjustment {
2945 fn from(value: BNRegisterStackAdjustment) -> Self {
2946 Self {
2947 register_id: value.regStack,
2948 adjustment: Conf::new(value.adjustment, value.confidence),
2949 }
2950 }
2951}
2952
2953impl From<RegisterStackAdjustment> for BNRegisterStackAdjustment {
2954 fn from(value: RegisterStackAdjustment) -> Self {
2955 Self {
2956 regStack: value.register_id,
2957 adjustment: value.adjustment.contents,
2958 confidence: value.adjustment.confidence,
2959 }
2960 }
2961}
2962
2963impl CoreArrayProvider for RegisterStackAdjustment {
2964 type Raw = BNRegisterStackAdjustment;
2965 type Context = ();
2966 type Wrapped<'a> = Self;
2967}
2968
2969unsafe impl CoreArrayProviderInner for RegisterStackAdjustment {
2970 unsafe fn free(raw: *mut Self::Raw, _count: usize, _context: &Self::Context) {
2971 BNFreeRegisterStackAdjustments(raw)
2972 }
2973
2974 unsafe fn wrap_raw<'a>(raw: &'a Self::Raw, _context: &'a Self::Context) -> Self::Wrapped<'a> {
2975 Self::from(*raw)
2976 }
2977}
2978
2979#[derive(Clone, Copy, Debug, Hash, Eq, PartialEq)]
2980pub enum HighlightColor {
2981 StandardHighlightColor {
2982 color: HighlightStandardColor,
2983 alpha: u8,
2984 },
2985 MixedHighlightColor {
2986 color: HighlightStandardColor,
2987 mix_color: HighlightStandardColor,
2988 mix: u8,
2989 alpha: u8,
2990 },
2991 CustomHighlightColor {
2992 r: u8,
2993 g: u8,
2994 b: u8,
2995 alpha: u8,
2996 },
2997}
2998
2999impl From<BNHighlightColor> for HighlightColor {
3000 fn from(value: BNHighlightColor) -> Self {
3001 match value.style {
3002 BNHighlightColorStyle::StandardHighlightColor => Self::StandardHighlightColor {
3003 color: value.color,
3004 alpha: value.alpha,
3005 },
3006 BNHighlightColorStyle::MixedHighlightColor => Self::MixedHighlightColor {
3007 color: value.color,
3008 mix_color: value.mixColor,
3009 mix: value.mix,
3010 alpha: value.alpha,
3011 },
3012 BNHighlightColorStyle::CustomHighlightColor => Self::CustomHighlightColor {
3013 r: value.r,
3014 g: value.g,
3015 b: value.b,
3016 alpha: value.alpha,
3017 },
3018 }
3019 }
3020}
3021
3022impl From<HighlightColor> for BNHighlightColor {
3023 fn from(value: HighlightColor) -> Self {
3024 match value {
3025 HighlightColor::StandardHighlightColor { color, alpha } => BNHighlightColor {
3026 style: BNHighlightColorStyle::StandardHighlightColor,
3027 color,
3028 alpha,
3029 ..Default::default()
3030 },
3031 HighlightColor::MixedHighlightColor {
3032 color,
3033 mix_color,
3034 mix,
3035 alpha,
3036 } => BNHighlightColor {
3037 style: BNHighlightColorStyle::MixedHighlightColor,
3038 color,
3039 mixColor: mix_color,
3040 mix,
3041 alpha,
3042 ..Default::default()
3043 },
3044 HighlightColor::CustomHighlightColor { r, g, b, alpha } => BNHighlightColor {
3045 style: BNHighlightColorStyle::CustomHighlightColor,
3046 r,
3047 g,
3048 b,
3049 alpha,
3050 ..Default::default()
3051 },
3052 }
3053 }
3054}
3055
3056impl Default for HighlightColor {
3057 fn default() -> Self {
3058 Self::StandardHighlightColor {
3059 color: HighlightStandardColor::NoHighlightColor,
3060 alpha: 0,
3061 }
3062 }
3063}
3064
3065#[derive(Clone, Debug, Hash, Eq, PartialEq)]
3068pub struct Comment {
3069 pub addr: u64,
3070 pub comment: String,
3071}
3072
3073impl CoreArrayProvider for Comment {
3074 type Raw = u64;
3075 type Context = Ref<Function>;
3076 type Wrapped<'a> = Comment;
3077}
3078
3079unsafe impl CoreArrayProviderInner for Comment {
3080 unsafe fn free(raw: *mut Self::Raw, _count: usize, _context: &Self::Context) {
3081 BNFreeAddressList(raw);
3082 }
3083
3084 unsafe fn wrap_raw<'a>(raw: &'a Self::Raw, function: &'a Self::Context) -> Self::Wrapped<'a> {
3085 Comment {
3086 addr: *raw,
3087 comment: function.comment_at(*raw),
3088 }
3089 }
3090}