1use binaryninjacore_sys::*;
25
26#[allow(unused)]
28pub use crate::workflow::AnalysisContext;
29
30use crate::architecture::{Architecture, CoreArchitecture};
31use crate::base_detection::BaseAddressDetection;
32use crate::basic_block::BasicBlock;
33use crate::component::Component;
34use crate::confidence::Conf;
35use crate::data_buffer::DataBuffer;
36use crate::debuginfo::DebugInfo;
37use crate::external_library::{ExternalLibrary, ExternalLocation};
38use crate::file_accessor::{Accessor, FileAccessor};
39use crate::file_metadata::FileMetadata;
40use crate::flowgraph::FlowGraph;
41use crate::function::{ArchAndAddr, Function, FunctionViewType, NativeBlock};
42use crate::linear_view::{LinearDisassemblyLine, LinearViewCursor};
43use crate::metadata::Metadata;
44use crate::platform::Platform;
45use crate::progress::{NoProgressCallback, ProgressCallback};
46use crate::project::file::ProjectFile;
47use crate::rc::*;
48use crate::references::{CodeReference, DataReference};
49use crate::relocation::Relocation;
50use crate::section::{Section, SectionBuilder};
51use crate::segment::{Segment, SegmentBuilder};
52use crate::settings::Settings;
53use crate::string::*;
54use crate::symbol::{Symbol, SymbolType};
55use crate::tags::{Tag, TagType};
56use crate::type_container::TypeContainer;
57use crate::type_library::TypeLibrary;
58use crate::types::{
59 NamedTypeReference, QualifiedName, QualifiedNameAndType, QualifiedNameTypeAndId, Type,
60};
61use crate::variable::DataVariable;
62use crate::Endianness;
63use std::collections::HashMap;
64use std::ffi::{c_char, c_void};
65use std::ops::Range;
66use std::path::Path;
67use std::ptr::NonNull;
68use std::{result, slice};
69pub mod memory_map;
72pub mod reader;
73pub mod search;
74pub mod writer;
75
76use crate::binary_view::search::SearchQuery;
77use crate::disassembly::DisassemblySettings;
78use crate::workflow::Workflow;
79pub use memory_map::MemoryMap;
80pub use reader::BinaryReader;
81pub use writer::BinaryWriter;
82
83pub type Result<R> = result::Result<R, ()>;
84pub type BinaryViewEventType = BNBinaryViewEventType;
85pub type AnalysisState = BNAnalysisState;
86pub type ModificationStatus = BNModificationStatus;
87pub type StringType = BNStringType;
88pub type FindFlag = BNFindFlag;
89
90#[allow(clippy::len_without_is_empty)]
91pub trait BinaryViewBase: AsRef<BinaryView> {
92 fn read(&self, _buf: &mut [u8], _offset: u64) -> usize {
93 0
94 }
95
96 fn write(&self, _offset: u64, _data: &[u8]) -> usize {
97 0
98 }
99
100 fn insert(&self, _offset: u64, _data: &[u8]) -> usize {
101 0
102 }
103
104 fn remove(&self, _offset: u64, _len: usize) -> usize {
105 0
106 }
107
108 fn offset_valid(&self, offset: u64) -> bool {
109 let mut buf = [0u8; 1];
110
111 self.as_ref().read(&mut buf[..], offset) == buf.len()
114 }
115
116 fn offset_readable(&self, offset: u64) -> bool {
117 self.offset_valid(offset)
118 }
119
120 fn offset_writable(&self, offset: u64) -> bool {
121 self.offset_valid(offset)
122 }
123
124 fn offset_executable(&self, offset: u64) -> bool {
125 self.offset_valid(offset)
126 }
127
128 fn offset_backed_by_file(&self, offset: u64) -> bool {
129 self.offset_valid(offset)
130 }
131
132 fn next_valid_offset_after(&self, offset: u64) -> u64 {
133 let start = self.as_ref().start();
134
135 if offset < start {
136 start
137 } else {
138 offset
139 }
140 }
141
142 #[allow(unused)]
143 fn modification_status(&self, offset: u64) -> ModificationStatus {
144 ModificationStatus::Original
145 }
146
147 fn start(&self) -> u64 {
148 0
149 }
150
151 fn len(&self) -> u64 {
152 0
153 }
154
155 fn executable(&self) -> bool {
156 true
157 }
158
159 fn relocatable(&self) -> bool {
160 true
161 }
162
163 fn entry_point(&self) -> u64;
164 fn default_endianness(&self) -> Endianness;
165 fn address_size(&self) -> usize;
166
167 fn save(&self) -> bool {
168 self.as_ref()
169 .parent_view()
170 .map(|view| view.save())
171 .unwrap_or(false)
172 }
173}
174
175#[derive(Debug, Clone)]
176pub struct ActiveAnalysisInfo {
177 pub func: Ref<Function>,
178 pub analysis_time: u64,
179 pub update_count: usize,
180 pub submit_count: usize,
181}
182
183#[derive(Debug, Clone)]
184pub struct AnalysisInfo {
185 pub state: AnalysisState,
186 pub analysis_time: u64,
187 pub active_info: Vec<ActiveAnalysisInfo>,
188}
189
190#[derive(Debug, Clone)]
191pub struct AnalysisProgress {
192 pub state: AnalysisState,
193 pub count: usize,
194 pub total: usize,
195}
196
197pub trait BinaryViewExt: BinaryViewBase {
198 fn file(&self) -> Ref<FileMetadata> {
199 unsafe {
200 let raw = BNGetFileForView(self.as_ref().handle);
201 FileMetadata::ref_from_raw(raw)
202 }
203 }
204
205 fn parent_view(&self) -> Option<Ref<BinaryView>> {
206 let raw_view_ptr = unsafe { BNGetParentView(self.as_ref().handle) };
207 match raw_view_ptr.is_null() {
208 false => Some(unsafe { BinaryView::ref_from_raw(raw_view_ptr) }),
209 true => None,
210 }
211 }
212
213 fn raw_view(&self) -> Option<Ref<BinaryView>> {
214 self.file().view_of_type("Raw")
215 }
216
217 fn view_type(&self) -> String {
218 let ptr: *mut c_char = unsafe { BNGetViewType(self.as_ref().handle) };
219 unsafe { BnString::into_string(ptr) }
220 }
221
222 fn read_vec(&self, offset: u64, len: usize) -> Vec<u8> {
224 let mut ret = vec![0; len];
225
226 let size = self.read(&mut ret, offset);
227 ret.truncate(size);
228
229 ret
230 }
231
232 fn read_into_vec(&self, dest: &mut Vec<u8>, offset: u64, len: usize) -> usize {
234 let starting_len = dest.len();
235 dest.resize(starting_len + len, 0);
236 let read_size = self.read(&mut dest[starting_len..], offset);
237 dest.truncate(starting_len + read_size);
238 read_size
239 }
240
241 fn search<C: FnMut(u64, &DataBuffer) -> bool>(&self, query: &SearchQuery, on_match: C) -> bool {
245 self.search_with_progress(query, on_match, NoProgressCallback)
246 }
247
248 fn search_with_progress<P: ProgressCallback, C: FnMut(u64, &DataBuffer) -> bool>(
252 &self,
253 query: &SearchQuery,
254 mut on_match: C,
255 mut progress: P,
256 ) -> bool {
257 unsafe extern "C" fn cb_on_match<C: FnMut(u64, &DataBuffer) -> bool>(
258 ctx: *mut c_void,
259 offset: u64,
260 data: *mut BNDataBuffer,
261 ) -> bool {
262 let f = ctx as *mut C;
263 let buffer = DataBuffer::from_raw(data);
264 (*f)(offset, &buffer)
265 }
266
267 let query = query.to_json().to_cstr();
268 unsafe {
269 BNSearch(
270 self.as_ref().handle,
271 query.as_ptr(),
272 &mut progress as *mut P as *mut c_void,
273 Some(P::cb_progress_callback),
274 &mut on_match as *const C as *mut c_void,
275 Some(cb_on_match::<C>),
276 )
277 }
278 }
279
280 fn find_next_data(&self, start: u64, end: u64, data: &DataBuffer) -> Option<u64> {
281 self.find_next_data_with_opts(
282 start,
283 end,
284 data,
285 FindFlag::FindCaseInsensitive,
286 NoProgressCallback,
287 )
288 }
289
290 fn find_next_data_with_opts<P: ProgressCallback>(
294 &self,
295 start: u64,
296 end: u64,
297 data: &DataBuffer,
298 flag: FindFlag,
299 mut progress: P,
300 ) -> Option<u64> {
301 let mut result: u64 = 0;
302 let found = unsafe {
303 BNFindNextDataWithProgress(
304 self.as_ref().handle,
305 start,
306 end,
307 data.as_raw(),
308 &mut result,
309 flag,
310 &mut progress as *mut P as *mut c_void,
311 Some(P::cb_progress_callback),
312 )
313 };
314
315 if found {
316 Some(result)
317 } else {
318 None
319 }
320 }
321
322 fn find_next_constant(
323 &self,
324 start: u64,
325 end: u64,
326 constant: u64,
327 view_type: FunctionViewType,
328 ) -> Option<u64> {
329 let settings = DisassemblySettings::new();
331 self.find_next_constant_with_opts(
332 start,
333 end,
334 constant,
335 &settings,
336 view_type,
337 NoProgressCallback,
338 )
339 }
340
341 fn find_next_constant_with_opts<P: ProgressCallback>(
345 &self,
346 start: u64,
347 end: u64,
348 constant: u64,
349 disasm_settings: &DisassemblySettings,
350 view_type: FunctionViewType,
351 mut progress: P,
352 ) -> Option<u64> {
353 let mut result: u64 = 0;
354 let raw_view_type = FunctionViewType::into_raw(view_type);
355 let found = unsafe {
356 BNFindNextConstantWithProgress(
357 self.as_ref().handle,
358 start,
359 end,
360 constant,
361 &mut result,
362 disasm_settings.handle,
363 raw_view_type,
364 &mut progress as *mut P as *mut c_void,
365 Some(P::cb_progress_callback),
366 )
367 };
368 FunctionViewType::free_raw(raw_view_type);
369
370 if found {
371 Some(result)
372 } else {
373 None
374 }
375 }
376
377 fn find_next_text(
378 &self,
379 start: u64,
380 end: u64,
381 text: &str,
382 view_type: FunctionViewType,
383 ) -> Option<u64> {
384 let settings = DisassemblySettings::new();
386 self.find_next_text_with_opts(
387 start,
388 end,
389 text,
390 &settings,
391 FindFlag::FindCaseInsensitive,
392 view_type,
393 NoProgressCallback,
394 )
395 }
396
397 fn find_next_text_with_opts<P: ProgressCallback>(
401 &self,
402 start: u64,
403 end: u64,
404 text: &str,
405 disasm_settings: &DisassemblySettings,
406 flag: FindFlag,
407 view_type: FunctionViewType,
408 mut progress: P,
409 ) -> Option<u64> {
410 let text = text.to_cstr();
411 let raw_view_type = FunctionViewType::into_raw(view_type);
412 let mut result: u64 = 0;
413 let found = unsafe {
414 BNFindNextTextWithProgress(
415 self.as_ref().handle,
416 start,
417 end,
418 text.as_ptr(),
419 &mut result,
420 disasm_settings.handle,
421 flag,
422 raw_view_type,
423 &mut progress as *mut P as *mut c_void,
424 Some(P::cb_progress_callback),
425 )
426 };
427 FunctionViewType::free_raw(raw_view_type);
428
429 if found {
430 Some(result)
431 } else {
432 None
433 }
434 }
435
436 fn notify_data_written(&self, offset: u64, len: usize) {
437 unsafe {
438 BNNotifyDataWritten(self.as_ref().handle, offset, len);
439 }
440 }
441
442 fn notify_data_inserted(&self, offset: u64, len: usize) {
443 unsafe {
444 BNNotifyDataInserted(self.as_ref().handle, offset, len);
445 }
446 }
447
448 fn notify_data_removed(&self, offset: u64, len: usize) {
449 unsafe {
450 BNNotifyDataRemoved(self.as_ref().handle, offset, len as u64);
451 }
452 }
453
454 fn offset_has_code_semantics(&self, offset: u64) -> bool {
457 unsafe { BNIsOffsetCodeSemantics(self.as_ref().handle, offset) }
458 }
459
460 fn offset_has_extern_semantics(&self, offset: u64) -> bool {
462 unsafe { BNIsOffsetExternSemantics(self.as_ref().handle, offset) }
463 }
464
465 fn offset_has_writable_semantics(&self, offset: u64) -> bool {
468 unsafe { BNIsOffsetWritableSemantics(self.as_ref().handle, offset) }
469 }
470
471 fn offset_has_read_only_semantics(&self, offset: u64) -> bool {
474 unsafe { BNIsOffsetReadOnlySemantics(self.as_ref().handle, offset) }
475 }
476
477 fn image_base(&self) -> u64 {
478 unsafe { BNGetImageBase(self.as_ref().handle) }
479 }
480
481 fn original_image_base(&self) -> u64 {
482 unsafe { BNGetOriginalImageBase(self.as_ref().handle) }
483 }
484
485 fn set_original_image_base(&self, image_base: u64) {
486 unsafe { BNSetOriginalImageBase(self.as_ref().handle, image_base) }
487 }
488
489 fn end(&self) -> u64 {
493 unsafe { BNGetEndOffset(self.as_ref().handle) }
494 }
495
496 fn add_analysis_option(&self, name: &str) {
497 let name = name.to_cstr();
498 unsafe { BNAddAnalysisOption(self.as_ref().handle, name.as_ptr()) }
499 }
500
501 fn has_initial_analysis(&self) -> bool {
502 unsafe { BNHasInitialAnalysis(self.as_ref().handle) }
503 }
504
505 fn set_analysis_hold(&self, enable: bool) {
506 unsafe { BNSetAnalysisHold(self.as_ref().handle, enable) }
507 }
508
509 fn update_analysis(&self) {
518 unsafe {
519 BNUpdateAnalysis(self.as_ref().handle);
520 }
521 }
522
523 fn update_analysis_and_wait(&self) {
532 unsafe {
533 BNUpdateAnalysisAndWait(self.as_ref().handle);
534 }
535 }
536
537 fn reanalyze(&self) {
544 unsafe {
545 BNReanalyzeAllFunctions(self.as_ref().handle);
546 }
547 }
548
549 fn abort_analysis(&self) {
550 unsafe { BNAbortAnalysis(self.as_ref().handle) }
551 }
552
553 fn analysis_is_aborted(&self) -> bool {
554 unsafe { BNAnalysisIsAborted(self.as_ref().handle) }
555 }
556
557 fn workflow(&self) -> Ref<Workflow> {
558 unsafe {
559 let raw_ptr = BNGetWorkflowForBinaryView(self.as_ref().handle);
560 let nonnull = NonNull::new(raw_ptr).expect("All views must have a workflow");
561 Workflow::ref_from_raw(nonnull)
562 }
563 }
564
565 fn analysis_info(&self) -> Result<AnalysisInfo> {
566 let info_ref = unsafe { BNGetAnalysisInfo(self.as_ref().handle) };
567 if info_ref.is_null() {
568 return Err(());
569 }
570 let info = unsafe { *info_ref };
571 let active_infos = unsafe { slice::from_raw_parts(info.activeInfo, info.count) };
572
573 let mut active_info_list = vec![];
574 for active_info in active_infos {
575 let func = unsafe { Function::ref_from_raw(active_info.func) };
576 active_info_list.push(ActiveAnalysisInfo {
577 func,
578 analysis_time: active_info.analysisTime,
579 update_count: active_info.updateCount,
580 submit_count: active_info.submitCount,
581 });
582 }
583
584 let result = AnalysisInfo {
585 state: info.state,
586 analysis_time: info.analysisTime,
587 active_info: vec![],
588 };
589
590 unsafe { BNFreeAnalysisInfo(info_ref) };
591 Ok(result)
592 }
593
594 fn analysis_progress(&self) -> AnalysisProgress {
595 let progress = unsafe { BNGetAnalysisProgress(self.as_ref().handle) };
596 AnalysisProgress {
597 state: progress.state,
598 count: progress.count,
599 total: progress.total,
600 }
601 }
602
603 fn default_arch(&self) -> Option<CoreArchitecture> {
604 unsafe {
605 let raw = BNGetDefaultArchitecture(self.as_ref().handle);
606
607 if raw.is_null() {
608 return None;
609 }
610
611 Some(CoreArchitecture::from_raw(raw))
612 }
613 }
614
615 fn set_default_arch<A: Architecture>(&self, arch: &A) {
616 unsafe {
617 BNSetDefaultArchitecture(self.as_ref().handle, arch.as_ref().handle);
618 }
619 }
620
621 fn default_platform(&self) -> Option<Ref<Platform>> {
622 unsafe {
623 let raw = BNGetDefaultPlatform(self.as_ref().handle);
624
625 if raw.is_null() {
626 return None;
627 }
628
629 Some(Platform::ref_from_raw(raw))
630 }
631 }
632
633 fn set_default_platform(&self, plat: &Platform) {
634 unsafe {
635 BNSetDefaultPlatform(self.as_ref().handle, plat.handle);
636 }
637 }
638
639 fn base_address_detection(&self) -> Option<BaseAddressDetection> {
640 unsafe {
641 let handle = BNCreateBaseAddressDetection(self.as_ref().handle);
642 NonNull::new(handle).map(|base| BaseAddressDetection::from_raw(base))
643 }
644 }
645
646 fn instruction_len<A: Architecture>(&self, arch: &A, addr: u64) -> Option<usize> {
647 unsafe {
648 let size = BNGetInstructionLength(self.as_ref().handle, arch.as_ref().handle, addr);
649
650 if size > 0 {
651 Some(size)
652 } else {
653 None
654 }
655 }
656 }
657
658 fn symbol_by_address(&self, addr: u64) -> Option<Ref<Symbol>> {
659 unsafe {
660 let raw_sym_ptr =
661 BNGetSymbolByAddress(self.as_ref().handle, addr, std::ptr::null_mut());
662 match raw_sym_ptr.is_null() {
663 false => Some(Symbol::ref_from_raw(raw_sym_ptr)),
664 true => None,
665 }
666 }
667 }
668
669 fn symbol_by_raw_name(&self, raw_name: impl IntoCStr) -> Option<Ref<Symbol>> {
670 let raw_name = raw_name.to_cstr();
671
672 unsafe {
673 let raw_sym_ptr = BNGetSymbolByRawName(
674 self.as_ref().handle,
675 raw_name.as_ptr(),
676 std::ptr::null_mut(),
677 );
678 match raw_sym_ptr.is_null() {
679 false => Some(Symbol::ref_from_raw(raw_sym_ptr)),
680 true => None,
681 }
682 }
683 }
684
685 fn symbols(&self) -> Array<Symbol> {
686 unsafe {
687 let mut count = 0;
688 let handles = BNGetSymbols(self.as_ref().handle, &mut count, std::ptr::null_mut());
689
690 Array::new(handles, count, ())
691 }
692 }
693
694 fn symbols_by_name(&self, name: impl IntoCStr) -> Array<Symbol> {
695 let raw_name = name.to_cstr();
696
697 unsafe {
698 let mut count = 0;
699 let handles = BNGetSymbolsByName(
700 self.as_ref().handle,
701 raw_name.as_ptr(),
702 &mut count,
703 std::ptr::null_mut(),
704 );
705
706 Array::new(handles, count, ())
707 }
708 }
709
710 fn symbols_in_range(&self, range: Range<u64>) -> Array<Symbol> {
711 unsafe {
712 let mut count = 0;
713 let len = range.end.wrapping_sub(range.start);
714 let handles = BNGetSymbolsInRange(
715 self.as_ref().handle,
716 range.start,
717 len,
718 &mut count,
719 std::ptr::null_mut(),
720 );
721
722 Array::new(handles, count, ())
723 }
724 }
725
726 fn symbols_of_type(&self, ty: SymbolType) -> Array<Symbol> {
727 unsafe {
728 let mut count = 0;
729 let handles = BNGetSymbolsOfType(
730 self.as_ref().handle,
731 ty.into(),
732 &mut count,
733 std::ptr::null_mut(),
734 );
735
736 Array::new(handles, count, ())
737 }
738 }
739
740 fn symbols_of_type_in_range(&self, ty: SymbolType, range: Range<u64>) -> Array<Symbol> {
741 unsafe {
742 let mut count = 0;
743 let len = range.end.wrapping_sub(range.start);
744 let handles = BNGetSymbolsOfTypeInRange(
745 self.as_ref().handle,
746 ty.into(),
747 range.start,
748 len,
749 &mut count,
750 std::ptr::null_mut(),
751 );
752
753 Array::new(handles, count, ())
754 }
755 }
756
757 fn define_auto_symbol(&self, sym: &Symbol) {
758 unsafe {
759 BNDefineAutoSymbol(self.as_ref().handle, sym.handle);
760 }
761 }
762
763 fn define_auto_symbol_with_type<'a, T: Into<Option<&'a Type>>>(
764 &self,
765 sym: &Symbol,
766 plat: &Platform,
767 ty: T,
768 ) -> Result<Ref<Symbol>> {
769 let mut type_with_conf = BNTypeWithConfidence {
770 type_: if let Some(t) = ty.into() {
771 t.handle
772 } else {
773 std::ptr::null_mut()
774 },
775 confidence: 255, };
777
778 unsafe {
779 let raw_sym = BNDefineAutoSymbolAndVariableOrFunction(
780 self.as_ref().handle,
781 plat.handle,
782 sym.handle,
783 &mut type_with_conf,
784 );
785
786 if raw_sym.is_null() {
787 return Err(());
788 }
789
790 Ok(Symbol::ref_from_raw(raw_sym))
791 }
792 }
793
794 fn undefine_auto_symbol(&self, sym: &Symbol) {
795 unsafe {
796 BNUndefineAutoSymbol(self.as_ref().handle, sym.handle);
797 }
798 }
799
800 fn define_user_symbol(&self, sym: &Symbol) {
801 unsafe {
802 BNDefineUserSymbol(self.as_ref().handle, sym.handle);
803 }
804 }
805
806 fn undefine_user_symbol(&self, sym: &Symbol) {
807 unsafe {
808 BNUndefineUserSymbol(self.as_ref().handle, sym.handle);
809 }
810 }
811
812 fn data_variables(&self) -> Array<DataVariable> {
813 unsafe {
814 let mut count = 0;
815 let vars = BNGetDataVariables(self.as_ref().handle, &mut count);
816 Array::new(vars, count, ())
817 }
818 }
819
820 fn data_variable_at_address(&self, addr: u64) -> Option<DataVariable> {
821 let mut dv = BNDataVariable::default();
822 unsafe {
823 if BNGetDataVariableAtAddress(self.as_ref().handle, addr, &mut dv) {
824 Some(DataVariable::from_owned_raw(dv))
825 } else {
826 None
827 }
828 }
829 }
830
831 fn define_auto_data_var<'a, T: Into<Conf<&'a Type>>>(&self, addr: u64, ty: T) {
832 let mut owned_raw_ty = Conf::<&Type>::into_raw(ty.into());
833 unsafe {
834 BNDefineDataVariable(self.as_ref().handle, addr, &mut owned_raw_ty);
835 }
836 }
837
838 fn define_user_data_var<'a, T: Into<Conf<&'a Type>>>(&self, addr: u64, ty: T) {
840 let mut owned_raw_ty = Conf::<&Type>::into_raw(ty.into());
841 unsafe {
842 BNDefineUserDataVariable(self.as_ref().handle, addr, &mut owned_raw_ty);
843 }
844 }
845
846 fn undefine_auto_data_var(&self, addr: u64, blacklist: Option<bool>) {
847 unsafe {
848 BNUndefineDataVariable(self.as_ref().handle, addr, blacklist.unwrap_or(true));
849 }
850 }
851
852 fn undefine_user_data_var(&self, addr: u64) {
853 unsafe {
854 BNUndefineUserDataVariable(self.as_ref().handle, addr);
855 }
856 }
857
858 fn define_auto_type<T: Into<QualifiedName>>(
859 &self,
860 name: T,
861 source: &str,
862 type_obj: &Type,
863 ) -> QualifiedName {
864 let mut raw_name = QualifiedName::into_raw(name.into());
865 let source_str = source.to_cstr();
866 let name_handle = unsafe {
867 let id_str =
868 BNGenerateAutoTypeId(source_str.as_ref().as_ptr() as *const _, &mut raw_name);
869 BNDefineAnalysisType(self.as_ref().handle, id_str, &mut raw_name, type_obj.handle)
870 };
871 QualifiedName::free_raw(raw_name);
872 QualifiedName::from_owned_raw(name_handle)
873 }
874
875 fn define_auto_type_with_id<T: Into<QualifiedName>>(
876 &self,
877 name: T,
878 id: &str,
879 type_obj: &Type,
880 ) -> QualifiedName {
881 let mut raw_name = QualifiedName::into_raw(name.into());
882 let id_str = id.to_cstr();
883 let result_raw_name = unsafe {
884 BNDefineAnalysisType(
885 self.as_ref().handle,
886 id_str.as_ref().as_ptr() as *const _,
887 &mut raw_name,
888 type_obj.handle,
889 )
890 };
891 QualifiedName::free_raw(raw_name);
892 QualifiedName::from_owned_raw(result_raw_name)
893 }
894
895 fn define_user_type<T: Into<QualifiedName>>(&self, name: T, type_obj: &Type) {
896 let mut raw_name = QualifiedName::into_raw(name.into());
897 unsafe { BNDefineUserAnalysisType(self.as_ref().handle, &mut raw_name, type_obj.handle) }
898 QualifiedName::free_raw(raw_name);
899 }
900
901 fn define_auto_types<T, I>(&self, names_sources_and_types: T) -> HashMap<String, QualifiedName>
902 where
903 T: Iterator<Item = I>,
904 I: Into<QualifiedNameTypeAndId>,
905 {
906 self.define_auto_types_with_progress(names_sources_and_types, NoProgressCallback)
907 }
908
909 fn define_auto_types_with_progress<T, I, P>(
910 &self,
911 names_sources_and_types: T,
912 mut progress: P,
913 ) -> HashMap<String, QualifiedName>
914 where
915 T: Iterator<Item = I>,
916 I: Into<QualifiedNameTypeAndId>,
917 P: ProgressCallback,
918 {
919 let mut types: Vec<BNQualifiedNameTypeAndId> = names_sources_and_types
920 .map(Into::into)
921 .map(QualifiedNameTypeAndId::into_raw)
922 .collect();
923 let mut result_ids: *mut *mut c_char = std::ptr::null_mut();
924 let mut result_names: *mut BNQualifiedName = std::ptr::null_mut();
925
926 let result_count = unsafe {
927 BNDefineAnalysisTypes(
928 self.as_ref().handle,
929 types.as_mut_ptr(),
930 types.len(),
931 Some(P::cb_progress_callback),
932 &mut progress as *mut P as *mut c_void,
933 &mut result_ids as *mut _,
934 &mut result_names as *mut _,
935 )
936 };
937
938 for ty in types {
939 QualifiedNameTypeAndId::free_raw(ty);
940 }
941
942 let id_array = unsafe { Array::<BnString>::new(result_ids, result_count, ()) };
943 let name_array = unsafe { Array::<QualifiedName>::new(result_names, result_count, ()) };
944 id_array
945 .into_iter()
946 .zip(&name_array)
947 .map(|(id, name)| (id.to_owned(), name))
948 .collect()
949 }
950
951 fn define_user_types<T, I>(&self, names_and_types: T)
952 where
953 T: Iterator<Item = I>,
954 I: Into<QualifiedNameAndType>,
955 {
956 self.define_user_types_with_progress(names_and_types, NoProgressCallback);
957 }
958
959 fn define_user_types_with_progress<T, I, P>(&self, names_and_types: T, mut progress: P)
960 where
961 T: Iterator<Item = I>,
962 I: Into<QualifiedNameAndType>,
963 P: ProgressCallback,
964 {
965 let mut types: Vec<BNQualifiedNameAndType> = names_and_types
966 .map(Into::into)
967 .map(QualifiedNameAndType::into_raw)
968 .collect();
969
970 unsafe {
971 BNDefineUserAnalysisTypes(
972 self.as_ref().handle,
973 types.as_mut_ptr(),
974 types.len(),
975 Some(P::cb_progress_callback),
976 &mut progress as *mut P as *mut c_void,
977 )
978 };
979
980 for ty in types {
981 QualifiedNameAndType::free_raw(ty);
982 }
983 }
984
985 fn undefine_auto_type(&self, id: &str) {
986 let id_str = id.to_cstr();
987 unsafe {
988 BNUndefineAnalysisType(self.as_ref().handle, id_str.as_ref().as_ptr() as *const _);
989 }
990 }
991
992 fn undefine_user_type<T: Into<QualifiedName>>(&self, name: T) {
993 let mut raw_name = QualifiedName::into_raw(name.into());
994 unsafe { BNUndefineUserAnalysisType(self.as_ref().handle, &mut raw_name) }
995 QualifiedName::free_raw(raw_name);
996 }
997
998 fn types(&self) -> Array<QualifiedNameAndType> {
999 unsafe {
1000 let mut count = 0usize;
1001 let types = BNGetAnalysisTypeList(self.as_ref().handle, &mut count);
1002 Array::new(types, count, ())
1003 }
1004 }
1005
1006 fn dependency_sorted_types(&self) -> Array<QualifiedNameAndType> {
1007 unsafe {
1008 let mut count = 0usize;
1009 let types = BNGetAnalysisDependencySortedTypeList(self.as_ref().handle, &mut count);
1010 Array::new(types, count, ())
1011 }
1012 }
1013
1014 fn type_by_name<T: Into<QualifiedName>>(&self, name: T) -> Option<Ref<Type>> {
1015 let mut raw_name = QualifiedName::into_raw(name.into());
1016 unsafe {
1017 let type_handle = BNGetAnalysisTypeByName(self.as_ref().handle, &mut raw_name);
1018 QualifiedName::free_raw(raw_name);
1019 if type_handle.is_null() {
1020 return None;
1021 }
1022 Some(Type::ref_from_raw(type_handle))
1023 }
1024 }
1025
1026 fn type_by_ref(&self, ref_: &NamedTypeReference) -> Option<Ref<Type>> {
1027 unsafe {
1028 let type_handle = BNGetAnalysisTypeByRef(self.as_ref().handle, ref_.handle);
1029 if type_handle.is_null() {
1030 return None;
1031 }
1032 Some(Type::ref_from_raw(type_handle))
1033 }
1034 }
1035
1036 fn type_by_id(&self, id: &str) -> Option<Ref<Type>> {
1037 let id_str = id.to_cstr();
1038 unsafe {
1039 let type_handle = BNGetAnalysisTypeById(self.as_ref().handle, id_str.as_ptr());
1040 if type_handle.is_null() {
1041 return None;
1042 }
1043 Some(Type::ref_from_raw(type_handle))
1044 }
1045 }
1046
1047 fn type_name_by_id(&self, id: &str) -> Option<QualifiedName> {
1048 let id_str = id.to_cstr();
1049 unsafe {
1050 let name_handle = BNGetAnalysisTypeNameById(self.as_ref().handle, id_str.as_ptr());
1051 let name = QualifiedName::from_owned_raw(name_handle);
1052 match name.items.is_empty() {
1054 true => None,
1055 false => Some(name),
1056 }
1057 }
1058 }
1059
1060 fn type_id_by_name<T: Into<QualifiedName>>(&self, name: T) -> Option<String> {
1061 let mut raw_name = QualifiedName::into_raw(name.into());
1062 unsafe {
1063 let id_cstr = BNGetAnalysisTypeId(self.as_ref().handle, &mut raw_name);
1064 QualifiedName::free_raw(raw_name);
1065 let id = BnString::into_string(id_cstr);
1066 match id.is_empty() {
1067 true => None,
1068 false => Some(id),
1069 }
1070 }
1071 }
1072
1073 fn is_type_auto_defined<T: Into<QualifiedName>>(&self, name: T) -> bool {
1074 let mut raw_name = QualifiedName::into_raw(name.into());
1075 let result = unsafe { BNIsAnalysisTypeAutoDefined(self.as_ref().handle, &mut raw_name) };
1076 QualifiedName::free_raw(raw_name);
1077 result
1078 }
1079
1080 fn segments(&self) -> Array<Segment> {
1081 unsafe {
1082 let mut count = 0;
1083 let raw_segments = BNGetSegments(self.as_ref().handle, &mut count);
1084 Array::new(raw_segments, count, ())
1085 }
1086 }
1087
1088 fn segment_at(&self, addr: u64) -> Option<Ref<Segment>> {
1089 unsafe {
1090 let raw_seg = BNGetSegmentAt(self.as_ref().handle, addr);
1091 match raw_seg.is_null() {
1092 false => Some(Segment::ref_from_raw(raw_seg)),
1093 true => None,
1094 }
1095 }
1096 }
1097
1098 fn add_segment(&self, segment: SegmentBuilder) {
1103 segment.create(self.as_ref());
1104 }
1105
1106 fn begin_bulk_add_segments(&self) {
1117 unsafe { BNBeginBulkAddSegments(self.as_ref().handle) }
1118 }
1119
1120 fn end_bulk_add_segments(&self) {
1126 unsafe { BNEndBulkAddSegments(self.as_ref().handle) }
1127 }
1128
1129 fn cancel_bulk_add_segments(&self) {
1137 unsafe { BNCancelBulkAddSegments(self.as_ref().handle) }
1138 }
1139
1140 fn add_section(&self, section: SectionBuilder) {
1141 section.create(self.as_ref());
1142 }
1143
1144 fn remove_auto_section(&self, name: impl IntoCStr) {
1145 let raw_name = name.to_cstr();
1146 let raw_name_ptr = raw_name.as_ptr();
1147 unsafe {
1148 BNRemoveAutoSection(self.as_ref().handle, raw_name_ptr);
1149 }
1150 }
1151
1152 fn remove_user_section(&self, name: impl IntoCStr) {
1153 let raw_name = name.to_cstr();
1154 let raw_name_ptr = raw_name.as_ptr();
1155 unsafe {
1156 BNRemoveUserSection(self.as_ref().handle, raw_name_ptr);
1157 }
1158 }
1159
1160 fn section_by_name(&self, name: impl IntoCStr) -> Option<Ref<Section>> {
1161 unsafe {
1162 let raw_name = name.to_cstr();
1163 let name_ptr = raw_name.as_ptr();
1164 let raw_section_ptr = BNGetSectionByName(self.as_ref().handle, name_ptr);
1165 match raw_section_ptr.is_null() {
1166 false => Some(Section::ref_from_raw(raw_section_ptr)),
1167 true => None,
1168 }
1169 }
1170 }
1171
1172 fn sections(&self) -> Array<Section> {
1173 unsafe {
1174 let mut count = 0;
1175 let sections = BNGetSections(self.as_ref().handle, &mut count);
1176 Array::new(sections, count, ())
1177 }
1178 }
1179
1180 fn sections_at(&self, addr: u64) -> Array<Section> {
1181 unsafe {
1182 let mut count = 0;
1183 let sections = BNGetSectionsAt(self.as_ref().handle, addr, &mut count);
1184 Array::new(sections, count, ())
1185 }
1186 }
1187
1188 fn memory_map(&self) -> MemoryMap {
1189 MemoryMap::new(self.as_ref().to_owned())
1190 }
1191
1192 fn add_auto_function(&self, address: u64) -> Option<Ref<Function>> {
1198 let platform = self.default_platform()?;
1199 self.add_auto_function_with_platform(address, &platform)
1200 }
1201
1202 fn add_auto_function_with_platform(
1208 &self,
1209 address: u64,
1210 platform: &Platform,
1211 ) -> Option<Ref<Function>> {
1212 self.add_auto_function_ext(address, platform, None)
1213 }
1214
1215 fn add_auto_function_ext(
1219 &self,
1220 address: u64,
1221 platform: &Platform,
1222 func_type: Option<&Type>,
1223 ) -> Option<Ref<Function>> {
1224 unsafe {
1225 let func_type = match func_type {
1226 Some(func_type) => func_type.handle,
1227 None => std::ptr::null_mut(),
1228 };
1229
1230 let handle = BNAddFunctionForAnalysis(
1231 self.as_ref().handle,
1232 platform.handle,
1233 address,
1234 true,
1235 func_type,
1236 );
1237
1238 if handle.is_null() {
1239 return None;
1240 }
1241
1242 Some(Function::ref_from_raw(handle))
1243 }
1244 }
1245
1246 fn remove_auto_function(&self, func: &Function, update_refs: bool) {
1254 unsafe {
1255 BNRemoveAnalysisFunction(self.as_ref().handle, func.handle, update_refs);
1256 }
1257 }
1258
1259 fn add_user_function(&self, addr: u64) -> Option<Ref<Function>> {
1265 let platform = self.default_platform()?;
1266 self.add_user_function_with_platform(addr, &platform)
1267 }
1268
1269 fn add_user_function_with_platform(
1273 &self,
1274 addr: u64,
1275 platform: &Platform,
1276 ) -> Option<Ref<Function>> {
1277 unsafe {
1278 let func = BNCreateUserFunction(self.as_ref().handle, platform.handle, addr);
1279 if func.is_null() {
1280 return None;
1281 }
1282 Some(Function::ref_from_raw(func))
1283 }
1284 }
1285
1286 fn remove_user_function(&self, func: &Function) {
1290 unsafe { BNRemoveUserFunction(self.as_ref().handle, func.handle) }
1291 }
1292
1293 fn has_functions(&self) -> bool {
1294 unsafe { BNHasFunctions(self.as_ref().handle) }
1295 }
1296
1297 fn add_entry_point(&self, addr: u64) {
1301 if let Some(platform) = self.default_platform() {
1302 self.add_entry_point_with_platform(addr, &platform);
1303 }
1304 }
1305
1306 fn add_entry_point_with_platform(&self, addr: u64, platform: &Platform) {
1310 unsafe {
1311 BNAddEntryPointForAnalysis(self.as_ref().handle, platform.handle, addr);
1312 }
1313 }
1314
1315 fn entry_point_function(&self) -> Option<Ref<Function>> {
1316 unsafe {
1317 let raw_func_ptr = BNGetAnalysisEntryPoint(self.as_ref().handle);
1318 match raw_func_ptr.is_null() {
1319 false => Some(Function::ref_from_raw(raw_func_ptr)),
1320 true => None,
1321 }
1322 }
1323 }
1324
1325 fn entry_point_functions(&self) -> Array<Function> {
1326 unsafe {
1327 let mut count = 0;
1328 let functions = BNGetAllEntryFunctions(self.as_ref().handle, &mut count);
1329
1330 Array::new(functions, count, ())
1331 }
1332 }
1333
1334 fn functions(&self) -> Array<Function> {
1335 unsafe {
1336 let mut count = 0;
1337 let functions = BNGetAnalysisFunctionList(self.as_ref().handle, &mut count);
1338
1339 Array::new(functions, count, ())
1340 }
1341 }
1342
1343 fn functions_at(&self, addr: u64) -> Array<Function> {
1345 unsafe {
1346 let mut count = 0;
1347 let functions =
1348 BNGetAnalysisFunctionsForAddress(self.as_ref().handle, addr, &mut count);
1349
1350 Array::new(functions, count, ())
1351 }
1352 }
1353
1354 fn functions_containing(&self, addr: u64) -> Array<Function> {
1356 unsafe {
1357 let mut count = 0;
1358 let functions =
1359 BNGetAnalysisFunctionsContainingAddress(self.as_ref().handle, addr, &mut count);
1360
1361 Array::new(functions, count, ())
1362 }
1363 }
1364
1365 fn functions_by_name(
1375 &self,
1376 name: impl IntoCStr,
1377 plat: Option<&Platform>,
1378 ) -> Vec<Ref<Function>> {
1379 let name = name.to_cstr();
1380 let symbols = self.symbols_by_name(&*name);
1381 let mut addresses: Vec<u64> = symbols.into_iter().map(|s| s.address()).collect();
1382 if addresses.is_empty() && name.to_bytes().starts_with(b"sub_") {
1383 if let Ok(str) = name.to_str() {
1384 if let Ok(address) = u64::from_str_radix(&str[4..], 16) {
1385 addresses.push(address);
1386 }
1387 }
1388 }
1389
1390 let mut functions = Vec::new();
1391
1392 for address in addresses {
1393 let funcs = self.functions_at(address);
1394 for func in funcs.into_iter() {
1395 if func.start() == address && plat.map_or(true, |p| p == func.platform().as_ref()) {
1396 functions.push(func.clone());
1397 }
1398 }
1399 }
1400
1401 functions
1402 }
1403
1404 fn function_at(&self, platform: &Platform, addr: u64) -> Option<Ref<Function>> {
1405 unsafe {
1406 let raw_func_ptr = BNGetAnalysisFunction(self.as_ref().handle, platform.handle, addr);
1407 match raw_func_ptr.is_null() {
1408 false => Some(Function::ref_from_raw(raw_func_ptr)),
1409 true => None,
1410 }
1411 }
1412 }
1413
1414 fn function_start_before(&self, addr: u64) -> u64 {
1415 unsafe { BNGetPreviousFunctionStartBeforeAddress(self.as_ref().handle, addr) }
1416 }
1417
1418 fn function_start_after(&self, addr: u64) -> u64 {
1419 unsafe { BNGetNextFunctionStartAfterAddress(self.as_ref().handle, addr) }
1420 }
1421
1422 fn basic_blocks_containing(&self, addr: u64) -> Array<BasicBlock<NativeBlock>> {
1423 unsafe {
1424 let mut count = 0;
1425 let blocks = BNGetBasicBlocksForAddress(self.as_ref().handle, addr, &mut count);
1426 Array::new(blocks, count, NativeBlock::new())
1427 }
1428 }
1429
1430 fn basic_blocks_starting_at(&self, addr: u64) -> Array<BasicBlock<NativeBlock>> {
1431 unsafe {
1432 let mut count = 0;
1433 let blocks = BNGetBasicBlocksStartingAtAddress(self.as_ref().handle, addr, &mut count);
1434 Array::new(blocks, count, NativeBlock::new())
1435 }
1436 }
1437
1438 fn is_new_auto_function_analysis_suppressed(&self) -> bool {
1439 unsafe { BNGetNewAutoFunctionAnalysisSuppressed(self.as_ref().handle) }
1440 }
1441
1442 fn set_new_auto_function_analysis_suppressed(&self, suppress: bool) {
1443 unsafe {
1444 BNSetNewAutoFunctionAnalysisSuppressed(self.as_ref().handle, suppress);
1445 }
1446 }
1447
1448 fn should_skip_target_analysis(
1449 &self,
1450 source: &ArchAndAddr,
1451 srcfunc: &Function,
1452 srcend: u64,
1453 target: &ArchAndAddr,
1454 ) -> bool {
1455 let mut srccopy = BNArchitectureAndAddress {
1456 arch: source.arch.handle,
1457 address: source.addr,
1458 };
1459 let mut targetcopy = BNArchitectureAndAddress {
1460 arch: target.arch.handle,
1461 address: target.addr,
1462 };
1463
1464 unsafe {
1465 BNShouldSkipTargetAnalysis(
1466 self.as_ref().handle,
1467 &mut srccopy,
1468 srcfunc.handle,
1469 srcend,
1470 &mut targetcopy,
1471 )
1472 }
1473 }
1474
1475 fn read_buffer(&self, offset: u64, len: usize) -> Result<DataBuffer> {
1476 let read_buffer = unsafe { BNReadViewBuffer(self.as_ref().handle, offset, len) };
1477 if read_buffer.is_null() {
1478 Err(())
1479 } else {
1480 Ok(DataBuffer::from_raw(read_buffer))
1481 }
1482 }
1483
1484 fn debug_info(&self) -> Ref<DebugInfo> {
1485 unsafe { DebugInfo::ref_from_raw(BNGetDebugInfo(self.as_ref().handle)) }
1486 }
1487
1488 fn set_debug_info(&self, debug_info: &DebugInfo) {
1489 unsafe { BNSetDebugInfo(self.as_ref().handle, debug_info.handle) }
1490 }
1491
1492 fn apply_debug_info(&self, debug_info: &DebugInfo) {
1493 unsafe { BNApplyDebugInfo(self.as_ref().handle, debug_info.handle) }
1494 }
1495
1496 fn show_plaintext_report(&self, title: &str, plaintext: &str) {
1497 let title = title.to_cstr();
1498 let plaintext = plaintext.to_cstr();
1499 unsafe {
1500 BNShowPlainTextReport(
1501 self.as_ref().handle,
1502 title.as_ref().as_ptr() as *mut _,
1503 plaintext.as_ref().as_ptr() as *mut _,
1504 )
1505 }
1506 }
1507
1508 fn show_markdown_report(&self, title: &str, contents: &str, plaintext: &str) {
1509 let title = title.to_cstr();
1510 let contents = contents.to_cstr();
1511 let plaintext = plaintext.to_cstr();
1512 unsafe {
1513 BNShowMarkdownReport(
1514 self.as_ref().handle,
1515 title.as_ref().as_ptr() as *mut _,
1516 contents.as_ref().as_ptr() as *mut _,
1517 plaintext.as_ref().as_ptr() as *mut _,
1518 )
1519 }
1520 }
1521
1522 fn show_html_report(&self, title: &str, contents: &str, plaintext: &str) {
1523 let title = title.to_cstr();
1524 let contents = contents.to_cstr();
1525 let plaintext = plaintext.to_cstr();
1526 unsafe {
1527 BNShowHTMLReport(
1528 self.as_ref().handle,
1529 title.as_ref().as_ptr() as *mut _,
1530 contents.as_ref().as_ptr() as *mut _,
1531 plaintext.as_ref().as_ptr() as *mut _,
1532 )
1533 }
1534 }
1535
1536 fn show_graph_report(&self, raw_name: &str, graph: &FlowGraph) {
1537 let raw_name = raw_name.to_cstr();
1538 unsafe {
1539 BNShowGraphReport(self.as_ref().handle, raw_name.as_ptr(), graph.handle);
1540 }
1541 }
1542
1543 fn load_settings(&self, view_type_name: &str) -> Result<Ref<Settings>> {
1544 let view_type_name = view_type_name.to_cstr();
1545 let settings_handle =
1546 unsafe { BNBinaryViewGetLoadSettings(self.as_ref().handle, view_type_name.as_ptr()) };
1547
1548 if settings_handle.is_null() {
1549 Err(())
1550 } else {
1551 Ok(unsafe { Settings::ref_from_raw(settings_handle) })
1552 }
1553 }
1554
1555 fn set_load_settings(&self, view_type_name: &str, settings: &Settings) {
1556 let view_type_name = view_type_name.to_cstr();
1557
1558 unsafe {
1559 BNBinaryViewSetLoadSettings(
1560 self.as_ref().handle,
1561 view_type_name.as_ptr(),
1562 settings.handle,
1563 )
1564 };
1565 }
1566
1567 fn create_tag_type(&self, name: &str, icon: &str) -> Ref<TagType> {
1573 let tag_type = TagType::create(self.as_ref(), name, icon);
1574 unsafe {
1575 BNAddTagType(self.as_ref().handle, tag_type.handle);
1576 }
1577 tag_type
1578 }
1579
1580 fn remove_tag_type(&self, tag_type: &TagType) {
1582 unsafe { BNRemoveTagType(self.as_ref().handle, tag_type.handle) }
1583 }
1584
1585 fn tag_type_by_name(&self, name: &str) -> Option<Ref<TagType>> {
1587 let name = name.to_cstr();
1588 unsafe {
1589 let handle = BNGetTagType(self.as_ref().handle, name.as_ptr());
1590 if handle.is_null() {
1591 return None;
1592 }
1593 Some(TagType::ref_from_raw(handle))
1594 }
1595 }
1596
1597 fn tag_by_id(&self, id: &str) -> Option<Ref<Tag>> {
1601 let id = id.to_cstr();
1602 unsafe {
1603 let handle = BNGetTag(self.as_ref().handle, id.as_ptr());
1604 if handle.is_null() {
1605 return None;
1606 }
1607 Some(Tag::ref_from_raw(handle))
1608 }
1609 }
1610
1611 fn add_tag(&self, addr: u64, t: &TagType, data: &str, user: bool) {
1615 let tag = Tag::new(t, data);
1616
1617 unsafe { BNAddTag(self.as_ref().handle, tag.handle, user) }
1618
1619 if user {
1620 unsafe { BNAddUserDataTag(self.as_ref().handle, addr, tag.handle) }
1621 } else {
1622 unsafe { BNAddAutoDataTag(self.as_ref().handle, addr, tag.handle) }
1623 }
1624 }
1625
1626 fn remove_auto_data_tag(&self, addr: u64, tag: &Tag) {
1628 unsafe { BNRemoveAutoDataTag(self.as_ref().handle, addr, tag.handle) }
1629 }
1630
1631 fn remove_user_data_tag(&self, addr: u64, tag: &Tag) {
1634 unsafe { BNRemoveUserDataTag(self.as_ref().handle, addr, tag.handle) }
1635 }
1636
1637 fn comment_at(&self, addr: u64) -> Option<String> {
1638 unsafe {
1639 let comment_raw = BNGetGlobalCommentForAddress(self.as_ref().handle, addr);
1640 match comment_raw.is_null() {
1641 false => Some(BnString::into_string(comment_raw)),
1642 true => None,
1643 }
1644 }
1645 }
1646
1647 fn set_comment_at(&self, addr: u64, comment: &str) {
1652 let comment_raw = comment.to_cstr();
1653 unsafe { BNSetGlobalCommentForAddress(self.as_ref().handle, addr, comment_raw.as_ptr()) }
1654 }
1655
1656 fn get_next_linear_disassembly_lines(
1665 &self,
1666 pos: &mut LinearViewCursor,
1667 ) -> Array<LinearDisassemblyLine> {
1668 let mut result = unsafe { Array::new(std::ptr::null_mut(), 0, ()) };
1669
1670 while result.is_empty() {
1671 result = pos.lines();
1672 if !pos.next() {
1673 return result;
1674 }
1675 }
1676
1677 result
1678 }
1679
1680 fn get_previous_linear_disassembly_lines(
1689 &self,
1690 pos: &mut LinearViewCursor,
1691 ) -> Array<LinearDisassemblyLine> {
1692 let mut result = unsafe { Array::new(std::ptr::null_mut(), 0, ()) };
1693 while result.is_empty() {
1694 if !pos.previous() {
1695 return result;
1696 }
1697
1698 result = pos.lines();
1699 }
1700
1701 result
1702 }
1703
1704 fn query_metadata(&self, key: &str) -> Option<Ref<Metadata>> {
1705 let key = key.to_cstr();
1706 let value: *mut BNMetadata =
1707 unsafe { BNBinaryViewQueryMetadata(self.as_ref().handle, key.as_ptr()) };
1708 if value.is_null() {
1709 None
1710 } else {
1711 Some(unsafe { Metadata::ref_from_raw(value) })
1712 }
1713 }
1714
1715 fn get_metadata<T>(&self, key: &str) -> Option<Result<T>>
1716 where
1717 T: for<'a> TryFrom<&'a Metadata>,
1718 {
1719 self.query_metadata(key)
1720 .map(|md| T::try_from(md.as_ref()).map_err(|_| ()))
1721 }
1722
1723 fn store_metadata<V>(&self, key: &str, value: V, is_auto: bool)
1724 where
1725 V: Into<Ref<Metadata>>,
1726 {
1727 let md = value.into();
1728 let key = key.to_cstr();
1729 unsafe {
1730 BNBinaryViewStoreMetadata(
1731 self.as_ref().handle,
1732 key.as_ptr(),
1733 md.as_ref().handle,
1734 is_auto,
1735 )
1736 };
1737 }
1738
1739 fn remove_metadata(&self, key: &str) {
1740 let key = key.to_cstr();
1741 unsafe { BNBinaryViewRemoveMetadata(self.as_ref().handle, key.as_ptr()) };
1742 }
1743
1744 fn code_refs_to_addr(&self, addr: u64) -> Array<CodeReference> {
1746 unsafe {
1747 let mut count = 0;
1748 let handle = BNGetCodeReferences(self.as_ref().handle, addr, &mut count, false, 0);
1749 Array::new(handle, count, ())
1750 }
1751 }
1752
1753 fn code_refs_into_range(&self, range: Range<u64>) -> Array<CodeReference> {
1755 unsafe {
1756 let mut count = 0;
1757 let handle = BNGetCodeReferencesInRange(
1758 self.as_ref().handle,
1759 range.start,
1760 range.end - range.start,
1761 &mut count,
1762 false,
1763 0,
1764 );
1765 Array::new(handle, count, ())
1766 }
1767 }
1768
1769 fn code_refs_from_addr(&self, addr: u64, func: Option<&Function>) -> Vec<u64> {
1771 unsafe {
1772 let mut count = 0;
1773 let code_ref =
1774 CodeReference::new(addr, func.map(|f| f.to_owned()), func.map(|f| f.arch()));
1775 let mut raw_code_ref = CodeReference::into_owned_raw(&code_ref);
1776 let addresses =
1777 BNGetCodeReferencesFrom(self.as_ref().handle, &mut raw_code_ref, &mut count);
1778 let res = std::slice::from_raw_parts(addresses, count).to_vec();
1779 BNFreeAddressList(addresses);
1780 res
1781 }
1782 }
1783
1784 fn data_refs_to_addr(&self, addr: u64) -> Array<DataReference> {
1786 unsafe {
1787 let mut count = 0;
1788 let handle = BNGetDataReferences(self.as_ref().handle, addr, &mut count, false, 0);
1789 Array::new(handle, count, ())
1790 }
1791 }
1792
1793 fn data_refs_into_range(&self, range: Range<u64>) -> Array<DataReference> {
1795 unsafe {
1796 let mut count = 0;
1797 let handle = BNGetDataReferencesInRange(
1798 self.as_ref().handle,
1799 range.start,
1800 range.end - range.start,
1801 &mut count,
1802 false,
1803 0,
1804 );
1805 Array::new(handle, count, ())
1806 }
1807 }
1808
1809 fn data_refs_from_addr(&self, addr: u64) -> Array<DataReference> {
1811 unsafe {
1812 let mut count = 0;
1813 let handle = BNGetDataReferencesFrom(self.as_ref().handle, addr, &mut count);
1814 Array::new(handle, count, ())
1815 }
1816 }
1817
1818 fn code_refs_using_type_name<T: Into<QualifiedName>>(&self, name: T) -> Array<CodeReference> {
1820 let mut raw_name = QualifiedName::into_raw(name.into());
1821 unsafe {
1822 let mut count = 0;
1823 let handle = BNGetCodeReferencesForType(
1824 self.as_ref().handle,
1825 &mut raw_name,
1826 &mut count,
1827 false,
1828 0,
1829 );
1830 QualifiedName::free_raw(raw_name);
1831 Array::new(handle, count, ())
1832 }
1833 }
1834
1835 fn data_refs_using_type_name<T: Into<QualifiedName>>(&self, name: T) -> Array<DataReference> {
1837 let mut raw_name = QualifiedName::into_raw(name.into());
1838 unsafe {
1839 let mut count = 0;
1840 let handle = BNGetDataReferencesForType(
1841 self.as_ref().handle,
1842 &mut raw_name,
1843 &mut count,
1844 false,
1845 0,
1846 );
1847 QualifiedName::free_raw(raw_name);
1848 Array::new(handle, count, ())
1849 }
1850 }
1851
1852 fn relocations_at(&self, addr: u64) -> Array<Relocation> {
1853 unsafe {
1854 let mut count = 0;
1855 let handle = BNGetRelocationsAt(self.as_ref().handle, addr, &mut count);
1856 Array::new(handle, count, ())
1857 }
1858 }
1859
1860 fn relocation_ranges(&self) -> Vec<Range<u64>> {
1861 let ranges = unsafe {
1862 let mut count = 0;
1863 let reloc_ranges_ptr = BNGetRelocationRanges(self.as_ref().handle, &mut count);
1864 let ranges = std::slice::from_raw_parts(reloc_ranges_ptr, count).to_vec();
1865 BNFreeRelocationRanges(reloc_ranges_ptr);
1866 ranges
1867 };
1868
1869 ranges
1871 .iter()
1872 .map(|range| Range {
1873 start: range.start,
1874 end: range.end,
1875 })
1876 .collect()
1877 }
1878
1879 fn component_by_guid(&self, guid: &str) -> Option<Ref<Component>> {
1880 let name = guid.to_cstr();
1881 let result = unsafe { BNGetComponentByGuid(self.as_ref().handle, name.as_ptr()) };
1882 NonNull::new(result).map(|h| unsafe { Component::ref_from_raw(h) })
1883 }
1884
1885 fn root_component(&self) -> Option<Ref<Component>> {
1886 let result = unsafe { BNGetRootComponent(self.as_ref().handle) };
1887 NonNull::new(result).map(|h| unsafe { Component::ref_from_raw(h) })
1888 }
1889
1890 fn component_by_path(&self, path: &str) -> Option<Ref<Component>> {
1891 let path = path.to_cstr();
1892 let result = unsafe { BNGetComponentByPath(self.as_ref().handle, path.as_ptr()) };
1893 NonNull::new(result).map(|h| unsafe { Component::ref_from_raw(h) })
1894 }
1895
1896 fn remove_component(&self, component: &Component) -> bool {
1897 unsafe { BNRemoveComponent(self.as_ref().handle, component.handle.as_ptr()) }
1898 }
1899
1900 fn remove_component_by_guid(&self, guid: &str) -> bool {
1901 let path = guid.to_cstr();
1902 unsafe { BNRemoveComponentByGuid(self.as_ref().handle, path.as_ptr()) }
1903 }
1904
1905 fn data_variable_parent_components(&self, data_variable: &DataVariable) -> Array<Component> {
1906 let mut count = 0;
1907 let result = unsafe {
1908 BNGetDataVariableParentComponents(
1909 self.as_ref().handle,
1910 data_variable.address,
1911 &mut count,
1912 )
1913 };
1914 unsafe { Array::new(result, count, ()) }
1915 }
1916
1917 fn external_libraries(&self) -> Array<ExternalLibrary> {
1918 let mut count = 0;
1919 let result = unsafe { BNBinaryViewGetExternalLibraries(self.as_ref().handle, &mut count) };
1920 unsafe { Array::new(result, count, ()) }
1921 }
1922
1923 fn external_library(&self, name: &str) -> Option<Ref<ExternalLibrary>> {
1924 let name_ptr = name.to_cstr();
1925 let result =
1926 unsafe { BNBinaryViewGetExternalLibrary(self.as_ref().handle, name_ptr.as_ptr()) };
1927 let result_ptr = NonNull::new(result)?;
1928 Some(unsafe { ExternalLibrary::ref_from_raw(result_ptr) })
1929 }
1930
1931 fn remove_external_library(&self, name: &str) {
1932 let name_ptr = name.to_cstr();
1933 unsafe { BNBinaryViewRemoveExternalLibrary(self.as_ref().handle, name_ptr.as_ptr()) };
1934 }
1935
1936 fn add_external_library(
1937 &self,
1938 name: &str,
1939 backing_file: Option<&ProjectFile>,
1940 auto: bool,
1941 ) -> Option<Ref<ExternalLibrary>> {
1942 let name_ptr = name.to_cstr();
1943 let result = unsafe {
1944 BNBinaryViewAddExternalLibrary(
1945 self.as_ref().handle,
1946 name_ptr.as_ptr(),
1947 backing_file
1948 .map(|b| b.handle.as_ptr())
1949 .unwrap_or(std::ptr::null_mut()),
1950 auto,
1951 )
1952 };
1953 NonNull::new(result).map(|h| unsafe { ExternalLibrary::ref_from_raw(h) })
1954 }
1955
1956 fn external_locations(&self) -> Array<ExternalLocation> {
1957 let mut count = 0;
1958 let result = unsafe { BNBinaryViewGetExternalLocations(self.as_ref().handle, &mut count) };
1959 unsafe { Array::new(result, count, ()) }
1960 }
1961
1962 fn external_location_from_symbol(&self, symbol: &Symbol) -> Option<Ref<ExternalLocation>> {
1963 let result =
1964 unsafe { BNBinaryViewGetExternalLocation(self.as_ref().handle, symbol.handle) };
1965 let result_ptr = NonNull::new(result)?;
1966 Some(unsafe { ExternalLocation::ref_from_raw(result_ptr) })
1967 }
1968
1969 fn remove_external_location(&self, location: &ExternalLocation) {
1970 self.remove_external_location_from_symbol(&location.source_symbol())
1971 }
1972
1973 fn remove_external_location_from_symbol(&self, symbol: &Symbol) {
1974 unsafe { BNBinaryViewRemoveExternalLocation(self.as_ref().handle, symbol.handle) };
1975 }
1976
1977 fn add_external_location(
1979 &self,
1980 symbol: &Symbol,
1981 library: &ExternalLibrary,
1982 target_symbol_name: &str,
1983 target_address: Option<u64>,
1984 target_is_auto: bool,
1985 ) -> Option<Ref<ExternalLocation>> {
1986 let target_symbol_name = target_symbol_name.to_cstr();
1987 let target_address_ptr = target_address
1988 .map(|a| a as *mut u64)
1989 .unwrap_or(std::ptr::null_mut());
1990 let result = unsafe {
1991 BNBinaryViewAddExternalLocation(
1992 self.as_ref().handle,
1993 symbol.handle,
1994 library.handle.as_ptr(),
1995 target_symbol_name.as_ptr(),
1996 target_address_ptr,
1997 target_is_auto,
1998 )
1999 };
2000 NonNull::new(result).map(|h| unsafe { ExternalLocation::ref_from_raw(h) })
2001 }
2002
2003 fn type_container(&self) -> TypeContainer {
2007 let type_container_ptr =
2008 NonNull::new(unsafe { BNGetAnalysisTypeContainer(self.as_ref().handle) });
2009 unsafe { TypeContainer::from_raw(type_container_ptr.unwrap()) }
2011 }
2012
2013 fn user_type_container(&self) -> TypeContainer {
2015 let type_container_ptr =
2016 NonNull::new(unsafe { BNGetAnalysisUserTypeContainer(self.as_ref().handle) });
2017 unsafe { TypeContainer::from_raw(type_container_ptr.unwrap()) }.clone()
2019 }
2020
2021 fn auto_type_container(&self) -> TypeContainer {
2025 let type_container_ptr =
2026 NonNull::new(unsafe { BNGetAnalysisAutoTypeContainer(self.as_ref().handle) });
2027 unsafe { TypeContainer::from_raw(type_container_ptr.unwrap()) }
2029 }
2030
2031 fn add_type_library(&self, library: &TypeLibrary) {
2033 unsafe { BNAddBinaryViewTypeLibrary(self.as_ref().handle, library.as_raw()) }
2034 }
2035
2036 fn type_library_by_name(&self, name: &str) -> Option<Ref<TypeLibrary>> {
2037 let name = name.to_cstr();
2038 let result = unsafe { BNGetBinaryViewTypeLibrary(self.as_ref().handle, name.as_ptr()) };
2039 NonNull::new(result).map(|h| unsafe { TypeLibrary::ref_from_raw(h) })
2040 }
2041
2042 fn record_imported_object_library<T: Into<QualifiedName>>(
2051 &self,
2052 lib: &TypeLibrary,
2053 name: T,
2054 addr: u64,
2055 platform: &Platform,
2056 ) {
2057 let mut raw_name = QualifiedName::into_raw(name.into());
2058 unsafe {
2059 BNBinaryViewRecordImportedObjectLibrary(
2060 self.as_ref().handle,
2061 platform.handle,
2062 addr,
2063 lib.as_raw(),
2064 &mut raw_name,
2065 )
2066 }
2067 QualifiedName::free_raw(raw_name);
2068 }
2069
2070 fn import_type_library<T: Into<QualifiedName>>(
2081 &self,
2082 name: T,
2083 mut lib: Option<TypeLibrary>,
2084 ) -> Option<Ref<Type>> {
2085 let mut lib_ref = lib
2086 .as_mut()
2087 .map(|l| unsafe { l.as_raw() } as *mut _)
2088 .unwrap_or(std::ptr::null_mut());
2089 let mut raw_name = QualifiedName::into_raw(name.into());
2090 let result = unsafe {
2091 BNBinaryViewImportTypeLibraryType(self.as_ref().handle, &mut lib_ref, &mut raw_name)
2092 };
2093 QualifiedName::free_raw(raw_name);
2094 (!result.is_null()).then(|| unsafe { Type::ref_from_raw(result) })
2095 }
2096
2097 fn import_type_object<T: Into<QualifiedName>>(
2107 &self,
2108 name: T,
2109 mut lib: Option<TypeLibrary>,
2110 ) -> Option<Ref<Type>> {
2111 let mut lib_ref = lib
2112 .as_mut()
2113 .map(|l| unsafe { l.as_raw() } as *mut _)
2114 .unwrap_or(std::ptr::null_mut());
2115 let mut raw_name = QualifiedName::into_raw(name.into());
2116 let result = unsafe {
2117 BNBinaryViewImportTypeLibraryObject(self.as_ref().handle, &mut lib_ref, &mut raw_name)
2118 };
2119 QualifiedName::free_raw(raw_name);
2120 (!result.is_null()).then(|| unsafe { Type::ref_from_raw(result) })
2121 }
2122
2123 fn import_type_by_guid(&self, guid: &str) -> Option<Ref<Type>> {
2125 let guid = guid.to_cstr();
2126 let result =
2127 unsafe { BNBinaryViewImportTypeLibraryTypeByGuid(self.as_ref().handle, guid.as_ptr()) };
2128 (!result.is_null()).then(|| unsafe { Type::ref_from_raw(result) })
2129 }
2130
2131 fn export_type_to_library<T: Into<QualifiedName>>(
2136 &self,
2137 lib: &TypeLibrary,
2138 name: T,
2139 type_obj: &Type,
2140 ) {
2141 let mut raw_name = QualifiedName::into_raw(name.into());
2142 unsafe {
2143 BNBinaryViewExportTypeToTypeLibrary(
2144 self.as_ref().handle,
2145 lib.as_raw(),
2146 &mut raw_name,
2147 type_obj.handle,
2148 )
2149 }
2150 QualifiedName::free_raw(raw_name);
2151 }
2152
2153 fn export_object_to_library<T: Into<QualifiedName>>(
2158 &self,
2159 lib: &TypeLibrary,
2160 name: T,
2161 type_obj: &Type,
2162 ) {
2163 let mut raw_name = QualifiedName::into_raw(name.into());
2164 unsafe {
2165 BNBinaryViewExportObjectToTypeLibrary(
2166 self.as_ref().handle,
2167 lib.as_raw(),
2168 &mut raw_name,
2169 type_obj.handle,
2170 )
2171 }
2172 QualifiedName::free_raw(raw_name);
2173 }
2174
2175 fn lookup_imported_object_library(
2181 &self,
2182 addr: u64,
2183 platform: &Platform,
2184 ) -> Option<(Ref<TypeLibrary>, QualifiedName)> {
2185 let mut result_lib = std::ptr::null_mut();
2186 let mut result_name = BNQualifiedName::default();
2187 let success = unsafe {
2188 BNBinaryViewLookupImportedObjectLibrary(
2189 self.as_ref().handle,
2190 platform.handle,
2191 addr,
2192 &mut result_lib,
2193 &mut result_name,
2194 )
2195 };
2196 if !success {
2197 return None;
2198 }
2199 let lib = unsafe { TypeLibrary::ref_from_raw(NonNull::new(result_lib)?) };
2200 let name = QualifiedName::from_owned_raw(result_name);
2201 Some((lib, name))
2202 }
2203
2204 fn lookup_imported_type_library<T: Into<QualifiedName>>(
2208 &self,
2209 name: T,
2210 ) -> Option<(Ref<TypeLibrary>, QualifiedName)> {
2211 let raw_name = QualifiedName::into_raw(name.into());
2212 let mut result_lib = std::ptr::null_mut();
2213 let mut result_name = BNQualifiedName::default();
2214 let success = unsafe {
2215 BNBinaryViewLookupImportedTypeLibrary(
2216 self.as_ref().handle,
2217 &raw_name,
2218 &mut result_lib,
2219 &mut result_name,
2220 )
2221 };
2222 QualifiedName::free_raw(raw_name);
2223 if !success {
2224 return None;
2225 }
2226 let lib = unsafe { TypeLibrary::ref_from_raw(NonNull::new(result_lib)?) };
2227 let name = QualifiedName::from_owned_raw(result_name);
2228 Some((lib, name))
2229 }
2230
2231 fn strings(&self) -> Array<StringReference> {
2237 unsafe {
2238 let mut count = 0;
2239 let strings = BNGetStrings(self.as_ref().handle, &mut count);
2240 Array::new(strings, count, ())
2241 }
2242 }
2243
2244 fn string_at(&self, addr: u64) -> Option<BNStringReference> {
2245 let mut str_ref = BNStringReference::default();
2246 let success = unsafe { BNGetStringAtAddress(self.as_ref().handle, addr, &mut str_ref) };
2247
2248 if success {
2249 Some(str_ref)
2250 } else {
2251 None
2252 }
2253 }
2254
2255 fn strings_in_range(&self, range: Range<u64>) -> Array<StringReference> {
2261 unsafe {
2262 let mut count = 0;
2263 let strings = BNGetStringsInRange(
2264 self.as_ref().handle,
2265 range.start,
2266 range.end - range.start,
2267 &mut count,
2268 );
2269 Array::new(strings, count, ())
2270 }
2271 }
2272
2273 }
2291
2292impl<T: BinaryViewBase> BinaryViewExt for T {}
2293
2294#[derive(PartialEq, Eq, Hash)]
2301pub struct BinaryView {
2302 pub handle: *mut BNBinaryView,
2303}
2304
2305impl BinaryView {
2306 pub unsafe fn from_raw(handle: *mut BNBinaryView) -> Self {
2307 debug_assert!(!handle.is_null());
2308 Self { handle }
2309 }
2310
2311 pub(crate) unsafe fn ref_from_raw(handle: *mut BNBinaryView) -> Ref<Self> {
2312 debug_assert!(!handle.is_null());
2313 Ref::new(Self { handle })
2314 }
2315
2316 pub fn from_path(meta: &mut FileMetadata, file_path: impl AsRef<Path>) -> Result<Ref<Self>> {
2317 let file = file_path.as_ref().to_cstr();
2318 let handle =
2319 unsafe { BNCreateBinaryDataViewFromFilename(meta.handle, file.as_ptr() as *mut _) };
2320
2321 if handle.is_null() {
2322 return Err(());
2323 }
2324
2325 unsafe { Ok(Ref::new(Self { handle })) }
2326 }
2327
2328 pub fn from_accessor<A: Accessor>(
2329 meta: &FileMetadata,
2330 file: &mut FileAccessor<A>,
2331 ) -> Result<Ref<Self>> {
2332 let handle = unsafe { BNCreateBinaryDataViewFromFile(meta.handle, &mut file.raw) };
2333
2334 if handle.is_null() {
2335 return Err(());
2336 }
2337
2338 unsafe { Ok(Ref::new(Self { handle })) }
2339 }
2340
2341 pub fn from_data(meta: &FileMetadata, data: &[u8]) -> Result<Ref<Self>> {
2342 let handle = unsafe {
2343 BNCreateBinaryDataViewFromData(meta.handle, data.as_ptr() as *mut _, data.len())
2344 };
2345
2346 if handle.is_null() {
2347 return Err(());
2348 }
2349
2350 unsafe { Ok(Ref::new(Self { handle })) }
2351 }
2352
2353 pub fn save_to_path(&self, file_path: impl AsRef<Path>) -> bool {
2362 let file = file_path.as_ref().to_cstr();
2363 unsafe { BNSaveToFilename(self.handle, file.as_ptr() as *mut _) }
2364 }
2365
2366 pub fn save_to_accessor<A: Accessor>(&self, file: &mut FileAccessor<A>) -> bool {
2375 unsafe { BNSaveToFile(self.handle, &mut file.raw) }
2376 }
2377}
2378
2379impl BinaryViewBase for BinaryView {
2380 fn read(&self, buf: &mut [u8], offset: u64) -> usize {
2381 unsafe { BNReadViewData(self.handle, buf.as_mut_ptr() as *mut _, offset, buf.len()) }
2382 }
2383
2384 fn write(&self, offset: u64, data: &[u8]) -> usize {
2385 unsafe { BNWriteViewData(self.handle, offset, data.as_ptr() as *const _, data.len()) }
2386 }
2387
2388 fn insert(&self, offset: u64, data: &[u8]) -> usize {
2389 unsafe { BNInsertViewData(self.handle, offset, data.as_ptr() as *const _, data.len()) }
2390 }
2391
2392 fn remove(&self, offset: u64, len: usize) -> usize {
2393 unsafe { BNRemoveViewData(self.handle, offset, len as u64) }
2394 }
2395
2396 fn offset_valid(&self, offset: u64) -> bool {
2400 unsafe { BNIsValidOffset(self.handle, offset) }
2401 }
2402
2403 fn offset_readable(&self, offset: u64) -> bool {
2407 unsafe { BNIsOffsetReadable(self.handle, offset) }
2408 }
2409
2410 fn offset_writable(&self, offset: u64) -> bool {
2414 unsafe { BNIsOffsetWritable(self.handle, offset) }
2415 }
2416
2417 fn offset_executable(&self, offset: u64) -> bool {
2421 unsafe { BNIsOffsetExecutable(self.handle, offset) }
2422 }
2423
2424 fn offset_backed_by_file(&self, offset: u64) -> bool {
2428 unsafe { BNIsOffsetBackedByFile(self.handle, offset) }
2429 }
2430
2431 fn next_valid_offset_after(&self, offset: u64) -> u64 {
2436 unsafe { BNGetNextValidOffset(self.handle, offset) }
2437 }
2438
2439 fn modification_status(&self, offset: u64) -> ModificationStatus {
2440 unsafe { BNGetModification(self.handle, offset) }
2441 }
2442
2443 fn start(&self) -> u64 {
2447 unsafe { BNGetStartOffset(self.handle) }
2448 }
2449
2450 fn len(&self) -> u64 {
2454 unsafe { BNGetViewLength(self.handle) }
2455 }
2456
2457 fn executable(&self) -> bool {
2458 unsafe { BNIsExecutableView(self.handle) }
2459 }
2460
2461 fn relocatable(&self) -> bool {
2462 unsafe { BNIsRelocatable(self.handle) }
2463 }
2464
2465 fn entry_point(&self) -> u64 {
2466 unsafe { BNGetEntryPoint(self.handle) }
2467 }
2468
2469 fn default_endianness(&self) -> Endianness {
2470 unsafe { BNGetDefaultEndianness(self.handle) }
2471 }
2472
2473 fn address_size(&self) -> usize {
2474 unsafe { BNGetViewAddressSize(self.handle) }
2475 }
2476}
2477
2478unsafe impl RefCountable for BinaryView {
2479 unsafe fn inc_ref(handle: &Self) -> Ref<Self> {
2480 Ref::new(Self {
2481 handle: BNNewViewReference(handle.handle),
2482 })
2483 }
2484
2485 unsafe fn dec_ref(handle: &Self) {
2486 BNFreeBinaryView(handle.handle);
2487 }
2488}
2489
2490impl AsRef<BinaryView> for BinaryView {
2491 fn as_ref(&self) -> &Self {
2492 self
2493 }
2494}
2495
2496impl ToOwned for BinaryView {
2497 type Owned = Ref<Self>;
2498
2499 fn to_owned(&self) -> Self::Owned {
2500 unsafe { RefCountable::inc_ref(self) }
2501 }
2502}
2503
2504unsafe impl Send for BinaryView {}
2505unsafe impl Sync for BinaryView {}
2506
2507impl std::fmt::Debug for BinaryView {
2508 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
2509 f.debug_struct("BinaryView")
2510 .field("view_type", &self.view_type())
2511 .field("file", &self.file())
2512 .field("original_image_base", &self.original_image_base())
2513 .field("start", &self.start())
2514 .field("end", &self.end())
2515 .field("len", &self.len())
2516 .field("default_platform", &self.default_platform())
2517 .field("default_arch", &self.default_arch())
2518 .field("default_endianness", &self.default_endianness())
2519 .field("entry_point", &self.entry_point())
2520 .field(
2521 "entry_point_functions",
2522 &self.entry_point_functions().to_vec(),
2523 )
2524 .field("address_size", &self.address_size())
2525 .field("sections", &self.sections().to_vec())
2526 .field("segments", &self.segments().to_vec())
2527 .finish()
2528 }
2529}
2530
2531pub trait BinaryViewEventHandler: 'static + Sync {
2532 fn on_event(&self, binary_view: &BinaryView);
2533}
2534
2535pub fn register_binary_view_event<Handler>(event_type: BinaryViewEventType, handler: Handler)
2565where
2566 Handler: BinaryViewEventHandler,
2567{
2568 unsafe extern "C" fn on_event<Handler: BinaryViewEventHandler>(
2569 ctx: *mut ::std::os::raw::c_void,
2570 view: *mut BNBinaryView,
2571 ) {
2572 ffi_wrap!("EventHandler::on_event", {
2573 let context = unsafe { &*(ctx as *const Handler) };
2574 context.on_event(&BinaryView::ref_from_raw(BNNewViewReference(view)));
2575 })
2576 }
2577
2578 let boxed = Box::new(handler);
2579 let raw = Box::into_raw(boxed);
2580
2581 unsafe {
2582 BNRegisterBinaryViewEvent(
2583 event_type,
2584 Some(on_event::<Handler>),
2585 raw as *mut ::std::os::raw::c_void,
2586 );
2587 }
2588}
2589
2590#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
2591pub struct StringReference {
2592 pub ty: StringType,
2593 pub start: u64,
2594 pub length: usize,
2595}
2596
2597impl From<BNStringReference> for StringReference {
2598 fn from(raw: BNStringReference) -> Self {
2599 Self {
2600 ty: raw.type_,
2601 start: raw.start,
2602 length: raw.length,
2603 }
2604 }
2605}
2606
2607impl From<StringReference> for BNStringReference {
2608 fn from(raw: StringReference) -> Self {
2609 Self {
2610 type_: raw.ty,
2611 start: raw.start,
2612 length: raw.length,
2613 }
2614 }
2615}
2616
2617impl CoreArrayProvider for StringReference {
2618 type Raw = BNStringReference;
2619 type Context = ();
2620 type Wrapped<'a> = Self;
2621}
2622
2623unsafe impl CoreArrayProviderInner for StringReference {
2624 unsafe fn free(raw: *mut Self::Raw, _count: usize, _context: &Self::Context) {
2625 BNFreeStringReferenceList(raw)
2626 }
2627
2628 unsafe fn wrap_raw<'a>(raw: &'a Self::Raw, _context: &'a Self::Context) -> Self::Wrapped<'a> {
2629 Self::from(*raw)
2630 }
2631}
2632
2633#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
2634pub struct AddressRange {
2635 pub start: u64,
2636 pub end: u64,
2637}
2638
2639impl From<BNAddressRange> for AddressRange {
2640 fn from(raw: BNAddressRange) -> Self {
2641 Self {
2642 start: raw.start,
2643 end: raw.end,
2644 }
2645 }
2646}
2647
2648impl From<AddressRange> for BNAddressRange {
2649 fn from(raw: AddressRange) -> Self {
2650 Self {
2651 start: raw.start,
2652 end: raw.end,
2653 }
2654 }
2655}
2656
2657impl CoreArrayProvider for AddressRange {
2658 type Raw = BNAddressRange;
2659 type Context = ();
2660 type Wrapped<'a> = Self;
2661}
2662
2663unsafe impl CoreArrayProviderInner for AddressRange {
2664 unsafe fn free(raw: *mut Self::Raw, _count: usize, _context: &Self::Context) {
2665 BNFreeAddressRanges(raw);
2666 }
2667
2668 unsafe fn wrap_raw<'a>(raw: &'a Self::Raw, _context: &'a Self::Context) -> Self::Wrapped<'a> {
2669 Self::from(*raw)
2670 }
2671}