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