11mod types;
2- use std:: path:: Path ;
2+ use std:: fs:: File ;
3+ use std:: io:: BufReader ;
34
45use binaryninja:: command:: Command ;
6+ use binaryninja:: string:: BnStrCompatible ;
57use binaryninja:: type_library:: TypeLibrary ;
68use binaryninja:: types:: QualifiedName ;
79use types:: * ;
@@ -41,7 +43,7 @@ impl CustomDebugInfoParser for IDBDebugInfoParser {
4143 debug_file : & BinaryView ,
4244 progress : Box < dyn Fn ( usize , usize ) -> Result < ( ) , ( ) > > ,
4345 ) -> bool {
44- match parse_idb_info ( debug_info, bv, debug_file, progress) {
46+ match import_idb_info ( debug_info, bv, debug_file, progress) {
4547 Ok ( ( ) ) => true ,
4648 Err ( error) => {
4749 error ! ( "Unable to parse IDB file: {error}" ) ;
@@ -68,7 +70,7 @@ impl CustomDebugInfoParser for TILDebugInfoParser {
6870 debug_file : & BinaryView ,
6971 progress : Box < dyn Fn ( usize , usize ) -> Result < ( ) , ( ) > > ,
7072 ) -> bool {
71- match parse_til_info ( debug_info, bv, debug_file, progress) {
73+ match import_til_info_from_debug_file ( debug_info, bv, debug_file, progress) {
7274 Ok ( ( ) ) => true ,
7375 Err ( error) => {
7476 error ! ( "Unable to parse TIL file: {error}" ) ;
@@ -124,79 +126,59 @@ impl std::io::Seek for BinaryViewReader<'_> {
124126 }
125127}
126128
127- fn parse_idb_info (
129+ fn dummy_progress ( _: usize , _: usize ) -> Result < ( ) , ( ) > {
130+ Ok ( ( ) )
131+ }
132+
133+ fn import_idb_info < P : Fn ( usize , usize ) -> Result < ( ) , ( ) > > (
128134 debug_info : & mut DebugInfo ,
129135 bv : & BinaryView ,
130136 debug_file : & BinaryView ,
131- progress : Box < dyn Fn ( usize , usize ) -> Result < ( ) , ( ) > > ,
137+ progress : P ,
132138) -> Result < ( ) > {
133139 trace ! ( "Opening a IDB file" ) ;
134- let file = BinaryViewReader {
140+ let file = BufReader :: new ( BinaryViewReader {
135141 bv : debug_file,
136142 offset : 0 ,
137- } ;
143+ } ) ;
138144 trace ! ( "Parsing a IDB file" ) ;
139- let file = std:: io:: BufReader :: new ( file) ;
140145 let mut parser = idb_rs:: IDBParser :: new ( file) ?;
141146
142- let default_arch = bv
143- . default_arch ( )
144- . ok_or_else ( || anyhow ! ( "Unable to get the default arch" ) ) ?;
145- let filename = debug_file. file ( ) . filename ( ) ;
146- let mut type_lib = TypeLibrary :: new ( default_arch, filename) ;
147-
148147 if let Some ( til_section) = parser. til_section_offset ( ) {
149148 // TODO handle dependency, create a function for that with closures
150149 trace ! ( "Parsing the TIL section" ) ;
151150 let til = parser. read_til_section ( til_section) ?;
152- // progress 0%-50%
153- import_til_section ( & mut type_lib, debug_file, & til, progress) ?;
151+ let filename = debug_file. file ( ) . filename ( ) ;
152+ // TODO progress 0%-50%
153+ import_til_to_type_library ( til, filename, bv, progress) ?;
154154 }
155155
156- if !type_lib. finalize ( ) {
157- return Err ( anyhow ! ( "Unable to finalize TypeLibrary" ) ) ;
158- } ;
159- bv. add_type_library ( & type_lib) ;
160-
161156 if let Some ( id0_section) = parser. id0_section_offset ( ) {
162157 trace ! ( "Parsing the ID0 section" ) ;
163158 let id0 = parser. read_id0_section ( id0_section) ?;
164- // progress 50%-100%
159+ // TODO progress 50%-100%
165160 parse_id0_section_info ( debug_info, bv, debug_file, & id0) ?;
166161 }
167162
168163 Ok ( ( ) )
169164}
170165
171- fn parse_til_info (
166+ fn import_til_info_from_debug_file < P : Fn ( usize , usize ) -> Result < ( ) , ( ) > > (
172167 _debug_info : & mut DebugInfo ,
173168 bv : & BinaryView ,
174169 debug_file : & BinaryView ,
175- progress : Box < dyn Fn ( usize , usize ) -> Result < ( ) , ( ) > > ,
170+ progress : P ,
176171) -> Result < ( ) > {
177172 trace ! ( "Opening a TIL file" ) ;
178173 let file = BinaryViewReader {
179174 bv : debug_file,
180175 offset : 0 ,
181176 } ;
182- let mut file = std:: io:: BufReader :: new ( file) ;
183-
184- let default_arch = bv
185- . default_arch ( )
186- . ok_or_else ( || anyhow ! ( "Unable to get the default arch" ) ) ?;
187177 let filename = debug_file. file ( ) . filename ( ) ;
188- let mut type_lib = TypeLibrary :: new ( default_arch, filename) ;
189-
190- trace ! ( "Parsing the TIL section" ) ;
178+ let mut file = std:: io:: BufReader :: new ( file) ;
191179 let til = TILSection :: read ( & mut file, idb_rs:: IDBSectionCompression :: None ) ?;
192- // TODO handle dependency, create a function for that with closures
193- import_til_section ( & mut type_lib, debug_file, & til, progress) ?;
194180
195- if !type_lib. finalize ( ) {
196- return Err ( anyhow ! ( "Unable to finalize TypeLibrary" ) ) ;
197- } ;
198- bv. add_type_library ( & type_lib) ;
199- Ok ( ( ) )
181+ import_til_to_type_library ( til, filename, bv, progress)
200182}
201183
202184fn interactive_import_til ( view : & BinaryView ) -> Result < ( ) > {
@@ -206,83 +188,115 @@ fn interactive_import_til(view: &BinaryView) -> Result<()> {
206188 return Ok ( ( ) ) ;
207189 } ;
208190
191+ let filename = file. file_name ( ) . unwrap ( ) . to_string_lossy ( ) ;
192+ let mut file = BufReader :: new ( File :: open ( & file) ?) ;
193+ let til = TILSection :: read ( & mut file, idb_rs:: IDBSectionCompression :: None ) ?;
194+
195+ // TODO remove the extension?
196+ import_til_to_type_library ( til, filename, view, dummy_progress)
197+ }
198+
199+ fn import_til_to_type_library < S , P > (
200+ til : TILSection ,
201+ type_lib_name : S ,
202+ view : & BinaryView ,
203+ progress : P ,
204+ ) -> Result < ( ) >
205+ where
206+ S : BnStrCompatible ,
207+ P : Fn ( usize , usize ) -> Result < ( ) , ( ) > ,
208+ {
209209 let default_arch = view
210210 . default_arch ( )
211211 . ok_or_else ( || anyhow ! ( "Unable to get the default arch" ) ) ?;
212- let filename = file. file_name ( ) . unwrap ( ) . to_string_lossy ( ) ;
213- let mut type_lib = TypeLibrary :: new ( default_arch, filename) ;
212+ let mut type_lib = TypeLibrary :: new ( default_arch, type_lib_name) ;
214213
215- interactive_import_til_file ( file. as_path ( ) , view, & mut type_lib) ?;
214+ // TODO create a background task to not freeze bn, also create a progress
215+ // user interface feedback
216+ import_til_file ( til, view, & mut type_lib, progress) ?;
216217 if !type_lib. finalize ( ) {
217218 return Err ( anyhow ! ( "Unable to finalize TypeLibrary" ) ) ;
218219 } ;
219220 view. add_type_library ( & type_lib) ;
220221 Ok ( ( ) )
221222}
222223
223- fn interactive_import_til_file (
224- file : & Path ,
224+ fn import_til_file < P : Fn ( usize , usize ) -> Result < ( ) , ( ) > > (
225+ til : TILSection ,
225226 view : & BinaryView ,
226227 type_library : & mut TypeLibrary ,
228+ progress : P ,
227229) -> Result < ( ) > {
228- // TODO create a background task to not freeze bn, also create a progress
229- // user interface feedback
230- let file = std:: fs:: File :: open ( file) ?;
231- let mut file = std:: io:: BufReader :: new ( file) ;
232- let til = TILSection :: read ( & mut file, idb_rs:: IDBSectionCompression :: None ) ?;
233- for dep in & til. header . dependencies {
234- let name = dep. as_utf8_lossy ( ) ;
230+ trace ! ( "Parsing the TIL section" ) ;
231+ // TODO
232+ let mut tils = vec ! [ til] ;
233+ import_til_dependency ( & mut tils, 0 , & progress) ?;
234+ import_til_section ( type_library, view, & tils, progress)
235+ }
236+
237+ fn import_til_dependency < P : Fn ( usize , usize ) -> Result < ( ) , ( ) > > (
238+ tils : & mut Vec < TILSection > ,
239+ til_idx : usize ,
240+ _progress : & P ,
241+ ) -> Result < ( ) > {
242+ let names: Vec < _ > = tils[ til_idx] . header . dependencies . to_vec ( ) ;
243+ for name in names {
244+ let name = name. as_utf8_lossy ( ) ;
235245 let message = format ! ( "Select the dependency \" {name}.til\" " , ) ;
236246 let Some ( dep_file) = binaryninja:: interaction:: get_open_filename_input ( & message, "*.til" )
237247 else {
238248 return Err ( anyhow ! ( "Unable to get the dependency {name}" ) ) ;
239249 } ;
240250
241- interactive_import_til_file ( dep_file. as_path ( ) , view, type_library)
242- . context ( "While importing dependency {name}" ) ?;
251+ let mut dep_file = BufReader :: new ( File :: open ( & dep_file) ?) ;
252+ let dep_til = TILSection :: read ( & mut dep_file, idb_rs:: IDBSectionCompression :: None ) ?;
253+ tils. push ( dep_til) ;
243254 }
244-
245- fn dummy_progress ( _: usize , _: usize ) -> Result < ( ) , ( ) > {
246- Ok ( ( ) )
255+ if tils. len ( ) > til_idx + 1 {
256+ // add dependencies of dependencies
257+ // TODO handle progress
258+ // TODO identify ciclycal dependencies
259+ import_til_dependency ( tils, til_idx + 1 , _progress)
260+ . context ( "While importing dependency {name}" ) ?;
247261 }
248- import_til_section ( type_library , view , & til , dummy_progress )
262+ Ok ( ( ) )
249263}
250264
251- fn import_til_section (
265+ fn import_til_section < P : Fn ( usize , usize ) -> Result < ( ) , ( ) > > (
252266 type_library : & mut TypeLibrary ,
253267 view : & BinaryView ,
254- til : & TILSection ,
255- progress : impl Fn ( usize , usize ) -> Result < ( ) , ( ) > ,
268+ tils : & [ TILSection ] ,
269+ progress : P ,
256270) -> Result < ( ) > {
257271 let default_arch = view
258272 . default_arch ( )
259273 . ok_or_else ( || anyhow ! ( "Unable to get the default arch" ) ) ?;
260- let types = types:: translate_til_types ( default_arch, til , progress) ?;
274+ let types = types:: translate_tils_types ( default_arch, tils , progress) ?;
261275
262276 // print any errors
263- print_til_convertsion_errors ( & types) ;
277+ print_til_convertsion_errors ( & types) ? ;
264278
265279 // add all type to the type library
266280 for ty in & types {
267281 if let TranslateTypeResult :: Translated ( bn_ty)
268282 | TranslateTypeResult :: PartiallyTranslated ( bn_ty, _) = & ty. ty
269283 {
270284 let name = QualifiedName :: new ( vec ! [ ty. name. as_utf8_lossy( ) . to_string( ) ] ) ;
271- type_library. add_named_type ( name, & bn_ty) ;
285+ type_library. add_named_type ( name, bn_ty) ;
272286 }
273287 }
274288
275289 Ok ( ( ) )
276290}
277291
278- fn print_til_convertsion_errors ( types : & [ TranslatesIDBType ] ) {
292+ fn print_til_convertsion_errors ( types : & [ TranslatesIDBType ] ) -> Result < ( ) > {
279293 for ty in types {
280294 match & ty. ty {
281295 TranslateTypeResult :: NotYet => {
282- panic ! (
283- "type could not be processed `{}`: {:#?}" ,
296+ // NOTE this should be unreachable
297+ error ! (
298+ "Unable to finish parsing type `{}`" ,
284299 ty. name. as_utf8_lossy( ) ,
285- & ty. og_ty
286300 ) ;
287301 }
288302 TranslateTypeResult :: Error ( error) => {
@@ -307,6 +321,7 @@ fn print_til_convertsion_errors(types: &[TranslatesIDBType]) {
307321 TranslateTypeResult :: Translated ( _) => { }
308322 } ;
309323 }
324+ Ok ( ( ) )
310325}
311326
312327fn parse_id0_section_info (
0 commit comments