1
- use std:: { borrow:: Cow , collections:: BTreeMap } ;
1
+ use std:: { borrow:: Cow , collections:: BTreeMap , ffi :: CStr } ;
2
2
3
3
use anyhow:: { bail, Result } ;
4
+ use byteorder:: ByteOrder ;
4
5
use object:: { Architecture , File , Object , ObjectSymbol , Relocation , RelocationFlags , Symbol } ;
5
6
6
7
use crate :: {
7
8
diff:: DiffObjConfig ,
8
9
obj:: { ObjIns , ObjReloc , ObjSection } ,
10
+ util:: ReallySigned ,
9
11
} ;
10
12
11
13
#[ cfg( feature = "arm" ) ]
@@ -17,6 +19,97 @@ pub mod ppc;
17
19
#[ cfg( feature = "x86" ) ]
18
20
pub mod x86;
19
21
22
+ /// Represents the type of data associated with an instruction
23
+ pub enum DataType {
24
+ Int8 ,
25
+ Int16 ,
26
+ Int32 ,
27
+ Int64 ,
28
+ Int128 ,
29
+ Float ,
30
+ Double ,
31
+ Bytes ,
32
+ String ,
33
+ }
34
+
35
+ impl DataType {
36
+ pub fn display_bytes < Endian : ByteOrder > ( & self , bytes : & [ u8 ] ) -> Option < String > {
37
+ if self . required_len ( ) . is_some_and ( |l| bytes. len ( ) < l) {
38
+ return None ;
39
+ }
40
+
41
+ match self {
42
+ DataType :: Int8 => {
43
+ let i = i8:: from_ne_bytes ( bytes. try_into ( ) . unwrap ( ) ) ;
44
+ if i < 0 {
45
+ format ! ( "Int8: {:#x} ({:#x})" , i, ReallySigned ( i) )
46
+ } else {
47
+ format ! ( "Int8: {:#x}" , i)
48
+ }
49
+ }
50
+ DataType :: Int16 => {
51
+ let i = Endian :: read_i16 ( bytes) ;
52
+ if i < 0 {
53
+ format ! ( "Int16: {:#x} ({:#x})" , i, ReallySigned ( i) )
54
+ } else {
55
+ format ! ( "Int16: {:#x}" , i)
56
+ }
57
+ }
58
+ DataType :: Int32 => {
59
+ let i = Endian :: read_i32 ( bytes) ;
60
+ if i < 0 {
61
+ format ! ( "Int32: {:#x} ({:#x})" , i, ReallySigned ( i) )
62
+ } else {
63
+ format ! ( "Int32: {:#x}" , i)
64
+ }
65
+ }
66
+ DataType :: Int64 => {
67
+ let i = Endian :: read_i64 ( bytes) ;
68
+ if i < 0 {
69
+ format ! ( "Int64: {:#x} ({:#x})" , i, ReallySigned ( i) )
70
+ } else {
71
+ format ! ( "Int64: {:#x}" , i)
72
+ }
73
+ }
74
+ DataType :: Int128 => {
75
+ let i = Endian :: read_i128 ( bytes) ;
76
+ if i < 0 {
77
+ format ! ( "Int128: {:#x} ({:#x})" , i, ReallySigned ( i) )
78
+ } else {
79
+ format ! ( "Int128: {:#x}" , i)
80
+ }
81
+ }
82
+ DataType :: Float => {
83
+ format ! ( "Float: {}" , Endian :: read_f32( bytes) )
84
+ }
85
+ DataType :: Double => {
86
+ format ! ( "Double: {}" , Endian :: read_f64( bytes) )
87
+ }
88
+ DataType :: Bytes => {
89
+ format ! ( "Bytes: {:#?}" , bytes)
90
+ }
91
+ DataType :: String => {
92
+ format ! ( "String: {:?}" , CStr :: from_bytes_until_nul( bytes) . ok( ) ?)
93
+ }
94
+ }
95
+ . into ( )
96
+ }
97
+
98
+ fn required_len ( & self ) -> Option < usize > {
99
+ match self {
100
+ DataType :: Int8 => Some ( 1 ) ,
101
+ DataType :: Int16 => Some ( 2 ) ,
102
+ DataType :: Int32 => Some ( 4 ) ,
103
+ DataType :: Int64 => Some ( 8 ) ,
104
+ DataType :: Int128 => Some ( 16 ) ,
105
+ DataType :: Float => Some ( 4 ) ,
106
+ DataType :: Double => Some ( 8 ) ,
107
+ DataType :: Bytes => None ,
108
+ DataType :: String => None ,
109
+ }
110
+ }
111
+ }
112
+
20
113
pub trait ObjArch : Send + Sync {
21
114
fn process_code (
22
115
& self ,
@@ -42,6 +135,12 @@ pub trait ObjArch: Send + Sync {
42
135
43
136
fn symbol_address ( & self , symbol : & Symbol ) -> u64 { symbol. address ( ) }
44
137
138
+ fn guess_data_type ( & self , _instruction : & ObjIns ) -> Option < DataType > { None }
139
+
140
+ fn display_data_type ( & self , _ty : DataType , bytes : & [ u8 ] ) -> Option < String > {
141
+ Some ( format ! ( "Bytes: {:#x?}" , bytes) )
142
+ }
143
+
45
144
// Downcast methods
46
145
#[ cfg( feature = "ppc" ) ]
47
146
fn ppc ( & self ) -> Option < & ppc:: ObjArchPpc > { None }
0 commit comments