|
1 #include <stdlib.h> |
|
2 #include <string.h> |
|
3 |
|
4 #include "ia32_invariant.h" |
|
5 #include "ia32_insn.h" |
|
6 #include "ia32_settings.h" |
|
7 |
|
8 extern ia32_table_desc_t *ia32_tables; |
|
9 extern ia32_settings_t ia32_settings; |
|
10 |
|
11 extern size_t ia32_table_lookup( unsigned char *buf, size_t buf_len, |
|
12 unsigned int table, ia32_insn_t **raw_insn, |
|
13 unsigned int *prefixes ); |
|
14 |
|
15 |
|
16 /* -------------------------------- ModR/M, SIB */ |
|
17 /* Convenience flags */ |
|
18 #define MODRM_EA 1 /* ModR/M is an effective addr */ |
|
19 #define MODRM_reg 2 /* ModR/M is a register */ |
|
20 |
|
21 /* ModR/M flags */ |
|
22 #define MODRM_RM_SIB 0x04 /* R/M == 100 */ |
|
23 #define MODRM_RM_NOREG 0x05 /* R/B == 101 */ |
|
24 /* if (MODRM.MOD_NODISP && MODRM.RM_NOREG) then just disp32 */ |
|
25 #define MODRM_MOD_NODISP 0x00 /* mod == 00 */ |
|
26 #define MODRM_MOD_DISP8 0x01 /* mod == 01 */ |
|
27 #define MODRM_MOD_DISP32 0x02 /* mod == 10 */ |
|
28 #define MODRM_MOD_NOEA 0x03 /* mod == 11 */ |
|
29 /* 16-bit modrm flags */ |
|
30 #define MOD16_MOD_NODISP 0 |
|
31 #define MOD16_MOD_DISP8 1 |
|
32 #define MOD16_MOD_DISP16 2 |
|
33 #define MOD16_MOD_REG 3 |
|
34 |
|
35 #define MOD16_RM_BXSI 0 |
|
36 #define MOD16_RM_BXDI 1 |
|
37 #define MOD16_RM_BPSI 2 |
|
38 #define MOD16_RM_BPDI 3 |
|
39 #define MOD16_RM_SI 4 |
|
40 #define MOD16_RM_DI 5 |
|
41 #define MOD16_RM_BP 6 |
|
42 #define MOD16_RM_BX 7 |
|
43 |
|
44 /* SIB flags */ |
|
45 #define SIB_INDEX_NONE 0x04 |
|
46 #define SIB_BASE_EBP 0x05 |
|
47 #define SIB_SCALE_NOBASE 0x00 |
|
48 |
|
49 /* Convenience struct for modR/M bitfield */ |
|
50 struct modRM_byte { |
|
51 unsigned int mod : 2; |
|
52 unsigned int reg : 3; |
|
53 unsigned int rm : 3; |
|
54 }; |
|
55 |
|
56 /* Convenience struct for SIB bitfield */ |
|
57 struct SIB_byte { |
|
58 unsigned int scale : 2; |
|
59 unsigned int index : 3; |
|
60 unsigned int base : 3; |
|
61 }; |
|
62 |
|
63 #ifdef WIN32 |
|
64 static void byte_decode(unsigned char b, struct modRM_byte *modrm) { |
|
65 #else |
|
66 static inline void byte_decode(unsigned char b, struct modRM_byte *modrm) { |
|
67 #endif |
|
68 /* generic bitfield-packing routine */ |
|
69 |
|
70 modrm->mod = b >> 6; /* top 2 bits */ |
|
71 modrm->reg = (b & 56) >> 3; /* middle 3 bits */ |
|
72 modrm->rm = b & 7; /* bottom 3 bits */ |
|
73 } |
|
74 static int ia32_invariant_modrm( unsigned char *in, unsigned char *out, |
|
75 unsigned int mode_16, x86_invariant_op_t *op) { |
|
76 struct modRM_byte modrm; |
|
77 struct SIB_byte sib; |
|
78 unsigned char *c, *cin; |
|
79 unsigned short *s; |
|
80 unsigned int *i; |
|
81 int size = 0; /* modrm byte is already counted */ |
|
82 |
|
83 |
|
84 byte_decode(*in, &modrm); /* get bitfields */ |
|
85 |
|
86 out[0] = in[0]; /* save modrm byte */ |
|
87 cin = &in[1]; |
|
88 c = &out[1]; |
|
89 s = (unsigned short *)&out[1]; |
|
90 i = (unsigned int *)&out[1]; |
|
91 |
|
92 op->type = op_expression; |
|
93 op->flags |= op_pointer; |
|
94 if ( ! mode_16 && modrm.rm == MODRM_RM_SIB && |
|
95 modrm.mod != MODRM_MOD_NOEA ) { |
|
96 size ++; |
|
97 byte_decode(*cin, (struct modRM_byte *)(void*)&sib); |
|
98 |
|
99 out[1] = in[1]; /* save sib byte */ |
|
100 cin = &in[2]; |
|
101 c = &out[2]; |
|
102 s = (unsigned short *)&out[2]; |
|
103 i = (unsigned int *)&out[2]; |
|
104 |
|
105 if ( sib.base == SIB_BASE_EBP && ! modrm.mod ) { |
|
106 /* disp 32 is variant! */ |
|
107 memset( i, X86_WILDCARD_BYTE, 4 ); |
|
108 size += 4; |
|
109 } |
|
110 } |
|
111 |
|
112 if (! modrm.mod && modrm.rm == 101) { |
|
113 if ( mode_16 ) { /* straight RVA in disp */ |
|
114 memset( s, X86_WILDCARD_BYTE, 2 ); |
|
115 size += 2; |
|
116 } else { |
|
117 memset( i, X86_WILDCARD_BYTE, 2 ); |
|
118 size += 4; |
|
119 } |
|
120 } else if (modrm.mod && modrm.mod < 3) { |
|
121 if (modrm.mod == MODRM_MOD_DISP8) { /* offset in disp */ |
|
122 *c = *cin; |
|
123 size += 1; |
|
124 } else if ( mode_16 ) { |
|
125 *s = (* ((unsigned short *) cin)); |
|
126 size += 2; |
|
127 } else { |
|
128 *i = (*((unsigned int *) cin)); |
|
129 size += 4; |
|
130 } |
|
131 } else if ( modrm.mod == 3 ) { |
|
132 op->type = op_register; |
|
133 op->flags &= ~op_pointer; |
|
134 } |
|
135 |
|
136 return (size); |
|
137 } |
|
138 |
|
139 |
|
140 static int ia32_decode_invariant( unsigned char *buf, size_t buf_len, |
|
141 ia32_insn_t *t, unsigned char *out, |
|
142 unsigned int prefixes, x86_invariant_t *inv) { |
|
143 |
|
144 unsigned int addr_size, op_size, mode_16; |
|
145 unsigned int op_flags[3] = { t->dest_flag, t->src_flag, t->aux_flag }; |
|
146 int x, type, bytes = 0, size = 0, modrm = 0; |
|
147 |
|
148 /* set addressing mode */ |
|
149 if (ia32_settings.options & opt_16_bit) { |
|
150 op_size = ( prefixes & PREFIX_OP_SIZE ) ? 4 : 2; |
|
151 addr_size = ( prefixes & PREFIX_ADDR_SIZE ) ? 4 : 2; |
|
152 mode_16 = ( prefixes & PREFIX_ADDR_SIZE ) ? 0 : 1; |
|
153 } else { |
|
154 op_size = ( prefixes & PREFIX_OP_SIZE ) ? 2 : 4; |
|
155 addr_size = ( prefixes & PREFIX_ADDR_SIZE ) ? 2 : 4; |
|
156 mode_16 = ( prefixes & PREFIX_ADDR_SIZE ) ? 1 : 0; |
|
157 } |
|
158 |
|
159 for (x = 0; x < 3; x++) { |
|
160 inv->operands[x].access = (enum x86_op_access) |
|
161 OP_PERM(op_flags[x]); |
|
162 inv->operands[x].flags = (enum x86_op_flags) |
|
163 (OP_FLAGS(op_flags[x]) >> 12); |
|
164 |
|
165 switch (op_flags[x] & OPTYPE_MASK) { |
|
166 case OPTYPE_c: |
|
167 size = (op_size == 4) ? 2 : 1; |
|
168 break; |
|
169 case OPTYPE_a: case OPTYPE_v: |
|
170 size = (op_size == 4) ? 4 : 2; |
|
171 break; |
|
172 case OPTYPE_p: |
|
173 size = (op_size == 4) ? 6 : 4; |
|
174 break; |
|
175 case OPTYPE_b: |
|
176 size = 1; |
|
177 break; |
|
178 case OPTYPE_w: |
|
179 size = 2; |
|
180 break; |
|
181 case OPTYPE_d: case OPTYPE_fs: case OPTYPE_fd: |
|
182 case OPTYPE_fe: case OPTYPE_fb: case OPTYPE_fv: |
|
183 case OPTYPE_si: case OPTYPE_fx: |
|
184 size = 4; |
|
185 break; |
|
186 case OPTYPE_s: |
|
187 size = 6; |
|
188 break; |
|
189 case OPTYPE_q: case OPTYPE_pi: |
|
190 size = 8; |
|
191 break; |
|
192 case OPTYPE_dq: case OPTYPE_ps: case OPTYPE_ss: |
|
193 case OPTYPE_pd: case OPTYPE_sd: |
|
194 size = 16; |
|
195 break; |
|
196 case OPTYPE_m: |
|
197 size = (addr_size == 4) ? 4 : 2; |
|
198 break; |
|
199 default: |
|
200 break; |
|
201 } |
|
202 |
|
203 type = op_flags[x] & ADDRMETH_MASK; |
|
204 switch (type) { |
|
205 case ADDRMETH_E: case ADDRMETH_M: case ADDRMETH_Q: |
|
206 case ADDRMETH_R: case ADDRMETH_W: |
|
207 modrm = 1; |
|
208 bytes += ia32_invariant_modrm( buf, out, |
|
209 mode_16, &inv->operands[x]); |
|
210 break; |
|
211 case ADDRMETH_C: case ADDRMETH_D: case ADDRMETH_G: |
|
212 case ADDRMETH_P: case ADDRMETH_S: case ADDRMETH_T: |
|
213 case ADDRMETH_V: |
|
214 inv->operands[x].type = op_register; |
|
215 modrm = 1; |
|
216 break; |
|
217 case ADDRMETH_A: case ADDRMETH_O: |
|
218 /* pad with xF4's */ |
|
219 memset( &out[bytes + modrm], X86_WILDCARD_BYTE, |
|
220 size ); |
|
221 bytes += size; |
|
222 inv->operands[x].type = op_offset; |
|
223 if ( type == ADDRMETH_O ) { |
|
224 inv->operands[x].flags |= op_signed | |
|
225 op_pointer; |
|
226 } |
|
227 break; |
|
228 case ADDRMETH_I: case ADDRMETH_J: |
|
229 /* grab imm value */ |
|
230 if ((op_flags[x] & OPTYPE_MASK) == OPTYPE_v) { |
|
231 /* assume this is an address */ |
|
232 memset( &out[bytes + modrm], |
|
233 X86_WILDCARD_BYTE, size ); |
|
234 } else { |
|
235 memcpy( &out[bytes + modrm], |
|
236 &buf[bytes + modrm], size ); |
|
237 } |
|
238 |
|
239 bytes += size; |
|
240 if ( type == ADDRMETH_J ) { |
|
241 if ( size == 1 ) { |
|
242 inv->operands[x].type = |
|
243 op_relative_near; |
|
244 } else { |
|
245 inv->operands[x].type = |
|
246 op_relative_far; |
|
247 } |
|
248 inv->operands[x].flags |= op_signed; |
|
249 } else { |
|
250 inv->operands[x].type = op_immediate; |
|
251 } |
|
252 break; |
|
253 case ADDRMETH_F: |
|
254 inv->operands[x].type = op_register; |
|
255 break; |
|
256 case ADDRMETH_X: |
|
257 inv->operands[x].flags |= op_signed | |
|
258 op_pointer | op_ds_seg | op_string; |
|
259 break; |
|
260 case ADDRMETH_Y: |
|
261 inv->operands[x].flags |= op_signed | |
|
262 op_pointer | op_es_seg | op_string; |
|
263 break; |
|
264 case ADDRMETH_RR: |
|
265 inv->operands[x].type = op_register; |
|
266 break; |
|
267 case ADDRMETH_II: |
|
268 inv->operands[x].type = op_immediate; |
|
269 break; |
|
270 default: |
|
271 inv->operands[x].type = op_unused; |
|
272 break; |
|
273 } |
|
274 } |
|
275 |
|
276 return (bytes + modrm); |
|
277 } |
|
278 |
|
279 size_t ia32_disasm_invariant( unsigned char * buf, size_t buf_len, |
|
280 x86_invariant_t *inv ) { |
|
281 ia32_insn_t *raw_insn = NULL; |
|
282 unsigned int prefixes; |
|
283 unsigned int type; |
|
284 size_t size; |
|
285 |
|
286 /* Perform recursive table lookup starting with main table (0) */ |
|
287 size = ia32_table_lookup( buf, buf_len, 0, &raw_insn, &prefixes ); |
|
288 if ( size == INVALID_INSN || size > buf_len ) { |
|
289 /* TODO: set errno */ |
|
290 return 0; |
|
291 } |
|
292 |
|
293 /* copy opcode bytes to buffer */ |
|
294 memcpy( inv->bytes, buf, size ); |
|
295 |
|
296 /* set mnemonic type and group */ |
|
297 type = raw_insn->mnem_flag & ~INS_FLAG_MASK; |
|
298 inv->group = (enum x86_insn_group) (INS_GROUP(type)) >> 12; |
|
299 inv->type = (enum x86_insn_type) INS_TYPE(type); |
|
300 |
|
301 /* handle operands */ |
|
302 size += ia32_decode_invariant( buf + size, buf_len - size, raw_insn, |
|
303 &buf[size - 1], prefixes, inv ); |
|
304 |
|
305 inv->size = size; |
|
306 |
|
307 return size; /* return size of instruction in bytes */ |
|
308 } |
|
309 |
|
310 size_t ia32_disasm_size( unsigned char *buf, size_t buf_len ) { |
|
311 x86_invariant_t inv = { {0} }; |
|
312 return( ia32_disasm_invariant( buf, buf_len, &inv ) ); |
|
313 } |