1616
1717use binaryninjacore_sys:: * ;
1818
19- use crate :: binary_view:: BinaryView ;
19+ use crate :: binary_view:: { BinaryView , BinaryViewBase } ;
2020use crate :: Endianness ;
2121
22- use std:: io:: { Read , Seek , SeekFrom } ;
22+ use crate :: rc:: Ref ;
23+ use std:: io:: { ErrorKind , Read , Seek , SeekFrom } ;
2324
2425pub struct BinaryReader {
26+ view : Ref < BinaryView > ,
2527 handle : * mut BNBinaryReader ,
2628}
2729
2830impl 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
5490impl 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
100133unsafe impl Sync for BinaryReader { }
101134unsafe 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+ }
0 commit comments