Skip to content

Commit d35ce9b

Browse files
committed
[Rust] Misc documentation and cleanup
1 parent b2ed663 commit d35ce9b

File tree

17 files changed

+242
-340
lines changed

17 files changed

+242
-340
lines changed

plugins/bntl_utils/src/dump.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,8 +47,7 @@ impl TILDump {
4747

4848
pub fn dump(&self, type_lib: &TypeLibrary) -> Result<String, TILDumpError> {
4949
let empty_file = FileMetadata::new();
50-
let empty_bv = BinaryView::from_data(&empty_file, &[])
51-
.map_err(|_| TILDumpError::ViewCreationFailed)?;
50+
let empty_bv = BinaryView::from_data(&empty_file, &[]);
5251

5352
let type_lib_plats = type_lib.platform_names();
5453
let platform_name = type_lib_plats

plugins/svd/tests/mapper.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ fn insta_snapshots() {
1818
let path = out_dir.join(file_name);
1919
let svd_str = std::fs::read_to_string(&path).expect("Failed to read svd file");
2020
let device = svd_parser::parse(&svd_str).expect("Failed to parse svd file");
21-
let view = BinaryView::from_data(&FileMetadata::new(), &[]).expect("Failed to create view");
21+
let view = BinaryView::from_data(&FileMetadata::new(), &[]);
2222
let address_size = view.address_size();
2323
DeviceMapper::new(LoadSettings::default(), address_size, device).map_to_view(&view);
2424

@@ -46,7 +46,7 @@ fn test_bitfield_unions() {
4646
let path = out_dir.join("ARM_Sample.svd");
4747
let svd_str = std::fs::read_to_string(&path).expect("Failed to read svd file");
4848
let device = svd_parser::parse(&svd_str).expect("Failed to parse svd file");
49-
let view = BinaryView::from_data(&FileMetadata::new(), &[]).expect("Failed to create view");
49+
let view = BinaryView::from_data(&FileMetadata::new(), &[]);
5050
let address_size = view.address_size();
5151
let mapper = DeviceMapper::new(LoadSettings::default(), address_size, device.clone());
5252

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
}

plugins/warp/tests/matcher.rs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -33,8 +33,7 @@ const MOCK_FUNCTION_BYTES: &[u8] = &[
3333

3434
fn create_mock_bn_function(_session: &Session) -> Ref<BNFunction> {
3535
let file = FileMetadata::new();
36-
let view =
37-
BinaryView::from_data(&file, MOCK_FUNCTION_BYTES).expect("Failed to create mock view");
36+
let view = BinaryView::from_data(&file, MOCK_FUNCTION_BYTES);
3837
let platform = Platform::by_name("x86").unwrap();
3938
// Add the constraint symbol so that the matcher picks it up, so we can test constraint matching.
4039
let constraint_symbol =
@@ -160,7 +159,7 @@ fn test_add_type_to_view() {
160159

161160
let _session = Session::new().expect("Failed to create session");
162161
let file = FileMetadata::new();
163-
let view = BinaryView::from_data(&file, &[]).expect("Failed to create view");
162+
let view = BinaryView::from_data(&file, &[]);
164163
let arch = CoreArchitecture::by_name("x86").expect("Failed to get architecture");
165164

166165
// Try and add a NTR to the view, this should also add the referenced struct type.

rust/examples/dump_type_library.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,8 +36,7 @@ fn main() {
3636
type_lib_header_path
3737
);
3838
let type_printer = CoreTypePrinter::default();
39-
let empty_bv =
40-
BinaryView::from_data(&FileMetadata::new(), &[]).expect("Failed to create empty view");
39+
let empty_bv = BinaryView::from_data(&FileMetadata::new(), &[]);
4140
let printed_types = type_printer
4241
.print_all_types(
4342
all_types,

rust/src/binary_view.rs

Lines changed: 53 additions & 54 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
}
@@ -546,8 +548,6 @@ pub trait BinaryViewExt: BinaryViewBase {
546548
}
547549

548550
/// The highest address in the view.
549-
///
550-
/// NOTE: If operating within a [`Workflow`], consider using [`AnalysisContext::end`].
551551
fn end(&self) -> u64 {
552552
unsafe { BNGetEndOffset(self.as_ref().handle) }
553553
}
@@ -2454,6 +2454,26 @@ pub trait BinaryViewExt: BinaryViewBase {
24542454

24552455
impl<T: BinaryViewBase> BinaryViewExt for T {}
24562456

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

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.
2499+
/// Construct the raw binary view from the given metadata.
2500+
///
2501+
/// Before calling this, make sure you have a valid file path set for the [`FileMetadata`]. It is
2502+
/// required that the [`FileMetadata::file_path`] exist in the local filesystem.
24822503
pub fn from_metadata(meta: &FileMetadata) -> Result<Ref<Self>> {
24832504
if !meta.file_path().exists() {
24842505
return Err(());
24852506
}
24862507
let file = meta.file_path().to_cstr();
24872508
let handle =
24882509
unsafe { BNCreateBinaryDataViewFromFilename(meta.handle, file.as_ptr() as *mut _) };
2489-
24902510
if handle.is_null() {
24912511
return Err(());
24922512
}
2493-
24942513
unsafe { Ok(Ref::new(Self { handle })) }
24952514
}
24962515

@@ -2503,29 +2522,34 @@ impl BinaryView {
25032522
Self::from_metadata(meta)
25042523
}
25052524

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

2519-
pub fn from_data(meta: &FileMetadata, data: &[u8]) -> Result<Ref<Self>> {
2541+
/// Construct the raw binary view from the given `data` and metadata.
2542+
///
2543+
/// The data will be copied into the view, so the caller does not need to keep the data alive.
2544+
pub fn from_data(meta: &FileMetadata, data: &[u8]) -> Ref<Self> {
25202545
let handle = unsafe {
25212546
BNCreateBinaryDataViewFromData(meta.handle, data.as_ptr() as *mut _, data.len())
25222547
};
2523-
2524-
if handle.is_null() {
2525-
return Err(());
2526-
}
2527-
2528-
unsafe { Ok(Ref::new(Self { handle })) }
2548+
assert!(
2549+
!handle.is_null(),
2550+
"BNCreateBinaryDataViewFromData should always succeed"
2551+
);
2552+
unsafe { Ref::new(Self { handle }) }
25292553
}
25302554

25312555
/// Save the original binary file to the provided `file_path` along with any modifications.
@@ -2571,45 +2595,26 @@ impl BinaryViewBase for BinaryView {
25712595
unsafe { BNRemoveViewData(self.handle, offset, len as u64) }
25722596
}
25732597

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`].
25772598
fn offset_valid(&self, offset: u64) -> bool {
25782599
unsafe { BNIsValidOffset(self.handle, offset) }
25792600
}
25802601

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`].
25842602
fn offset_readable(&self, offset: u64) -> bool {
25852603
unsafe { BNIsOffsetReadable(self.handle, offset) }
25862604
}
25872605

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`].
25912606
fn offset_writable(&self, offset: u64) -> bool {
25922607
unsafe { BNIsOffsetWritable(self.handle, offset) }
25932608
}
25942609

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`].
25982610
fn offset_executable(&self, offset: u64) -> bool {
25992611
unsafe { BNIsOffsetExecutable(self.handle, offset) }
26002612
}
26012613

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`].
26052614
fn offset_backed_by_file(&self, offset: u64) -> bool {
26062615
unsafe { BNIsOffsetBackedByFile(self.handle, offset) }
26072616
}
26082617

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`].
26132618
fn next_valid_offset_after(&self, offset: u64) -> u64 {
26142619
unsafe { BNGetNextValidOffset(self.handle, offset) }
26152620
}
@@ -2618,16 +2623,10 @@ impl BinaryViewBase for BinaryView {
26182623
unsafe { BNGetModification(self.handle, offset) }
26192624
}
26202625

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

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

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)