1
- use std:: borrow:: Cow ;
1
+ use std:: { borrow:: Cow , sync :: Mutex } ;
2
2
3
3
use anyhow:: { anyhow, bail, Result } ;
4
- use object:: { elf, Endian , Endianness , File , Object , Relocation , RelocationFlags } ;
4
+ use object:: { elf, Endian , Endianness , File , FileFlags , Object , Relocation , RelocationFlags } ;
5
5
use rabbitizer:: { config, Abi , InstrCategory , Instruction , OperandType } ;
6
6
7
7
use crate :: {
8
8
arch:: { ObjArch , ProcessCodeResult } ,
9
- diff:: DiffObjConfig ,
9
+ diff:: { DiffObjConfig , MipsAbi , MipsInstrCategory } ,
10
10
obj:: { ObjInfo , ObjIns , ObjInsArg , ObjInsArgValue , ObjReloc , ObjSection , SymbolRef } ,
11
11
} ;
12
12
13
- fn configure_rabbitizer ( ) {
13
+ static RABBITIZER_MUTEX : Mutex < ( ) > = Mutex :: new ( ( ) ) ;
14
+
15
+ fn configure_rabbitizer ( abi : Abi ) {
14
16
unsafe {
15
- config:: RabbitizerConfig_Cfg . reg_names . fpr_abi_names = Abi :: O32 ;
17
+ config:: RabbitizerConfig_Cfg . reg_names . fpr_abi_names = abi ;
16
18
}
17
19
}
18
20
19
21
pub struct ObjArchMips {
20
22
pub endianness : Endianness ,
23
+ pub abi : Abi ,
24
+ pub instr_category : InstrCategory ,
21
25
}
22
26
27
+ const EF_MIPS_ABI : u32 = 0x0000F000 ;
28
+ const EF_MIPS_MACH : u32 = 0x00FF0000 ;
29
+
30
+ const E_MIPS_MACH_ALLEGREX : u32 = 0x00840000 ;
31
+ const E_MIPS_MACH_5900 : u32 = 0x00920000 ;
32
+
23
33
impl ObjArchMips {
24
34
pub fn new ( object : & File ) -> Result < Self > {
25
- configure_rabbitizer ( ) ;
26
- Ok ( Self { endianness : object. endianness ( ) } )
35
+ let mut abi = Abi :: NUMERIC ;
36
+ let mut instr_category = InstrCategory :: CPU ;
37
+ match object. flags ( ) {
38
+ FileFlags :: None => { }
39
+ FileFlags :: Elf { e_flags, .. } => {
40
+ abi = match e_flags & EF_MIPS_ABI {
41
+ elf:: EF_MIPS_ABI_O32 => Abi :: O32 ,
42
+ elf:: EF_MIPS_ABI_EABI32 | elf:: EF_MIPS_ABI_EABI64 => Abi :: N32 ,
43
+ _ => Abi :: NUMERIC ,
44
+ } ;
45
+ instr_category = match e_flags & EF_MIPS_MACH {
46
+ E_MIPS_MACH_ALLEGREX => InstrCategory :: R4000ALLEGREX ,
47
+ E_MIPS_MACH_5900 => InstrCategory :: R5900 ,
48
+ _ => InstrCategory :: CPU ,
49
+ } ;
50
+ }
51
+ _ => bail ! ( "Unsupported MIPS file flags" ) ,
52
+ }
53
+ Ok ( Self { endianness : object. endianness ( ) , abi, instr_category } )
27
54
}
28
55
}
29
56
@@ -39,6 +66,22 @@ impl ObjArch for ObjArchMips {
39
66
let code = & section. data
40
67
[ symbol. section_address as usize ..( symbol. section_address + symbol. size ) as usize ] ;
41
68
69
+ let _guard = RABBITIZER_MUTEX . lock ( ) . map_err ( |e| anyhow ! ( "Failed to lock mutex: {e}" ) ) ?;
70
+ configure_rabbitizer ( match config. mips_abi {
71
+ MipsAbi :: Auto => self . abi ,
72
+ MipsAbi :: O32 => Abi :: O32 ,
73
+ MipsAbi :: N32 => Abi :: N32 ,
74
+ MipsAbi :: N64 => Abi :: N64 ,
75
+ } ) ;
76
+ let instr_category = match config. mips_instr_category {
77
+ MipsInstrCategory :: Auto => self . instr_category ,
78
+ MipsInstrCategory :: Cpu => InstrCategory :: CPU ,
79
+ MipsInstrCategory :: Rsp => InstrCategory :: RSP ,
80
+ MipsInstrCategory :: R3000Gte => InstrCategory :: R3000GTE ,
81
+ MipsInstrCategory :: R4000Allegrex => InstrCategory :: R4000ALLEGREX ,
82
+ MipsInstrCategory :: R5900 => InstrCategory :: R5900 ,
83
+ } ;
84
+
42
85
let start_address = symbol. address ;
43
86
let end_address = symbol. address + symbol. size ;
44
87
let ins_count = code. len ( ) / 4 ;
@@ -48,7 +91,7 @@ impl ObjArch for ObjArchMips {
48
91
for chunk in code. chunks_exact ( 4 ) {
49
92
let reloc = section. relocations . iter ( ) . find ( |r| ( r. address as u32 & !3 ) == cur_addr) ;
50
93
let code = self . endianness . read_u32_bytes ( chunk. try_into ( ) ?) ;
51
- let instruction = Instruction :: new ( code, cur_addr, InstrCategory :: CPU ) ;
94
+ let instruction = Instruction :: new ( code, cur_addr, instr_category ) ;
52
95
53
96
let formatted = instruction. disassemble ( None , 0 ) ;
54
97
let op = instruction. unique_id as u16 ;
0 commit comments