@@ -358,6 +358,7 @@ pub struct Tag {
358
358
pub kind : TagKind ,
359
359
pub is_erased : bool , // Tag was deleted but has been reconstructed
360
360
pub is_erased_root : bool , // Tag is erased and is the root of a tree of erased tags
361
+ pub data_endian : Endian , // Endianness of the tag data (could be different from the address endianness for erased tags)
361
362
pub attributes : Vec < Attribute > ,
362
363
}
363
364
@@ -554,6 +555,7 @@ where
554
555
kind : TagKind :: Padding ,
555
556
is_erased,
556
557
is_erased_root : false ,
558
+ data_endian,
557
559
attributes : Vec :: new ( ) ,
558
560
} ) ;
559
561
return Ok ( tags) ;
@@ -563,26 +565,42 @@ where
563
565
let tag = TagKind :: try_from ( tag_num) . context ( "Unknown DWARF tag type" ) ?;
564
566
if tag == TagKind :: Padding {
565
567
if include_erased {
566
- // Erased entries that have become padding are little-endian, and we
567
- // have to guess the length and tag of the first entry. We assume
568
- // the entry is either a variable or a function, and read until we
569
- // find the high_pc attribute. Only MwGlobalRef will follow, and
570
- // these are unlikely to be confused with the length of the next
571
- // entry.
568
+ // Erased entries that have become padding could be either
569
+ // little-endian or big-endian, and we have to guess the length and
570
+ // tag of the first entry. We assume the entry is either a variable
571
+ // or a function, and read until we find the high_pc attribute. Only
572
+ // MwGlobalRef will follow, and these are unlikely to be confused
573
+ // with the length of the next entry.
572
574
let mut attributes = Vec :: new ( ) ;
573
575
let mut is_function = false ;
576
+
577
+ // Guess endianness based on first attribute
578
+ let data_endian = if is_erased {
579
+ data_endian
580
+ } else {
581
+ // Peek next two bytes
582
+ let mut buf = [ 0u8 ; 2 ] ;
583
+ reader. read_exact ( & mut buf) ?;
584
+ let attr_tag = u16:: from_reader ( & mut Cursor :: new ( & buf) , data_endian) ?;
585
+ reader. seek ( SeekFrom :: Current ( -2 ) ) ?;
586
+ match AttributeKind :: try_from ( attr_tag) {
587
+ Ok ( _) => data_endian,
588
+ Err ( _) => data_endian. flip ( ) ,
589
+ }
590
+ } ;
591
+
574
592
while reader. stream_position ( ) ? < position + size as u64 {
575
593
// Peek next two bytes
576
594
let mut buf = [ 0u8 ; 2 ] ;
577
595
reader. read_exact ( & mut buf) ?;
578
- let attr_tag = u16:: from_reader ( & mut Cursor :: new ( & buf) , Endian :: Little ) ?;
596
+ let attr_tag = u16:: from_reader ( & mut Cursor :: new ( & buf) , data_endian ) ?;
579
597
reader. seek ( SeekFrom :: Current ( -2 ) ) ?;
580
598
581
599
if is_function && attr_tag != AttributeKind :: MwGlobalRef as u16 {
582
600
break ;
583
601
}
584
602
585
- let attr = read_attribute ( reader, Endian :: Little , addr_endian) ?;
603
+ let attr = read_attribute ( reader, data_endian , addr_endian) ?;
586
604
if attr. kind == AttributeKind :: HighPc {
587
605
is_function = true ;
588
606
}
@@ -594,12 +612,13 @@ where
594
612
kind,
595
613
is_erased : true ,
596
614
is_erased_root : true ,
615
+ data_endian,
597
616
attributes,
598
617
} ) ;
599
618
600
619
// Read the rest of the tags
601
620
while reader. stream_position ( ) ? < position + size as u64 {
602
- for tag in read_tags ( reader, Endian :: Little , addr_endian, include_erased, true ) ? {
621
+ for tag in read_tags ( reader, data_endian , addr_endian, include_erased, true ) ? {
603
622
tags. push ( tag) ;
604
623
}
605
624
}
@@ -616,6 +635,7 @@ where
616
635
kind : tag,
617
636
is_erased,
618
637
is_erased_root : false ,
638
+ data_endian,
619
639
attributes,
620
640
} ) ;
621
641
}
@@ -2028,9 +2048,9 @@ fn process_array_tag(info: &DwarfInfo, tag: &Tag) -> Result<ArrayType> {
2028
2048
( AttributeKind :: Sibling , _) => { }
2029
2049
( AttributeKind :: SubscrData , AttributeValue :: Block ( data) ) => {
2030
2050
subscr_data =
2031
- Some ( process_array_subscript_data ( data, info. e , tag . is_erased ) . with_context (
2032
- || format ! ( "Failed to process SubscrData for tag: {tag:?}" ) ,
2033
- ) ?)
2051
+ Some ( process_array_subscript_data ( data, info. e ) . with_context ( || {
2052
+ format ! ( "Failed to process SubscrData for tag: {tag:?}" )
2053
+ } ) ?)
2034
2054
}
2035
2055
( AttributeKind :: Ordering , val) => match val {
2036
2056
AttributeValue :: Data2 ( d2) => {
@@ -2056,11 +2076,7 @@ fn process_array_tag(info: &DwarfInfo, tag: &Tag) -> Result<ArrayType> {
2056
2076
Ok ( ArrayType { element_type : Box :: from ( element_type) , dimensions } )
2057
2077
}
2058
2078
2059
- fn process_array_subscript_data (
2060
- data : & [ u8 ] ,
2061
- e : Endian ,
2062
- is_erased : bool ,
2063
- ) -> Result < ( Type , Vec < ArrayDimension > ) > {
2079
+ fn process_array_subscript_data ( data : & [ u8 ] , e : Endian ) -> Result < ( Type , Vec < ArrayDimension > ) > {
2064
2080
let mut element_type = None ;
2065
2081
let mut dimensions = Vec :: new ( ) ;
2066
2082
let mut data = data;
@@ -2101,8 +2117,7 @@ fn process_array_subscript_data(
2101
2117
SubscriptFormat :: ElementType => {
2102
2118
let mut cursor = Cursor :: new ( data) ;
2103
2119
// TODO: is this the right endianness to use for erased tags?
2104
- let type_attr =
2105
- read_attribute ( & mut cursor, if is_erased { Endian :: Little } else { e } , e) ?;
2120
+ let type_attr = read_attribute ( & mut cursor, e, e) ?;
2106
2121
element_type = Some ( process_type ( & type_attr, e) ?) ;
2107
2122
data = & data[ cursor. position ( ) as usize ..] ;
2108
2123
}
@@ -2456,10 +2471,7 @@ fn process_subroutine_parameter_tag(info: &DwarfInfo, tag: &Tag) -> Result<Subro
2456
2471
) => kind = Some ( process_type ( attr, info. e ) ?) ,
2457
2472
( AttributeKind :: Location , AttributeValue :: Block ( block) ) => {
2458
2473
if !block. is_empty ( ) {
2459
- location = Some ( process_variable_location (
2460
- block,
2461
- if tag. is_erased { Endian :: Little } else { info. e } ,
2462
- ) ?) ;
2474
+ location = Some ( process_variable_location ( block, tag. data_endian ) ?) ;
2463
2475
}
2464
2476
}
2465
2477
( AttributeKind :: MwDwarf2Location , AttributeValue :: Block ( _block) ) => {
@@ -2514,10 +2526,7 @@ fn process_local_variable_tag(info: &DwarfInfo, tag: &Tag) -> Result<SubroutineV
2514
2526
) => kind = Some ( process_type ( attr, info. e ) ?) ,
2515
2527
( AttributeKind :: Location , AttributeValue :: Block ( block) ) => {
2516
2528
if !block. is_empty ( ) {
2517
- location = Some ( process_variable_location (
2518
- block,
2519
- if tag. is_erased { Endian :: Little } else { info. e } ,
2520
- ) ?) ;
2529
+ location = Some ( process_variable_location ( block, tag. data_endian ) ?) ;
2521
2530
}
2522
2531
}
2523
2532
( AttributeKind :: MwDwarf2Location , AttributeValue :: Block ( _block) ) => {
0 commit comments