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