@@ -44,6 +44,7 @@ use gimli::{
44
44
45
45
use binaryninja:: logger:: Logger ;
46
46
use helpers:: { get_build_id, load_debug_info_for_build_id} ;
47
+ use iset:: IntervalMap ;
47
48
use log:: { debug, error, warn} ;
48
49
49
50
trait ReaderType : Reader < Offset = usize > { }
@@ -374,37 +375,39 @@ where
374
375
{
375
376
let mut bases = gimli:: BaseAddresses :: default ( ) ;
376
377
378
+ let view_start = view. start ( ) ;
379
+
377
380
if let Some ( section) = view
378
381
. section_by_name ( ".eh_frame_hdr" )
379
382
. or ( view. section_by_name ( "__eh_frame_hdr" ) )
380
383
{
381
- bases = bases. set_eh_frame_hdr ( section. start ( ) ) ;
384
+ bases = bases. set_eh_frame_hdr ( section. start ( ) - view_start ) ;
382
385
}
383
386
384
387
if let Some ( section) = view
385
388
. section_by_name ( ".eh_frame" )
386
389
. or ( view. section_by_name ( "__eh_frame" ) )
387
390
{
388
- bases = bases. set_eh_frame ( section. start ( ) ) ;
391
+ bases = bases. set_eh_frame ( section. start ( ) - view_start ) ;
389
392
} else if let Some ( section) = view
390
393
. section_by_name ( ".debug_frame" )
391
394
. or ( view. section_by_name ( "__debug_frame" ) )
392
395
{
393
- bases = bases. set_eh_frame ( section. start ( ) ) ;
396
+ bases = bases. set_eh_frame ( section. start ( ) - view_start ) ;
394
397
}
395
398
396
399
if let Some ( section) = view
397
400
. section_by_name ( ".text" )
398
401
. or ( view. section_by_name ( "__text" ) )
399
402
{
400
- bases = bases. set_text ( section. start ( ) ) ;
403
+ bases = bases. set_text ( section. start ( ) - view_start ) ;
401
404
}
402
405
403
406
if let Some ( section) = view
404
407
. section_by_name ( ".got" )
405
408
. or ( view. section_by_name ( "__got" ) )
406
409
{
407
- bases = bases. set_got ( section. start ( ) ) ;
410
+ bases = bases. set_got ( section. start ( ) - view_start ) ;
408
411
}
409
412
410
413
let mut cies = HashMap :: new ( ) ;
@@ -453,6 +456,19 @@ where
453
456
register : _,
454
457
offset,
455
458
} => {
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
+ */
456
472
// TODO: we should store offsets by register
457
473
if row. start_address ( ) < row. end_address ( ) {
458
474
cfa_offsets
@@ -497,8 +513,44 @@ fn get_supplementary_build_id(bv: &BinaryView) -> Option<String> {
497
513
}
498
514
}
499
515
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
+
500
552
fn parse_dwarf (
501
- _bv : & BinaryView ,
553
+ bv : & BinaryView ,
502
554
debug_bv : & BinaryView ,
503
555
supplementary_bv : Option < & BinaryView > ,
504
556
progress : Box < dyn Fn ( usize , usize ) -> Result < ( ) , ( ) > > ,
@@ -548,35 +600,20 @@ fn parse_dwarf(
548
600
}
549
601
}
550
602
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 ( )
561
614
}
562
615
}
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
+ } ;
580
617
581
618
// Create debug info builder and recover name mapping first
582
619
// Since DWARF is stored as a tree with arbitrary implicit edges among leaves,
0 commit comments