Skip to content

Commit 16e8ad4

Browse files
committed
More rust cleanup
- Refactored BinaryReader and BinaryWriter - Added some warnings to high_level_il and medium_level_il modules that they are unstable - Add BinaryReader and BinaryWriter tests - Changed BinaryView len to return u64 (that is what the core returns) - Misc formatting changes - Remove extern uses in lib.rs
1 parent 94bdf81 commit 16e8ad4

File tree

18 files changed

+397
-194
lines changed

18 files changed

+397
-194
lines changed

plugins/idb_import/src/types.rs

Lines changed: 5 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,11 @@ use std::collections::HashMap;
33
use anyhow::{anyhow, Result};
44
use binaryninja::architecture::CoreArchitecture;
55
use binaryninja::binary_view::{BinaryView, BinaryViewExt};
6-
use binaryninja::binaryninjacore_sys::{BNMemberAccess, BNMemberScope};
76
use binaryninja::confidence::Conf;
87
use binaryninja::rc::Ref;
98
use binaryninja::types::{
10-
EnumerationBuilder, FunctionParameter, StructureBuilder, StructureType, Type,
9+
EnumerationBuilder, FunctionParameter, MemberAccess, MemberScope, StructureBuilder,
10+
StructureType, Type,
1111
};
1212
use idb_rs::til::{
1313
array::Array as TILArray, function::Function as TILFunction, r#enum::Enum as TILEnum,
@@ -313,12 +313,7 @@ impl<F: Fn(usize, usize) -> Result<(), ()>> TranslateIDBTypes<'_, F> {
313313
format!("bitfield_{}_{}", offset + start_idx, offset + (i - 1))
314314
};
315315
let field = field_from_bytes(bytes);
316-
struct_builder.append(
317-
&field,
318-
name,
319-
BNMemberAccess::NoAccess,
320-
BNMemberScope::NoScope,
321-
);
316+
struct_builder.append(&field, name, MemberAccess::NoAccess, MemberScope::NoScope);
322317
};
323318

324319
for (i, member) in members {
@@ -402,7 +397,7 @@ impl<F: Fn(usize, usize) -> Result<(), ()>> TranslateIDBTypes<'_, F> {
402397
.as_ref()
403398
.map(|name| String::from_utf8_lossy(name).to_string())
404399
.unwrap_or_else(|| format!("member_{i}"));
405-
structure.append(&mem, name, BNMemberAccess::NoAccess, BNMemberScope::NoScope);
400+
structure.append(&mem, name, MemberAccess::NoAccess, MemberScope::NoScope);
406401
}
407402
if let Some(start_idx) = first_bitfield_seq {
408403
let members_bitrange = &members[start_idx..];
@@ -452,7 +447,7 @@ impl<F: Fn(usize, usize) -> Result<(), ()>> TranslateIDBTypes<'_, F> {
452447
.as_ref()
453448
.map(|name| String::from_utf8_lossy(name).to_string())
454449
.unwrap_or_else(|| format!("member_{i}"));
455-
structure.append(&mem, name, BNMemberAccess::NoAccess, BNMemberScope::NoScope);
450+
structure.append(&mem, name, MemberAccess::NoAccess, MemberScope::NoScope);
456451
}
457452
let str_ref = structure.finalize();
458453

plugins/pdb-ng/src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -552,7 +552,7 @@ impl CustomDebugInfoParser for PDBParser {
552552
) -> bool {
553553
if is_pdb(debug_file) {
554554
match self.load_from_file(
555-
&debug_file.read_vec(0, debug_file.len()),
555+
&debug_file.read_vec(0, debug_file.len() as usize),
556556
debug_info,
557557
view,
558558
&progress,

rust/examples/decompile.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use binaryninja::binary_view::{BinaryView, BinaryViewBase, BinaryViewExt};
22
use binaryninja::disassembly::{DisassemblyOption, DisassemblySettings};
33
use binaryninja::function::Function;
4-
use binaryninja::linear_view::{LinearViewCursor, LinearViewObject};
4+
use binaryninja::linear_view::LinearViewObject;
55

66
fn decompile_to_c(view: &BinaryView, func: &Function) {
77
let settings = DisassemblySettings::new();
@@ -13,7 +13,7 @@ fn decompile_to_c(view: &BinaryView, func: &Function) {
1313

1414
let linear_view = LinearViewObject::language_representation(view, &settings, "Pseudo C");
1515

16-
let mut cursor = LinearViewCursor::new(&linear_view);
16+
let mut cursor = linear_view.create_cursor();
1717
cursor.seek_to_address(func.highest_address());
1818

1919
let last = view.get_next_linear_disassembly_lines(&mut cursor.duplicate());

rust/src/binary_reader.rs

Lines changed: 90 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -16,59 +16,95 @@
1616
1717
use binaryninjacore_sys::*;
1818

19-
use crate::binary_view::BinaryView;
19+
use crate::binary_view::{BinaryView, BinaryViewBase};
2020
use crate::Endianness;
2121

22-
use std::io::{Read, Seek, SeekFrom};
22+
use crate::rc::Ref;
23+
use std::io::{ErrorKind, Read, Seek, SeekFrom};
2324

2425
pub struct BinaryReader {
26+
view: Ref<BinaryView>,
2527
handle: *mut BNBinaryReader,
2628
}
2729

2830
impl BinaryReader {
29-
pub fn new(view: &BinaryView, endian: Endianness) -> Self {
31+
pub fn new(view: &BinaryView) -> Self {
3032
let handle = unsafe { BNCreateBinaryReader(view.handle) };
31-
unsafe {
32-
BNSetBinaryReaderEndianness(handle, endian);
33+
Self {
34+
view: view.to_owned(),
35+
handle,
3336
}
34-
Self { handle }
3537
}
3638

37-
pub fn endian(&self) -> Endianness {
39+
pub fn new_with_opts(view: &BinaryView, options: &BinaryReaderOptions) -> Self {
40+
let mut reader = Self::new(view);
41+
if let Some(endianness) = options.endianness {
42+
reader.set_endianness(endianness);
43+
}
44+
// Set the virtual base before we seek.
45+
if let Some(virtual_base) = options.virtual_base {
46+
reader.set_virtual_base(virtual_base);
47+
}
48+
if let Some(address) = options.address {
49+
reader.seek_to_offset(address);
50+
}
51+
reader
52+
}
53+
54+
pub fn endianness(&self) -> Endianness {
3855
unsafe { BNGetBinaryReaderEndianness(self.handle) }
3956
}
4057

41-
pub fn set_endian(&self, endian: Endianness) {
42-
unsafe { BNSetBinaryReaderEndianness(self.handle, endian) }
58+
pub fn set_endianness(&mut self, endianness: Endianness) {
59+
unsafe { BNSetBinaryReaderEndianness(self.handle, endianness) }
60+
}
61+
62+
pub fn virtual_base(&self) -> u64 {
63+
unsafe { BNGetBinaryReaderVirtualBase(self.handle) }
64+
}
65+
66+
pub fn set_virtual_base(&mut self, virtual_base_addr: u64) {
67+
unsafe { BNSetBinaryReaderVirtualBase(self.handle, virtual_base_addr) }
68+
}
69+
70+
/// Prefer using [crate::binary_reader::BinaryReader::seek] over this.
71+
pub fn seek_to_offset(&mut self, offset: u64) {
72+
unsafe { BNSeekBinaryReader(self.handle, offset) }
73+
}
74+
75+
/// Prefer using [crate::binary_reader::BinaryReader::seek] over this.
76+
pub fn seek_to_relative_offset(&mut self, offset: i64) {
77+
unsafe { BNSeekBinaryReaderRelative(self.handle, offset) }
4378
}
4479

4580
pub fn offset(&self) -> u64 {
4681
unsafe { BNGetReaderPosition(self.handle) }
4782
}
4883

49-
pub fn eof(&self) -> bool {
84+
/// Are we at the end of the file?
85+
pub fn is_eof(&self) -> bool {
5086
unsafe { BNIsEndOfFile(self.handle) }
5187
}
5288
}
5389

5490
impl Seek for BinaryReader {
5591
/// Seek to the specified position.
56-
///
57-
/// # Errors
58-
/// Seeking relative to [SeekFrom::End] is unsupported and will return an error.
5992
fn seek(&mut self, pos: SeekFrom) -> std::io::Result<u64> {
60-
unsafe {
61-
match pos {
62-
SeekFrom::Current(offset) => BNSeekBinaryReaderRelative(self.handle, offset),
63-
SeekFrom::Start(offset) => BNSeekBinaryReader(self.handle, offset),
64-
_ => {
65-
return Err(std::io::Error::new(
66-
std::io::ErrorKind::Unsupported,
67-
"Cannot seek end of BinaryReader",
68-
))
69-
}
70-
};
71-
}
93+
match pos {
94+
SeekFrom::Current(offset) => self.seek_to_relative_offset(offset),
95+
SeekFrom::Start(offset) => self.seek_to_offset(offset),
96+
SeekFrom::End(end_offset) => {
97+
let offset =
98+
self.view
99+
.len()
100+
.checked_add_signed(end_offset)
101+
.ok_or(std::io::Error::new(
102+
ErrorKind::Other,
103+
"Seeking from end overflowed",
104+
))?;
105+
self.seek_to_offset(offset);
106+
}
107+
};
72108

73109
Ok(self.offset())
74110
}
@@ -81,10 +117,7 @@ impl Read for BinaryReader {
81117
let result = unsafe { BNReadData(self.handle, buf.as_mut_ptr() as *mut _, len) };
82118

83119
if !result {
84-
Err(std::io::Error::new(
85-
std::io::ErrorKind::Other,
86-
"Read out of bounds",
87-
))
120+
Err(std::io::Error::new(ErrorKind::Other, "Read out of bounds"))
88121
} else {
89122
Ok(len)
90123
}
@@ -99,3 +132,31 @@ impl Drop for BinaryReader {
99132

100133
unsafe impl Sync for BinaryReader {}
101134
unsafe impl Send for BinaryReader {}
135+
136+
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
137+
pub struct BinaryReaderOptions {
138+
endianness: Option<Endianness>,
139+
virtual_base: Option<u64>,
140+
address: Option<u64>,
141+
}
142+
143+
impl BinaryReaderOptions {
144+
pub fn new() -> Self {
145+
Self::default()
146+
}
147+
148+
pub fn with_endianness(mut self, endian: Endianness) -> Self {
149+
self.endianness = Some(endian);
150+
self
151+
}
152+
153+
pub fn with_virtual_base(mut self, virtual_base_addr: u64) -> Self {
154+
self.virtual_base = Some(virtual_base_addr);
155+
self
156+
}
157+
158+
pub fn with_address(mut self, address: u64) -> Self {
159+
self.address = Some(address);
160+
self
161+
}
162+
}

rust/src/binary_view.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,7 @@ pub trait BinaryViewBase: AsRef<BinaryView> {
129129
0
130130
}
131131

132-
fn len(&self) -> usize {
132+
fn len(&self) -> u64 {
133133
0
134134
}
135135

@@ -1937,8 +1937,8 @@ impl BinaryViewBase for BinaryView {
19371937
unsafe { BNGetStartOffset(self.handle) }
19381938
}
19391939

1940-
fn len(&self) -> usize {
1941-
unsafe { BNGetViewLength(self.handle) as usize }
1940+
fn len(&self) -> u64 {
1941+
unsafe { BNGetViewLength(self.handle) }
19421942
}
19431943

19441944
fn executable(&self) -> bool {

rust/src/binary_writer.rs

Lines changed: 67 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -16,30 +16,51 @@
1616
1717
use binaryninjacore_sys::*;
1818

19-
use crate::binary_view::BinaryView;
19+
use crate::binary_view::{BinaryView, BinaryViewBase};
2020
use crate::Endianness;
2121

22-
use std::io::{Seek, SeekFrom, Write};
22+
use crate::rc::Ref;
23+
use std::io::{ErrorKind, Seek, SeekFrom, Write};
2324

2425
pub struct BinaryWriter {
26+
view: Ref<BinaryView>,
2527
handle: *mut BNBinaryWriter,
2628
}
2729

2830
impl BinaryWriter {
29-
pub fn new(view: &BinaryView, endian: Endianness) -> Self {
31+
pub fn new(view: &BinaryView) -> Self {
3032
let handle = unsafe { BNCreateBinaryWriter(view.handle) };
31-
unsafe {
32-
BNSetBinaryWriterEndianness(handle, endian);
33+
Self {
34+
view: view.to_owned(),
35+
handle,
3336
}
34-
Self { handle }
3537
}
3638

37-
pub fn endian(&self) -> Endianness {
39+
pub fn new_with_opts(view: &BinaryView, options: &BinaryWriterOptions) -> Self {
40+
let mut writer = Self::new(view);
41+
if let Some(endianness) = options.endianness {
42+
writer.set_endianness(endianness);
43+
}
44+
if let Some(address) = options.address {
45+
writer.seek_to_offset(address);
46+
}
47+
writer
48+
}
49+
50+
pub fn endianness(&self) -> Endianness {
3851
unsafe { BNGetBinaryWriterEndianness(self.handle) }
3952
}
4053

41-
pub fn set_endian(&self, endian: Endianness) {
42-
unsafe { BNSetBinaryWriterEndianness(self.handle, endian) }
54+
pub fn set_endianness(&mut self, endianness: Endianness) {
55+
unsafe { BNSetBinaryWriterEndianness(self.handle, endianness) }
56+
}
57+
58+
pub fn seek_to_offset(&mut self, offset: u64) {
59+
unsafe { BNSeekBinaryWriter(self.handle, offset) }
60+
}
61+
62+
pub fn seek_to_relative_offset(&mut self, offset: i64) {
63+
unsafe { BNSeekBinaryWriterRelative(self.handle, offset) }
4364
}
4465

4566
pub fn offset(&self) -> u64 {
@@ -49,22 +70,22 @@ impl BinaryWriter {
4970

5071
impl Seek for BinaryWriter {
5172
/// Seek to the specified position.
52-
///
53-
/// # Errors
54-
/// Seeking relative to [SeekFrom::End] is unsupported and will return an error.
5573
fn seek(&mut self, pos: SeekFrom) -> std::io::Result<u64> {
56-
unsafe {
57-
match pos {
58-
SeekFrom::Current(offset) => BNSeekBinaryWriterRelative(self.handle, offset),
59-
SeekFrom::Start(offset) => BNSeekBinaryWriter(self.handle, offset),
60-
_ => {
61-
return Err(std::io::Error::new(
62-
std::io::ErrorKind::Unsupported,
63-
"Cannot seek end of BinaryWriter",
64-
))
65-
}
66-
};
67-
}
74+
match pos {
75+
SeekFrom::Current(offset) => self.seek_to_relative_offset(offset),
76+
SeekFrom::Start(offset) => self.seek_to_offset(offset),
77+
SeekFrom::End(end_offset) => {
78+
let offset =
79+
self.view
80+
.len()
81+
.checked_add_signed(end_offset)
82+
.ok_or(std::io::Error::new(
83+
ErrorKind::Other,
84+
"Seeking from end overflowed",
85+
))?;
86+
self.seek_to_offset(offset);
87+
}
88+
};
6889

6990
Ok(self.offset())
7091
}
@@ -97,3 +118,25 @@ impl Drop for BinaryWriter {
97118

98119
unsafe impl Sync for BinaryWriter {}
99120
unsafe impl Send for BinaryWriter {}
121+
122+
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
123+
pub struct BinaryWriterOptions {
124+
endianness: Option<Endianness>,
125+
address: Option<u64>,
126+
}
127+
128+
impl BinaryWriterOptions {
129+
pub fn new() -> Self {
130+
Self::default()
131+
}
132+
133+
pub fn with_endianness(mut self, endian: Endianness) -> Self {
134+
self.endianness = Some(endian);
135+
self
136+
}
137+
138+
pub fn with_address(mut self, address: u64) -> Self {
139+
self.address = Some(address);
140+
self
141+
}
142+
}

0 commit comments

Comments
 (0)