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, DataReference};
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 code_refs_from_addr(&self, addr: u64, func: Option<&Function>) -> Vec<u64> {
2488 unsafe {
2489 let mut count = 0;
2490 let code_ref =
2491 CodeReference::new(addr, func.map(|f| f.to_owned()), func.map(|f| f.arch()));
2492 let mut raw_code_ref = CodeReference::into_owned_raw(&code_ref);
2493 let addresses = BNGetCodeReferencesFrom(self.handle, &mut raw_code_ref, &mut count);
2494 let res = std::slice::from_raw_parts(addresses, count).to_vec();
2495 BNFreeAddressList(addresses);
2496 res
2497 }
2498 }
2499
2500 pub fn data_refs_to_addr(&self, addr: u64) -> Array<DataReference> {
2502 unsafe {
2503 let mut count = 0;
2504 let handle = BNGetDataReferences(self.handle, addr, &mut count, false, 0);
2505 Array::new(handle, count, ())
2506 }
2507 }
2508
2509 pub fn data_refs_into_range(&self, range: Range<u64>) -> Array<DataReference> {
2511 unsafe {
2512 let mut count = 0;
2513 let handle = BNGetDataReferencesInRange(
2514 self.handle,
2515 range.start,
2516 range.end - range.start,
2517 &mut count,
2518 false,
2519 0,
2520 );
2521 Array::new(handle, count, ())
2522 }
2523 }
2524
2525 pub fn data_refs_from_addr(&self, addr: u64) -> Array<DataReference> {
2527 unsafe {
2528 let mut count = 0;
2529 let handle = BNGetDataReferencesFrom(self.handle, addr, &mut count);
2530 Array::new(handle, count, ())
2531 }
2532 }
2533
2534 pub fn code_refs_using_type_name<T: Into<QualifiedName>>(
2536 &self,
2537 name: T,
2538 ) -> Array<CodeReference> {
2539 let mut raw_name = QualifiedName::into_raw(name.into());
2540 unsafe {
2541 let mut count = 0;
2542 let handle =
2543 BNGetCodeReferencesForType(self.handle, &mut raw_name, &mut count, false, 0);
2544 QualifiedName::free_raw(raw_name);
2545 Array::new(handle, count, ())
2546 }
2547 }
2548
2549 pub fn data_refs_using_type_name<T: Into<QualifiedName>>(
2551 &self,
2552 name: T,
2553 ) -> Array<DataReference> {
2554 let mut raw_name = QualifiedName::into_raw(name.into());
2555 unsafe {
2556 let mut count = 0;
2557 let handle =
2558 BNGetDataReferencesForType(self.handle, &mut raw_name, &mut count, false, 0);
2559 QualifiedName::free_raw(raw_name);
2560 Array::new(handle, count, ())
2561 }
2562 }
2563
2564 pub fn relocations_at(&self, addr: u64) -> Array<Relocation> {
2565 unsafe {
2566 let mut count = 0;
2567 let handle = BNGetRelocationsAt(self.handle, addr, &mut count);
2568 Array::new(handle, count, ())
2569 }
2570 }
2571
2572 pub fn relocation_ranges(&self) -> Vec<Range<u64>> {
2573 let ranges = unsafe {
2574 let mut count = 0;
2575 let reloc_ranges_ptr = BNGetRelocationRanges(self.handle, &mut count);
2576 let ranges = std::slice::from_raw_parts(reloc_ranges_ptr, count).to_vec();
2577 BNFreeRelocationRanges(reloc_ranges_ptr);
2578 ranges
2579 };
2580
2581 ranges
2583 .iter()
2584 .map(|range| Range {
2585 start: range.start,
2586 end: range.end,
2587 })
2588 .collect()
2589 }
2590
2591 pub fn component_by_guid(&self, guid: &str) -> Option<Ref<Component>> {
2592 let name = guid.to_cstr();
2593 let result = unsafe { BNGetComponentByGuid(self.handle, name.as_ptr()) };
2594 NonNull::new(result).map(|h| unsafe { Component::ref_from_raw(h) })
2595 }
2596
2597 pub fn root_component(&self) -> Option<Ref<Component>> {
2598 let result = unsafe { BNGetRootComponent(self.handle) };
2599 NonNull::new(result).map(|h| unsafe { Component::ref_from_raw(h) })
2600 }
2601
2602 pub fn component_by_path(&self, path: &str) -> Option<Ref<Component>> {
2603 let path = path.to_cstr();
2604 let result = unsafe { BNGetComponentByPath(self.handle, path.as_ptr()) };
2605 NonNull::new(result).map(|h| unsafe { Component::ref_from_raw(h) })
2606 }
2607
2608 pub fn remove_component(&self, component: &Component) -> bool {
2609 unsafe { BNRemoveComponent(self.handle, component.handle.as_ptr()) }
2610 }
2611
2612 pub fn remove_component_by_guid(&self, guid: &str) -> bool {
2613 let path = guid.to_cstr();
2614 unsafe { BNRemoveComponentByGuid(self.handle, path.as_ptr()) }
2615 }
2616
2617 pub fn data_variable_parent_components(
2618 &self,
2619 data_variable: &DataVariable,
2620 ) -> Array<Component> {
2621 let mut count = 0;
2622 let result = unsafe {
2623 BNGetDataVariableParentComponents(self.handle, data_variable.address, &mut count)
2624 };
2625 unsafe { Array::new(result, count, ()) }
2626 }
2627
2628 pub fn external_libraries(&self) -> Array<ExternalLibrary> {
2629 let mut count = 0;
2630 let result = unsafe { BNBinaryViewGetExternalLibraries(self.handle, &mut count) };
2631 unsafe { Array::new(result, count, ()) }
2632 }
2633
2634 pub fn external_library(&self, name: &str) -> Option<Ref<ExternalLibrary>> {
2635 let name_ptr = name.to_cstr();
2636 let result = unsafe { BNBinaryViewGetExternalLibrary(self.handle, name_ptr.as_ptr()) };
2637 let result_ptr = NonNull::new(result)?;
2638 Some(unsafe { ExternalLibrary::ref_from_raw(result_ptr) })
2639 }
2640
2641 pub fn remove_external_library(&self, name: &str) {
2642 let name_ptr = name.to_cstr();
2643 unsafe { BNBinaryViewRemoveExternalLibrary(self.handle, name_ptr.as_ptr()) };
2644 }
2645
2646 pub fn add_external_library(
2647 &self,
2648 name: &str,
2649 backing_file: Option<&ProjectFile>,
2650 auto: bool,
2651 ) -> Option<Ref<ExternalLibrary>> {
2652 let name_ptr = name.to_cstr();
2653 let result = unsafe {
2654 BNBinaryViewAddExternalLibrary(
2655 self.handle,
2656 name_ptr.as_ptr(),
2657 backing_file
2658 .map(|b| b.handle.as_ptr())
2659 .unwrap_or(std::ptr::null_mut()),
2660 auto,
2661 )
2662 };
2663 NonNull::new(result).map(|h| unsafe { ExternalLibrary::ref_from_raw(h) })
2664 }
2665
2666 pub fn external_locations(&self) -> Array<ExternalLocation> {
2667 let mut count = 0;
2668 let result = unsafe { BNBinaryViewGetExternalLocations(self.handle, &mut count) };
2669 unsafe { Array::new(result, count, ()) }
2670 }
2671
2672 pub fn external_location_from_symbol(&self, symbol: &Symbol) -> Option<Ref<ExternalLocation>> {
2673 let result = unsafe { BNBinaryViewGetExternalLocation(self.handle, symbol.handle) };
2674 let result_ptr = NonNull::new(result)?;
2675 Some(unsafe { ExternalLocation::ref_from_raw(result_ptr) })
2676 }
2677
2678 pub fn remove_external_location(&self, location: &ExternalLocation) {
2679 self.remove_external_location_from_symbol(&location.source_symbol())
2680 }
2681
2682 pub fn remove_external_location_from_symbol(&self, symbol: &Symbol) {
2683 unsafe { BNBinaryViewRemoveExternalLocation(self.handle, symbol.handle) };
2684 }
2685
2686 pub fn add_external_location(
2688 &self,
2689 symbol: &Symbol,
2690 library: &ExternalLibrary,
2691 target_symbol_name: &str,
2692 target_address: Option<u64>,
2693 target_is_auto: bool,
2694 ) -> Option<Ref<ExternalLocation>> {
2695 let target_symbol_name = target_symbol_name.to_cstr();
2696 let target_address_ptr = target_address
2697 .map(|a| a as *mut u64)
2698 .unwrap_or(std::ptr::null_mut());
2699 let result = unsafe {
2700 BNBinaryViewAddExternalLocation(
2701 self.handle,
2702 symbol.handle,
2703 library.handle.as_ptr(),
2704 target_symbol_name.as_ptr(),
2705 target_address_ptr,
2706 target_is_auto,
2707 )
2708 };
2709 NonNull::new(result).map(|h| unsafe { ExternalLocation::ref_from_raw(h) })
2710 }
2711
2712 pub fn type_container(&self) -> TypeContainer {
2716 let type_container_ptr = NonNull::new(unsafe { BNGetAnalysisTypeContainer(self.handle) });
2717 unsafe { TypeContainer::from_raw(type_container_ptr.unwrap()) }
2719 }
2720
2721 pub fn user_type_container(&self) -> TypeContainer {
2723 let type_container_ptr =
2724 NonNull::new(unsafe { BNGetAnalysisUserTypeContainer(self.handle) });
2725 unsafe { TypeContainer::from_raw(type_container_ptr.unwrap()) }.clone()
2727 }
2728
2729 pub fn auto_type_container(&self) -> TypeContainer {
2733 let type_container_ptr =
2734 NonNull::new(unsafe { BNGetAnalysisAutoTypeContainer(self.handle) });
2735 unsafe { TypeContainer::from_raw(type_container_ptr.unwrap()) }
2737 }
2738
2739 pub fn type_libraries(&self) -> Array<TypeLibrary> {
2740 let mut count = 0;
2741 let result = unsafe { BNGetBinaryViewTypeLibraries(self.handle, &mut count) };
2742 unsafe { Array::new(result, count, ()) }
2743 }
2744
2745 pub fn add_type_library(&self, library: &TypeLibrary) {
2747 unsafe { BNAddBinaryViewTypeLibrary(self.handle, library.as_raw()) }
2748 }
2749
2750 pub fn type_library_by_name(&self, name: &str) -> Option<Ref<TypeLibrary>> {
2751 let name = name.to_cstr();
2752 let result = unsafe { BNGetBinaryViewTypeLibrary(self.handle, name.as_ptr()) };
2753 NonNull::new(result).map(|h| unsafe { TypeLibrary::ref_from_raw(h) })
2754 }
2755
2756 pub fn record_imported_object_library<T: Into<QualifiedName>>(
2765 &self,
2766 lib: &TypeLibrary,
2767 name: T,
2768 addr: u64,
2769 platform: &Platform,
2770 ) {
2771 let mut raw_name = QualifiedName::into_raw(name.into());
2772 unsafe {
2773 BNBinaryViewRecordImportedObjectLibrary(
2774 self.handle,
2775 platform.handle,
2776 addr,
2777 lib.as_raw(),
2778 &mut raw_name,
2779 )
2780 }
2781 QualifiedName::free_raw(raw_name);
2782 }
2783
2784 pub fn import_type_library_type<T: Into<QualifiedName>>(
2795 &self,
2796 name: T,
2797 lib: Option<&TypeLibrary>,
2798 ) -> Option<Ref<Type>> {
2799 let mut lib_ref = lib
2800 .as_ref()
2801 .map(|l| unsafe { l.as_raw() } as *mut _)
2802 .unwrap_or(std::ptr::null_mut());
2803 let mut raw_name = QualifiedName::into_raw(name.into());
2804 let result =
2805 unsafe { BNBinaryViewImportTypeLibraryType(self.handle, &mut lib_ref, &mut raw_name) };
2806 QualifiedName::free_raw(raw_name);
2807 (!result.is_null()).then(|| unsafe { Type::ref_from_raw(result) })
2808 }
2809
2810 pub fn import_type_library_object<T: Into<QualifiedName>>(
2821 &self,
2822 name: T,
2823 lib: Option<&TypeLibrary>,
2824 ) -> Option<Ref<Type>> {
2825 let mut lib_ref = lib
2826 .as_ref()
2827 .map(|l| unsafe { l.as_raw() } as *mut _)
2828 .unwrap_or(std::ptr::null_mut());
2829 let mut raw_name = QualifiedName::into_raw(name.into());
2830 let result = unsafe {
2831 BNBinaryViewImportTypeLibraryObject(self.handle, &mut lib_ref, &mut raw_name)
2832 };
2833 QualifiedName::free_raw(raw_name);
2834 (!result.is_null()).then(|| unsafe { Type::ref_from_raw(result) })
2835 }
2836
2837 pub fn import_type_by_guid(&self, guid: &str) -> Option<Ref<Type>> {
2839 let guid = guid.to_cstr();
2840 let result = unsafe { BNBinaryViewImportTypeLibraryTypeByGuid(self.handle, guid.as_ptr()) };
2841 (!result.is_null()).then(|| unsafe { Type::ref_from_raw(result) })
2842 }
2843
2844 pub fn export_type_to_library<T: Into<QualifiedName>>(
2849 &self,
2850 lib: &TypeLibrary,
2851 name: T,
2852 type_obj: &Type,
2853 ) {
2854 let mut raw_name = QualifiedName::into_raw(name.into());
2855 unsafe {
2856 BNBinaryViewExportTypeToTypeLibrary(
2857 self.handle,
2858 lib.as_raw(),
2859 &mut raw_name,
2860 type_obj.handle,
2861 )
2862 }
2863 QualifiedName::free_raw(raw_name);
2864 }
2865
2866 pub fn export_object_to_library<T: Into<QualifiedName>>(
2871 &self,
2872 lib: &TypeLibrary,
2873 name: T,
2874 type_obj: &Type,
2875 ) {
2876 let mut raw_name = QualifiedName::into_raw(name.into());
2877 unsafe {
2878 BNBinaryViewExportObjectToTypeLibrary(
2879 self.handle,
2880 lib.as_raw(),
2881 &mut raw_name,
2882 type_obj.handle,
2883 )
2884 }
2885 QualifiedName::free_raw(raw_name);
2886 }
2887
2888 pub fn lookup_imported_object_library(
2894 &self,
2895 addr: u64,
2896 platform: &Platform,
2897 ) -> Option<(Ref<TypeLibrary>, QualifiedName)> {
2898 let mut result_lib = std::ptr::null_mut();
2899 let mut result_name = BNQualifiedName::default();
2900 let success = unsafe {
2901 BNBinaryViewLookupImportedObjectLibrary(
2902 self.handle,
2903 platform.handle,
2904 addr,
2905 &mut result_lib,
2906 &mut result_name,
2907 )
2908 };
2909 if !success {
2910 return None;
2911 }
2912 let lib = unsafe { TypeLibrary::ref_from_raw(NonNull::new(result_lib)?) };
2913 let name = QualifiedName::from_owned_raw(result_name);
2914 Some((lib, name))
2915 }
2916
2917 pub fn lookup_imported_type_library<T: Into<QualifiedName>>(
2921 &self,
2922 name: T,
2923 ) -> Option<(Ref<TypeLibrary>, QualifiedName)> {
2924 let raw_name = QualifiedName::into_raw(name.into());
2925 let mut result_lib = std::ptr::null_mut();
2926 let mut result_name = BNQualifiedName::default();
2927 let success = unsafe {
2928 BNBinaryViewLookupImportedTypeLibrary(
2929 self.handle,
2930 &raw_name,
2931 &mut result_lib,
2932 &mut result_name,
2933 )
2934 };
2935 QualifiedName::free_raw(raw_name);
2936 if !success {
2937 return None;
2938 }
2939 let lib = unsafe { TypeLibrary::ref_from_raw(NonNull::new(result_lib)?) };
2940 let name = QualifiedName::from_owned_raw(result_name);
2941 Some((lib, name))
2942 }
2943
2944 pub fn strings(&self) -> Array<StringReference> {
2958 unsafe {
2959 let mut count = 0;
2960 let strings = BNGetStrings(self.handle, &mut count);
2961 Array::new(strings, count, ())
2962 }
2963 }
2964
2965 pub fn string_at(&self, addr: u64) -> Option<StringReference> {
2979 let mut str_ref = BNStringReference::default();
2980 let success = unsafe { BNGetStringAtAddress(self.handle, addr, &mut str_ref) };
2981 if success {
2982 Some(str_ref.into())
2983 } else {
2984 None
2985 }
2986 }
2987
2988 pub fn strings_in_range(&self, range: Range<u64>) -> Array<StringReference> {
3002 unsafe {
3003 let mut count = 0;
3004 let strings = BNGetStringsInRange(
3005 self.handle,
3006 range.start,
3007 range.end - range.start,
3008 &mut count,
3009 );
3010 Array::new(strings, count, ())
3011 }
3012 }
3013
3014 pub fn attached_type_archives(&self) -> Vec<TypeArchiveId> {
3018 let mut ids: *mut *mut c_char = std::ptr::null_mut();
3019 let mut paths: *mut *mut c_char = std::ptr::null_mut();
3020 let count = unsafe { BNBinaryViewGetTypeArchives(self.handle, &mut ids, &mut paths) };
3021 let _path_list = unsafe { Array::<BnString>::new(paths, count, ()) };
3025 let id_list = unsafe { Array::<BnString>::new(ids, count, ()) };
3026 id_list
3027 .into_iter()
3028 .map(|id| TypeArchiveId(id.to_string()))
3029 .collect()
3030 }
3031
3032 pub fn type_archive_by_id(&self, id: &TypeArchiveId) -> Option<Ref<TypeArchive>> {
3036 let id = id.0.as_str().to_cstr();
3037 let result = unsafe { BNBinaryViewGetTypeArchive(self.handle, id.as_ptr()) };
3038 let result_ptr = NonNull::new(result)?;
3039 Some(unsafe { TypeArchive::ref_from_raw(result_ptr) })
3040 }
3041
3042 pub fn type_archive_path_by_id(&self, id: &TypeArchiveId) -> Option<PathBuf> {
3044 let id = id.0.as_str().to_cstr();
3045 let result = unsafe { BNBinaryViewGetTypeArchivePath(self.handle, id.as_ptr()) };
3046 if result.is_null() {
3047 return None;
3048 }
3049 let path_str = unsafe { BnString::into_string(result) };
3050 Some(PathBuf::from(path_str))
3051 }
3052
3053 pub fn deref_return_value_named_type_references(
3054 &self,
3055 return_value: &ReturnValue,
3056 ) -> ReturnValue {
3057 ReturnValue {
3058 ty: Conf::new(
3059 return_value.ty.contents.deref_named_type_reference(self),
3060 return_value.ty.confidence,
3061 ),
3062 location: return_value.location.clone(),
3063 }
3064 }
3065
3066 pub fn deref_parameter_named_type_references(
3067 &self,
3068 params: &[FunctionParameter],
3069 ) -> Vec<FunctionParameter> {
3070 params
3071 .iter()
3072 .map(|param| FunctionParameter {
3073 ty: Conf::new(
3074 param.ty.contents.deref_named_type_reference(self),
3075 param.ty.confidence,
3076 ),
3077 name: param.name.clone(),
3078 location: param.location.clone(),
3079 })
3080 .collect()
3081 }
3082}
3083
3084impl BinaryViewBase for BinaryView {
3085 fn read(&self, buf: &mut [u8], offset: u64) -> usize {
3086 unsafe { BNReadViewData(self.handle, buf.as_mut_ptr() as *mut _, offset, buf.len()) }
3087 }
3088
3089 fn write(&self, offset: u64, data: &[u8]) -> usize {
3090 unsafe { BNWriteViewData(self.handle, offset, data.as_ptr() as *const _, data.len()) }
3091 }
3092
3093 fn insert(&self, offset: u64, data: &[u8]) -> usize {
3094 unsafe { BNInsertViewData(self.handle, offset, data.as_ptr() as *const _, data.len()) }
3095 }
3096
3097 fn remove(&self, offset: u64, len: usize) -> usize {
3098 unsafe { BNRemoveViewData(self.handle, offset, len as u64) }
3099 }
3100
3101 fn offset_valid(&self, offset: u64) -> bool {
3102 unsafe { BNIsValidOffset(self.handle, offset) }
3103 }
3104
3105 fn offset_readable(&self, offset: u64) -> bool {
3106 unsafe { BNIsOffsetReadable(self.handle, offset) }
3107 }
3108
3109 fn offset_writable(&self, offset: u64) -> bool {
3110 unsafe { BNIsOffsetWritable(self.handle, offset) }
3111 }
3112
3113 fn offset_executable(&self, offset: u64) -> bool {
3114 unsafe { BNIsOffsetExecutable(self.handle, offset) }
3115 }
3116
3117 fn offset_backed_by_file(&self, offset: u64) -> bool {
3118 unsafe { BNIsOffsetBackedByFile(self.handle, offset) }
3119 }
3120
3121 fn next_valid_offset_after(&self, offset: u64) -> u64 {
3122 unsafe { BNGetNextValidOffset(self.handle, offset) }
3123 }
3124
3125 fn modification_status(&self, offset: u64) -> ModificationStatus {
3126 unsafe { BNGetModification(self.handle, offset) }
3127 }
3128
3129 fn start(&self) -> u64 {
3130 unsafe { BNGetStartOffset(self.handle) }
3131 }
3132
3133 fn len(&self) -> u64 {
3134 unsafe { BNGetViewLength(self.handle) }
3135 }
3136
3137 fn executable(&self) -> bool {
3138 unsafe { BNIsExecutableView(self.handle) }
3139 }
3140
3141 fn relocatable(&self) -> bool {
3142 unsafe { BNIsRelocatable(self.handle) }
3143 }
3144
3145 fn entry_point(&self) -> u64 {
3146 unsafe { BNGetEntryPoint(self.handle) }
3147 }
3148
3149 fn default_endianness(&self) -> Endianness {
3150 unsafe { BNGetDefaultEndianness(self.handle) }
3151 }
3152
3153 fn address_size(&self) -> usize {
3154 unsafe { BNGetViewAddressSize(self.handle) }
3155 }
3156}
3157
3158unsafe impl RefCountable for BinaryView {
3159 unsafe fn inc_ref(handle: &Self) -> Ref<Self> {
3160 Ref::new(Self {
3161 handle: BNNewViewReference(handle.handle),
3162 })
3163 }
3164
3165 unsafe fn dec_ref(handle: &Self) {
3166 BNFreeBinaryView(handle.handle);
3167 }
3168}
3169
3170impl AsRef<BinaryView> for BinaryView {
3171 fn as_ref(&self) -> &Self {
3172 self
3173 }
3174}
3175
3176impl ToOwned for BinaryView {
3177 type Owned = Ref<Self>;
3178
3179 fn to_owned(&self) -> Self::Owned {
3180 unsafe { RefCountable::inc_ref(self) }
3181 }
3182}
3183
3184unsafe impl Send for BinaryView {}
3185unsafe impl Sync for BinaryView {}
3186
3187impl std::fmt::Debug for BinaryView {
3188 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
3189 f.debug_struct("BinaryView")
3190 .field("view_type", &self.view_type())
3191 .field("file", &self.file())
3192 .field("original_image_base", &self.original_image_base())
3193 .field("start", &self.start())
3194 .field("end", &self.end())
3195 .field("len", &self.len())
3196 .field("default_platform", &self.default_platform())
3197 .field("default_arch", &self.default_arch())
3198 .field("default_endianness", &self.default_endianness())
3199 .field("entry_point", &self.entry_point())
3200 .field(
3201 "entry_point_functions",
3202 &self.entry_point_functions().to_vec(),
3203 )
3204 .field("address_size", &self.address_size())
3205 .field("sections", &self.sections().to_vec())
3206 .field("segments", &self.segments().to_vec())
3207 .finish()
3208 }
3209}
3210
3211pub trait BinaryViewEventHandler: 'static + Sync {
3212 fn on_event(&self, binary_view: &BinaryView);
3213}
3214
3215impl<F: Fn(&BinaryView) + 'static + Sync> BinaryViewEventHandler for F {
3216 fn on_event(&self, binary_view: &BinaryView) {
3217 self(binary_view);
3218 }
3219}
3220
3221pub fn register_binary_view_event<Handler>(event_type: BinaryViewEventType, handler: Handler)
3251where
3252 Handler: BinaryViewEventHandler,
3253{
3254 unsafe extern "C" fn on_event<Handler: BinaryViewEventHandler>(
3255 ctx: *mut c_void,
3256 view: *mut BNBinaryView,
3257 ) {
3258 ffi_wrap!("EventHandler::on_event", {
3259 let context = unsafe { &*(ctx as *const Handler) };
3260 context.on_event(&BinaryView::ref_from_raw(BNNewViewReference(view)));
3261 })
3262 }
3263
3264 let boxed = Box::new(handler);
3265 let raw = Box::into_raw(boxed);
3266
3267 unsafe {
3268 BNRegisterBinaryViewEvent(event_type, Some(on_event::<Handler>), raw as *mut c_void);
3269 }
3270}
3271
3272#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
3273pub struct CommentReference {
3274 pub start: u64,
3275}
3276
3277impl From<u64> for CommentReference {
3278 fn from(start: u64) -> Self {
3279 Self { start }
3280 }
3281}
3282
3283impl CoreArrayProvider for CommentReference {
3284 type Raw = u64;
3285 type Context = ();
3286 type Wrapped<'a> = Self;
3287}
3288
3289unsafe impl CoreArrayProviderInner for CommentReference {
3290 unsafe fn free(raw: *mut Self::Raw, _count: usize, _context: &Self::Context) {
3291 BNFreeAddressList(raw)
3292 }
3293
3294 unsafe fn wrap_raw<'a>(raw: &'a Self::Raw, _context: &'a Self::Context) -> Self::Wrapped<'a> {
3295 Self::from(*raw)
3296 }
3297}
3298
3299#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
3300pub struct StringReference {
3301 pub ty: StringType,
3302 pub start: u64,
3303 pub length: usize,
3304}
3305
3306impl From<BNStringReference> for StringReference {
3307 fn from(raw: BNStringReference) -> Self {
3308 Self {
3309 ty: raw.type_,
3310 start: raw.start,
3311 length: raw.length,
3312 }
3313 }
3314}
3315
3316impl From<StringReference> for BNStringReference {
3317 fn from(raw: StringReference) -> Self {
3318 Self {
3319 type_: raw.ty,
3320 start: raw.start,
3321 length: raw.length,
3322 }
3323 }
3324}
3325
3326impl CoreArrayProvider for StringReference {
3327 type Raw = BNStringReference;
3328 type Context = ();
3329 type Wrapped<'a> = Self;
3330}
3331
3332unsafe impl CoreArrayProviderInner for StringReference {
3333 unsafe fn free(raw: *mut Self::Raw, _count: usize, _context: &Self::Context) {
3334 BNFreeStringReferenceList(raw)
3335 }
3336
3337 unsafe fn wrap_raw<'a>(raw: &'a Self::Raw, _context: &'a Self::Context) -> Self::Wrapped<'a> {
3338 Self::from(*raw)
3339 }
3340}
3341
3342#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
3343pub struct AddressRange {
3344 pub start: u64,
3345 pub end: u64,
3346}
3347
3348impl From<BNAddressRange> for AddressRange {
3349 fn from(raw: BNAddressRange) -> Self {
3350 Self {
3351 start: raw.start,
3352 end: raw.end,
3353 }
3354 }
3355}
3356
3357impl From<AddressRange> for BNAddressRange {
3358 fn from(raw: AddressRange) -> Self {
3359 Self {
3360 start: raw.start,
3361 end: raw.end,
3362 }
3363 }
3364}
3365
3366impl CoreArrayProvider for AddressRange {
3367 type Raw = BNAddressRange;
3368 type Context = ();
3369 type Wrapped<'a> = Self;
3370}
3371
3372unsafe impl CoreArrayProviderInner for AddressRange {
3373 unsafe fn free(raw: *mut Self::Raw, _count: usize, _context: &Self::Context) {
3374 BNFreeAddressRanges(raw);
3375 }
3376
3377 unsafe fn wrap_raw<'a>(raw: &'a Self::Raw, _context: &'a Self::Context) -> Self::Wrapped<'a> {
3378 Self::from(*raw)
3379 }
3380}
3381
3382extern "C" fn cb_valid<T>(ctxt: *mut c_void, data: *mut BNBinaryView) -> bool
3383where
3384 T: CustomBinaryViewType,
3385{
3386 let view_type = unsafe { &*(ctxt as *mut T) };
3387 let data = unsafe { BinaryView::ref_from_raw(BNNewViewReference(data)) };
3388 let _span = ffi_span!("CustomBinaryViewType::is_valid_for", data);
3389 view_type.is_valid_for(&data)
3390}
3391
3392extern "C" fn cb_deprecated<T>(_ctxt: *mut c_void) -> bool
3393where
3394 T: CustomBinaryViewType,
3395{
3396 T::DEPRECATED
3397}
3398
3399extern "C" fn cb_force_loadable<T>(_ctxt: *mut c_void) -> bool
3400where
3401 T: CustomBinaryViewType,
3402{
3403 T::FORCE_LOADABLE
3404}
3405
3406extern "C" fn cb_has_no_initial_content<T>(_ctxt: *mut c_void) -> bool
3407where
3408 T: CustomBinaryViewType,
3409{
3410 T::HAS_NO_INITIAL_CONTENT
3411}
3412
3413extern "C" fn cb_create<T>(ctxt: *mut c_void, data: *mut BNBinaryView) -> *mut BNBinaryView
3414where
3415 T: CustomBinaryViewType,
3416{
3417 ffi_wrap!("CustomBinaryViewType::create", unsafe {
3418 let view_type = &*(ctxt as *mut T);
3419 let data = BinaryView::from_raw(data);
3420 let _span = ffi_span!("CustomBinaryViewType::create", data);
3421 match view_type.create_binary_view(&data) {
3422 Ok(custom_view) => {
3423 match BinaryView::from_custom(T::NAME, &data.file(), &data, custom_view) {
3424 Ok(custom_view) => Ref::into_raw(custom_view).handle,
3425 Err(_) => std::ptr::null_mut(),
3426 }
3427 }
3428 Err(_) => std::ptr::null_mut(),
3429 }
3430 })
3431}
3432
3433extern "C" fn cb_parse<T>(ctxt: *mut c_void, data: *mut BNBinaryView) -> *mut BNBinaryView
3434where
3435 T: CustomBinaryViewType,
3436{
3437 ffi_wrap!("CustomBinaryViewType::parse", unsafe {
3438 let view_type = &*(ctxt as *mut T);
3439 let data = BinaryView::from_raw(data);
3440 let _span = ffi_span!("CustomBinaryViewType::parse", data);
3441 match view_type.create_binary_view_for_parse(&data) {
3442 Ok(custom_view) => {
3443 match BinaryView::from_custom(T::NAME, &data.file(), &data, custom_view) {
3444 Ok(custom_view) => Ref::into_raw(custom_view).handle,
3445 Err(_) => std::ptr::null_mut(),
3446 }
3447 }
3448 Err(_) => std::ptr::null_mut(),
3449 }
3450 })
3451}
3452
3453extern "C" fn cb_load_settings<T>(ctxt: *mut c_void, data: *mut BNBinaryView) -> *mut BNSettings
3454where
3455 T: CustomBinaryViewType,
3456{
3457 ffi_wrap!("CustomBinaryViewType::load_settings", unsafe {
3458 let view_type = &*(ctxt as *mut T);
3459 let data = BinaryView::from_raw(data);
3460
3461 let _span = ffi_span!("CustomBinaryViewType::load_settings", data);
3462 match view_type.load_settings_for_data(&data) {
3463 Some(load_settings) => Ref::into_raw(load_settings).handle,
3464 None => std::ptr::null_mut(),
3465 }
3466 })
3467}
3468
3469extern "C" fn cb_init<C>(ctxt: *mut c_void) -> bool
3470where
3471 C: CustomBinaryView,
3472{
3473 ffi_wrap!("BinaryViewBase::init", unsafe {
3474 let context = &mut *(ctxt as *mut CustomBinaryViewContext<C>);
3475 context.view.initialize(context.core_view.assume_init_ref())
3479 })
3480}
3481
3482extern "C" fn cb_on_after_snapshot_data_applied<C>(ctxt: *mut c_void)
3483where
3484 C: CustomBinaryView,
3485{
3486 ffi_wrap!("BinaryViewBase::onAfterSnapshotDataApplied", unsafe {
3487 let context = &mut *(ctxt as *mut CustomBinaryViewContext<C>);
3488 context.view.on_after_snapshot_data_applied();
3491 })
3492}
3493
3494extern "C" fn cb_free_object<C>(ctxt: *mut c_void)
3495where
3496 C: CustomBinaryView,
3497{
3498 ffi_wrap!("BinaryViewBase::freeObject", unsafe {
3499 let context = ctxt as *mut CustomBinaryViewContext<C>;
3500 let _context = Box::from_raw(context);
3501 })
3502}
3503
3504extern "C" fn cb_read<C>(ctxt: *mut c_void, dest: *mut c_void, offset: u64, len: usize) -> usize
3505where
3506 C: CustomBinaryView,
3507{
3508 ffi_wrap!("BinaryViewBase::read", unsafe {
3509 let context = &*(ctxt as *mut CustomBinaryViewContext<C>);
3510 let dest = std::slice::from_raw_parts_mut(dest as *mut u8, len);
3511 context.view.read(dest, offset)
3512 })
3513}
3514
3515extern "C" fn cb_write<C>(ctxt: *mut c_void, offset: u64, src: *const c_void, len: usize) -> usize
3516where
3517 C: CustomBinaryView,
3518{
3519 ffi_wrap!("BinaryViewBase::write", unsafe {
3520 let context = &*(ctxt as *mut CustomBinaryViewContext<C>);
3521 let src = std::slice::from_raw_parts(src as *const u8, len);
3522 context.view.write(offset, src)
3523 })
3524}
3525
3526extern "C" fn cb_insert<C>(ctxt: *mut c_void, offset: u64, src: *const c_void, len: usize) -> usize
3527where
3528 C: CustomBinaryView,
3529{
3530 ffi_wrap!("BinaryViewBase::insert", unsafe {
3531 let context = &*(ctxt as *mut CustomBinaryViewContext<C>);
3532 let src = std::slice::from_raw_parts(src as *const u8, len);
3533 context.view.insert(offset, src)
3534 })
3535}
3536
3537extern "C" fn cb_remove<C>(ctxt: *mut c_void, offset: u64, len: u64) -> usize
3538where
3539 C: CustomBinaryView,
3540{
3541 ffi_wrap!("BinaryViewBase::remove", unsafe {
3542 let context = &*(ctxt as *mut CustomBinaryViewContext<C>);
3543 context.view.remove(offset, len as usize)
3544 })
3545}
3546
3547extern "C" fn cb_modification<C>(ctxt: *mut c_void, offset: u64) -> ModificationStatus
3548where
3549 C: CustomBinaryView,
3550{
3551 ffi_wrap!("BinaryViewBase::modification_status", unsafe {
3552 let context = &*(ctxt as *mut CustomBinaryViewContext<C>);
3553 context.view.modification_status(offset)
3554 })
3555}
3556
3557extern "C" fn cb_offset_valid<C>(ctxt: *mut c_void, offset: u64) -> bool
3558where
3559 C: CustomBinaryView,
3560{
3561 ffi_wrap!("BinaryViewBase::offset_valid", unsafe {
3562 let context = &*(ctxt as *mut CustomBinaryViewContext<C>);
3563 context.view.offset_valid(offset)
3564 })
3565}
3566
3567extern "C" fn cb_offset_readable<C>(ctxt: *mut c_void, offset: u64) -> bool
3568where
3569 C: CustomBinaryView,
3570{
3571 ffi_wrap!("BinaryViewBase::readable", unsafe {
3572 let context = &*(ctxt as *mut CustomBinaryViewContext<C>);
3573 context.view.offset_readable(offset)
3574 })
3575}
3576
3577extern "C" fn cb_offset_writable<C>(ctxt: *mut c_void, offset: u64) -> bool
3578where
3579 C: CustomBinaryView,
3580{
3581 ffi_wrap!("BinaryViewBase::writable", unsafe {
3582 let context = &*(ctxt as *mut CustomBinaryViewContext<C>);
3583 context.view.offset_writable(offset)
3584 })
3585}
3586
3587extern "C" fn cb_offset_executable<C>(ctxt: *mut c_void, offset: u64) -> bool
3588where
3589 C: CustomBinaryView,
3590{
3591 ffi_wrap!("BinaryViewBase::offset_executable", unsafe {
3592 let context = &*(ctxt as *mut CustomBinaryViewContext<C>);
3593 context.view.offset_executable(offset)
3594 })
3595}
3596
3597extern "C" fn cb_offset_backed_by_file<C>(ctxt: *mut c_void, offset: u64) -> bool
3598where
3599 C: CustomBinaryView,
3600{
3601 ffi_wrap!("BinaryViewBase::offset_backed_by_file", unsafe {
3602 let context = &*(ctxt as *mut CustomBinaryViewContext<C>);
3603 context.view.offset_backed_by_file(offset)
3604 })
3605}
3606
3607extern "C" fn cb_next_valid_offset<C>(ctxt: *mut c_void, offset: u64) -> u64
3608where
3609 C: CustomBinaryView,
3610{
3611 ffi_wrap!("BinaryViewBase::next_valid_offset_after", unsafe {
3612 let context = &*(ctxt as *mut CustomBinaryViewContext<C>);
3613 context.view.next_valid_offset_after(offset)
3614 })
3615}
3616
3617extern "C" fn cb_start<C>(ctxt: *mut c_void) -> u64
3618where
3619 C: CustomBinaryView,
3620{
3621 ffi_wrap!("BinaryViewBase::start", unsafe {
3622 let context = &*(ctxt as *mut CustomBinaryViewContext<C>);
3623 context.view.start()
3624 })
3625}
3626
3627extern "C" fn cb_length<C>(ctxt: *mut c_void) -> u64
3628where
3629 C: CustomBinaryView,
3630{
3631 ffi_wrap!("BinaryViewBase::len", unsafe {
3632 let context = &*(ctxt as *mut CustomBinaryViewContext<C>);
3633 context.view.len()
3634 })
3635}
3636
3637extern "C" fn cb_entry_point<C>(ctxt: *mut c_void) -> u64
3638where
3639 C: CustomBinaryView,
3640{
3641 ffi_wrap!("BinaryViewBase::entry_point", unsafe {
3642 let context = &*(ctxt as *mut CustomBinaryViewContext<C>);
3643 context.view.entry_point()
3644 })
3645}
3646
3647extern "C" fn cb_executable<C>(ctxt: *mut c_void) -> bool
3648where
3649 C: CustomBinaryView,
3650{
3651 ffi_wrap!("BinaryViewBase::executable", unsafe {
3652 let context = &*(ctxt as *mut CustomBinaryViewContext<C>);
3653 context.view.executable()
3654 })
3655}
3656
3657extern "C" fn cb_endianness<C>(ctxt: *mut c_void) -> Endianness
3658where
3659 C: CustomBinaryView,
3660{
3661 ffi_wrap!("BinaryViewBase::default_endianness", unsafe {
3662 let context = &*(ctxt as *mut CustomBinaryViewContext<C>);
3663 context.view.default_endianness()
3664 })
3665}
3666
3667extern "C" fn cb_relocatable<C>(ctxt: *mut c_void) -> bool
3668where
3669 C: CustomBinaryView,
3670{
3671 ffi_wrap!("BinaryViewBase::relocatable", unsafe {
3672 let context = &*(ctxt as *mut CustomBinaryViewContext<C>);
3673 context.view.relocatable()
3674 })
3675}
3676
3677extern "C" fn cb_address_size<C>(ctxt: *mut c_void) -> usize
3678where
3679 C: CustomBinaryView,
3680{
3681 ffi_wrap!("BinaryViewBase::address_size", unsafe {
3682 let context = &*(ctxt as *mut CustomBinaryViewContext<C>);
3683 context.view.address_size()
3684 })
3685}
3686
3687extern "C" fn cb_save<C>(ctxt: *mut c_void, file: *mut BNFileAccessor) -> bool
3688where
3689 C: CustomBinaryView,
3690{
3691 ffi_wrap!("BinaryViewBase::save", unsafe {
3692 let context = &*(ctxt as *mut CustomBinaryViewContext<C>);
3693 let mut file = BorrowedFileAccessor::from_raw(file);
3694 context
3697 .view
3698 .save(context.core_view.assume_init_ref(), &mut file)
3699 })
3700}