1
1
use alloc:: { string:: String , vec:: Vec } ;
2
+ use std:: collections:: HashMap ;
2
3
3
4
use anyhow:: { Result , bail} ;
4
5
use object:: elf;
@@ -20,6 +21,11 @@ impl ArchSuperH {
20
21
pub fn new ( _file : & object:: File ) -> Result < Self > { Ok ( Self { } ) }
21
22
}
22
23
24
+ struct DataInfo {
25
+ address : u64 ,
26
+ size : u32 ,
27
+ }
28
+
23
29
impl Arch for ArchSuperH {
24
30
fn scan_instructions (
25
31
& self ,
@@ -31,6 +37,7 @@ impl Arch for ArchSuperH {
31
37
) -> Result < Vec < ScannedInstruction > > {
32
38
let mut ops = Vec :: < ScannedInstruction > :: with_capacity ( code. len ( ) / 2 ) ;
33
39
let mut offset = address;
40
+
34
41
for chunk in code. chunks_exact ( 2 ) {
35
42
let opcode = u16:: from_be_bytes ( chunk. try_into ( ) . unwrap ( ) ) ;
36
43
let mut parts: Vec < InstructionPart > = vec ! [ ] ;
@@ -67,8 +74,60 @@ impl Arch for ArchSuperH {
67
74
let opcode = u16:: from_be_bytes ( resolved. code . try_into ( ) . unwrap ( ) ) ;
68
75
let mut parts: Vec < InstructionPart > = vec ! [ ] ;
69
76
let mut branch_dest: Option < u64 > = None ;
77
+
70
78
sh2_disasm ( 0 , opcode, true , & mut parts, & resolved, & mut branch_dest) ;
71
79
80
+ if let Some ( symbol_data) = resolved. section . symbol_data ( resolved. symbol ) {
81
+ // scan for data
82
+ // map of instruction offsets to data target offsets
83
+ let mut data_offsets: HashMap < u64 , DataInfo > = HashMap :: < u64 , DataInfo > :: new ( ) ;
84
+
85
+ let mut pos: u64 = 0 ;
86
+ for chunk in symbol_data. chunks_exact ( 2 ) {
87
+ let opcode = u16:: from_be_bytes ( chunk. try_into ( ) . unwrap ( ) ) ;
88
+ // mov.w
89
+ if ( opcode & 0xf000 ) == 0x9000 {
90
+ let target = ( opcode as u64 & 0xff ) * 2 + 4 + pos;
91
+ let data_info = DataInfo { address : target, size : 2 } ;
92
+ data_offsets. insert ( pos, data_info) ;
93
+ }
94
+ // mov.l
95
+ else if ( opcode & 0xf000 ) == 0xd000 {
96
+ let target = ( ( opcode as u64 & 0xff ) * 4 + 4 + pos) & 0xfffffffc ;
97
+ let data_info = DataInfo { address : target, size : 4 } ;
98
+ data_offsets. insert ( pos, data_info) ;
99
+ }
100
+ pos += 2 ;
101
+ }
102
+
103
+ let pos = resolved. ins_ref . address - resolved. symbol . address ;
104
+
105
+ // add the data info
106
+ if let Some ( value) = data_offsets. get ( & pos) {
107
+ if value. size == 2 && value. address as usize + 1 < symbol_data. len ( ) {
108
+ let data = u16:: from_be_bytes (
109
+ symbol_data[ value. address as usize ..value. address as usize + 2 ]
110
+ . try_into ( )
111
+ . unwrap ( ) ,
112
+ ) ;
113
+ parts. push ( InstructionPart :: basic ( " /* " ) ) ;
114
+ parts. push ( InstructionPart :: basic ( "0x" ) ) ;
115
+ parts. push ( InstructionPart :: basic ( format ! ( "{:04X}" , data) ) ) ;
116
+ parts. push ( InstructionPart :: basic ( " */" ) ) ;
117
+ } else if value. size == 4 && value. address as usize + 3 < symbol_data. len ( ) {
118
+ let data = u32:: from_be_bytes (
119
+ symbol_data[ value. address as usize ..value. address as usize + 4 ]
120
+ . try_into ( )
121
+ . unwrap ( ) ,
122
+ ) ;
123
+ parts. push ( InstructionPart :: basic ( " /* " ) ) ;
124
+ parts. push ( InstructionPart :: basic ( "0x" ) ) ;
125
+ parts. push ( InstructionPart :: basic ( format ! ( "{:08X}" , data) ) ) ;
126
+ parts. push ( InstructionPart :: basic ( " */" ) ) ;
127
+ }
128
+ }
129
+ }
130
+
72
131
for part in parts {
73
132
cb ( part) ?;
74
133
}
@@ -153,7 +212,7 @@ mod test {
153
212
use std:: fmt:: { self , Display } ;
154
213
155
214
use super :: * ;
156
- use crate :: obj:: InstructionArg ;
215
+ use crate :: obj:: { InstructionArg , Section , SectionData , Symbol } ;
157
216
158
217
impl Display for InstructionPart < ' _ > {
159
218
fn fmt ( & self , f : & mut fmt:: Formatter ) -> fmt:: Result {
@@ -634,4 +693,92 @@ mod test {
634
693
assert_eq ! ( joined_str, expected_str. to_string( ) ) ;
635
694
}
636
695
}
696
+
697
+ #[ test]
698
+ fn test_func_0606_f378_mov_w_data_labeling ( ) {
699
+ let arch = ArchSuperH { } ;
700
+ let ops: & [ ( u16 , u32 , & str ) ] = & [ ( 0x9000 , 0x0606F378 , "mov.w @(0x4, pc), r0 /* 0x00B0 */" ) ] ;
701
+
702
+ let mut code = Vec :: new ( ) ;
703
+ code. extend_from_slice ( & 0x9000_u16 . to_be_bytes ( ) ) ;
704
+ code. extend_from_slice ( & 0x0009_u16 . to_be_bytes ( ) ) ;
705
+ code. extend_from_slice ( & 0x00B0_u16 . to_be_bytes ( ) ) ;
706
+
707
+ for & ( opcode, addr, expected_str) in ops {
708
+ let mut parts = Vec :: new ( ) ;
709
+
710
+ arch. display_instruction (
711
+ ResolvedInstructionRef {
712
+ ins_ref : InstructionRef { address : addr as u64 , size : 2 , opcode } ,
713
+ code : & opcode. to_be_bytes ( ) ,
714
+ symbol : & Symbol {
715
+ address : 0x0606F378 , // func base address
716
+ size : code. len ( ) as u64 ,
717
+ ..Default :: default ( )
718
+ } ,
719
+ section : & Section {
720
+ address : 0x0606F378 ,
721
+ size : code. len ( ) as u64 ,
722
+ data : SectionData ( code. clone ( ) ) ,
723
+ ..Default :: default ( )
724
+ } ,
725
+ ..Default :: default ( )
726
+ } ,
727
+ & DiffObjConfig :: default ( ) ,
728
+ & mut |part| {
729
+ parts. push ( part. into_static ( ) ) ;
730
+ Ok ( ( ) )
731
+ } ,
732
+ )
733
+ . unwrap ( ) ;
734
+
735
+ let joined_str: String = parts. iter ( ) . map ( |part| format ! ( "{}" , part) ) . collect ( ) ;
736
+ assert_eq ! ( joined_str, expected_str. to_string( ) ) ;
737
+ }
738
+ }
739
+
740
+ #[ test]
741
+ fn test_func_0606_f378_mov_l_data_labeling ( ) {
742
+ let arch = ArchSuperH { } ;
743
+ let ops: & [ ( u16 , u32 , & str ) ] =
744
+ & [ ( 0xd000 , 0x0606F378 , "mov.l @(0x4, pc), r0 /* 0x00B000B0 */" ) ] ;
745
+
746
+ let mut code = Vec :: new ( ) ;
747
+ code. extend_from_slice ( & 0xd000_u16 . to_be_bytes ( ) ) ;
748
+ code. extend_from_slice ( & 0x0009_u16 . to_be_bytes ( ) ) ;
749
+ code. extend_from_slice ( & 0x00B0_u16 . to_be_bytes ( ) ) ;
750
+ code. extend_from_slice ( & 0x00B0_u16 . to_be_bytes ( ) ) ;
751
+
752
+ for & ( opcode, addr, expected_str) in ops {
753
+ let mut parts = Vec :: new ( ) ;
754
+
755
+ arch. display_instruction (
756
+ ResolvedInstructionRef {
757
+ ins_ref : InstructionRef { address : addr as u64 , size : 2 , opcode } ,
758
+ code : & opcode. to_be_bytes ( ) ,
759
+ symbol : & Symbol {
760
+ address : 0x0606F378 , // func base address
761
+ size : code. len ( ) as u64 ,
762
+ ..Default :: default ( )
763
+ } ,
764
+ section : & Section {
765
+ address : 0x0606F378 ,
766
+ size : code. len ( ) as u64 ,
767
+ data : SectionData ( code. clone ( ) ) ,
768
+ ..Default :: default ( )
769
+ } ,
770
+ ..Default :: default ( )
771
+ } ,
772
+ & DiffObjConfig :: default ( ) ,
773
+ & mut |part| {
774
+ parts. push ( part. into_static ( ) ) ;
775
+ Ok ( ( ) )
776
+ } ,
777
+ )
778
+ . unwrap ( ) ;
779
+
780
+ let joined_str: String = parts. iter ( ) . map ( |part| format ! ( "{}" , part) ) . collect ( ) ;
781
+ assert_eq ! ( joined_str, expected_str. to_string( ) ) ;
782
+ }
783
+ }
637
784
}
0 commit comments