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::{Accessor, FileAccessor};
36use crate::file_metadata::FileMetadata;
37use crate::flowgraph::FlowGraph;
38use crate::function::{Function, FunctionViewType, Location, NativeBlock};
39use crate::linear_view::{LinearDisassemblyLine, LinearViewCursor};
40use crate::metadata::Metadata;
41use crate::platform::Platform;
42use crate::progress::{NoProgressCallback, ProgressCallback};
43use crate::project::file::ProjectFile;
44use crate::rc::*;
45use crate::references::{CodeReference, DataReference};
46use crate::relocation::Relocation;
47use crate::section::{Section, SectionBuilder};
48use crate::segment::{Segment, SegmentBuilder};
49use crate::settings::Settings;
50use crate::string::*;
51use crate::symbol::{Symbol, SymbolType};
52use crate::tags::{Tag, TagReference, TagType};
53use crate::types::{
54 NamedTypeReference, QualifiedName, QualifiedNameAndType, QualifiedNameTypeAndId, Type,
55 TypeArchive, TypeArchiveId, TypeContainer, TypeLibrary,
56};
57use crate::variable::DataVariable;
58use crate::workflow::Workflow;
59use crate::{Endianness, BN_FULL_CONFIDENCE};
60use std::collections::{BTreeMap, HashMap};
61use std::ffi::{c_char, c_void, CString};
62use std::fmt::{Debug, Display, Formatter};
63use std::mem::MaybeUninit;
64use std::ops::Range;
65use std::path::{Path, PathBuf};
66use std::ptr::NonNull;
67
68pub mod memory_map;
69pub mod reader;
70pub mod search;
71pub mod writer;
72
73pub use memory_map::{MemoryMap, MemoryRegionInfo, ResolvedRange};
74pub use reader::BinaryReader;
75pub use writer::BinaryWriter;
76
77pub type BinaryViewEventType = BNBinaryViewEventType;
78pub type AnalysisState = BNAnalysisState;
79pub type ModificationStatus = BNModificationStatus;
80pub type StringType = BNStringType;
81pub type FindFlag = BNFindFlag;
82
83pub fn register_binary_view_type<T>(view_type: T) -> (&'static T, BinaryViewType)
85where
86 T: CustomBinaryViewType,
87{
88 let name = T::NAME.to_cstr();
89 let long_name = T::LONG_NAME.to_cstr();
90 let leaked_type = Box::leak(Box::new(view_type));
91
92 let result = unsafe {
93 BNRegisterBinaryViewType(
94 name.as_ref().as_ptr() as *const _,
95 long_name.as_ref().as_ptr() as *const _,
96 &mut BNCustomBinaryViewType {
97 context: leaked_type as *mut _ as *mut std::os::raw::c_void,
98 create: Some(cb_create::<T>),
99 parse: Some(cb_parse::<T>),
100 isValidForData: Some(cb_valid::<T>),
101 isDeprecated: Some(cb_deprecated::<T>),
102 isForceLoadable: Some(cb_force_loadable::<T>),
103 getLoadSettingsForData: Some(cb_load_settings::<T>),
104 hasNoInitialContent: Some(cb_has_no_initial_content::<T>),
105 },
106 )
107 };
108
109 assert!(
110 !result.is_null(),
111 "BNRegisterBinaryViewType always returns a non-null handle"
112 );
113 let core_view_type = unsafe { BinaryViewType::from_raw(result) };
114 (leaked_type, core_view_type)
115}
116
117pub trait CustomBinaryViewType: 'static + Sync {
119 type CustomBinaryView: CustomBinaryView;
121
122 const NAME: &'static str;
124
125 const LONG_NAME: &'static str = Self::NAME;
127
128 const DEPRECATED: bool = false;
133
134 const FORCE_LOADABLE: bool = false;
138
139 const HAS_NO_INITIAL_CONTENT: bool = false;
148
149 fn create_binary_view(&self, data: &BinaryView) -> Result<Self::CustomBinaryView, ()>;
151
152 fn create_binary_view_for_parse(
163 &self,
164 data: &BinaryView,
165 ) -> Result<Self::CustomBinaryView, ()> {
166 self.create_binary_view(data)
167 }
168
169 fn is_valid_for(&self, data: &BinaryView) -> bool;
174
175 fn load_settings_for_data(&self, _data: &BinaryView) -> Ref<Settings> {
176 Settings::new()
177 }
178}
179
180#[derive(Copy, Clone, PartialEq, Eq, Hash)]
186pub struct BinaryViewType {
187 pub handle: *mut BNBinaryViewType,
188}
189
190impl BinaryViewType {
191 pub(crate) unsafe fn from_raw(handle: *mut BNBinaryViewType) -> Self {
192 debug_assert!(!handle.is_null());
193 Self { handle }
194 }
195
196 pub fn list_all() -> Array<BinaryViewType> {
197 unsafe {
198 let mut count: usize = 0;
199 let types = BNGetBinaryViewTypes(&mut count as *mut _);
200 Array::new(types, count, ())
201 }
202 }
203
204 pub fn valid_types_for_data(data: &BinaryView) -> Array<BinaryViewType> {
207 unsafe {
208 let mut count: usize = 0;
209 let types = BNGetBinaryViewTypesForData(data.handle, &mut count as *mut _);
210 Array::new(types, count, ())
211 }
212 }
213
214 pub fn by_name(name: &str) -> Option<Self> {
216 let bytes = name.to_cstr();
217 let handle = unsafe { BNGetBinaryViewTypeByName(bytes.as_ref().as_ptr() as *const _) };
218 if handle.is_null() {
219 None
220 } else {
221 Some(unsafe { BinaryViewType::from_raw(handle) })
222 }
223 }
224
225 pub fn name(&self) -> String {
227 unsafe { BnString::into_string(BNGetBinaryViewTypeName(self.handle)) }
228 }
229
230 pub fn long_name(&self) -> String {
232 unsafe { BnString::into_string(BNGetBinaryViewTypeLongName(self.handle)) }
233 }
234
235 pub fn register_arch<A: Architecture>(&self, id: u32, endianness: Endianness, arch: &A) {
240 unsafe {
241 BNRegisterArchitectureForViewType(self.handle, id, endianness, arch.as_ref().handle);
242 }
243 }
244
245 pub fn register_platform(&self, id: u32, plat: &Platform) {
250 let arch = plat.arch();
251 unsafe {
252 BNRegisterPlatformForViewType(self.handle, id, arch.handle, plat.handle);
253 }
254 }
255
256 pub fn register_platform_recognizer<R>(&self, id: u32, endian: Endianness, recognizer: R)
275 where
276 R: 'static + Fn(&BinaryView, &Metadata) -> Option<Ref<Platform>> + Send + Sync,
277 {
278 #[repr(C)]
279 struct PlatformRecognizerHandlerContext<R>
280 where
281 R: 'static + Fn(&BinaryView, &Metadata) -> Option<Ref<Platform>> + Send + Sync,
282 {
283 recognizer: R,
284 }
285
286 extern "C" fn cb_recognize_low_level_il<R>(
287 ctxt: *mut std::os::raw::c_void,
288 bv: *mut BNBinaryView,
289 metadata: *mut BNMetadata,
290 ) -> *mut BNPlatform
291 where
292 R: 'static + Fn(&BinaryView, &Metadata) -> Option<Ref<Platform>> + Send + Sync,
293 {
294 let context = unsafe { &*(ctxt as *mut PlatformRecognizerHandlerContext<R>) };
295 let bv = unsafe { BinaryView::from_raw(bv).to_owned() };
296 let metadata = unsafe { Metadata::from_raw(metadata).to_owned() };
297 match (context.recognizer)(&bv, &metadata) {
298 Some(plat) => unsafe { Ref::into_raw(plat).handle },
299 None => std::ptr::null_mut(),
300 }
301 }
302
303 let recognizer = PlatformRecognizerHandlerContext { recognizer };
304 let raw = Box::into_raw(Box::new(recognizer));
305 unsafe {
306 BNRegisterPlatformRecognizerForViewType(
307 self.handle,
308 id as u64,
309 endian,
310 Some(cb_recognize_low_level_il::<R>),
311 raw as *mut std::os::raw::c_void,
312 )
313 }
314 }
315
316 pub fn create(&self, data: &BinaryView) -> Result<Ref<BinaryView>, ()> {
322 let handle = unsafe { BNCreateBinaryViewOfType(self.handle, data.handle) };
323 if handle.is_null() {
324 return Err(());
326 }
327 unsafe { Ok(BinaryView::ref_from_raw(handle)) }
328 }
329
330 pub fn parse(&self, data: &BinaryView) -> Result<Ref<BinaryView>, ()> {
334 let handle = unsafe { BNParseBinaryViewOfType(self.handle, data.handle) };
335 if handle.is_null() {
336 return Err(());
338 }
339 unsafe { Ok(BinaryView::ref_from_raw(handle)) }
340 }
341
342 pub fn is_valid_for(&self, data: &BinaryView) -> bool {
347 unsafe { BNIsBinaryViewTypeValidForData(self.handle, data.handle) }
348 }
349
350 pub fn is_deprecated(&self) -> bool {
355 unsafe { BNIsBinaryViewTypeDeprecated(self.handle) }
356 }
357
358 pub fn is_force_loadable(&self) -> bool {
362 unsafe { BNIsBinaryViewTypeForceLoadable(self.handle) }
363 }
364
365 pub fn has_no_initial_content(&self) -> bool {
374 unsafe { BNBinaryViewTypeHasNoInitialContent(self.handle) }
375 }
376
377 pub fn load_settings_for_data(&self, data: &BinaryView) -> Option<Ref<Settings>> {
378 let settings_handle =
379 unsafe { BNGetBinaryViewLoadSettingsForData(self.handle, data.handle) };
380
381 if settings_handle.is_null() {
382 None
383 } else {
384 unsafe { Some(Settings::ref_from_raw(settings_handle)) }
385 }
386 }
387}
388
389impl Debug for BinaryViewType {
390 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
391 f.debug_struct("BinaryViewType")
392 .field("name", &self.name())
393 .field("long_name", &self.long_name())
394 .finish()
395 }
396}
397
398impl CoreArrayProvider for BinaryViewType {
399 type Raw = *mut BNBinaryViewType;
400 type Context = ();
401 type Wrapped<'a> = Guard<'a, BinaryViewType>;
402}
403
404unsafe impl CoreArrayProviderInner for BinaryViewType {
405 unsafe fn free(raw: *mut Self::Raw, _count: usize, _context: &Self::Context) {
406 BNFreeBinaryViewTypeList(raw);
407 }
408
409 unsafe fn wrap_raw<'a>(raw: &'a Self::Raw, _context: &'a Self::Context) -> Self::Wrapped<'a> {
410 Guard::new(BinaryViewType::from_raw(*raw), &())
411 }
412}
413
414unsafe impl Send for BinaryViewType {}
415unsafe impl Sync for BinaryViewType {}
416
417pub trait CustomBinaryView: BinaryViewBase {
419 fn initialize(&mut self, view: &BinaryView) -> bool;
429
430 fn on_after_snapshot_data_applied(&mut self) {}
435}
436
437struct CustomBinaryViewContext<C: CustomBinaryView> {
440 core_view: MaybeUninit<BinaryView>,
443 view: C,
444}
445
446#[allow(clippy::len_without_is_empty)]
447pub trait BinaryViewBase {
448 fn read(&self, _buf: &mut [u8], _offset: u64) -> usize {
449 0
450 }
451
452 fn write(&self, _offset: u64, _data: &[u8]) -> usize {
453 0
454 }
455
456 fn insert(&self, _offset: u64, _data: &[u8]) -> usize {
457 0
458 }
459
460 fn remove(&self, _offset: u64, _len: usize) -> usize {
461 0
462 }
463
464 fn offset_valid(&self, offset: u64) -> bool {
466 let mut buf = [0u8; 1];
467 self.read(&mut buf[..], offset) == buf.len()
468 }
469
470 fn offset_readable(&self, offset: u64) -> bool {
472 self.offset_valid(offset)
473 }
474
475 fn offset_writable(&self, offset: u64) -> bool {
477 self.offset_valid(offset)
478 }
479
480 fn offset_executable(&self, offset: u64) -> bool {
482 self.offset_valid(offset)
483 }
484
485 fn offset_backed_by_file(&self, offset: u64) -> bool {
487 self.offset_valid(offset)
488 }
489
490 fn next_valid_offset_after(&self, offset: u64) -> u64 {
493 let start = self.start();
494 if offset < start {
495 start
496 } else {
497 offset
498 }
499 }
500
501 fn modification_status(&self, _offset: u64) -> ModificationStatus {
503 ModificationStatus::Original
504 }
505
506 fn start(&self) -> u64 {
508 0
509 }
510
511 fn len(&self) -> u64 {
513 0
514 }
515
516 fn executable(&self) -> bool {
517 true
518 }
519
520 fn relocatable(&self) -> bool {
521 false
522 }
523
524 fn entry_point(&self) -> u64 {
525 0
526 }
527
528 fn default_endianness(&self) -> Endianness;
529
530 fn address_size(&self) -> usize;
531
532 fn save(&self) -> bool {
534 false
535 }
536}
537
538#[derive(Debug, Clone)]
539pub struct ActiveAnalysisInfo {
540 pub func: Ref<Function>,
541 pub analysis_time: u64,
542 pub update_count: usize,
543 pub submit_count: usize,
544}
545
546#[derive(Debug, Clone)]
547pub struct AnalysisInfo {
548 pub state: AnalysisState,
549 pub analysis_time: u64,
550 pub active_info: Vec<ActiveAnalysisInfo>,
551}
552
553#[derive(Debug, Clone, Ord, PartialOrd, Eq, PartialEq)]
554pub enum AnalysisProgress {
555 Initial,
556 Hold,
557 Idle,
558 Discovery,
559 Disassembling(usize, usize),
560 Analyzing(usize, usize),
561 ExtendedAnalysis,
562}
563
564impl Display for AnalysisProgress {
565 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
566 match self {
567 AnalysisProgress::Initial => {
568 write!(f, "Initial")
569 }
570 AnalysisProgress::Hold => {
571 write!(f, "Hold")
572 }
573 AnalysisProgress::Idle => {
574 write!(f, "Idle")
575 }
576 AnalysisProgress::Discovery => {
577 write!(f, "Discovery")
578 }
579 AnalysisProgress::Disassembling(count, total) => {
580 write!(f, "Disassembling ({count}/{total})")
581 }
582 AnalysisProgress::Analyzing(count, total) => {
583 write!(f, "Analyzing ({count}/{total})")
584 }
585 AnalysisProgress::ExtendedAnalysis => {
586 write!(f, "Extended Analysis")
587 }
588 }
589 }
590}
591
592impl From<BNAnalysisProgress> for AnalysisProgress {
593 fn from(value: BNAnalysisProgress) -> Self {
594 match value.state {
595 BNAnalysisState::InitialState => Self::Initial,
596 BNAnalysisState::HoldState => Self::Hold,
597 BNAnalysisState::IdleState => Self::Idle,
598 BNAnalysisState::DiscoveryState => Self::Discovery,
599 BNAnalysisState::DisassembleState => Self::Disassembling(value.count, value.total),
600 BNAnalysisState::AnalyzeState => Self::Analyzing(value.count, value.total),
601 BNAnalysisState::ExtendedAnalyzeState => Self::ExtendedAnalysis,
602 }
603 }
604}
605
606#[derive(PartialEq, Eq, Hash)]
633pub struct BinaryView {
634 pub handle: *mut BNBinaryView,
635}
636
637impl BinaryView {
638 pub unsafe fn from_raw(handle: *mut BNBinaryView) -> Self {
639 debug_assert!(!handle.is_null());
640 Self { handle }
641 }
642
643 pub(crate) unsafe fn ref_from_raw(handle: *mut BNBinaryView) -> Ref<Self> {
644 debug_assert!(!handle.is_null());
645 Ref::new(Self { handle })
646 }
647
648 pub fn from_custom<C: CustomBinaryView>(
650 view_type_name: &str,
651 file: &FileMetadata,
652 parent_view: &BinaryView,
653 view: C,
654 ) -> Result<Ref<Self>, ()> {
655 let type_name = view_type_name.to_cstr();
656 let custom_context = CustomBinaryViewContext {
659 core_view: MaybeUninit::uninit(),
660 view,
661 };
662 let leaked_view = Box::leak(Box::new(custom_context));
664 let handle = unsafe {
665 BNCreateCustomBinaryView(
666 type_name.as_ptr(),
667 file.handle,
668 parent_view.handle,
669 &mut BNCustomBinaryView {
670 context: leaked_view as *mut CustomBinaryViewContext<C> as *mut _,
671 init: Some(cb_init::<C>),
672 freeObject: Some(cb_free_object::<C>),
673 externalRefTaken: None,
674 externalRefReleased: None,
675 read: Some(cb_read::<C>),
676 write: Some(cb_write::<C>),
677 insert: Some(cb_insert::<C>),
678 remove: Some(cb_remove::<C>),
679 getModification: Some(cb_modification::<C>),
680 isValidOffset: Some(cb_offset_valid::<C>),
681 isOffsetReadable: Some(cb_offset_readable::<C>),
682 isOffsetWritable: Some(cb_offset_writable::<C>),
683 isOffsetExecutable: Some(cb_offset_executable::<C>),
684 isOffsetBackedByFile: Some(cb_offset_backed_by_file::<C>),
685 getNextValidOffset: Some(cb_next_valid_offset::<C>),
686 getStart: Some(cb_start::<C>),
687 getLength: Some(cb_length::<C>),
688 getEntryPoint: Some(cb_entry_point::<C>),
689 isExecutable: Some(cb_executable::<C>),
690 getDefaultEndianness: Some(cb_endianness::<C>),
691 isRelocatable: Some(cb_relocatable::<C>),
692 getAddressSize: Some(cb_address_size::<C>),
693 save: Some(cb_save::<C>),
694 onAfterSnapshotDataApplied: Some(cb_on_after_snapshot_data_applied::<C>),
695 },
696 )
697 };
698 if handle.is_null() {
699 let _ = unsafe { Box::from_raw(leaked_view) };
701 return Err(());
702 }
703 leaked_view.core_view = unsafe { MaybeUninit::new(BinaryView::from_raw(handle)) };
704 unsafe { Ok(Ref::new(Self { handle })) }
705 }
706
707 pub fn from_metadata(meta: &FileMetadata) -> Result<Ref<Self>, ()> {
712 if !meta.file_path().exists() {
713 return Err(());
714 }
715 let file = meta.file_path().to_cstr();
716 let handle =
717 unsafe { BNCreateBinaryDataViewFromFilename(meta.handle, file.as_ptr() as *mut _) };
718 if handle.is_null() {
719 return Err(());
720 }
721 unsafe { Ok(Ref::new(Self { handle })) }
722 }
723
724 pub fn from_path(meta: &FileMetadata, file_path: impl AsRef<Path>) -> Result<Ref<Self>, ()> {
729 meta.set_file_path(file_path.as_ref());
730 Self::from_metadata(meta)
731 }
732
733 pub unsafe fn from_accessor<A: Accessor>(
739 meta: &FileMetadata,
740 accessor: &mut FileAccessor<A>,
741 ) -> Result<Ref<Self>, ()> {
742 let handle = unsafe { BNCreateBinaryDataViewFromFile(meta.handle, &mut accessor.raw) };
743 if handle.is_null() {
744 return Err(());
745 }
746 unsafe { Ok(Ref::new(Self { handle })) }
747 }
748
749 pub fn from_data(meta: &FileMetadata, data: &[u8]) -> Ref<Self> {
753 let handle = unsafe {
754 BNCreateBinaryDataViewFromData(meta.handle, data.as_ptr() as *mut _, data.len())
755 };
756 assert!(
757 !handle.is_null(),
758 "BNCreateBinaryDataViewFromData should always succeed"
759 );
760 unsafe { Ref::new(Self { handle }) }
761 }
762
763 pub fn save_to_path(&self, file_path: impl AsRef<Path>) -> bool {
772 let file = file_path.as_ref().to_cstr();
773 unsafe { BNSaveToFilename(self.handle, file.as_ptr() as *mut _) }
774 }
775
776 pub fn save_to_accessor<A: Accessor>(&self, file: &mut FileAccessor<A>) -> bool {
785 unsafe { BNSaveToFile(self.handle, &mut file.raw) }
786 }
787
788 pub fn file(&self) -> Ref<FileMetadata> {
789 unsafe {
790 let raw = BNGetFileForView(self.handle);
791 FileMetadata::ref_from_raw(raw)
792 }
793 }
794
795 pub fn parent_view(&self) -> Option<Ref<BinaryView>> {
796 let raw_view_ptr = unsafe { BNGetParentView(self.handle) };
797 match raw_view_ptr.is_null() {
798 false => Some(unsafe { BinaryView::ref_from_raw(raw_view_ptr) }),
799 true => None,
800 }
801 }
802
803 pub fn raw_view(&self) -> Option<Ref<BinaryView>> {
804 self.file().view_of_type("Raw")
805 }
806
807 pub fn view_type(&self) -> String {
808 let ptr: *mut c_char = unsafe { BNGetViewType(self.handle) };
809 unsafe { BnString::into_string(ptr) }
810 }
811
812 pub fn read_vec(&self, offset: u64, len: usize) -> Vec<u8> {
814 let mut ret = vec![0; len];
815 let size = self.read(&mut ret, offset);
816 ret.truncate(size);
817 ret
818 }
819
820 pub fn read_into_vec(&self, dest: &mut Vec<u8>, offset: u64, len: usize) -> usize {
822 let starting_len = dest.len();
823 dest.resize(starting_len + len, 0);
824 let read_size = self.read(&mut dest[starting_len..], offset);
825 dest.truncate(starting_len + read_size);
826 read_size
827 }
828
829 pub fn read_c_string_at(&self, offset: u64, len: usize) -> Option<CString> {
831 let mut buf = vec![0; len];
832 let size = self.read(&mut buf, offset);
833 let string = CString::new(buf[..size].to_vec()).ok()?;
834 Some(string)
835 }
836
837 pub fn read_utf8_string_at(&self, offset: u64, len: usize) -> Option<String> {
839 let mut buf = vec![0; len];
840 let size = self.read(&mut buf, offset);
841 let string = String::from_utf8(buf[..size].to_vec()).ok()?;
842 Some(string)
843 }
844
845 pub fn search<C: FnMut(u64, &DataBuffer) -> bool>(
849 &self,
850 query: &SearchQuery,
851 on_match: C,
852 ) -> bool {
853 self.search_with_progress(query, on_match, NoProgressCallback)
854 }
855
856 pub fn search_with_progress<P: ProgressCallback, C: FnMut(u64, &DataBuffer) -> bool>(
860 &self,
861 query: &SearchQuery,
862 mut on_match: C,
863 mut progress: P,
864 ) -> bool {
865 unsafe extern "C" fn cb_on_match<C: FnMut(u64, &DataBuffer) -> bool>(
866 ctx: *mut c_void,
867 offset: u64,
868 data: *mut BNDataBuffer,
869 ) -> bool {
870 let f = ctx as *mut C;
871 let buffer = DataBuffer::from_raw(data);
872 (*f)(offset, &buffer)
873 }
874
875 let query = query.to_json().to_cstr();
876 unsafe {
877 BNSearch(
878 self.handle,
879 query.as_ptr(),
880 &mut progress as *mut P as *mut c_void,
881 Some(P::cb_progress_callback),
882 &mut on_match as *const C as *mut c_void,
883 Some(cb_on_match::<C>),
884 )
885 }
886 }
887
888 pub fn find_next_data(&self, start: u64, end: u64, data: &DataBuffer) -> Option<u64> {
889 self.find_next_data_with_opts(
890 start,
891 end,
892 data,
893 FindFlag::FindCaseInsensitive,
894 NoProgressCallback,
895 )
896 }
897
898 pub fn find_next_data_with_opts<P: ProgressCallback>(
902 &self,
903 start: u64,
904 end: u64,
905 data: &DataBuffer,
906 flag: FindFlag,
907 mut progress: P,
908 ) -> Option<u64> {
909 let mut result: u64 = 0;
910 let found = unsafe {
911 BNFindNextDataWithProgress(
912 self.handle,
913 start,
914 end,
915 data.as_raw(),
916 &mut result,
917 flag,
918 &mut progress as *mut P as *mut c_void,
919 Some(P::cb_progress_callback),
920 )
921 };
922
923 if found {
924 Some(result)
925 } else {
926 None
927 }
928 }
929
930 pub fn find_next_constant(
931 &self,
932 start: u64,
933 end: u64,
934 constant: u64,
935 view_type: FunctionViewType,
936 ) -> Option<u64> {
937 let settings = DisassemblySettings::new();
939 self.find_next_constant_with_opts(
940 start,
941 end,
942 constant,
943 &settings,
944 view_type,
945 NoProgressCallback,
946 )
947 }
948
949 pub fn find_next_constant_with_opts<P: ProgressCallback>(
953 &self,
954 start: u64,
955 end: u64,
956 constant: u64,
957 disasm_settings: &DisassemblySettings,
958 view_type: FunctionViewType,
959 mut progress: P,
960 ) -> Option<u64> {
961 let mut result: u64 = 0;
962 let raw_view_type = FunctionViewType::into_raw(view_type);
963 let found = unsafe {
964 BNFindNextConstantWithProgress(
965 self.handle,
966 start,
967 end,
968 constant,
969 &mut result,
970 disasm_settings.handle,
971 raw_view_type,
972 &mut progress as *mut P as *mut c_void,
973 Some(P::cb_progress_callback),
974 )
975 };
976 FunctionViewType::free_raw(raw_view_type);
977
978 if found {
979 Some(result)
980 } else {
981 None
982 }
983 }
984
985 pub fn find_next_text(
986 &self,
987 start: u64,
988 end: u64,
989 text: &str,
990 view_type: FunctionViewType,
991 ) -> Option<u64> {
992 let settings = DisassemblySettings::new();
994 self.find_next_text_with_opts(
995 start,
996 end,
997 text,
998 &settings,
999 FindFlag::FindCaseInsensitive,
1000 view_type,
1001 NoProgressCallback,
1002 )
1003 }
1004
1005 pub fn find_next_text_with_opts<P: ProgressCallback>(
1009 &self,
1010 start: u64,
1011 end: u64,
1012 text: &str,
1013 disasm_settings: &DisassemblySettings,
1014 flag: FindFlag,
1015 view_type: FunctionViewType,
1016 mut progress: P,
1017 ) -> Option<u64> {
1018 let text = text.to_cstr();
1019 let raw_view_type = FunctionViewType::into_raw(view_type);
1020 let mut result: u64 = 0;
1021 let found = unsafe {
1022 BNFindNextTextWithProgress(
1023 self.handle,
1024 start,
1025 end,
1026 text.as_ptr(),
1027 &mut result,
1028 disasm_settings.handle,
1029 flag,
1030 raw_view_type,
1031 &mut progress as *mut P as *mut c_void,
1032 Some(P::cb_progress_callback),
1033 )
1034 };
1035 FunctionViewType::free_raw(raw_view_type);
1036
1037 if found {
1038 Some(result)
1039 } else {
1040 None
1041 }
1042 }
1043
1044 pub fn notify_data_written(&self, offset: u64, len: usize) {
1045 unsafe {
1046 BNNotifyDataWritten(self.handle, offset, len);
1047 }
1048 }
1049
1050 pub fn notify_data_inserted(&self, offset: u64, len: usize) {
1051 unsafe {
1052 BNNotifyDataInserted(self.handle, offset, len);
1053 }
1054 }
1055
1056 pub fn notify_data_removed(&self, offset: u64, len: usize) {
1057 unsafe {
1058 BNNotifyDataRemoved(self.handle, offset, len as u64);
1059 }
1060 }
1061
1062 pub fn offset_has_code_semantics(&self, offset: u64) -> bool {
1065 unsafe { BNIsOffsetCodeSemantics(self.handle, offset) }
1066 }
1067
1068 pub fn offset_has_extern_semantics(&self, offset: u64) -> bool {
1070 unsafe { BNIsOffsetExternSemantics(self.handle, offset) }
1071 }
1072
1073 pub fn offset_has_writable_semantics(&self, offset: u64) -> bool {
1076 unsafe { BNIsOffsetWritableSemantics(self.handle, offset) }
1077 }
1078
1079 pub fn offset_has_read_only_semantics(&self, offset: u64) -> bool {
1082 unsafe { BNIsOffsetReadOnlySemantics(self.handle, offset) }
1083 }
1084
1085 pub fn image_base(&self) -> u64 {
1086 unsafe { BNGetImageBase(self.handle) }
1087 }
1088
1089 pub fn original_image_base(&self) -> u64 {
1090 unsafe { BNGetOriginalImageBase(self.handle) }
1091 }
1092
1093 pub fn set_original_image_base(&self, image_base: u64) {
1094 unsafe { BNSetOriginalImageBase(self.handle, image_base) }
1095 }
1096
1097 pub fn end(&self) -> u64 {
1099 unsafe { BNGetEndOffset(self.handle) }
1100 }
1101
1102 pub fn add_analysis_option(&self, name: &str) {
1103 let name = name.to_cstr();
1104 unsafe { BNAddAnalysisOption(self.handle, name.as_ptr()) }
1105 }
1106
1107 pub fn has_initial_analysis(&self) -> bool {
1108 unsafe { BNHasInitialAnalysis(self.handle) }
1109 }
1110
1111 pub fn set_analysis_hold(&self, enable: bool) {
1112 unsafe { BNSetAnalysisHold(self.handle, enable) }
1113 }
1114
1115 pub fn update_analysis(&self) {
1124 unsafe {
1125 BNUpdateAnalysis(self.handle);
1126 }
1127 }
1128
1129 pub fn update_analysis_and_wait(&self) {
1138 unsafe {
1139 BNUpdateAnalysisAndWait(self.handle);
1140 }
1141 }
1142
1143 pub fn reanalyze(&self) {
1150 unsafe {
1151 BNReanalyzeAllFunctions(self.handle);
1152 }
1153 }
1154
1155 pub fn abort_analysis(&self) {
1156 unsafe { BNAbortAnalysis(self.handle) }
1157 }
1158
1159 pub fn analysis_is_aborted(&self) -> bool {
1160 unsafe { BNAnalysisIsAborted(self.handle) }
1161 }
1162
1163 pub fn workflow(&self) -> Ref<Workflow> {
1164 unsafe {
1165 let raw_ptr = BNGetWorkflowForBinaryView(self.handle);
1166 let nonnull = NonNull::new(raw_ptr).expect("All views must have a workflow");
1167 Workflow::ref_from_raw(nonnull)
1168 }
1169 }
1170
1171 pub fn analysis_info(&self) -> AnalysisInfo {
1172 let info_ptr = unsafe { BNGetAnalysisInfo(self.handle) };
1173 assert!(!info_ptr.is_null());
1174 let info = unsafe { *info_ptr };
1175 let active_infos = unsafe { std::slice::from_raw_parts(info.activeInfo, info.count) };
1176
1177 let mut active_info_list = vec![];
1178 for active_info in active_infos {
1179 let func = unsafe { Function::from_raw(active_info.func).to_owned() };
1180 active_info_list.push(ActiveAnalysisInfo {
1181 func,
1182 analysis_time: active_info.analysisTime,
1183 update_count: active_info.updateCount,
1184 submit_count: active_info.submitCount,
1185 });
1186 }
1187
1188 let result = AnalysisInfo {
1189 state: info.state,
1190 analysis_time: info.analysisTime,
1191 active_info: active_info_list,
1192 };
1193
1194 unsafe { BNFreeAnalysisInfo(info_ptr) };
1195 result
1196 }
1197
1198 pub fn analysis_progress(&self) -> AnalysisProgress {
1199 let progress_raw = unsafe { BNGetAnalysisProgress(self.handle) };
1200 AnalysisProgress::from(progress_raw)
1201 }
1202
1203 pub fn default_arch(&self) -> Option<CoreArchitecture> {
1204 unsafe {
1205 let raw = BNGetDefaultArchitecture(self.handle);
1206
1207 if raw.is_null() {
1208 return None;
1209 }
1210
1211 Some(CoreArchitecture::from_raw(raw))
1212 }
1213 }
1214
1215 pub fn set_default_arch<A: Architecture>(&self, arch: &A) {
1216 unsafe {
1217 BNSetDefaultArchitecture(self.handle, arch.as_ref().handle);
1218 }
1219 }
1220
1221 pub fn default_platform(&self) -> Option<Ref<Platform>> {
1222 unsafe {
1223 let raw = BNGetDefaultPlatform(self.handle);
1224
1225 if raw.is_null() {
1226 return None;
1227 }
1228
1229 Some(Platform::ref_from_raw(raw))
1230 }
1231 }
1232
1233 pub fn set_default_platform(&self, plat: &Platform) {
1234 unsafe {
1235 BNSetDefaultPlatform(self.handle, plat.handle);
1236 }
1237 }
1238
1239 pub fn base_address_detection(&self) -> Option<BaseAddressDetection> {
1240 unsafe {
1241 let handle = BNCreateBaseAddressDetection(self.handle);
1242 NonNull::new(handle).map(|base| BaseAddressDetection::from_raw(base))
1243 }
1244 }
1245
1246 pub fn instruction_len<A: Architecture>(&self, arch: &A, addr: u64) -> Option<usize> {
1247 unsafe {
1248 let size = BNGetInstructionLength(self.handle, arch.as_ref().handle, addr);
1249
1250 if size > 0 {
1251 Some(size)
1252 } else {
1253 None
1254 }
1255 }
1256 }
1257
1258 pub fn symbol_by_address(&self, addr: u64) -> Option<Ref<Symbol>> {
1259 unsafe {
1260 let raw_sym_ptr = BNGetSymbolByAddress(self.handle, addr, std::ptr::null_mut());
1261 match raw_sym_ptr.is_null() {
1262 false => Some(Symbol::ref_from_raw(raw_sym_ptr)),
1263 true => None,
1264 }
1265 }
1266 }
1267
1268 pub fn symbol_by_raw_name(&self, raw_name: impl IntoCStr) -> Option<Ref<Symbol>> {
1269 let raw_name = raw_name.to_cstr();
1270
1271 unsafe {
1272 let raw_sym_ptr =
1273 BNGetSymbolByRawName(self.handle, raw_name.as_ptr(), std::ptr::null_mut());
1274 match raw_sym_ptr.is_null() {
1275 false => Some(Symbol::ref_from_raw(raw_sym_ptr)),
1276 true => None,
1277 }
1278 }
1279 }
1280
1281 pub fn symbols(&self) -> Array<Symbol> {
1282 unsafe {
1283 let mut count = 0;
1284 let handles = BNGetSymbols(self.handle, &mut count, std::ptr::null_mut());
1285
1286 Array::new(handles, count, ())
1287 }
1288 }
1289
1290 pub fn symbols_by_name(&self, name: impl IntoCStr) -> Array<Symbol> {
1291 let raw_name = name.to_cstr();
1292
1293 unsafe {
1294 let mut count = 0;
1295 let handles = BNGetSymbolsByName(
1296 self.handle,
1297 raw_name.as_ptr(),
1298 &mut count,
1299 std::ptr::null_mut(),
1300 );
1301
1302 Array::new(handles, count, ())
1303 }
1304 }
1305
1306 pub fn symbols_in_range(&self, range: Range<u64>) -> Array<Symbol> {
1307 unsafe {
1308 let mut count = 0;
1309 let len = range.end.wrapping_sub(range.start);
1310 let handles = BNGetSymbolsInRange(
1311 self.handle,
1312 range.start,
1313 len,
1314 &mut count,
1315 std::ptr::null_mut(),
1316 );
1317
1318 Array::new(handles, count, ())
1319 }
1320 }
1321
1322 pub fn symbols_of_type(&self, ty: SymbolType) -> Array<Symbol> {
1323 unsafe {
1324 let mut count = 0;
1325 let handles =
1326 BNGetSymbolsOfType(self.handle, ty.into(), &mut count, std::ptr::null_mut());
1327
1328 Array::new(handles, count, ())
1329 }
1330 }
1331
1332 pub fn symbols_of_type_in_range(&self, ty: SymbolType, range: Range<u64>) -> Array<Symbol> {
1333 unsafe {
1334 let mut count = 0;
1335 let len = range.end.wrapping_sub(range.start);
1336 let handles = BNGetSymbolsOfTypeInRange(
1337 self.handle,
1338 ty.into(),
1339 range.start,
1340 len,
1341 &mut count,
1342 std::ptr::null_mut(),
1343 );
1344
1345 Array::new(handles, count, ())
1346 }
1347 }
1348
1349 pub fn define_auto_symbol(&self, sym: &Symbol) {
1350 unsafe {
1351 BNDefineAutoSymbol(self.handle, sym.handle);
1352 }
1353 }
1354
1355 pub fn define_auto_symbol_with_type<'a, T: Into<Option<&'a Type>>>(
1359 &self,
1360 sym: &Symbol,
1361 plat: &Platform,
1362 ty: T,
1363 ) -> Ref<Symbol> {
1364 let mut type_with_conf = BNTypeWithConfidence {
1365 type_: if let Some(t) = ty.into() {
1366 t.handle
1367 } else {
1368 std::ptr::null_mut()
1369 },
1370 confidence: BN_FULL_CONFIDENCE,
1371 };
1372
1373 unsafe {
1374 let raw_sym = BNDefineAutoSymbolAndVariableOrFunction(
1375 self.handle,
1376 plat.handle,
1377 sym.handle,
1378 &mut type_with_conf,
1379 );
1380 debug_assert!(
1382 !raw_sym.is_null(),
1383 "BNDefineAutoSymbolAndVariableOrFunction should not return null"
1384 );
1385 Symbol::ref_from_raw(raw_sym)
1386 }
1387 }
1388
1389 pub fn undefine_auto_symbol(&self, sym: &Symbol) {
1390 unsafe {
1391 BNUndefineAutoSymbol(self.handle, sym.handle);
1392 }
1393 }
1394
1395 pub fn define_user_symbol(&self, sym: &Symbol) {
1396 unsafe {
1397 BNDefineUserSymbol(self.handle, sym.handle);
1398 }
1399 }
1400
1401 pub fn undefine_user_symbol(&self, sym: &Symbol) {
1402 unsafe {
1403 BNUndefineUserSymbol(self.handle, sym.handle);
1404 }
1405 }
1406
1407 pub fn data_variables(&self) -> Array<DataVariable> {
1408 unsafe {
1409 let mut count = 0;
1410 let vars = BNGetDataVariables(self.handle, &mut count);
1411 Array::new(vars, count, ())
1412 }
1413 }
1414
1415 pub fn data_variable_at_address(&self, addr: u64) -> Option<DataVariable> {
1416 let mut dv = BNDataVariable::default();
1417 unsafe {
1418 if BNGetDataVariableAtAddress(self.handle, addr, &mut dv) {
1419 Some(DataVariable::from_owned_raw(dv))
1420 } else {
1421 None
1422 }
1423 }
1424 }
1425
1426 pub fn define_auto_data_var<'a, T: Into<Conf<&'a Type>>>(&self, addr: u64, ty: T) {
1427 let mut owned_raw_ty = Conf::<&Type>::into_raw(ty.into());
1428 unsafe {
1429 BNDefineDataVariable(self.handle, addr, &mut owned_raw_ty);
1430 }
1431 }
1432
1433 pub fn define_user_data_var<'a, T: Into<Conf<&'a Type>>>(&self, addr: u64, ty: T) {
1435 let mut owned_raw_ty = Conf::<&Type>::into_raw(ty.into());
1436 unsafe {
1437 BNDefineUserDataVariable(self.handle, addr, &mut owned_raw_ty);
1438 }
1439 }
1440
1441 pub fn undefine_auto_data_var(&self, addr: u64, blacklist: Option<bool>) {
1442 unsafe {
1443 BNUndefineDataVariable(self.handle, addr, blacklist.unwrap_or(true));
1444 }
1445 }
1446
1447 pub fn undefine_user_data_var(&self, addr: u64) {
1448 unsafe {
1449 BNUndefineUserDataVariable(self.handle, addr);
1450 }
1451 }
1452
1453 pub fn define_auto_type<T: Into<QualifiedName>>(
1454 &self,
1455 name: T,
1456 source: &str,
1457 type_obj: &Type,
1458 ) -> QualifiedName {
1459 let mut raw_name = QualifiedName::into_raw(name.into());
1460 let source_str = source.to_cstr();
1461 let name_handle = unsafe {
1462 let id_str =
1463 BNGenerateAutoTypeId(source_str.as_ref().as_ptr() as *const _, &mut raw_name);
1464 BNDefineAnalysisType(self.handle, id_str, &mut raw_name, type_obj.handle)
1465 };
1466 QualifiedName::free_raw(raw_name);
1467 QualifiedName::from_owned_raw(name_handle)
1468 }
1469
1470 pub fn define_auto_type_with_id<T: Into<QualifiedName>>(
1471 &self,
1472 name: T,
1473 id: &str,
1474 type_obj: &Type,
1475 ) -> QualifiedName {
1476 let mut raw_name = QualifiedName::into_raw(name.into());
1477 let id_str = id.to_cstr();
1478 let result_raw_name = unsafe {
1479 BNDefineAnalysisType(
1480 self.handle,
1481 id_str.as_ref().as_ptr() as *const _,
1482 &mut raw_name,
1483 type_obj.handle,
1484 )
1485 };
1486 QualifiedName::free_raw(raw_name);
1487 QualifiedName::from_owned_raw(result_raw_name)
1488 }
1489
1490 pub fn define_user_type<T: Into<QualifiedName>>(&self, name: T, type_obj: &Type) {
1491 let mut raw_name = QualifiedName::into_raw(name.into());
1492 unsafe { BNDefineUserAnalysisType(self.handle, &mut raw_name, type_obj.handle) }
1493 QualifiedName::free_raw(raw_name);
1494 }
1495
1496 pub fn define_auto_types<T, I>(
1497 &self,
1498 names_sources_and_types: T,
1499 ) -> HashMap<String, QualifiedName>
1500 where
1501 T: Iterator<Item = I>,
1502 I: Into<QualifiedNameTypeAndId>,
1503 {
1504 self.define_auto_types_with_progress(names_sources_and_types, NoProgressCallback)
1505 }
1506
1507 pub fn define_auto_types_with_progress<T, I, P>(
1508 &self,
1509 names_sources_and_types: T,
1510 mut progress: P,
1511 ) -> HashMap<String, QualifiedName>
1512 where
1513 T: Iterator<Item = I>,
1514 I: Into<QualifiedNameTypeAndId>,
1515 P: ProgressCallback,
1516 {
1517 let mut types: Vec<BNQualifiedNameTypeAndId> = names_sources_and_types
1518 .map(Into::into)
1519 .map(QualifiedNameTypeAndId::into_raw)
1520 .collect();
1521 let mut result_ids: *mut *mut c_char = std::ptr::null_mut();
1522 let mut result_names: *mut BNQualifiedName = std::ptr::null_mut();
1523
1524 let result_count = unsafe {
1525 BNDefineAnalysisTypes(
1526 self.handle,
1527 types.as_mut_ptr(),
1528 types.len(),
1529 Some(P::cb_progress_callback),
1530 &mut progress as *mut P as *mut c_void,
1531 &mut result_ids as *mut _,
1532 &mut result_names as *mut _,
1533 )
1534 };
1535
1536 for ty in types {
1537 QualifiedNameTypeAndId::free_raw(ty);
1538 }
1539
1540 let id_array = unsafe { Array::<BnString>::new(result_ids, result_count, ()) };
1541 let name_array = unsafe { Array::<QualifiedName>::new(result_names, result_count, ()) };
1542 id_array
1543 .into_iter()
1544 .zip(&name_array)
1545 .map(|(id, name)| (id.to_owned(), name))
1546 .collect()
1547 }
1548
1549 pub fn define_user_types<T, I>(&self, names_and_types: T)
1550 where
1551 T: Iterator<Item = I>,
1552 I: Into<QualifiedNameAndType>,
1553 {
1554 self.define_user_types_with_progress(names_and_types, NoProgressCallback);
1555 }
1556
1557 pub fn define_user_types_with_progress<T, I, P>(&self, names_and_types: T, mut progress: P)
1558 where
1559 T: Iterator<Item = I>,
1560 I: Into<QualifiedNameAndType>,
1561 P: ProgressCallback,
1562 {
1563 let mut types: Vec<BNQualifiedNameAndType> = names_and_types
1564 .map(Into::into)
1565 .map(QualifiedNameAndType::into_raw)
1566 .collect();
1567
1568 unsafe {
1569 BNDefineUserAnalysisTypes(
1570 self.handle,
1571 types.as_mut_ptr(),
1572 types.len(),
1573 Some(P::cb_progress_callback),
1574 &mut progress as *mut P as *mut c_void,
1575 )
1576 };
1577
1578 for ty in types {
1579 QualifiedNameAndType::free_raw(ty);
1580 }
1581 }
1582
1583 pub fn undefine_auto_type(&self, id: &str) {
1584 let id_str = id.to_cstr();
1585 unsafe {
1586 BNUndefineAnalysisType(self.handle, id_str.as_ref().as_ptr() as *const _);
1587 }
1588 }
1589
1590 pub fn undefine_user_type<T: Into<QualifiedName>>(&self, name: T) {
1591 let mut raw_name = QualifiedName::into_raw(name.into());
1592 unsafe { BNUndefineUserAnalysisType(self.handle, &mut raw_name) }
1593 QualifiedName::free_raw(raw_name);
1594 }
1595
1596 pub fn types(&self) -> Array<QualifiedNameAndType> {
1597 unsafe {
1598 let mut count = 0usize;
1599 let types = BNGetAnalysisTypeList(self.handle, &mut count);
1600 Array::new(types, count, ())
1601 }
1602 }
1603
1604 pub fn dependency_sorted_types(&self) -> Array<QualifiedNameAndType> {
1605 unsafe {
1606 let mut count = 0usize;
1607 let types = BNGetAnalysisDependencySortedTypeList(self.handle, &mut count);
1608 Array::new(types, count, ())
1609 }
1610 }
1611
1612 pub fn type_by_name<T: Into<QualifiedName>>(&self, name: T) -> Option<Ref<Type>> {
1613 let mut raw_name = QualifiedName::into_raw(name.into());
1614 unsafe {
1615 let type_handle = BNGetAnalysisTypeByName(self.handle, &mut raw_name);
1616 QualifiedName::free_raw(raw_name);
1617 if type_handle.is_null() {
1618 return None;
1619 }
1620 Some(Type::ref_from_raw(type_handle))
1621 }
1622 }
1623
1624 pub fn type_by_ref(&self, ref_: &NamedTypeReference) -> Option<Ref<Type>> {
1625 unsafe {
1626 let type_handle = BNGetAnalysisTypeByRef(self.handle, ref_.handle);
1627 if type_handle.is_null() {
1628 return None;
1629 }
1630 Some(Type::ref_from_raw(type_handle))
1631 }
1632 }
1633
1634 pub fn type_by_id(&self, id: &str) -> Option<Ref<Type>> {
1635 let id_str = id.to_cstr();
1636 unsafe {
1637 let type_handle = BNGetAnalysisTypeById(self.handle, id_str.as_ptr());
1638 if type_handle.is_null() {
1639 return None;
1640 }
1641 Some(Type::ref_from_raw(type_handle))
1642 }
1643 }
1644
1645 pub fn type_name_by_id(&self, id: &str) -> Option<QualifiedName> {
1646 let id_str = id.to_cstr();
1647 unsafe {
1648 let name_handle = BNGetAnalysisTypeNameById(self.handle, id_str.as_ptr());
1649 let name = QualifiedName::from_owned_raw(name_handle);
1650 match name.items.is_empty() {
1652 true => None,
1653 false => Some(name),
1654 }
1655 }
1656 }
1657
1658 pub fn type_id_by_name<T: Into<QualifiedName>>(&self, name: T) -> Option<String> {
1659 let mut raw_name = QualifiedName::into_raw(name.into());
1660 unsafe {
1661 let id_cstr = BNGetAnalysisTypeId(self.handle, &mut raw_name);
1662 QualifiedName::free_raw(raw_name);
1663 let id = BnString::into_string(id_cstr);
1664 match id.is_empty() {
1665 true => None,
1666 false => Some(id),
1667 }
1668 }
1669 }
1670
1671 pub fn is_type_auto_defined<T: Into<QualifiedName>>(&self, name: T) -> bool {
1672 let mut raw_name = QualifiedName::into_raw(name.into());
1673 let result = unsafe { BNIsAnalysisTypeAutoDefined(self.handle, &mut raw_name) };
1674 QualifiedName::free_raw(raw_name);
1675 result
1676 }
1677
1678 pub fn segments(&self) -> Array<Segment> {
1679 unsafe {
1680 let mut count = 0;
1681 let raw_segments = BNGetSegments(self.handle, &mut count);
1682 Array::new(raw_segments, count, ())
1683 }
1684 }
1685
1686 pub fn segment_at(&self, addr: u64) -> Option<Ref<Segment>> {
1687 unsafe {
1688 let raw_seg = BNGetSegmentAt(self.handle, addr);
1689 match raw_seg.is_null() {
1690 false => Some(Segment::ref_from_raw(raw_seg)),
1691 true => None,
1692 }
1693 }
1694 }
1695
1696 pub fn add_segment(&self, segment: SegmentBuilder) {
1701 segment.create(self.as_ref());
1702 }
1703
1704 pub fn begin_bulk_add_segments(&self) {
1715 unsafe { BNBeginBulkAddSegments(self.handle) }
1716 }
1717
1718 pub fn end_bulk_add_segments(&self) {
1724 unsafe { BNEndBulkAddSegments(self.handle) }
1725 }
1726
1727 pub fn cancel_bulk_add_segments(&self) {
1735 unsafe { BNCancelBulkAddSegments(self.handle) }
1736 }
1737
1738 pub fn add_section(&self, section: SectionBuilder) {
1739 section.create(self.as_ref());
1740 }
1741
1742 pub fn remove_auto_section(&self, name: impl IntoCStr) {
1743 let raw_name = name.to_cstr();
1744 let raw_name_ptr = raw_name.as_ptr();
1745 unsafe {
1746 BNRemoveAutoSection(self.handle, raw_name_ptr);
1747 }
1748 }
1749
1750 pub fn remove_user_section(&self, name: impl IntoCStr) {
1751 let raw_name = name.to_cstr();
1752 let raw_name_ptr = raw_name.as_ptr();
1753 unsafe {
1754 BNRemoveUserSection(self.handle, raw_name_ptr);
1755 }
1756 }
1757
1758 pub fn section_by_name(&self, name: impl IntoCStr) -> Option<Ref<Section>> {
1759 unsafe {
1760 let raw_name = name.to_cstr();
1761 let name_ptr = raw_name.as_ptr();
1762 let raw_section_ptr = BNGetSectionByName(self.handle, name_ptr);
1763 match raw_section_ptr.is_null() {
1764 false => Some(Section::ref_from_raw(raw_section_ptr)),
1765 true => None,
1766 }
1767 }
1768 }
1769
1770 pub fn sections(&self) -> Array<Section> {
1771 unsafe {
1772 let mut count = 0;
1773 let sections = BNGetSections(self.handle, &mut count);
1774 Array::new(sections, count, ())
1775 }
1776 }
1777
1778 pub fn sections_at(&self, addr: u64) -> Array<Section> {
1779 unsafe {
1780 let mut count = 0;
1781 let sections = BNGetSectionsAt(self.handle, addr, &mut count);
1782 Array::new(sections, count, ())
1783 }
1784 }
1785
1786 pub fn memory_map(&self) -> MemoryMap {
1787 MemoryMap::new(self.as_ref().to_owned())
1788 }
1789
1790 pub fn add_auto_function(&self, address: u64) -> Option<Ref<Function>> {
1796 let platform = self.default_platform()?;
1797 self.add_auto_function_with_platform(address, &platform)
1798 }
1799
1800 pub fn add_auto_function_with_platform(
1806 &self,
1807 address: u64,
1808 platform: &Platform,
1809 ) -> Option<Ref<Function>> {
1810 self.add_auto_function_ext(address, platform, None)
1811 }
1812
1813 pub fn add_auto_function_ext(
1817 &self,
1818 address: u64,
1819 platform: &Platform,
1820 func_type: Option<&Type>,
1821 ) -> Option<Ref<Function>> {
1822 unsafe {
1823 let func_type = match func_type {
1824 Some(func_type) => func_type.handle,
1825 None => std::ptr::null_mut(),
1826 };
1827
1828 let handle =
1829 BNAddFunctionForAnalysis(self.handle, platform.handle, address, true, func_type);
1830
1831 if handle.is_null() {
1832 return None;
1833 }
1834
1835 Some(Function::ref_from_raw(handle))
1836 }
1837 }
1838
1839 pub fn remove_auto_function(&self, func: &Function, update_refs: bool) {
1847 unsafe {
1848 BNRemoveAnalysisFunction(self.handle, func.handle, update_refs);
1849 }
1850 }
1851
1852 pub fn add_user_function(&self, addr: u64) -> Option<Ref<Function>> {
1858 let platform = self.default_platform()?;
1859 self.add_user_function_with_platform(addr, &platform)
1860 }
1861
1862 pub fn add_user_function_with_platform(
1866 &self,
1867 addr: u64,
1868 platform: &Platform,
1869 ) -> Option<Ref<Function>> {
1870 unsafe {
1871 let func = BNCreateUserFunction(self.handle, platform.handle, addr);
1872 if func.is_null() {
1873 return None;
1874 }
1875 Some(Function::ref_from_raw(func))
1876 }
1877 }
1878
1879 pub fn remove_user_function(&self, func: &Function) {
1883 unsafe { BNRemoveUserFunction(self.handle, func.handle) }
1884 }
1885
1886 pub fn has_functions(&self) -> bool {
1887 unsafe { BNHasFunctions(self.handle) }
1888 }
1889
1890 pub fn add_entry_point(&self, addr: u64) {
1894 if let Some(platform) = self.default_platform() {
1895 self.add_entry_point_with_platform(addr, &platform);
1896 }
1897 }
1898
1899 pub fn add_entry_point_with_platform(&self, addr: u64, platform: &Platform) {
1903 unsafe {
1904 BNAddEntryPointForAnalysis(self.handle, platform.handle, addr);
1905 }
1906 }
1907
1908 pub fn entry_point_function(&self) -> Option<Ref<Function>> {
1909 unsafe {
1910 let raw_func_ptr = BNGetAnalysisEntryPoint(self.handle);
1911 match raw_func_ptr.is_null() {
1912 false => Some(Function::ref_from_raw(raw_func_ptr)),
1913 true => None,
1914 }
1915 }
1916 }
1917
1918 pub fn entry_point_functions(&self) -> Array<Function> {
1924 unsafe {
1925 let mut count = 0;
1926 let functions = BNGetAllEntryFunctions(self.handle, &mut count);
1927
1928 Array::new(functions, count, ())
1929 }
1930 }
1931
1932 pub fn functions(&self) -> Array<Function> {
1933 unsafe {
1934 let mut count = 0;
1935 let functions = BNGetAnalysisFunctionList(self.handle, &mut count);
1936
1937 Array::new(functions, count, ())
1938 }
1939 }
1940
1941 pub fn functions_at(&self, addr: u64) -> Array<Function> {
1943 unsafe {
1944 let mut count = 0;
1945 let functions = BNGetAnalysisFunctionsForAddress(self.handle, addr, &mut count);
1946
1947 Array::new(functions, count, ())
1948 }
1949 }
1950
1951 pub fn functions_containing(&self, addr: u64) -> Array<Function> {
1953 unsafe {
1954 let mut count = 0;
1955 let functions = BNGetAnalysisFunctionsContainingAddress(self.handle, addr, &mut count);
1956
1957 Array::new(functions, count, ())
1958 }
1959 }
1960
1961 pub fn functions_by_name(
1971 &self,
1972 name: impl IntoCStr,
1973 plat: Option<&Platform>,
1974 ) -> Vec<Ref<Function>> {
1975 let name = name.to_cstr();
1976 let symbols = self.symbols_by_name(&*name);
1977 let mut addresses: Vec<u64> = symbols.into_iter().map(|s| s.address()).collect();
1978 if addresses.is_empty() && name.to_bytes().starts_with(b"sub_") {
1979 if let Ok(str) = name.to_str() {
1980 if let Ok(address) = u64::from_str_radix(&str[4..], 16) {
1981 addresses.push(address);
1982 }
1983 }
1984 }
1985
1986 let mut functions = Vec::new();
1987
1988 for address in addresses {
1989 let funcs = self.functions_at(address);
1990 for func in funcs.into_iter() {
1991 if func.start() == address && plat.is_none_or(|p| p == func.platform().as_ref()) {
1992 functions.push(func.clone());
1993 }
1994 }
1995 }
1996
1997 functions
1998 }
1999
2000 pub fn function_at(&self, platform: &Platform, addr: u64) -> Option<Ref<Function>> {
2001 unsafe {
2002 let raw_func_ptr = BNGetAnalysisFunction(self.handle, platform.handle, addr);
2003 match raw_func_ptr.is_null() {
2004 false => Some(Function::ref_from_raw(raw_func_ptr)),
2005 true => None,
2006 }
2007 }
2008 }
2009
2010 pub fn function_start_before(&self, addr: u64) -> u64 {
2011 unsafe { BNGetPreviousFunctionStartBeforeAddress(self.handle, addr) }
2012 }
2013
2014 pub fn function_start_after(&self, addr: u64) -> u64 {
2015 unsafe { BNGetNextFunctionStartAfterAddress(self.handle, addr) }
2016 }
2017
2018 pub fn basic_blocks_containing(&self, addr: u64) -> Array<BasicBlock<NativeBlock>> {
2019 unsafe {
2020 let mut count = 0;
2021 let blocks = BNGetBasicBlocksForAddress(self.handle, addr, &mut count);
2022 Array::new(blocks, count, NativeBlock::new())
2023 }
2024 }
2025
2026 pub fn basic_blocks_starting_at(&self, addr: u64) -> Array<BasicBlock<NativeBlock>> {
2027 unsafe {
2028 let mut count = 0;
2029 let blocks = BNGetBasicBlocksStartingAtAddress(self.handle, addr, &mut count);
2030 Array::new(blocks, count, NativeBlock::new())
2031 }
2032 }
2033
2034 pub fn is_new_auto_function_analysis_suppressed(&self) -> bool {
2035 unsafe { BNGetNewAutoFunctionAnalysisSuppressed(self.handle) }
2036 }
2037
2038 pub fn set_new_auto_function_analysis_suppressed(&self, suppress: bool) {
2039 unsafe {
2040 BNSetNewAutoFunctionAnalysisSuppressed(self.handle, suppress);
2041 }
2042 }
2043
2044 pub fn should_skip_target_analysis(
2046 &self,
2047 src_loc: impl Into<Location>,
2048 src_func: &Function,
2049 src_end: u64,
2050 target: impl Into<Location>,
2051 ) -> bool {
2052 let src_loc = src_loc.into();
2053 let target = target.into();
2054 unsafe {
2055 BNShouldSkipTargetAnalysis(
2056 self.handle,
2057 &mut src_loc.into(),
2058 src_func.handle,
2059 src_end,
2060 &mut target.into(),
2061 )
2062 }
2063 }
2064
2065 pub fn read_buffer(&self, offset: u64, len: usize) -> Option<DataBuffer> {
2066 let read_buffer = unsafe { BNReadViewBuffer(self.handle, offset, len) };
2067 if read_buffer.is_null() {
2068 None
2069 } else {
2070 Some(DataBuffer::from_raw(read_buffer))
2071 }
2072 }
2073
2074 pub fn debug_info(&self) -> Ref<DebugInfo> {
2075 unsafe { DebugInfo::ref_from_raw(BNGetDebugInfo(self.handle)) }
2076 }
2077
2078 pub fn set_debug_info(&self, debug_info: &DebugInfo) {
2079 unsafe { BNSetDebugInfo(self.handle, debug_info.handle) }
2080 }
2081
2082 pub fn apply_debug_info(&self, debug_info: &DebugInfo) {
2083 unsafe { BNApplyDebugInfo(self.handle, debug_info.handle) }
2084 }
2085
2086 pub fn show_plaintext_report(&self, title: &str, plaintext: &str) {
2087 let title = title.to_cstr();
2088 let plaintext = plaintext.to_cstr();
2089 unsafe {
2090 BNShowPlainTextReport(
2091 self.handle,
2092 title.as_ref().as_ptr() as *mut _,
2093 plaintext.as_ref().as_ptr() as *mut _,
2094 )
2095 }
2096 }
2097
2098 pub fn show_markdown_report(&self, title: &str, contents: &str, plaintext: &str) {
2099 let title = title.to_cstr();
2100 let contents = contents.to_cstr();
2101 let plaintext = plaintext.to_cstr();
2102 unsafe {
2103 BNShowMarkdownReport(
2104 self.handle,
2105 title.as_ref().as_ptr() as *mut _,
2106 contents.as_ref().as_ptr() as *mut _,
2107 plaintext.as_ref().as_ptr() as *mut _,
2108 )
2109 }
2110 }
2111
2112 pub fn show_html_report(&self, title: &str, contents: &str, plaintext: &str) {
2113 let title = title.to_cstr();
2114 let contents = contents.to_cstr();
2115 let plaintext = plaintext.to_cstr();
2116 unsafe {
2117 BNShowHTMLReport(
2118 self.handle,
2119 title.as_ref().as_ptr() as *mut _,
2120 contents.as_ref().as_ptr() as *mut _,
2121 plaintext.as_ref().as_ptr() as *mut _,
2122 )
2123 }
2124 }
2125
2126 pub fn show_graph_report(&self, raw_name: &str, graph: &FlowGraph) {
2127 let raw_name = raw_name.to_cstr();
2128 unsafe {
2129 BNShowGraphReport(self.handle, raw_name.as_ptr(), graph.handle);
2130 }
2131 }
2132
2133 pub fn load_settings(&self, view_type_name: &str) -> Option<Ref<Settings>> {
2134 let view_type_name = view_type_name.to_cstr();
2135 let settings_handle =
2136 unsafe { BNBinaryViewGetLoadSettings(self.handle, view_type_name.as_ptr()) };
2137 match settings_handle.is_null() {
2138 true => None,
2139 false => Some(unsafe { Settings::ref_from_raw(settings_handle) }),
2140 }
2141 }
2142
2143 pub fn set_load_settings(&self, view_type_name: &str, settings: &Settings) {
2144 let view_type_name = view_type_name.to_cstr();
2145
2146 unsafe {
2147 BNBinaryViewSetLoadSettings(self.handle, view_type_name.as_ptr(), settings.handle)
2148 };
2149 }
2150
2151 pub fn create_tag_type(&self, name: &str, icon: &str) -> Ref<TagType> {
2157 let tag_type = TagType::create(self, name, icon);
2158 unsafe {
2159 BNAddTagType(self.handle, tag_type.handle);
2160 }
2161 tag_type
2162 }
2163
2164 pub fn remove_tag_type(&self, tag_type: &TagType) {
2166 unsafe { BNRemoveTagType(self.handle, tag_type.handle) }
2167 }
2168
2169 pub fn tag_type_by_name(&self, name: &str) -> Option<Ref<TagType>> {
2171 let name = name.to_cstr();
2172 unsafe {
2173 let handle = BNGetTagType(self.handle, name.as_ptr());
2174 if handle.is_null() {
2175 return None;
2176 }
2177 Some(TagType::ref_from_raw(handle))
2178 }
2179 }
2180
2181 pub fn tags_all_scopes(&self) -> Array<TagReference> {
2183 let mut count = 0;
2184 unsafe {
2185 let tag_references = BNGetAllTagReferences(self.handle, &mut count);
2186 Array::new(tag_references, count, ())
2187 }
2188 }
2189
2190 pub fn tag_types(&self) -> Array<TagType> {
2192 let mut count = 0;
2193 unsafe {
2194 let tag_types_raw = BNGetTagTypes(self.handle, &mut count);
2195 Array::new(tag_types_raw, count, ())
2196 }
2197 }
2198
2199 pub fn tags_by_type(&self, tag_type: &TagType) -> Array<TagReference> {
2201 let mut count = 0;
2202 unsafe {
2203 let tag_references =
2204 BNGetAllTagReferencesOfType(self.handle, tag_type.handle, &mut count);
2205 Array::new(tag_references, count, ())
2206 }
2207 }
2208
2209 pub fn tag_by_id(&self, id: &str) -> Option<Ref<Tag>> {
2213 let id = id.to_cstr();
2214 unsafe {
2215 let handle = BNGetTag(self.handle, id.as_ptr());
2216 if handle.is_null() {
2217 return None;
2218 }
2219 Some(Tag::ref_from_raw(handle))
2220 }
2221 }
2222
2223 pub fn add_tag(&self, addr: u64, t: &TagType, data: &str, user: bool) {
2227 let tag = Tag::new(t, data);
2228
2229 unsafe { BNAddTag(self.handle, tag.handle, user) }
2230
2231 if user {
2232 unsafe { BNAddUserDataTag(self.handle, addr, tag.handle) }
2233 } else {
2234 unsafe { BNAddAutoDataTag(self.handle, addr, tag.handle) }
2235 }
2236 }
2237
2238 pub fn remove_auto_data_tag(&self, addr: u64, tag: &Tag) {
2240 unsafe { BNRemoveAutoDataTag(self.handle, addr, tag.handle) }
2241 }
2242
2243 pub fn remove_user_data_tag(&self, addr: u64, tag: &Tag) {
2246 unsafe { BNRemoveUserDataTag(self.handle, addr, tag.handle) }
2247 }
2248
2249 pub fn comment_references(&self) -> Array<CommentReference> {
2255 let mut count = 0;
2256 let addresses_raw = unsafe { BNGetGlobalCommentedAddresses(self.handle, &mut count) };
2257 unsafe { Array::new(addresses_raw, count, ()) }
2258 }
2259
2260 pub fn comments(&self) -> BTreeMap<u64, String> {
2265 self.comment_references()
2266 .iter()
2267 .filter_map(|cmt_ref| Some((cmt_ref.start, self.comment_at(cmt_ref.start)?)))
2268 .collect()
2269 }
2270
2271 pub fn comment_at(&self, addr: u64) -> Option<String> {
2272 unsafe {
2273 let comment_raw = BNGetGlobalCommentForAddress(self.handle, addr);
2274 match comment_raw.is_null() {
2275 false => Some(BnString::into_string(comment_raw)),
2276 true => None,
2277 }
2278 }
2279 }
2280
2281 pub fn set_comment_at(&self, addr: u64, comment: &str) {
2286 let comment_raw = comment.to_cstr();
2287 unsafe { BNSetGlobalCommentForAddress(self.handle, addr, comment_raw.as_ptr()) }
2288 }
2289
2290 pub fn get_next_linear_disassembly_lines(
2299 &self,
2300 pos: &mut LinearViewCursor,
2301 ) -> Array<LinearDisassemblyLine> {
2302 let mut result = unsafe { Array::new(std::ptr::null_mut(), 0, ()) };
2303
2304 while result.is_empty() {
2305 result = pos.lines();
2306 if !pos.next() {
2307 return result;
2308 }
2309 }
2310
2311 result
2312 }
2313
2314 pub fn get_previous_linear_disassembly_lines(
2323 &self,
2324 pos: &mut LinearViewCursor,
2325 ) -> Array<LinearDisassemblyLine> {
2326 let mut result = unsafe { Array::new(std::ptr::null_mut(), 0, ()) };
2327 while result.is_empty() {
2328 if !pos.previous() {
2329 return result;
2330 }
2331
2332 result = pos.lines();
2333 }
2334
2335 result
2336 }
2337
2338 pub fn query_metadata(&self, key: &str) -> Option<Ref<Metadata>> {
2339 let key = key.to_cstr();
2340 let value: *mut BNMetadata =
2341 unsafe { BNBinaryViewQueryMetadata(self.handle, key.as_ptr()) };
2342 if value.is_null() {
2343 None
2344 } else {
2345 Some(unsafe { Metadata::ref_from_raw(value) })
2346 }
2347 }
2348
2349 pub fn get_metadata<T>(&self, key: &str) -> Option<T>
2353 where
2354 T: for<'a> TryFrom<&'a Metadata>,
2355 {
2356 self.query_metadata(key)
2357 .and_then(|md| T::try_from(md.as_ref()).ok())
2358 }
2359
2360 pub fn store_metadata<V>(&self, key: &str, value: V, is_auto: bool)
2361 where
2362 V: Into<Ref<Metadata>>,
2363 {
2364 let md = value.into();
2365 let key = key.to_cstr();
2366 unsafe {
2367 BNBinaryViewStoreMetadata(self.handle, key.as_ptr(), md.as_ref().handle, is_auto)
2368 };
2369 }
2370
2371 pub fn remove_metadata(&self, key: &str) {
2372 let key = key.to_cstr();
2373 unsafe { BNBinaryViewRemoveMetadata(self.handle, key.as_ptr()) };
2374 }
2375
2376 pub fn code_refs_to_addr(&self, addr: u64) -> Array<CodeReference> {
2378 unsafe {
2379 let mut count = 0;
2380 let handle = BNGetCodeReferences(self.handle, addr, &mut count, false, 0);
2381 Array::new(handle, count, ())
2382 }
2383 }
2384
2385 pub fn code_refs_into_range(&self, range: Range<u64>) -> Array<CodeReference> {
2387 unsafe {
2388 let mut count = 0;
2389 let handle = BNGetCodeReferencesInRange(
2390 self.handle,
2391 range.start,
2392 range.end - range.start,
2393 &mut count,
2394 false,
2395 0,
2396 );
2397 Array::new(handle, count, ())
2398 }
2399 }
2400
2401 pub fn code_refs_from_addr(&self, addr: u64, func: Option<&Function>) -> Vec<u64> {
2403 unsafe {
2404 let mut count = 0;
2405 let code_ref =
2406 CodeReference::new(addr, func.map(|f| f.to_owned()), func.map(|f| f.arch()));
2407 let mut raw_code_ref = CodeReference::into_owned_raw(&code_ref);
2408 let addresses = BNGetCodeReferencesFrom(self.handle, &mut raw_code_ref, &mut count);
2409 let res = std::slice::from_raw_parts(addresses, count).to_vec();
2410 BNFreeAddressList(addresses);
2411 res
2412 }
2413 }
2414
2415 pub fn data_refs_to_addr(&self, addr: u64) -> Array<DataReference> {
2417 unsafe {
2418 let mut count = 0;
2419 let handle = BNGetDataReferences(self.handle, addr, &mut count, false, 0);
2420 Array::new(handle, count, ())
2421 }
2422 }
2423
2424 pub fn data_refs_into_range(&self, range: Range<u64>) -> Array<DataReference> {
2426 unsafe {
2427 let mut count = 0;
2428 let handle = BNGetDataReferencesInRange(
2429 self.handle,
2430 range.start,
2431 range.end - range.start,
2432 &mut count,
2433 false,
2434 0,
2435 );
2436 Array::new(handle, count, ())
2437 }
2438 }
2439
2440 pub fn data_refs_from_addr(&self, addr: u64) -> Array<DataReference> {
2442 unsafe {
2443 let mut count = 0;
2444 let handle = BNGetDataReferencesFrom(self.handle, addr, &mut count);
2445 Array::new(handle, count, ())
2446 }
2447 }
2448
2449 pub fn code_refs_using_type_name<T: Into<QualifiedName>>(
2451 &self,
2452 name: T,
2453 ) -> Array<CodeReference> {
2454 let mut raw_name = QualifiedName::into_raw(name.into());
2455 unsafe {
2456 let mut count = 0;
2457 let handle =
2458 BNGetCodeReferencesForType(self.handle, &mut raw_name, &mut count, false, 0);
2459 QualifiedName::free_raw(raw_name);
2460 Array::new(handle, count, ())
2461 }
2462 }
2463
2464 pub fn data_refs_using_type_name<T: Into<QualifiedName>>(
2466 &self,
2467 name: T,
2468 ) -> Array<DataReference> {
2469 let mut raw_name = QualifiedName::into_raw(name.into());
2470 unsafe {
2471 let mut count = 0;
2472 let handle =
2473 BNGetDataReferencesForType(self.handle, &mut raw_name, &mut count, false, 0);
2474 QualifiedName::free_raw(raw_name);
2475 Array::new(handle, count, ())
2476 }
2477 }
2478
2479 pub fn relocations_at(&self, addr: u64) -> Array<Relocation> {
2480 unsafe {
2481 let mut count = 0;
2482 let handle = BNGetRelocationsAt(self.handle, addr, &mut count);
2483 Array::new(handle, count, ())
2484 }
2485 }
2486
2487 pub fn relocation_ranges(&self) -> Vec<Range<u64>> {
2488 let ranges = unsafe {
2489 let mut count = 0;
2490 let reloc_ranges_ptr = BNGetRelocationRanges(self.handle, &mut count);
2491 let ranges = std::slice::from_raw_parts(reloc_ranges_ptr, count).to_vec();
2492 BNFreeRelocationRanges(reloc_ranges_ptr);
2493 ranges
2494 };
2495
2496 ranges
2498 .iter()
2499 .map(|range| Range {
2500 start: range.start,
2501 end: range.end,
2502 })
2503 .collect()
2504 }
2505
2506 pub fn component_by_guid(&self, guid: &str) -> Option<Ref<Component>> {
2507 let name = guid.to_cstr();
2508 let result = unsafe { BNGetComponentByGuid(self.handle, name.as_ptr()) };
2509 NonNull::new(result).map(|h| unsafe { Component::ref_from_raw(h) })
2510 }
2511
2512 pub fn root_component(&self) -> Option<Ref<Component>> {
2513 let result = unsafe { BNGetRootComponent(self.handle) };
2514 NonNull::new(result).map(|h| unsafe { Component::ref_from_raw(h) })
2515 }
2516
2517 pub fn component_by_path(&self, path: &str) -> Option<Ref<Component>> {
2518 let path = path.to_cstr();
2519 let result = unsafe { BNGetComponentByPath(self.handle, path.as_ptr()) };
2520 NonNull::new(result).map(|h| unsafe { Component::ref_from_raw(h) })
2521 }
2522
2523 pub fn remove_component(&self, component: &Component) -> bool {
2524 unsafe { BNRemoveComponent(self.handle, component.handle.as_ptr()) }
2525 }
2526
2527 pub fn remove_component_by_guid(&self, guid: &str) -> bool {
2528 let path = guid.to_cstr();
2529 unsafe { BNRemoveComponentByGuid(self.handle, path.as_ptr()) }
2530 }
2531
2532 pub fn data_variable_parent_components(
2533 &self,
2534 data_variable: &DataVariable,
2535 ) -> Array<Component> {
2536 let mut count = 0;
2537 let result = unsafe {
2538 BNGetDataVariableParentComponents(self.handle, data_variable.address, &mut count)
2539 };
2540 unsafe { Array::new(result, count, ()) }
2541 }
2542
2543 pub fn external_libraries(&self) -> Array<ExternalLibrary> {
2544 let mut count = 0;
2545 let result = unsafe { BNBinaryViewGetExternalLibraries(self.handle, &mut count) };
2546 unsafe { Array::new(result, count, ()) }
2547 }
2548
2549 pub fn external_library(&self, name: &str) -> Option<Ref<ExternalLibrary>> {
2550 let name_ptr = name.to_cstr();
2551 let result = unsafe { BNBinaryViewGetExternalLibrary(self.handle, name_ptr.as_ptr()) };
2552 let result_ptr = NonNull::new(result)?;
2553 Some(unsafe { ExternalLibrary::ref_from_raw(result_ptr) })
2554 }
2555
2556 pub fn remove_external_library(&self, name: &str) {
2557 let name_ptr = name.to_cstr();
2558 unsafe { BNBinaryViewRemoveExternalLibrary(self.handle, name_ptr.as_ptr()) };
2559 }
2560
2561 pub fn add_external_library(
2562 &self,
2563 name: &str,
2564 backing_file: Option<&ProjectFile>,
2565 auto: bool,
2566 ) -> Option<Ref<ExternalLibrary>> {
2567 let name_ptr = name.to_cstr();
2568 let result = unsafe {
2569 BNBinaryViewAddExternalLibrary(
2570 self.handle,
2571 name_ptr.as_ptr(),
2572 backing_file
2573 .map(|b| b.handle.as_ptr())
2574 .unwrap_or(std::ptr::null_mut()),
2575 auto,
2576 )
2577 };
2578 NonNull::new(result).map(|h| unsafe { ExternalLibrary::ref_from_raw(h) })
2579 }
2580
2581 pub fn external_locations(&self) -> Array<ExternalLocation> {
2582 let mut count = 0;
2583 let result = unsafe { BNBinaryViewGetExternalLocations(self.handle, &mut count) };
2584 unsafe { Array::new(result, count, ()) }
2585 }
2586
2587 pub fn external_location_from_symbol(&self, symbol: &Symbol) -> Option<Ref<ExternalLocation>> {
2588 let result = unsafe { BNBinaryViewGetExternalLocation(self.handle, symbol.handle) };
2589 let result_ptr = NonNull::new(result)?;
2590 Some(unsafe { ExternalLocation::ref_from_raw(result_ptr) })
2591 }
2592
2593 pub fn remove_external_location(&self, location: &ExternalLocation) {
2594 self.remove_external_location_from_symbol(&location.source_symbol())
2595 }
2596
2597 pub fn remove_external_location_from_symbol(&self, symbol: &Symbol) {
2598 unsafe { BNBinaryViewRemoveExternalLocation(self.handle, symbol.handle) };
2599 }
2600
2601 pub fn add_external_location(
2603 &self,
2604 symbol: &Symbol,
2605 library: &ExternalLibrary,
2606 target_symbol_name: &str,
2607 target_address: Option<u64>,
2608 target_is_auto: bool,
2609 ) -> Option<Ref<ExternalLocation>> {
2610 let target_symbol_name = target_symbol_name.to_cstr();
2611 let target_address_ptr = target_address
2612 .map(|a| a as *mut u64)
2613 .unwrap_or(std::ptr::null_mut());
2614 let result = unsafe {
2615 BNBinaryViewAddExternalLocation(
2616 self.handle,
2617 symbol.handle,
2618 library.handle.as_ptr(),
2619 target_symbol_name.as_ptr(),
2620 target_address_ptr,
2621 target_is_auto,
2622 )
2623 };
2624 NonNull::new(result).map(|h| unsafe { ExternalLocation::ref_from_raw(h) })
2625 }
2626
2627 pub fn type_container(&self) -> TypeContainer {
2631 let type_container_ptr = NonNull::new(unsafe { BNGetAnalysisTypeContainer(self.handle) });
2632 unsafe { TypeContainer::from_raw(type_container_ptr.unwrap()) }
2634 }
2635
2636 pub fn user_type_container(&self) -> TypeContainer {
2638 let type_container_ptr =
2639 NonNull::new(unsafe { BNGetAnalysisUserTypeContainer(self.handle) });
2640 unsafe { TypeContainer::from_raw(type_container_ptr.unwrap()) }.clone()
2642 }
2643
2644 pub fn auto_type_container(&self) -> TypeContainer {
2648 let type_container_ptr =
2649 NonNull::new(unsafe { BNGetAnalysisAutoTypeContainer(self.handle) });
2650 unsafe { TypeContainer::from_raw(type_container_ptr.unwrap()) }
2652 }
2653
2654 pub fn type_libraries(&self) -> Array<TypeLibrary> {
2655 let mut count = 0;
2656 let result = unsafe { BNGetBinaryViewTypeLibraries(self.handle, &mut count) };
2657 unsafe { Array::new(result, count, ()) }
2658 }
2659
2660 pub fn add_type_library(&self, library: &TypeLibrary) {
2662 unsafe { BNAddBinaryViewTypeLibrary(self.handle, library.as_raw()) }
2663 }
2664
2665 pub fn type_library_by_name(&self, name: &str) -> Option<Ref<TypeLibrary>> {
2666 let name = name.to_cstr();
2667 let result = unsafe { BNGetBinaryViewTypeLibrary(self.handle, name.as_ptr()) };
2668 NonNull::new(result).map(|h| unsafe { TypeLibrary::ref_from_raw(h) })
2669 }
2670
2671 pub fn record_imported_object_library<T: Into<QualifiedName>>(
2680 &self,
2681 lib: &TypeLibrary,
2682 name: T,
2683 addr: u64,
2684 platform: &Platform,
2685 ) {
2686 let mut raw_name = QualifiedName::into_raw(name.into());
2687 unsafe {
2688 BNBinaryViewRecordImportedObjectLibrary(
2689 self.handle,
2690 platform.handle,
2691 addr,
2692 lib.as_raw(),
2693 &mut raw_name,
2694 )
2695 }
2696 QualifiedName::free_raw(raw_name);
2697 }
2698
2699 pub fn import_type_library_type<T: Into<QualifiedName>>(
2710 &self,
2711 name: T,
2712 lib: Option<&TypeLibrary>,
2713 ) -> Option<Ref<Type>> {
2714 let mut lib_ref = lib
2715 .as_ref()
2716 .map(|l| unsafe { l.as_raw() } as *mut _)
2717 .unwrap_or(std::ptr::null_mut());
2718 let mut raw_name = QualifiedName::into_raw(name.into());
2719 let result =
2720 unsafe { BNBinaryViewImportTypeLibraryType(self.handle, &mut lib_ref, &mut raw_name) };
2721 QualifiedName::free_raw(raw_name);
2722 (!result.is_null()).then(|| unsafe { Type::ref_from_raw(result) })
2723 }
2724
2725 pub fn import_type_library_object<T: Into<QualifiedName>>(
2736 &self,
2737 name: T,
2738 lib: Option<&TypeLibrary>,
2739 ) -> Option<Ref<Type>> {
2740 let mut lib_ref = lib
2741 .as_ref()
2742 .map(|l| unsafe { l.as_raw() } as *mut _)
2743 .unwrap_or(std::ptr::null_mut());
2744 let mut raw_name = QualifiedName::into_raw(name.into());
2745 let result = unsafe {
2746 BNBinaryViewImportTypeLibraryObject(self.handle, &mut lib_ref, &mut raw_name)
2747 };
2748 QualifiedName::free_raw(raw_name);
2749 (!result.is_null()).then(|| unsafe { Type::ref_from_raw(result) })
2750 }
2751
2752 pub fn import_type_by_guid(&self, guid: &str) -> Option<Ref<Type>> {
2754 let guid = guid.to_cstr();
2755 let result = unsafe { BNBinaryViewImportTypeLibraryTypeByGuid(self.handle, guid.as_ptr()) };
2756 (!result.is_null()).then(|| unsafe { Type::ref_from_raw(result) })
2757 }
2758
2759 pub fn export_type_to_library<T: Into<QualifiedName>>(
2764 &self,
2765 lib: &TypeLibrary,
2766 name: T,
2767 type_obj: &Type,
2768 ) {
2769 let mut raw_name = QualifiedName::into_raw(name.into());
2770 unsafe {
2771 BNBinaryViewExportTypeToTypeLibrary(
2772 self.handle,
2773 lib.as_raw(),
2774 &mut raw_name,
2775 type_obj.handle,
2776 )
2777 }
2778 QualifiedName::free_raw(raw_name);
2779 }
2780
2781 pub fn export_object_to_library<T: Into<QualifiedName>>(
2786 &self,
2787 lib: &TypeLibrary,
2788 name: T,
2789 type_obj: &Type,
2790 ) {
2791 let mut raw_name = QualifiedName::into_raw(name.into());
2792 unsafe {
2793 BNBinaryViewExportObjectToTypeLibrary(
2794 self.handle,
2795 lib.as_raw(),
2796 &mut raw_name,
2797 type_obj.handle,
2798 )
2799 }
2800 QualifiedName::free_raw(raw_name);
2801 }
2802
2803 pub fn lookup_imported_object_library(
2809 &self,
2810 addr: u64,
2811 platform: &Platform,
2812 ) -> Option<(Ref<TypeLibrary>, QualifiedName)> {
2813 let mut result_lib = std::ptr::null_mut();
2814 let mut result_name = BNQualifiedName::default();
2815 let success = unsafe {
2816 BNBinaryViewLookupImportedObjectLibrary(
2817 self.handle,
2818 platform.handle,
2819 addr,
2820 &mut result_lib,
2821 &mut result_name,
2822 )
2823 };
2824 if !success {
2825 return None;
2826 }
2827 let lib = unsafe { TypeLibrary::ref_from_raw(NonNull::new(result_lib)?) };
2828 let name = QualifiedName::from_owned_raw(result_name);
2829 Some((lib, name))
2830 }
2831
2832 pub fn lookup_imported_type_library<T: Into<QualifiedName>>(
2836 &self,
2837 name: T,
2838 ) -> Option<(Ref<TypeLibrary>, QualifiedName)> {
2839 let raw_name = QualifiedName::into_raw(name.into());
2840 let mut result_lib = std::ptr::null_mut();
2841 let mut result_name = BNQualifiedName::default();
2842 let success = unsafe {
2843 BNBinaryViewLookupImportedTypeLibrary(
2844 self.handle,
2845 &raw_name,
2846 &mut result_lib,
2847 &mut result_name,
2848 )
2849 };
2850 QualifiedName::free_raw(raw_name);
2851 if !success {
2852 return None;
2853 }
2854 let lib = unsafe { TypeLibrary::ref_from_raw(NonNull::new(result_lib)?) };
2855 let name = QualifiedName::from_owned_raw(result_name);
2856 Some((lib, name))
2857 }
2858
2859 pub fn strings(&self) -> Array<StringReference> {
2873 unsafe {
2874 let mut count = 0;
2875 let strings = BNGetStrings(self.handle, &mut count);
2876 Array::new(strings, count, ())
2877 }
2878 }
2879
2880 pub fn string_at(&self, addr: u64) -> Option<StringReference> {
2894 let mut str_ref = BNStringReference::default();
2895 let success = unsafe { BNGetStringAtAddress(self.handle, addr, &mut str_ref) };
2896 if success {
2897 Some(str_ref.into())
2898 } else {
2899 None
2900 }
2901 }
2902
2903 pub fn strings_in_range(&self, range: Range<u64>) -> Array<StringReference> {
2917 unsafe {
2918 let mut count = 0;
2919 let strings = BNGetStringsInRange(
2920 self.handle,
2921 range.start,
2922 range.end - range.start,
2923 &mut count,
2924 );
2925 Array::new(strings, count, ())
2926 }
2927 }
2928
2929 pub fn attached_type_archives(&self) -> Vec<TypeArchiveId> {
2933 let mut ids: *mut *mut c_char = std::ptr::null_mut();
2934 let mut paths: *mut *mut c_char = std::ptr::null_mut();
2935 let count = unsafe { BNBinaryViewGetTypeArchives(self.handle, &mut ids, &mut paths) };
2936 let _path_list = unsafe { Array::<BnString>::new(paths, count, ()) };
2940 let id_list = unsafe { Array::<BnString>::new(ids, count, ()) };
2941 id_list
2942 .into_iter()
2943 .map(|id| TypeArchiveId(id.to_string()))
2944 .collect()
2945 }
2946
2947 pub fn type_archive_by_id(&self, id: &TypeArchiveId) -> Option<Ref<TypeArchive>> {
2951 let id = id.0.as_str().to_cstr();
2952 let result = unsafe { BNBinaryViewGetTypeArchive(self.handle, id.as_ptr()) };
2953 let result_ptr = NonNull::new(result)?;
2954 Some(unsafe { TypeArchive::ref_from_raw(result_ptr) })
2955 }
2956
2957 pub fn type_archive_path_by_id(&self, id: &TypeArchiveId) -> Option<PathBuf> {
2959 let id = id.0.as_str().to_cstr();
2960 let result = unsafe { BNBinaryViewGetTypeArchivePath(self.handle, id.as_ptr()) };
2961 if result.is_null() {
2962 return None;
2963 }
2964 let path_str = unsafe { BnString::into_string(result) };
2965 Some(PathBuf::from(path_str))
2966 }
2967}
2968
2969impl BinaryViewBase for BinaryView {
2970 fn read(&self, buf: &mut [u8], offset: u64) -> usize {
2971 unsafe { BNReadViewData(self.handle, buf.as_mut_ptr() as *mut _, offset, buf.len()) }
2972 }
2973
2974 fn write(&self, offset: u64, data: &[u8]) -> usize {
2975 unsafe { BNWriteViewData(self.handle, offset, data.as_ptr() as *const _, data.len()) }
2976 }
2977
2978 fn insert(&self, offset: u64, data: &[u8]) -> usize {
2979 unsafe { BNInsertViewData(self.handle, offset, data.as_ptr() as *const _, data.len()) }
2980 }
2981
2982 fn remove(&self, offset: u64, len: usize) -> usize {
2983 unsafe { BNRemoveViewData(self.handle, offset, len as u64) }
2984 }
2985
2986 fn offset_valid(&self, offset: u64) -> bool {
2987 unsafe { BNIsValidOffset(self.handle, offset) }
2988 }
2989
2990 fn offset_readable(&self, offset: u64) -> bool {
2991 unsafe { BNIsOffsetReadable(self.handle, offset) }
2992 }
2993
2994 fn offset_writable(&self, offset: u64) -> bool {
2995 unsafe { BNIsOffsetWritable(self.handle, offset) }
2996 }
2997
2998 fn offset_executable(&self, offset: u64) -> bool {
2999 unsafe { BNIsOffsetExecutable(self.handle, offset) }
3000 }
3001
3002 fn offset_backed_by_file(&self, offset: u64) -> bool {
3003 unsafe { BNIsOffsetBackedByFile(self.handle, offset) }
3004 }
3005
3006 fn next_valid_offset_after(&self, offset: u64) -> u64 {
3007 unsafe { BNGetNextValidOffset(self.handle, offset) }
3008 }
3009
3010 fn modification_status(&self, offset: u64) -> ModificationStatus {
3011 unsafe { BNGetModification(self.handle, offset) }
3012 }
3013
3014 fn start(&self) -> u64 {
3015 unsafe { BNGetStartOffset(self.handle) }
3016 }
3017
3018 fn len(&self) -> u64 {
3019 unsafe { BNGetViewLength(self.handle) }
3020 }
3021
3022 fn executable(&self) -> bool {
3023 unsafe { BNIsExecutableView(self.handle) }
3024 }
3025
3026 fn relocatable(&self) -> bool {
3027 unsafe { BNIsRelocatable(self.handle) }
3028 }
3029
3030 fn entry_point(&self) -> u64 {
3031 unsafe { BNGetEntryPoint(self.handle) }
3032 }
3033
3034 fn default_endianness(&self) -> Endianness {
3035 unsafe { BNGetDefaultEndianness(self.handle) }
3036 }
3037
3038 fn address_size(&self) -> usize {
3039 unsafe { BNGetViewAddressSize(self.handle) }
3040 }
3041}
3042
3043unsafe impl RefCountable for BinaryView {
3044 unsafe fn inc_ref(handle: &Self) -> Ref<Self> {
3045 Ref::new(Self {
3046 handle: BNNewViewReference(handle.handle),
3047 })
3048 }
3049
3050 unsafe fn dec_ref(handle: &Self) {
3051 BNFreeBinaryView(handle.handle);
3052 }
3053}
3054
3055impl AsRef<BinaryView> for BinaryView {
3056 fn as_ref(&self) -> &Self {
3057 self
3058 }
3059}
3060
3061impl ToOwned for BinaryView {
3062 type Owned = Ref<Self>;
3063
3064 fn to_owned(&self) -> Self::Owned {
3065 unsafe { RefCountable::inc_ref(self) }
3066 }
3067}
3068
3069unsafe impl Send for BinaryView {}
3070unsafe impl Sync for BinaryView {}
3071
3072impl std::fmt::Debug for BinaryView {
3073 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
3074 f.debug_struct("BinaryView")
3075 .field("view_type", &self.view_type())
3076 .field("file", &self.file())
3077 .field("original_image_base", &self.original_image_base())
3078 .field("start", &self.start())
3079 .field("end", &self.end())
3080 .field("len", &self.len())
3081 .field("default_platform", &self.default_platform())
3082 .field("default_arch", &self.default_arch())
3083 .field("default_endianness", &self.default_endianness())
3084 .field("entry_point", &self.entry_point())
3085 .field(
3086 "entry_point_functions",
3087 &self.entry_point_functions().to_vec(),
3088 )
3089 .field("address_size", &self.address_size())
3090 .field("sections", &self.sections().to_vec())
3091 .field("segments", &self.segments().to_vec())
3092 .finish()
3093 }
3094}
3095
3096pub trait BinaryViewEventHandler: 'static + Sync {
3097 fn on_event(&self, binary_view: &BinaryView);
3098}
3099
3100impl<F: Fn(&BinaryView) + 'static + Sync> BinaryViewEventHandler for F {
3101 fn on_event(&self, binary_view: &BinaryView) {
3102 self(binary_view);
3103 }
3104}
3105
3106pub fn register_binary_view_event<Handler>(event_type: BinaryViewEventType, handler: Handler)
3136where
3137 Handler: BinaryViewEventHandler,
3138{
3139 unsafe extern "C" fn on_event<Handler: BinaryViewEventHandler>(
3140 ctx: *mut c_void,
3141 view: *mut BNBinaryView,
3142 ) {
3143 ffi_wrap!("EventHandler::on_event", {
3144 let context = unsafe { &*(ctx as *const Handler) };
3145 context.on_event(&BinaryView::ref_from_raw(BNNewViewReference(view)));
3146 })
3147 }
3148
3149 let boxed = Box::new(handler);
3150 let raw = Box::into_raw(boxed);
3151
3152 unsafe {
3153 BNRegisterBinaryViewEvent(event_type, Some(on_event::<Handler>), raw as *mut c_void);
3154 }
3155}
3156
3157#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
3158pub struct CommentReference {
3159 pub start: u64,
3160}
3161
3162impl From<u64> for CommentReference {
3163 fn from(start: u64) -> Self {
3164 Self { start }
3165 }
3166}
3167
3168impl CoreArrayProvider for CommentReference {
3169 type Raw = u64;
3170 type Context = ();
3171 type Wrapped<'a> = Self;
3172}
3173
3174unsafe impl CoreArrayProviderInner for CommentReference {
3175 unsafe fn free(raw: *mut Self::Raw, _count: usize, _context: &Self::Context) {
3176 BNFreeAddressList(raw)
3177 }
3178
3179 unsafe fn wrap_raw<'a>(raw: &'a Self::Raw, _context: &'a Self::Context) -> Self::Wrapped<'a> {
3180 Self::from(*raw)
3181 }
3182}
3183
3184#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
3185pub struct StringReference {
3186 pub ty: StringType,
3187 pub start: u64,
3188 pub length: usize,
3189}
3190
3191impl From<BNStringReference> for StringReference {
3192 fn from(raw: BNStringReference) -> Self {
3193 Self {
3194 ty: raw.type_,
3195 start: raw.start,
3196 length: raw.length,
3197 }
3198 }
3199}
3200
3201impl From<StringReference> for BNStringReference {
3202 fn from(raw: StringReference) -> Self {
3203 Self {
3204 type_: raw.ty,
3205 start: raw.start,
3206 length: raw.length,
3207 }
3208 }
3209}
3210
3211impl CoreArrayProvider for StringReference {
3212 type Raw = BNStringReference;
3213 type Context = ();
3214 type Wrapped<'a> = Self;
3215}
3216
3217unsafe impl CoreArrayProviderInner for StringReference {
3218 unsafe fn free(raw: *mut Self::Raw, _count: usize, _context: &Self::Context) {
3219 BNFreeStringReferenceList(raw)
3220 }
3221
3222 unsafe fn wrap_raw<'a>(raw: &'a Self::Raw, _context: &'a Self::Context) -> Self::Wrapped<'a> {
3223 Self::from(*raw)
3224 }
3225}
3226
3227#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
3228pub struct AddressRange {
3229 pub start: u64,
3230 pub end: u64,
3231}
3232
3233impl From<BNAddressRange> for AddressRange {
3234 fn from(raw: BNAddressRange) -> Self {
3235 Self {
3236 start: raw.start,
3237 end: raw.end,
3238 }
3239 }
3240}
3241
3242impl From<AddressRange> for BNAddressRange {
3243 fn from(raw: AddressRange) -> Self {
3244 Self {
3245 start: raw.start,
3246 end: raw.end,
3247 }
3248 }
3249}
3250
3251impl CoreArrayProvider for AddressRange {
3252 type Raw = BNAddressRange;
3253 type Context = ();
3254 type Wrapped<'a> = Self;
3255}
3256
3257unsafe impl CoreArrayProviderInner for AddressRange {
3258 unsafe fn free(raw: *mut Self::Raw, _count: usize, _context: &Self::Context) {
3259 BNFreeAddressRanges(raw);
3260 }
3261
3262 unsafe fn wrap_raw<'a>(raw: &'a Self::Raw, _context: &'a Self::Context) -> Self::Wrapped<'a> {
3263 Self::from(*raw)
3264 }
3265}
3266
3267extern "C" fn cb_valid<T>(ctxt: *mut c_void, data: *mut BNBinaryView) -> bool
3268where
3269 T: CustomBinaryViewType,
3270{
3271 let view_type = unsafe { &*(ctxt as *mut T) };
3272 let data = unsafe { BinaryView::ref_from_raw(BNNewViewReference(data)) };
3273 let _span = ffi_span!("CustomBinaryViewType::is_valid_for", data);
3274 view_type.is_valid_for(&data)
3275}
3276
3277extern "C" fn cb_deprecated<T>(_ctxt: *mut c_void) -> bool
3278where
3279 T: CustomBinaryViewType,
3280{
3281 T::DEPRECATED
3282}
3283
3284extern "C" fn cb_force_loadable<T>(_ctxt: *mut c_void) -> bool
3285where
3286 T: CustomBinaryViewType,
3287{
3288 T::FORCE_LOADABLE
3289}
3290
3291extern "C" fn cb_has_no_initial_content<T>(_ctxt: *mut c_void) -> bool
3292where
3293 T: CustomBinaryViewType,
3294{
3295 T::HAS_NO_INITIAL_CONTENT
3296}
3297
3298extern "C" fn cb_create<T>(ctxt: *mut c_void, data: *mut BNBinaryView) -> *mut BNBinaryView
3299where
3300 T: CustomBinaryViewType,
3301{
3302 ffi_wrap!("CustomBinaryViewType::create", unsafe {
3303 let view_type = &*(ctxt as *mut T);
3304 let data = BinaryView::from_raw(data);
3305 let _span = ffi_span!("CustomBinaryViewType::create", data);
3306 match view_type.create_binary_view(&data) {
3307 Ok(custom_view) => {
3308 match BinaryView::from_custom(T::NAME, &data.file(), &data, custom_view) {
3309 Ok(custom_view) => Ref::into_raw(custom_view).handle,
3310 Err(_) => std::ptr::null_mut(),
3311 }
3312 }
3313 Err(_) => std::ptr::null_mut(),
3314 }
3315 })
3316}
3317
3318extern "C" fn cb_parse<T>(ctxt: *mut c_void, data: *mut BNBinaryView) -> *mut BNBinaryView
3319where
3320 T: CustomBinaryViewType,
3321{
3322 ffi_wrap!("CustomBinaryViewType::parse", unsafe {
3323 let view_type = &*(ctxt as *mut T);
3324 let data = BinaryView::from_raw(data);
3325 let _span = ffi_span!("CustomBinaryViewType::parse", data);
3326 match view_type.create_binary_view_for_parse(&data) {
3327 Ok(custom_view) => {
3328 match BinaryView::from_custom(T::NAME, &data.file(), &data, custom_view) {
3329 Ok(custom_view) => Ref::into_raw(custom_view).handle,
3330 Err(_) => std::ptr::null_mut(),
3331 }
3332 }
3333 Err(_) => std::ptr::null_mut(),
3334 }
3335 })
3336}
3337
3338extern "C" fn cb_load_settings<T>(ctxt: *mut c_void, data: *mut BNBinaryView) -> *mut BNSettings
3339where
3340 T: CustomBinaryViewType,
3341{
3342 ffi_wrap!("CustomBinaryViewType::load_settings", unsafe {
3343 let view_type = &*(ctxt as *mut T);
3344 let data = BinaryView::from_raw(data);
3345
3346 let _span = ffi_span!("CustomBinaryViewType::load_settings", data);
3347 let settings = view_type.load_settings_for_data(&data);
3348 Ref::into_raw(settings).handle
3349 })
3350}
3351
3352extern "C" fn cb_init<C>(ctxt: *mut c_void) -> bool
3353where
3354 C: CustomBinaryView,
3355{
3356 ffi_wrap!("BinaryViewBase::init", unsafe {
3357 let context = &mut *(ctxt as *mut CustomBinaryViewContext<C>);
3358 context.view.initialize(context.core_view.assume_init_ref())
3362 })
3363}
3364
3365extern "C" fn cb_on_after_snapshot_data_applied<C>(ctxt: *mut c_void)
3366where
3367 C: CustomBinaryView,
3368{
3369 ffi_wrap!("BinaryViewBase::onAfterSnapshotDataApplied", unsafe {
3370 let context = &mut *(ctxt as *mut CustomBinaryViewContext<C>);
3371 context.view.on_after_snapshot_data_applied();
3374 })
3375}
3376
3377extern "C" fn cb_free_object<C>(ctxt: *mut c_void)
3378where
3379 C: CustomBinaryView,
3380{
3381 ffi_wrap!("BinaryViewBase::freeObject", unsafe {
3382 let context = ctxt as *mut CustomBinaryViewContext<C>;
3383 let _context = Box::from_raw(context);
3384 })
3385}
3386
3387extern "C" fn cb_read<C>(ctxt: *mut c_void, dest: *mut c_void, offset: u64, len: usize) -> usize
3388where
3389 C: CustomBinaryView,
3390{
3391 ffi_wrap!("BinaryViewBase::read", unsafe {
3392 let context = &*(ctxt as *mut CustomBinaryViewContext<C>);
3393 let dest = std::slice::from_raw_parts_mut(dest as *mut u8, len);
3394 context.view.read(dest, offset)
3395 })
3396}
3397
3398extern "C" fn cb_write<C>(ctxt: *mut c_void, offset: u64, src: *const c_void, len: usize) -> usize
3399where
3400 C: CustomBinaryView,
3401{
3402 ffi_wrap!("BinaryViewBase::write", unsafe {
3403 let context = &*(ctxt as *mut CustomBinaryViewContext<C>);
3404 let src = std::slice::from_raw_parts(src as *const u8, len);
3405 context.view.write(offset, src)
3406 })
3407}
3408
3409extern "C" fn cb_insert<C>(ctxt: *mut c_void, offset: u64, src: *const c_void, len: usize) -> usize
3410where
3411 C: CustomBinaryView,
3412{
3413 ffi_wrap!("BinaryViewBase::insert", unsafe {
3414 let context = &*(ctxt as *mut CustomBinaryViewContext<C>);
3415 let src = std::slice::from_raw_parts(src as *const u8, len);
3416 context.view.insert(offset, src)
3417 })
3418}
3419
3420extern "C" fn cb_remove<C>(ctxt: *mut c_void, offset: u64, len: u64) -> usize
3421where
3422 C: CustomBinaryView,
3423{
3424 ffi_wrap!("BinaryViewBase::remove", unsafe {
3425 let context = &*(ctxt as *mut CustomBinaryViewContext<C>);
3426 context.view.remove(offset, len as usize)
3427 })
3428}
3429
3430extern "C" fn cb_modification<C>(ctxt: *mut c_void, offset: u64) -> ModificationStatus
3431where
3432 C: CustomBinaryView,
3433{
3434 ffi_wrap!("BinaryViewBase::modification_status", unsafe {
3435 let context = &*(ctxt as *mut CustomBinaryViewContext<C>);
3436 context.view.modification_status(offset)
3437 })
3438}
3439
3440extern "C" fn cb_offset_valid<C>(ctxt: *mut c_void, offset: u64) -> bool
3441where
3442 C: CustomBinaryView,
3443{
3444 ffi_wrap!("BinaryViewBase::offset_valid", unsafe {
3445 let context = &*(ctxt as *mut CustomBinaryViewContext<C>);
3446 context.view.offset_valid(offset)
3447 })
3448}
3449
3450extern "C" fn cb_offset_readable<C>(ctxt: *mut c_void, offset: u64) -> bool
3451where
3452 C: CustomBinaryView,
3453{
3454 ffi_wrap!("BinaryViewBase::readable", unsafe {
3455 let context = &*(ctxt as *mut CustomBinaryViewContext<C>);
3456 context.view.offset_readable(offset)
3457 })
3458}
3459
3460extern "C" fn cb_offset_writable<C>(ctxt: *mut c_void, offset: u64) -> bool
3461where
3462 C: CustomBinaryView,
3463{
3464 ffi_wrap!("BinaryViewBase::writable", unsafe {
3465 let context = &*(ctxt as *mut CustomBinaryViewContext<C>);
3466 context.view.offset_writable(offset)
3467 })
3468}
3469
3470extern "C" fn cb_offset_executable<C>(ctxt: *mut c_void, offset: u64) -> bool
3471where
3472 C: CustomBinaryView,
3473{
3474 ffi_wrap!("BinaryViewBase::offset_executable", unsafe {
3475 let context = &*(ctxt as *mut CustomBinaryViewContext<C>);
3476 context.view.offset_executable(offset)
3477 })
3478}
3479
3480extern "C" fn cb_offset_backed_by_file<C>(ctxt: *mut c_void, offset: u64) -> bool
3481where
3482 C: CustomBinaryView,
3483{
3484 ffi_wrap!("BinaryViewBase::offset_backed_by_file", unsafe {
3485 let context = &*(ctxt as *mut CustomBinaryViewContext<C>);
3486 context.view.offset_backed_by_file(offset)
3487 })
3488}
3489
3490extern "C" fn cb_next_valid_offset<C>(ctxt: *mut c_void, offset: u64) -> u64
3491where
3492 C: CustomBinaryView,
3493{
3494 ffi_wrap!("BinaryViewBase::next_valid_offset_after", unsafe {
3495 let context = &*(ctxt as *mut CustomBinaryViewContext<C>);
3496 context.view.next_valid_offset_after(offset)
3497 })
3498}
3499
3500extern "C" fn cb_start<C>(ctxt: *mut c_void) -> u64
3501where
3502 C: CustomBinaryView,
3503{
3504 ffi_wrap!("BinaryViewBase::start", unsafe {
3505 let context = &*(ctxt as *mut CustomBinaryViewContext<C>);
3506 context.view.start()
3507 })
3508}
3509
3510extern "C" fn cb_length<C>(ctxt: *mut c_void) -> u64
3511where
3512 C: CustomBinaryView,
3513{
3514 ffi_wrap!("BinaryViewBase::len", unsafe {
3515 let context = &*(ctxt as *mut CustomBinaryViewContext<C>);
3516 context.view.len()
3517 })
3518}
3519
3520extern "C" fn cb_entry_point<C>(ctxt: *mut c_void) -> u64
3521where
3522 C: CustomBinaryView,
3523{
3524 ffi_wrap!("BinaryViewBase::entry_point", unsafe {
3525 let context = &*(ctxt as *mut CustomBinaryViewContext<C>);
3526 context.view.entry_point()
3527 })
3528}
3529
3530extern "C" fn cb_executable<C>(ctxt: *mut c_void) -> bool
3531where
3532 C: CustomBinaryView,
3533{
3534 ffi_wrap!("BinaryViewBase::executable", unsafe {
3535 let context = &*(ctxt as *mut CustomBinaryViewContext<C>);
3536 context.view.executable()
3537 })
3538}
3539
3540extern "C" fn cb_endianness<C>(ctxt: *mut c_void) -> Endianness
3541where
3542 C: CustomBinaryView,
3543{
3544 ffi_wrap!("BinaryViewBase::default_endianness", unsafe {
3545 let context = &*(ctxt as *mut CustomBinaryViewContext<C>);
3546 context.view.default_endianness()
3547 })
3548}
3549
3550extern "C" fn cb_relocatable<C>(ctxt: *mut c_void) -> bool
3551where
3552 C: CustomBinaryView,
3553{
3554 ffi_wrap!("BinaryViewBase::relocatable", unsafe {
3555 let context = &*(ctxt as *mut CustomBinaryViewContext<C>);
3556 context.view.relocatable()
3557 })
3558}
3559
3560extern "C" fn cb_address_size<C>(ctxt: *mut c_void) -> usize
3561where
3562 C: CustomBinaryView,
3563{
3564 ffi_wrap!("BinaryViewBase::address_size", unsafe {
3565 let context = &*(ctxt as *mut CustomBinaryViewContext<C>);
3566 context.view.address_size()
3567 })
3568}
3569
3570extern "C" fn cb_save<C>(ctxt: *mut c_void, _file: *mut BNFileAccessor) -> bool
3571where
3572 C: CustomBinaryView,
3573{
3574 ffi_wrap!("BinaryViewBase::save", unsafe {
3575 let context = &*(ctxt as *mut CustomBinaryViewContext<C>);
3576 context.view.save()
3579 })
3580}