Skip to content

Commit f67d8c2

Browse files
committed
[Rust] Misc documentation and cleanup
1 parent 15a99d4 commit f67d8c2

9 files changed

Lines changed: 225 additions & 312 deletions

File tree

plugins/warp/src/processor.rs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ use binaryninja::rc::{Guard, Ref};
2929
use crate::cache::cached_type_references;
3030
use crate::convert::platform_to_target;
3131
use crate::{build_function, INCLUDE_TAG_ICON, INCLUDE_TAG_NAME};
32+
use binaryninja::file_metadata::{SaveOption, SaveSettings};
3233
use warp::chunk::{Chunk, ChunkKind, CompressionType};
3334
use warp::r#type::chunk::TypeChunk;
3435
use warp::signature::chunk::SignatureChunk;
@@ -645,7 +646,11 @@ impl WarpFileProcessor {
645646
if !view.file().is_database_backed() {
646647
// Update the cache.
647648
tracing::debug!("Saving analysis database to {:?}", file_cache_path);
648-
if !view.file().create_database(&file_cache_path) {
649+
let save_settings = SaveSettings::new().with_option(SaveOption::RemoveUndoData);
650+
if !view
651+
.file()
652+
.create_database(&file_cache_path, &save_settings)
653+
{
649654
// TODO: We might want to error here...
650655
tracing::warn!("Failed to save analysis database to {:?}", file_cache_path);
651656
}

rust/src/binary_view.rs

Lines changed: 47 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -12,14 +12,7 @@
1212
// See the License for the specific language governing permissions and
1313
// limitations under the License.
1414

15-
//! A view on binary data and queryable interface of a binary file.
16-
//!
17-
//! One key job of BinaryView is file format parsing which allows Binary Ninja to read, write,
18-
//! insert, remove portions of the file given a virtual address.
19-
//!
20-
//! For the purposes of this documentation we define a virtual address as the memory address that
21-
//! the various pieces of the physical file will be loaded at.
22-
//! TODO : Mirror the Python docs for this
15+
//! A view on binary data and queryable interface of a binary files analysis.
2316
2417
use binaryninjacore_sys::*;
2518

@@ -104,6 +97,7 @@ pub trait BinaryViewBase: AsRef<BinaryView> {
10497
0
10598
}
10699

100+
/// Check if the offset is valid for the current view.
107101
fn offset_valid(&self, offset: u64) -> bool {
108102
let mut buf = [0u8; 1];
109103

@@ -112,22 +106,28 @@ pub trait BinaryViewBase: AsRef<BinaryView> {
112106
self.as_ref().read(&mut buf[..], offset) == buf.len()
113107
}
114108

109+
/// Check if the offset is readable for the current view.
115110
fn offset_readable(&self, offset: u64) -> bool {
116111
self.offset_valid(offset)
117112
}
118113

114+
/// Check if the offset is writable for the current view.
119115
fn offset_writable(&self, offset: u64) -> bool {
120116
self.offset_valid(offset)
121117
}
122118

119+
/// Check if the offset is executable for the current view.
123120
fn offset_executable(&self, offset: u64) -> bool {
124121
self.offset_valid(offset)
125122
}
126123

124+
/// Check if the offset is backed by the original file and not added after the fact.
127125
fn offset_backed_by_file(&self, offset: u64) -> bool {
128126
self.offset_valid(offset)
129127
}
130128

129+
/// Get the next valid offset after the provided `offset`, useful if you need to iterate over all
130+
/// readable offsets in the view.
131131
fn next_valid_offset_after(&self, offset: u64) -> u64 {
132132
let start = self.as_ref().start();
133133

@@ -138,15 +138,17 @@ pub trait BinaryViewBase: AsRef<BinaryView> {
138138
}
139139
}
140140

141-
#[allow(unused)]
142-
fn modification_status(&self, offset: u64) -> ModificationStatus {
141+
/// Whether the data at the given `offset` been modified (patched).
142+
fn modification_status(&self, _offset: u64) -> ModificationStatus {
143143
ModificationStatus::Original
144144
}
145145

146+
/// The lowest address in the view.
146147
fn start(&self) -> u64 {
147148
0
148149
}
149150

151+
/// The length of the view.
150152
fn len(&self) -> u64 {
151153
0
152154
}
@@ -2454,6 +2456,26 @@ pub trait BinaryViewExt: BinaryViewBase {
24542456

24552457
impl<T: BinaryViewBase> BinaryViewExt for T {}
24562458

2459+
/// Represents the "whole view" of the binary and its analysis.
2460+
///
2461+
/// Analysis information:
2462+
///
2463+
/// - [`BinaryView::functions`]
2464+
/// - [`BinaryView::data_variables`]
2465+
/// - [`BinaryView::strings`]
2466+
///
2467+
/// Annotation information:
2468+
///
2469+
/// - [`BinaryView::symbols`]
2470+
/// - [`BinaryView::tags_all_scopes`]
2471+
/// - [`BinaryView::comments`]
2472+
///
2473+
/// Data representation and binary information:
2474+
///
2475+
/// - [`BinaryView::types`]
2476+
/// - [`BinaryView::segments`]
2477+
/// - [`BinaryView::sections`]
2478+
///
24572479
/// # Cleaning up
24582480
///
24592481
/// [`BinaryView`] has a cyclic relationship with the associated [`FileMetadata`], each holds a strong
@@ -2476,21 +2498,20 @@ impl BinaryView {
24762498
Ref::new(Self { handle })
24772499
}
24782500

2479-
/// Construct the raw binary view from the given metadata. Before calling this make sure you have
2480-
/// a valid file path set for the [`FileMetadata`]. It is required that the [`FileMetadata::file_path`]
2481-
/// exist on the local filesystem.
2501+
/// Construct the raw binary view from the given metadata.
2502+
///
2503+
/// Before calling this, make sure you have a valid file path set for the [`FileMetadata`]. It is
2504+
/// required that the [`FileMetadata::file_path`] exist in the local filesystem.
24822505
pub fn from_metadata(meta: &FileMetadata) -> Result<Ref<Self>> {
24832506
if !meta.file_path().exists() {
24842507
return Err(());
24852508
}
24862509
let file = meta.file_path().to_cstr();
24872510
let handle =
24882511
unsafe { BNCreateBinaryDataViewFromFilename(meta.handle, file.as_ptr() as *mut _) };
2489-
24902512
if handle.is_null() {
24912513
return Err(());
24922514
}
2493-
24942515
unsafe { Ok(Ref::new(Self { handle })) }
24952516
}
24962517

@@ -2503,28 +2524,32 @@ impl BinaryView {
25032524
Self::from_metadata(meta)
25042525
}
25052526

2506-
pub fn from_accessor<A: Accessor>(
2527+
// TODO: Provide an API that manages the lifetime of the accessor and the view.
2528+
/// Construct the raw binary view from the given `accessor` and metadata.
2529+
///
2530+
/// It is the responsibility of the caller to keep the accessor alive for the lifetime of the view;
2531+
/// because of this, we mark the function as unsafe.
2532+
pub unsafe fn from_accessor<A: Accessor>(
25072533
meta: &FileMetadata,
2508-
file: &mut FileAccessor<A>,
2534+
accessor: &mut FileAccessor<A>,
25092535
) -> Result<Ref<Self>> {
2510-
let handle = unsafe { BNCreateBinaryDataViewFromFile(meta.handle, &mut file.raw) };
2511-
2536+
let handle = unsafe { BNCreateBinaryDataViewFromFile(meta.handle, &mut accessor.raw) };
25122537
if handle.is_null() {
25132538
return Err(());
25142539
}
2515-
25162540
unsafe { Ok(Ref::new(Self { handle })) }
25172541
}
25182542

2543+
/// Construct the raw binary view from the given `data` and metadata.
2544+
///
2545+
/// The data will be copied into the view, so the caller does not need to keep the data alive.
25192546
pub fn from_data(meta: &FileMetadata, data: &[u8]) -> Result<Ref<Self>> {
25202547
let handle = unsafe {
25212548
BNCreateBinaryDataViewFromData(meta.handle, data.as_ptr() as *mut _, data.len())
25222549
};
2523-
25242550
if handle.is_null() {
25252551
return Err(());
25262552
}
2527-
25282553
unsafe { Ok(Ref::new(Self { handle })) }
25292554
}
25302555

@@ -2571,45 +2596,26 @@ impl BinaryViewBase for BinaryView {
25712596
unsafe { BNRemoveViewData(self.handle, offset, len as u64) }
25722597
}
25732598

2574-
/// Check if the offset is valid for the current view.
2575-
///
2576-
/// NOTE: If operating within a [`Workflow`], consider using [`AnalysisContext::is_offset_valid`].
25772599
fn offset_valid(&self, offset: u64) -> bool {
25782600
unsafe { BNIsValidOffset(self.handle, offset) }
25792601
}
25802602

2581-
/// Check if the offset is readable for the current view.
2582-
///
2583-
/// NOTE: If operating within a [`Workflow`], consider using [`AnalysisContext::is_offset_valid`].
25842603
fn offset_readable(&self, offset: u64) -> bool {
25852604
unsafe { BNIsOffsetReadable(self.handle, offset) }
25862605
}
25872606

2588-
/// Check if the offset is writable for the current view.
2589-
///
2590-
/// NOTE: If operating within a [`Workflow`], consider using [`AnalysisContext::is_offset_writable`].
25912607
fn offset_writable(&self, offset: u64) -> bool {
25922608
unsafe { BNIsOffsetWritable(self.handle, offset) }
25932609
}
25942610

2595-
/// Check if the offset is executable for the current view.
2596-
///
2597-
/// NOTE: If operating within a [`Workflow`], consider using [`AnalysisContext::is_offset_executable`].
25982611
fn offset_executable(&self, offset: u64) -> bool {
25992612
unsafe { BNIsOffsetExecutable(self.handle, offset) }
26002613
}
26012614

2602-
/// Check if the offset is backed by the original file and not added after the fact.
2603-
///
2604-
/// NOTE: If operating within a [`Workflow`], consider using [`AnalysisContext::is_offset_backed_by_file`].
26052615
fn offset_backed_by_file(&self, offset: u64) -> bool {
26062616
unsafe { BNIsOffsetBackedByFile(self.handle, offset) }
26072617
}
26082618

2609-
/// Get the next valid offset after the provided `offset`, useful if you need to iterate over all
2610-
/// readable offsets in the view.
2611-
///
2612-
/// NOTE: If operating within a [`Workflow`], consider using [`AnalysisContext::next_valid_offset`].
26132619
fn next_valid_offset_after(&self, offset: u64) -> u64 {
26142620
unsafe { BNGetNextValidOffset(self.handle, offset) }
26152621
}
@@ -2618,16 +2624,10 @@ impl BinaryViewBase for BinaryView {
26182624
unsafe { BNGetModification(self.handle, offset) }
26192625
}
26202626

2621-
/// The lowest address in the view.
2622-
///
2623-
/// NOTE: If operating within a [`Workflow`], consider using [`AnalysisContext::start`].
26242627
fn start(&self) -> u64 {
26252628
unsafe { BNGetStartOffset(self.handle) }
26262629
}
26272630

2628-
/// The length of the view, lowest to highest address.
2629-
///
2630-
/// NOTE: If operating within a [`Workflow`], consider using [`AnalysisContext::length`].
26312631
fn len(&self) -> u64 {
26322632
unsafe { BNGetViewLength(self.handle) }
26332633
}

rust/src/custom_binary_view.rs

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -178,12 +178,23 @@ where
178178
}
179179

180180
pub trait BinaryViewTypeBase: AsRef<BinaryViewType> {
181+
/// Is this [`BinaryViewType`] valid for the given the raw [`BinaryView`]?
182+
///
183+
/// Typical implementations will read the magic bytes (e.g. 'MZ'), this is a performance-sensitive
184+
/// path so prefer inexpensive checks rather than comprehensive ones.
181185
fn is_valid_for(&self, data: &BinaryView) -> bool;
182186

187+
/// Is this [`BinaryViewType`] deprecated and should not be used?
188+
///
189+
/// We specify this such that the view type may still be used by existing databases, but not
190+
/// newly created views.
183191
fn is_deprecated(&self) -> bool {
184192
false
185193
}
186194

195+
/// Is this [`BinaryViewType`] able to be loaded forcefully?
196+
///
197+
/// If so, it will be shown in the drop-down when a user opens a file with options.
187198
fn is_force_loadable(&self) -> bool {
188199
false
189200
}
@@ -319,6 +330,9 @@ pub trait BinaryViewTypeExt: BinaryViewTypeBase {
319330

320331
impl<T: BinaryViewTypeBase> BinaryViewTypeExt for T {}
321332

333+
/// A [`BinaryViewType`] acts as a factory for [`BinaryView`] objects.
334+
///
335+
/// Each file format will have its own type, such as PE, ELF, or Mach-O.
322336
#[derive(Copy, Clone, PartialEq, Eq, Hash)]
323337
pub struct BinaryViewType {
324338
pub handle: *mut BNBinaryViewType,
@@ -338,7 +352,9 @@ impl BinaryViewType {
338352
}
339353
}
340354

341-
pub fn list_valid_types_for(data: &BinaryView) -> Array<BinaryViewType> {
355+
/// Enumerates all view types and checks to see if the given raw [`BinaryView`] is valid,
356+
/// returning only those that are.
357+
pub fn valid_types_for_data(data: &BinaryView) -> Array<BinaryViewType> {
342358
unsafe {
343359
let mut count: usize = 0;
344360
let types = BNGetBinaryViewTypesForData(data.handle, &mut count as *mut _);

0 commit comments

Comments
 (0)