11mod types;
2- use idb_rs:: { IDAKind , IDAUsize } ;
2+ use std:: borrow:: Cow ;
3+ use std:: io:: { BufRead , Cursor , Seek } ;
4+
5+ use idb_rs:: id1:: ID1Section ;
6+ use idb_rs:: id2:: { ID2Section , ID2SectionVariants } ;
7+ use idb_rs:: { IDAKind , IDAUsize , IDBFormat } ;
38use types:: * ;
49mod addr_info;
510use addr_info:: * ;
@@ -9,13 +14,13 @@ use binaryninja::debuginfo::{
914 CustomDebugInfoParser , DebugFunctionInfo , DebugInfo , DebugInfoParser ,
1015} ;
1116
12- use idb_rs:: id0:: { ID0Section , IDBParam1 , IDBParam2 } ;
17+ use idb_rs:: id0:: { ID0Section , ID0SectionVariants } ;
1318use idb_rs:: til:: section:: TILSection ;
1419use idb_rs:: til:: TypeVariant as TILTypeVariant ;
1520
1621use log:: { error, trace, warn, LevelFilter } ;
1722
18- use anyhow:: Result ;
23+ use anyhow:: { anyhow , Result } ;
1924use binaryninja:: logger:: Logger ;
2025
2126struct IDBDebugInfoParser ;
@@ -83,7 +88,7 @@ impl std::io::Read for BinaryViewReader<'_> {
8388 if !self . bv . offset_valid ( self . offset ) {
8489 return Ok ( 0 ) ;
8590 }
86- let len = BinaryView :: read ( & self . bv , buf, self . offset ) ;
91+ let len = BinaryView :: read ( self . bv , buf, self . offset ) ;
8792 self . offset += u64:: try_from ( len) . unwrap ( ) ;
8893 Ok ( len)
8994 }
@@ -125,27 +130,73 @@ fn parse_idb_info(
125130 offset : 0 ,
126131 } ;
127132 trace ! ( "Parsing a IDB file" ) ;
128- let file = std:: io:: BufReader :: new ( file) ;
129- let mut parser = idb_rs:: IDBParserVariants :: new ( file) ?;
130- if let Some ( til_section) = parser. til_section_offset ( ) {
133+ let mut file = std:: io:: BufReader :: new ( file) ;
134+ let idb_kind = idb_rs:: identify_idb_file ( & mut file) ?;
135+ match idb_kind {
136+ idb_rs:: IDBFormats :: Separated ( sep) => {
137+ parse_idb_info_format ( debug_info, bv, debug_file, sep, file, progress)
138+ }
139+ idb_rs:: IDBFormats :: InlineUncompressed ( inline) => {
140+ parse_idb_info_format ( debug_info, bv, debug_file, inline, file, progress)
141+ }
142+ idb_rs:: IDBFormats :: InlineCompressed ( compressed) => {
143+ let mut buf = vec ! [ ] ;
144+ let inline = compressed. decompress_into_memory ( & mut file, & mut buf) ?;
145+ parse_idb_info_format (
146+ debug_info,
147+ bv,
148+ debug_file,
149+ inline,
150+ Cursor :: new ( & buf[ ..] ) ,
151+ progress,
152+ )
153+ }
154+ }
155+ }
156+
157+ fn parse_idb_info_format (
158+ debug_info : & mut DebugInfo ,
159+ bv : & BinaryView ,
160+ debug_file : & BinaryView ,
161+ format : impl IDBFormat ,
162+ mut idb_data : impl BufRead + Seek ,
163+ progress : Box < dyn Fn ( usize , usize ) -> Result < ( ) , ( ) > > ,
164+ ) -> Result < ( ) > {
165+ let Some ( id0_idx) = format. id0_location ( ) else {
166+ return Err ( anyhow ! ( "Unable to find the ID0 section" ) ) ;
167+ } ;
168+ let Some ( id1_idx) = format. id1_location ( ) else {
169+ return Err ( anyhow ! ( "Unable to find the ID1 section" ) ) ;
170+ } ;
171+ let id2_idx = format. id2_location ( ) ;
172+
173+ if let Some ( til_idx) = format. til_location ( ) {
131174 trace ! ( "Parsing the TIL section" ) ;
132- let til = parser . read_til_section ( til_section ) ?;
175+ let til = format . read_til ( & mut idb_data , til_idx ) ?;
133176 // progress 0%-50%
134177 import_til_section ( debug_info, debug_file, & til, progress) ?;
135- }
178+ } ;
136179
137- if let Some ( id0_section) = parser. id0_section_offset ( ) {
138- trace ! ( "Parsing the ID0 section" ) ;
139- let id0 = parser. read_id0_section ( id0_section) ?;
140- // progress 50%-100%
141- match id0 {
142- idb_rs:: IDAVariants :: IDA32 ( id0) => {
143- parse_id0_section_info :: < idb_rs:: IDA32 > ( debug_info, bv, debug_file, & id0) ?
144- }
145- idb_rs:: IDAVariants :: IDA64 ( id0) => {
146- parse_id0_section_info :: < idb_rs:: IDA64 > ( debug_info, bv, debug_file, & id0) ?
147- }
180+ let id0 = format. read_id0 ( & mut idb_data, id0_idx) ?;
181+ let id1 = format. read_id1 ( & mut idb_data, id1_idx) ?;
182+ let id2 = id2_idx
183+ . map ( |id2_idx| format. read_id2 ( & mut idb_data, id2_idx) )
184+ . transpose ( ) ?;
185+
186+ match ( id0, id2) {
187+ ( ID0SectionVariants :: IDA32 ( id0) , Some ( ID2SectionVariants :: IDA32 ( id2) ) ) => {
188+ parse_id0_section_info ( debug_info, bv, debug_file, & id0, & id1, Some ( & id2) ) ?
189+ }
190+ ( ID0SectionVariants :: IDA32 ( id0) , None ) => {
191+ parse_id0_section_info ( debug_info, bv, debug_file, & id0, & id1, None ) ?
192+ }
193+ ( ID0SectionVariants :: IDA64 ( id0) , Some ( ID2SectionVariants :: IDA64 ( id2) ) ) => {
194+ parse_id0_section_info ( debug_info, bv, debug_file, & id0, & id1, Some ( & id2) ) ?
148195 }
196+ ( ID0SectionVariants :: IDA64 ( id0) , None ) => {
197+ parse_id0_section_info ( debug_info, bv, debug_file, & id0, & id1, None ) ?
198+ }
199+ _ => unreachable ! ( ) ,
149200 }
150201
151202 Ok ( ( ) )
@@ -238,23 +289,20 @@ fn parse_id0_section_info<K: IDAKind>(
238289 bv : & BinaryView ,
239290 debug_file : & BinaryView ,
240291 id0 : & ID0Section < K > ,
292+ id1 : & ID1Section ,
293+ id2 : Option < & ID2Section < K > > ,
241294) -> Result < ( ) > {
242- let ( version, idb_baseaddr) = match id0. ida_info ( ) ? {
243- idb_rs:: id0:: IDBParam :: V1 ( IDBParam1 {
244- version, baseaddr, ..
245- } )
246- | idb_rs:: id0:: IDBParam :: V2 ( IDBParam2 {
247- version, baseaddr, ..
248- } ) => ( version, baseaddr. into_u64 ( ) ) ,
249- } ;
250-
295+ let ida_info_idx = id0. root_node ( ) ?;
296+ let ida_info = id0. ida_info ( ida_info_idx) ?;
297+ let idb_baseaddr = ida_info. addresses . loading_base . into_u64 ( ) ;
251298 let bv_baseaddr = bv. start ( ) ;
299+ let netdelta = ida_info. netdelta ( ) ;
252300 // just addr this value to the address to translate from ida to bn
253- // NOTE this delta could wrapp here and while using translating
301+ // NOTE this delta could wrap here and while using translating
254302 let addr_delta = bv_baseaddr. wrapping_sub ( idb_baseaddr) ;
255303
256- for ( idb_addr, info) in get_info ( id0, version ) ? {
257- let addr = addr_delta. wrapping_add ( idb_addr. into_u64 ( ) ) ;
304+ for ( idb_addr, info) in get_info ( id0, id1 , id2 , netdelta ) ? {
305+ let addr = addr_delta. wrapping_add ( idb_addr. into_raw ( ) . into_u64 ( ) ) ;
258306 // just in case we change this struct in the future, this line will for us to review this code
259307 // TODO merge this data with folder locations
260308 let AddrInfo {
@@ -286,6 +334,8 @@ fn parse_id0_section_info<K: IDAKind>(
286334 }
287335 } ) ;
288336
337+ let label: Option < Cow < ' _ , str > > =
338+ label. as_ref ( ) . map ( Cow :: as_ref) . map ( String :: from_utf8_lossy) ;
289339 match ( label, & ty, bnty) {
290340 ( label, Some ( ty) , bnty) if matches ! ( & ty. type_variant, TILTypeVariant :: Function ( _) ) => {
291341 if bnty. is_none ( ) {
@@ -294,7 +344,7 @@ fn parse_id0_section_info<K: IDAKind>(
294344 if !debug_info. add_function ( & DebugFunctionInfo :: new (
295345 None ,
296346 None ,
297- label. map ( |x| x . to_string ( ) ) ,
347+ label. map ( Cow :: into_owned ) ,
298348 bnty,
299349 Some ( addr) ,
300350 None ,
@@ -305,15 +355,15 @@ fn parse_id0_section_info<K: IDAKind>(
305355 }
306356 }
307357 ( label, Some ( _ty) , Some ( bnty) ) => {
308- let label : Option < & str > = label. as_ref ( ) . map ( |x| x . as_ref ( ) ) ;
309- if !debug_info . add_data_variable ( addr , & bnty , label , & [ ] ) {
358+ if !debug_info . add_data_variable ( addr , & bnty , label. as_ref ( ) . map ( Cow :: as_ref) , & [ ] )
359+ {
310360 error ! ( "Unable to add the type at {addr:#x}" )
311361 }
312362 }
313363 ( label, Some ( _ty) , None ) => {
314364 // TODO types come from the TIL sections, can we make all types be just NamedTypes?
315365 error ! ( "Unable to convert type {addr:#x}" ) ;
316- // TODO how to add a label without a type associacted with it?
366+ // TODO how to add a label without a type associated with it?
317367 if let Some ( name) = label {
318368 if !debug_info. add_data_variable (
319369 addr,
@@ -326,7 +376,7 @@ fn parse_id0_section_info<K: IDAKind>(
326376 }
327377 }
328378 ( Some ( name) , None , None ) => {
329- // TODO how to add a label without a type associacted with it?
379+ // TODO how to add a label without a type associated with it?
330380 if !debug_info. add_data_variable (
331381 addr,
332382 & binaryninja:: types:: Type :: void ( ) ,
0 commit comments