binaryninja/
function.rs

1// Copyright 2021-2025 Vector 35 Inc.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15use binaryninjacore_sys::*;
16
17use crate::{
18    architecture::{Architecture, CoreArchitecture, CoreRegister, Register},
19    basic_block::{BasicBlock, BlockContext},
20    binary_view::{BinaryView, BinaryViewExt},
21    calling_convention::CoreCallingConvention,
22    component::Component,
23    disassembly::{DisassemblySettings, DisassemblyTextLine},
24    flowgraph::FlowGraph,
25    medium_level_il::FunctionGraphType,
26    platform::Platform,
27    references::CodeReference,
28    string::*,
29    symbol::{Binding, Symbol},
30    tags::{Tag, TagReference, TagType},
31    types::{IntegerDisplayType, QualifiedName, Type},
32};
33use crate::{data_buffer::DataBuffer, disassembly::InstructionTextToken, rc::*};
34pub use binaryninjacore_sys::BNAnalysisSkipReason as AnalysisSkipReason;
35pub use binaryninjacore_sys::BNBuiltinType as BuiltinType;
36pub use binaryninjacore_sys::BNFunctionAnalysisSkipOverride as FunctionAnalysisSkipOverride;
37pub use binaryninjacore_sys::BNFunctionUpdateType as FunctionUpdateType;
38pub use binaryninjacore_sys::BNHighlightStandardColor as HighlightStandardColor;
39
40use crate::architecture::RegisterId;
41use crate::binary_view::AddressRange;
42use crate::confidence::Conf;
43use crate::high_level_il::HighLevelILFunction;
44use crate::language_representation::CoreLanguageRepresentationFunction;
45use crate::low_level_il::LowLevelILRegularFunction;
46use crate::medium_level_il::MediumLevelILFunction;
47use crate::metadata::Metadata;
48use crate::variable::{
49    IndirectBranchInfo, MergedVariable, NamedVariableWithType, RegisterValue, RegisterValueType,
50    StackVariableReference, Variable,
51};
52use crate::workflow::Workflow;
53use std::collections::HashSet;
54use std::ffi::CStr;
55use std::fmt::{Debug, Formatter};
56use std::ptr::NonNull;
57use std::time::Duration;
58use std::{hash::Hash, ops::Range};
59
60/// Used to describe a location within a [`Function`].
61#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
62pub struct Location {
63    pub arch: Option<CoreArchitecture>,
64    pub addr: u64,
65}
66
67impl Location {
68    pub(crate) fn from_raw(addr: u64, arch: *mut BNArchitecture) -> Self {
69        Self {
70            addr,
71            arch: Some(unsafe { CoreArchitecture::from_raw(arch) }),
72        }
73    }
74}
75
76impl From<u64> for Location {
77    fn from(addr: u64) -> Self {
78        Location { arch: None, addr }
79    }
80}
81
82impl From<(CoreArchitecture, u64)> for Location {
83    fn from(loc: (CoreArchitecture, u64)) -> Self {
84        Location {
85            arch: Some(loc.0),
86            addr: loc.1,
87        }
88    }
89}
90
91impl From<BNArchitectureAndAddress> for Location {
92    fn from(value: BNArchitectureAndAddress) -> Self {
93        Self::from_raw(value.address, value.arch)
94    }
95}
96
97impl From<Location> for BNArchitectureAndAddress {
98    fn from(value: Location) -> Self {
99        Self {
100            arch: value.arch.map(|a| a.handle).unwrap_or(std::ptr::null_mut()),
101            address: value.addr,
102        }
103    }
104}
105
106pub struct NativeBlockIter {
107    arch: CoreArchitecture,
108    bv: Ref<BinaryView>,
109    cur: u64,
110    end: u64,
111}
112
113impl Iterator for NativeBlockIter {
114    type Item = u64;
115
116    fn next(&mut self) -> Option<u64> {
117        let res = self.cur;
118
119        if res >= self.end {
120            None
121        } else {
122            self.bv
123                .instruction_len(&self.arch, res)
124                .map(|x| {
125                    self.cur += x as u64;
126                    res
127                })
128                .or_else(|| {
129                    self.cur = self.end;
130                    None
131                })
132        }
133    }
134}
135
136#[derive(Clone, Debug, PartialEq, Eq)]
137pub struct NativeBlock {
138    _priv: (),
139}
140
141impl NativeBlock {
142    pub fn new() -> Self {
143        NativeBlock { _priv: () }
144    }
145}
146
147impl Default for NativeBlock {
148    fn default() -> Self {
149        NativeBlock::new()
150    }
151}
152
153impl BlockContext for NativeBlock {
154    type Instruction = u64;
155    type InstructionIndex = u64;
156    type Iter = NativeBlockIter;
157
158    fn start(&self, block: &BasicBlock<Self>) -> u64 {
159        block.start_index()
160    }
161
162    fn iter(&self, block: &BasicBlock<Self>) -> NativeBlockIter {
163        NativeBlockIter {
164            arch: block.arch(),
165            bv: block.function().view(),
166            cur: block.start_index(),
167            end: block.end_index(),
168        }
169    }
170}
171
172#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
173pub enum FunctionViewType {
174    Normal,
175    LowLevelIL,
176    LiftedIL,
177    LowLevelILSSAForm,
178    MediumLevelIL,
179    MediumLevelILSSAForm,
180    MappedMediumLevelIL,
181    MappedMediumLevelILSSAForm,
182    HighLevelIL,
183    HighLevelILSSAForm,
184    HighLevelLanguageRepresentation(String),
185}
186
187#[allow(unused)]
188impl FunctionViewType {
189    pub(crate) fn from_raw(value: &BNFunctionViewType) -> Option<Self> {
190        match value.type_ {
191            BNFunctionGraphType::InvalidILViewType => None,
192            BNFunctionGraphType::NormalFunctionGraph => Some(FunctionViewType::Normal),
193            BNFunctionGraphType::LowLevelILFunctionGraph => Some(FunctionViewType::LowLevelIL),
194            BNFunctionGraphType::LiftedILFunctionGraph => Some(FunctionViewType::LiftedIL),
195            BNFunctionGraphType::LowLevelILSSAFormFunctionGraph => {
196                Some(FunctionViewType::LowLevelILSSAForm)
197            }
198            BNFunctionGraphType::MediumLevelILFunctionGraph => {
199                Some(FunctionViewType::MediumLevelIL)
200            }
201            BNFunctionGraphType::MediumLevelILSSAFormFunctionGraph => {
202                Some(FunctionViewType::MediumLevelILSSAForm)
203            }
204            BNFunctionGraphType::MappedMediumLevelILFunctionGraph => {
205                Some(FunctionViewType::MappedMediumLevelIL)
206            }
207            BNFunctionGraphType::MappedMediumLevelILSSAFormFunctionGraph => {
208                Some(FunctionViewType::MappedMediumLevelILSSAForm)
209            }
210            BNFunctionGraphType::HighLevelILFunctionGraph => Some(FunctionViewType::HighLevelIL),
211            BNFunctionGraphType::HighLevelILSSAFormFunctionGraph => {
212                Some(FunctionViewType::HighLevelILSSAForm)
213            }
214            BNFunctionGraphType::HighLevelLanguageRepresentationFunctionGraph => {
215                Some(FunctionViewType::HighLevelLanguageRepresentation(
216                    raw_to_string(value.name).unwrap(),
217                ))
218            }
219        }
220    }
221
222    pub(crate) fn from_owned_raw(value: BNFunctionViewType) -> Option<Self> {
223        let owned = Self::from_raw(&value);
224        Self::free_raw(value);
225        owned
226    }
227
228    pub(crate) fn into_raw(value: Self) -> BNFunctionViewType {
229        let view_type = match value {
230            FunctionViewType::Normal => BNFunctionGraphType::NormalFunctionGraph,
231            FunctionViewType::LowLevelIL => BNFunctionGraphType::LowLevelILFunctionGraph,
232            FunctionViewType::LiftedIL => BNFunctionGraphType::LiftedILFunctionGraph,
233            FunctionViewType::LowLevelILSSAForm => {
234                BNFunctionGraphType::LowLevelILSSAFormFunctionGraph
235            }
236            FunctionViewType::MediumLevelIL => BNFunctionGraphType::MediumLevelILFunctionGraph,
237            FunctionViewType::MediumLevelILSSAForm => {
238                BNFunctionGraphType::MediumLevelILSSAFormFunctionGraph
239            }
240            FunctionViewType::MappedMediumLevelIL => {
241                BNFunctionGraphType::MappedMediumLevelILFunctionGraph
242            }
243            FunctionViewType::MappedMediumLevelILSSAForm => {
244                BNFunctionGraphType::MappedMediumLevelILSSAFormFunctionGraph
245            }
246            FunctionViewType::HighLevelIL => BNFunctionGraphType::HighLevelILFunctionGraph,
247            FunctionViewType::HighLevelILSSAForm => {
248                BNFunctionGraphType::HighLevelILSSAFormFunctionGraph
249            }
250            FunctionViewType::HighLevelLanguageRepresentation(_) => {
251                BNFunctionGraphType::HighLevelLanguageRepresentationFunctionGraph
252            }
253        };
254        let view_name = match value {
255            FunctionViewType::HighLevelLanguageRepresentation(name) => Some(BnString::new(name)),
256            _ => None,
257        };
258        BNFunctionViewType {
259            type_: view_type,
260            name: view_name
261                .map(|n| BnString::into_raw(n) as *mut _)
262                .unwrap_or(std::ptr::null_mut()),
263        }
264    }
265
266    pub(crate) fn free_raw(value: BNFunctionViewType) {
267        unsafe { BnString::free_raw(value.name as *mut _) };
268    }
269}
270
271impl From<FunctionGraphType> for FunctionViewType {
272    fn from(view_type: FunctionGraphType) -> Self {
273        match view_type {
274            BNFunctionGraphType::LowLevelILFunctionGraph => FunctionViewType::LowLevelIL,
275            BNFunctionGraphType::LiftedILFunctionGraph => FunctionViewType::LiftedIL,
276            BNFunctionGraphType::LowLevelILSSAFormFunctionGraph => {
277                FunctionViewType::LowLevelILSSAForm
278            }
279            BNFunctionGraphType::MediumLevelILFunctionGraph => FunctionViewType::MediumLevelIL,
280            BNFunctionGraphType::MediumLevelILSSAFormFunctionGraph => {
281                FunctionViewType::MediumLevelILSSAForm
282            }
283            BNFunctionGraphType::MappedMediumLevelILFunctionGraph => {
284                FunctionViewType::MappedMediumLevelIL
285            }
286            BNFunctionGraphType::MappedMediumLevelILSSAFormFunctionGraph => {
287                FunctionViewType::MappedMediumLevelILSSAForm
288            }
289            BNFunctionGraphType::HighLevelILFunctionGraph => FunctionViewType::HighLevelIL,
290            BNFunctionGraphType::HighLevelILSSAFormFunctionGraph => {
291                FunctionViewType::HighLevelILSSAForm
292            }
293            BNFunctionGraphType::HighLevelLanguageRepresentationFunctionGraph => {
294                // Historically this was the only language representation.
295                FunctionViewType::HighLevelLanguageRepresentation("Pseudo C".into())
296            }
297            BNFunctionGraphType::InvalidILViewType | BNFunctionGraphType::NormalFunctionGraph => {
298                FunctionViewType::Normal
299            }
300        }
301    }
302}
303
304#[derive(Eq)]
305pub struct Function {
306    pub(crate) handle: *mut BNFunction,
307}
308
309impl Function {
310    pub unsafe fn from_raw(handle: *mut BNFunction) -> Self {
311        debug_assert!(!handle.is_null());
312        Self { handle }
313    }
314
315    pub unsafe fn ref_from_raw(handle: *mut BNFunction) -> Ref<Self> {
316        debug_assert!(!handle.is_null());
317        Ref::new(Self { handle })
318    }
319
320    pub fn arch(&self) -> CoreArchitecture {
321        unsafe {
322            let arch = BNGetFunctionArchitecture(self.handle);
323            CoreArchitecture::from_raw(arch)
324        }
325    }
326
327    pub fn platform(&self) -> Ref<Platform> {
328        unsafe {
329            let plat = BNGetFunctionPlatform(self.handle);
330            Platform::ref_from_raw(plat)
331        }
332    }
333
334    pub fn view(&self) -> Ref<BinaryView> {
335        unsafe {
336            let view = BNGetFunctionData(self.handle);
337            BinaryView::ref_from_raw(view)
338        }
339    }
340
341    pub fn symbol(&self) -> Ref<Symbol> {
342        unsafe {
343            let sym = BNGetFunctionSymbol(self.handle);
344            Symbol::ref_from_raw(sym)
345        }
346    }
347
348    /// Returns true when the function's symbol binding marks it as exported.
349    pub fn is_exported(&self) -> bool {
350        let symbol = self.symbol();
351        matches!(symbol.binding(), Binding::Global | Binding::Weak)
352    }
353
354    pub fn workflow(&self) -> Option<Ref<Workflow>> {
355        unsafe {
356            let workflow = NonNull::new(BNGetWorkflowForFunction(self.handle))?;
357            Some(Workflow::ref_from_raw(workflow))
358        }
359    }
360
361    pub fn start(&self) -> u64 {
362        unsafe { BNGetFunctionStart(self.handle) }
363    }
364
365    pub fn lowest_address(&self) -> u64 {
366        unsafe { BNGetFunctionLowestAddress(self.handle) }
367    }
368
369    pub fn highest_address(&self) -> u64 {
370        unsafe { BNGetFunctionHighestAddress(self.handle) }
371    }
372
373    pub fn address_ranges(&self) -> Array<AddressRange> {
374        unsafe {
375            let mut count = 0;
376            let addresses = BNGetFunctionAddressRanges(self.handle, &mut count);
377            Array::new(addresses, count, ())
378        }
379    }
380
381    pub fn comment(&self) -> String {
382        unsafe { BnString::into_string(BNGetFunctionComment(self.handle)) }
383    }
384
385    pub fn set_comment(&self, comment: &str) {
386        let raw = comment.to_cstr();
387
388        unsafe {
389            BNSetFunctionComment(self.handle, raw.as_ptr());
390        }
391    }
392
393    pub fn set_can_return_auto<T: Into<Conf<bool>>>(&self, can_return: T) {
394        let mut bool_with_confidence = can_return.into().into();
395        unsafe { BNSetAutoFunctionCanReturn(self.handle, &mut bool_with_confidence) }
396    }
397
398    pub fn set_can_return_user<T: Into<Conf<bool>>>(&self, can_return: T) {
399        let mut bool_with_confidence = can_return.into().into();
400        unsafe { BNSetUserFunctionCanReturn(self.handle, &mut bool_with_confidence) }
401    }
402
403    pub fn comment_at(&self, addr: u64) -> String {
404        unsafe { BnString::into_string(BNGetCommentForAddress(self.handle, addr)) }
405    }
406
407    pub fn set_comment_at(&self, addr: u64, comment: &str) {
408        let raw = comment.to_cstr();
409
410        unsafe {
411            BNSetCommentForAddress(self.handle, addr, raw.as_ptr());
412        }
413    }
414
415    /// All comments in the function
416    pub fn comments(&self) -> Array<Comment> {
417        let mut count = 0;
418        let lines = unsafe { BNGetCommentedAddresses(self.handle, &mut count) };
419        unsafe { Array::new(lines, count, self.to_owned()) }
420    }
421
422    pub fn basic_blocks(&self) -> Array<BasicBlock<NativeBlock>> {
423        unsafe {
424            let mut count = 0;
425            let blocks = BNGetFunctionBasicBlockList(self.handle, &mut count);
426            let context = NativeBlock { _priv: () };
427
428            Array::new(blocks, count, context)
429        }
430    }
431
432    /// Returns the BasicBlock that contains the given address `addr`.
433    ///
434    /// * `addr` - Address of the BasicBlock to retrieve.
435    /// * `arch` - Architecture of the basic block if different from the Function's self.arch
436    ///
437    /// # Example
438    /// ```no_run
439    /// # use binaryninja::function::Function;
440    /// # let fun: Function = todo!();
441    /// let blocks = fun.basic_block_containing(0x1000, None);
442    /// ```
443    pub fn basic_block_containing(
444        &self,
445        addr: u64,
446        arch: Option<CoreArchitecture>,
447    ) -> Option<Ref<BasicBlock<NativeBlock>>> {
448        let arch = arch.unwrap_or_else(|| self.arch());
449        unsafe {
450            let basic_block_ptr = BNGetFunctionBasicBlockAtAddress(self.handle, arch.handle, addr);
451            let context = NativeBlock { _priv: () };
452            match basic_block_ptr.is_null() {
453                false => Some(BasicBlock::ref_from_raw(basic_block_ptr, context)),
454                true => None,
455            }
456        }
457    }
458
459    pub fn block_annotations(
460        &self,
461        addr: u64,
462        arch: Option<CoreArchitecture>,
463    ) -> Array<Array<InstructionTextToken>> {
464        let arch = arch.unwrap_or_else(|| self.arch());
465        let mut count = 0;
466        let lines =
467            unsafe { BNGetFunctionBlockAnnotations(self.handle, arch.handle, addr, &mut count) };
468        assert!(!lines.is_null());
469        unsafe { Array::new(lines, count, ()) }
470    }
471
472    pub fn variable_name(&self, var: &Variable) -> String {
473        unsafe {
474            let raw_var = BNVariable::from(var);
475            let raw_name = BNGetVariableName(self.handle, &raw_var);
476            BnString::into_string(raw_name)
477        }
478    }
479
480    pub fn variable_type(&self, var: &Variable) -> Option<Conf<Ref<Type>>> {
481        let raw_var = BNVariable::from(var);
482        let result = unsafe { BNGetVariableType(self.handle, &raw_var) };
483        match result.type_.is_null() {
484            false => Some(Conf::<Ref<Type>>::from_owned_raw(result)),
485            true => None,
486        }
487    }
488
489    /// Get the language representation of the function.
490    ///
491    ///  * `language` - The language representation, ex. "Pseudo C".
492    pub fn language_representation(
493        &self,
494        language: &str,
495    ) -> Option<Ref<CoreLanguageRepresentationFunction>> {
496        let lang_name = language.to_cstr();
497        let repr = unsafe { BNGetFunctionLanguageRepresentation(self.handle, lang_name.as_ptr()) };
498        NonNull::new(repr)
499            .map(|handle| unsafe { CoreLanguageRepresentationFunction::ref_from_raw(handle) })
500    }
501
502    /// Get the language representation of the function, if available.
503    ///
504    ///  * `language` - The language representation, ex. "Pseudo C".
505    pub fn language_representation_if_available(
506        &self,
507        language: &str,
508    ) -> Option<Ref<CoreLanguageRepresentationFunction>> {
509        let lang_name = language.to_cstr();
510        let repr = unsafe {
511            BNGetFunctionLanguageRepresentationIfAvailable(self.handle, lang_name.as_ptr())
512        };
513        NonNull::new(repr)
514            .map(|handle| unsafe { CoreLanguageRepresentationFunction::ref_from_raw(handle) })
515    }
516
517    pub fn high_level_il(&self, full_ast: bool) -> Result<Ref<HighLevelILFunction>, ()> {
518        unsafe {
519            let hlil_ptr = BNGetFunctionHighLevelIL(self.handle);
520            match hlil_ptr.is_null() {
521                false => Ok(HighLevelILFunction::ref_from_raw(hlil_ptr, full_ast)),
522                true => Err(()),
523            }
524        }
525    }
526
527    pub fn high_level_il_if_available(&self) -> Option<Ref<HighLevelILFunction>> {
528        let hlil_ptr = unsafe { BNGetFunctionHighLevelILIfAvailable(self.handle) };
529        match hlil_ptr.is_null() {
530            false => Some(unsafe { HighLevelILFunction::ref_from_raw(hlil_ptr, true) }),
531            true => None,
532        }
533    }
534
535    /// MediumLevelILFunction used to represent Function mapped medium level IL
536    pub fn mapped_medium_level_il(&self) -> Result<Ref<MediumLevelILFunction>, ()> {
537        let mlil_ptr = unsafe { BNGetFunctionMappedMediumLevelIL(self.handle) };
538        match mlil_ptr.is_null() {
539            false => Ok(unsafe { MediumLevelILFunction::ref_from_raw(mlil_ptr) }),
540            true => Err(()),
541        }
542    }
543
544    pub fn mapped_medium_level_il_if_available(&self) -> Option<Ref<MediumLevelILFunction>> {
545        let mlil_ptr = unsafe { BNGetFunctionMappedMediumLevelILIfAvailable(self.handle) };
546        match mlil_ptr.is_null() {
547            false => Some(unsafe { MediumLevelILFunction::ref_from_raw(mlil_ptr) }),
548            true => None,
549        }
550    }
551
552    pub fn medium_level_il(&self) -> Result<Ref<MediumLevelILFunction>, ()> {
553        unsafe {
554            let mlil_ptr = BNGetFunctionMediumLevelIL(self.handle);
555            match mlil_ptr.is_null() {
556                false => Ok(MediumLevelILFunction::ref_from_raw(mlil_ptr)),
557                true => Err(()),
558            }
559        }
560    }
561
562    pub fn medium_level_il_if_available(&self) -> Option<Ref<MediumLevelILFunction>> {
563        let mlil_ptr = unsafe { BNGetFunctionMediumLevelILIfAvailable(self.handle) };
564        match mlil_ptr.is_null() {
565            false => Some(unsafe { MediumLevelILFunction::ref_from_raw(mlil_ptr) }),
566            true => None,
567        }
568    }
569
570    pub fn low_level_il(&self) -> Result<Ref<LowLevelILRegularFunction>, ()> {
571        unsafe {
572            let llil_ptr = BNGetFunctionLowLevelIL(self.handle);
573            match llil_ptr.is_null() {
574                false => Ok(LowLevelILRegularFunction::ref_from_raw(llil_ptr)),
575                true => Err(()),
576            }
577        }
578    }
579
580    pub fn low_level_il_if_available(&self) -> Option<Ref<LowLevelILRegularFunction>> {
581        let llil_ptr = unsafe { BNGetFunctionLowLevelILIfAvailable(self.handle) };
582        match llil_ptr.is_null() {
583            false => Some(unsafe { LowLevelILRegularFunction::ref_from_raw(llil_ptr) }),
584            true => None,
585        }
586    }
587
588    pub fn lifted_il(&self) -> Result<Ref<LowLevelILRegularFunction>, ()> {
589        unsafe {
590            let llil_ptr = BNGetFunctionLiftedIL(self.handle);
591            match llil_ptr.is_null() {
592                false => Ok(LowLevelILRegularFunction::ref_from_raw(llil_ptr)),
593                true => Err(()),
594            }
595        }
596    }
597
598    pub fn lifted_il_if_available(&self) -> Option<Ref<LowLevelILRegularFunction>> {
599        let llil_ptr = unsafe { BNGetFunctionLiftedILIfAvailable(self.handle) };
600        match llil_ptr.is_null() {
601            false => Some(unsafe { LowLevelILRegularFunction::ref_from_raw(llil_ptr) }),
602            true => None,
603        }
604    }
605
606    pub fn return_type(&self) -> Conf<Ref<Type>> {
607        let raw_return_type = unsafe { BNGetFunctionReturnType(self.handle) };
608        Conf::<Ref<Type>>::from_owned_raw(raw_return_type)
609    }
610
611    pub fn set_auto_return_type<'a, C>(&self, return_type: C)
612    where
613        C: Into<Conf<&'a Type>>,
614    {
615        let mut raw_return_type = Conf::<&Type>::into_raw(return_type.into());
616        unsafe { BNSetAutoFunctionReturnType(self.handle, &mut raw_return_type) }
617    }
618
619    pub fn set_user_return_type<'a, C>(&self, return_type: C)
620    where
621        C: Into<Conf<&'a Type>>,
622    {
623        let mut raw_return_type = Conf::<&Type>::into_raw(return_type.into());
624        unsafe { BNSetUserFunctionReturnType(self.handle, &mut raw_return_type) }
625    }
626
627    pub fn function_type(&self) -> Ref<Type> {
628        unsafe { Type::ref_from_raw(BNGetFunctionType(self.handle)) }
629    }
630
631    pub fn has_user_type(&self) -> bool {
632        unsafe { BNFunctionHasUserType(self.handle) }
633    }
634
635    pub fn set_user_type(&self, t: &Type) {
636        unsafe { BNSetFunctionUserType(self.handle, t.handle) }
637    }
638
639    pub fn set_auto_type(&self, t: &Type) {
640        unsafe { BNSetFunctionAutoType(self.handle, t.handle) }
641    }
642
643    pub fn stack_layout(&self) -> Array<NamedVariableWithType> {
644        let mut count = 0;
645        unsafe {
646            let variables = BNGetStackLayout(self.handle, &mut count);
647            Array::new(variables, count, ())
648        }
649    }
650
651    /// Gets number of bytes removed from the stack after return
652    pub fn stack_adjustment(&self) -> Conf<i64> {
653        unsafe { BNGetFunctionStackAdjustment(self.handle) }.into()
654    }
655
656    /// Sets number of bytes removed from the stack after return
657    pub fn set_user_stack_adjustment<C>(&self, value: C)
658    where
659        C: Into<Conf<i64>>,
660    {
661        let value: Conf<i64> = value.into();
662        let mut value_raw = value.into();
663        unsafe { BNSetUserFunctionStackAdjustment(self.handle, &mut value_raw) }
664    }
665
666    /// Sets number of bytes removed from the stack after return
667    pub fn set_auto_stack_adjustment<C>(&self, value: C)
668    where
669        C: Into<Conf<i64>>,
670    {
671        let value: Conf<i64> = value.into();
672        let mut value_raw = value.into();
673        unsafe { BNSetAutoFunctionStackAdjustment(self.handle, &mut value_raw) }
674    }
675
676    pub fn call_stack_adjustment(&self, addr: u64, arch: Option<CoreArchitecture>) -> Conf<i64> {
677        let arch = arch.unwrap_or_else(|| self.arch());
678        let result = unsafe { BNGetCallStackAdjustment(self.handle, arch.handle, addr) };
679        result.into()
680    }
681
682    pub fn set_user_call_stack_adjustment<I>(
683        &self,
684        addr: u64,
685        adjust: I,
686        arch: Option<CoreArchitecture>,
687    ) where
688        I: Into<Conf<i64>>,
689    {
690        let arch = arch.unwrap_or_else(|| self.arch());
691        let adjust: Conf<i64> = adjust.into();
692        unsafe {
693            BNSetUserCallStackAdjustment(
694                self.handle,
695                arch.handle,
696                addr,
697                adjust.contents,
698                adjust.confidence,
699            )
700        }
701    }
702
703    pub fn set_auto_call_stack_adjustment<I>(
704        &self,
705        addr: u64,
706        adjust: I,
707        arch: Option<CoreArchitecture>,
708    ) where
709        I: Into<Conf<i64>>,
710    {
711        let arch = arch.unwrap_or_else(|| self.arch());
712        let adjust: Conf<i64> = adjust.into();
713        unsafe {
714            BNSetAutoCallStackAdjustment(
715                self.handle,
716                arch.handle,
717                addr,
718                adjust.contents,
719                adjust.confidence,
720            )
721        }
722    }
723
724    pub fn call_type_adjustment(
725        &self,
726        addr: u64,
727        arch: Option<CoreArchitecture>,
728    ) -> Option<Conf<Ref<Type>>> {
729        let arch = arch.unwrap_or_else(|| self.arch());
730        let result = unsafe { BNGetCallTypeAdjustment(self.handle, arch.handle, addr) };
731        match result.type_.is_null() {
732            false => Some(Conf::<Ref<Type>>::from_owned_raw(result)),
733            true => None,
734        }
735    }
736
737    /// Sets or removes the call type override at a call site to the given type.
738    ///
739    /// * `addr` - virtual address of the call instruction to adjust
740    /// * `adjust_type` - (optional) overridden call type, or `None` to remove an existing adjustment
741    /// * `arch` - (optional) Architecture of the instruction if different from self.arch
742    pub fn set_user_call_type_adjustment<'a, I>(
743        &self,
744        addr: u64,
745        adjust_type: Option<I>,
746        arch: Option<CoreArchitecture>,
747    ) where
748        I: Into<Conf<&'a Type>>,
749    {
750        let arch = arch.unwrap_or_else(|| self.arch());
751        let mut adjust_type = adjust_type.map(|adjust_type| {
752            let adjust_type = adjust_type.into();
753            BNTypeWithConfidence {
754                type_: adjust_type.contents.handle,
755                confidence: adjust_type.confidence,
756            }
757        });
758        let adjust_ptr = adjust_type
759            .as_mut()
760            .map(|x| x as *mut _)
761            .unwrap_or(std::ptr::null_mut());
762        unsafe { BNSetUserCallTypeAdjustment(self.handle, arch.handle, addr, adjust_ptr) }
763    }
764
765    pub fn set_auto_call_type_adjustment<'a, I>(
766        &self,
767        addr: u64,
768        adjust_type: I,
769        arch: Option<CoreArchitecture>,
770    ) where
771        I: Into<Conf<&'a Type>>,
772    {
773        let arch = arch.unwrap_or_else(|| self.arch());
774        let adjust_type: Conf<&Type> = adjust_type.into();
775        unsafe {
776            BNSetAutoCallTypeAdjustment(
777                self.handle,
778                arch.handle,
779                addr,
780                &mut BNTypeWithConfidence {
781                    type_: adjust_type.contents.handle,
782                    confidence: adjust_type.confidence,
783                },
784            )
785        }
786    }
787
788    pub fn call_reg_stack_adjustment(
789        &self,
790        addr: u64,
791        arch: Option<CoreArchitecture>,
792    ) -> Array<RegisterStackAdjustment> {
793        let arch = arch.unwrap_or_else(|| self.arch());
794        let mut count = 0;
795        let adjust =
796            unsafe { BNGetCallRegisterStackAdjustment(self.handle, arch.handle, addr, &mut count) };
797        assert!(!adjust.is_null());
798        unsafe { Array::new(adjust, count, ()) }
799    }
800
801    pub fn set_user_call_reg_stack_adjustment<I>(
802        self,
803        addr: u64,
804        adjust: I,
805        arch: Option<CoreArchitecture>,
806    ) where
807        I: IntoIterator<Item = RegisterStackAdjustment>,
808    {
809        let arch = arch.unwrap_or_else(|| self.arch());
810        let adjustments: Vec<BNRegisterStackAdjustment> =
811            adjust.into_iter().map(Into::into).collect();
812        unsafe {
813            BNSetUserCallRegisterStackAdjustment(
814                self.handle,
815                arch.handle,
816                addr,
817                adjustments.as_ptr() as *mut _,
818                adjustments.len(),
819            )
820        }
821    }
822
823    pub fn set_auto_call_reg_stack_adjustment<I>(
824        &self,
825        addr: u64,
826        adjust: I,
827        arch: Option<CoreArchitecture>,
828    ) where
829        I: IntoIterator<Item = RegisterStackAdjustment>,
830    {
831        let arch = arch.unwrap_or_else(|| self.arch());
832        let adjustments: Vec<BNRegisterStackAdjustment> =
833            adjust.into_iter().map(Into::into).collect();
834        unsafe {
835            BNSetAutoCallRegisterStackAdjustment(
836                self.handle,
837                arch.handle,
838                addr,
839                adjustments.as_ptr() as *mut _,
840                adjustments.len(),
841            )
842        }
843    }
844
845    pub fn call_reg_stack_adjustment_for_reg_stack(
846        &self,
847        addr: u64,
848        reg_stack_id: u32,
849        arch: Option<CoreArchitecture>,
850    ) -> RegisterStackAdjustment {
851        let arch = arch.unwrap_or_else(|| self.arch());
852        let adjust = unsafe {
853            BNGetCallRegisterStackAdjustmentForRegisterStack(
854                self.handle,
855                arch.handle,
856                addr,
857                reg_stack_id,
858            )
859        };
860        RegisterStackAdjustment::from(adjust)
861    }
862
863    pub fn set_user_call_reg_stack_adjustment_for_reg_stack<I>(
864        &self,
865        addr: u64,
866        reg_stack_id: u32,
867        adjust: I,
868        arch: Option<CoreArchitecture>,
869    ) where
870        I: Into<Conf<i32>>,
871    {
872        let arch = arch.unwrap_or_else(|| self.arch());
873        let adjust: Conf<i32> = adjust.into();
874        unsafe {
875            BNSetUserCallRegisterStackAdjustmentForRegisterStack(
876                self.handle,
877                arch.handle,
878                addr,
879                reg_stack_id,
880                adjust.contents,
881                adjust.confidence,
882            )
883        }
884    }
885
886    pub fn set_auto_call_reg_stack_adjustment_for_reg_stack<I>(
887        &self,
888        addr: u64,
889        reg_stack_id: u32,
890        adjust: I,
891        arch: Option<CoreArchitecture>,
892    ) where
893        I: Into<Conf<i32>>,
894    {
895        let arch = arch.unwrap_or_else(|| self.arch());
896        let adjust: Conf<i32> = adjust.into();
897        unsafe {
898            BNSetAutoCallRegisterStackAdjustmentForRegisterStack(
899                self.handle,
900                arch.handle,
901                addr,
902                reg_stack_id,
903                adjust.contents,
904                adjust.confidence,
905            )
906        }
907    }
908
909    pub fn reg_stack_adjustments(&self) -> Array<RegisterStackAdjustment> {
910        let mut count = 0;
911        let adjust = unsafe { BNGetFunctionRegisterStackAdjustments(self.handle, &mut count) };
912        assert!(!adjust.is_null());
913        unsafe { Array::new(adjust, count, ()) }
914    }
915
916    pub fn set_user_reg_stack_adjustments<I>(&self, values: I)
917    where
918        I: IntoIterator<Item = RegisterStackAdjustment>,
919    {
920        let values: Vec<BNRegisterStackAdjustment> = values.into_iter().map(Into::into).collect();
921        unsafe {
922            BNSetUserFunctionRegisterStackAdjustments(
923                self.handle,
924                values.as_ptr() as *mut _,
925                values.len(),
926            )
927        }
928    }
929
930    pub fn set_auto_reg_stack_adjustments<I>(&self, values: I)
931    where
932        I: IntoIterator<Item = RegisterStackAdjustment>,
933    {
934        let values: Vec<BNRegisterStackAdjustment> = values.into_iter().map(Into::into).collect();
935        unsafe {
936            BNSetAutoFunctionRegisterStackAdjustments(
937                self.handle,
938                values.as_ptr() as *mut _,
939                values.len(),
940            )
941        }
942    }
943
944    // TODO: Turn this into an actual type?
945    /// List of function variables: including name, variable and type
946    pub fn variables(&self) -> Array<NamedVariableWithType> {
947        let mut count = 0;
948        let vars = unsafe { BNGetFunctionVariables(self.handle, &mut count) };
949        assert!(!vars.is_null());
950        unsafe { Array::new(vars, count, ()) }
951    }
952
953    pub fn split_variables(&self) -> Array<Variable> {
954        let mut count = 0;
955        let vars = unsafe { BNGetSplitVariables(self.handle, &mut count) };
956        assert!(!vars.is_null());
957        unsafe { Array::new(vars, count, ()) }
958    }
959
960    pub fn parameter_variables(&self) -> Conf<Vec<Variable>> {
961        unsafe {
962            let mut raw_variables = BNGetFunctionParameterVariables(self.handle);
963            let raw_var_list = std::slice::from_raw_parts(raw_variables.vars, raw_variables.count);
964            let variables: Vec<Variable> = raw_var_list.iter().map(Into::into).collect();
965            let confidence = raw_variables.confidence;
966            BNFreeParameterVariables(&mut raw_variables);
967            Conf::new(variables, confidence)
968        }
969    }
970
971    pub fn set_user_parameter_variables<I>(&self, values: I, confidence: u8)
972    where
973        I: IntoIterator<Item = Variable>,
974    {
975        let vars: Vec<BNVariable> = values.into_iter().map(Into::into).collect();
976        unsafe {
977            BNSetUserFunctionParameterVariables(
978                self.handle,
979                &mut BNParameterVariablesWithConfidence {
980                    vars: vars.as_ptr() as *mut _,
981                    count: vars.len(),
982                    confidence,
983                },
984            )
985        }
986    }
987
988    pub fn set_auto_parameter_variables<I>(&self, values: I, confidence: u8)
989    where
990        I: IntoIterator<Item = Variable>,
991    {
992        let vars: Vec<BNVariable> = values.into_iter().map(Into::into).collect();
993        unsafe {
994            BNSetAutoFunctionParameterVariables(
995                self.handle,
996                &mut BNParameterVariablesWithConfidence {
997                    vars: vars.as_ptr() as *mut _,
998                    count: vars.len(),
999                    confidence,
1000                },
1001            )
1002        }
1003    }
1004
1005    pub fn parameter_at(
1006        &self,
1007        addr: u64,
1008        func_type: Option<&Type>,
1009        i: usize,
1010        arch: Option<CoreArchitecture>,
1011    ) -> RegisterValue {
1012        let arch = arch.unwrap_or_else(|| self.arch());
1013        let func_type = func_type.map(|f| f.handle).unwrap_or(std::ptr::null_mut());
1014        let value = unsafe {
1015            BNGetParameterValueAtInstruction(self.handle, arch.handle, addr, func_type, i)
1016        };
1017        value.into()
1018    }
1019
1020    pub fn parameter_at_low_level_il_instruction(
1021        &self,
1022        instr: usize,
1023        func_type: &Type,
1024        i: usize,
1025    ) -> RegisterValue {
1026        let value = unsafe {
1027            BNGetParameterValueAtLowLevelILInstruction(self.handle, instr, func_type.handle, i)
1028        };
1029        value.into()
1030    }
1031
1032    pub fn apply_imported_types(&self, sym: &Symbol, t: Option<&Type>) {
1033        unsafe {
1034            BNApplyImportedTypes(
1035                self.handle,
1036                sym.handle,
1037                t.map(|t| t.handle).unwrap_or(std::ptr::null_mut()),
1038            );
1039        }
1040    }
1041
1042    pub fn apply_auto_discovered_type(&self, func_type: &Type) {
1043        unsafe { BNApplyAutoDiscoveredFunctionType(self.handle, func_type.handle) }
1044    }
1045
1046    /// Whether automatic analysis was skipped for this function.
1047    /// Can be set to false to re-enable analysis.
1048    pub fn analysis_skipped(&self) -> bool {
1049        unsafe { BNIsFunctionAnalysisSkipped(self.handle) }
1050    }
1051
1052    pub fn set_analysis_skipped(&self, skip: bool) {
1053        if skip {
1054            unsafe {
1055                BNSetFunctionAnalysisSkipOverride(
1056                    self.handle,
1057                    BNFunctionAnalysisSkipOverride::AlwaysSkipFunctionAnalysis,
1058                );
1059            }
1060        } else {
1061            unsafe {
1062                BNSetFunctionAnalysisSkipOverride(
1063                    self.handle,
1064                    BNFunctionAnalysisSkipOverride::NeverSkipFunctionAnalysis,
1065                );
1066            }
1067        }
1068    }
1069
1070    pub fn analysis_skip_reason(&self) -> AnalysisSkipReason {
1071        unsafe { BNGetAnalysisSkipReason(self.handle) }
1072    }
1073
1074    pub fn analysis_skip_override(&self) -> FunctionAnalysisSkipOverride {
1075        unsafe { BNGetFunctionAnalysisSkipOverride(self.handle) }
1076    }
1077
1078    pub fn set_analysis_skip_override(&self, override_: FunctionAnalysisSkipOverride) {
1079        unsafe { BNSetFunctionAnalysisSkipOverride(self.handle, override_) }
1080    }
1081
1082    ///Whether the function's IL should be inlined into all callers' IL
1083    pub fn inline_during_analysis(&self) -> Conf<bool> {
1084        let result = unsafe { BNIsFunctionInlinedDuringAnalysis(self.handle) };
1085        result.into()
1086    }
1087
1088    pub fn set_auto_inline_during_analysis<C>(&self, value: C)
1089    where
1090        C: Into<Conf<bool>>,
1091    {
1092        let value: Conf<bool> = value.into();
1093        unsafe { BNSetAutoFunctionInlinedDuringAnalysis(self.handle, value.into()) }
1094    }
1095
1096    pub fn set_user_inline_during_analysis<C>(&self, value: C)
1097    where
1098        C: Into<Conf<bool>>,
1099    {
1100        let value: Conf<bool> = value.into();
1101        unsafe { BNSetUserFunctionInlinedDuringAnalysis(self.handle, value.into()) }
1102    }
1103
1104    pub fn analysis_performance_info(&self) -> Array<PerformanceInfo> {
1105        let mut count = 0;
1106        let info = unsafe { BNGetFunctionAnalysisPerformanceInfo(self.handle, &mut count) };
1107        assert!(!info.is_null());
1108        unsafe { Array::new(info, count, ()) }
1109    }
1110
1111    /// Creates and adds a [Tag] object on either a function, or on
1112    /// an address inside of a function.
1113    ///
1114    /// "Function tags" appear at the top of a function and are a good way to label an
1115    /// entire function with some information. If you include an address when you call
1116    /// Function.add_tag, you'll create an "address tag". These are good for labeling
1117    /// specific instructions.
1118    ///
1119    /// For tagging arbitrary data, consider [BinaryViewExt::add_tag].
1120    ///
1121    /// * `tag_type_name` - The name of the tag type for this Tag.
1122    /// * `data` - Additional data for the Tag.
1123    /// * `addr` - Address at which to add the tag.
1124    /// * `user` - Whether or not a user tag.
1125    ///
1126    /// # Example
1127    ///
1128    /// ```no_run
1129    /// # use binaryninja::binary_view::{BinaryView, BinaryViewExt};
1130    /// # use binaryninja::function::Function;
1131    /// # let fun: Function = todo!();
1132    /// # let bv: BinaryView = todo!();
1133    /// let important = bv.create_tag_type("Important", "⚠️");
1134    /// fun.add_tag(
1135    ///     &important,
1136    ///     "I think this is the main function",
1137    ///     None,
1138    ///     false,
1139    ///     None,
1140    /// );
1141    /// let crash = bv.create_tag_type("Crashes", "🎯");
1142    /// fun.add_tag(&crash, "Nullpointer dereference", Some(0x1337), false, None);
1143    /// ```
1144    pub fn add_tag(
1145        &self,
1146        tag_type: &TagType,
1147        data: &str,
1148        addr: Option<u64>,
1149        user: bool,
1150        arch: Option<CoreArchitecture>,
1151    ) {
1152        let arch = arch.unwrap_or_else(|| self.arch());
1153
1154        // Create tag
1155        let tag = Tag::new(tag_type, data);
1156        unsafe { BNAddTag(self.view().handle, tag.handle, user) };
1157
1158        unsafe {
1159            match (user, addr) {
1160                (false, None) => BNAddAutoFunctionTag(self.handle, tag.handle),
1161                (false, Some(addr)) => {
1162                    BNAddAutoAddressTag(self.handle, arch.handle, addr, tag.handle)
1163                }
1164                (true, None) => BNAddUserFunctionTag(self.handle, tag.handle),
1165                (true, Some(addr)) => {
1166                    BNAddUserAddressTag(self.handle, arch.handle, addr, tag.handle)
1167                }
1168            }
1169        }
1170    }
1171
1172    /// Remove [Tag] object on either a function, or on an address inside of a function.
1173    ///
1174    /// * `tag` - The tag to remove.
1175    /// * `addr` - (optional) Address at which to remove the tag.
1176    /// * `user` - Whether or not a user tag.
1177    pub fn remove_tag(
1178        &self,
1179        tag: &Tag,
1180        addr: Option<u64>,
1181        user: bool,
1182        arch: Option<CoreArchitecture>,
1183    ) {
1184        let arch = arch.unwrap_or_else(|| self.arch());
1185        unsafe {
1186            match (user, addr) {
1187                (false, None) => BNRemoveAutoFunctionTag(self.handle, tag.handle),
1188                (false, Some(addr)) => {
1189                    BNRemoveAutoAddressTag(self.handle, arch.handle, addr, tag.handle)
1190                }
1191                (true, None) => BNRemoveUserFunctionTag(self.handle, tag.handle),
1192                (true, Some(addr)) => {
1193                    BNRemoveUserAddressTag(self.handle, arch.handle, addr, tag.handle)
1194                }
1195            }
1196        }
1197    }
1198
1199    /// Remove [Tag] object of type on either a function, or on an address
1200    /// inside of a function.
1201    ///
1202    /// * `tag_type` - The type of the to remove.
1203    /// * `addr` - Address at which to add the tag.
1204    /// * `user` - Whether or not a user tag.
1205    pub fn remove_tags_of_type(
1206        &self,
1207        tag_type: &TagType,
1208        addr: Option<u64>,
1209        user: bool,
1210        arch: Option<CoreArchitecture>,
1211    ) {
1212        let arch = arch.unwrap_or_else(|| self.arch());
1213        unsafe {
1214            match (user, addr) {
1215                (false, None) => BNRemoveAutoFunctionTagsOfType(self.handle, tag_type.handle),
1216                (false, Some(addr)) => {
1217                    BNRemoveAutoAddressTagsOfType(self.handle, arch.handle, addr, tag_type.handle)
1218                }
1219                (true, None) => BNRemoveUserFunctionTagsOfType(self.handle, tag_type.handle),
1220                (true, Some(addr)) => {
1221                    BNRemoveUserAddressTagsOfType(self.handle, arch.handle, addr, tag_type.handle)
1222                }
1223            }
1224        }
1225    }
1226
1227    /// Places a user-defined cross-reference from the instruction at
1228    /// the given address and architecture to the specified target address. If the specified
1229    /// source instruction is not contained within this function, no action is performed.
1230    /// To remove the reference, use [Function::remove_user_code_ref].
1231    ///
1232    /// * `from_addr` - Virtual address of the source instruction.
1233    /// * `to_addr` - Virtual address of the xref's destination.
1234    /// * `arch` - Architecture of the source instruction.
1235    ///
1236    /// # Example
1237    ///
1238    /// ```no_run
1239    /// # use binaryninja::function::Function;
1240    /// # let fun: Function = todo!();
1241    /// fun.add_user_code_ref(0x1337, 0x400000, None);
1242    /// ```
1243    pub fn add_user_code_ref(&self, from_addr: u64, to_addr: u64, arch: Option<CoreArchitecture>) {
1244        let arch = arch.unwrap_or_else(|| self.arch());
1245        unsafe { BNAddUserCodeReference(self.handle, arch.handle, from_addr, to_addr) }
1246    }
1247
1248    /// Removes a user-defined cross-reference.
1249    /// If the given address is not contained within this function, or if there is no
1250    /// such user-defined cross-reference, no action is performed.
1251    ///
1252    /// * `from_addr` - virtual address of the source instruction
1253    /// * `to_addr` - virtual address of the xref's destination.
1254    /// * `arch` - architecture of the source instruction
1255    ///
1256    /// #Example
1257    ///
1258    /// ```no_run
1259    /// # use binaryninja::function::Function;
1260    /// # let fun: Function = todo!();
1261    /// fun.remove_user_code_ref(0x1337, 0x400000, None);
1262    /// ```
1263    pub fn remove_user_code_ref(
1264        self,
1265        from_addr: u64,
1266        to_addr: u64,
1267        arch: Option<CoreArchitecture>,
1268    ) {
1269        let arch = arch.unwrap_or_else(|| self.arch());
1270        unsafe { BNRemoveUserCodeReference(self.handle, arch.handle, from_addr, to_addr) }
1271    }
1272
1273    /// Places a user-defined type cross-reference from the instruction at
1274    /// the given address and architecture to the specified type. If the specified
1275    /// source instruction is not contained within this function, no action is performed.
1276    /// To remove the reference, use [Function::remove_user_type_ref].
1277    ///
1278    /// * `from_addr` - Virtual address of the source instruction.
1279    /// * `name` - Name of the referenced type.
1280    /// * `arch` - Architecture of the source instruction.
1281    ///
1282    /// # Example
1283    /// ```no_run
1284    /// # use binaryninja::function::Function;
1285    /// # let fun: Function = todo!();
1286    /// fun.add_user_type_ref(0x1337, "A", None);
1287    /// ```
1288    pub fn add_user_type_ref<T: Into<QualifiedName>>(
1289        &self,
1290        from_addr: u64,
1291        name: T,
1292        arch: Option<CoreArchitecture>,
1293    ) {
1294        let arch = arch.unwrap_or_else(|| self.arch());
1295        let mut raw_name = QualifiedName::into_raw(name.into());
1296        unsafe { BNAddUserTypeReference(self.handle, arch.handle, from_addr, &mut raw_name) };
1297        QualifiedName::free_raw(raw_name);
1298    }
1299
1300    /// Removes a user-defined type cross-reference.
1301    /// If the given address is not contained within this function, or if there is no
1302    /// such user-defined cross-reference, no action is performed.
1303    ///
1304    /// * `from_addr` - Virtual address of the source instruction.
1305    /// * `name` - Name of the referenced type.
1306    /// * `from_arch` - Architecture of the source instruction.
1307    ///
1308    /// # Example
1309    /// ```no_run
1310    /// # use binaryninja::function::Function;
1311    /// # let fun: Function = todo!();
1312    /// fun.remove_user_type_ref(0x1337, "A", None);
1313    /// ```
1314    pub fn remove_user_type_ref<T: Into<QualifiedName>>(
1315        &self,
1316        from_addr: u64,
1317        name: T,
1318        arch: Option<CoreArchitecture>,
1319    ) {
1320        let arch = arch.unwrap_or_else(|| self.arch());
1321        let mut raw_name = QualifiedName::into_raw(name.into());
1322        unsafe { BNRemoveUserTypeReference(self.handle, arch.handle, from_addr, &mut raw_name) };
1323        QualifiedName::free_raw(raw_name);
1324    }
1325
1326    /// Places a user-defined type field cross-reference from the
1327    /// instruction at the given address and architecture to the specified type. If the specified
1328    /// source instruction is not contained within this function, no action is performed.
1329    /// To remove the reference, use [Function::remove_user_type_field_ref].
1330    ///
1331    /// * `from_addr` - Virtual address of the source instruction.
1332    /// * `name` - Name of the referenced type.
1333    /// * `offset` - Offset of the field, relative to the type.
1334    /// * `arch` - Architecture of the source instruction.
1335    /// * `size` - The size of the access.
1336    ///
1337    /// # Example
1338    /// ```no_run
1339    /// # use binaryninja::function::Function;
1340    /// # let fun: Function = todo!();
1341    /// fun.add_user_type_field_ref(0x1337, "A", 0x8, None, None);
1342    /// ```
1343    pub fn add_user_type_field_ref<T: Into<QualifiedName>>(
1344        &self,
1345        from_addr: u64,
1346        name: T,
1347        offset: u64,
1348        arch: Option<CoreArchitecture>,
1349        size: Option<usize>,
1350    ) {
1351        let size = size.unwrap_or(0);
1352        let arch = arch.unwrap_or_else(|| self.arch());
1353        let mut raw_name = QualifiedName::into_raw(name.into());
1354        unsafe {
1355            BNAddUserTypeFieldReference(
1356                self.handle,
1357                arch.handle,
1358                from_addr,
1359                &mut raw_name,
1360                offset,
1361                size,
1362            )
1363        };
1364        QualifiedName::free_raw(raw_name);
1365    }
1366
1367    /// Removes a user-defined type field cross-reference.
1368    /// If the given address is not contained within this function, or if there is no
1369    /// such user-defined cross-reference, no action is performed.
1370    ///
1371    /// * `from_addr` - Virtual address of the source instruction
1372    /// * `name` - Name of the referenced type
1373    /// * `offset` - Offset of the field, relative to the type
1374    /// * `arch` - Architecture of the source instruction
1375    /// * `size` - The size of the access
1376    ///
1377    /// # Example
1378    /// ```no_run
1379    /// # use binaryninja::function::Function;
1380    /// # let fun: Function = todo!();
1381    /// fun.remove_user_type_field_ref(0x1337, "A", 0x8, None, None);
1382    /// ```
1383    pub fn remove_user_type_field_ref<T: Into<QualifiedName>>(
1384        &self,
1385        from_addr: u64,
1386        name: T,
1387        offset: u64,
1388        arch: Option<CoreArchitecture>,
1389        size: Option<usize>,
1390    ) {
1391        let size = size.unwrap_or(0);
1392        let arch = arch.unwrap_or_else(|| self.arch());
1393        let mut raw_name = QualifiedName::into_raw(name.into());
1394        unsafe {
1395            BNRemoveUserTypeFieldReference(
1396                self.handle,
1397                arch.handle,
1398                from_addr,
1399                &mut raw_name,
1400                offset,
1401                size,
1402            )
1403        }
1404        QualifiedName::free_raw(raw_name);
1405    }
1406
1407    pub fn constant_data(
1408        &self,
1409        state: RegisterValueType,
1410        value: u64,
1411        size: Option<usize>,
1412    ) -> (DataBuffer, BuiltinType) {
1413        let size = size.unwrap_or(0);
1414        // TODO: Adjust `BuiltinType`?
1415        let mut builtin_type = BuiltinType::BuiltinNone;
1416        let buffer = DataBuffer::from_raw(unsafe {
1417            BNGetConstantData(self.handle, state, value, size, &mut builtin_type)
1418        });
1419        (buffer, builtin_type)
1420    }
1421
1422    pub fn constants_referenced_by(
1423        &self,
1424        addr: u64,
1425        arch: Option<CoreArchitecture>,
1426    ) -> Array<ConstantReference> {
1427        let arch = arch.unwrap_or_else(|| self.arch());
1428        let mut count = 0;
1429        let refs = unsafe {
1430            BNGetConstantsReferencedByInstruction(self.handle, arch.handle, addr, &mut count)
1431        };
1432        assert!(!refs.is_null());
1433        unsafe { Array::new(refs, count, ()) }
1434    }
1435
1436    pub fn constants_referenced_by_address_if_available(
1437        &self,
1438        addr: u64,
1439        arch: Option<CoreArchitecture>,
1440    ) -> Array<ConstantReference> {
1441        let arch = arch.unwrap_or_else(|| self.arch());
1442        let mut count = 0;
1443        let refs = unsafe {
1444            BNGetConstantsReferencedByInstructionIfAvailable(
1445                self.handle,
1446                arch.handle,
1447                addr,
1448                &mut count,
1449            )
1450        };
1451        assert!(!refs.is_null());
1452        unsafe { Array::new(refs, count, ()) }
1453    }
1454
1455    /// Returns a list of function Tags for the function.
1456    ///
1457    /// `auto` - If `None`, gets all tags, if `true`, gets auto tags, if `false`, gets user tags
1458    /// `tag_type` - If `None`, gets all tags, otherwise only gets tags of the given type
1459    pub fn function_tags(&self, auto: Option<bool>, tag_type: Option<&str>) -> Array<Tag> {
1460        let mut count = 0;
1461
1462        let tag_type = tag_type.map(|tag_type| self.view().tag_type_by_name(tag_type));
1463
1464        let tags = unsafe {
1465            match (tag_type, auto) {
1466                // received a tag_type, BinaryView found none
1467                (Some(None), _) => return Array::new(std::ptr::null_mut(), 0, ()),
1468
1469                // with tag_type
1470                (Some(Some(tag_type)), None) => {
1471                    BNGetFunctionTagsOfType(self.handle, tag_type.handle, &mut count)
1472                }
1473                (Some(Some(tag_type)), Some(true)) => {
1474                    BNGetAutoFunctionTagsOfType(self.handle, tag_type.handle, &mut count)
1475                }
1476                (Some(Some(tag_type)), Some(false)) => {
1477                    BNGetUserFunctionTagsOfType(self.handle, tag_type.handle, &mut count)
1478                }
1479                // without tag_type
1480                (None, None) => BNGetFunctionTags(self.handle, &mut count),
1481                (None, Some(true)) => BNGetAutoFunctionTags(self.handle, &mut count),
1482                (None, Some(false)) => BNGetUserFunctionTags(self.handle, &mut count),
1483            }
1484        };
1485        assert!(!tags.is_null());
1486
1487        unsafe { Array::new(tags, count, ()) }
1488    }
1489
1490    pub fn tags(&self) -> Array<TagReference> {
1491        let mut count = 0;
1492        let tags = unsafe { BNGetAddressTagReferences(self.handle, &mut count) };
1493        unsafe { Array::new(tags, count, ()) }
1494    }
1495
1496    /// Gets a list of Tags at the address.
1497    ///
1498    /// * `addr` - Address to get tags from.
1499    /// * `auto` - If `None`, gets all tags, if `true`, gets auto tags, if `false`, gets user tags
1500    pub fn tags_at(
1501        &self,
1502        addr: u64,
1503        auto: Option<bool>,
1504        arch: Option<CoreArchitecture>,
1505    ) -> Array<Tag> {
1506        let arch = arch.unwrap_or_else(|| self.arch());
1507        let mut count = 0;
1508
1509        let tags = match auto {
1510            None => unsafe { BNGetAddressTags(self.handle, arch.handle, addr, &mut count) },
1511            Some(true) => unsafe {
1512                BNGetAutoAddressTags(self.handle, arch.handle, addr, &mut count)
1513            },
1514            Some(false) => unsafe {
1515                BNGetUserAddressTags(self.handle, arch.handle, addr, &mut count)
1516            },
1517        };
1518        assert!(!tags.is_null());
1519        unsafe { Array::new(tags, count, ()) }
1520    }
1521
1522    /// Gets a list of Tags in the address range.
1523    ///
1524    /// * `addr` - Address to get tags from.
1525    /// * `auto` - If `None`, gets all tags, if `true`, gets auto tags, if `false`, gets user tags
1526    pub fn tags_in_range(
1527        &self,
1528        range: Range<u64>,
1529        auto: Option<bool>,
1530        arch: Option<CoreArchitecture>,
1531    ) -> Array<TagReference> {
1532        let arch = arch.unwrap_or_else(|| self.arch());
1533        let mut count = 0;
1534
1535        let tags = match auto {
1536            None => unsafe {
1537                BNGetAddressTagsInRange(
1538                    self.handle,
1539                    arch.handle,
1540                    range.start,
1541                    range.end,
1542                    &mut count,
1543                )
1544            },
1545            Some(true) => unsafe {
1546                BNGetAutoAddressTagsInRange(
1547                    self.handle,
1548                    arch.handle,
1549                    range.start,
1550                    range.end,
1551                    &mut count,
1552                )
1553            },
1554            Some(false) => unsafe {
1555                BNGetUserAddressTagsInRange(
1556                    self.handle,
1557                    arch.handle,
1558                    range.start,
1559                    range.end,
1560                    &mut count,
1561                )
1562            },
1563        };
1564        assert!(!tags.is_null());
1565        unsafe { Array::new(tags, count, ()) }
1566    }
1567
1568    /// List of indirect branches
1569    pub fn indirect_branches(&self) -> Array<IndirectBranchInfo> {
1570        let mut count = 0;
1571        let branches = unsafe { BNGetIndirectBranches(self.handle, &mut count) };
1572        assert!(!branches.is_null());
1573        unsafe { Array::new(branches, count, ()) }
1574    }
1575
1576    pub fn set_user_indirect_branches<I>(
1577        &self,
1578        source: u64,
1579        branches: I,
1580        arch: Option<CoreArchitecture>,
1581    ) where
1582        I: IntoIterator<Item = u64>,
1583    {
1584        let arch = arch.unwrap_or_else(|| self.arch());
1585        let mut branches: Box<[BNArchitectureAndAddress]> = branches
1586            .into_iter()
1587            .map(|address| BNArchitectureAndAddress {
1588                address,
1589                arch: arch.handle,
1590            })
1591            .collect();
1592        unsafe {
1593            BNSetUserIndirectBranches(
1594                self.handle,
1595                arch.handle,
1596                source,
1597                branches.as_mut_ptr(),
1598                branches.len(),
1599            )
1600        }
1601    }
1602
1603    pub fn set_auto_indirect_branches<I>(
1604        &self,
1605        source: u64,
1606        branches: I,
1607        arch: Option<CoreArchitecture>,
1608    ) where
1609        I: IntoIterator<Item = u64>,
1610    {
1611        let arch = arch.unwrap_or_else(|| self.arch());
1612        let mut branches: Box<[BNArchitectureAndAddress]> = branches
1613            .into_iter()
1614            .map(|address| BNArchitectureAndAddress {
1615                address,
1616                arch: arch.handle,
1617            })
1618            .collect();
1619        unsafe {
1620            BNSetAutoIndirectBranches(
1621                self.handle,
1622                arch.handle,
1623                source,
1624                branches.as_mut_ptr(),
1625                branches.len(),
1626            )
1627        }
1628    }
1629
1630    /// List of indirect branches at this address
1631    pub fn indirect_branches_at(
1632        &self,
1633        addr: u64,
1634        arch: Option<CoreArchitecture>,
1635    ) -> Array<IndirectBranchInfo> {
1636        let arch = arch.unwrap_or_else(|| self.arch());
1637        let mut count = 0;
1638        let branches =
1639            unsafe { BNGetIndirectBranchesAt(self.handle, arch.handle, addr, &mut count) };
1640        assert!(!branches.is_null());
1641        unsafe { Array::new(branches, count, ()) }
1642    }
1643
1644    /// # Example
1645    /// ```no_run
1646    /// # let fun: binaryninja::function::Function = todo!();
1647    /// let color = fun.instr_highlight(0x1337, None);
1648    /// ```
1649    pub fn instr_highlight(&self, addr: u64, arch: Option<CoreArchitecture>) -> HighlightColor {
1650        let arch = arch.unwrap_or_else(|| self.arch());
1651        let color = unsafe { BNGetInstructionHighlight(self.handle, arch.handle, addr) };
1652        HighlightColor::from(color)
1653    }
1654
1655    /// Sets the highlights the instruction at the specified address with the supplied color
1656    ///
1657    /// <div class="warning">Use only in analysis plugins. Do not use in regular plugins, as colors won't be saved to the database.</div>
1658    ///
1659    /// * `addr` - virtual address of the instruction to be highlighted
1660    /// * `color` - Color value to use for highlighting
1661    /// * `arch` - (optional) Architecture of the instruction if different from self.arch
1662    pub fn set_auto_instr_highlight(
1663        &self,
1664        addr: u64,
1665        color: HighlightColor,
1666        arch: Option<CoreArchitecture>,
1667    ) {
1668        let arch = arch.unwrap_or_else(|| self.arch());
1669        unsafe { BNSetAutoInstructionHighlight(self.handle, arch.handle, addr, color.into()) }
1670    }
1671
1672    /// Sets the highlights the instruction at the specified address with the supplied color
1673    ///
1674    /// * `addr` - virtual address of the instruction to be highlighted
1675    /// * `color` - Color value to use for highlighting
1676    /// * `arch` - (optional) Architecture of the instruction, pass this if not views default arch
1677    ///
1678    /// # Example
1679    /// ```no_run
1680    /// # use binaryninja::function::{HighlightColor, HighlightStandardColor};
1681    /// # let function: binaryninja::function::Function = todo!();
1682    /// let color = HighlightColor::StandardHighlightColor {
1683    ///     color: HighlightStandardColor::RedHighlightColor,
1684    ///     alpha: u8::MAX,
1685    /// };
1686    /// function.set_user_instr_highlight(0x1337, color, None);
1687    /// ```
1688    pub fn set_user_instr_highlight(
1689        &self,
1690        addr: u64,
1691        color: HighlightColor,
1692        arch: Option<CoreArchitecture>,
1693    ) {
1694        let arch = arch.unwrap_or_else(|| self.arch());
1695        unsafe { BNSetUserInstructionHighlight(self.handle, arch.handle, addr, color.into()) }
1696    }
1697
1698    pub fn create_user_stack_var<'a, C: Into<Conf<&'a Type>>>(
1699        &self,
1700        offset: i64,
1701        var_type: C,
1702        name: &str,
1703    ) {
1704        let mut owned_raw_var_ty = Conf::<&Type>::into_raw(var_type.into());
1705        let name = name.to_cstr();
1706        unsafe {
1707            BNCreateUserStackVariable(self.handle, offset, &mut owned_raw_var_ty, name.as_ptr())
1708        }
1709    }
1710
1711    pub fn delete_user_stack_var(&self, offset: i64) {
1712        unsafe { BNDeleteUserStackVariable(self.handle, offset) }
1713    }
1714
1715    pub fn create_user_var<'a, C: Into<Conf<&'a Type>>>(
1716        &self,
1717        var: &Variable,
1718        var_type: C,
1719        name: &str,
1720        ignore_disjoint_uses: bool,
1721    ) {
1722        let raw_var = BNVariable::from(var);
1723        let mut owned_raw_var_ty = Conf::<&Type>::into_raw(var_type.into());
1724        let name = name.to_cstr();
1725        unsafe {
1726            BNCreateUserVariable(
1727                self.handle,
1728                &raw_var,
1729                &mut owned_raw_var_ty,
1730                name.as_ref().as_ptr() as *const _,
1731                ignore_disjoint_uses,
1732            )
1733        }
1734    }
1735
1736    pub fn delete_user_var(&self, var: &Variable) {
1737        let raw_var = BNVariable::from(var);
1738        unsafe { BNDeleteUserVariable(self.handle, &raw_var) }
1739    }
1740
1741    pub fn is_var_user_defined(&self, var: &Variable) -> bool {
1742        let raw_var = BNVariable::from(var);
1743        unsafe { BNIsVariableUserDefined(self.handle, &raw_var) }
1744    }
1745
1746    pub fn create_auto_stack_var<'a, T: Into<Conf<&'a Type>>>(
1747        &self,
1748        offset: i64,
1749        var_type: T,
1750        name: &str,
1751    ) {
1752        let mut owned_raw_var_ty = Conf::<&Type>::into_raw(var_type.into());
1753        let name = name.to_cstr();
1754        unsafe {
1755            BNCreateAutoStackVariable(self.handle, offset, &mut owned_raw_var_ty, name.as_ptr())
1756        }
1757    }
1758
1759    pub fn delete_auto_stack_var(&self, offset: i64) {
1760        unsafe { BNDeleteAutoStackVariable(self.handle, offset) }
1761    }
1762
1763    pub fn create_auto_var<'a, C: Into<Conf<&'a Type>>>(
1764        &self,
1765        var: &Variable,
1766        var_type: C,
1767        name: &str,
1768        ignore_disjoint_uses: bool,
1769    ) {
1770        let raw_var = BNVariable::from(var);
1771        let mut owned_raw_var_ty = Conf::<&Type>::into_raw(var_type.into());
1772        let name = name.to_cstr();
1773        unsafe {
1774            BNCreateAutoVariable(
1775                self.handle,
1776                &raw_var,
1777                &mut owned_raw_var_ty,
1778                name.as_ptr(),
1779                ignore_disjoint_uses,
1780            )
1781        }
1782    }
1783
1784    /// return the address, if any, of the instruction that contains the
1785    /// provided address
1786    pub fn instruction_containing_address(
1787        &self,
1788        addr: u64,
1789        arch: Option<CoreArchitecture>,
1790    ) -> Option<u64> {
1791        let arch = arch.unwrap_or_else(|| self.arch());
1792        let mut start = 0;
1793        unsafe { BNGetInstructionContainingAddress(self.handle, arch.handle, addr, &mut start) }
1794            .then_some(start)
1795    }
1796
1797    /// Get the current text display type for an integer token in the disassembly or IL views
1798    ///
1799    /// See also see [Function::int_display_type_and_typeid]
1800    ///
1801    /// * `instr_addr`  - Address of the instruction or IL line containing the token
1802    /// * `value` - field of the InstructionTextToken object for the token, usually the constant displayed
1803    /// * `operand` - Operand index of the token, defined as the number of OperandSeparatorTokens in the disassembly line before the token
1804    /// * `arch` - (optional) Architecture of the instruction or IL line containing the token
1805    pub fn int_display_type(
1806        &self,
1807        instr_addr: u64,
1808        value: u64,
1809        operand: usize,
1810        arch: Option<CoreArchitecture>,
1811    ) -> IntegerDisplayType {
1812        let arch = arch.unwrap_or_else(|| self.arch());
1813        unsafe {
1814            BNGetIntegerConstantDisplayType(self.handle, arch.handle, instr_addr, value, operand)
1815        }
1816    }
1817
1818    /// Change the text display type for an integer token in the disassembly or IL views
1819    ///
1820    /// * `instr_addr` - Address of the instruction or IL line containing the token
1821    /// * `value` - Field of the InstructionTextToken object for the token, usually the constant displayed
1822    /// * `operand` - Operand index of the token, defined as the number of OperandSeparatorTokens in the disassembly line before the token
1823    /// * `display_type` - Desired display type
1824    /// * `arch` - (optional) Architecture of the instruction or IL line containing the token
1825    /// * `enum_display_typeid` - (optional) Whenever passing EnumDisplayType to `display_type`, passing a type ID here will specify the Enumeration display type. Must be a valid type ID and resolve to an enumeration type.
1826    pub fn set_int_display_type(
1827        &self,
1828        instr_addr: u64,
1829        value: u64,
1830        operand: usize,
1831        display_type: IntegerDisplayType,
1832        arch: Option<CoreArchitecture>,
1833        enum_display_typeid: Option<&str>,
1834    ) {
1835        let arch = arch.unwrap_or_else(|| self.arch());
1836        let enum_display_typeid = enum_display_typeid.map(IntoCStr::to_cstr);
1837        let enum_display_typeid_ptr = enum_display_typeid
1838            .map(|x| x.as_ptr())
1839            .unwrap_or(std::ptr::null());
1840        unsafe {
1841            BNSetIntegerConstantDisplayType(
1842                self.handle,
1843                arch.handle,
1844                instr_addr,
1845                value,
1846                operand,
1847                display_type,
1848                enum_display_typeid_ptr,
1849            )
1850        }
1851    }
1852
1853    /// Get the current text display enum type for an integer token in the disassembly or IL views.
1854    ///
1855    /// See also see [Function::int_display_type_and_typeid]
1856    ///
1857    /// * `instr_addr` - Address of the instruction or IL line containing the token
1858    /// * `value` - field of the InstructionTextToken object for the token, usually the constant displayed
1859    /// * `operand` - Operand index of the token, defined as the number of OperandSeparatorTokens in the disassembly line before the token
1860    /// * `arch` - (optional) Architecture of the instruction or IL line containing the token
1861    pub fn int_enum_display_typeid(
1862        &self,
1863        instr_addr: u64,
1864        value: u64,
1865        operand: usize,
1866        arch: Option<CoreArchitecture>,
1867    ) -> String {
1868        let arch = arch.unwrap_or_else(|| self.arch());
1869        unsafe {
1870            BnString::into_string(BNGetIntegerConstantDisplayTypeEnumerationType(
1871                self.handle,
1872                arch.handle,
1873                instr_addr,
1874                value,
1875                operand,
1876            ))
1877        }
1878    }
1879
1880    /// Get the current text display type for an integer token in the disassembly or IL views
1881    ///
1882    /// * `instr_addr` - Address of the instruction or IL line containing the token
1883    /// * `value` - field of the InstructionTextToken object for the token, usually the constant displayed
1884    /// * `operand` - Operand index of the token, defined as the number of OperandSeparatorTokens in the disassembly line before the token
1885    /// * `arch` - (optional) Architecture of the instruction or IL line containing the token
1886    pub fn int_display_type_and_typeid(
1887        &self,
1888        instr_addr: u64,
1889        value: u64,
1890        operand: usize,
1891        arch: Option<CoreArchitecture>,
1892    ) -> (IntegerDisplayType, String) {
1893        let arch = arch.unwrap_or_else(|| self.arch());
1894        let name = self.int_enum_display_typeid(instr_addr, value, operand, Some(arch));
1895        let display = self.int_display_type(instr_addr, value, operand, Some(arch));
1896        (display, name)
1897    }
1898
1899    /// Get the value the provided string register address corresponding to the given virtual address
1900    ///
1901    /// * `addr` - virtual address of the instruction to query
1902    /// * `reg` - string value of native register to query
1903    /// * `arch` - (optional) Architecture for the given function
1904    ///
1905    /// # Example
1906    /// ```no_run
1907    /// # use binaryninja::architecture::{ArchitectureExt, Register};
1908    /// # let fun: binaryninja::function::Function = todo!();
1909    /// let reg = fun.arch().register_by_name("rdi").unwrap();
1910    /// let value = fun.register_value_at(0x400dbe, reg.id(), None);
1911    /// ```
1912    pub fn register_value_at(
1913        &self,
1914        addr: u64,
1915        reg: RegisterId,
1916        arch: Option<CoreArchitecture>,
1917    ) -> RegisterValue {
1918        let arch = arch.unwrap_or_else(|| self.arch());
1919        let register =
1920            unsafe { BNGetRegisterValueAtInstruction(self.handle, arch.handle, addr, reg.0) };
1921        register.into()
1922    }
1923
1924    /// Gets the value instruction address corresponding to the given virtual address
1925    ///
1926    /// * `addr` - virtual address of the instruction to query
1927    /// * `reg` - string value of native register to query
1928    /// * `arch` - (optional) Architecture for the given function
1929    ///
1930    /// # Example
1931    /// ```no_run
1932    /// # use binaryninja::architecture::{ArchitectureExt, Register};
1933    /// # let fun: binaryninja::function::Function = todo!();
1934    /// let reg = fun.arch().register_by_name("rdi").unwrap();
1935    /// let value = fun.register_value_after(0x400dbe, reg.id(), None);
1936    /// ```
1937    pub fn register_value_after(
1938        &self,
1939        addr: u64,
1940        reg: RegisterId,
1941        arch: Option<CoreArchitecture>,
1942    ) -> RegisterValue {
1943        let arch = arch.unwrap_or_else(|| self.arch());
1944        let register =
1945            unsafe { BNGetRegisterValueAfterInstruction(self.handle, arch.handle, addr, reg.0) };
1946        register.into()
1947    }
1948
1949    pub fn register_value_at_exit(&self, reg: u32) -> Conf<RegisterValue> {
1950        let register = unsafe { BNGetFunctionRegisterValueAtExit(self.handle, reg) };
1951        Conf::new(register.value.into(), register.confidence)
1952    }
1953
1954    pub fn registers_read_by(
1955        &self,
1956        addr: u64,
1957        arch: Option<CoreArchitecture>,
1958    ) -> Array<CoreRegister> {
1959        let arch = arch.unwrap_or_else(|| self.arch());
1960        let mut count = 0;
1961        let regs =
1962            unsafe { BNGetRegistersReadByInstruction(self.handle, arch.handle, addr, &mut count) };
1963        assert!(!regs.is_null());
1964        unsafe { Array::new(regs, count, arch) }
1965    }
1966
1967    pub fn registers_written_by(
1968        &self,
1969        addr: u64,
1970        arch: Option<CoreArchitecture>,
1971    ) -> Array<CoreRegister> {
1972        let arch = arch.unwrap_or_else(|| self.arch());
1973        let mut count = 0;
1974        let regs = unsafe {
1975            BNGetRegistersWrittenByInstruction(self.handle, arch.handle, addr, &mut count)
1976        };
1977        assert!(!regs.is_null());
1978        unsafe { Array::new(regs, count, arch) }
1979    }
1980
1981    /// Registers that are modified by this function
1982    pub fn clobbered_registers(&self) -> Conf<Array<CoreRegister>> {
1983        let result = unsafe { BNGetFunctionClobberedRegisters(self.handle) };
1984
1985        let reg_set = unsafe { Array::new(result.regs, result.count, self.arch().handle()) };
1986        Conf::new(reg_set, result.confidence)
1987    }
1988
1989    pub fn set_user_clobbered_registers<I>(&self, registers: I, confidence: u8)
1990    where
1991        I: IntoIterator<Item = CoreRegister>,
1992    {
1993        let mut regs: Box<[u32]> = registers.into_iter().map(|reg| reg.id().0).collect();
1994        let mut regs = BNRegisterSetWithConfidence {
1995            regs: regs.as_mut_ptr(),
1996            count: regs.len(),
1997            confidence,
1998        };
1999        unsafe { BNSetUserFunctionClobberedRegisters(self.handle, &mut regs) }
2000    }
2001
2002    pub fn set_auto_clobbered_registers<I>(&self, registers: I, confidence: u8)
2003    where
2004        I: IntoIterator<Item = CoreRegister>,
2005    {
2006        let mut regs: Box<[u32]> = registers.into_iter().map(|reg| reg.id().0).collect();
2007        let mut regs = BNRegisterSetWithConfidence {
2008            regs: regs.as_mut_ptr(),
2009            count: regs.len(),
2010            confidence,
2011        };
2012        unsafe { BNSetAutoFunctionClobberedRegisters(self.handle, &mut regs) }
2013    }
2014
2015    pub fn stack_contents_at(
2016        &self,
2017        addr: u64,
2018        offset: i64,
2019        size: usize,
2020        arch: Option<CoreArchitecture>,
2021    ) -> RegisterValue {
2022        let arch = arch.unwrap_or_else(|| self.arch());
2023        let value = unsafe {
2024            BNGetStackContentsAtInstruction(self.handle, arch.handle, addr, offset, size)
2025        };
2026        value.into()
2027    }
2028
2029    pub fn stack_contents_after(
2030        &self,
2031        addr: u64,
2032        offset: i64,
2033        size: usize,
2034        arch: Option<CoreArchitecture>,
2035    ) -> RegisterValue {
2036        let arch = arch.unwrap_or_else(|| self.arch());
2037        let value = unsafe {
2038            BNGetStackContentsAfterInstruction(self.handle, arch.handle, addr, offset, size)
2039        };
2040        value.into()
2041    }
2042
2043    pub fn stack_var_at_frame_offset(
2044        &self,
2045        addr: u64,
2046        offset: i64,
2047        arch: Option<CoreArchitecture>,
2048    ) -> Option<NamedVariableWithType> {
2049        let arch = arch.unwrap_or_else(|| self.arch());
2050        let mut found_value = BNVariableNameAndType::default();
2051        let found = unsafe {
2052            BNGetStackVariableAtFrameOffset(
2053                self.handle,
2054                arch.handle,
2055                addr,
2056                offset,
2057                &mut found_value,
2058            )
2059        };
2060        if !found {
2061            return None;
2062        }
2063        Some(NamedVariableWithType::from_owned_raw(found_value))
2064    }
2065
2066    pub fn stack_var_at_frame_offset_after_instruction(
2067        &self,
2068        addr: u64,
2069        offset: i64,
2070        arch: Option<CoreArchitecture>,
2071    ) -> Option<NamedVariableWithType> {
2072        let arch = arch.unwrap_or_else(|| self.arch());
2073        let mut found_value = BNVariableNameAndType::default();
2074        let found = unsafe {
2075            BNGetStackVariableAtFrameOffsetAfterInstruction(
2076                self.handle,
2077                arch.handle,
2078                addr,
2079                offset,
2080                &mut found_value,
2081            )
2082        };
2083        if !found {
2084            return None;
2085        }
2086        Some(NamedVariableWithType::from_owned_raw(found_value))
2087    }
2088
2089    pub fn stack_variables_referenced_by(
2090        &self,
2091        addr: u64,
2092        arch: Option<CoreArchitecture>,
2093    ) -> Array<StackVariableReference> {
2094        let arch = arch.unwrap_or_else(|| self.arch());
2095        let mut count = 0;
2096        let refs = unsafe {
2097            BNGetStackVariablesReferencedByInstruction(self.handle, arch.handle, addr, &mut count)
2098        };
2099        assert!(!refs.is_null());
2100        unsafe { Array::new(refs, count, ()) }
2101    }
2102
2103    pub fn stack_variables_referenced_by_address_if_available(
2104        &self,
2105        addr: u64,
2106        arch: Option<CoreArchitecture>,
2107    ) -> Array<StackVariableReference> {
2108        let arch = arch.unwrap_or_else(|| self.arch());
2109        let mut count = 0;
2110        let refs = unsafe {
2111            BNGetStackVariablesReferencedByInstructionIfAvailable(
2112                self.handle,
2113                arch.handle,
2114                addr,
2115                &mut count,
2116            )
2117        };
2118        assert!(!refs.is_null());
2119        unsafe { Array::new(refs, count, ()) }
2120    }
2121
2122    /// Discovered value of the global pointer register, if the function uses one
2123    pub fn global_pointer_value(&self) -> Conf<RegisterValue> {
2124        let result = unsafe { BNGetFunctionGlobalPointerValue(self.handle) };
2125        Conf::new(result.value.into(), result.confidence)
2126    }
2127
2128    pub fn type_tokens(
2129        &self,
2130        settings: Option<&DisassemblySettings>,
2131    ) -> Array<DisassemblyTextLine> {
2132        let settings = settings.map(|s| s.handle).unwrap_or(std::ptr::null_mut());
2133        let mut count = 0;
2134        let lines = unsafe { BNGetFunctionTypeTokens(self.handle, settings, &mut count) };
2135        assert!(!lines.is_null());
2136        unsafe { Array::new(lines, count, ()) }
2137    }
2138
2139    pub fn is_call_instruction(&self, addr: u64, arch: Option<CoreArchitecture>) -> bool {
2140        let arch = arch.unwrap_or_else(|| self.arch());
2141        unsafe { BNIsCallInstruction(self.handle, arch.handle, addr) }
2142    }
2143
2144    pub fn is_variable_user_defined(&self, var: &Variable) -> bool {
2145        let raw_var = BNVariable::from(var);
2146        unsafe { BNIsVariableUserDefined(self.handle, &raw_var) }
2147    }
2148
2149    pub fn is_pure(&self) -> Conf<bool> {
2150        unsafe { BNIsFunctionPure(self.handle) }.into()
2151    }
2152
2153    pub fn set_user_pure<C>(&self, value: C)
2154    where
2155        C: Into<Conf<bool>>,
2156    {
2157        let value: Conf<bool> = value.into();
2158        let mut value_raw = value.into();
2159        unsafe { BNSetUserFunctionPure(self.handle, &mut value_raw) };
2160    }
2161
2162    pub fn set_auto_pure<C>(&self, value: C)
2163    where
2164        C: Into<Conf<bool>>,
2165    {
2166        let value: Conf<bool> = value.into();
2167        let mut value_raw = value.into();
2168        unsafe { BNSetAutoFunctionPure(self.handle, &mut value_raw) };
2169    }
2170
2171    pub fn is_too_large(&self) -> bool {
2172        unsafe { BNIsFunctionTooLarge(self.handle) }
2173    }
2174
2175    pub fn is_update_needed(&self) -> bool {
2176        unsafe { BNIsFunctionUpdateNeeded(self.handle) }
2177    }
2178
2179    /// Indicates that this function needs to be reanalyzed during the next update cycle
2180    ///
2181    /// * `update_type` - Desired update type
2182    pub fn mark_updates_required(&self, update_type: FunctionUpdateType) {
2183        unsafe { BNMarkUpdatesRequired(self.handle, update_type) }
2184    }
2185
2186    /// Indicates that callers of this function need to be reanalyzed during the next update cycle
2187    ///
2188    /// * `update_type` - Desired update type
2189    pub fn mark_caller_updates_required(&self, update_type: FunctionUpdateType) {
2190        unsafe { BNMarkCallerUpdatesRequired(self.handle, update_type) }
2191    }
2192
2193    pub fn mark_recent_use(&self) {
2194        unsafe { BNMarkFunctionAsRecentlyUsed(self.handle) }
2195    }
2196
2197    // Gets the list of merged variables
2198    pub fn merged_variables(&self) -> Array<MergedVariable> {
2199        let mut count = 0;
2200        let vars = unsafe { BNGetMergedVariables(self.handle, &mut count) };
2201        assert!(!vars.is_null());
2202        unsafe { Array::new(vars, count, ()) }
2203    }
2204
2205    /// Merge one or more variables in `sources` into the `target` variable. All
2206    /// variable accesses to the variables in `sources` will be rewritten to use `target`.
2207    ///
2208    /// * `target` - target variable
2209    /// * `sources` - list of source variables
2210    pub fn merge_variables<'a>(
2211        &self,
2212        target: &Variable,
2213        sources: impl IntoIterator<Item = &'a Variable>,
2214    ) {
2215        let raw_target_var = BNVariable::from(target);
2216        let sources_raw: Vec<BNVariable> = sources.into_iter().copied().map(Into::into).collect();
2217        unsafe {
2218            BNMergeVariables(
2219                self.handle,
2220                &raw_target_var,
2221                sources_raw.as_ptr(),
2222                sources_raw.len(),
2223            )
2224        }
2225    }
2226
2227    /// Undoes variable merging performed with [Function::merge_variables]. The variables in
2228    /// `sources` will no longer be merged into the `target` variable.
2229    ///
2230    /// * `target` - target variable
2231    /// * `sources` - list of source variables
2232    pub fn unmerge_variables<'a>(
2233        &self,
2234        target: &Variable,
2235        sources: impl IntoIterator<Item = &'a Variable>,
2236    ) {
2237        let raw_target_var = BNVariable::from(target);
2238        let sources_raw: Vec<BNVariable> = sources.into_iter().copied().map(Into::into).collect();
2239        unsafe {
2240            BNUnmergeVariables(
2241                self.handle,
2242                &raw_target_var,
2243                sources_raw.as_ptr(),
2244                sources_raw.len(),
2245            )
2246        }
2247    }
2248
2249    /// Splits a variable at the definition site. The given `var` must be the
2250    /// variable unique to the definition and should be obtained by using
2251    /// [crate::medium_level_il::MediumLevelILInstruction::split_var_for_definition] at the definition site.
2252    ///
2253    /// This function is not meant to split variables that have been previously merged. Use
2254    /// [Function::unmerge_variables] to split previously merged variables.
2255    ///
2256    /// <div class="warning">
2257    ///
2258    /// Binary Ninja automatically splits all variables that the analysis determines
2259    /// to be safely splittable. Splitting a variable manually with [Function::split_variable] can cause
2260    /// IL and decompilation to be incorrect. There are some patterns where variables can be safely
2261    /// split semantically but analysis cannot determine that it is safe. This function is provided
2262    /// to allow variable splitting to be performed in these cases by plugins or by the user.
2263    ///
2264    /// </div>
2265    ///
2266    /// * `var` - variable to split
2267    pub fn split_variable(&self, var: &Variable) {
2268        let raw_var = BNVariable::from(var);
2269        unsafe { BNSplitVariable(self.handle, &raw_var) }
2270    }
2271
2272    /// Undoes variable splitting performed with [Function::split_variable]. The given `var`
2273    /// must be the variable unique to the definition and should be obtained by using
2274    /// [crate::medium_level_il::MediumLevelILInstruction::split_var_for_definition] at the definition site.
2275    ///
2276    /// * `var` - variable to unsplit
2277    pub fn unsplit_variable(&self, var: &Variable) {
2278        let raw_var = BNVariable::from(var);
2279        unsafe { BNUnsplitVariable(self.handle, &raw_var) }
2280    }
2281
2282    /// Causes this function to be analyzed if it's out of date. This function does not wait for the analysis to finish.
2283    pub fn analyze(&self) {
2284        unsafe { BNAnalyzeFunction(self.handle) }
2285    }
2286
2287    /// Causes this function to be reanalyzed. This function does not wait for the analysis to finish.
2288    ///
2289    /// * `update_type` - Desired update type
2290    ///
2291    /// <div class="warning">
2292    ///
2293    /// If analysis_skipped is `true`, using this API will not trigger
2294    /// re-analysis. Instead, use [Function::set_analysis_skipped] with `false`.
2295    ///
2296    /// </div>
2297    pub fn reanalyze(&self, update_type: FunctionUpdateType) {
2298        unsafe { BNReanalyzeFunction(self.handle, update_type) }
2299    }
2300
2301    /// Generate internal debug reports for a variety of analysis.
2302    /// Current list of possible values include:
2303    ///
2304    /// - mlil_translator
2305    /// - stack_adjust_graph
2306    /// - high_level_il
2307    ///
2308    /// * `name` - Name of the debug report
2309    pub fn request_debug_report(&self, name: &str) {
2310        const DEBUG_REPORT_ALIAS: &[(&str, &CStr)] = &[
2311            ("stack", c"stack_adjust_graph"),
2312            ("mlil", c"mlil_translator"),
2313            ("hlil", c"high_level_il"),
2314        ];
2315
2316        if let Some(alias_idx) = DEBUG_REPORT_ALIAS
2317            .iter()
2318            .position(|(alias, _value)| *alias == name)
2319        {
2320            let name = DEBUG_REPORT_ALIAS[alias_idx].1.as_ptr();
2321            unsafe { BNRequestFunctionDebugReport(self.handle, name) }
2322        } else {
2323            let name = std::ffi::CString::new(name.to_string()).unwrap();
2324            unsafe { BNRequestFunctionDebugReport(self.handle, name.as_ptr()) }
2325        }
2326
2327        self.view().update_analysis()
2328    }
2329
2330    ///Checks if a function has had a debug report requested with the given name, and then,
2331    /// if one has been requested, clears the request internally so that future calls
2332    /// to this function for that report will return False.
2333    ///
2334    /// If a function has had a debug report requested, it is the caller of this function's
2335    /// responsibility to actually generate and show the debug report.
2336    /// You can use [crate::interaction::report::ReportCollection::show]
2337    /// for showing a debug report from a workflow activity.
2338    pub fn check_for_debug_report(&self, name: &str) -> bool {
2339        let name = std::ffi::CString::new(name.to_string()).unwrap();
2340        unsafe { BNFunctionCheckForDebugReport(self.handle, name.as_ptr()) }
2341    }
2342
2343    /// Whether function was automatically discovered s a result of some creation of a 'user' function.
2344    /// 'user' functions may or may not have been created by a user through the or API. For instance the entry point
2345    /// into a function is always created a 'user' function. 'user' functions should be considered the root of auto
2346    /// analysis.
2347    pub fn is_auto(&self) -> bool {
2348        unsafe { BNWasFunctionAutomaticallyDiscovered(self.handle) }
2349    }
2350
2351    /// Returns a list of possible call sites contained in this function.
2352    /// This includes ordinary calls, tail calls, and indirect jumps. Not all of
2353    /// the returned call sites are necessarily true call sites; some may simply
2354    /// be unresolved indirect jumps, for example.
2355    pub fn call_sites(&self) -> Array<CodeReference> {
2356        let mut count = 0;
2357        let refs = unsafe { BNGetFunctionCallSites(self.handle, &mut count) };
2358        assert!(!refs.is_null());
2359        unsafe { Array::new(refs, count, ()) }
2360    }
2361
2362    /// Returns a list of ReferenceSource objects corresponding to the addresses
2363    /// in functions which reference this function
2364    pub fn caller_sites(&self) -> Array<CodeReference> {
2365        self.view().code_refs_to_addr(self.start())
2366    }
2367
2368    /// Calling convention used by the function
2369    pub fn calling_convention(&self) -> Option<Conf<Ref<CoreCallingConvention>>> {
2370        let result = unsafe { BNGetFunctionCallingConvention(self.handle) };
2371        (!result.convention.is_null()).then(|| {
2372            Conf::new(
2373                unsafe { CoreCallingConvention::ref_from_raw(result.convention, self.arch()) },
2374                result.confidence,
2375            )
2376        })
2377    }
2378
2379    /// Set the User calling convention used by the function
2380    pub fn set_user_calling_convention<'a, I>(&self, value: Option<I>)
2381    where
2382        I: Into<Conf<&'a CoreCallingConvention>>,
2383    {
2384        let mut conv_conf = BNCallingConventionWithConfidence::default();
2385        if let Some(value) = value {
2386            let value = value.into();
2387            conv_conf.convention = value.contents.handle;
2388            conv_conf.confidence = value.confidence;
2389        }
2390        unsafe { BNSetUserFunctionCallingConvention(self.handle, &mut conv_conf) }
2391    }
2392
2393    /// Set the calling convention used by the function
2394    pub fn set_auto_calling_convention<'a, I>(&self, value: Option<I>)
2395    where
2396        I: Into<Conf<&'a CoreCallingConvention>>,
2397    {
2398        let mut conv_conf = BNCallingConventionWithConfidence::default();
2399        if let Some(value) = value {
2400            let value = value.into();
2401            conv_conf.convention = value.contents.handle;
2402            conv_conf.confidence = value.confidence;
2403        }
2404        unsafe { BNSetAutoFunctionCallingConvention(self.handle, &mut conv_conf) }
2405    }
2406
2407    pub fn can_return(&self) -> Conf<bool> {
2408        unsafe { BNCanFunctionReturn(self.handle) }.into()
2409    }
2410
2411    pub fn set_user_can_return<I>(&self, value: I)
2412    where
2413        I: Into<Conf<bool>>,
2414    {
2415        let value: Conf<bool> = value.into();
2416        let mut value_raw: BNBoolWithConfidence = value.into();
2417        unsafe { BNSetUserFunctionCanReturn(self.handle, &mut value_raw) }
2418    }
2419
2420    pub fn set_auto_can_return<I>(&self, value: I)
2421    where
2422        I: Into<Conf<bool>>,
2423    {
2424        let value: Conf<bool> = value.into();
2425        let mut value_raw: BNBoolWithConfidence = value.into();
2426        unsafe { BNSetAutoFunctionCanReturn(self.handle, &mut value_raw) }
2427    }
2428
2429    /// Whether the function type was defined with [`Function::apply_auto_discovered_type`].
2430    ///
2431    /// NOTE: This is different from [`Function::has_user_type`].
2432    pub fn has_explicitly_defined_type(&self) -> bool {
2433        unsafe { BNFunctionHasExplicitlyDefinedType(self.handle) }
2434    }
2435
2436    pub fn has_user_annotations(&self) -> bool {
2437        unsafe { BNFunctionHasUserAnnotations(self.handle) }
2438    }
2439
2440    pub fn has_variable_arguments(&self) -> Conf<bool> {
2441        unsafe { BNFunctionHasVariableArguments(self.handle) }.into()
2442    }
2443
2444    pub fn set_user_has_variable_arguments<I>(&self, value: I)
2445    where
2446        I: Into<Conf<bool>>,
2447    {
2448        let bc: Conf<bool> = value.into();
2449        let mut bc = bc.into();
2450        unsafe { BNSetUserFunctionHasVariableArguments(self.handle, &mut bc) }
2451    }
2452
2453    pub fn set_auto_has_variable_arguments<I>(&self, value: I)
2454    where
2455        I: Into<Conf<bool>>,
2456    {
2457        let bc: Conf<bool> = value.into();
2458        let mut bc = bc.into();
2459        unsafe { BNSetAutoFunctionHasVariableArguments(self.handle, &mut bc) }
2460    }
2461
2462    /// Has unresolved indirect branches
2463    pub fn has_unresolved_indirect_branches(&self) -> bool {
2464        unsafe { BNHasUnresolvedIndirectBranches(self.handle) }
2465    }
2466
2467    /*
2468    /// List of address of unresolved indirect branches
2469    pub fn unresolved_indirect_branches(&self) -> Array<Arch> {
2470        let mut count = 0;
2471        let result = unsafe { BNGetUnresolvedIndirectBranches(self.handle, &mut count) };
2472        unsafe { Array::new(result, count, ()) }
2473    }
2474    */
2475
2476    /// Returns a string representing the provenance. This portion of the API
2477    /// is under development. Currently the provenance information is
2478    /// undocumented, not persistent, and not saved to a database.
2479    pub fn provenance(&self) -> String {
2480        unsafe { BnString::into_string(BNGetProvenanceString(self.handle)) }
2481    }
2482
2483    /// Get registers that are used for the return value
2484    pub fn return_registers(&self) -> Conf<Array<CoreRegister>> {
2485        let result = unsafe { BNGetFunctionReturnRegisters(self.handle) };
2486        let regs = unsafe { Array::new(result.regs, result.count, self.arch().handle()) };
2487        Conf::new(regs, result.confidence)
2488    }
2489
2490    pub fn set_user_return_registers<I>(&self, values: I, confidence: u8)
2491    where
2492        I: IntoIterator<Item = CoreRegister>,
2493    {
2494        let mut regs: Box<[u32]> = values.into_iter().map(|reg| reg.id().0).collect();
2495        let mut regs = BNRegisterSetWithConfidence {
2496            regs: regs.as_mut_ptr(),
2497            count: regs.len(),
2498            confidence,
2499        };
2500        unsafe { BNSetUserFunctionReturnRegisters(self.handle, &mut regs) }
2501    }
2502
2503    pub fn set_auto_return_registers<I>(&self, values: I, confidence: u8)
2504    where
2505        I: IntoIterator<Item = CoreRegister>,
2506    {
2507        let mut regs: Box<[u32]> = values.into_iter().map(|reg| reg.id().0).collect();
2508        let mut regs = BNRegisterSetWithConfidence {
2509            regs: regs.as_mut_ptr(),
2510            count: regs.len(),
2511            confidence,
2512        };
2513        unsafe { BNSetAutoFunctionReturnRegisters(self.handle, &mut regs) }
2514    }
2515
2516    /// Flow graph of unresolved stack adjustments
2517    pub fn unresolved_stack_adjustment_graph(&self) -> Option<Ref<FlowGraph>> {
2518        let graph = unsafe { BNGetUnresolvedStackAdjustmentGraph(self.handle) };
2519        (!graph.is_null()).then(|| unsafe { FlowGraph::ref_from_raw(graph) })
2520    }
2521
2522    pub fn create_graph(
2523        &self,
2524        view_type: FunctionViewType,
2525        settings: Option<&DisassemblySettings>,
2526    ) -> Ref<FlowGraph> {
2527        let settings_raw = settings.map(|s| s.handle).unwrap_or(std::ptr::null_mut());
2528        let raw_view_type = FunctionViewType::into_raw(view_type);
2529        let result = unsafe { BNCreateFunctionGraph(self.handle, raw_view_type, settings_raw) };
2530        FunctionViewType::free_raw(raw_view_type);
2531        unsafe { FlowGraph::ref_from_raw(result) }
2532    }
2533
2534    pub fn create_graph_immediate(
2535        &self,
2536        view_type: FunctionViewType,
2537        settings: Option<&DisassemblySettings>,
2538    ) -> Ref<FlowGraph> {
2539        let settings_raw = settings.map(|s| s.handle).unwrap_or(std::ptr::null_mut());
2540        let raw_view_type = FunctionViewType::into_raw(view_type);
2541        let result =
2542            unsafe { BNCreateImmediateFunctionGraph(self.handle, raw_view_type, settings_raw) };
2543        FunctionViewType::free_raw(raw_view_type);
2544        unsafe { FlowGraph::ref_from_raw(result) }
2545    }
2546
2547    pub fn parent_components(&self) -> Array<Component> {
2548        let mut count = 0;
2549        let result =
2550            unsafe { BNGetFunctionParentComponents(self.view().handle, self.handle, &mut count) };
2551        assert!(!result.is_null());
2552        unsafe { Array::new(result, count, ()) }
2553    }
2554
2555    pub fn query_metadata(&self, key: &str) -> Option<Ref<Metadata>> {
2556        let key = key.to_cstr();
2557        let value: *mut BNMetadata = unsafe { BNFunctionQueryMetadata(self.handle, key.as_ptr()) };
2558        if value.is_null() {
2559            None
2560        } else {
2561            Some(unsafe { Metadata::ref_from_raw(value) })
2562        }
2563    }
2564
2565    pub fn get_metadata(&self) -> Option<Ref<Metadata>> {
2566        let value: *mut BNMetadata = unsafe { BNFunctionGetMetadata(self.handle) };
2567        if value.is_null() {
2568            None
2569        } else {
2570            Some(unsafe { Metadata::ref_from_raw(value) })
2571        }
2572    }
2573
2574    pub fn get_auto_metadata(&self) -> Option<Ref<Metadata>> {
2575        let value: *mut BNMetadata = unsafe { BNFunctionGetAutoMetadata(self.handle) };
2576        if value.is_null() {
2577            None
2578        } else {
2579            Some(unsafe { Metadata::ref_from_raw(value) })
2580        }
2581    }
2582
2583    pub fn store_metadata<V>(&self, key: &str, value: V, is_auto: bool)
2584    where
2585        V: Into<Ref<Metadata>>,
2586    {
2587        let md = value.into();
2588        let key = key.to_cstr();
2589        unsafe { BNFunctionStoreMetadata(self.handle, key.as_ptr(), md.as_ref().handle, is_auto) };
2590    }
2591
2592    pub fn remove_metadata(&self, key: &str) {
2593        let key = key.to_cstr();
2594        unsafe { BNFunctionRemoveMetadata(self.handle, key.as_ptr()) };
2595    }
2596
2597    pub fn guided_source_blocks(&self) -> HashSet<ArchAndAddr> {
2598        let mut count = 0;
2599        let raw = unsafe { BNGetGuidedSourceBlocks(self.handle, &mut count) };
2600        if raw.is_null() || count == 0 {
2601            return HashSet::new();
2602        }
2603
2604        (0..count)
2605            .map(|i| {
2606                let raw = unsafe { std::ptr::read(raw.add(i)) };
2607                ArchAndAddr::from(raw)
2608            })
2609            .collect::<HashSet<_>>()
2610    }
2611}
2612
2613impl Debug for Function {
2614    fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
2615        // TODO: I am sure there is more we should add to this.
2616        f.debug_struct("Function")
2617            .field("start", &self.start())
2618            .field("arch", &self.arch().name())
2619            .field("platform", &self.platform())
2620            .field("symbol", &self.symbol())
2621            .field("is_auto", &self.is_auto())
2622            .field("tags", &self.tags().to_vec())
2623            .field("comments", &self.comments().to_vec())
2624            .finish()
2625    }
2626}
2627
2628unsafe impl Send for Function {}
2629unsafe impl Sync for Function {}
2630
2631impl ToOwned for Function {
2632    type Owned = Ref<Self>;
2633
2634    fn to_owned(&self) -> Self::Owned {
2635        unsafe { RefCountable::inc_ref(self) }
2636    }
2637}
2638
2639unsafe impl RefCountable for Function {
2640    unsafe fn inc_ref(handle: &Self) -> Ref<Self> {
2641        Ref::new(Self {
2642            handle: BNNewFunctionReference(handle.handle),
2643        })
2644    }
2645
2646    unsafe fn dec_ref(handle: &Self) {
2647        BNFreeFunction(handle.handle);
2648    }
2649}
2650
2651impl CoreArrayProvider for Function {
2652    type Raw = *mut BNFunction;
2653    type Context = ();
2654    type Wrapped<'a> = Guard<'a, Function>;
2655}
2656
2657unsafe impl CoreArrayProviderInner for Function {
2658    unsafe fn free(raw: *mut Self::Raw, count: usize, _context: &Self::Context) {
2659        BNFreeFunctionList(raw, count);
2660    }
2661
2662    unsafe fn wrap_raw<'a>(raw: &'a Self::Raw, context: &'a Self::Context) -> Self::Wrapped<'a> {
2663        Guard::new(Self::from_raw(*raw), context)
2664    }
2665}
2666
2667impl Hash for Function {
2668    fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
2669        let start_address = self.start();
2670        let architecture = self.arch();
2671        let platform = self.platform();
2672        (start_address, architecture, platform).hash(state)
2673    }
2674}
2675
2676impl PartialEq for Function {
2677    fn eq(&self, other: &Self) -> bool {
2678        if self.handle == other.handle {
2679            return true;
2680        }
2681        self.start() == other.start()
2682            && self.arch() == other.arch()
2683            && self.platform() == other.platform()
2684    }
2685}
2686
2687#[derive(Clone, Debug, Eq, Hash, PartialEq)]
2688pub struct PerformanceInfo {
2689    pub name: String,
2690    pub seconds: Duration,
2691}
2692
2693#[allow(unused)]
2694impl PerformanceInfo {
2695    pub fn new(name: String, seconds: Duration) -> Self {
2696        Self {
2697            name: name.to_string(),
2698            seconds,
2699        }
2700    }
2701
2702    pub(crate) fn from_raw(value: &BNPerformanceInfo) -> Self {
2703        Self {
2704            name: raw_to_string(value.name as *mut _).unwrap(),
2705            seconds: Duration::from_secs_f64(value.seconds),
2706        }
2707    }
2708
2709    pub(crate) fn from_owned_raw(value: BNPerformanceInfo) -> Self {
2710        let owned = Self::from_raw(&value);
2711        Self::free_raw(value);
2712        owned
2713    }
2714
2715    pub(crate) fn into_raw(value: Self) -> BNPerformanceInfo {
2716        let bn_name = BnString::new(value.name);
2717        BNPerformanceInfo {
2718            name: BnString::into_raw(bn_name),
2719            seconds: value.seconds.as_secs_f64(),
2720        }
2721    }
2722
2723    pub(crate) fn free_raw(value: BNPerformanceInfo) {
2724        unsafe { BnString::free_raw(value.name) };
2725    }
2726}
2727
2728impl CoreArrayProvider for PerformanceInfo {
2729    type Raw = BNPerformanceInfo;
2730    type Context = ();
2731    type Wrapped<'a> = Self;
2732}
2733
2734unsafe impl CoreArrayProviderInner for PerformanceInfo {
2735    unsafe fn free(raw: *mut Self::Raw, count: usize, _context: &Self::Context) {
2736        BNFreeAnalysisPerformanceInfo(raw, count);
2737    }
2738
2739    unsafe fn wrap_raw<'a>(raw: &'a Self::Raw, _context: &'a Self::Context) -> Self::Wrapped<'a> {
2740        Self::from_raw(raw)
2741    }
2742}
2743
2744// NOTE: only exists as part of an Array, never owned
2745pub struct UnresolvedIndirectBranches(u64);
2746
2747impl UnresolvedIndirectBranches {
2748    pub fn address(&self) -> u64 {
2749        self.0
2750    }
2751}
2752
2753impl CoreArrayProvider for UnresolvedIndirectBranches {
2754    type Raw = u64;
2755    type Context = ();
2756    type Wrapped<'a> = Self;
2757}
2758
2759unsafe impl CoreArrayProviderInner for UnresolvedIndirectBranches {
2760    unsafe fn free(raw: *mut Self::Raw, _count: usize, _context: &Self::Context) {
2761        BNFreeAddressList(raw)
2762    }
2763
2764    unsafe fn wrap_raw<'a>(raw: &'a Self::Raw, _context: &'a Self::Context) -> Self::Wrapped<'a> {
2765        Self(*raw)
2766    }
2767}
2768
2769#[derive(Clone, Copy, Debug, Hash, Eq, PartialEq)]
2770pub struct ConstantReference {
2771    pub value: i64,
2772    pub size: usize,
2773    pub pointer: bool,
2774    pub intermediate: bool,
2775}
2776
2777impl From<BNConstantReference> for ConstantReference {
2778    fn from(value: BNConstantReference) -> Self {
2779        Self {
2780            value: value.value,
2781            size: value.size,
2782            pointer: value.pointer,
2783            intermediate: value.intermediate,
2784        }
2785    }
2786}
2787
2788impl From<ConstantReference> for BNConstantReference {
2789    fn from(value: ConstantReference) -> Self {
2790        Self {
2791            value: value.value,
2792            size: value.size,
2793            pointer: value.pointer,
2794            intermediate: value.intermediate,
2795        }
2796    }
2797}
2798
2799impl CoreArrayProvider for ConstantReference {
2800    type Raw = BNConstantReference;
2801    type Context = ();
2802    type Wrapped<'a> = Self;
2803}
2804
2805unsafe impl CoreArrayProviderInner for ConstantReference {
2806    unsafe fn free(raw: *mut Self::Raw, _count: usize, _context: &Self::Context) {
2807        BNFreeConstantReferenceList(raw)
2808    }
2809
2810    unsafe fn wrap_raw<'a>(raw: &'a Self::Raw, _context: &'a Self::Context) -> Self::Wrapped<'a> {
2811        Self::from(*raw)
2812    }
2813}
2814
2815#[derive(Debug, Copy, Clone)]
2816pub struct RegisterStackAdjustment {
2817    pub register_id: u32,
2818    pub adjustment: Conf<i32>,
2819}
2820
2821impl RegisterStackAdjustment {
2822    pub fn new(register_id: u32, adjustment: impl Into<Conf<i32>>) -> Self {
2823        Self {
2824            register_id,
2825            adjustment: adjustment.into(),
2826        }
2827    }
2828}
2829
2830impl From<BNRegisterStackAdjustment> for RegisterStackAdjustment {
2831    fn from(value: BNRegisterStackAdjustment) -> Self {
2832        Self {
2833            register_id: value.regStack,
2834            adjustment: Conf::new(value.adjustment, value.confidence),
2835        }
2836    }
2837}
2838
2839impl From<RegisterStackAdjustment> for BNRegisterStackAdjustment {
2840    fn from(value: RegisterStackAdjustment) -> Self {
2841        Self {
2842            regStack: value.register_id,
2843            adjustment: value.adjustment.contents,
2844            confidence: value.adjustment.confidence,
2845        }
2846    }
2847}
2848
2849impl CoreArrayProvider for RegisterStackAdjustment {
2850    type Raw = BNRegisterStackAdjustment;
2851    type Context = ();
2852    type Wrapped<'a> = Self;
2853}
2854
2855unsafe impl CoreArrayProviderInner for RegisterStackAdjustment {
2856    unsafe fn free(raw: *mut Self::Raw, _count: usize, _context: &Self::Context) {
2857        BNFreeRegisterStackAdjustments(raw)
2858    }
2859
2860    unsafe fn wrap_raw<'a>(raw: &'a Self::Raw, _context: &'a Self::Context) -> Self::Wrapped<'a> {
2861        Self::from(*raw)
2862    }
2863}
2864
2865#[derive(Clone, Copy, Debug, Hash, Eq, PartialEq)]
2866pub enum HighlightColor {
2867    StandardHighlightColor {
2868        color: HighlightStandardColor,
2869        alpha: u8,
2870    },
2871    MixedHighlightColor {
2872        color: HighlightStandardColor,
2873        mix_color: HighlightStandardColor,
2874        mix: u8,
2875        alpha: u8,
2876    },
2877    CustomHighlightColor {
2878        r: u8,
2879        g: u8,
2880        b: u8,
2881        alpha: u8,
2882    },
2883}
2884
2885impl From<BNHighlightColor> for HighlightColor {
2886    fn from(value: BNHighlightColor) -> Self {
2887        match value.style {
2888            BNHighlightColorStyle::StandardHighlightColor => Self::StandardHighlightColor {
2889                color: value.color,
2890                alpha: value.alpha,
2891            },
2892            BNHighlightColorStyle::MixedHighlightColor => Self::MixedHighlightColor {
2893                color: value.color,
2894                mix_color: value.mixColor,
2895                mix: value.mix,
2896                alpha: value.alpha,
2897            },
2898            BNHighlightColorStyle::CustomHighlightColor => Self::CustomHighlightColor {
2899                r: value.r,
2900                g: value.g,
2901                b: value.b,
2902                alpha: value.alpha,
2903            },
2904        }
2905    }
2906}
2907
2908impl From<HighlightColor> for BNHighlightColor {
2909    fn from(value: HighlightColor) -> Self {
2910        match value {
2911            HighlightColor::StandardHighlightColor { color, alpha } => BNHighlightColor {
2912                style: BNHighlightColorStyle::StandardHighlightColor,
2913                color,
2914                alpha,
2915                ..Default::default()
2916            },
2917            HighlightColor::MixedHighlightColor {
2918                color,
2919                mix_color,
2920                mix,
2921                alpha,
2922            } => BNHighlightColor {
2923                style: BNHighlightColorStyle::MixedHighlightColor,
2924                color,
2925                mixColor: mix_color,
2926                mix,
2927                alpha,
2928                ..Default::default()
2929            },
2930            HighlightColor::CustomHighlightColor { r, g, b, alpha } => BNHighlightColor {
2931                style: BNHighlightColorStyle::CustomHighlightColor,
2932                r,
2933                g,
2934                b,
2935                alpha,
2936                ..Default::default()
2937            },
2938        }
2939    }
2940}
2941
2942impl Default for HighlightColor {
2943    fn default() -> Self {
2944        Self::StandardHighlightColor {
2945            color: HighlightStandardColor::NoHighlightColor,
2946            alpha: 0,
2947        }
2948    }
2949}
2950
2951// TODO: Move this out of function, so we can use it in the binary view
2952// NOTE only exists as Array<Comments>, cant be owned
2953#[derive(Clone, Debug, Hash, Eq, PartialEq)]
2954pub struct Comment {
2955    pub addr: u64,
2956    pub comment: String,
2957}
2958
2959impl CoreArrayProvider for Comment {
2960    type Raw = u64;
2961    type Context = Ref<Function>;
2962    type Wrapped<'a> = Comment;
2963}
2964
2965unsafe impl CoreArrayProviderInner for Comment {
2966    unsafe fn free(raw: *mut Self::Raw, _count: usize, _context: &Self::Context) {
2967        BNFreeAddressList(raw);
2968    }
2969
2970    unsafe fn wrap_raw<'a>(raw: &'a Self::Raw, function: &'a Self::Context) -> Self::Wrapped<'a> {
2971        Comment {
2972            addr: *raw,
2973            comment: function.comment_at(*raw),
2974        }
2975    }
2976}
2977
2978#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq)]
2979pub struct ArchAndAddr {
2980    pub arch: CoreArchitecture,
2981    pub addr: u64,
2982}
2983
2984impl ArchAndAddr {
2985    pub fn new(arch: CoreArchitecture, addr: u64) -> Self {
2986        Self { arch, addr }
2987    }
2988}
2989
2990impl From<BNArchitectureAndAddress> for ArchAndAddr {
2991    fn from(raw: BNArchitectureAndAddress) -> Self {
2992        unsafe {
2993            let arch = CoreArchitecture::from_raw(raw.arch);
2994            let addr = raw.address;
2995            ArchAndAddr { arch, addr }
2996        }
2997    }
2998}
2999
3000impl ArchAndAddr {
3001    pub fn into_raw(self) -> BNArchitectureAndAddress {
3002        BNArchitectureAndAddress {
3003            arch: self.arch.handle,
3004            address: self.addr,
3005        }
3006    }
3007}