binaryninja/
function.rs

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