1use binaryninjacore_sys::*;
20
21#[allow(unused)]
23pub use crate::workflow::AnalysisContext;
24
25use crate::architecture::{Architecture, CoreArchitecture};
26use crate::base_detection::BaseAddressDetection;
27use crate::basic_block::BasicBlock;
28use crate::binary_view::search::SearchQuery;
29use crate::component::Component;
30use crate::confidence::Conf;
31use crate::data_buffer::DataBuffer;
32use crate::debuginfo::DebugInfo;
33use crate::disassembly::DisassemblySettings;
34use crate::external_library::{ExternalLibrary, ExternalLocation};
35use crate::file_accessor::{
36 raw_mut as raw_file_accessor, Accessor, BorrowedFileAccessor, FileAccessor, FileAccessorHandle,
37};
38use crate::file_metadata::FileMetadata;
39use crate::flowgraph::FlowGraph;
40use crate::function::{Function, FunctionViewType, Location, NativeBlock};
41use crate::linear_view::{LinearDisassemblyLine, LinearViewCursor};
42use crate::metadata::Metadata;
43use crate::platform::Platform;
44use crate::progress::{NoProgressCallback, ProgressCallback};
45use crate::project::file::ProjectFile;
46use crate::rc::*;
47use crate::references::{CodeReference, CodeXref, DataReference, DataXref};
48use crate::relocation::Relocation;
49use crate::section::{Section, SectionBuilder};
50use crate::segment::{Segment, SegmentBuilder};
51use crate::settings::Settings;
52use crate::string::*;
53use crate::symbol::{Symbol, SymbolType};
54use crate::tags::{Tag, TagReference, TagType};
55use crate::types::{
56 FunctionParameter, NamedTypeReference, QualifiedName, QualifiedNameAndType,
57 QualifiedNameTypeAndId, ReturnValue, Type, TypeArchive, TypeArchiveId, TypeContainer,
58 TypeLibrary,
59};
60use crate::variable::DataVariable;
61use crate::workflow::Workflow;
62use crate::{Endianness, BN_FULL_CONFIDENCE};
63use std::collections::{BTreeMap, HashMap};
64use std::ffi::{c_char, c_void, CString};
65use std::fmt::{Debug, Display, Formatter};
66use std::mem::MaybeUninit;
67use std::ops::Range;
68use std::path::{Path, PathBuf};
69use std::ptr::NonNull;
70
71pub mod memory_map;
72pub mod reader;
73pub mod search;
74pub mod writer;
75
76pub use memory_map::{MemoryMap, MemoryRegionInfo, ResolvedRange};
77pub use reader::BinaryReader;
78pub use writer::BinaryWriter;
79
80pub type BinaryViewEventType = BNBinaryViewEventType;
81pub type AnalysisState = BNAnalysisState;
82pub type ModificationStatus = BNModificationStatus;
83pub type StringType = BNStringType;
84pub type FindFlag = BNFindFlag;
85
86pub fn register_binary_view_type<T>(view_type: T) -> (&'static T, BinaryViewType)
88where
89 T: CustomBinaryViewType,
90{
91 let name = T::NAME.to_cstr();
92 let long_name = T::LONG_NAME.to_cstr();
93 let leaked_type = Box::leak(Box::new(view_type));
94
95 let result = unsafe {
96 BNRegisterBinaryViewType(
97 name.as_ref().as_ptr() as *const _,
98 long_name.as_ref().as_ptr() as *const _,
99 &mut BNCustomBinaryViewType {
100 context: leaked_type as *mut _ as *mut std::os::raw::c_void,
101 create: Some(cb_create::<T>),
102 parse: Some(cb_parse::<T>),
103 isValidForData: Some(cb_valid::<T>),
104 isDeprecated: Some(cb_deprecated::<T>),
105 isForceLoadable: Some(cb_force_loadable::<T>),
106 getLoadSettingsForData: Some(cb_load_settings::<T>),
107 hasNoInitialContent: Some(cb_has_no_initial_content::<T>),
108 },
109 )
110 };
111
112 assert!(
113 !result.is_null(),
114 "BNRegisterBinaryViewType always returns a non-null handle"
115 );
116 let core_view_type = unsafe { BinaryViewType::from_raw(result) };
117 (leaked_type, core_view_type)
118}
119
120pub trait CustomBinaryViewType: 'static + Sync {
122 type CustomBinaryView: CustomBinaryView;
124
125 const NAME: &'static str;
127
128 const LONG_NAME: &'static str = Self::NAME;
130
131 const DEPRECATED: bool = false;
136
137 const FORCE_LOADABLE: bool = false;
141
142 const HAS_NO_INITIAL_CONTENT: bool = false;
151
152 fn create_binary_view(&self, data: &BinaryView) -> Result<Self::CustomBinaryView, ()>;
154
155 fn create_binary_view_for_parse(
166 &self,
167 data: &BinaryView,
168 ) -> Result<Self::CustomBinaryView, ()> {
169 self.create_binary_view(data)
170 }
171
172 fn is_valid_for(&self, data: &BinaryView) -> bool;
177
178 fn load_settings_for_data(&self, _data: &BinaryView) -> Option<Ref<Settings>> {
185 None
186 }
187}
188
189#[derive(Copy, Clone, PartialEq, Eq, Hash)]
195pub struct BinaryViewType {
196 pub handle: *mut BNBinaryViewType,
197}
198
199impl BinaryViewType {
200 pub(crate) unsafe fn from_raw(handle: *mut BNBinaryViewType) -> Self {
201 debug_assert!(!handle.is_null());
202 Self { handle }
203 }
204
205 pub fn list_all() -> Array<BinaryViewType> {
206 unsafe {
207 let mut count: usize = 0;
208 let types = BNGetBinaryViewTypes(&mut count as *mut _);
209 Array::new(types, count, ())
210 }
211 }
212
213 pub fn valid_types_for_data(data: &BinaryView) -> Array<BinaryViewType> {
216 unsafe {
217 let mut count: usize = 0;
218 let types = BNGetBinaryViewTypesForData(data.handle, &mut count as *mut _);
219 Array::new(types, count, ())
220 }
221 }
222
223 pub fn by_name(name: &str) -> Option<Self> {
225 let bytes = name.to_cstr();
226 let handle = unsafe { BNGetBinaryViewTypeByName(bytes.as_ref().as_ptr() as *const _) };
227 if handle.is_null() {
228 None
229 } else {
230 Some(unsafe { BinaryViewType::from_raw(handle) })
231 }
232 }
233
234 pub fn name(&self) -> String {
236 unsafe { BnString::into_string(BNGetBinaryViewTypeName(self.handle)) }
237 }
238
239 pub fn long_name(&self) -> String {
241 unsafe { BnString::into_string(BNGetBinaryViewTypeLongName(self.handle)) }
242 }
243
244 pub fn register_arch<A: Architecture>(&self, id: u32, endianness: Endianness, arch: &A) {
249 unsafe {
250 BNRegisterArchitectureForViewType(self.handle, id, endianness, arch.as_ref().handle);
251 }
252 }
253
254 pub fn register_platform(&self, id: u32, plat: &Platform) {
259 let arch = plat.arch();
260 unsafe {
261 BNRegisterPlatformForViewType(self.handle, id, arch.handle, plat.handle);
262 }
263 }
264
265 pub fn register_platform_recognizer<R>(&self, id: u32, endian: Endianness, recognizer: R)
284 where
285 R: 'static + Fn(&BinaryView, &Metadata) -> Option<Ref<Platform>> + Send + Sync,
286 {
287 #[repr(C)]
288 struct PlatformRecognizerHandlerContext<R>
289 where
290 R: 'static + Fn(&BinaryView, &Metadata) -> Option<Ref<Platform>> + Send + Sync,
291 {
292 recognizer: R,
293 }
294
295 extern "C" fn cb_recognize_low_level_il<R>(
296 ctxt: *mut std::os::raw::c_void,
297 bv: *mut BNBinaryView,
298 metadata: *mut BNMetadata,
299 ) -> *mut BNPlatform
300 where
301 R: 'static + Fn(&BinaryView, &Metadata) -> Option<Ref<Platform>> + Send + Sync,
302 {
303 let context = unsafe { &*(ctxt as *mut PlatformRecognizerHandlerContext<R>) };
304 let bv = unsafe { BinaryView::from_raw(bv).to_owned() };
305 let metadata = unsafe { Metadata::from_raw(metadata).to_owned() };
306 match (context.recognizer)(&bv, &metadata) {
307 Some(plat) => unsafe { Ref::into_raw(plat).handle },
308 None => std::ptr::null_mut(),
309 }
310 }
311
312 let recognizer = PlatformRecognizerHandlerContext { recognizer };
313 let raw = Box::into_raw(Box::new(recognizer));
314 unsafe {
315 BNRegisterPlatformRecognizerForViewType(
316 self.handle,
317 id as u64,
318 endian,
319 Some(cb_recognize_low_level_il::<R>),
320 raw as *mut std::os::raw::c_void,
321 )
322 }
323 }
324
325 pub fn create(&self, data: &BinaryView) -> Result<Ref<BinaryView>, ()> {
331 let handle = unsafe { BNCreateBinaryViewOfType(self.handle, data.handle) };
332 if handle.is_null() {
333 return Err(());
335 }
336 unsafe { Ok(BinaryView::ref_from_raw(handle)) }
337 }
338
339 pub fn parse(&self, data: &BinaryView) -> Result<Ref<BinaryView>, ()> {
343 let handle = unsafe { BNParseBinaryViewOfType(self.handle, data.handle) };
344 if handle.is_null() {
345 return Err(());
347 }
348 unsafe { Ok(BinaryView::ref_from_raw(handle)) }
349 }
350
351 pub fn is_valid_for(&self, data: &BinaryView) -> bool {
356 unsafe { BNIsBinaryViewTypeValidForData(self.handle, data.handle) }
357 }
358
359 pub fn is_deprecated(&self) -> bool {
364 unsafe { BNIsBinaryViewTypeDeprecated(self.handle) }
365 }
366
367 pub fn is_force_loadable(&self) -> bool {
371 unsafe { BNIsBinaryViewTypeForceLoadable(self.handle) }
372 }
373
374 pub fn has_no_initial_content(&self) -> bool {
383 unsafe { BNBinaryViewTypeHasNoInitialContent(self.handle) }
384 }
385
386 pub fn load_settings_for_data(&self, data: &BinaryView) -> Option<Ref<Settings>> {
387 let settings_handle =
388 unsafe { BNGetBinaryViewLoadSettingsForData(self.handle, data.handle) };
389
390 if settings_handle.is_null() {
391 None
392 } else {
393 unsafe { Some(Settings::ref_from_raw(settings_handle)) }
394 }
395 }
396}
397
398impl Debug for BinaryViewType {
399 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
400 f.debug_struct("BinaryViewType")
401 .field("name", &self.name())
402 .field("long_name", &self.long_name())
403 .finish()
404 }
405}
406
407impl CoreArrayProvider for BinaryViewType {
408 type Raw = *mut BNBinaryViewType;
409 type Context = ();
410 type Wrapped<'a> = Guard<'a, BinaryViewType>;
411}
412
413unsafe impl CoreArrayProviderInner for BinaryViewType {
414 unsafe fn free(raw: *mut Self::Raw, _count: usize, _context: &Self::Context) {
415 BNFreeBinaryViewTypeList(raw);
416 }
417
418 unsafe fn wrap_raw<'a>(raw: &'a Self::Raw, _context: &'a Self::Context) -> Self::Wrapped<'a> {
419 Guard::new(BinaryViewType::from_raw(*raw), &())
420 }
421}
422
423unsafe impl Send for BinaryViewType {}
424unsafe impl Sync for BinaryViewType {}
425
426pub trait CustomBinaryView: BinaryViewBase {
428 fn initialize(&mut self, view: &BinaryView) -> bool;
438
439 fn on_after_snapshot_data_applied(&mut self) {}
444}
445
446struct CustomBinaryViewContext<C: CustomBinaryView> {
449 core_view: MaybeUninit<BinaryView>,
452 view: C,
453}
454
455#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
462pub struct MetadataStoreFlags {
463 pub persistent: bool,
464 pub marks_analysis_changed: bool,
465}
466
467impl MetadataStoreFlags {
468 pub const EPHEMERAL: Self = Self {
471 persistent: false,
472 marks_analysis_changed: false,
473 };
474
475 pub const PERSISTENT: Self = Self {
479 persistent: true,
480 marks_analysis_changed: false,
481 };
482
483 pub fn persistent(mut self, persistent: bool) -> Self {
484 self.persistent = persistent;
485 self
486 }
487
488 pub fn marks_analysis_changed(mut self, marks_analysis_changed: bool) -> Self {
489 self.marks_analysis_changed = marks_analysis_changed;
490 self
491 }
492
493 pub(crate) fn into_raw(self) -> BNMetadataStoreFlag {
494 let mut raw = BNMetadataStoreFlag::MetadataStoreEphemeral;
495 if self.persistent {
496 raw |= BNMetadataStoreFlag::MetadataStorePersistent;
497 }
498 if self.marks_analysis_changed {
499 raw |= BNMetadataStoreFlag::MetadataStoreMarksAnalysisChanged;
500 }
501 raw
502 }
503}
504
505#[allow(clippy::len_without_is_empty)]
506pub trait BinaryViewBase {
507 fn read(&self, _buf: &mut [u8], _offset: u64) -> usize {
508 0
509 }
510
511 fn write(&self, _offset: u64, _data: &[u8]) -> usize {
512 0
513 }
514
515 fn insert(&self, _offset: u64, _data: &[u8]) -> usize {
516 0
517 }
518
519 fn remove(&self, _offset: u64, _len: usize) -> usize {
520 0
521 }
522
523 fn offset_valid(&self, offset: u64) -> bool {
525 let mut buf = [0u8; 1];
526 self.read(&mut buf[..], offset) == buf.len()
527 }
528
529 fn offset_readable(&self, offset: u64) -> bool {
531 self.offset_valid(offset)
532 }
533
534 fn offset_writable(&self, offset: u64) -> bool {
536 self.offset_valid(offset)
537 }
538
539 fn offset_executable(&self, offset: u64) -> bool {
541 self.offset_valid(offset)
542 }
543
544 fn offset_backed_by_file(&self, offset: u64) -> bool {
546 self.offset_valid(offset)
547 }
548
549 fn next_valid_offset_after(&self, offset: u64) -> u64 {
552 let start = self.start();
553 if offset < start {
554 start
555 } else {
556 offset
557 }
558 }
559
560 fn modification_status(&self, _offset: u64) -> ModificationStatus {
562 ModificationStatus::Original
563 }
564
565 fn start(&self) -> u64 {
567 0
568 }
569
570 fn len(&self) -> u64 {
572 0
573 }
574
575 fn executable(&self) -> bool {
576 true
577 }
578
579 fn relocatable(&self) -> bool {
580 false
581 }
582
583 fn entry_point(&self) -> u64 {
584 0
585 }
586
587 fn default_endianness(&self) -> Endianness;
588
589 fn address_size(&self) -> usize;
590
591 fn save(&self, view: &BinaryView, file: &mut BorrowedFileAccessor<'_>) -> bool {
596 view.parent_view().is_some_and(|parent| {
597 unsafe { parent.save_to_accessor(file) }
601 })
602 }
603}
604
605#[derive(Debug, Clone)]
606pub struct ActiveAnalysisInfo {
607 pub func: Ref<Function>,
608 pub analysis_time: u64,
609 pub update_count: usize,
610 pub submit_count: usize,
611}
612
613#[derive(Debug, Clone)]
614pub struct AnalysisInfo {
615 pub state: AnalysisState,
616 pub analysis_time: u64,
617 pub active_info: Vec<ActiveAnalysisInfo>,
618}
619
620#[derive(Debug, Clone, Ord, PartialOrd, Eq, PartialEq)]
621pub enum AnalysisProgress {
622 Initial,
623 Hold,
624 Idle,
625 Discovery,
626 Disassembling(usize, usize),
627 Analyzing(usize, usize),
628 ExtendedAnalysis,
629}
630
631impl Display for AnalysisProgress {
632 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
633 match self {
634 AnalysisProgress::Initial => {
635 write!(f, "Initial")
636 }
637 AnalysisProgress::Hold => {
638 write!(f, "Hold")
639 }
640 AnalysisProgress::Idle => {
641 write!(f, "Idle")
642 }
643 AnalysisProgress::Discovery => {
644 write!(f, "Discovery")
645 }
646 AnalysisProgress::Disassembling(count, total) => {
647 write!(f, "Disassembling ({count}/{total})")
648 }
649 AnalysisProgress::Analyzing(count, total) => {
650 write!(f, "Analyzing ({count}/{total})")
651 }
652 AnalysisProgress::ExtendedAnalysis => {
653 write!(f, "Extended Analysis")
654 }
655 }
656 }
657}
658
659impl From<BNAnalysisProgress> for AnalysisProgress {
660 fn from(value: BNAnalysisProgress) -> Self {
661 match value.state {
662 BNAnalysisState::InitialState => Self::Initial,
663 BNAnalysisState::HoldState => Self::Hold,
664 BNAnalysisState::IdleState => Self::Idle,
665 BNAnalysisState::DiscoveryState => Self::Discovery,
666 BNAnalysisState::DisassembleState => Self::Disassembling(value.count, value.total),
667 BNAnalysisState::AnalyzeState => Self::Analyzing(value.count, value.total),
668 BNAnalysisState::ExtendedAnalyzeState => Self::ExtendedAnalysis,
669 }
670 }
671}
672
673#[derive(PartialEq, Eq, Hash)]
700pub struct BinaryView {
701 pub handle: *mut BNBinaryView,
702}
703
704impl BinaryView {
705 pub unsafe fn from_raw(handle: *mut BNBinaryView) -> Self {
706 debug_assert!(!handle.is_null());
707 Self { handle }
708 }
709
710 pub(crate) unsafe fn ref_from_raw(handle: *mut BNBinaryView) -> Ref<Self> {
711 debug_assert!(!handle.is_null());
712 Ref::new(Self { handle })
713 }
714
715 pub fn from_custom<C: CustomBinaryView>(
717 view_type_name: &str,
718 file: &FileMetadata,
719 parent_view: &BinaryView,
720 view: C,
721 ) -> Result<Ref<Self>, ()> {
722 let type_name = view_type_name.to_cstr();
723 let custom_context = CustomBinaryViewContext {
726 core_view: MaybeUninit::uninit(),
727 view,
728 };
729 let leaked_view = Box::leak(Box::new(custom_context));
731 let handle = unsafe {
732 BNCreateCustomBinaryView(
733 type_name.as_ptr(),
734 file.handle,
735 parent_view.handle,
736 &mut BNCustomBinaryView {
737 context: leaked_view as *mut CustomBinaryViewContext<C> as *mut _,
738 init: Some(cb_init::<C>),
739 freeObject: Some(cb_free_object::<C>),
740 externalRefTaken: None,
741 externalRefReleased: None,
742 read: Some(cb_read::<C>),
743 write: Some(cb_write::<C>),
744 insert: Some(cb_insert::<C>),
745 remove: Some(cb_remove::<C>),
746 getModification: Some(cb_modification::<C>),
747 isValidOffset: Some(cb_offset_valid::<C>),
748 isOffsetReadable: Some(cb_offset_readable::<C>),
749 isOffsetWritable: Some(cb_offset_writable::<C>),
750 isOffsetExecutable: Some(cb_offset_executable::<C>),
751 isOffsetBackedByFile: Some(cb_offset_backed_by_file::<C>),
752 getNextValidOffset: Some(cb_next_valid_offset::<C>),
753 getStart: Some(cb_start::<C>),
754 getLength: Some(cb_length::<C>),
755 getEntryPoint: Some(cb_entry_point::<C>),
756 isExecutable: Some(cb_executable::<C>),
757 getDefaultEndianness: Some(cb_endianness::<C>),
758 isRelocatable: Some(cb_relocatable::<C>),
759 getAddressSize: Some(cb_address_size::<C>),
760 save: Some(cb_save::<C>),
761 onAfterSnapshotDataApplied: Some(cb_on_after_snapshot_data_applied::<C>),
762 },
763 )
764 };
765 if handle.is_null() {
766 let _ = unsafe { Box::from_raw(leaked_view) };
768 return Err(());
769 }
770 leaked_view.core_view = unsafe { MaybeUninit::new(BinaryView::from_raw(handle)) };
771 unsafe { Ok(Ref::new(Self { handle })) }
772 }
773
774 pub fn from_metadata(meta: &FileMetadata) -> Result<Ref<Self>, ()> {
779 if !meta.file_path().exists() {
780 return Err(());
781 }
782 let file = meta.file_path().to_cstr();
783 let handle =
784 unsafe { BNCreateBinaryDataViewFromFilename(meta.handle, file.as_ptr() as *mut _) };
785 if handle.is_null() {
786 return Err(());
787 }
788 unsafe { Ok(Ref::new(Self { handle })) }
789 }
790
791 pub fn from_path(meta: &FileMetadata, file_path: impl AsRef<Path>) -> Result<Ref<Self>, ()> {
796 meta.set_file_path(file_path.as_ref());
797 Self::from_metadata(meta)
798 }
799
800 pub unsafe fn from_accessor<A: Accessor>(
806 meta: &FileMetadata,
807 accessor: &mut FileAccessor<A>,
808 ) -> Result<Ref<Self>, ()> {
809 let handle = unsafe { BNCreateBinaryDataViewFromFile(meta.handle, &mut accessor.raw) };
810 if handle.is_null() {
811 return Err(());
812 }
813 unsafe { Ok(Ref::new(Self { handle })) }
814 }
815
816 pub fn from_data(meta: &FileMetadata, data: &[u8]) -> Ref<Self> {
820 let handle = unsafe {
821 BNCreateBinaryDataViewFromData(meta.handle, data.as_ptr() as *mut _, data.len())
822 };
823 assert!(
824 !handle.is_null(),
825 "BNCreateBinaryDataViewFromData should always succeed"
826 );
827 unsafe { Ref::new(Self { handle }) }
828 }
829
830 pub unsafe fn save_to_path(&self, file_path: impl AsRef<Path>) -> bool {
839 let file = file_path.as_ref().to_cstr();
840 unsafe { BNSaveToFilename(self.handle, file.as_ptr() as *mut _) }
841 }
842
843 pub unsafe fn save_to_accessor<A: FileAccessorHandle + ?Sized>(&self, file: &mut A) -> bool {
852 unsafe { BNSaveToFile(self.handle, raw_file_accessor(file)) }
853 }
854
855 pub fn file(&self) -> Ref<FileMetadata> {
856 unsafe {
857 let raw = BNGetFileForView(self.handle);
858 FileMetadata::ref_from_raw(raw)
859 }
860 }
861
862 pub fn parent_view(&self) -> Option<Ref<BinaryView>> {
863 let raw_view_ptr = unsafe { BNGetParentView(self.handle) };
864 match raw_view_ptr.is_null() {
865 false => Some(unsafe { BinaryView::ref_from_raw(raw_view_ptr) }),
866 true => None,
867 }
868 }
869
870 pub fn raw_view(&self) -> Option<Ref<BinaryView>> {
871 self.file().view_of_type("Raw")
872 }
873
874 pub fn view_type(&self) -> String {
875 let ptr: *mut c_char = unsafe { BNGetViewType(self.handle) };
876 unsafe { BnString::into_string(ptr) }
877 }
878
879 pub fn read_vec(&self, offset: u64, len: usize) -> Vec<u8> {
881 let mut ret = vec![0; len];
882 let size = self.read(&mut ret, offset);
883 ret.truncate(size);
884 ret
885 }
886
887 pub fn read_into_vec(&self, dest: &mut Vec<u8>, offset: u64, len: usize) -> usize {
889 let starting_len = dest.len();
890 dest.resize(starting_len + len, 0);
891 let read_size = self.read(&mut dest[starting_len..], offset);
892 dest.truncate(starting_len + read_size);
893 read_size
894 }
895
896 pub fn read_c_string_at(&self, offset: u64, len: usize) -> Option<CString> {
898 let mut buf = vec![0; len];
899 let size = self.read(&mut buf, offset);
900 let string = CString::new(buf[..size].to_vec()).ok()?;
901 Some(string)
902 }
903
904 pub fn read_utf8_string_at(&self, offset: u64, len: usize) -> Option<String> {
906 let mut buf = vec![0; len];
907 let size = self.read(&mut buf, offset);
908 let string = String::from_utf8(buf[..size].to_vec()).ok()?;
909 Some(string)
910 }
911
912 pub fn search<C: FnMut(u64, &DataBuffer) -> bool>(
916 &self,
917 query: &SearchQuery,
918 on_match: C,
919 ) -> bool {
920 self.search_with_progress(query, on_match, NoProgressCallback)
921 }
922
923 pub fn search_with_progress<P: ProgressCallback, C: FnMut(u64, &DataBuffer) -> bool>(
927 &self,
928 query: &SearchQuery,
929 mut on_match: C,
930 mut progress: P,
931 ) -> bool {
932 unsafe extern "C" fn cb_on_match<C: FnMut(u64, &DataBuffer) -> bool>(
933 ctx: *mut c_void,
934 offset: u64,
935 data: *mut BNDataBuffer,
936 ) -> bool {
937 let f = ctx as *mut C;
938 let buffer = DataBuffer::from_raw(data);
939 (*f)(offset, &buffer)
940 }
941
942 let query = query.to_json().to_cstr();
943 unsafe {
944 BNSearch(
945 self.handle,
946 query.as_ptr(),
947 &mut progress as *mut P as *mut c_void,
948 Some(P::cb_progress_callback),
949 &mut on_match as *const C as *mut c_void,
950 Some(cb_on_match::<C>),
951 )
952 }
953 }
954
955 pub fn find_next_data(&self, start: u64, end: u64, data: &DataBuffer) -> Option<u64> {
956 self.find_next_data_with_opts(
957 start,
958 end,
959 data,
960 FindFlag::FindCaseInsensitive,
961 NoProgressCallback,
962 )
963 }
964
965 pub fn find_next_data_with_opts<P: ProgressCallback>(
969 &self,
970 start: u64,
971 end: u64,
972 data: &DataBuffer,
973 flag: FindFlag,
974 mut progress: P,
975 ) -> Option<u64> {
976 let mut result: u64 = 0;
977 let found = unsafe {
978 BNFindNextDataWithProgress(
979 self.handle,
980 start,
981 end,
982 data.as_raw(),
983 &mut result,
984 flag,
985 &mut progress as *mut P as *mut c_void,
986 Some(P::cb_progress_callback),
987 )
988 };
989
990 if found {
991 Some(result)
992 } else {
993 None
994 }
995 }
996
997 pub fn find_next_constant(
998 &self,
999 start: u64,
1000 end: u64,
1001 constant: u64,
1002 view_type: FunctionViewType,
1003 ) -> Option<u64> {
1004 let settings = DisassemblySettings::new();
1006 self.find_next_constant_with_opts(
1007 start,
1008 end,
1009 constant,
1010 &settings,
1011 view_type,
1012 NoProgressCallback,
1013 )
1014 }
1015
1016 pub fn find_next_constant_with_opts<P: ProgressCallback>(
1020 &self,
1021 start: u64,
1022 end: u64,
1023 constant: u64,
1024 disasm_settings: &DisassemblySettings,
1025 view_type: FunctionViewType,
1026 mut progress: P,
1027 ) -> Option<u64> {
1028 let mut result: u64 = 0;
1029 let raw_view_type = FunctionViewType::into_raw(view_type);
1030 let found = unsafe {
1031 BNFindNextConstantWithProgress(
1032 self.handle,
1033 start,
1034 end,
1035 constant,
1036 &mut result,
1037 disasm_settings.handle,
1038 raw_view_type,
1039 &mut progress as *mut P as *mut c_void,
1040 Some(P::cb_progress_callback),
1041 )
1042 };
1043 FunctionViewType::free_raw(raw_view_type);
1044
1045 if found {
1046 Some(result)
1047 } else {
1048 None
1049 }
1050 }
1051
1052 pub fn find_next_text(
1053 &self,
1054 start: u64,
1055 end: u64,
1056 text: &str,
1057 view_type: FunctionViewType,
1058 ) -> Option<u64> {
1059 let settings = DisassemblySettings::new();
1061 self.find_next_text_with_opts(
1062 start,
1063 end,
1064 text,
1065 &settings,
1066 FindFlag::FindCaseInsensitive,
1067 view_type,
1068 NoProgressCallback,
1069 )
1070 }
1071
1072 pub fn find_next_text_with_opts<P: ProgressCallback>(
1076 &self,
1077 start: u64,
1078 end: u64,
1079 text: &str,
1080 disasm_settings: &DisassemblySettings,
1081 flag: FindFlag,
1082 view_type: FunctionViewType,
1083 mut progress: P,
1084 ) -> Option<u64> {
1085 let text = text.to_cstr();
1086 let raw_view_type = FunctionViewType::into_raw(view_type);
1087 let mut result: u64 = 0;
1088 let found = unsafe {
1089 BNFindNextTextWithProgress(
1090 self.handle,
1091 start,
1092 end,
1093 text.as_ptr(),
1094 &mut result,
1095 disasm_settings.handle,
1096 flag,
1097 raw_view_type,
1098 &mut progress as *mut P as *mut c_void,
1099 Some(P::cb_progress_callback),
1100 )
1101 };
1102 FunctionViewType::free_raw(raw_view_type);
1103
1104 if found {
1105 Some(result)
1106 } else {
1107 None
1108 }
1109 }
1110
1111 pub fn notify_data_written(&self, offset: u64, len: usize) {
1112 unsafe {
1113 BNNotifyDataWritten(self.handle, offset, len);
1114 }
1115 }
1116
1117 pub fn notify_data_inserted(&self, offset: u64, len: usize) {
1118 unsafe {
1119 BNNotifyDataInserted(self.handle, offset, len);
1120 }
1121 }
1122
1123 pub fn notify_data_removed(&self, offset: u64, len: usize) {
1124 unsafe {
1125 BNNotifyDataRemoved(self.handle, offset, len as u64);
1126 }
1127 }
1128
1129 pub fn offset_has_code_semantics(&self, offset: u64) -> bool {
1132 unsafe { BNIsOffsetCodeSemantics(self.handle, offset) }
1133 }
1134
1135 pub fn offset_has_extern_semantics(&self, offset: u64) -> bool {
1137 unsafe { BNIsOffsetExternSemantics(self.handle, offset) }
1138 }
1139
1140 pub fn offset_has_writable_semantics(&self, offset: u64) -> bool {
1143 unsafe { BNIsOffsetWritableSemantics(self.handle, offset) }
1144 }
1145
1146 pub fn offset_has_read_only_semantics(&self, offset: u64) -> bool {
1149 unsafe { BNIsOffsetReadOnlySemantics(self.handle, offset) }
1150 }
1151
1152 pub fn image_base(&self) -> u64 {
1153 unsafe { BNGetImageBase(self.handle) }
1154 }
1155
1156 pub fn original_image_base(&self) -> u64 {
1157 unsafe { BNGetOriginalImageBase(self.handle) }
1158 }
1159
1160 pub fn set_original_image_base(&self, image_base: u64) {
1161 unsafe { BNSetOriginalImageBase(self.handle, image_base) }
1162 }
1163
1164 pub fn end(&self) -> u64 {
1166 unsafe { BNGetEndOffset(self.handle) }
1167 }
1168
1169 pub fn add_analysis_option(&self, name: &str) {
1170 let name = name.to_cstr();
1171 unsafe { BNAddAnalysisOption(self.handle, name.as_ptr()) }
1172 }
1173
1174 pub fn has_initial_analysis(&self) -> bool {
1175 unsafe { BNHasInitialAnalysis(self.handle) }
1176 }
1177
1178 pub fn set_analysis_hold(&self, enable: bool) {
1179 unsafe { BNSetAnalysisHold(self.handle, enable) }
1180 }
1181
1182 pub fn update_analysis(&self) {
1191 unsafe {
1192 BNUpdateAnalysis(self.handle);
1193 }
1194 }
1195
1196 pub fn update_analysis_and_wait(&self) {
1205 unsafe {
1206 BNUpdateAnalysisAndWait(self.handle);
1207 }
1208 }
1209
1210 pub fn reanalyze(&self) {
1217 unsafe {
1218 BNReanalyzeAllFunctions(self.handle);
1219 }
1220 }
1221
1222 pub fn abort_analysis(&self) {
1223 unsafe { BNAbortAnalysis(self.handle) }
1224 }
1225
1226 pub fn analysis_is_aborted(&self) -> bool {
1227 unsafe { BNAnalysisIsAborted(self.handle) }
1228 }
1229
1230 pub fn workflow(&self) -> Ref<Workflow> {
1231 unsafe {
1232 let raw_ptr = BNGetWorkflowForBinaryView(self.handle);
1233 let nonnull = NonNull::new(raw_ptr).expect("All views must have a workflow");
1234 Workflow::ref_from_raw(nonnull)
1235 }
1236 }
1237
1238 pub fn analysis_info(&self) -> AnalysisInfo {
1239 let info_ptr = unsafe { BNGetAnalysisInfo(self.handle) };
1240 assert!(!info_ptr.is_null());
1241 let info = unsafe { *info_ptr };
1242 let active_infos = unsafe { std::slice::from_raw_parts(info.activeInfo, info.count) };
1243
1244 let mut active_info_list = vec![];
1245 for active_info in active_infos {
1246 let func = unsafe { Function::from_raw(active_info.func).to_owned() };
1247 active_info_list.push(ActiveAnalysisInfo {
1248 func,
1249 analysis_time: active_info.analysisTime,
1250 update_count: active_info.updateCount,
1251 submit_count: active_info.submitCount,
1252 });
1253 }
1254
1255 let result = AnalysisInfo {
1256 state: info.state,
1257 analysis_time: info.analysisTime,
1258 active_info: active_info_list,
1259 };
1260
1261 unsafe { BNFreeAnalysisInfo(info_ptr) };
1262 result
1263 }
1264
1265 pub fn analysis_progress(&self) -> AnalysisProgress {
1266 let progress_raw = unsafe { BNGetAnalysisProgress(self.handle) };
1267 AnalysisProgress::from(progress_raw)
1268 }
1269
1270 pub fn default_arch(&self) -> Option<CoreArchitecture> {
1271 unsafe {
1272 let raw = BNGetDefaultArchitecture(self.handle);
1273
1274 if raw.is_null() {
1275 return None;
1276 }
1277
1278 Some(CoreArchitecture::from_raw(raw))
1279 }
1280 }
1281
1282 pub fn set_default_arch<A: Architecture>(&self, arch: &A) {
1283 unsafe {
1284 BNSetDefaultArchitecture(self.handle, arch.as_ref().handle);
1285 }
1286 }
1287
1288 pub fn default_platform(&self) -> Option<Ref<Platform>> {
1289 unsafe {
1290 let raw = BNGetDefaultPlatform(self.handle);
1291
1292 if raw.is_null() {
1293 return None;
1294 }
1295
1296 Some(Platform::ref_from_raw(raw))
1297 }
1298 }
1299
1300 pub fn set_default_platform(&self, plat: &Platform) {
1301 unsafe {
1302 BNSetDefaultPlatform(self.handle, plat.handle);
1303 }
1304 }
1305
1306 pub fn base_address_detection(&self) -> Option<BaseAddressDetection> {
1307 unsafe {
1308 let handle = BNCreateBaseAddressDetection(self.handle);
1309 NonNull::new(handle).map(|base| BaseAddressDetection::from_raw(base))
1310 }
1311 }
1312
1313 pub fn instruction_len<A: Architecture>(&self, arch: &A, addr: u64) -> Option<usize> {
1314 unsafe {
1315 let size = BNGetInstructionLength(self.handle, arch.as_ref().handle, addr);
1316
1317 if size > 0 {
1318 Some(size)
1319 } else {
1320 None
1321 }
1322 }
1323 }
1324
1325 pub fn symbol_by_address(&self, addr: u64) -> Option<Ref<Symbol>> {
1326 unsafe {
1327 let raw_sym_ptr = BNGetSymbolByAddress(self.handle, addr, std::ptr::null_mut());
1328 match raw_sym_ptr.is_null() {
1329 false => Some(Symbol::ref_from_raw(raw_sym_ptr)),
1330 true => None,
1331 }
1332 }
1333 }
1334
1335 pub fn symbol_by_raw_name(&self, raw_name: impl IntoCStr) -> Option<Ref<Symbol>> {
1336 let raw_name = raw_name.to_cstr();
1337
1338 unsafe {
1339 let raw_sym_ptr =
1340 BNGetSymbolByRawName(self.handle, raw_name.as_ptr(), std::ptr::null_mut());
1341 match raw_sym_ptr.is_null() {
1342 false => Some(Symbol::ref_from_raw(raw_sym_ptr)),
1343 true => None,
1344 }
1345 }
1346 }
1347
1348 pub fn symbols(&self) -> Array<Symbol> {
1349 unsafe {
1350 let mut count = 0;
1351 let handles = BNGetSymbols(self.handle, &mut count, std::ptr::null_mut());
1352
1353 Array::new(handles, count, ())
1354 }
1355 }
1356
1357 pub fn symbols_by_name(&self, name: impl IntoCStr) -> Array<Symbol> {
1358 let raw_name = name.to_cstr();
1359
1360 unsafe {
1361 let mut count = 0;
1362 let handles = BNGetSymbolsByName(
1363 self.handle,
1364 raw_name.as_ptr(),
1365 &mut count,
1366 std::ptr::null_mut(),
1367 );
1368
1369 Array::new(handles, count, ())
1370 }
1371 }
1372
1373 pub fn symbols_in_range(&self, range: Range<u64>) -> Array<Symbol> {
1374 unsafe {
1375 let mut count = 0;
1376 let len = range.end.wrapping_sub(range.start);
1377 let handles = BNGetSymbolsInRange(
1378 self.handle,
1379 range.start,
1380 len,
1381 &mut count,
1382 std::ptr::null_mut(),
1383 );
1384
1385 Array::new(handles, count, ())
1386 }
1387 }
1388
1389 pub fn symbols_of_type(&self, ty: SymbolType) -> Array<Symbol> {
1390 unsafe {
1391 let mut count = 0;
1392 let handles =
1393 BNGetSymbolsOfType(self.handle, ty.into(), &mut count, std::ptr::null_mut());
1394
1395 Array::new(handles, count, ())
1396 }
1397 }
1398
1399 pub fn symbols_of_type_in_range(&self, ty: SymbolType, range: Range<u64>) -> Array<Symbol> {
1400 unsafe {
1401 let mut count = 0;
1402 let len = range.end.wrapping_sub(range.start);
1403 let handles = BNGetSymbolsOfTypeInRange(
1404 self.handle,
1405 ty.into(),
1406 range.start,
1407 len,
1408 &mut count,
1409 std::ptr::null_mut(),
1410 );
1411
1412 Array::new(handles, count, ())
1413 }
1414 }
1415
1416 pub fn define_auto_symbol(&self, sym: &Symbol) {
1417 unsafe {
1418 BNDefineAutoSymbol(self.handle, sym.handle);
1419 }
1420 }
1421
1422 pub fn define_auto_symbol_with_type<'a, T: Into<Option<&'a Type>>>(
1426 &self,
1427 sym: &Symbol,
1428 plat: &Platform,
1429 ty: T,
1430 ) -> Ref<Symbol> {
1431 let mut type_with_conf = BNTypeWithConfidence {
1432 type_: if let Some(t) = ty.into() {
1433 t.handle
1434 } else {
1435 std::ptr::null_mut()
1436 },
1437 confidence: BN_FULL_CONFIDENCE,
1438 };
1439
1440 unsafe {
1441 let raw_sym = BNDefineAutoSymbolAndVariableOrFunction(
1442 self.handle,
1443 plat.handle,
1444 sym.handle,
1445 &mut type_with_conf,
1446 );
1447 debug_assert!(
1449 !raw_sym.is_null(),
1450 "BNDefineAutoSymbolAndVariableOrFunction should not return null"
1451 );
1452 Symbol::ref_from_raw(raw_sym)
1453 }
1454 }
1455
1456 pub fn undefine_auto_symbol(&self, sym: &Symbol) {
1457 unsafe {
1458 BNUndefineAutoSymbol(self.handle, sym.handle);
1459 }
1460 }
1461
1462 pub fn define_user_symbol(&self, sym: &Symbol) {
1463 unsafe {
1464 BNDefineUserSymbol(self.handle, sym.handle);
1465 }
1466 }
1467
1468 pub fn undefine_user_symbol(&self, sym: &Symbol) {
1469 unsafe {
1470 BNUndefineUserSymbol(self.handle, sym.handle);
1471 }
1472 }
1473
1474 pub fn data_variables(&self) -> Array<DataVariable> {
1475 unsafe {
1476 let mut count = 0;
1477 let vars = BNGetDataVariables(self.handle, &mut count);
1478 Array::new(vars, count, ())
1479 }
1480 }
1481
1482 pub fn data_variable_at_address(&self, addr: u64) -> Option<DataVariable> {
1483 let mut dv = BNDataVariable::default();
1484 unsafe {
1485 if BNGetDataVariableAtAddress(self.handle, addr, &mut dv) {
1486 Some(DataVariable::from_owned_raw(dv))
1487 } else {
1488 None
1489 }
1490 }
1491 }
1492
1493 pub fn define_auto_data_var<'a, T: Into<Conf<&'a Type>>>(&self, addr: u64, ty: T) {
1494 let mut owned_raw_ty = Conf::<&Type>::into_raw(ty.into());
1495 unsafe {
1496 BNDefineDataVariable(self.handle, addr, &mut owned_raw_ty);
1497 }
1498 }
1499
1500 pub fn define_user_data_var<'a, T: Into<Conf<&'a Type>>>(&self, addr: u64, ty: T) {
1502 let mut owned_raw_ty = Conf::<&Type>::into_raw(ty.into());
1503 unsafe {
1504 BNDefineUserDataVariable(self.handle, addr, &mut owned_raw_ty);
1505 }
1506 }
1507
1508 pub fn undefine_auto_data_var(&self, addr: u64, blacklist: Option<bool>) {
1509 unsafe {
1510 BNUndefineDataVariable(self.handle, addr, blacklist.unwrap_or(true));
1511 }
1512 }
1513
1514 pub fn undefine_user_data_var(&self, addr: u64) {
1515 unsafe {
1516 BNUndefineUserDataVariable(self.handle, addr);
1517 }
1518 }
1519
1520 pub fn define_auto_type<T: Into<QualifiedName>>(
1521 &self,
1522 name: T,
1523 source: &str,
1524 type_obj: &Type,
1525 ) -> QualifiedName {
1526 let mut raw_name = QualifiedName::into_raw(name.into());
1527 let source_str = source.to_cstr();
1528 let name_handle = unsafe {
1529 let id_str =
1530 BNGenerateAutoTypeId(source_str.as_ref().as_ptr() as *const _, &mut raw_name);
1531 let name_handle =
1532 BNDefineAnalysisType(self.handle, id_str, &mut raw_name, type_obj.handle);
1533 BNFreeString(id_str);
1534 name_handle
1535 };
1536 QualifiedName::free_raw(raw_name);
1537 QualifiedName::from_owned_raw(name_handle)
1538 }
1539
1540 pub fn define_auto_type_with_id<T: Into<QualifiedName>>(
1541 &self,
1542 name: T,
1543 id: &str,
1544 type_obj: &Type,
1545 ) -> QualifiedName {
1546 let mut raw_name = QualifiedName::into_raw(name.into());
1547 let id_str = id.to_cstr();
1548 let result_raw_name = unsafe {
1549 BNDefineAnalysisType(
1550 self.handle,
1551 id_str.as_ref().as_ptr() as *const _,
1552 &mut raw_name,
1553 type_obj.handle,
1554 )
1555 };
1556 QualifiedName::free_raw(raw_name);
1557 QualifiedName::from_owned_raw(result_raw_name)
1558 }
1559
1560 pub fn define_user_type<T: Into<QualifiedName>>(&self, name: T, type_obj: &Type) {
1561 let mut raw_name = QualifiedName::into_raw(name.into());
1562 unsafe { BNDefineUserAnalysisType(self.handle, &mut raw_name, type_obj.handle) }
1563 QualifiedName::free_raw(raw_name);
1564 }
1565
1566 pub fn define_auto_types<T, I>(
1567 &self,
1568 names_sources_and_types: T,
1569 ) -> HashMap<String, QualifiedName>
1570 where
1571 T: Iterator<Item = I>,
1572 I: Into<QualifiedNameTypeAndId>,
1573 {
1574 self.define_auto_types_with_progress(names_sources_and_types, NoProgressCallback)
1575 }
1576
1577 pub fn define_auto_types_with_progress<T, I, P>(
1578 &self,
1579 names_sources_and_types: T,
1580 mut progress: P,
1581 ) -> HashMap<String, QualifiedName>
1582 where
1583 T: Iterator<Item = I>,
1584 I: Into<QualifiedNameTypeAndId>,
1585 P: ProgressCallback,
1586 {
1587 let mut types: Vec<BNQualifiedNameTypeAndId> = names_sources_and_types
1588 .map(Into::into)
1589 .map(QualifiedNameTypeAndId::into_raw)
1590 .collect();
1591 let mut result_ids: *mut *mut c_char = std::ptr::null_mut();
1592 let mut result_names: *mut BNQualifiedName = std::ptr::null_mut();
1593
1594 let result_count = unsafe {
1595 BNDefineAnalysisTypes(
1596 self.handle,
1597 types.as_mut_ptr(),
1598 types.len(),
1599 Some(P::cb_progress_callback),
1600 &mut progress as *mut P as *mut c_void,
1601 &mut result_ids as *mut _,
1602 &mut result_names as *mut _,
1603 )
1604 };
1605
1606 for ty in types {
1607 QualifiedNameTypeAndId::free_raw(ty);
1608 }
1609
1610 let id_array = unsafe { Array::<BnString>::new(result_ids, result_count, ()) };
1611 let name_array = unsafe { Array::<QualifiedName>::new(result_names, result_count, ()) };
1612 id_array
1613 .into_iter()
1614 .zip(&name_array)
1615 .map(|(id, name)| (id.to_owned(), name))
1616 .collect()
1617 }
1618
1619 pub fn define_user_types<T, I>(&self, names_and_types: T)
1620 where
1621 T: Iterator<Item = I>,
1622 I: Into<QualifiedNameAndType>,
1623 {
1624 self.define_user_types_with_progress(names_and_types, NoProgressCallback);
1625 }
1626
1627 pub fn define_user_types_with_progress<T, I, P>(&self, names_and_types: T, mut progress: P)
1628 where
1629 T: Iterator<Item = I>,
1630 I: Into<QualifiedNameAndType>,
1631 P: ProgressCallback,
1632 {
1633 let mut types: Vec<BNQualifiedNameAndType> = names_and_types
1634 .map(Into::into)
1635 .map(QualifiedNameAndType::into_raw)
1636 .collect();
1637
1638 unsafe {
1639 BNDefineUserAnalysisTypes(
1640 self.handle,
1641 types.as_mut_ptr(),
1642 types.len(),
1643 Some(P::cb_progress_callback),
1644 &mut progress as *mut P as *mut c_void,
1645 )
1646 };
1647
1648 for ty in types {
1649 QualifiedNameAndType::free_raw(ty);
1650 }
1651 }
1652
1653 pub fn undefine_auto_type(&self, id: &str) {
1654 let id_str = id.to_cstr();
1655 unsafe {
1656 BNUndefineAnalysisType(self.handle, id_str.as_ref().as_ptr() as *const _);
1657 }
1658 }
1659
1660 pub fn undefine_user_type<T: Into<QualifiedName>>(&self, name: T) {
1661 let mut raw_name = QualifiedName::into_raw(name.into());
1662 unsafe { BNUndefineUserAnalysisType(self.handle, &mut raw_name) }
1663 QualifiedName::free_raw(raw_name);
1664 }
1665
1666 pub fn types(&self) -> Array<QualifiedNameAndType> {
1667 unsafe {
1668 let mut count = 0usize;
1669 let types = BNGetAnalysisTypeList(self.handle, &mut count);
1670 Array::new(types, count, ())
1671 }
1672 }
1673
1674 pub fn dependency_sorted_types(&self) -> Array<QualifiedNameAndType> {
1675 unsafe {
1676 let mut count = 0usize;
1677 let types = BNGetAnalysisDependencySortedTypeList(self.handle, &mut count);
1678 Array::new(types, count, ())
1679 }
1680 }
1681
1682 pub fn type_by_name<T: Into<QualifiedName>>(&self, name: T) -> Option<Ref<Type>> {
1683 let mut raw_name = QualifiedName::into_raw(name.into());
1684 unsafe {
1685 let type_handle = BNGetAnalysisTypeByName(self.handle, &mut raw_name);
1686 QualifiedName::free_raw(raw_name);
1687 if type_handle.is_null() {
1688 return None;
1689 }
1690 Some(Type::ref_from_raw(type_handle))
1691 }
1692 }
1693
1694 pub fn type_by_ref(&self, ref_: &NamedTypeReference) -> Option<Ref<Type>> {
1695 unsafe {
1696 let type_handle = BNGetAnalysisTypeByRef(self.handle, ref_.handle);
1697 if type_handle.is_null() {
1698 return None;
1699 }
1700 Some(Type::ref_from_raw(type_handle))
1701 }
1702 }
1703
1704 pub fn type_by_id(&self, id: &str) -> Option<Ref<Type>> {
1705 let id_str = id.to_cstr();
1706 unsafe {
1707 let type_handle = BNGetAnalysisTypeById(self.handle, id_str.as_ptr());
1708 if type_handle.is_null() {
1709 return None;
1710 }
1711 Some(Type::ref_from_raw(type_handle))
1712 }
1713 }
1714
1715 pub fn type_name_by_id(&self, id: &str) -> Option<QualifiedName> {
1716 let id_str = id.to_cstr();
1717 unsafe {
1718 let name_handle = BNGetAnalysisTypeNameById(self.handle, id_str.as_ptr());
1719 let name = QualifiedName::from_owned_raw(name_handle);
1720 match name.items.is_empty() {
1722 true => None,
1723 false => Some(name),
1724 }
1725 }
1726 }
1727
1728 pub fn type_id_by_name<T: Into<QualifiedName>>(&self, name: T) -> Option<String> {
1729 let mut raw_name = QualifiedName::into_raw(name.into());
1730 unsafe {
1731 let id_cstr = BNGetAnalysisTypeId(self.handle, &mut raw_name);
1732 QualifiedName::free_raw(raw_name);
1733 let id = BnString::into_string(id_cstr);
1734 match id.is_empty() {
1735 true => None,
1736 false => Some(id),
1737 }
1738 }
1739 }
1740
1741 pub fn is_type_auto_defined<T: Into<QualifiedName>>(&self, name: T) -> bool {
1742 let mut raw_name = QualifiedName::into_raw(name.into());
1743 let result = unsafe { BNIsAnalysisTypeAutoDefined(self.handle, &mut raw_name) };
1744 QualifiedName::free_raw(raw_name);
1745 result
1746 }
1747
1748 pub fn segments(&self) -> Array<Segment> {
1749 unsafe {
1750 let mut count = 0;
1751 let raw_segments = BNGetSegments(self.handle, &mut count);
1752 Array::new(raw_segments, count, ())
1753 }
1754 }
1755
1756 pub fn segment_at(&self, addr: u64) -> Option<Ref<Segment>> {
1757 unsafe {
1758 let raw_seg = BNGetSegmentAt(self.handle, addr);
1759 match raw_seg.is_null() {
1760 false => Some(Segment::ref_from_raw(raw_seg)),
1761 true => None,
1762 }
1763 }
1764 }
1765
1766 pub fn add_segment(&self, segment: SegmentBuilder) {
1771 segment.create(self.as_ref());
1772 }
1773
1774 pub fn begin_bulk_add_segments(&self) {
1785 unsafe { BNBeginBulkAddSegments(self.handle) }
1786 }
1787
1788 pub fn end_bulk_add_segments(&self) {
1794 unsafe { BNEndBulkAddSegments(self.handle) }
1795 }
1796
1797 pub fn cancel_bulk_add_segments(&self) {
1805 unsafe { BNCancelBulkAddSegments(self.handle) }
1806 }
1807
1808 pub fn add_section(&self, section: SectionBuilder) {
1809 section.create(self.as_ref());
1810 }
1811
1812 pub fn remove_auto_section(&self, name: impl IntoCStr) {
1813 let raw_name = name.to_cstr();
1814 let raw_name_ptr = raw_name.as_ptr();
1815 unsafe {
1816 BNRemoveAutoSection(self.handle, raw_name_ptr);
1817 }
1818 }
1819
1820 pub fn remove_user_section(&self, name: impl IntoCStr) {
1821 let raw_name = name.to_cstr();
1822 let raw_name_ptr = raw_name.as_ptr();
1823 unsafe {
1824 BNRemoveUserSection(self.handle, raw_name_ptr);
1825 }
1826 }
1827
1828 pub fn section_by_name(&self, name: impl IntoCStr) -> Option<Ref<Section>> {
1829 unsafe {
1830 let raw_name = name.to_cstr();
1831 let name_ptr = raw_name.as_ptr();
1832 let raw_section_ptr = BNGetSectionByName(self.handle, name_ptr);
1833 match raw_section_ptr.is_null() {
1834 false => Some(Section::ref_from_raw(raw_section_ptr)),
1835 true => None,
1836 }
1837 }
1838 }
1839
1840 pub fn sections(&self) -> Array<Section> {
1841 unsafe {
1842 let mut count = 0;
1843 let sections = BNGetSections(self.handle, &mut count);
1844 Array::new(sections, count, ())
1845 }
1846 }
1847
1848 pub fn sections_at(&self, addr: u64) -> Array<Section> {
1849 unsafe {
1850 let mut count = 0;
1851 let sections = BNGetSectionsAt(self.handle, addr, &mut count);
1852 Array::new(sections, count, ())
1853 }
1854 }
1855
1856 pub fn memory_map(&self) -> MemoryMap {
1857 MemoryMap::new(self.as_ref().to_owned())
1858 }
1859
1860 pub fn add_auto_function(&self, address: u64) -> Option<Ref<Function>> {
1866 let platform = self.default_platform()?;
1867 self.add_auto_function_with_platform(address, &platform)
1868 }
1869
1870 pub fn add_auto_function_with_platform(
1876 &self,
1877 address: u64,
1878 platform: &Platform,
1879 ) -> Option<Ref<Function>> {
1880 self.add_auto_function_ext(address, platform, None, false)
1881 }
1882
1883 pub fn add_auto_function_ext(
1891 &self,
1892 address: u64,
1893 platform: &Platform,
1894 func_type: Option<&Type>,
1895 auto_discovered: bool,
1896 ) -> Option<Ref<Function>> {
1897 unsafe {
1898 let func_type = match func_type {
1899 Some(func_type) => func_type.handle,
1900 None => std::ptr::null_mut(),
1901 };
1902
1903 let handle = BNAddFunctionForAnalysis(
1904 self.handle,
1905 platform.handle,
1906 address,
1907 auto_discovered,
1908 func_type,
1909 );
1910
1911 if handle.is_null() {
1912 return None;
1913 }
1914
1915 Some(Function::ref_from_raw(handle))
1916 }
1917 }
1918
1919 pub fn remove_auto_function(&self, func: &Function, update_refs: bool) {
1927 unsafe {
1928 BNRemoveAnalysisFunction(self.handle, func.handle, update_refs);
1929 }
1930 }
1931
1932 pub fn add_user_function(&self, addr: u64) -> Option<Ref<Function>> {
1938 let platform = self.default_platform()?;
1939 self.add_user_function_with_platform(addr, &platform)
1940 }
1941
1942 pub fn add_user_function_with_platform(
1946 &self,
1947 addr: u64,
1948 platform: &Platform,
1949 ) -> Option<Ref<Function>> {
1950 unsafe {
1951 let func = BNCreateUserFunction(self.handle, platform.handle, addr);
1952 if func.is_null() {
1953 return None;
1954 }
1955 Some(Function::ref_from_raw(func))
1956 }
1957 }
1958
1959 pub fn remove_user_function(&self, func: &Function) {
1963 unsafe { BNRemoveUserFunction(self.handle, func.handle) }
1964 }
1965
1966 pub fn has_functions(&self) -> bool {
1967 unsafe { BNHasFunctions(self.handle) }
1968 }
1969
1970 pub fn add_entry_point(&self, addr: u64) {
1974 if let Some(platform) = self.default_platform() {
1975 self.add_entry_point_with_platform(addr, &platform);
1976 }
1977 }
1978
1979 pub fn add_entry_point_with_platform(&self, addr: u64, platform: &Platform) {
1983 unsafe {
1984 BNAddEntryPointForAnalysis(self.handle, platform.handle, addr);
1985 }
1986 }
1987
1988 pub fn entry_point_function(&self) -> Option<Ref<Function>> {
1989 unsafe {
1990 let raw_func_ptr = BNGetAnalysisEntryPoint(self.handle);
1991 match raw_func_ptr.is_null() {
1992 false => Some(Function::ref_from_raw(raw_func_ptr)),
1993 true => None,
1994 }
1995 }
1996 }
1997
1998 pub fn entry_point_functions(&self) -> Array<Function> {
2004 unsafe {
2005 let mut count = 0;
2006 let functions = BNGetAllEntryFunctions(self.handle, &mut count);
2007
2008 Array::new(functions, count, ())
2009 }
2010 }
2011
2012 pub fn functions(&self) -> Array<Function> {
2013 unsafe {
2014 let mut count = 0;
2015 let functions = BNGetAnalysisFunctionList(self.handle, &mut count);
2016
2017 Array::new(functions, count, ())
2018 }
2019 }
2020
2021 pub fn functions_at(&self, addr: u64) -> Array<Function> {
2023 unsafe {
2024 let mut count = 0;
2025 let functions = BNGetAnalysisFunctionsForAddress(self.handle, addr, &mut count);
2026
2027 Array::new(functions, count, ())
2028 }
2029 }
2030
2031 pub fn functions_containing(&self, addr: u64) -> Array<Function> {
2033 unsafe {
2034 let mut count = 0;
2035 let functions = BNGetAnalysisFunctionsContainingAddress(self.handle, addr, &mut count);
2036
2037 Array::new(functions, count, ())
2038 }
2039 }
2040
2041 pub fn functions_by_name(
2051 &self,
2052 name: impl IntoCStr,
2053 plat: Option<&Platform>,
2054 ) -> Vec<Ref<Function>> {
2055 let name = name.to_cstr();
2056 let symbols = self.symbols_by_name(&*name);
2057 let mut addresses: Vec<u64> = symbols.into_iter().map(|s| s.address()).collect();
2058 if addresses.is_empty() && name.to_bytes().starts_with(b"sub_") {
2059 if let Ok(str) = name.to_str() {
2060 if let Ok(address) = u64::from_str_radix(&str[4..], 16) {
2061 addresses.push(address);
2062 }
2063 }
2064 }
2065
2066 let mut functions = Vec::new();
2067
2068 for address in addresses {
2069 let funcs = self.functions_at(address);
2070 for func in funcs.into_iter() {
2071 if func.start() == address && plat.is_none_or(|p| p == func.platform().as_ref()) {
2072 functions.push(func.clone());
2073 }
2074 }
2075 }
2076
2077 functions
2078 }
2079
2080 pub fn function_at(&self, platform: &Platform, addr: u64) -> Option<Ref<Function>> {
2081 unsafe {
2082 let raw_func_ptr = BNGetAnalysisFunction(self.handle, platform.handle, addr);
2083 match raw_func_ptr.is_null() {
2084 false => Some(Function::ref_from_raw(raw_func_ptr)),
2085 true => None,
2086 }
2087 }
2088 }
2089
2090 pub fn function_start_before(&self, addr: u64) -> u64 {
2091 unsafe { BNGetPreviousFunctionStartBeforeAddress(self.handle, addr) }
2092 }
2093
2094 pub fn function_start_after(&self, addr: u64) -> u64 {
2095 unsafe { BNGetNextFunctionStartAfterAddress(self.handle, addr) }
2096 }
2097
2098 pub fn basic_blocks_containing(&self, addr: u64) -> Array<BasicBlock<NativeBlock>> {
2099 unsafe {
2100 let mut count = 0;
2101 let blocks = BNGetBasicBlocksForAddress(self.handle, addr, &mut count);
2102 Array::new(blocks, count, NativeBlock::new())
2103 }
2104 }
2105
2106 pub fn basic_blocks_starting_at(&self, addr: u64) -> Array<BasicBlock<NativeBlock>> {
2107 unsafe {
2108 let mut count = 0;
2109 let blocks = BNGetBasicBlocksStartingAtAddress(self.handle, addr, &mut count);
2110 Array::new(blocks, count, NativeBlock::new())
2111 }
2112 }
2113
2114 pub fn is_new_auto_function_analysis_suppressed(&self) -> bool {
2115 unsafe { BNGetNewAutoFunctionAnalysisSuppressed(self.handle) }
2116 }
2117
2118 pub fn set_new_auto_function_analysis_suppressed(&self, suppress: bool) {
2119 unsafe {
2120 BNSetNewAutoFunctionAnalysisSuppressed(self.handle, suppress);
2121 }
2122 }
2123
2124 pub fn should_skip_target_analysis(
2126 &self,
2127 src_loc: impl Into<Location>,
2128 src_func: &Function,
2129 src_end: u64,
2130 target: impl Into<Location>,
2131 ) -> bool {
2132 let src_loc = src_loc.into();
2133 let target = target.into();
2134 unsafe {
2135 BNShouldSkipTargetAnalysis(
2136 self.handle,
2137 &mut src_loc.into(),
2138 src_func.handle,
2139 src_end,
2140 &mut target.into(),
2141 )
2142 }
2143 }
2144
2145 pub fn read_buffer(&self, offset: u64, len: usize) -> Option<DataBuffer> {
2146 let read_buffer = unsafe { BNReadViewBuffer(self.handle, offset, len) };
2147 if read_buffer.is_null() {
2148 None
2149 } else {
2150 Some(DataBuffer::from_raw(read_buffer))
2151 }
2152 }
2153
2154 pub fn debug_info(&self) -> Ref<DebugInfo> {
2155 unsafe { DebugInfo::ref_from_raw(BNGetDebugInfo(self.handle)) }
2156 }
2157
2158 pub fn set_debug_info(&self, debug_info: &DebugInfo) {
2159 unsafe { BNSetDebugInfo(self.handle, debug_info.handle) }
2160 }
2161
2162 pub fn apply_debug_info(&self, debug_info: &DebugInfo) {
2163 unsafe { BNApplyDebugInfo(self.handle, debug_info.handle) }
2164 }
2165
2166 pub fn show_plaintext_report(&self, title: &str, plaintext: &str) {
2167 let title = title.to_cstr();
2168 let plaintext = plaintext.to_cstr();
2169 unsafe {
2170 BNShowPlainTextReport(
2171 self.handle,
2172 title.as_ref().as_ptr() as *mut _,
2173 plaintext.as_ref().as_ptr() as *mut _,
2174 )
2175 }
2176 }
2177
2178 pub fn show_markdown_report(&self, title: &str, contents: &str, plaintext: &str) {
2179 let title = title.to_cstr();
2180 let contents = contents.to_cstr();
2181 let plaintext = plaintext.to_cstr();
2182 unsafe {
2183 BNShowMarkdownReport(
2184 self.handle,
2185 title.as_ref().as_ptr() as *mut _,
2186 contents.as_ref().as_ptr() as *mut _,
2187 plaintext.as_ref().as_ptr() as *mut _,
2188 )
2189 }
2190 }
2191
2192 pub fn show_html_report(&self, title: &str, contents: &str, plaintext: &str) {
2193 let title = title.to_cstr();
2194 let contents = contents.to_cstr();
2195 let plaintext = plaintext.to_cstr();
2196 unsafe {
2197 BNShowHTMLReport(
2198 self.handle,
2199 title.as_ref().as_ptr() as *mut _,
2200 contents.as_ref().as_ptr() as *mut _,
2201 plaintext.as_ref().as_ptr() as *mut _,
2202 )
2203 }
2204 }
2205
2206 pub fn show_graph_report(&self, raw_name: &str, graph: &FlowGraph) {
2207 let raw_name = raw_name.to_cstr();
2208 unsafe {
2209 BNShowGraphReport(self.handle, raw_name.as_ptr(), graph.handle);
2210 }
2211 }
2212
2213 pub fn load_settings(&self, view_type_name: &str) -> Option<Ref<Settings>> {
2214 let view_type_name = view_type_name.to_cstr();
2215 let settings_handle =
2216 unsafe { BNBinaryViewGetLoadSettings(self.handle, view_type_name.as_ptr()) };
2217 match settings_handle.is_null() {
2218 true => None,
2219 false => Some(unsafe { Settings::ref_from_raw(settings_handle) }),
2220 }
2221 }
2222
2223 pub fn set_load_settings(&self, view_type_name: &str, settings: &Settings) {
2224 let view_type_name = view_type_name.to_cstr();
2225
2226 unsafe {
2227 BNBinaryViewSetLoadSettings(self.handle, view_type_name.as_ptr(), settings.handle)
2228 };
2229 }
2230
2231 pub fn create_tag_type(&self, name: &str, icon: &str) -> Ref<TagType> {
2237 let tag_type = TagType::create(self, name, icon);
2238 unsafe {
2239 BNAddTagType(self.handle, tag_type.handle);
2240 }
2241 tag_type
2242 }
2243
2244 pub fn remove_tag_type(&self, tag_type: &TagType) {
2246 unsafe { BNRemoveTagType(self.handle, tag_type.handle) }
2247 }
2248
2249 pub fn tag_type_by_name(&self, name: &str) -> Option<Ref<TagType>> {
2251 let name = name.to_cstr();
2252 unsafe {
2253 let handle = BNGetTagType(self.handle, name.as_ptr());
2254 if handle.is_null() {
2255 return None;
2256 }
2257 Some(TagType::ref_from_raw(handle))
2258 }
2259 }
2260
2261 pub fn tags_all_scopes(&self) -> Array<TagReference> {
2263 let mut count = 0;
2264 unsafe {
2265 let tag_references = BNGetAllTagReferences(self.handle, &mut count);
2266 Array::new(tag_references, count, ())
2267 }
2268 }
2269
2270 pub fn tag_types(&self) -> Array<TagType> {
2272 let mut count = 0;
2273 unsafe {
2274 let tag_types_raw = BNGetTagTypes(self.handle, &mut count);
2275 Array::new(tag_types_raw, count, ())
2276 }
2277 }
2278
2279 pub fn tags_by_type(&self, tag_type: &TagType) -> Array<TagReference> {
2281 let mut count = 0;
2282 unsafe {
2283 let tag_references =
2284 BNGetAllTagReferencesOfType(self.handle, tag_type.handle, &mut count);
2285 Array::new(tag_references, count, ())
2286 }
2287 }
2288
2289 pub fn tag_by_id(&self, id: &str) -> Option<Ref<Tag>> {
2293 let id = id.to_cstr();
2294 unsafe {
2295 let handle = BNGetTag(self.handle, id.as_ptr());
2296 if handle.is_null() {
2297 return None;
2298 }
2299 Some(Tag::ref_from_raw(handle))
2300 }
2301 }
2302
2303 pub fn add_tag(&self, addr: u64, t: &TagType, data: &str, user: bool) {
2307 let tag = Tag::new(t, data);
2308
2309 unsafe { BNAddTag(self.handle, tag.handle, user) }
2310
2311 if user {
2312 unsafe { BNAddUserDataTag(self.handle, addr, tag.handle) }
2313 } else {
2314 unsafe { BNAddAutoDataTag(self.handle, addr, tag.handle) }
2315 }
2316 }
2317
2318 pub fn remove_auto_data_tag(&self, addr: u64, tag: &Tag) {
2320 unsafe { BNRemoveAutoDataTag(self.handle, addr, tag.handle) }
2321 }
2322
2323 pub fn remove_user_data_tag(&self, addr: u64, tag: &Tag) {
2326 unsafe { BNRemoveUserDataTag(self.handle, addr, tag.handle) }
2327 }
2328
2329 pub fn comment_references(&self) -> Array<CommentReference> {
2335 let mut count = 0;
2336 let addresses_raw = unsafe { BNGetGlobalCommentedAddresses(self.handle, &mut count) };
2337 unsafe { Array::new(addresses_raw, count, ()) }
2338 }
2339
2340 pub fn comments(&self) -> BTreeMap<u64, String> {
2345 self.comment_references()
2346 .iter()
2347 .filter_map(|cmt_ref| Some((cmt_ref.start, self.comment_at(cmt_ref.start)?)))
2348 .collect()
2349 }
2350
2351 pub fn comment_at(&self, addr: u64) -> Option<String> {
2352 unsafe {
2353 let comment_raw = BNGetGlobalCommentForAddress(self.handle, addr);
2354 match comment_raw.is_null() {
2355 false => Some(BnString::into_string(comment_raw)),
2356 true => None,
2357 }
2358 }
2359 }
2360
2361 pub fn set_comment_at(&self, addr: u64, comment: &str) {
2366 let comment_raw = comment.to_cstr();
2367 unsafe { BNSetGlobalCommentForAddress(self.handle, addr, comment_raw.as_ptr()) }
2368 }
2369
2370 pub fn get_next_linear_disassembly_lines(
2379 &self,
2380 pos: &mut LinearViewCursor,
2381 ) -> Array<LinearDisassemblyLine> {
2382 let mut result = unsafe { Array::new(std::ptr::null_mut(), 0, ()) };
2383
2384 while result.is_empty() {
2385 result = pos.lines();
2386 if !pos.next() {
2387 return result;
2388 }
2389 }
2390
2391 result
2392 }
2393
2394 pub fn get_previous_linear_disassembly_lines(
2403 &self,
2404 pos: &mut LinearViewCursor,
2405 ) -> Array<LinearDisassemblyLine> {
2406 let mut result = unsafe { Array::new(std::ptr::null_mut(), 0, ()) };
2407 while result.is_empty() {
2408 if !pos.previous() {
2409 return result;
2410 }
2411
2412 result = pos.lines();
2413 }
2414
2415 result
2416 }
2417
2418 pub fn query_metadata(&self, key: &str) -> Option<Ref<Metadata>> {
2419 let key = key.to_cstr();
2420 let value: *mut BNMetadata =
2421 unsafe { BNBinaryViewQueryMetadata(self.handle, key.as_ptr()) };
2422 if value.is_null() {
2423 None
2424 } else {
2425 Some(unsafe { Metadata::ref_from_raw(value) })
2426 }
2427 }
2428
2429 pub fn get_metadata<T>(&self, key: &str) -> Option<T>
2433 where
2434 T: for<'a> TryFrom<&'a Metadata>,
2435 {
2436 self.query_metadata(key)
2437 .and_then(|md| T::try_from(md.as_ref()).ok())
2438 }
2439
2440 pub fn store_metadata<V>(&self, key: &str, value: V, flags: MetadataStoreFlags)
2441 where
2442 V: Into<Ref<Metadata>>,
2443 {
2444 let md = value.into();
2445 let key = key.to_cstr();
2446 unsafe {
2447 BNBinaryViewStoreMetadata(
2448 self.handle,
2449 key.as_ptr(),
2450 md.as_ref().handle,
2451 flags.into_raw(),
2452 )
2453 };
2454 }
2455
2456 pub fn remove_metadata(&self, key: &str) {
2457 let key = key.to_cstr();
2458 unsafe { BNBinaryViewRemoveMetadata(self.handle, key.as_ptr()) };
2459 }
2460
2461 pub fn code_refs_to_addr(&self, addr: u64) -> Array<CodeReference> {
2463 unsafe {
2464 let mut count = 0;
2465 let handle = BNGetCodeReferences(self.handle, addr, &mut count, false, 0);
2466 Array::new(handle, count, ())
2467 }
2468 }
2469
2470 pub fn code_refs_into_range(&self, range: Range<u64>) -> Array<CodeReference> {
2472 unsafe {
2473 let mut count = 0;
2474 let handle = BNGetCodeReferencesInRange(
2475 self.handle,
2476 range.start,
2477 range.end - range.start,
2478 &mut count,
2479 false,
2480 0,
2481 );
2482 Array::new(handle, count, ())
2483 }
2484 }
2485
2486 pub fn incoming_code_refs(&self, range: Range<u64>) -> Array<CodeXref> {
2488 unsafe {
2489 let mut count = 0;
2490 let handle = BNGetIncomingCodeReferences(
2491 self.handle,
2492 range.start,
2493 range.end - range.start,
2494 &mut count,
2495 false,
2496 0,
2497 );
2498 Array::new(handle, count, ())
2499 }
2500 }
2501
2502 pub fn code_refs_from_addr(&self, addr: u64, func: Option<&Function>) -> Vec<u64> {
2504 unsafe {
2505 let mut count = 0;
2506 let code_ref =
2507 CodeReference::new(addr, func.map(|f| f.to_owned()), func.map(|f| f.arch()));
2508 let mut raw_code_ref = CodeReference::into_owned_raw(&code_ref);
2509 let addresses = BNGetCodeReferencesFrom(self.handle, &mut raw_code_ref, &mut count);
2510 let res = std::slice::from_raw_parts(addresses, count).to_vec();
2511 BNFreeAddressList(addresses);
2512 res
2513 }
2514 }
2515
2516 pub fn outgoing_code_refs(
2521 &self,
2522 range: Range<u64>,
2523 func: Option<&Function>,
2524 ) -> Array<CodeXref> {
2525 unsafe {
2526 let mut count = 0;
2527 let handle = BNGetOutgoingCodeReferences(
2528 self.handle,
2529 range.start,
2530 range.end - range.start,
2531 func.map(|f| f.handle).unwrap_or(std::ptr::null_mut()),
2532 &mut count,
2533 false,
2534 0,
2535 );
2536 Array::new(handle, count, ())
2537 }
2538 }
2539
2540 pub fn data_refs_to_addr(&self, addr: u64) -> Array<DataReference> {
2542 unsafe {
2543 let mut count = 0;
2544 let handle = BNGetDataReferences(self.handle, addr, &mut count, false, 0);
2545 Array::new(handle, count, ())
2546 }
2547 }
2548
2549 pub fn data_refs_into_range(&self, range: Range<u64>) -> Array<DataReference> {
2551 unsafe {
2552 let mut count = 0;
2553 let handle = BNGetDataReferencesInRange(
2554 self.handle,
2555 range.start,
2556 range.end - range.start,
2557 &mut count,
2558 false,
2559 0,
2560 );
2561 Array::new(handle, count, ())
2562 }
2563 }
2564
2565 pub fn incoming_data_refs(&self, range: Range<u64>) -> Array<DataXref> {
2567 unsafe {
2568 let mut count = 0;
2569 let handle = BNGetIncomingDataReferences(
2570 self.handle,
2571 range.start,
2572 range.end - range.start,
2573 &mut count,
2574 false,
2575 0,
2576 );
2577 Array::new(handle, count, ())
2578 }
2579 }
2580
2581 pub fn data_refs_from_addr(&self, addr: u64) -> Array<DataReference> {
2583 unsafe {
2584 let mut count = 0;
2585 let handle = BNGetDataReferencesFrom(self.handle, addr, &mut count);
2586 Array::new(handle, count, ())
2587 }
2588 }
2589
2590 pub fn outgoing_data_refs(&self, range: Range<u64>) -> Array<DataXref> {
2592 unsafe {
2593 let mut count = 0;
2594 let handle = BNGetOutgoingDataReferences(
2595 self.handle,
2596 range.start,
2597 range.end - range.start,
2598 &mut count,
2599 false,
2600 0,
2601 );
2602 Array::new(handle, count, ())
2603 }
2604 }
2605
2606 pub fn code_refs_using_type_name<T: Into<QualifiedName>>(
2608 &self,
2609 name: T,
2610 ) -> Array<CodeReference> {
2611 let mut raw_name = QualifiedName::into_raw(name.into());
2612 unsafe {
2613 let mut count = 0;
2614 let handle =
2615 BNGetCodeReferencesForType(self.handle, &mut raw_name, &mut count, false, 0);
2616 QualifiedName::free_raw(raw_name);
2617 Array::new(handle, count, ())
2618 }
2619 }
2620
2621 pub fn data_refs_using_type_name<T: Into<QualifiedName>>(
2623 &self,
2624 name: T,
2625 ) -> Array<DataReference> {
2626 let mut raw_name = QualifiedName::into_raw(name.into());
2627 unsafe {
2628 let mut count = 0;
2629 let handle =
2630 BNGetDataReferencesForType(self.handle, &mut raw_name, &mut count, false, 0);
2631 QualifiedName::free_raw(raw_name);
2632 Array::new(handle, count, ())
2633 }
2634 }
2635
2636 pub fn relocations_at(&self, addr: u64) -> Array<Relocation> {
2637 unsafe {
2638 let mut count = 0;
2639 let handle = BNGetRelocationsAt(self.handle, addr, &mut count);
2640 Array::new(handle, count, ())
2641 }
2642 }
2643
2644 pub fn relocation_ranges(&self) -> Vec<Range<u64>> {
2645 let ranges = unsafe {
2646 let mut count = 0;
2647 let reloc_ranges_ptr = BNGetRelocationRanges(self.handle, &mut count);
2648 let ranges = std::slice::from_raw_parts(reloc_ranges_ptr, count).to_vec();
2649 BNFreeRelocationRanges(reloc_ranges_ptr);
2650 ranges
2651 };
2652
2653 ranges
2655 .iter()
2656 .map(|range| Range {
2657 start: range.start,
2658 end: range.end,
2659 })
2660 .collect()
2661 }
2662
2663 pub fn component_by_guid(&self, guid: &str) -> Option<Ref<Component>> {
2664 let name = guid.to_cstr();
2665 let result = unsafe { BNGetComponentByGuid(self.handle, name.as_ptr()) };
2666 NonNull::new(result).map(|h| unsafe { Component::ref_from_raw(h) })
2667 }
2668
2669 pub fn root_component(&self) -> Option<Ref<Component>> {
2670 let result = unsafe { BNGetRootComponent(self.handle) };
2671 NonNull::new(result).map(|h| unsafe { Component::ref_from_raw(h) })
2672 }
2673
2674 pub fn component_by_path(&self, path: &str) -> Option<Ref<Component>> {
2675 let path = path.to_cstr();
2676 let result = unsafe { BNGetComponentByPath(self.handle, path.as_ptr()) };
2677 NonNull::new(result).map(|h| unsafe { Component::ref_from_raw(h) })
2678 }
2679
2680 pub fn remove_component(&self, component: &Component) -> bool {
2681 unsafe { BNRemoveComponent(self.handle, component.handle.as_ptr()) }
2682 }
2683
2684 pub fn remove_component_by_guid(&self, guid: &str) -> bool {
2685 let path = guid.to_cstr();
2686 unsafe { BNRemoveComponentByGuid(self.handle, path.as_ptr()) }
2687 }
2688
2689 pub fn data_variable_parent_components(
2690 &self,
2691 data_variable: &DataVariable,
2692 ) -> Array<Component> {
2693 let mut count = 0;
2694 let result = unsafe {
2695 BNGetDataVariableParentComponents(self.handle, data_variable.address, &mut count)
2696 };
2697 unsafe { Array::new(result, count, ()) }
2698 }
2699
2700 pub fn external_libraries(&self) -> Array<ExternalLibrary> {
2701 let mut count = 0;
2702 let result = unsafe { BNBinaryViewGetExternalLibraries(self.handle, &mut count) };
2703 unsafe { Array::new(result, count, ()) }
2704 }
2705
2706 pub fn external_library(&self, name: &str) -> Option<Ref<ExternalLibrary>> {
2707 let name_ptr = name.to_cstr();
2708 let result = unsafe { BNBinaryViewGetExternalLibrary(self.handle, name_ptr.as_ptr()) };
2709 let result_ptr = NonNull::new(result)?;
2710 Some(unsafe { ExternalLibrary::ref_from_raw(result_ptr) })
2711 }
2712
2713 pub fn remove_external_library(&self, name: &str) {
2714 let name_ptr = name.to_cstr();
2715 unsafe { BNBinaryViewRemoveExternalLibrary(self.handle, name_ptr.as_ptr()) };
2716 }
2717
2718 pub fn add_external_library(
2719 &self,
2720 name: &str,
2721 backing_file: Option<&ProjectFile>,
2722 auto: bool,
2723 ) -> Option<Ref<ExternalLibrary>> {
2724 let name_ptr = name.to_cstr();
2725 let result = unsafe {
2726 BNBinaryViewAddExternalLibrary(
2727 self.handle,
2728 name_ptr.as_ptr(),
2729 backing_file
2730 .map(|b| b.handle.as_ptr())
2731 .unwrap_or(std::ptr::null_mut()),
2732 auto,
2733 )
2734 };
2735 NonNull::new(result).map(|h| unsafe { ExternalLibrary::ref_from_raw(h) })
2736 }
2737
2738 pub fn external_locations(&self) -> Array<ExternalLocation> {
2739 let mut count = 0;
2740 let result = unsafe { BNBinaryViewGetExternalLocations(self.handle, &mut count) };
2741 unsafe { Array::new(result, count, ()) }
2742 }
2743
2744 pub fn external_location_from_symbol(&self, symbol: &Symbol) -> Option<Ref<ExternalLocation>> {
2745 let result = unsafe { BNBinaryViewGetExternalLocation(self.handle, symbol.handle) };
2746 let result_ptr = NonNull::new(result)?;
2747 Some(unsafe { ExternalLocation::ref_from_raw(result_ptr) })
2748 }
2749
2750 pub fn remove_external_location(&self, location: &ExternalLocation) {
2751 self.remove_external_location_from_symbol(&location.source_symbol())
2752 }
2753
2754 pub fn remove_external_location_from_symbol(&self, symbol: &Symbol) {
2755 unsafe { BNBinaryViewRemoveExternalLocation(self.handle, symbol.handle) };
2756 }
2757
2758 pub fn add_external_location(
2760 &self,
2761 symbol: &Symbol,
2762 library: &ExternalLibrary,
2763 target_symbol_name: &str,
2764 target_address: Option<u64>,
2765 target_is_auto: bool,
2766 ) -> Option<Ref<ExternalLocation>> {
2767 let target_symbol_name = target_symbol_name.to_cstr();
2768 let target_address_ptr = target_address
2769 .map(|a| a as *mut u64)
2770 .unwrap_or(std::ptr::null_mut());
2771 let result = unsafe {
2772 BNBinaryViewAddExternalLocation(
2773 self.handle,
2774 symbol.handle,
2775 library.handle.as_ptr(),
2776 target_symbol_name.as_ptr(),
2777 target_address_ptr,
2778 target_is_auto,
2779 )
2780 };
2781 NonNull::new(result).map(|h| unsafe { ExternalLocation::ref_from_raw(h) })
2782 }
2783
2784 pub fn type_container(&self) -> TypeContainer {
2788 let type_container_ptr = NonNull::new(unsafe { BNGetAnalysisTypeContainer(self.handle) });
2789 unsafe { TypeContainer::from_raw(type_container_ptr.unwrap()) }
2791 }
2792
2793 pub fn user_type_container(&self) -> TypeContainer {
2795 let type_container_ptr =
2796 NonNull::new(unsafe { BNGetAnalysisUserTypeContainer(self.handle) });
2797 unsafe { TypeContainer::from_raw(type_container_ptr.unwrap()) }.clone()
2799 }
2800
2801 pub fn auto_type_container(&self) -> TypeContainer {
2805 let type_container_ptr =
2806 NonNull::new(unsafe { BNGetAnalysisAutoTypeContainer(self.handle) });
2807 unsafe { TypeContainer::from_raw(type_container_ptr.unwrap()) }
2809 }
2810
2811 pub fn type_libraries(&self) -> Array<TypeLibrary> {
2812 let mut count = 0;
2813 let result = unsafe { BNGetBinaryViewTypeLibraries(self.handle, &mut count) };
2814 unsafe { Array::new(result, count, ()) }
2815 }
2816
2817 pub fn add_type_library(&self, library: &TypeLibrary) {
2819 unsafe { BNAddBinaryViewTypeLibrary(self.handle, library.as_raw()) }
2820 }
2821
2822 pub fn type_library_by_name(&self, name: &str) -> Option<Ref<TypeLibrary>> {
2823 let name = name.to_cstr();
2824 let result = unsafe { BNGetBinaryViewTypeLibrary(self.handle, name.as_ptr()) };
2825 NonNull::new(result).map(|h| unsafe { TypeLibrary::ref_from_raw(h) })
2826 }
2827
2828 pub fn record_imported_object_library<T: Into<QualifiedName>>(
2837 &self,
2838 lib: &TypeLibrary,
2839 name: T,
2840 addr: u64,
2841 platform: &Platform,
2842 ) {
2843 let mut raw_name = QualifiedName::into_raw(name.into());
2844 unsafe {
2845 BNBinaryViewRecordImportedObjectLibrary(
2846 self.handle,
2847 platform.handle,
2848 addr,
2849 lib.as_raw(),
2850 &mut raw_name,
2851 )
2852 }
2853 QualifiedName::free_raw(raw_name);
2854 }
2855
2856 pub fn import_type_library_type<T: Into<QualifiedName>>(
2867 &self,
2868 name: T,
2869 lib: Option<&TypeLibrary>,
2870 ) -> Option<Ref<Type>> {
2871 let mut lib_ref = lib
2872 .as_ref()
2873 .map(|l| unsafe { l.as_raw() } as *mut _)
2874 .unwrap_or(std::ptr::null_mut());
2875 let mut raw_name = QualifiedName::into_raw(name.into());
2876 let result =
2877 unsafe { BNBinaryViewImportTypeLibraryType(self.handle, &mut lib_ref, &mut raw_name) };
2878 QualifiedName::free_raw(raw_name);
2879 if let Some(lib_ref) = NonNull::new(lib_ref) {
2881 drop(unsafe { TypeLibrary::ref_from_raw(lib_ref) });
2882 }
2883 (!result.is_null()).then(|| unsafe { Type::ref_from_raw(result) })
2884 }
2885
2886 pub fn import_type_library_object<T: Into<QualifiedName>>(
2897 &self,
2898 name: T,
2899 lib: Option<&TypeLibrary>,
2900 ) -> Option<Ref<Type>> {
2901 let mut lib_ref = lib
2902 .as_ref()
2903 .map(|l| unsafe { l.as_raw() } as *mut _)
2904 .unwrap_or(std::ptr::null_mut());
2905 let mut raw_name = QualifiedName::into_raw(name.into());
2906 let result = unsafe {
2907 BNBinaryViewImportTypeLibraryObject(self.handle, &mut lib_ref, &mut raw_name)
2908 };
2909 QualifiedName::free_raw(raw_name);
2910 if let Some(lib_ref) = NonNull::new(lib_ref) {
2912 drop(unsafe { TypeLibrary::ref_from_raw(lib_ref) });
2913 }
2914 (!result.is_null()).then(|| unsafe { Type::ref_from_raw(result) })
2915 }
2916
2917 pub fn import_type_by_guid(&self, guid: &str) -> Option<Ref<Type>> {
2919 let guid = guid.to_cstr();
2920 let result = unsafe { BNBinaryViewImportTypeLibraryTypeByGuid(self.handle, guid.as_ptr()) };
2921 (!result.is_null()).then(|| unsafe { Type::ref_from_raw(result) })
2922 }
2923
2924 pub fn export_type_to_library<T: Into<QualifiedName>>(
2929 &self,
2930 lib: &TypeLibrary,
2931 name: T,
2932 type_obj: &Type,
2933 ) {
2934 let mut raw_name = QualifiedName::into_raw(name.into());
2935 unsafe {
2936 BNBinaryViewExportTypeToTypeLibrary(
2937 self.handle,
2938 lib.as_raw(),
2939 &mut raw_name,
2940 type_obj.handle,
2941 )
2942 }
2943 QualifiedName::free_raw(raw_name);
2944 }
2945
2946 pub fn export_object_to_library<T: Into<QualifiedName>>(
2951 &self,
2952 lib: &TypeLibrary,
2953 name: T,
2954 type_obj: &Type,
2955 ) {
2956 let mut raw_name = QualifiedName::into_raw(name.into());
2957 unsafe {
2958 BNBinaryViewExportObjectToTypeLibrary(
2959 self.handle,
2960 lib.as_raw(),
2961 &mut raw_name,
2962 type_obj.handle,
2963 )
2964 }
2965 QualifiedName::free_raw(raw_name);
2966 }
2967
2968 pub fn lookup_imported_object_library(
2974 &self,
2975 addr: u64,
2976 platform: &Platform,
2977 ) -> Option<(Ref<TypeLibrary>, QualifiedName)> {
2978 let mut result_lib = std::ptr::null_mut();
2979 let mut result_name = BNQualifiedName::default();
2980 let success = unsafe {
2981 BNBinaryViewLookupImportedObjectLibrary(
2982 self.handle,
2983 platform.handle,
2984 addr,
2985 &mut result_lib,
2986 &mut result_name,
2987 )
2988 };
2989 if !success {
2990 return None;
2991 }
2992 let lib = unsafe { TypeLibrary::ref_from_raw(NonNull::new(result_lib)?) };
2993 let name = QualifiedName::from_owned_raw(result_name);
2994 Some((lib, name))
2995 }
2996
2997 pub fn lookup_imported_type_library<T: Into<QualifiedName>>(
3001 &self,
3002 name: T,
3003 ) -> Option<(Ref<TypeLibrary>, QualifiedName)> {
3004 let raw_name = QualifiedName::into_raw(name.into());
3005 let mut result_lib = std::ptr::null_mut();
3006 let mut result_name = BNQualifiedName::default();
3007 let success = unsafe {
3008 BNBinaryViewLookupImportedTypeLibrary(
3009 self.handle,
3010 &raw_name,
3011 &mut result_lib,
3012 &mut result_name,
3013 )
3014 };
3015 QualifiedName::free_raw(raw_name);
3016 if !success {
3017 return None;
3018 }
3019 let lib = unsafe { TypeLibrary::ref_from_raw(NonNull::new(result_lib)?) };
3020 let name = QualifiedName::from_owned_raw(result_name);
3021 Some((lib, name))
3022 }
3023
3024 pub fn strings(&self) -> Array<StringReference> {
3038 unsafe {
3039 let mut count = 0;
3040 let strings = BNGetStrings(self.handle, &mut count);
3041 Array::new(strings, count, ())
3042 }
3043 }
3044
3045 pub fn string_at(&self, addr: u64) -> Option<StringReference> {
3059 let mut str_ref = BNStringReference::default();
3060 let success = unsafe { BNGetStringAtAddress(self.handle, addr, &mut str_ref) };
3061 if success {
3062 Some(str_ref.into())
3063 } else {
3064 None
3065 }
3066 }
3067
3068 pub fn strings_in_range(&self, range: Range<u64>) -> Array<StringReference> {
3082 unsafe {
3083 let mut count = 0;
3084 let strings = BNGetStringsInRange(
3085 self.handle,
3086 range.start,
3087 range.end - range.start,
3088 &mut count,
3089 );
3090 Array::new(strings, count, ())
3091 }
3092 }
3093
3094 pub fn attached_type_archives(&self) -> Vec<TypeArchiveId> {
3098 let mut ids: *mut *mut c_char = std::ptr::null_mut();
3099 let mut paths: *mut *mut c_char = std::ptr::null_mut();
3100 let count = unsafe { BNBinaryViewGetTypeArchives(self.handle, &mut ids, &mut paths) };
3101 let _path_list = unsafe { Array::<BnString>::new(paths, count, ()) };
3105 let id_list = unsafe { Array::<BnString>::new(ids, count, ()) };
3106 id_list
3107 .into_iter()
3108 .map(|id| TypeArchiveId(id.to_string()))
3109 .collect()
3110 }
3111
3112 pub fn type_archive_by_id(&self, id: &TypeArchiveId) -> Option<Ref<TypeArchive>> {
3116 let id = id.0.as_str().to_cstr();
3117 let result = unsafe { BNBinaryViewGetTypeArchive(self.handle, id.as_ptr()) };
3118 let result_ptr = NonNull::new(result)?;
3119 Some(unsafe { TypeArchive::ref_from_raw(result_ptr) })
3120 }
3121
3122 pub fn type_archive_path_by_id(&self, id: &TypeArchiveId) -> Option<PathBuf> {
3124 let id = id.0.as_str().to_cstr();
3125 let result = unsafe { BNBinaryViewGetTypeArchivePath(self.handle, id.as_ptr()) };
3126 if result.is_null() {
3127 return None;
3128 }
3129 let path_str = unsafe { BnString::into_string(result) };
3130 Some(PathBuf::from(path_str))
3131 }
3132
3133 pub fn deref_return_value_named_type_references(
3134 &self,
3135 return_value: &ReturnValue,
3136 ) -> ReturnValue {
3137 ReturnValue {
3138 ty: Conf::new(
3139 return_value.ty.contents.deref_named_type_reference(self),
3140 return_value.ty.confidence,
3141 ),
3142 location: return_value.location.clone(),
3143 }
3144 }
3145
3146 pub fn deref_parameter_named_type_references(
3147 &self,
3148 params: &[FunctionParameter],
3149 ) -> Vec<FunctionParameter> {
3150 params
3151 .iter()
3152 .map(|param| FunctionParameter {
3153 ty: Conf::new(
3154 param.ty.contents.deref_named_type_reference(self),
3155 param.ty.confidence,
3156 ),
3157 name: param.name.clone(),
3158 location: param.location.clone(),
3159 })
3160 .collect()
3161 }
3162}
3163
3164impl BinaryViewBase for BinaryView {
3165 fn read(&self, buf: &mut [u8], offset: u64) -> usize {
3166 unsafe { BNReadViewData(self.handle, buf.as_mut_ptr() as *mut _, offset, buf.len()) }
3167 }
3168
3169 fn write(&self, offset: u64, data: &[u8]) -> usize {
3170 unsafe { BNWriteViewData(self.handle, offset, data.as_ptr() as *const _, data.len()) }
3171 }
3172
3173 fn insert(&self, offset: u64, data: &[u8]) -> usize {
3174 unsafe { BNInsertViewData(self.handle, offset, data.as_ptr() as *const _, data.len()) }
3175 }
3176
3177 fn remove(&self, offset: u64, len: usize) -> usize {
3178 unsafe { BNRemoveViewData(self.handle, offset, len as u64) }
3179 }
3180
3181 fn offset_valid(&self, offset: u64) -> bool {
3182 unsafe { BNIsValidOffset(self.handle, offset) }
3183 }
3184
3185 fn offset_readable(&self, offset: u64) -> bool {
3186 unsafe { BNIsOffsetReadable(self.handle, offset) }
3187 }
3188
3189 fn offset_writable(&self, offset: u64) -> bool {
3190 unsafe { BNIsOffsetWritable(self.handle, offset) }
3191 }
3192
3193 fn offset_executable(&self, offset: u64) -> bool {
3194 unsafe { BNIsOffsetExecutable(self.handle, offset) }
3195 }
3196
3197 fn offset_backed_by_file(&self, offset: u64) -> bool {
3198 unsafe { BNIsOffsetBackedByFile(self.handle, offset) }
3199 }
3200
3201 fn next_valid_offset_after(&self, offset: u64) -> u64 {
3202 unsafe { BNGetNextValidOffset(self.handle, offset) }
3203 }
3204
3205 fn modification_status(&self, offset: u64) -> ModificationStatus {
3206 unsafe { BNGetModification(self.handle, offset) }
3207 }
3208
3209 fn start(&self) -> u64 {
3210 unsafe { BNGetStartOffset(self.handle) }
3211 }
3212
3213 fn len(&self) -> u64 {
3214 unsafe { BNGetViewLength(self.handle) }
3215 }
3216
3217 fn executable(&self) -> bool {
3218 unsafe { BNIsExecutableView(self.handle) }
3219 }
3220
3221 fn relocatable(&self) -> bool {
3222 unsafe { BNIsRelocatable(self.handle) }
3223 }
3224
3225 fn entry_point(&self) -> u64 {
3226 unsafe { BNGetEntryPoint(self.handle) }
3227 }
3228
3229 fn default_endianness(&self) -> Endianness {
3230 unsafe { BNGetDefaultEndianness(self.handle) }
3231 }
3232
3233 fn address_size(&self) -> usize {
3234 unsafe { BNGetViewAddressSize(self.handle) }
3235 }
3236}
3237
3238unsafe impl RefCountable for BinaryView {
3239 unsafe fn inc_ref(handle: &Self) -> Ref<Self> {
3240 Ref::new(Self {
3241 handle: BNNewViewReference(handle.handle),
3242 })
3243 }
3244
3245 unsafe fn dec_ref(handle: &Self) {
3246 BNFreeBinaryView(handle.handle);
3247 }
3248}
3249
3250impl AsRef<BinaryView> for BinaryView {
3251 fn as_ref(&self) -> &Self {
3252 self
3253 }
3254}
3255
3256impl ToOwned for BinaryView {
3257 type Owned = Ref<Self>;
3258
3259 fn to_owned(&self) -> Self::Owned {
3260 unsafe { RefCountable::inc_ref(self) }
3261 }
3262}
3263
3264unsafe impl Send for BinaryView {}
3265unsafe impl Sync for BinaryView {}
3266
3267impl std::fmt::Debug for BinaryView {
3268 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
3269 f.debug_struct("BinaryView")
3270 .field("view_type", &self.view_type())
3271 .field("file", &self.file())
3272 .field("original_image_base", &self.original_image_base())
3273 .field("start", &self.start())
3274 .field("end", &self.end())
3275 .field("len", &self.len())
3276 .field("default_platform", &self.default_platform())
3277 .field("default_arch", &self.default_arch())
3278 .field("default_endianness", &self.default_endianness())
3279 .field("entry_point", &self.entry_point())
3280 .field(
3281 "entry_point_functions",
3282 &self.entry_point_functions().to_vec(),
3283 )
3284 .field("address_size", &self.address_size())
3285 .field("sections", &self.sections().to_vec())
3286 .field("segments", &self.segments().to_vec())
3287 .finish()
3288 }
3289}
3290
3291pub trait BinaryViewEventHandler: 'static + Sync {
3292 fn on_event(&self, binary_view: &BinaryView);
3293}
3294
3295impl<F: Fn(&BinaryView) + 'static + Sync> BinaryViewEventHandler for F {
3296 fn on_event(&self, binary_view: &BinaryView) {
3297 self(binary_view);
3298 }
3299}
3300
3301pub fn register_binary_view_event<Handler>(event_type: BinaryViewEventType, handler: Handler)
3331where
3332 Handler: BinaryViewEventHandler,
3333{
3334 unsafe extern "C" fn on_event<Handler: BinaryViewEventHandler>(
3335 ctx: *mut c_void,
3336 view: *mut BNBinaryView,
3337 ) {
3338 ffi_wrap!("EventHandler::on_event", {
3339 let context = unsafe { &*(ctx as *const Handler) };
3340 context.on_event(&BinaryView::ref_from_raw(BNNewViewReference(view)));
3341 })
3342 }
3343
3344 let boxed = Box::new(handler);
3345 let raw = Box::into_raw(boxed);
3346
3347 unsafe {
3348 BNRegisterBinaryViewEvent(event_type, Some(on_event::<Handler>), raw as *mut c_void);
3349 }
3350}
3351
3352#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
3353pub struct CommentReference {
3354 pub start: u64,
3355}
3356
3357impl From<u64> for CommentReference {
3358 fn from(start: u64) -> Self {
3359 Self { start }
3360 }
3361}
3362
3363impl CoreArrayProvider for CommentReference {
3364 type Raw = u64;
3365 type Context = ();
3366 type Wrapped<'a> = Self;
3367}
3368
3369unsafe impl CoreArrayProviderInner for CommentReference {
3370 unsafe fn free(raw: *mut Self::Raw, _count: usize, _context: &Self::Context) {
3371 BNFreeAddressList(raw)
3372 }
3373
3374 unsafe fn wrap_raw<'a>(raw: &'a Self::Raw, _context: &'a Self::Context) -> Self::Wrapped<'a> {
3375 Self::from(*raw)
3376 }
3377}
3378
3379#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
3380pub struct StringReference {
3381 pub ty: StringType,
3382 pub start: u64,
3383 pub length: usize,
3384}
3385
3386impl From<BNStringReference> for StringReference {
3387 fn from(raw: BNStringReference) -> Self {
3388 Self {
3389 ty: raw.type_,
3390 start: raw.start,
3391 length: raw.length,
3392 }
3393 }
3394}
3395
3396impl From<StringReference> for BNStringReference {
3397 fn from(raw: StringReference) -> Self {
3398 Self {
3399 type_: raw.ty,
3400 start: raw.start,
3401 length: raw.length,
3402 }
3403 }
3404}
3405
3406impl CoreArrayProvider for StringReference {
3407 type Raw = BNStringReference;
3408 type Context = ();
3409 type Wrapped<'a> = Self;
3410}
3411
3412unsafe impl CoreArrayProviderInner for StringReference {
3413 unsafe fn free(raw: *mut Self::Raw, _count: usize, _context: &Self::Context) {
3414 BNFreeStringReferenceList(raw)
3415 }
3416
3417 unsafe fn wrap_raw<'a>(raw: &'a Self::Raw, _context: &'a Self::Context) -> Self::Wrapped<'a> {
3418 Self::from(*raw)
3419 }
3420}
3421
3422#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
3423pub struct AddressRange {
3424 pub start: u64,
3425 pub end: u64,
3426}
3427
3428impl From<BNAddressRange> for AddressRange {
3429 fn from(raw: BNAddressRange) -> Self {
3430 Self {
3431 start: raw.start,
3432 end: raw.end,
3433 }
3434 }
3435}
3436
3437impl From<AddressRange> for BNAddressRange {
3438 fn from(raw: AddressRange) -> Self {
3439 Self {
3440 start: raw.start,
3441 end: raw.end,
3442 }
3443 }
3444}
3445
3446impl CoreArrayProvider for AddressRange {
3447 type Raw = BNAddressRange;
3448 type Context = ();
3449 type Wrapped<'a> = Self;
3450}
3451
3452unsafe impl CoreArrayProviderInner for AddressRange {
3453 unsafe fn free(raw: *mut Self::Raw, _count: usize, _context: &Self::Context) {
3454 BNFreeAddressRanges(raw);
3455 }
3456
3457 unsafe fn wrap_raw<'a>(raw: &'a Self::Raw, _context: &'a Self::Context) -> Self::Wrapped<'a> {
3458 Self::from(*raw)
3459 }
3460}
3461
3462extern "C" fn cb_valid<T>(ctxt: *mut c_void, data: *mut BNBinaryView) -> bool
3463where
3464 T: CustomBinaryViewType,
3465{
3466 let view_type = unsafe { &*(ctxt as *mut T) };
3467 let data = unsafe { BinaryView::ref_from_raw(BNNewViewReference(data)) };
3468 let _span = ffi_span!("CustomBinaryViewType::is_valid_for", data);
3469 view_type.is_valid_for(&data)
3470}
3471
3472extern "C" fn cb_deprecated<T>(_ctxt: *mut c_void) -> bool
3473where
3474 T: CustomBinaryViewType,
3475{
3476 T::DEPRECATED
3477}
3478
3479extern "C" fn cb_force_loadable<T>(_ctxt: *mut c_void) -> bool
3480where
3481 T: CustomBinaryViewType,
3482{
3483 T::FORCE_LOADABLE
3484}
3485
3486extern "C" fn cb_has_no_initial_content<T>(_ctxt: *mut c_void) -> bool
3487where
3488 T: CustomBinaryViewType,
3489{
3490 T::HAS_NO_INITIAL_CONTENT
3491}
3492
3493extern "C" fn cb_create<T>(ctxt: *mut c_void, data: *mut BNBinaryView) -> *mut BNBinaryView
3494where
3495 T: CustomBinaryViewType,
3496{
3497 ffi_wrap!("CustomBinaryViewType::create", unsafe {
3498 let view_type = &*(ctxt as *mut T);
3499 let data = BinaryView::from_raw(data);
3500 let _span = ffi_span!("CustomBinaryViewType::create", data);
3501 match view_type.create_binary_view(&data) {
3502 Ok(custom_view) => {
3503 match BinaryView::from_custom(T::NAME, &data.file(), &data, custom_view) {
3504 Ok(custom_view) => Ref::into_raw(custom_view).handle,
3505 Err(_) => std::ptr::null_mut(),
3506 }
3507 }
3508 Err(_) => std::ptr::null_mut(),
3509 }
3510 })
3511}
3512
3513extern "C" fn cb_parse<T>(ctxt: *mut c_void, data: *mut BNBinaryView) -> *mut BNBinaryView
3514where
3515 T: CustomBinaryViewType,
3516{
3517 ffi_wrap!("CustomBinaryViewType::parse", unsafe {
3518 let view_type = &*(ctxt as *mut T);
3519 let data = BinaryView::from_raw(data);
3520 let _span = ffi_span!("CustomBinaryViewType::parse", data);
3521 match view_type.create_binary_view_for_parse(&data) {
3522 Ok(custom_view) => {
3523 match BinaryView::from_custom(T::NAME, &data.file(), &data, custom_view) {
3524 Ok(custom_view) => Ref::into_raw(custom_view).handle,
3525 Err(_) => std::ptr::null_mut(),
3526 }
3527 }
3528 Err(_) => std::ptr::null_mut(),
3529 }
3530 })
3531}
3532
3533extern "C" fn cb_load_settings<T>(ctxt: *mut c_void, data: *mut BNBinaryView) -> *mut BNSettings
3534where
3535 T: CustomBinaryViewType,
3536{
3537 ffi_wrap!("CustomBinaryViewType::load_settings", unsafe {
3538 let view_type = &*(ctxt as *mut T);
3539 let data = BinaryView::from_raw(data);
3540
3541 let _span = ffi_span!("CustomBinaryViewType::load_settings", data);
3542 match view_type.load_settings_for_data(&data) {
3543 Some(load_settings) => Ref::into_raw(load_settings).handle,
3544 None => std::ptr::null_mut(),
3545 }
3546 })
3547}
3548
3549extern "C" fn cb_init<C>(ctxt: *mut c_void) -> bool
3550where
3551 C: CustomBinaryView,
3552{
3553 ffi_wrap!("BinaryViewBase::init", unsafe {
3554 let context = &mut *(ctxt as *mut CustomBinaryViewContext<C>);
3555 context.view.initialize(context.core_view.assume_init_ref())
3559 })
3560}
3561
3562extern "C" fn cb_on_after_snapshot_data_applied<C>(ctxt: *mut c_void)
3563where
3564 C: CustomBinaryView,
3565{
3566 ffi_wrap!("BinaryViewBase::onAfterSnapshotDataApplied", unsafe {
3567 let context = &mut *(ctxt as *mut CustomBinaryViewContext<C>);
3568 context.view.on_after_snapshot_data_applied();
3571 })
3572}
3573
3574extern "C" fn cb_free_object<C>(ctxt: *mut c_void)
3575where
3576 C: CustomBinaryView,
3577{
3578 ffi_wrap!("BinaryViewBase::freeObject", unsafe {
3579 let context = ctxt as *mut CustomBinaryViewContext<C>;
3580 let _context = Box::from_raw(context);
3581 })
3582}
3583
3584extern "C" fn cb_read<C>(ctxt: *mut c_void, dest: *mut c_void, offset: u64, len: usize) -> usize
3585where
3586 C: CustomBinaryView,
3587{
3588 ffi_wrap!("BinaryViewBase::read", unsafe {
3589 let context = &*(ctxt as *mut CustomBinaryViewContext<C>);
3590 let dest = std::slice::from_raw_parts_mut(dest as *mut u8, len);
3591 context.view.read(dest, offset)
3592 })
3593}
3594
3595extern "C" fn cb_write<C>(ctxt: *mut c_void, offset: u64, src: *const c_void, len: usize) -> usize
3596where
3597 C: CustomBinaryView,
3598{
3599 ffi_wrap!("BinaryViewBase::write", unsafe {
3600 let context = &*(ctxt as *mut CustomBinaryViewContext<C>);
3601 let src = std::slice::from_raw_parts(src as *const u8, len);
3602 context.view.write(offset, src)
3603 })
3604}
3605
3606extern "C" fn cb_insert<C>(ctxt: *mut c_void, offset: u64, src: *const c_void, len: usize) -> usize
3607where
3608 C: CustomBinaryView,
3609{
3610 ffi_wrap!("BinaryViewBase::insert", unsafe {
3611 let context = &*(ctxt as *mut CustomBinaryViewContext<C>);
3612 let src = std::slice::from_raw_parts(src as *const u8, len);
3613 context.view.insert(offset, src)
3614 })
3615}
3616
3617extern "C" fn cb_remove<C>(ctxt: *mut c_void, offset: u64, len: u64) -> usize
3618where
3619 C: CustomBinaryView,
3620{
3621 ffi_wrap!("BinaryViewBase::remove", unsafe {
3622 let context = &*(ctxt as *mut CustomBinaryViewContext<C>);
3623 context.view.remove(offset, len as usize)
3624 })
3625}
3626
3627extern "C" fn cb_modification<C>(ctxt: *mut c_void, offset: u64) -> ModificationStatus
3628where
3629 C: CustomBinaryView,
3630{
3631 ffi_wrap!("BinaryViewBase::modification_status", unsafe {
3632 let context = &*(ctxt as *mut CustomBinaryViewContext<C>);
3633 context.view.modification_status(offset)
3634 })
3635}
3636
3637extern "C" fn cb_offset_valid<C>(ctxt: *mut c_void, offset: u64) -> bool
3638where
3639 C: CustomBinaryView,
3640{
3641 ffi_wrap!("BinaryViewBase::offset_valid", unsafe {
3642 let context = &*(ctxt as *mut CustomBinaryViewContext<C>);
3643 context.view.offset_valid(offset)
3644 })
3645}
3646
3647extern "C" fn cb_offset_readable<C>(ctxt: *mut c_void, offset: u64) -> bool
3648where
3649 C: CustomBinaryView,
3650{
3651 ffi_wrap!("BinaryViewBase::readable", unsafe {
3652 let context = &*(ctxt as *mut CustomBinaryViewContext<C>);
3653 context.view.offset_readable(offset)
3654 })
3655}
3656
3657extern "C" fn cb_offset_writable<C>(ctxt: *mut c_void, offset: u64) -> bool
3658where
3659 C: CustomBinaryView,
3660{
3661 ffi_wrap!("BinaryViewBase::writable", unsafe {
3662 let context = &*(ctxt as *mut CustomBinaryViewContext<C>);
3663 context.view.offset_writable(offset)
3664 })
3665}
3666
3667extern "C" fn cb_offset_executable<C>(ctxt: *mut c_void, offset: u64) -> bool
3668where
3669 C: CustomBinaryView,
3670{
3671 ffi_wrap!("BinaryViewBase::offset_executable", unsafe {
3672 let context = &*(ctxt as *mut CustomBinaryViewContext<C>);
3673 context.view.offset_executable(offset)
3674 })
3675}
3676
3677extern "C" fn cb_offset_backed_by_file<C>(ctxt: *mut c_void, offset: u64) -> bool
3678where
3679 C: CustomBinaryView,
3680{
3681 ffi_wrap!("BinaryViewBase::offset_backed_by_file", unsafe {
3682 let context = &*(ctxt as *mut CustomBinaryViewContext<C>);
3683 context.view.offset_backed_by_file(offset)
3684 })
3685}
3686
3687extern "C" fn cb_next_valid_offset<C>(ctxt: *mut c_void, offset: u64) -> u64
3688where
3689 C: CustomBinaryView,
3690{
3691 ffi_wrap!("BinaryViewBase::next_valid_offset_after", unsafe {
3692 let context = &*(ctxt as *mut CustomBinaryViewContext<C>);
3693 context.view.next_valid_offset_after(offset)
3694 })
3695}
3696
3697extern "C" fn cb_start<C>(ctxt: *mut c_void) -> u64
3698where
3699 C: CustomBinaryView,
3700{
3701 ffi_wrap!("BinaryViewBase::start", unsafe {
3702 let context = &*(ctxt as *mut CustomBinaryViewContext<C>);
3703 context.view.start()
3704 })
3705}
3706
3707extern "C" fn cb_length<C>(ctxt: *mut c_void) -> u64
3708where
3709 C: CustomBinaryView,
3710{
3711 ffi_wrap!("BinaryViewBase::len", unsafe {
3712 let context = &*(ctxt as *mut CustomBinaryViewContext<C>);
3713 context.view.len()
3714 })
3715}
3716
3717extern "C" fn cb_entry_point<C>(ctxt: *mut c_void) -> u64
3718where
3719 C: CustomBinaryView,
3720{
3721 ffi_wrap!("BinaryViewBase::entry_point", unsafe {
3722 let context = &*(ctxt as *mut CustomBinaryViewContext<C>);
3723 context.view.entry_point()
3724 })
3725}
3726
3727extern "C" fn cb_executable<C>(ctxt: *mut c_void) -> bool
3728where
3729 C: CustomBinaryView,
3730{
3731 ffi_wrap!("BinaryViewBase::executable", unsafe {
3732 let context = &*(ctxt as *mut CustomBinaryViewContext<C>);
3733 context.view.executable()
3734 })
3735}
3736
3737extern "C" fn cb_endianness<C>(ctxt: *mut c_void) -> Endianness
3738where
3739 C: CustomBinaryView,
3740{
3741 ffi_wrap!("BinaryViewBase::default_endianness", unsafe {
3742 let context = &*(ctxt as *mut CustomBinaryViewContext<C>);
3743 context.view.default_endianness()
3744 })
3745}
3746
3747extern "C" fn cb_relocatable<C>(ctxt: *mut c_void) -> bool
3748where
3749 C: CustomBinaryView,
3750{
3751 ffi_wrap!("BinaryViewBase::relocatable", unsafe {
3752 let context = &*(ctxt as *mut CustomBinaryViewContext<C>);
3753 context.view.relocatable()
3754 })
3755}
3756
3757extern "C" fn cb_address_size<C>(ctxt: *mut c_void) -> usize
3758where
3759 C: CustomBinaryView,
3760{
3761 ffi_wrap!("BinaryViewBase::address_size", unsafe {
3762 let context = &*(ctxt as *mut CustomBinaryViewContext<C>);
3763 context.view.address_size()
3764 })
3765}
3766
3767extern "C" fn cb_save<C>(ctxt: *mut c_void, file: *mut BNFileAccessor) -> bool
3768where
3769 C: CustomBinaryView,
3770{
3771 ffi_wrap!("BinaryViewBase::save", unsafe {
3772 let context = &*(ctxt as *mut CustomBinaryViewContext<C>);
3773 let mut file = BorrowedFileAccessor::from_raw(file);
3774 context
3777 .view
3778 .save(context.core_view.assume_init_ref(), &mut file)
3779 })
3780}