11use alloc:: { string:: String , vec:: Vec } ;
2+ use std:: collections:: HashMap ;
23
34use anyhow:: { Result , bail} ;
45use object:: elf;
@@ -20,6 +21,11 @@ impl ArchSuperH {
2021 pub fn new ( _file : & object:: File ) -> Result < Self > { Ok ( Self { } ) }
2122}
2223
24+ struct DataInfo {
25+ address : u64 ,
26+ size : u32 ,
27+ }
28+
2329impl Arch for ArchSuperH {
2430 fn scan_instructions (
2531 & self ,
@@ -31,6 +37,7 @@ impl Arch for ArchSuperH {
3137 ) -> Result < Vec < ScannedInstruction > > {
3238 let mut ops = Vec :: < ScannedInstruction > :: with_capacity ( code. len ( ) / 2 ) ;
3339 let mut offset = address;
40+
3441 for chunk in code. chunks_exact ( 2 ) {
3542 let opcode = u16:: from_be_bytes ( chunk. try_into ( ) . unwrap ( ) ) ;
3643 let mut parts: Vec < InstructionPart > = vec ! [ ] ;
@@ -67,8 +74,60 @@ impl Arch for ArchSuperH {
6774 let opcode = u16:: from_be_bytes ( resolved. code . try_into ( ) . unwrap ( ) ) ;
6875 let mut parts: Vec < InstructionPart > = vec ! [ ] ;
6976 let mut branch_dest: Option < u64 > = None ;
77+
7078 sh2_disasm ( 0 , opcode, true , & mut parts, & resolved, & mut branch_dest) ;
7179
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+
72131 for part in parts {
73132 cb ( part) ?;
74133 }
@@ -153,7 +212,7 @@ mod test {
153212 use std:: fmt:: { self , Display } ;
154213
155214 use super :: * ;
156- use crate :: obj:: InstructionArg ;
215+ use crate :: obj:: { InstructionArg , Section , SectionData , Symbol } ;
157216
158217 impl Display for InstructionPart < ' _ > {
159218 fn fmt ( & self , f : & mut fmt:: Formatter ) -> fmt:: Result {
@@ -634,4 +693,92 @@ mod test {
634693 assert_eq ! ( joined_str, expected_str. to_string( ) ) ;
635694 }
636695 }
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+ }
637784}
0 commit comments