@@ -7,10 +7,12 @@ use crate::{
7
7
arch:: { Arch , superh:: disasm:: sh2_disasm} ,
8
8
diff:: { DiffObjConfig , display:: InstructionPart } ,
9
9
obj:: {
10
- InstructionRef , Relocation , RelocationFlags , ResolvedInstructionRef , ScannedInstruction ,
10
+ InstructionRef , Relocation , RelocationFlags , ResolvedInstructionRef , ScannedInstruction
11
11
} ,
12
12
} ;
13
13
14
+ use std:: collections:: HashMap ;
15
+
14
16
pub mod disasm;
15
17
16
18
#[ derive( Debug ) ]
@@ -20,6 +22,12 @@ impl ArchSuperH {
20
22
pub fn new ( _file : & object:: File ) -> Result < Self > { Ok ( Self { } ) }
21
23
}
22
24
25
+
26
+ struct DataInfo {
27
+ address : u64 ,
28
+ size : u32 ,
29
+ }
30
+
23
31
impl Arch for ArchSuperH {
24
32
fn scan_instructions (
25
33
& self ,
@@ -31,6 +39,7 @@ impl Arch for ArchSuperH {
31
39
) -> Result < Vec < ScannedInstruction > > {
32
40
let mut ops = Vec :: < ScannedInstruction > :: with_capacity ( code. len ( ) / 2 ) ;
33
41
let mut offset = address;
42
+
34
43
for chunk in code. chunks_exact ( 2 ) {
35
44
let opcode = u16:: from_be_bytes ( chunk. try_into ( ) . unwrap ( ) ) ;
36
45
let mut parts: Vec < InstructionPart > = vec ! [ ] ;
@@ -62,13 +71,68 @@ impl Arch for ArchSuperH {
62
71
& self ,
63
72
resolved : ResolvedInstructionRef ,
64
73
_diff_config : & DiffObjConfig ,
74
+ _code : Option < & [ u8 ] > ,
65
75
cb : & mut dyn FnMut ( InstructionPart ) -> Result < ( ) > ,
66
76
) -> Result < ( ) > {
67
77
let opcode = u16:: from_be_bytes ( resolved. code . try_into ( ) . unwrap ( ) ) ;
68
78
let mut parts: Vec < InstructionPart > = vec ! [ ] ;
69
79
let mut branch_dest: Option < u64 > = None ;
80
+
70
81
sh2_disasm ( 0 , opcode, true , & mut parts, & resolved, & mut branch_dest) ;
71
82
83
+ if let Some ( code) = _code {
84
+ // scan for data
85
+ // map of instruction offsets to data target offsets
86
+ let mut data_offsets: HashMap < u64 , DataInfo > = HashMap :: < u64 , DataInfo > :: new ( ) ;
87
+
88
+ let mut pos: u64 = 0 ;
89
+ for chunk in code. chunks_exact ( 2 ) {
90
+ let opcode = u16:: from_be_bytes ( chunk. try_into ( ) . unwrap ( ) ) ;
91
+ // mov.w
92
+ if ( opcode & 0xf000 ) == 0x9000 {
93
+ let target = ( opcode as u64 & 0xff ) * 2 + 4 + pos;
94
+ let data_info = DataInfo { address : target, size : 2 } ;
95
+ data_offsets. insert ( pos, data_info) ;
96
+ }
97
+ // mov.l
98
+ else if ( opcode & 0xf000 ) == 0xd000 {
99
+ let target = ( ( opcode as u64 & 0xff ) * 4 + 4 + pos) & 0xfffffffc ;
100
+ let data_info = DataInfo { address : target, size : 4 } ;
101
+ data_offsets. insert ( pos, data_info) ;
102
+ }
103
+ pos += 2 ;
104
+ }
105
+
106
+ let pos = resolved. ins_ref . address - resolved. symbol . address ;
107
+ let a = resolved. ins_ref . address ;
108
+ let b = resolved. symbol . address ;
109
+
110
+ // add the data info
111
+ if let Some ( value) = data_offsets. get ( & pos) {
112
+ if value. size == 2 && value. address as usize + 1 < code. len ( ) {
113
+ let data = u16:: from_be_bytes (
114
+ code[ value. address as usize ..value. address as usize + 2 ]
115
+ . try_into ( )
116
+ . unwrap ( ) ,
117
+ ) ;
118
+ parts. push ( InstructionPart :: basic ( " /* " ) ) ;
119
+ parts. push ( InstructionPart :: basic ( "0x" ) ) ;
120
+ parts. push ( InstructionPart :: basic ( format ! ( "{:04X}" , data) ) ) ;
121
+ parts. push ( InstructionPart :: basic ( " */" ) ) ;
122
+ } else if value. size == 4 && value. address as usize + 3 < code. len ( ) {
123
+ let data = u32:: from_be_bytes (
124
+ code[ value. address as usize ..value. address as usize + 4 ]
125
+ . try_into ( )
126
+ . unwrap ( ) ,
127
+ ) ;
128
+ parts. push ( InstructionPart :: basic ( " /* " ) ) ;
129
+ parts. push ( InstructionPart :: basic ( "0x" ) ) ;
130
+ parts. push ( InstructionPart :: basic ( format ! ( "{:08X}" , data) ) ) ;
131
+ parts. push ( InstructionPart :: basic ( " */" ) ) ;
132
+ }
133
+ }
134
+ }
135
+
72
136
for part in parts {
73
137
cb ( part) ?;
74
138
}
@@ -154,6 +218,7 @@ mod test {
154
218
155
219
use super :: * ;
156
220
use crate :: obj:: InstructionArg ;
221
+ use crate :: obj:: Symbol ;
157
222
158
223
impl Display for InstructionPart < ' _ > {
159
224
fn fmt ( & self , f : & mut fmt:: Formatter ) -> fmt:: Result {
@@ -201,6 +266,7 @@ mod test {
201
266
..Default :: default ( )
202
267
} ,
203
268
& DiffObjConfig :: default ( ) ,
269
+ None ,
204
270
& mut |part| {
205
271
parts. push ( part. into_static ( ) ) ;
206
272
Ok ( ( ) )
@@ -279,6 +345,7 @@ mod test {
279
345
..Default :: default ( )
280
346
} ,
281
347
& DiffObjConfig :: default ( ) ,
348
+ None ,
282
349
& mut |part| {
283
350
parts. push ( part. into_static ( ) ) ;
284
351
Ok ( ( ) )
@@ -362,6 +429,7 @@ mod test {
362
429
..Default :: default ( )
363
430
} ,
364
431
& DiffObjConfig :: default ( ) ,
432
+ None ,
365
433
& mut |part| {
366
434
parts. push ( part. into_static ( ) ) ;
367
435
Ok ( ( ) )
@@ -399,6 +467,7 @@ mod test {
399
467
..Default :: default ( )
400
468
} ,
401
469
& DiffObjConfig :: default ( ) ,
470
+ None ,
402
471
& mut |part| {
403
472
parts. push ( part. into_static ( ) ) ;
404
473
Ok ( ( ) )
@@ -448,6 +517,7 @@ mod test {
448
517
..Default :: default ( )
449
518
} ,
450
519
& DiffObjConfig :: default ( ) ,
520
+ None ,
451
521
& mut |part| {
452
522
parts. push ( part. into_static ( ) ) ;
453
523
Ok ( ( ) )
@@ -484,6 +554,7 @@ mod test {
484
554
..Default :: default ( )
485
555
} ,
486
556
& DiffObjConfig :: default ( ) ,
557
+ None ,
487
558
& mut |part| {
488
559
parts. push ( part. into_static ( ) ) ;
489
560
Ok ( ( ) )
@@ -523,6 +594,7 @@ mod test {
523
594
..Default :: default ( )
524
595
} ,
525
596
& DiffObjConfig :: default ( ) ,
597
+ None ,
526
598
& mut |part| {
527
599
parts. push ( part. into_static ( ) ) ;
528
600
Ok ( ( ) )
@@ -562,6 +634,7 @@ mod test {
562
634
..Default :: default ( )
563
635
} ,
564
636
& DiffObjConfig :: default ( ) ,
637
+ None ,
565
638
& mut |part| {
566
639
parts. push ( part. into_static ( ) ) ;
567
640
Ok ( ( ) )
@@ -594,6 +667,7 @@ mod test {
594
667
..Default :: default ( )
595
668
} ,
596
669
& DiffObjConfig :: default ( ) ,
670
+ None ,
597
671
& mut |part| {
598
672
parts. push ( part. into_static ( ) ) ;
599
673
Ok ( ( ) )
@@ -623,6 +697,85 @@ mod test {
623
697
..Default :: default ( )
624
698
} ,
625
699
& DiffObjConfig :: default ( ) ,
700
+ None ,
701
+ & mut |part| {
702
+ parts. push ( part. into_static ( ) ) ;
703
+ Ok ( ( ) )
704
+ } ,
705
+ )
706
+ . unwrap ( ) ;
707
+
708
+ let joined_str: String = parts. iter ( ) . map ( |part| format ! ( "{}" , part) ) . collect ( ) ;
709
+ assert_eq ! ( joined_str, expected_str. to_string( ) ) ;
710
+ }
711
+ }
712
+
713
+ #[ test]
714
+ fn test_func_0606_f378_mov_w_data_labeling ( ) {
715
+ let arch = ArchSuperH { } ;
716
+ let ops: & [ ( u16 , u32 , & str ) ] = & [ ( 0x9000 , 0x0606F378 , "mov.w @(0x4, pc), r0 /* 0x00B0 */" ) ] ;
717
+
718
+ let mut code = Vec :: new ( ) ;
719
+ code. extend_from_slice ( & 0x9000_u16 . to_be_bytes ( ) ) ;
720
+ code. extend_from_slice ( & 0x0009_u16 . to_be_bytes ( ) ) ;
721
+ code. extend_from_slice ( & 0x00B0_u16 . to_be_bytes ( ) ) ;
722
+
723
+ for & ( opcode, addr, expected_str) in ops {
724
+ let code_slice = & code;
725
+ let mut parts = Vec :: new ( ) ;
726
+
727
+ arch. display_instruction (
728
+ ResolvedInstructionRef {
729
+ ins_ref : InstructionRef { address : addr as u64 , size : 2 , opcode } ,
730
+ code : & opcode. to_be_bytes ( ) ,
731
+ symbol : & Symbol {
732
+ address : 0x0606F378 , // func base address
733
+ ..Default :: default ( )
734
+ } ,
735
+ ..Default :: default ( )
736
+ } ,
737
+ & DiffObjConfig :: default ( ) ,
738
+ Some ( code_slice) ,
739
+ & mut |part| {
740
+ parts. push ( part. into_static ( ) ) ;
741
+ Ok ( ( ) )
742
+ } ,
743
+ )
744
+ . unwrap ( ) ;
745
+
746
+ let joined_str: String = parts. iter ( ) . map ( |part| format ! ( "{}" , part) ) . collect ( ) ;
747
+ assert_eq ! ( joined_str, expected_str. to_string( ) ) ;
748
+ }
749
+ }
750
+
751
+ #[ test]
752
+ fn test_func_0606_f378_mov_l_data_labeling ( ) {
753
+ let arch = ArchSuperH { } ;
754
+ let ops: & [ ( u16 , u32 , & str ) ] =
755
+ & [ ( 0xd000 , 0x0606F378 , "mov.l @(0x4, pc), r0 /* 0x00B000B0 */" ) ] ;
756
+
757
+ let mut code = Vec :: new ( ) ;
758
+ code. extend_from_slice ( & 0xd000_u16 . to_be_bytes ( ) ) ;
759
+ code. extend_from_slice ( & 0x0009_u16 . to_be_bytes ( ) ) ;
760
+ code. extend_from_slice ( & 0x00B0_u16 . to_be_bytes ( ) ) ;
761
+ code. extend_from_slice ( & 0x00B0_u16 . to_be_bytes ( ) ) ;
762
+
763
+ for & ( opcode, addr, expected_str) in ops {
764
+ let code_slice = & code;
765
+ let mut parts = Vec :: new ( ) ;
766
+
767
+ arch. display_instruction (
768
+ ResolvedInstructionRef {
769
+ ins_ref : InstructionRef { address : addr as u64 , size : 2 , opcode } ,
770
+ code : & opcode. to_be_bytes ( ) ,
771
+ symbol : & Symbol {
772
+ address : 0x0606F378 , // func base address
773
+ ..Default :: default ( )
774
+ } ,
775
+ ..Default :: default ( )
776
+ } ,
777
+ & DiffObjConfig :: default ( ) ,
778
+ Some ( code_slice) ,
626
779
& mut |part| {
627
780
parts. push ( part. into_static ( ) ) ;
628
781
Ok ( ( ) )
0 commit comments