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