1use binaryninjacore_sys::*;
18
19#[allow(unused)]
21pub use crate::workflow::AnalysisContext;
22
23use crate::architecture::{Architecture, CoreArchitecture};
24use crate::base_detection::BaseAddressDetection;
25use crate::basic_block::BasicBlock;
26use crate::binary_view::search::SearchQuery;
27use crate::component::Component;
28use crate::confidence::Conf;
29use crate::data_buffer::DataBuffer;
30use crate::debuginfo::DebugInfo;
31use crate::disassembly::DisassemblySettings;
32use crate::external_library::{ExternalLibrary, ExternalLocation};
33use crate::file_accessor::{Accessor, FileAccessor};
34use crate::file_metadata::FileMetadata;
35use crate::flowgraph::FlowGraph;
36use crate::function::{Function, FunctionViewType, Location, NativeBlock};
37use crate::linear_view::{LinearDisassemblyLine, LinearViewCursor};
38use crate::metadata::Metadata;
39use crate::platform::Platform;
40use crate::progress::{NoProgressCallback, ProgressCallback};
41use crate::project::file::ProjectFile;
42use crate::rc::*;
43use crate::references::{CodeReference, DataReference};
44use crate::relocation::Relocation;
45use crate::section::{Section, SectionBuilder};
46use crate::segment::{Segment, SegmentBuilder};
47use crate::settings::Settings;
48use crate::string::*;
49use crate::symbol::{Symbol, SymbolType};
50use crate::tags::{Tag, TagReference, TagType};
51use crate::types::{
52 NamedTypeReference, QualifiedName, QualifiedNameAndType, QualifiedNameTypeAndId, Type,
53 TypeArchive, TypeArchiveId, TypeContainer, TypeLibrary,
54};
55use crate::variable::DataVariable;
56use crate::workflow::Workflow;
57use crate::{Endianness, BN_FULL_CONFIDENCE};
58use std::collections::{BTreeMap, HashMap};
59use std::ffi::{c_char, c_void, CString};
60use std::fmt::{Display, Formatter};
61use std::ops::Range;
62use std::path::{Path, PathBuf};
63use std::ptr::NonNull;
64use std::{result, slice};
65
66pub mod memory_map;
67pub mod reader;
68pub mod search;
69pub mod writer;
70
71pub use memory_map::{MemoryMap, MemoryRegionInfo, ResolvedRange};
72pub use reader::BinaryReader;
73pub use writer::BinaryWriter;
74
75pub type Result<R> = result::Result<R, ()>;
76pub type BinaryViewEventType = BNBinaryViewEventType;
77pub type AnalysisState = BNAnalysisState;
78pub type ModificationStatus = BNModificationStatus;
79pub type StringType = BNStringType;
80pub type FindFlag = BNFindFlag;
81
82#[allow(clippy::len_without_is_empty)]
83pub trait BinaryViewBase: AsRef<BinaryView> {
84 fn read(&self, _buf: &mut [u8], _offset: u64) -> usize {
85 0
86 }
87
88 fn write(&self, _offset: u64, _data: &[u8]) -> usize {
89 0
90 }
91
92 fn insert(&self, _offset: u64, _data: &[u8]) -> usize {
93 0
94 }
95
96 fn remove(&self, _offset: u64, _len: usize) -> usize {
97 0
98 }
99
100 fn offset_valid(&self, offset: u64) -> bool {
102 let mut buf = [0u8; 1];
103
104 self.as_ref().read(&mut buf[..], offset) == buf.len()
107 }
108
109 fn offset_readable(&self, offset: u64) -> bool {
111 self.offset_valid(offset)
112 }
113
114 fn offset_writable(&self, offset: u64) -> bool {
116 self.offset_valid(offset)
117 }
118
119 fn offset_executable(&self, offset: u64) -> bool {
121 self.offset_valid(offset)
122 }
123
124 fn offset_backed_by_file(&self, offset: u64) -> bool {
126 self.offset_valid(offset)
127 }
128
129 fn next_valid_offset_after(&self, offset: u64) -> u64 {
132 let start = self.as_ref().start();
133
134 if offset < start {
135 start
136 } else {
137 offset
138 }
139 }
140
141 fn modification_status(&self, _offset: u64) -> ModificationStatus {
143 ModificationStatus::Original
144 }
145
146 fn start(&self) -> u64 {
148 0
149 }
150
151 fn len(&self) -> u64 {
153 0
154 }
155
156 fn executable(&self) -> bool {
157 true
158 }
159
160 fn relocatable(&self) -> bool {
161 true
162 }
163
164 fn entry_point(&self) -> u64;
165 fn default_endianness(&self) -> Endianness;
166 fn address_size(&self) -> usize;
167
168 fn save(&self) -> bool {
169 self.as_ref()
170 .parent_view()
171 .map(|view| view.save())
172 .unwrap_or(false)
173 }
174}
175
176#[derive(Debug, Clone)]
177pub struct ActiveAnalysisInfo {
178 pub func: Ref<Function>,
179 pub analysis_time: u64,
180 pub update_count: usize,
181 pub submit_count: usize,
182}
183
184#[derive(Debug, Clone)]
185pub struct AnalysisInfo {
186 pub state: AnalysisState,
187 pub analysis_time: u64,
188 pub active_info: Vec<ActiveAnalysisInfo>,
189}
190
191#[derive(Debug, Clone, Ord, PartialOrd, Eq, PartialEq)]
192pub enum AnalysisProgress {
193 Initial,
194 Hold,
195 Idle,
196 Discovery,
197 Disassembling(usize, usize),
198 Analyzing(usize, usize),
199 ExtendedAnalysis,
200}
201
202impl Display for AnalysisProgress {
203 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
204 match self {
205 AnalysisProgress::Initial => {
206 write!(f, "Initial")
207 }
208 AnalysisProgress::Hold => {
209 write!(f, "Hold")
210 }
211 AnalysisProgress::Idle => {
212 write!(f, "Idle")
213 }
214 AnalysisProgress::Discovery => {
215 write!(f, "Discovery")
216 }
217 AnalysisProgress::Disassembling(count, total) => {
218 write!(f, "Disassembling ({count}/{total})")
219 }
220 AnalysisProgress::Analyzing(count, total) => {
221 write!(f, "Analyzing ({count}/{total})")
222 }
223 AnalysisProgress::ExtendedAnalysis => {
224 write!(f, "Extended Analysis")
225 }
226 }
227 }
228}
229
230impl From<BNAnalysisProgress> for AnalysisProgress {
231 fn from(value: BNAnalysisProgress) -> Self {
232 match value.state {
233 BNAnalysisState::InitialState => Self::Initial,
234 BNAnalysisState::HoldState => Self::Hold,
235 BNAnalysisState::IdleState => Self::Idle,
236 BNAnalysisState::DiscoveryState => Self::Discovery,
237 BNAnalysisState::DisassembleState => Self::Disassembling(value.count, value.total),
238 BNAnalysisState::AnalyzeState => Self::Analyzing(value.count, value.total),
239 BNAnalysisState::ExtendedAnalyzeState => Self::ExtendedAnalysis,
240 }
241 }
242}
243
244pub trait BinaryViewExt: BinaryViewBase {
245 fn file(&self) -> Ref<FileMetadata> {
246 unsafe {
247 let raw = BNGetFileForView(self.as_ref().handle);
248 FileMetadata::ref_from_raw(raw)
249 }
250 }
251
252 fn parent_view(&self) -> Option<Ref<BinaryView>> {
253 let raw_view_ptr = unsafe { BNGetParentView(self.as_ref().handle) };
254 match raw_view_ptr.is_null() {
255 false => Some(unsafe { BinaryView::ref_from_raw(raw_view_ptr) }),
256 true => None,
257 }
258 }
259
260 fn raw_view(&self) -> Option<Ref<BinaryView>> {
261 self.file().view_of_type("Raw")
262 }
263
264 fn view_type(&self) -> String {
265 let ptr: *mut c_char = unsafe { BNGetViewType(self.as_ref().handle) };
266 unsafe { BnString::into_string(ptr) }
267 }
268
269 fn read_vec(&self, offset: u64, len: usize) -> Vec<u8> {
271 let mut ret = vec![0; len];
272 let size = self.read(&mut ret, offset);
273 ret.truncate(size);
274 ret
275 }
276
277 fn read_into_vec(&self, dest: &mut Vec<u8>, offset: u64, len: usize) -> usize {
279 let starting_len = dest.len();
280 dest.resize(starting_len + len, 0);
281 let read_size = self.read(&mut dest[starting_len..], offset);
282 dest.truncate(starting_len + read_size);
283 read_size
284 }
285
286 fn read_c_string_at(&self, offset: u64, len: usize) -> Option<CString> {
288 let mut buf = vec![0; len];
289 let size = self.read(&mut buf, offset);
290 let string = CString::new(buf[..size].to_vec()).ok()?;
291 Some(string)
292 }
293
294 fn read_utf8_string_at(&self, offset: u64, len: usize) -> Option<String> {
296 let mut buf = vec![0; len];
297 let size = self.read(&mut buf, offset);
298 let string = String::from_utf8(buf[..size].to_vec()).ok()?;
299 Some(string)
300 }
301
302 fn search<C: FnMut(u64, &DataBuffer) -> bool>(&self, query: &SearchQuery, on_match: C) -> bool {
306 self.search_with_progress(query, on_match, NoProgressCallback)
307 }
308
309 fn search_with_progress<P: ProgressCallback, C: FnMut(u64, &DataBuffer) -> bool>(
313 &self,
314 query: &SearchQuery,
315 mut on_match: C,
316 mut progress: P,
317 ) -> bool {
318 unsafe extern "C" fn cb_on_match<C: FnMut(u64, &DataBuffer) -> bool>(
319 ctx: *mut c_void,
320 offset: u64,
321 data: *mut BNDataBuffer,
322 ) -> bool {
323 let f = ctx as *mut C;
324 let buffer = DataBuffer::from_raw(data);
325 (*f)(offset, &buffer)
326 }
327
328 let query = query.to_json().to_cstr();
329 unsafe {
330 BNSearch(
331 self.as_ref().handle,
332 query.as_ptr(),
333 &mut progress as *mut P as *mut c_void,
334 Some(P::cb_progress_callback),
335 &mut on_match as *const C as *mut c_void,
336 Some(cb_on_match::<C>),
337 )
338 }
339 }
340
341 fn find_next_data(&self, start: u64, end: u64, data: &DataBuffer) -> Option<u64> {
342 self.find_next_data_with_opts(
343 start,
344 end,
345 data,
346 FindFlag::FindCaseInsensitive,
347 NoProgressCallback,
348 )
349 }
350
351 fn find_next_data_with_opts<P: ProgressCallback>(
355 &self,
356 start: u64,
357 end: u64,
358 data: &DataBuffer,
359 flag: FindFlag,
360 mut progress: P,
361 ) -> Option<u64> {
362 let mut result: u64 = 0;
363 let found = unsafe {
364 BNFindNextDataWithProgress(
365 self.as_ref().handle,
366 start,
367 end,
368 data.as_raw(),
369 &mut result,
370 flag,
371 &mut progress as *mut P as *mut c_void,
372 Some(P::cb_progress_callback),
373 )
374 };
375
376 if found {
377 Some(result)
378 } else {
379 None
380 }
381 }
382
383 fn find_next_constant(
384 &self,
385 start: u64,
386 end: u64,
387 constant: u64,
388 view_type: FunctionViewType,
389 ) -> Option<u64> {
390 let settings = DisassemblySettings::new();
392 self.find_next_constant_with_opts(
393 start,
394 end,
395 constant,
396 &settings,
397 view_type,
398 NoProgressCallback,
399 )
400 }
401
402 fn find_next_constant_with_opts<P: ProgressCallback>(
406 &self,
407 start: u64,
408 end: u64,
409 constant: u64,
410 disasm_settings: &DisassemblySettings,
411 view_type: FunctionViewType,
412 mut progress: P,
413 ) -> Option<u64> {
414 let mut result: u64 = 0;
415 let raw_view_type = FunctionViewType::into_raw(view_type);
416 let found = unsafe {
417 BNFindNextConstantWithProgress(
418 self.as_ref().handle,
419 start,
420 end,
421 constant,
422 &mut result,
423 disasm_settings.handle,
424 raw_view_type,
425 &mut progress as *mut P as *mut c_void,
426 Some(P::cb_progress_callback),
427 )
428 };
429 FunctionViewType::free_raw(raw_view_type);
430
431 if found {
432 Some(result)
433 } else {
434 None
435 }
436 }
437
438 fn find_next_text(
439 &self,
440 start: u64,
441 end: u64,
442 text: &str,
443 view_type: FunctionViewType,
444 ) -> Option<u64> {
445 let settings = DisassemblySettings::new();
447 self.find_next_text_with_opts(
448 start,
449 end,
450 text,
451 &settings,
452 FindFlag::FindCaseInsensitive,
453 view_type,
454 NoProgressCallback,
455 )
456 }
457
458 fn find_next_text_with_opts<P: ProgressCallback>(
462 &self,
463 start: u64,
464 end: u64,
465 text: &str,
466 disasm_settings: &DisassemblySettings,
467 flag: FindFlag,
468 view_type: FunctionViewType,
469 mut progress: P,
470 ) -> Option<u64> {
471 let text = text.to_cstr();
472 let raw_view_type = FunctionViewType::into_raw(view_type);
473 let mut result: u64 = 0;
474 let found = unsafe {
475 BNFindNextTextWithProgress(
476 self.as_ref().handle,
477 start,
478 end,
479 text.as_ptr(),
480 &mut result,
481 disasm_settings.handle,
482 flag,
483 raw_view_type,
484 &mut progress as *mut P as *mut c_void,
485 Some(P::cb_progress_callback),
486 )
487 };
488 FunctionViewType::free_raw(raw_view_type);
489
490 if found {
491 Some(result)
492 } else {
493 None
494 }
495 }
496
497 fn notify_data_written(&self, offset: u64, len: usize) {
498 unsafe {
499 BNNotifyDataWritten(self.as_ref().handle, offset, len);
500 }
501 }
502
503 fn notify_data_inserted(&self, offset: u64, len: usize) {
504 unsafe {
505 BNNotifyDataInserted(self.as_ref().handle, offset, len);
506 }
507 }
508
509 fn notify_data_removed(&self, offset: u64, len: usize) {
510 unsafe {
511 BNNotifyDataRemoved(self.as_ref().handle, offset, len as u64);
512 }
513 }
514
515 fn offset_has_code_semantics(&self, offset: u64) -> bool {
518 unsafe { BNIsOffsetCodeSemantics(self.as_ref().handle, offset) }
519 }
520
521 fn offset_has_extern_semantics(&self, offset: u64) -> bool {
523 unsafe { BNIsOffsetExternSemantics(self.as_ref().handle, offset) }
524 }
525
526 fn offset_has_writable_semantics(&self, offset: u64) -> bool {
529 unsafe { BNIsOffsetWritableSemantics(self.as_ref().handle, offset) }
530 }
531
532 fn offset_has_read_only_semantics(&self, offset: u64) -> bool {
535 unsafe { BNIsOffsetReadOnlySemantics(self.as_ref().handle, offset) }
536 }
537
538 fn image_base(&self) -> u64 {
539 unsafe { BNGetImageBase(self.as_ref().handle) }
540 }
541
542 fn original_image_base(&self) -> u64 {
543 unsafe { BNGetOriginalImageBase(self.as_ref().handle) }
544 }
545
546 fn set_original_image_base(&self, image_base: u64) {
547 unsafe { BNSetOriginalImageBase(self.as_ref().handle, image_base) }
548 }
549
550 fn end(&self) -> u64 {
552 unsafe { BNGetEndOffset(self.as_ref().handle) }
553 }
554
555 fn add_analysis_option(&self, name: &str) {
556 let name = name.to_cstr();
557 unsafe { BNAddAnalysisOption(self.as_ref().handle, name.as_ptr()) }
558 }
559
560 fn has_initial_analysis(&self) -> bool {
561 unsafe { BNHasInitialAnalysis(self.as_ref().handle) }
562 }
563
564 fn set_analysis_hold(&self, enable: bool) {
565 unsafe { BNSetAnalysisHold(self.as_ref().handle, enable) }
566 }
567
568 fn update_analysis(&self) {
577 unsafe {
578 BNUpdateAnalysis(self.as_ref().handle);
579 }
580 }
581
582 fn update_analysis_and_wait(&self) {
591 unsafe {
592 BNUpdateAnalysisAndWait(self.as_ref().handle);
593 }
594 }
595
596 fn reanalyze(&self) {
603 unsafe {
604 BNReanalyzeAllFunctions(self.as_ref().handle);
605 }
606 }
607
608 fn abort_analysis(&self) {
609 unsafe { BNAbortAnalysis(self.as_ref().handle) }
610 }
611
612 fn analysis_is_aborted(&self) -> bool {
613 unsafe { BNAnalysisIsAborted(self.as_ref().handle) }
614 }
615
616 fn workflow(&self) -> Ref<Workflow> {
617 unsafe {
618 let raw_ptr = BNGetWorkflowForBinaryView(self.as_ref().handle);
619 let nonnull = NonNull::new(raw_ptr).expect("All views must have a workflow");
620 Workflow::ref_from_raw(nonnull)
621 }
622 }
623
624 fn analysis_info(&self) -> AnalysisInfo {
625 let info_ptr = unsafe { BNGetAnalysisInfo(self.as_ref().handle) };
626 assert!(!info_ptr.is_null());
627 let info = unsafe { *info_ptr };
628 let active_infos = unsafe { slice::from_raw_parts(info.activeInfo, info.count) };
629
630 let mut active_info_list = vec![];
631 for active_info in active_infos {
632 let func = unsafe { Function::from_raw(active_info.func).to_owned() };
633 active_info_list.push(ActiveAnalysisInfo {
634 func,
635 analysis_time: active_info.analysisTime,
636 update_count: active_info.updateCount,
637 submit_count: active_info.submitCount,
638 });
639 }
640
641 let result = AnalysisInfo {
642 state: info.state,
643 analysis_time: info.analysisTime,
644 active_info: active_info_list,
645 };
646
647 unsafe { BNFreeAnalysisInfo(info_ptr) };
648 result
649 }
650
651 fn analysis_progress(&self) -> AnalysisProgress {
652 let progress_raw = unsafe { BNGetAnalysisProgress(self.as_ref().handle) };
653 AnalysisProgress::from(progress_raw)
654 }
655
656 fn default_arch(&self) -> Option<CoreArchitecture> {
657 unsafe {
658 let raw = BNGetDefaultArchitecture(self.as_ref().handle);
659
660 if raw.is_null() {
661 return None;
662 }
663
664 Some(CoreArchitecture::from_raw(raw))
665 }
666 }
667
668 fn set_default_arch<A: Architecture>(&self, arch: &A) {
669 unsafe {
670 BNSetDefaultArchitecture(self.as_ref().handle, arch.as_ref().handle);
671 }
672 }
673
674 fn default_platform(&self) -> Option<Ref<Platform>> {
675 unsafe {
676 let raw = BNGetDefaultPlatform(self.as_ref().handle);
677
678 if raw.is_null() {
679 return None;
680 }
681
682 Some(Platform::ref_from_raw(raw))
683 }
684 }
685
686 fn set_default_platform(&self, plat: &Platform) {
687 unsafe {
688 BNSetDefaultPlatform(self.as_ref().handle, plat.handle);
689 }
690 }
691
692 fn base_address_detection(&self) -> Option<BaseAddressDetection> {
693 unsafe {
694 let handle = BNCreateBaseAddressDetection(self.as_ref().handle);
695 NonNull::new(handle).map(|base| BaseAddressDetection::from_raw(base))
696 }
697 }
698
699 fn instruction_len<A: Architecture>(&self, arch: &A, addr: u64) -> Option<usize> {
700 unsafe {
701 let size = BNGetInstructionLength(self.as_ref().handle, arch.as_ref().handle, addr);
702
703 if size > 0 {
704 Some(size)
705 } else {
706 None
707 }
708 }
709 }
710
711 fn symbol_by_address(&self, addr: u64) -> Option<Ref<Symbol>> {
712 unsafe {
713 let raw_sym_ptr =
714 BNGetSymbolByAddress(self.as_ref().handle, addr, std::ptr::null_mut());
715 match raw_sym_ptr.is_null() {
716 false => Some(Symbol::ref_from_raw(raw_sym_ptr)),
717 true => None,
718 }
719 }
720 }
721
722 fn symbol_by_raw_name(&self, raw_name: impl IntoCStr) -> Option<Ref<Symbol>> {
723 let raw_name = raw_name.to_cstr();
724
725 unsafe {
726 let raw_sym_ptr = BNGetSymbolByRawName(
727 self.as_ref().handle,
728 raw_name.as_ptr(),
729 std::ptr::null_mut(),
730 );
731 match raw_sym_ptr.is_null() {
732 false => Some(Symbol::ref_from_raw(raw_sym_ptr)),
733 true => None,
734 }
735 }
736 }
737
738 fn symbols(&self) -> Array<Symbol> {
739 unsafe {
740 let mut count = 0;
741 let handles = BNGetSymbols(self.as_ref().handle, &mut count, std::ptr::null_mut());
742
743 Array::new(handles, count, ())
744 }
745 }
746
747 fn symbols_by_name(&self, name: impl IntoCStr) -> Array<Symbol> {
748 let raw_name = name.to_cstr();
749
750 unsafe {
751 let mut count = 0;
752 let handles = BNGetSymbolsByName(
753 self.as_ref().handle,
754 raw_name.as_ptr(),
755 &mut count,
756 std::ptr::null_mut(),
757 );
758
759 Array::new(handles, count, ())
760 }
761 }
762
763 fn symbols_in_range(&self, range: Range<u64>) -> Array<Symbol> {
764 unsafe {
765 let mut count = 0;
766 let len = range.end.wrapping_sub(range.start);
767 let handles = BNGetSymbolsInRange(
768 self.as_ref().handle,
769 range.start,
770 len,
771 &mut count,
772 std::ptr::null_mut(),
773 );
774
775 Array::new(handles, count, ())
776 }
777 }
778
779 fn symbols_of_type(&self, ty: SymbolType) -> Array<Symbol> {
780 unsafe {
781 let mut count = 0;
782 let handles = BNGetSymbolsOfType(
783 self.as_ref().handle,
784 ty.into(),
785 &mut count,
786 std::ptr::null_mut(),
787 );
788
789 Array::new(handles, count, ())
790 }
791 }
792
793 fn symbols_of_type_in_range(&self, ty: SymbolType, range: Range<u64>) -> Array<Symbol> {
794 unsafe {
795 let mut count = 0;
796 let len = range.end.wrapping_sub(range.start);
797 let handles = BNGetSymbolsOfTypeInRange(
798 self.as_ref().handle,
799 ty.into(),
800 range.start,
801 len,
802 &mut count,
803 std::ptr::null_mut(),
804 );
805
806 Array::new(handles, count, ())
807 }
808 }
809
810 fn define_auto_symbol(&self, sym: &Symbol) {
811 unsafe {
812 BNDefineAutoSymbol(self.as_ref().handle, sym.handle);
813 }
814 }
815
816 fn define_auto_symbol_with_type<'a, T: Into<Option<&'a Type>>>(
817 &self,
818 sym: &Symbol,
819 plat: &Platform,
820 ty: T,
821 ) -> Result<Ref<Symbol>> {
822 let mut type_with_conf = BNTypeWithConfidence {
823 type_: if let Some(t) = ty.into() {
824 t.handle
825 } else {
826 std::ptr::null_mut()
827 },
828 confidence: BN_FULL_CONFIDENCE,
829 };
830
831 unsafe {
832 let raw_sym = BNDefineAutoSymbolAndVariableOrFunction(
833 self.as_ref().handle,
834 plat.handle,
835 sym.handle,
836 &mut type_with_conf,
837 );
838
839 if raw_sym.is_null() {
840 return Err(());
841 }
842
843 Ok(Symbol::ref_from_raw(raw_sym))
844 }
845 }
846
847 fn undefine_auto_symbol(&self, sym: &Symbol) {
848 unsafe {
849 BNUndefineAutoSymbol(self.as_ref().handle, sym.handle);
850 }
851 }
852
853 fn define_user_symbol(&self, sym: &Symbol) {
854 unsafe {
855 BNDefineUserSymbol(self.as_ref().handle, sym.handle);
856 }
857 }
858
859 fn undefine_user_symbol(&self, sym: &Symbol) {
860 unsafe {
861 BNUndefineUserSymbol(self.as_ref().handle, sym.handle);
862 }
863 }
864
865 fn data_variables(&self) -> Array<DataVariable> {
866 unsafe {
867 let mut count = 0;
868 let vars = BNGetDataVariables(self.as_ref().handle, &mut count);
869 Array::new(vars, count, ())
870 }
871 }
872
873 fn data_variable_at_address(&self, addr: u64) -> Option<DataVariable> {
874 let mut dv = BNDataVariable::default();
875 unsafe {
876 if BNGetDataVariableAtAddress(self.as_ref().handle, addr, &mut dv) {
877 Some(DataVariable::from_owned_raw(dv))
878 } else {
879 None
880 }
881 }
882 }
883
884 fn define_auto_data_var<'a, T: Into<Conf<&'a Type>>>(&self, addr: u64, ty: T) {
885 let mut owned_raw_ty = Conf::<&Type>::into_raw(ty.into());
886 unsafe {
887 BNDefineDataVariable(self.as_ref().handle, addr, &mut owned_raw_ty);
888 }
889 }
890
891 fn define_user_data_var<'a, T: Into<Conf<&'a Type>>>(&self, addr: u64, ty: T) {
893 let mut owned_raw_ty = Conf::<&Type>::into_raw(ty.into());
894 unsafe {
895 BNDefineUserDataVariable(self.as_ref().handle, addr, &mut owned_raw_ty);
896 }
897 }
898
899 fn undefine_auto_data_var(&self, addr: u64, blacklist: Option<bool>) {
900 unsafe {
901 BNUndefineDataVariable(self.as_ref().handle, addr, blacklist.unwrap_or(true));
902 }
903 }
904
905 fn undefine_user_data_var(&self, addr: u64) {
906 unsafe {
907 BNUndefineUserDataVariable(self.as_ref().handle, addr);
908 }
909 }
910
911 fn define_auto_type<T: Into<QualifiedName>>(
912 &self,
913 name: T,
914 source: &str,
915 type_obj: &Type,
916 ) -> QualifiedName {
917 let mut raw_name = QualifiedName::into_raw(name.into());
918 let source_str = source.to_cstr();
919 let name_handle = unsafe {
920 let id_str =
921 BNGenerateAutoTypeId(source_str.as_ref().as_ptr() as *const _, &mut raw_name);
922 BNDefineAnalysisType(self.as_ref().handle, id_str, &mut raw_name, type_obj.handle)
923 };
924 QualifiedName::free_raw(raw_name);
925 QualifiedName::from_owned_raw(name_handle)
926 }
927
928 fn define_auto_type_with_id<T: Into<QualifiedName>>(
929 &self,
930 name: T,
931 id: &str,
932 type_obj: &Type,
933 ) -> QualifiedName {
934 let mut raw_name = QualifiedName::into_raw(name.into());
935 let id_str = id.to_cstr();
936 let result_raw_name = unsafe {
937 BNDefineAnalysisType(
938 self.as_ref().handle,
939 id_str.as_ref().as_ptr() as *const _,
940 &mut raw_name,
941 type_obj.handle,
942 )
943 };
944 QualifiedName::free_raw(raw_name);
945 QualifiedName::from_owned_raw(result_raw_name)
946 }
947
948 fn define_user_type<T: Into<QualifiedName>>(&self, name: T, type_obj: &Type) {
949 let mut raw_name = QualifiedName::into_raw(name.into());
950 unsafe { BNDefineUserAnalysisType(self.as_ref().handle, &mut raw_name, type_obj.handle) }
951 QualifiedName::free_raw(raw_name);
952 }
953
954 fn define_auto_types<T, I>(&self, names_sources_and_types: T) -> HashMap<String, QualifiedName>
955 where
956 T: Iterator<Item = I>,
957 I: Into<QualifiedNameTypeAndId>,
958 {
959 self.define_auto_types_with_progress(names_sources_and_types, NoProgressCallback)
960 }
961
962 fn define_auto_types_with_progress<T, I, P>(
963 &self,
964 names_sources_and_types: T,
965 mut progress: P,
966 ) -> HashMap<String, QualifiedName>
967 where
968 T: Iterator<Item = I>,
969 I: Into<QualifiedNameTypeAndId>,
970 P: ProgressCallback,
971 {
972 let mut types: Vec<BNQualifiedNameTypeAndId> = names_sources_and_types
973 .map(Into::into)
974 .map(QualifiedNameTypeAndId::into_raw)
975 .collect();
976 let mut result_ids: *mut *mut c_char = std::ptr::null_mut();
977 let mut result_names: *mut BNQualifiedName = std::ptr::null_mut();
978
979 let result_count = unsafe {
980 BNDefineAnalysisTypes(
981 self.as_ref().handle,
982 types.as_mut_ptr(),
983 types.len(),
984 Some(P::cb_progress_callback),
985 &mut progress as *mut P as *mut c_void,
986 &mut result_ids as *mut _,
987 &mut result_names as *mut _,
988 )
989 };
990
991 for ty in types {
992 QualifiedNameTypeAndId::free_raw(ty);
993 }
994
995 let id_array = unsafe { Array::<BnString>::new(result_ids, result_count, ()) };
996 let name_array = unsafe { Array::<QualifiedName>::new(result_names, result_count, ()) };
997 id_array
998 .into_iter()
999 .zip(&name_array)
1000 .map(|(id, name)| (id.to_owned(), name))
1001 .collect()
1002 }
1003
1004 fn define_user_types<T, I>(&self, names_and_types: T)
1005 where
1006 T: Iterator<Item = I>,
1007 I: Into<QualifiedNameAndType>,
1008 {
1009 self.define_user_types_with_progress(names_and_types, NoProgressCallback);
1010 }
1011
1012 fn define_user_types_with_progress<T, I, P>(&self, names_and_types: T, mut progress: P)
1013 where
1014 T: Iterator<Item = I>,
1015 I: Into<QualifiedNameAndType>,
1016 P: ProgressCallback,
1017 {
1018 let mut types: Vec<BNQualifiedNameAndType> = names_and_types
1019 .map(Into::into)
1020 .map(QualifiedNameAndType::into_raw)
1021 .collect();
1022
1023 unsafe {
1024 BNDefineUserAnalysisTypes(
1025 self.as_ref().handle,
1026 types.as_mut_ptr(),
1027 types.len(),
1028 Some(P::cb_progress_callback),
1029 &mut progress as *mut P as *mut c_void,
1030 )
1031 };
1032
1033 for ty in types {
1034 QualifiedNameAndType::free_raw(ty);
1035 }
1036 }
1037
1038 fn undefine_auto_type(&self, id: &str) {
1039 let id_str = id.to_cstr();
1040 unsafe {
1041 BNUndefineAnalysisType(self.as_ref().handle, id_str.as_ref().as_ptr() as *const _);
1042 }
1043 }
1044
1045 fn undefine_user_type<T: Into<QualifiedName>>(&self, name: T) {
1046 let mut raw_name = QualifiedName::into_raw(name.into());
1047 unsafe { BNUndefineUserAnalysisType(self.as_ref().handle, &mut raw_name) }
1048 QualifiedName::free_raw(raw_name);
1049 }
1050
1051 fn types(&self) -> Array<QualifiedNameAndType> {
1052 unsafe {
1053 let mut count = 0usize;
1054 let types = BNGetAnalysisTypeList(self.as_ref().handle, &mut count);
1055 Array::new(types, count, ())
1056 }
1057 }
1058
1059 fn dependency_sorted_types(&self) -> Array<QualifiedNameAndType> {
1060 unsafe {
1061 let mut count = 0usize;
1062 let types = BNGetAnalysisDependencySortedTypeList(self.as_ref().handle, &mut count);
1063 Array::new(types, count, ())
1064 }
1065 }
1066
1067 fn type_by_name<T: Into<QualifiedName>>(&self, name: T) -> Option<Ref<Type>> {
1068 let mut raw_name = QualifiedName::into_raw(name.into());
1069 unsafe {
1070 let type_handle = BNGetAnalysisTypeByName(self.as_ref().handle, &mut raw_name);
1071 QualifiedName::free_raw(raw_name);
1072 if type_handle.is_null() {
1073 return None;
1074 }
1075 Some(Type::ref_from_raw(type_handle))
1076 }
1077 }
1078
1079 fn type_by_ref(&self, ref_: &NamedTypeReference) -> Option<Ref<Type>> {
1080 unsafe {
1081 let type_handle = BNGetAnalysisTypeByRef(self.as_ref().handle, ref_.handle);
1082 if type_handle.is_null() {
1083 return None;
1084 }
1085 Some(Type::ref_from_raw(type_handle))
1086 }
1087 }
1088
1089 fn type_by_id(&self, id: &str) -> Option<Ref<Type>> {
1090 let id_str = id.to_cstr();
1091 unsafe {
1092 let type_handle = BNGetAnalysisTypeById(self.as_ref().handle, id_str.as_ptr());
1093 if type_handle.is_null() {
1094 return None;
1095 }
1096 Some(Type::ref_from_raw(type_handle))
1097 }
1098 }
1099
1100 fn type_name_by_id(&self, id: &str) -> Option<QualifiedName> {
1101 let id_str = id.to_cstr();
1102 unsafe {
1103 let name_handle = BNGetAnalysisTypeNameById(self.as_ref().handle, id_str.as_ptr());
1104 let name = QualifiedName::from_owned_raw(name_handle);
1105 match name.items.is_empty() {
1107 true => None,
1108 false => Some(name),
1109 }
1110 }
1111 }
1112
1113 fn type_id_by_name<T: Into<QualifiedName>>(&self, name: T) -> Option<String> {
1114 let mut raw_name = QualifiedName::into_raw(name.into());
1115 unsafe {
1116 let id_cstr = BNGetAnalysisTypeId(self.as_ref().handle, &mut raw_name);
1117 QualifiedName::free_raw(raw_name);
1118 let id = BnString::into_string(id_cstr);
1119 match id.is_empty() {
1120 true => None,
1121 false => Some(id),
1122 }
1123 }
1124 }
1125
1126 fn is_type_auto_defined<T: Into<QualifiedName>>(&self, name: T) -> bool {
1127 let mut raw_name = QualifiedName::into_raw(name.into());
1128 let result = unsafe { BNIsAnalysisTypeAutoDefined(self.as_ref().handle, &mut raw_name) };
1129 QualifiedName::free_raw(raw_name);
1130 result
1131 }
1132
1133 fn segments(&self) -> Array<Segment> {
1134 unsafe {
1135 let mut count = 0;
1136 let raw_segments = BNGetSegments(self.as_ref().handle, &mut count);
1137 Array::new(raw_segments, count, ())
1138 }
1139 }
1140
1141 fn segment_at(&self, addr: u64) -> Option<Ref<Segment>> {
1142 unsafe {
1143 let raw_seg = BNGetSegmentAt(self.as_ref().handle, addr);
1144 match raw_seg.is_null() {
1145 false => Some(Segment::ref_from_raw(raw_seg)),
1146 true => None,
1147 }
1148 }
1149 }
1150
1151 fn add_segment(&self, segment: SegmentBuilder) {
1156 segment.create(self.as_ref());
1157 }
1158
1159 fn begin_bulk_add_segments(&self) {
1170 unsafe { BNBeginBulkAddSegments(self.as_ref().handle) }
1171 }
1172
1173 fn end_bulk_add_segments(&self) {
1179 unsafe { BNEndBulkAddSegments(self.as_ref().handle) }
1180 }
1181
1182 fn cancel_bulk_add_segments(&self) {
1190 unsafe { BNCancelBulkAddSegments(self.as_ref().handle) }
1191 }
1192
1193 fn add_section(&self, section: SectionBuilder) {
1194 section.create(self.as_ref());
1195 }
1196
1197 fn remove_auto_section(&self, name: impl IntoCStr) {
1198 let raw_name = name.to_cstr();
1199 let raw_name_ptr = raw_name.as_ptr();
1200 unsafe {
1201 BNRemoveAutoSection(self.as_ref().handle, raw_name_ptr);
1202 }
1203 }
1204
1205 fn remove_user_section(&self, name: impl IntoCStr) {
1206 let raw_name = name.to_cstr();
1207 let raw_name_ptr = raw_name.as_ptr();
1208 unsafe {
1209 BNRemoveUserSection(self.as_ref().handle, raw_name_ptr);
1210 }
1211 }
1212
1213 fn section_by_name(&self, name: impl IntoCStr) -> Option<Ref<Section>> {
1214 unsafe {
1215 let raw_name = name.to_cstr();
1216 let name_ptr = raw_name.as_ptr();
1217 let raw_section_ptr = BNGetSectionByName(self.as_ref().handle, name_ptr);
1218 match raw_section_ptr.is_null() {
1219 false => Some(Section::ref_from_raw(raw_section_ptr)),
1220 true => None,
1221 }
1222 }
1223 }
1224
1225 fn sections(&self) -> Array<Section> {
1226 unsafe {
1227 let mut count = 0;
1228 let sections = BNGetSections(self.as_ref().handle, &mut count);
1229 Array::new(sections, count, ())
1230 }
1231 }
1232
1233 fn sections_at(&self, addr: u64) -> Array<Section> {
1234 unsafe {
1235 let mut count = 0;
1236 let sections = BNGetSectionsAt(self.as_ref().handle, addr, &mut count);
1237 Array::new(sections, count, ())
1238 }
1239 }
1240
1241 fn memory_map(&self) -> MemoryMap {
1242 MemoryMap::new(self.as_ref().to_owned())
1243 }
1244
1245 fn add_auto_function(&self, address: u64) -> Option<Ref<Function>> {
1251 let platform = self.default_platform()?;
1252 self.add_auto_function_with_platform(address, &platform)
1253 }
1254
1255 fn add_auto_function_with_platform(
1261 &self,
1262 address: u64,
1263 platform: &Platform,
1264 ) -> Option<Ref<Function>> {
1265 self.add_auto_function_ext(address, platform, None)
1266 }
1267
1268 fn add_auto_function_ext(
1272 &self,
1273 address: u64,
1274 platform: &Platform,
1275 func_type: Option<&Type>,
1276 ) -> Option<Ref<Function>> {
1277 unsafe {
1278 let func_type = match func_type {
1279 Some(func_type) => func_type.handle,
1280 None => std::ptr::null_mut(),
1281 };
1282
1283 let handle = BNAddFunctionForAnalysis(
1284 self.as_ref().handle,
1285 platform.handle,
1286 address,
1287 true,
1288 func_type,
1289 );
1290
1291 if handle.is_null() {
1292 return None;
1293 }
1294
1295 Some(Function::ref_from_raw(handle))
1296 }
1297 }
1298
1299 fn remove_auto_function(&self, func: &Function, update_refs: bool) {
1307 unsafe {
1308 BNRemoveAnalysisFunction(self.as_ref().handle, func.handle, update_refs);
1309 }
1310 }
1311
1312 fn add_user_function(&self, addr: u64) -> Option<Ref<Function>> {
1318 let platform = self.default_platform()?;
1319 self.add_user_function_with_platform(addr, &platform)
1320 }
1321
1322 fn add_user_function_with_platform(
1326 &self,
1327 addr: u64,
1328 platform: &Platform,
1329 ) -> Option<Ref<Function>> {
1330 unsafe {
1331 let func = BNCreateUserFunction(self.as_ref().handle, platform.handle, addr);
1332 if func.is_null() {
1333 return None;
1334 }
1335 Some(Function::ref_from_raw(func))
1336 }
1337 }
1338
1339 fn remove_user_function(&self, func: &Function) {
1343 unsafe { BNRemoveUserFunction(self.as_ref().handle, func.handle) }
1344 }
1345
1346 fn has_functions(&self) -> bool {
1347 unsafe { BNHasFunctions(self.as_ref().handle) }
1348 }
1349
1350 fn add_entry_point(&self, addr: u64) {
1354 if let Some(platform) = self.default_platform() {
1355 self.add_entry_point_with_platform(addr, &platform);
1356 }
1357 }
1358
1359 fn add_entry_point_with_platform(&self, addr: u64, platform: &Platform) {
1363 unsafe {
1364 BNAddEntryPointForAnalysis(self.as_ref().handle, platform.handle, addr);
1365 }
1366 }
1367
1368 fn entry_point_function(&self) -> Option<Ref<Function>> {
1369 unsafe {
1370 let raw_func_ptr = BNGetAnalysisEntryPoint(self.as_ref().handle);
1371 match raw_func_ptr.is_null() {
1372 false => Some(Function::ref_from_raw(raw_func_ptr)),
1373 true => None,
1374 }
1375 }
1376 }
1377
1378 fn entry_point_functions(&self) -> Array<Function> {
1384 unsafe {
1385 let mut count = 0;
1386 let functions = BNGetAllEntryFunctions(self.as_ref().handle, &mut count);
1387
1388 Array::new(functions, count, ())
1389 }
1390 }
1391
1392 fn functions(&self) -> Array<Function> {
1393 unsafe {
1394 let mut count = 0;
1395 let functions = BNGetAnalysisFunctionList(self.as_ref().handle, &mut count);
1396
1397 Array::new(functions, count, ())
1398 }
1399 }
1400
1401 fn functions_at(&self, addr: u64) -> Array<Function> {
1403 unsafe {
1404 let mut count = 0;
1405 let functions =
1406 BNGetAnalysisFunctionsForAddress(self.as_ref().handle, addr, &mut count);
1407
1408 Array::new(functions, count, ())
1409 }
1410 }
1411
1412 fn functions_containing(&self, addr: u64) -> Array<Function> {
1414 unsafe {
1415 let mut count = 0;
1416 let functions =
1417 BNGetAnalysisFunctionsContainingAddress(self.as_ref().handle, addr, &mut count);
1418
1419 Array::new(functions, count, ())
1420 }
1421 }
1422
1423 fn functions_by_name(
1433 &self,
1434 name: impl IntoCStr,
1435 plat: Option<&Platform>,
1436 ) -> Vec<Ref<Function>> {
1437 let name = name.to_cstr();
1438 let symbols = self.symbols_by_name(&*name);
1439 let mut addresses: Vec<u64> = symbols.into_iter().map(|s| s.address()).collect();
1440 if addresses.is_empty() && name.to_bytes().starts_with(b"sub_") {
1441 if let Ok(str) = name.to_str() {
1442 if let Ok(address) = u64::from_str_radix(&str[4..], 16) {
1443 addresses.push(address);
1444 }
1445 }
1446 }
1447
1448 let mut functions = Vec::new();
1449
1450 for address in addresses {
1451 let funcs = self.functions_at(address);
1452 for func in funcs.into_iter() {
1453 if func.start() == address && plat.is_none_or(|p| p == func.platform().as_ref()) {
1454 functions.push(func.clone());
1455 }
1456 }
1457 }
1458
1459 functions
1460 }
1461
1462 fn function_at(&self, platform: &Platform, addr: u64) -> Option<Ref<Function>> {
1463 unsafe {
1464 let raw_func_ptr = BNGetAnalysisFunction(self.as_ref().handle, platform.handle, addr);
1465 match raw_func_ptr.is_null() {
1466 false => Some(Function::ref_from_raw(raw_func_ptr)),
1467 true => None,
1468 }
1469 }
1470 }
1471
1472 fn function_start_before(&self, addr: u64) -> u64 {
1473 unsafe { BNGetPreviousFunctionStartBeforeAddress(self.as_ref().handle, addr) }
1474 }
1475
1476 fn function_start_after(&self, addr: u64) -> u64 {
1477 unsafe { BNGetNextFunctionStartAfterAddress(self.as_ref().handle, addr) }
1478 }
1479
1480 fn basic_blocks_containing(&self, addr: u64) -> Array<BasicBlock<NativeBlock>> {
1481 unsafe {
1482 let mut count = 0;
1483 let blocks = BNGetBasicBlocksForAddress(self.as_ref().handle, addr, &mut count);
1484 Array::new(blocks, count, NativeBlock::new())
1485 }
1486 }
1487
1488 fn basic_blocks_starting_at(&self, addr: u64) -> Array<BasicBlock<NativeBlock>> {
1489 unsafe {
1490 let mut count = 0;
1491 let blocks = BNGetBasicBlocksStartingAtAddress(self.as_ref().handle, addr, &mut count);
1492 Array::new(blocks, count, NativeBlock::new())
1493 }
1494 }
1495
1496 fn is_new_auto_function_analysis_suppressed(&self) -> bool {
1497 unsafe { BNGetNewAutoFunctionAnalysisSuppressed(self.as_ref().handle) }
1498 }
1499
1500 fn set_new_auto_function_analysis_suppressed(&self, suppress: bool) {
1501 unsafe {
1502 BNSetNewAutoFunctionAnalysisSuppressed(self.as_ref().handle, suppress);
1503 }
1504 }
1505
1506 fn should_skip_target_analysis(
1508 &self,
1509 src_loc: impl Into<Location>,
1510 src_func: &Function,
1511 src_end: u64,
1512 target: impl Into<Location>,
1513 ) -> bool {
1514 let src_loc = src_loc.into();
1515 let target = target.into();
1516 unsafe {
1517 BNShouldSkipTargetAnalysis(
1518 self.as_ref().handle,
1519 &mut src_loc.into(),
1520 src_func.handle,
1521 src_end,
1522 &mut target.into(),
1523 )
1524 }
1525 }
1526
1527 fn read_buffer(&self, offset: u64, len: usize) -> Option<DataBuffer> {
1528 let read_buffer = unsafe { BNReadViewBuffer(self.as_ref().handle, offset, len) };
1529 if read_buffer.is_null() {
1530 None
1531 } else {
1532 Some(DataBuffer::from_raw(read_buffer))
1533 }
1534 }
1535
1536 fn debug_info(&self) -> Ref<DebugInfo> {
1537 unsafe { DebugInfo::ref_from_raw(BNGetDebugInfo(self.as_ref().handle)) }
1538 }
1539
1540 fn set_debug_info(&self, debug_info: &DebugInfo) {
1541 unsafe { BNSetDebugInfo(self.as_ref().handle, debug_info.handle) }
1542 }
1543
1544 fn apply_debug_info(&self, debug_info: &DebugInfo) {
1545 unsafe { BNApplyDebugInfo(self.as_ref().handle, debug_info.handle) }
1546 }
1547
1548 fn show_plaintext_report(&self, title: &str, plaintext: &str) {
1549 let title = title.to_cstr();
1550 let plaintext = plaintext.to_cstr();
1551 unsafe {
1552 BNShowPlainTextReport(
1553 self.as_ref().handle,
1554 title.as_ref().as_ptr() as *mut _,
1555 plaintext.as_ref().as_ptr() as *mut _,
1556 )
1557 }
1558 }
1559
1560 fn show_markdown_report(&self, title: &str, contents: &str, plaintext: &str) {
1561 let title = title.to_cstr();
1562 let contents = contents.to_cstr();
1563 let plaintext = plaintext.to_cstr();
1564 unsafe {
1565 BNShowMarkdownReport(
1566 self.as_ref().handle,
1567 title.as_ref().as_ptr() as *mut _,
1568 contents.as_ref().as_ptr() as *mut _,
1569 plaintext.as_ref().as_ptr() as *mut _,
1570 )
1571 }
1572 }
1573
1574 fn show_html_report(&self, title: &str, contents: &str, plaintext: &str) {
1575 let title = title.to_cstr();
1576 let contents = contents.to_cstr();
1577 let plaintext = plaintext.to_cstr();
1578 unsafe {
1579 BNShowHTMLReport(
1580 self.as_ref().handle,
1581 title.as_ref().as_ptr() as *mut _,
1582 contents.as_ref().as_ptr() as *mut _,
1583 plaintext.as_ref().as_ptr() as *mut _,
1584 )
1585 }
1586 }
1587
1588 fn show_graph_report(&self, raw_name: &str, graph: &FlowGraph) {
1589 let raw_name = raw_name.to_cstr();
1590 unsafe {
1591 BNShowGraphReport(self.as_ref().handle, raw_name.as_ptr(), graph.handle);
1592 }
1593 }
1594
1595 fn load_settings(&self, view_type_name: &str) -> Result<Ref<Settings>> {
1596 let view_type_name = view_type_name.to_cstr();
1597 let settings_handle =
1598 unsafe { BNBinaryViewGetLoadSettings(self.as_ref().handle, view_type_name.as_ptr()) };
1599
1600 if settings_handle.is_null() {
1601 Err(())
1602 } else {
1603 Ok(unsafe { Settings::ref_from_raw(settings_handle) })
1604 }
1605 }
1606
1607 fn set_load_settings(&self, view_type_name: &str, settings: &Settings) {
1608 let view_type_name = view_type_name.to_cstr();
1609
1610 unsafe {
1611 BNBinaryViewSetLoadSettings(
1612 self.as_ref().handle,
1613 view_type_name.as_ptr(),
1614 settings.handle,
1615 )
1616 };
1617 }
1618
1619 fn create_tag_type(&self, name: &str, icon: &str) -> Ref<TagType> {
1625 let tag_type = TagType::create(self.as_ref(), name, icon);
1626 unsafe {
1627 BNAddTagType(self.as_ref().handle, tag_type.handle);
1628 }
1629 tag_type
1630 }
1631
1632 fn remove_tag_type(&self, tag_type: &TagType) {
1634 unsafe { BNRemoveTagType(self.as_ref().handle, tag_type.handle) }
1635 }
1636
1637 fn tag_type_by_name(&self, name: &str) -> Option<Ref<TagType>> {
1639 let name = name.to_cstr();
1640 unsafe {
1641 let handle = BNGetTagType(self.as_ref().handle, name.as_ptr());
1642 if handle.is_null() {
1643 return None;
1644 }
1645 Some(TagType::ref_from_raw(handle))
1646 }
1647 }
1648
1649 fn tags_all_scopes(&self) -> Array<TagReference> {
1651 let mut count = 0;
1652 unsafe {
1653 let tag_references = BNGetAllTagReferences(self.as_ref().handle, &mut count);
1654 Array::new(tag_references, count, ())
1655 }
1656 }
1657
1658 fn tag_types(&self) -> Array<TagType> {
1660 let mut count = 0;
1661 unsafe {
1662 let tag_types_raw = BNGetTagTypes(self.as_ref().handle, &mut count);
1663 Array::new(tag_types_raw, count, ())
1664 }
1665 }
1666
1667 fn tags_by_type(&self, tag_type: &TagType) -> Array<TagReference> {
1669 let mut count = 0;
1670 unsafe {
1671 let tag_references =
1672 BNGetAllTagReferencesOfType(self.as_ref().handle, tag_type.handle, &mut count);
1673 Array::new(tag_references, count, ())
1674 }
1675 }
1676
1677 fn tag_by_id(&self, id: &str) -> Option<Ref<Tag>> {
1681 let id = id.to_cstr();
1682 unsafe {
1683 let handle = BNGetTag(self.as_ref().handle, id.as_ptr());
1684 if handle.is_null() {
1685 return None;
1686 }
1687 Some(Tag::ref_from_raw(handle))
1688 }
1689 }
1690
1691 fn add_tag(&self, addr: u64, t: &TagType, data: &str, user: bool) {
1695 let tag = Tag::new(t, data);
1696
1697 unsafe { BNAddTag(self.as_ref().handle, tag.handle, user) }
1698
1699 if user {
1700 unsafe { BNAddUserDataTag(self.as_ref().handle, addr, tag.handle) }
1701 } else {
1702 unsafe { BNAddAutoDataTag(self.as_ref().handle, addr, tag.handle) }
1703 }
1704 }
1705
1706 fn remove_auto_data_tag(&self, addr: u64, tag: &Tag) {
1708 unsafe { BNRemoveAutoDataTag(self.as_ref().handle, addr, tag.handle) }
1709 }
1710
1711 fn remove_user_data_tag(&self, addr: u64, tag: &Tag) {
1714 unsafe { BNRemoveUserDataTag(self.as_ref().handle, addr, tag.handle) }
1715 }
1716
1717 fn comment_references(&self) -> Array<CommentReference> {
1723 let mut count = 0;
1724 let addresses_raw =
1725 unsafe { BNGetGlobalCommentedAddresses(self.as_ref().handle, &mut count) };
1726 unsafe { Array::new(addresses_raw, count, ()) }
1727 }
1728
1729 fn comments(&self) -> BTreeMap<u64, String> {
1734 self.comment_references()
1735 .iter()
1736 .filter_map(|cmt_ref| Some((cmt_ref.start, self.comment_at(cmt_ref.start)?)))
1737 .collect()
1738 }
1739
1740 fn comment_at(&self, addr: u64) -> Option<String> {
1741 unsafe {
1742 let comment_raw = BNGetGlobalCommentForAddress(self.as_ref().handle, addr);
1743 match comment_raw.is_null() {
1744 false => Some(BnString::into_string(comment_raw)),
1745 true => None,
1746 }
1747 }
1748 }
1749
1750 fn set_comment_at(&self, addr: u64, comment: &str) {
1755 let comment_raw = comment.to_cstr();
1756 unsafe { BNSetGlobalCommentForAddress(self.as_ref().handle, addr, comment_raw.as_ptr()) }
1757 }
1758
1759 fn get_next_linear_disassembly_lines(
1768 &self,
1769 pos: &mut LinearViewCursor,
1770 ) -> Array<LinearDisassemblyLine> {
1771 let mut result = unsafe { Array::new(std::ptr::null_mut(), 0, ()) };
1772
1773 while result.is_empty() {
1774 result = pos.lines();
1775 if !pos.next() {
1776 return result;
1777 }
1778 }
1779
1780 result
1781 }
1782
1783 fn get_previous_linear_disassembly_lines(
1792 &self,
1793 pos: &mut LinearViewCursor,
1794 ) -> Array<LinearDisassemblyLine> {
1795 let mut result = unsafe { Array::new(std::ptr::null_mut(), 0, ()) };
1796 while result.is_empty() {
1797 if !pos.previous() {
1798 return result;
1799 }
1800
1801 result = pos.lines();
1802 }
1803
1804 result
1805 }
1806
1807 fn query_metadata(&self, key: &str) -> Option<Ref<Metadata>> {
1808 let key = key.to_cstr();
1809 let value: *mut BNMetadata =
1810 unsafe { BNBinaryViewQueryMetadata(self.as_ref().handle, key.as_ptr()) };
1811 if value.is_null() {
1812 None
1813 } else {
1814 Some(unsafe { Metadata::ref_from_raw(value) })
1815 }
1816 }
1817
1818 fn get_metadata<T>(&self, key: &str) -> Option<Result<T>>
1822 where
1823 T: for<'a> TryFrom<&'a Metadata>,
1824 {
1825 self.query_metadata(key)
1826 .map(|md| T::try_from(md.as_ref()).map_err(|_| ()))
1827 }
1828
1829 fn store_metadata<V>(&self, key: &str, value: V, is_auto: bool)
1830 where
1831 V: Into<Ref<Metadata>>,
1832 {
1833 let md = value.into();
1834 let key = key.to_cstr();
1835 unsafe {
1836 BNBinaryViewStoreMetadata(
1837 self.as_ref().handle,
1838 key.as_ptr(),
1839 md.as_ref().handle,
1840 is_auto,
1841 )
1842 };
1843 }
1844
1845 fn remove_metadata(&self, key: &str) {
1846 let key = key.to_cstr();
1847 unsafe { BNBinaryViewRemoveMetadata(self.as_ref().handle, key.as_ptr()) };
1848 }
1849
1850 fn code_refs_to_addr(&self, addr: u64) -> Array<CodeReference> {
1852 unsafe {
1853 let mut count = 0;
1854 let handle = BNGetCodeReferences(self.as_ref().handle, addr, &mut count, false, 0);
1855 Array::new(handle, count, ())
1856 }
1857 }
1858
1859 fn code_refs_into_range(&self, range: Range<u64>) -> Array<CodeReference> {
1861 unsafe {
1862 let mut count = 0;
1863 let handle = BNGetCodeReferencesInRange(
1864 self.as_ref().handle,
1865 range.start,
1866 range.end - range.start,
1867 &mut count,
1868 false,
1869 0,
1870 );
1871 Array::new(handle, count, ())
1872 }
1873 }
1874
1875 fn code_refs_from_addr(&self, addr: u64, func: Option<&Function>) -> Vec<u64> {
1877 unsafe {
1878 let mut count = 0;
1879 let code_ref =
1880 CodeReference::new(addr, func.map(|f| f.to_owned()), func.map(|f| f.arch()));
1881 let mut raw_code_ref = CodeReference::into_owned_raw(&code_ref);
1882 let addresses =
1883 BNGetCodeReferencesFrom(self.as_ref().handle, &mut raw_code_ref, &mut count);
1884 let res = std::slice::from_raw_parts(addresses, count).to_vec();
1885 BNFreeAddressList(addresses);
1886 res
1887 }
1888 }
1889
1890 fn data_refs_to_addr(&self, addr: u64) -> Array<DataReference> {
1892 unsafe {
1893 let mut count = 0;
1894 let handle = BNGetDataReferences(self.as_ref().handle, addr, &mut count, false, 0);
1895 Array::new(handle, count, ())
1896 }
1897 }
1898
1899 fn data_refs_into_range(&self, range: Range<u64>) -> Array<DataReference> {
1901 unsafe {
1902 let mut count = 0;
1903 let handle = BNGetDataReferencesInRange(
1904 self.as_ref().handle,
1905 range.start,
1906 range.end - range.start,
1907 &mut count,
1908 false,
1909 0,
1910 );
1911 Array::new(handle, count, ())
1912 }
1913 }
1914
1915 fn data_refs_from_addr(&self, addr: u64) -> Array<DataReference> {
1917 unsafe {
1918 let mut count = 0;
1919 let handle = BNGetDataReferencesFrom(self.as_ref().handle, addr, &mut count);
1920 Array::new(handle, count, ())
1921 }
1922 }
1923
1924 fn code_refs_using_type_name<T: Into<QualifiedName>>(&self, name: T) -> Array<CodeReference> {
1926 let mut raw_name = QualifiedName::into_raw(name.into());
1927 unsafe {
1928 let mut count = 0;
1929 let handle = BNGetCodeReferencesForType(
1930 self.as_ref().handle,
1931 &mut raw_name,
1932 &mut count,
1933 false,
1934 0,
1935 );
1936 QualifiedName::free_raw(raw_name);
1937 Array::new(handle, count, ())
1938 }
1939 }
1940
1941 fn data_refs_using_type_name<T: Into<QualifiedName>>(&self, name: T) -> Array<DataReference> {
1943 let mut raw_name = QualifiedName::into_raw(name.into());
1944 unsafe {
1945 let mut count = 0;
1946 let handle = BNGetDataReferencesForType(
1947 self.as_ref().handle,
1948 &mut raw_name,
1949 &mut count,
1950 false,
1951 0,
1952 );
1953 QualifiedName::free_raw(raw_name);
1954 Array::new(handle, count, ())
1955 }
1956 }
1957
1958 fn relocations_at(&self, addr: u64) -> Array<Relocation> {
1959 unsafe {
1960 let mut count = 0;
1961 let handle = BNGetRelocationsAt(self.as_ref().handle, addr, &mut count);
1962 Array::new(handle, count, ())
1963 }
1964 }
1965
1966 fn relocation_ranges(&self) -> Vec<Range<u64>> {
1967 let ranges = unsafe {
1968 let mut count = 0;
1969 let reloc_ranges_ptr = BNGetRelocationRanges(self.as_ref().handle, &mut count);
1970 let ranges = std::slice::from_raw_parts(reloc_ranges_ptr, count).to_vec();
1971 BNFreeRelocationRanges(reloc_ranges_ptr);
1972 ranges
1973 };
1974
1975 ranges
1977 .iter()
1978 .map(|range| Range {
1979 start: range.start,
1980 end: range.end,
1981 })
1982 .collect()
1983 }
1984
1985 fn component_by_guid(&self, guid: &str) -> Option<Ref<Component>> {
1986 let name = guid.to_cstr();
1987 let result = unsafe { BNGetComponentByGuid(self.as_ref().handle, name.as_ptr()) };
1988 NonNull::new(result).map(|h| unsafe { Component::ref_from_raw(h) })
1989 }
1990
1991 fn root_component(&self) -> Option<Ref<Component>> {
1992 let result = unsafe { BNGetRootComponent(self.as_ref().handle) };
1993 NonNull::new(result).map(|h| unsafe { Component::ref_from_raw(h) })
1994 }
1995
1996 fn component_by_path(&self, path: &str) -> Option<Ref<Component>> {
1997 let path = path.to_cstr();
1998 let result = unsafe { BNGetComponentByPath(self.as_ref().handle, path.as_ptr()) };
1999 NonNull::new(result).map(|h| unsafe { Component::ref_from_raw(h) })
2000 }
2001
2002 fn remove_component(&self, component: &Component) -> bool {
2003 unsafe { BNRemoveComponent(self.as_ref().handle, component.handle.as_ptr()) }
2004 }
2005
2006 fn remove_component_by_guid(&self, guid: &str) -> bool {
2007 let path = guid.to_cstr();
2008 unsafe { BNRemoveComponentByGuid(self.as_ref().handle, path.as_ptr()) }
2009 }
2010
2011 fn data_variable_parent_components(&self, data_variable: &DataVariable) -> Array<Component> {
2012 let mut count = 0;
2013 let result = unsafe {
2014 BNGetDataVariableParentComponents(
2015 self.as_ref().handle,
2016 data_variable.address,
2017 &mut count,
2018 )
2019 };
2020 unsafe { Array::new(result, count, ()) }
2021 }
2022
2023 fn external_libraries(&self) -> Array<ExternalLibrary> {
2024 let mut count = 0;
2025 let result = unsafe { BNBinaryViewGetExternalLibraries(self.as_ref().handle, &mut count) };
2026 unsafe { Array::new(result, count, ()) }
2027 }
2028
2029 fn external_library(&self, name: &str) -> Option<Ref<ExternalLibrary>> {
2030 let name_ptr = name.to_cstr();
2031 let result =
2032 unsafe { BNBinaryViewGetExternalLibrary(self.as_ref().handle, name_ptr.as_ptr()) };
2033 let result_ptr = NonNull::new(result)?;
2034 Some(unsafe { ExternalLibrary::ref_from_raw(result_ptr) })
2035 }
2036
2037 fn remove_external_library(&self, name: &str) {
2038 let name_ptr = name.to_cstr();
2039 unsafe { BNBinaryViewRemoveExternalLibrary(self.as_ref().handle, name_ptr.as_ptr()) };
2040 }
2041
2042 fn add_external_library(
2043 &self,
2044 name: &str,
2045 backing_file: Option<&ProjectFile>,
2046 auto: bool,
2047 ) -> Option<Ref<ExternalLibrary>> {
2048 let name_ptr = name.to_cstr();
2049 let result = unsafe {
2050 BNBinaryViewAddExternalLibrary(
2051 self.as_ref().handle,
2052 name_ptr.as_ptr(),
2053 backing_file
2054 .map(|b| b.handle.as_ptr())
2055 .unwrap_or(std::ptr::null_mut()),
2056 auto,
2057 )
2058 };
2059 NonNull::new(result).map(|h| unsafe { ExternalLibrary::ref_from_raw(h) })
2060 }
2061
2062 fn external_locations(&self) -> Array<ExternalLocation> {
2063 let mut count = 0;
2064 let result = unsafe { BNBinaryViewGetExternalLocations(self.as_ref().handle, &mut count) };
2065 unsafe { Array::new(result, count, ()) }
2066 }
2067
2068 fn external_location_from_symbol(&self, symbol: &Symbol) -> Option<Ref<ExternalLocation>> {
2069 let result =
2070 unsafe { BNBinaryViewGetExternalLocation(self.as_ref().handle, symbol.handle) };
2071 let result_ptr = NonNull::new(result)?;
2072 Some(unsafe { ExternalLocation::ref_from_raw(result_ptr) })
2073 }
2074
2075 fn remove_external_location(&self, location: &ExternalLocation) {
2076 self.remove_external_location_from_symbol(&location.source_symbol())
2077 }
2078
2079 fn remove_external_location_from_symbol(&self, symbol: &Symbol) {
2080 unsafe { BNBinaryViewRemoveExternalLocation(self.as_ref().handle, symbol.handle) };
2081 }
2082
2083 fn add_external_location(
2085 &self,
2086 symbol: &Symbol,
2087 library: &ExternalLibrary,
2088 target_symbol_name: &str,
2089 target_address: Option<u64>,
2090 target_is_auto: bool,
2091 ) -> Option<Ref<ExternalLocation>> {
2092 let target_symbol_name = target_symbol_name.to_cstr();
2093 let target_address_ptr = target_address
2094 .map(|a| a as *mut u64)
2095 .unwrap_or(std::ptr::null_mut());
2096 let result = unsafe {
2097 BNBinaryViewAddExternalLocation(
2098 self.as_ref().handle,
2099 symbol.handle,
2100 library.handle.as_ptr(),
2101 target_symbol_name.as_ptr(),
2102 target_address_ptr,
2103 target_is_auto,
2104 )
2105 };
2106 NonNull::new(result).map(|h| unsafe { ExternalLocation::ref_from_raw(h) })
2107 }
2108
2109 fn type_container(&self) -> TypeContainer {
2113 let type_container_ptr =
2114 NonNull::new(unsafe { BNGetAnalysisTypeContainer(self.as_ref().handle) });
2115 unsafe { TypeContainer::from_raw(type_container_ptr.unwrap()) }
2117 }
2118
2119 fn user_type_container(&self) -> TypeContainer {
2121 let type_container_ptr =
2122 NonNull::new(unsafe { BNGetAnalysisUserTypeContainer(self.as_ref().handle) });
2123 unsafe { TypeContainer::from_raw(type_container_ptr.unwrap()) }.clone()
2125 }
2126
2127 fn auto_type_container(&self) -> TypeContainer {
2131 let type_container_ptr =
2132 NonNull::new(unsafe { BNGetAnalysisAutoTypeContainer(self.as_ref().handle) });
2133 unsafe { TypeContainer::from_raw(type_container_ptr.unwrap()) }
2135 }
2136
2137 fn type_libraries(&self) -> Array<TypeLibrary> {
2138 let mut count = 0;
2139 let result = unsafe { BNGetBinaryViewTypeLibraries(self.as_ref().handle, &mut count) };
2140 unsafe { Array::new(result, count, ()) }
2141 }
2142
2143 fn add_type_library(&self, library: &TypeLibrary) {
2145 unsafe { BNAddBinaryViewTypeLibrary(self.as_ref().handle, library.as_raw()) }
2146 }
2147
2148 fn type_library_by_name(&self, name: &str) -> Option<Ref<TypeLibrary>> {
2149 let name = name.to_cstr();
2150 let result = unsafe { BNGetBinaryViewTypeLibrary(self.as_ref().handle, name.as_ptr()) };
2151 NonNull::new(result).map(|h| unsafe { TypeLibrary::ref_from_raw(h) })
2152 }
2153
2154 fn record_imported_object_library<T: Into<QualifiedName>>(
2163 &self,
2164 lib: &TypeLibrary,
2165 name: T,
2166 addr: u64,
2167 platform: &Platform,
2168 ) {
2169 let mut raw_name = QualifiedName::into_raw(name.into());
2170 unsafe {
2171 BNBinaryViewRecordImportedObjectLibrary(
2172 self.as_ref().handle,
2173 platform.handle,
2174 addr,
2175 lib.as_raw(),
2176 &mut raw_name,
2177 )
2178 }
2179 QualifiedName::free_raw(raw_name);
2180 }
2181
2182 fn import_type_library_type<T: Into<QualifiedName>>(
2193 &self,
2194 name: T,
2195 lib: Option<&TypeLibrary>,
2196 ) -> Option<Ref<Type>> {
2197 let mut lib_ref = lib
2198 .as_ref()
2199 .map(|l| unsafe { l.as_raw() } as *mut _)
2200 .unwrap_or(std::ptr::null_mut());
2201 let mut raw_name = QualifiedName::into_raw(name.into());
2202 let result = unsafe {
2203 BNBinaryViewImportTypeLibraryType(self.as_ref().handle, &mut lib_ref, &mut raw_name)
2204 };
2205 QualifiedName::free_raw(raw_name);
2206 (!result.is_null()).then(|| unsafe { Type::ref_from_raw(result) })
2207 }
2208
2209 fn import_type_library_object<T: Into<QualifiedName>>(
2220 &self,
2221 name: T,
2222 lib: Option<&TypeLibrary>,
2223 ) -> Option<Ref<Type>> {
2224 let mut lib_ref = lib
2225 .as_ref()
2226 .map(|l| unsafe { l.as_raw() } as *mut _)
2227 .unwrap_or(std::ptr::null_mut());
2228 let mut raw_name = QualifiedName::into_raw(name.into());
2229 let result = unsafe {
2230 BNBinaryViewImportTypeLibraryObject(self.as_ref().handle, &mut lib_ref, &mut raw_name)
2231 };
2232 QualifiedName::free_raw(raw_name);
2233 (!result.is_null()).then(|| unsafe { Type::ref_from_raw(result) })
2234 }
2235
2236 fn import_type_by_guid(&self, guid: &str) -> Option<Ref<Type>> {
2238 let guid = guid.to_cstr();
2239 let result =
2240 unsafe { BNBinaryViewImportTypeLibraryTypeByGuid(self.as_ref().handle, guid.as_ptr()) };
2241 (!result.is_null()).then(|| unsafe { Type::ref_from_raw(result) })
2242 }
2243
2244 fn export_type_to_library<T: Into<QualifiedName>>(
2249 &self,
2250 lib: &TypeLibrary,
2251 name: T,
2252 type_obj: &Type,
2253 ) {
2254 let mut raw_name = QualifiedName::into_raw(name.into());
2255 unsafe {
2256 BNBinaryViewExportTypeToTypeLibrary(
2257 self.as_ref().handle,
2258 lib.as_raw(),
2259 &mut raw_name,
2260 type_obj.handle,
2261 )
2262 }
2263 QualifiedName::free_raw(raw_name);
2264 }
2265
2266 fn export_object_to_library<T: Into<QualifiedName>>(
2271 &self,
2272 lib: &TypeLibrary,
2273 name: T,
2274 type_obj: &Type,
2275 ) {
2276 let mut raw_name = QualifiedName::into_raw(name.into());
2277 unsafe {
2278 BNBinaryViewExportObjectToTypeLibrary(
2279 self.as_ref().handle,
2280 lib.as_raw(),
2281 &mut raw_name,
2282 type_obj.handle,
2283 )
2284 }
2285 QualifiedName::free_raw(raw_name);
2286 }
2287
2288 fn lookup_imported_object_library(
2294 &self,
2295 addr: u64,
2296 platform: &Platform,
2297 ) -> Option<(Ref<TypeLibrary>, QualifiedName)> {
2298 let mut result_lib = std::ptr::null_mut();
2299 let mut result_name = BNQualifiedName::default();
2300 let success = unsafe {
2301 BNBinaryViewLookupImportedObjectLibrary(
2302 self.as_ref().handle,
2303 platform.handle,
2304 addr,
2305 &mut result_lib,
2306 &mut result_name,
2307 )
2308 };
2309 if !success {
2310 return None;
2311 }
2312 let lib = unsafe { TypeLibrary::ref_from_raw(NonNull::new(result_lib)?) };
2313 let name = QualifiedName::from_owned_raw(result_name);
2314 Some((lib, name))
2315 }
2316
2317 fn lookup_imported_type_library<T: Into<QualifiedName>>(
2321 &self,
2322 name: T,
2323 ) -> Option<(Ref<TypeLibrary>, QualifiedName)> {
2324 let raw_name = QualifiedName::into_raw(name.into());
2325 let mut result_lib = std::ptr::null_mut();
2326 let mut result_name = BNQualifiedName::default();
2327 let success = unsafe {
2328 BNBinaryViewLookupImportedTypeLibrary(
2329 self.as_ref().handle,
2330 &raw_name,
2331 &mut result_lib,
2332 &mut result_name,
2333 )
2334 };
2335 QualifiedName::free_raw(raw_name);
2336 if !success {
2337 return None;
2338 }
2339 let lib = unsafe { TypeLibrary::ref_from_raw(NonNull::new(result_lib)?) };
2340 let name = QualifiedName::from_owned_raw(result_name);
2341 Some((lib, name))
2342 }
2343
2344 fn strings(&self) -> Array<StringReference> {
2358 unsafe {
2359 let mut count = 0;
2360 let strings = BNGetStrings(self.as_ref().handle, &mut count);
2361 Array::new(strings, count, ())
2362 }
2363 }
2364
2365 fn string_at(&self, addr: u64) -> Option<StringReference> {
2379 let mut str_ref = BNStringReference::default();
2380 let success = unsafe { BNGetStringAtAddress(self.as_ref().handle, addr, &mut str_ref) };
2381 if success {
2382 Some(str_ref.into())
2383 } else {
2384 None
2385 }
2386 }
2387
2388 fn strings_in_range(&self, range: Range<u64>) -> Array<StringReference> {
2402 unsafe {
2403 let mut count = 0;
2404 let strings = BNGetStringsInRange(
2405 self.as_ref().handle,
2406 range.start,
2407 range.end - range.start,
2408 &mut count,
2409 );
2410 Array::new(strings, count, ())
2411 }
2412 }
2413
2414 fn attached_type_archives(&self) -> Vec<TypeArchiveId> {
2418 let mut ids: *mut *mut c_char = std::ptr::null_mut();
2419 let mut paths: *mut *mut c_char = std::ptr::null_mut();
2420 let count =
2421 unsafe { BNBinaryViewGetTypeArchives(self.as_ref().handle, &mut ids, &mut paths) };
2422 let _path_list = unsafe { Array::<BnString>::new(paths, count, ()) };
2426 let id_list = unsafe { Array::<BnString>::new(ids, count, ()) };
2427 id_list
2428 .into_iter()
2429 .map(|id| TypeArchiveId(id.to_string()))
2430 .collect()
2431 }
2432
2433 fn type_archive_by_id(&self, id: &TypeArchiveId) -> Option<Ref<TypeArchive>> {
2437 let id = id.0.as_str().to_cstr();
2438 let result = unsafe { BNBinaryViewGetTypeArchive(self.as_ref().handle, id.as_ptr()) };
2439 let result_ptr = NonNull::new(result)?;
2440 Some(unsafe { TypeArchive::ref_from_raw(result_ptr) })
2441 }
2442
2443 fn type_archive_path_by_id(&self, id: &TypeArchiveId) -> Option<PathBuf> {
2445 let id = id.0.as_str().to_cstr();
2446 let result = unsafe { BNBinaryViewGetTypeArchivePath(self.as_ref().handle, id.as_ptr()) };
2447 if result.is_null() {
2448 return None;
2449 }
2450 let path_str = unsafe { BnString::into_string(result) };
2451 Some(PathBuf::from(path_str))
2452 }
2453}
2454
2455impl<T: BinaryViewBase> BinaryViewExt for T {}
2456
2457#[derive(PartialEq, Eq, Hash)]
2484pub struct BinaryView {
2485 pub handle: *mut BNBinaryView,
2486}
2487
2488impl BinaryView {
2489 pub unsafe fn from_raw(handle: *mut BNBinaryView) -> Self {
2490 debug_assert!(!handle.is_null());
2491 Self { handle }
2492 }
2493
2494 pub(crate) unsafe fn ref_from_raw(handle: *mut BNBinaryView) -> Ref<Self> {
2495 debug_assert!(!handle.is_null());
2496 Ref::new(Self { handle })
2497 }
2498
2499 pub fn from_metadata(meta: &FileMetadata) -> Result<Ref<Self>> {
2504 if !meta.file_path().exists() {
2505 return Err(());
2506 }
2507 let file = meta.file_path().to_cstr();
2508 let handle =
2509 unsafe { BNCreateBinaryDataViewFromFilename(meta.handle, file.as_ptr() as *mut _) };
2510 if handle.is_null() {
2511 return Err(());
2512 }
2513 unsafe { Ok(Ref::new(Self { handle })) }
2514 }
2515
2516 pub fn from_path(meta: &FileMetadata, file_path: impl AsRef<Path>) -> Result<Ref<Self>> {
2521 meta.set_file_path(file_path.as_ref());
2522 Self::from_metadata(meta)
2523 }
2524
2525 pub unsafe fn from_accessor<A: Accessor>(
2531 meta: &FileMetadata,
2532 accessor: &mut FileAccessor<A>,
2533 ) -> Result<Ref<Self>> {
2534 let handle = unsafe { BNCreateBinaryDataViewFromFile(meta.handle, &mut accessor.raw) };
2535 if handle.is_null() {
2536 return Err(());
2537 }
2538 unsafe { Ok(Ref::new(Self { handle })) }
2539 }
2540
2541 pub fn from_data(meta: &FileMetadata, data: &[u8]) -> Ref<Self> {
2545 let handle = unsafe {
2546 BNCreateBinaryDataViewFromData(meta.handle, data.as_ptr() as *mut _, data.len())
2547 };
2548 assert!(
2549 !handle.is_null(),
2550 "BNCreateBinaryDataViewFromData should always succeed"
2551 );
2552 unsafe { Ref::new(Self { handle }) }
2553 }
2554
2555 pub fn save_to_path(&self, file_path: impl AsRef<Path>) -> bool {
2564 let file = file_path.as_ref().to_cstr();
2565 unsafe { BNSaveToFilename(self.handle, file.as_ptr() as *mut _) }
2566 }
2567
2568 pub fn save_to_accessor<A: Accessor>(&self, file: &mut FileAccessor<A>) -> bool {
2577 unsafe { BNSaveToFile(self.handle, &mut file.raw) }
2578 }
2579}
2580
2581impl BinaryViewBase for BinaryView {
2582 fn read(&self, buf: &mut [u8], offset: u64) -> usize {
2583 unsafe { BNReadViewData(self.handle, buf.as_mut_ptr() as *mut _, offset, buf.len()) }
2584 }
2585
2586 fn write(&self, offset: u64, data: &[u8]) -> usize {
2587 unsafe { BNWriteViewData(self.handle, offset, data.as_ptr() as *const _, data.len()) }
2588 }
2589
2590 fn insert(&self, offset: u64, data: &[u8]) -> usize {
2591 unsafe { BNInsertViewData(self.handle, offset, data.as_ptr() as *const _, data.len()) }
2592 }
2593
2594 fn remove(&self, offset: u64, len: usize) -> usize {
2595 unsafe { BNRemoveViewData(self.handle, offset, len as u64) }
2596 }
2597
2598 fn offset_valid(&self, offset: u64) -> bool {
2599 unsafe { BNIsValidOffset(self.handle, offset) }
2600 }
2601
2602 fn offset_readable(&self, offset: u64) -> bool {
2603 unsafe { BNIsOffsetReadable(self.handle, offset) }
2604 }
2605
2606 fn offset_writable(&self, offset: u64) -> bool {
2607 unsafe { BNIsOffsetWritable(self.handle, offset) }
2608 }
2609
2610 fn offset_executable(&self, offset: u64) -> bool {
2611 unsafe { BNIsOffsetExecutable(self.handle, offset) }
2612 }
2613
2614 fn offset_backed_by_file(&self, offset: u64) -> bool {
2615 unsafe { BNIsOffsetBackedByFile(self.handle, offset) }
2616 }
2617
2618 fn next_valid_offset_after(&self, offset: u64) -> u64 {
2619 unsafe { BNGetNextValidOffset(self.handle, offset) }
2620 }
2621
2622 fn modification_status(&self, offset: u64) -> ModificationStatus {
2623 unsafe { BNGetModification(self.handle, offset) }
2624 }
2625
2626 fn start(&self) -> u64 {
2627 unsafe { BNGetStartOffset(self.handle) }
2628 }
2629
2630 fn len(&self) -> u64 {
2631 unsafe { BNGetViewLength(self.handle) }
2632 }
2633
2634 fn executable(&self) -> bool {
2635 unsafe { BNIsExecutableView(self.handle) }
2636 }
2637
2638 fn relocatable(&self) -> bool {
2639 unsafe { BNIsRelocatable(self.handle) }
2640 }
2641
2642 fn entry_point(&self) -> u64 {
2643 unsafe { BNGetEntryPoint(self.handle) }
2644 }
2645
2646 fn default_endianness(&self) -> Endianness {
2647 unsafe { BNGetDefaultEndianness(self.handle) }
2648 }
2649
2650 fn address_size(&self) -> usize {
2651 unsafe { BNGetViewAddressSize(self.handle) }
2652 }
2653}
2654
2655unsafe impl RefCountable for BinaryView {
2656 unsafe fn inc_ref(handle: &Self) -> Ref<Self> {
2657 Ref::new(Self {
2658 handle: BNNewViewReference(handle.handle),
2659 })
2660 }
2661
2662 unsafe fn dec_ref(handle: &Self) {
2663 BNFreeBinaryView(handle.handle);
2664 }
2665}
2666
2667impl AsRef<BinaryView> for BinaryView {
2668 fn as_ref(&self) -> &Self {
2669 self
2670 }
2671}
2672
2673impl ToOwned for BinaryView {
2674 type Owned = Ref<Self>;
2675
2676 fn to_owned(&self) -> Self::Owned {
2677 unsafe { RefCountable::inc_ref(self) }
2678 }
2679}
2680
2681unsafe impl Send for BinaryView {}
2682unsafe impl Sync for BinaryView {}
2683
2684impl std::fmt::Debug for BinaryView {
2685 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
2686 f.debug_struct("BinaryView")
2687 .field("view_type", &self.view_type())
2688 .field("file", &self.file())
2689 .field("original_image_base", &self.original_image_base())
2690 .field("start", &self.start())
2691 .field("end", &self.end())
2692 .field("len", &self.len())
2693 .field("default_platform", &self.default_platform())
2694 .field("default_arch", &self.default_arch())
2695 .field("default_endianness", &self.default_endianness())
2696 .field("entry_point", &self.entry_point())
2697 .field(
2698 "entry_point_functions",
2699 &self.entry_point_functions().to_vec(),
2700 )
2701 .field("address_size", &self.address_size())
2702 .field("sections", &self.sections().to_vec())
2703 .field("segments", &self.segments().to_vec())
2704 .finish()
2705 }
2706}
2707
2708pub trait BinaryViewEventHandler: 'static + Sync {
2709 fn on_event(&self, binary_view: &BinaryView);
2710}
2711
2712pub fn register_binary_view_event<Handler>(event_type: BinaryViewEventType, handler: Handler)
2742where
2743 Handler: BinaryViewEventHandler,
2744{
2745 unsafe extern "C" fn on_event<Handler: BinaryViewEventHandler>(
2746 ctx: *mut ::std::os::raw::c_void,
2747 view: *mut BNBinaryView,
2748 ) {
2749 ffi_wrap!("EventHandler::on_event", {
2750 let context = unsafe { &*(ctx as *const Handler) };
2751 context.on_event(&BinaryView::ref_from_raw(BNNewViewReference(view)));
2752 })
2753 }
2754
2755 let boxed = Box::new(handler);
2756 let raw = Box::into_raw(boxed);
2757
2758 unsafe {
2759 BNRegisterBinaryViewEvent(
2760 event_type,
2761 Some(on_event::<Handler>),
2762 raw as *mut ::std::os::raw::c_void,
2763 );
2764 }
2765}
2766
2767#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
2768pub struct CommentReference {
2769 pub start: u64,
2770}
2771
2772impl From<u64> for CommentReference {
2773 fn from(start: u64) -> Self {
2774 Self { start }
2775 }
2776}
2777
2778impl CoreArrayProvider for CommentReference {
2779 type Raw = u64;
2780 type Context = ();
2781 type Wrapped<'a> = Self;
2782}
2783
2784unsafe impl CoreArrayProviderInner for CommentReference {
2785 unsafe fn free(raw: *mut Self::Raw, _count: usize, _context: &Self::Context) {
2786 BNFreeAddressList(raw)
2787 }
2788
2789 unsafe fn wrap_raw<'a>(raw: &'a Self::Raw, _context: &'a Self::Context) -> Self::Wrapped<'a> {
2790 Self::from(*raw)
2791 }
2792}
2793
2794#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
2795pub struct StringReference {
2796 pub ty: StringType,
2797 pub start: u64,
2798 pub length: usize,
2799}
2800
2801impl From<BNStringReference> for StringReference {
2802 fn from(raw: BNStringReference) -> Self {
2803 Self {
2804 ty: raw.type_,
2805 start: raw.start,
2806 length: raw.length,
2807 }
2808 }
2809}
2810
2811impl From<StringReference> for BNStringReference {
2812 fn from(raw: StringReference) -> Self {
2813 Self {
2814 type_: raw.ty,
2815 start: raw.start,
2816 length: raw.length,
2817 }
2818 }
2819}
2820
2821impl CoreArrayProvider for StringReference {
2822 type Raw = BNStringReference;
2823 type Context = ();
2824 type Wrapped<'a> = Self;
2825}
2826
2827unsafe impl CoreArrayProviderInner for StringReference {
2828 unsafe fn free(raw: *mut Self::Raw, _count: usize, _context: &Self::Context) {
2829 BNFreeStringReferenceList(raw)
2830 }
2831
2832 unsafe fn wrap_raw<'a>(raw: &'a Self::Raw, _context: &'a Self::Context) -> Self::Wrapped<'a> {
2833 Self::from(*raw)
2834 }
2835}
2836
2837#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
2838pub struct AddressRange {
2839 pub start: u64,
2840 pub end: u64,
2841}
2842
2843impl From<BNAddressRange> for AddressRange {
2844 fn from(raw: BNAddressRange) -> Self {
2845 Self {
2846 start: raw.start,
2847 end: raw.end,
2848 }
2849 }
2850}
2851
2852impl From<AddressRange> for BNAddressRange {
2853 fn from(raw: AddressRange) -> Self {
2854 Self {
2855 start: raw.start,
2856 end: raw.end,
2857 }
2858 }
2859}
2860
2861impl CoreArrayProvider for AddressRange {
2862 type Raw = BNAddressRange;
2863 type Context = ();
2864 type Wrapped<'a> = Self;
2865}
2866
2867unsafe impl CoreArrayProviderInner for AddressRange {
2868 unsafe fn free(raw: *mut Self::Raw, _count: usize, _context: &Self::Context) {
2869 BNFreeAddressRanges(raw);
2870 }
2871
2872 unsafe fn wrap_raw<'a>(raw: &'a Self::Raw, _context: &'a Self::Context) -> Self::Wrapped<'a> {
2873 Self::from(*raw)
2874 }
2875}