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