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