@@ -44,6 +44,7 @@ use gimli::{
4444
4545use binaryninja:: logger:: Logger ;
4646use helpers:: { get_build_id, load_debug_info_for_build_id} ;
47+ use iset:: IntervalMap ;
4748use log:: { debug, error, warn} ;
4849
4950trait ReaderType : Reader < Offset = usize > { }
@@ -374,37 +375,39 @@ where
374375{
375376 let mut bases = gimli:: BaseAddresses :: default ( ) ;
376377
378+ let view_start = view. start ( ) ;
379+
377380 if let Some ( section) = view
378381 . section_by_name ( ".eh_frame_hdr" )
379382 . or ( view. section_by_name ( "__eh_frame_hdr" ) )
380383 {
381- bases = bases. set_eh_frame_hdr ( section. start ( ) ) ;
384+ bases = bases. set_eh_frame_hdr ( section. start ( ) - view_start ) ;
382385 }
383386
384387 if let Some ( section) = view
385388 . section_by_name ( ".eh_frame" )
386389 . or ( view. section_by_name ( "__eh_frame" ) )
387390 {
388- bases = bases. set_eh_frame ( section. start ( ) ) ;
391+ bases = bases. set_eh_frame ( section. start ( ) - view_start ) ;
389392 } else if let Some ( section) = view
390393 . section_by_name ( ".debug_frame" )
391394 . or ( view. section_by_name ( "__debug_frame" ) )
392395 {
393- bases = bases. set_eh_frame ( section. start ( ) ) ;
396+ bases = bases. set_eh_frame ( section. start ( ) - view_start ) ;
394397 }
395398
396399 if let Some ( section) = view
397400 . section_by_name ( ".text" )
398401 . or ( view. section_by_name ( "__text" ) )
399402 {
400- bases = bases. set_text ( section. start ( ) ) ;
403+ bases = bases. set_text ( section. start ( ) - view_start ) ;
401404 }
402405
403406 if let Some ( section) = view
404407 . section_by_name ( ".got" )
405408 . or ( view. section_by_name ( "__got" ) )
406409 {
407- bases = bases. set_got ( section. start ( ) ) ;
410+ bases = bases. set_got ( section. start ( ) - view_start ) ;
408411 }
409412
410413 let mut cies = HashMap :: new ( ) ;
@@ -453,6 +456,19 @@ where
453456 register : _,
454457 offset,
455458 } => {
459+ //TODO: can we normalize this to be sp-based?
460+ /*
461+ Switching to RBP from RSP in this example breaks things, and we should know that RBP = RSP - 8
462+ 65 │ 0x1139: CFA=RSP+8: RIP=[CFA-8]
463+ 66 │ 0x113a: CFA=RSP+16: RBP=[CFA-16], RIP=[CFA-8]
464+ 67 │ 0x113d: CFA=RBP+16: RBP=[CFA-16], RIP=[CFA-8]
465+ 68 │ 0x1162: CFA=RSP+8: RBP=[CFA-16], RIP=[CFA-8]
466+
467+ can we
468+ know that CFA=RSP+8 at the beginning
469+ in the next instruction (66) we know RBP=[CFA-16]=[RSP-8]
470+ and do something with that?
471+ */
456472 // TODO: we should store offsets by register
457473 if row. start_address ( ) < row. end_address ( ) {
458474 cfa_offsets
@@ -497,8 +513,44 @@ fn get_supplementary_build_id(bv: &BinaryView) -> Option<String> {
497513 }
498514}
499515
516+ fn parse_range_data_offsets ( bv : & BinaryView , dwo_file : bool ) -> Option < Result < IntervalMap < u64 , i64 > , ( ) > > {
517+ if bv. section_by_name ( ".eh_frame" ) . is_some ( ) || bv. section_by_name ( "__eh_frame" ) . is_some ( ) {
518+ let eh_frame_endian = get_endian ( bv) ;
519+ let eh_frame_section_reader = |section_id : SectionId | -> _ {
520+ create_section_reader ( section_id, bv, eh_frame_endian, dwo_file)
521+ } ;
522+ let mut eh_frame = gimli:: EhFrame :: load ( eh_frame_section_reader) . unwrap ( ) ;
523+ if let Some ( view_arch) = bv. default_arch ( ) {
524+ if view_arch. name ( ) . as_str ( ) == "aarch64" {
525+ eh_frame. set_vendor ( gimli:: Vendor :: AArch64 ) ;
526+ }
527+ }
528+ eh_frame. set_address_size ( bv. address_size ( ) as u8 ) ;
529+ Some ( parse_unwind_section ( bv, eh_frame)
530+ . map_err ( |e| error ! ( "Error parsing .eh_frame: {}" , e) ) )
531+ } else if bv. section_by_name ( ".debug_frame" ) . is_some ( )
532+ || bv. section_by_name ( "__debug_frame" ) . is_some ( )
533+ {
534+ let debug_frame_endian = get_endian ( bv) ;
535+ let debug_frame_section_reader = |section_id : SectionId | -> _ {
536+ create_section_reader ( section_id, bv, debug_frame_endian, dwo_file)
537+ } ;
538+ let mut debug_frame = gimli:: DebugFrame :: load ( debug_frame_section_reader) . unwrap ( ) ;
539+ if let Some ( view_arch) = bv. default_arch ( ) {
540+ if view_arch. name ( ) . as_str ( ) == "aarch64" {
541+ debug_frame. set_vendor ( gimli:: Vendor :: AArch64 ) ;
542+ }
543+ }
544+ debug_frame. set_address_size ( bv. address_size ( ) as u8 ) ;
545+ Some ( parse_unwind_section ( bv, debug_frame)
546+ . map_err ( |e| error ! ( "Error parsing .debug_frame: {}" , e) ) )
547+ } else {
548+ None
549+ }
550+ }
551+
500552fn parse_dwarf (
501- _bv : & BinaryView ,
553+ bv : & BinaryView ,
502554 debug_bv : & BinaryView ,
503555 supplementary_bv : Option < & BinaryView > ,
504556 progress : Box < dyn Fn ( usize , usize ) -> Result < ( ) , ( ) > > ,
@@ -548,35 +600,20 @@ fn parse_dwarf(
548600 }
549601 }
550602
551- let range_data_offsets;
552- if view. section_by_name ( ".eh_frame" ) . is_some ( ) || view. section_by_name ( "__eh_frame" ) . is_some ( ) {
553- let eh_frame_endian = get_endian ( view) ;
554- let eh_frame_section_reader = |section_id : SectionId | -> _ {
555- create_section_reader ( section_id, view, eh_frame_endian, dwo_file)
556- } ;
557- let mut eh_frame = gimli:: EhFrame :: load ( eh_frame_section_reader) . unwrap ( ) ;
558- if let Some ( view_arch) = view. default_arch ( ) {
559- if view_arch. name ( ) . as_str ( ) == "aarch64" {
560- eh_frame. set_vendor ( gimli:: Vendor :: AArch64 ) ;
603+ let range_data_offsets = match parse_range_data_offsets ( bv, dwo_file) {
604+ Some ( x) => x?,
605+ None => {
606+ if let Some ( raw_view) = bv. raw_view ( ) {
607+ if let Some ( offsets) = parse_range_data_offsets ( & raw_view, dwo_file) {
608+ offsets?
609+ } else {
610+ Default :: default ( )
611+ }
612+ } else {
613+ Default :: default ( )
561614 }
562615 }
563- eh_frame. set_address_size ( view. address_size ( ) as u8 ) ;
564- range_data_offsets = parse_unwind_section ( view, eh_frame)
565- . map_err ( |e| error ! ( "Error parsing .eh_frame: {}" , e) ) ?;
566- } else if view. section_by_name ( ".debug_frame" ) . is_some ( )
567- || view. section_by_name ( "__debug_frame" ) . is_some ( )
568- {
569- let debug_frame_endian = get_endian ( view) ;
570- let debug_frame_section_reader = |section_id : SectionId | -> _ {
571- create_section_reader ( section_id, view, debug_frame_endian, dwo_file)
572- } ;
573- let mut debug_frame = gimli:: DebugFrame :: load ( debug_frame_section_reader) . unwrap ( ) ;
574- debug_frame. set_address_size ( view. address_size ( ) as u8 ) ;
575- range_data_offsets = parse_unwind_section ( view, debug_frame)
576- . map_err ( |e| error ! ( "Error parsing .debug_frame: {}" , e) ) ?;
577- } else {
578- range_data_offsets = Default :: default ( ) ;
579- }
616+ } ;
580617
581618 // Create debug info builder and recover name mapping first
582619 // Since DWARF is stored as a tree with arbitrary implicit edges among leaves,
0 commit comments