OLD | NEW |
---|---|
1 /* | 1 /* |
2 * Copyright (c) 2011 The Native Client Authors. All rights reserved. | 2 * Copyright (c) 2011 The Native Client Authors. All rights reserved. |
3 * Use of this source code is governed by a BSD-style license that can be | 3 * Use of this source code is governed by a BSD-style license that can be |
4 * found in the LICENSE file. | 4 * found in the LICENSE file. |
5 */ | 5 */ |
6 | 6 |
7 /* | 7 /* |
8 * Defines an instruction (decoder), based on the current location of | 8 * This file contains includes, static functions, and constants that are used |
9 * the instruction iterator. The instruction decoder takes a list | 9 * in nc_inst_state.c, but have been factored out and put into this file, so |
10 * of candidate opcode (instruction) patterns, and searches for the | 10 * that we can test them. That is, to allow nc_inst_state.c and |
11 * first candidate that matches the requirements of the opcode pattern. | 11 * nc_inst_state_Tests.cc to use them. |
12 */ | 12 */ |
Brad Chen
2011/04/25 21:47:27
It would probably make sense to put in a #define p
Karl
2011/06/24 18:15:00
Done.
| |
13 | 13 |
14 #include <stdio.h> | 14 #include <stdio.h> |
15 #include <assert.h> | 15 #include <assert.h> |
16 | |
17 #include "native_client/src/trusted/validator_x86/nc_inst_state.h" | |
18 | |
19 #include "native_client/src/shared/platform/nacl_log.h" | 16 #include "native_client/src/shared/platform/nacl_log.h" |
20 #include "native_client/src/trusted/validator_x86/nc_inst_iter.h" | 17 #include "native_client/src/trusted/validator_x86/nc_inst_iter.h" |
21 #include "native_client/src/trusted/validator_x86/nc_inst_state_internal.h" | 18 #include "native_client/src/trusted/validator_x86/nc_inst_state_internal.h" |
22 #include "native_client/src/trusted/validator_x86/nc_inst_trans.h" | 19 #include "native_client/src/trusted/validator_x86/nc_inst_trans.h" |
23 #include "native_client/src/trusted/validator_x86/nc_segment.h" | 20 #include "native_client/src/trusted/validator_x86/nc_segment.h" |
24 #include "native_client/src/trusted/validator_x86/ncop_exps.h" | 21 #include "native_client/src/trusted/validator_x86/ncop_exps.h" |
25 #include "native_client/src/trusted/validator_x86/ncopcode_desc.h" | 22 #include "native_client/src/trusted/validator_x86/ncopcode_desc.h" |
26 #ifdef _WIN64 | 23 #ifdef _WIN64 |
27 #include "gen/native_client/src/trusted/validator_x86/nc_opcode_table64.h" | 24 #include "gen/native_client/src/trusted/validator_x86/nc_opcode_table64.h" |
28 #else | 25 #else |
29 #include "gen/native_client/src/trusted/validator_x86/nc_opcode_table.h" | 26 #include "gen/native_client/src/trusted/validator_x86/nc_opcode_table.h" |
30 #endif | 27 #endif |
31 | 28 #include "native_client/src/trusted/validator_x86/RexPrefixes.h" |
32 /* To turn on debugging of instruction decoding, change value of | |
33 * DEBUGGING to 1. | |
34 */ | |
35 #define DEBUGGING 0 | |
36 | 29 |
37 #include "native_client/src/shared/utils/debugging.h" | 30 #include "native_client/src/shared/utils/debugging.h" |
38 | 31 |
32 EXTERN_C_BEGIN | |
33 | |
39 /* Given the current location of the instruction iterator, initialize | 34 /* Given the current location of the instruction iterator, initialize |
40 * the given state (to match). | 35 * the given state (to match). |
41 */ | 36 */ |
42 static void NaClInstStateInit(NaClInstIter* iter, NaClInstState* state) { | 37 static void NaClInstStateInit(NaClInstIter* iter, NaClInstState* state) { |
43 NaClMemorySize limit; | 38 NaClMemorySize limit; |
44 NCInstBytesInit(&state->bytes); | 39 NCInstBytesInit(&state->bytes); |
45 state->vpc = iter->segment->vbase + iter->index; | 40 state->vpc = iter->segment->vbase + iter->index; |
46 limit = iter->segment->size - iter->index; | 41 limit = iter->segment->size - iter->index; |
47 if (limit > NACL_MAX_BYTES_PER_X86_INSTRUCTION) { | 42 if (limit > NACL_MAX_BYTES_PER_X86_INSTRUCTION) { |
48 limit = NACL_MAX_BYTES_PER_X86_INSTRUCTION; | 43 limit = NACL_MAX_BYTES_PER_X86_INSTRUCTION; |
(...skipping 17 matching lines...) Expand all Loading... | |
66 state->prefix_mask = 0; | 61 state->prefix_mask = 0; |
67 state->inst = NULL; | 62 state->inst = NULL; |
68 state->nodes.is_defined = FALSE; | 63 state->nodes.is_defined = FALSE; |
69 state->nodes.number_expr_nodes = 0; | 64 state->nodes.number_expr_nodes = 0; |
70 } | 65 } |
71 | 66 |
72 /* Computes the number of bytes defined for operands of the matched | 67 /* Computes the number of bytes defined for operands of the matched |
73 * instruction of the given state. | 68 * instruction of the given state. |
74 */ | 69 */ |
75 static int NaClExtractOpSize(NaClInstState* state) { | 70 static int NaClExtractOpSize(NaClInstState* state) { |
76 if (state->inst->flags & NACL_IFLAG(OperandSize_b)) { | 71 if (NaClHasBit(state->inst->flags, NACL_IFLAG(OperandSize_b))) { |
77 return 1; | 72 return 1; |
78 } | 73 } |
79 if (NACL_TARGET_SUBARCH == 64) { | 74 if (NACL_TARGET_SUBARCH == 64) { |
80 if ((state->rexprefix && state->rexprefix & 0x8) || | 75 if ((state->rexprefix && NaClRexW(state->rexprefix)) || |
81 (state->inst->flags & NACL_IFLAG(OperandSizeForce64))) { | 76 (NaClHasBit(state->inst->flags, NACL_IFLAG(OperandSizeForce64)))) { |
82 return 8; | 77 return 8; |
83 } | 78 } |
84 } | 79 } |
85 if ((state->prefix_mask & kPrefixDATA16) && | 80 if (NaClHasBit(state->prefix_mask, kPrefixDATA16) && |
86 (NACL_EMPTY_IFLAGS == | 81 (NACL_EMPTY_IFLAGS == |
87 (state->inst->flags & NACL_IFLAG(SizeIgnoresData16)))) { | 82 (state->inst->flags & NACL_IFLAG(SizeIgnoresData16)))) { |
88 return 2; | 83 return 2; |
89 } | 84 } |
90 if ((NACL_TARGET_SUBARCH == 64) && | 85 if ((NACL_TARGET_SUBARCH == 64) && |
91 (state->inst->flags & NACL_IFLAG(OperandSizeDefaultIs64))) { | 86 NaClHasBit(state->inst->flags, NACL_IFLAG(OperandSizeDefaultIs64))) { |
92 return 8; | 87 return 8; |
93 } | 88 } |
94 return 4; | 89 return 4; |
95 } | 90 } |
96 | 91 |
97 /* Computes the number of bits defined for addresses of the matched | 92 /* Computes the number of bits defined for addresses of the matched |
98 * instruction of the given state. | 93 * instruction of the given state. |
99 */ | 94 */ |
100 static int NaClExtractAddressSize(NaClInstState* state) { | 95 static int NaClExtractAddressSize(NaClInstState* state) { |
101 if (NACL_TARGET_SUBARCH == 64) { | 96 if (NACL_TARGET_SUBARCH == 64) { |
102 return (state->prefix_mask & kPrefixADDR16) ? 32 : 64; | 97 return NaClHasBit(state->prefix_mask, kPrefixADDR16) ? 32 : 64; |
103 } else { | 98 } else { |
104 return (state->prefix_mask & kPrefixADDR16) ? 16 : 32; | 99 return NaClHasBit(state->prefix_mask, kPrefixADDR16) ? 16 : 32; |
105 } | 100 } |
106 } | 101 } |
107 | 102 |
108 /* Manual implies only 4 bytes is allowed, but I have found up to 6. | 103 /* Manual implies only 4 bytes is allowed, but I have found up to 6. |
109 * Why don't we allow any number, so long as (1) There is room for | 104 * Why don't we allow any number, so long as (1) There is room for |
110 * at least one opcode byte, and (2) we don't exceed the max bytes. | 105 * at least one opcode byte, and (2) we don't exceed the max bytes. |
111 */ | 106 */ |
112 static const int kNaClMaximumPrefixBytes = | 107 static const int kNaClMaximumPrefixBytes = |
113 NACL_MAX_BYTES_PER_X86_INSTRUCTION - 1; | 108 NACL_MAX_BYTES_PER_X86_INSTRUCTION - 1; |
114 | 109 |
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
176 if (NACL_TARGET_SUBARCH == 64) { | 171 if (NACL_TARGET_SUBARCH == 64) { |
177 /* REX prefix must be last, unless FO exists. If FO | 172 /* REX prefix must be last, unless FO exists. If FO |
178 * exists, it must be after REX (Intel Manual). | 173 * exists, it must be after REX (Intel Manual). |
179 * | 174 * |
180 * NOTE: (karl) It appears that this constraint is violated | 175 * NOTE: (karl) It appears that this constraint is violated |
181 * with compiled code of /bin/ld_static. According to AMD, | 176 * with compiled code of /bin/ld_static. According to AMD, |
182 * the rex prefix must be last. Changing code to allow REX | 177 * the rex prefix must be last. Changing code to allow REX |
183 * prefix to occur anywhere. | 178 * prefix to occur anywhere. |
184 */ | 179 */ |
185 if (rex_index >= 0) { | 180 if (rex_index >= 0) { |
186 return (rex_index + 1) == state->num_prefix_bytes; | 181 return (Bool) ((rex_index + 1) == state->num_prefix_bytes); |
187 } | 182 } |
188 } | 183 } |
189 return TRUE; | 184 return TRUE; |
190 } | 185 } |
191 | 186 |
192 /* Structure holding the results of consuming the opcode bytes of the | |
193 * instruction. | |
194 */ | |
195 typedef struct { | |
196 /* The (last) byte of the matched opcode. */ | |
197 uint8_t opcode_byte; | |
198 /* The most specific prefix that the opcode bytes can match | |
199 * (or OpcodePrefixEnumSize if no such patterns exist). | |
200 */ | |
201 NaClInstPrefix matched_prefix; | |
202 /* The number of bytes to subtract from the instruction length, | |
203 * the next time GetNextNaClInstCandidates is called. | |
204 */ | |
205 uint8_t next_length_adjustment; | |
206 } NaClInstPrefixDescriptor; | |
207 | |
208 /* Assuming we have matched the byte sequence OF 38, consume the corresponding | 187 /* Assuming we have matched the byte sequence OF 38, consume the corresponding |
209 * following (instruction) opcode byte, returning the most specific prefix the | 188 * following (instruction) opcode byte, returning the most specific prefix the |
210 * patterns can match (or NaClInstPrefixEnumSize if no such patterns exist); | 189 * patterns can match (or NaClInstPrefixEnumSize if no such patterns exist); |
211 */ | 190 */ |
212 static void NaClConsume0F38XXNaClInstBytes(NaClInstState* state, | 191 static void NaClConsume0F38XXNaClInstBytes(NaClInstState* state, |
213 NaClInstPrefixDescriptor* desc) { | 192 NaClInstPrefixDescriptor* desc) { |
214 /* Fail if there are no more bytes. Otherwise, read the next | 193 /* Fail if there are no more bytes. Otherwise, read the next |
215 * byte. | 194 * byte. |
216 */ | 195 */ |
217 if (state->bytes.length >= state->length_limit) { | 196 if (state->bytes.length >= state->length_limit) { |
218 desc->matched_prefix = NaClInstPrefixEnumSize; | 197 desc->matched_prefix = NaClInstPrefixEnumSize; |
219 return; | 198 return; |
220 } | 199 } |
221 | 200 |
222 desc->opcode_byte = NCInstBytesRead(&state->bytes); | 201 desc->opcode_byte = NCInstBytesRead(&state->bytes); |
223 if (state->prefix_mask & kPrefixREPNE) { | 202 DEBUG(NaClLog(LOG_INFO, "Consume inst byte %02"NACL_PRIx8".\n", |
224 desc->matched_prefix = PrefixF20F38; | 203 desc->opcode_byte)); |
204 if (NaClExcludesBit(state->prefix_mask, kPrefixREP)) { | |
205 if (NaClHasBit(state->prefix_mask, kPrefixREPNE)) { | |
206 /* Note: Flag OpcodeAllowsData16 will explicitly clarify | |
207 * ambigous case of both REP and DATA16 prefixes. | |
208 */ | |
209 desc->matched_prefix = PrefixF20F38; | |
210 } else if (NaClHasBit(state->prefix_mask, kPrefixDATA16)) { | |
211 desc->matched_prefix = Prefix660F38; | |
212 } else { | |
213 desc->matched_prefix = Prefix0F38; | |
214 } | |
215 return; | |
225 } | 216 } |
226 else if (state->prefix_mask & kPrefixDATA16) { | 217 /* If reached, can't match special prefixes, fail. */ |
227 desc->matched_prefix = Prefix660F38; | 218 desc->matched_prefix = NaClInstPrefixEnumSize; |
228 } else if ((state->prefix_mask & ~kPrefixREX) == 0) { | |
229 desc->matched_prefix = Prefix0F38; | |
230 } else { | |
231 /* Other prefixes like F3 cause an undefined instruction error. */ | |
232 desc->matched_prefix = NaClInstPrefixEnumSize; | |
233 } | |
234 } | 219 } |
235 | 220 |
236 /* Assuming we have matched the byte sequence OF 3A, consume the corresponding | 221 /* Assuming we have matched the byte sequence OF 3A, consume the corresponding |
237 * following (instruction) opcode byte, returning the most specific prefix the | 222 * following (instruction) opcode byte, returning the most specific prefix the |
238 * patterns can match (or NaClInstPrefixEnumSize if no such patterns exist). | 223 * patterns can match (or NaClInstPrefixEnumSize if no such patterns exist). |
239 */ | 224 */ |
240 static void NaClConsume0F3AXXNaClInstBytes(NaClInstState* state, | 225 static void NaClConsume0F3AXXNaClInstBytes(NaClInstState* state, |
241 NaClInstPrefixDescriptor* desc) { | 226 NaClInstPrefixDescriptor* desc) { |
242 /* Fail if there are no more bytes. Otherwise, read the next | 227 /* Fail if there are no more bytes. Otherwise, read the next |
243 * byte and choose appropriate prefix. | 228 * byte and choose appropriate prefix. |
244 */ | 229 */ |
245 if (state->bytes.length >= state->length_limit) { | 230 if (state->bytes.length >= state->length_limit) { |
246 desc->matched_prefix = NaClInstPrefixEnumSize; | 231 desc->matched_prefix = NaClInstPrefixEnumSize; |
247 return; | 232 return; |
248 } | 233 } |
249 | 234 |
250 desc->opcode_byte = NCInstBytesRead(&state->bytes); | 235 desc->opcode_byte = NCInstBytesRead(&state->bytes); |
251 if (state->prefix_mask & kPrefixDATA16) { | 236 DEBUG(NaClLog(LOG_INFO, "Consume inst byte %02"NACL_PRIx8".\n", |
252 desc->matched_prefix = Prefix660F3A; | 237 desc->opcode_byte)); |
253 } else if ((state->prefix_mask & ~kPrefixREX) == 0) { | 238 if (NaClExcludesBit(state->prefix_mask, kPrefixREP) && |
254 desc->matched_prefix = Prefix0F3A; | 239 NaClExcludesBit(state->prefix_mask, kPrefixREPNE)) { |
255 } else { | 240 if (NaClHasBit(state->prefix_mask, kPrefixDATA16)) { |
256 /* Other prefixes like F3 cause an undefined instruction error. */ | 241 desc->matched_prefix = Prefix660F3A; |
257 desc->matched_prefix = NaClInstPrefixEnumSize; | 242 } else { |
243 desc->matched_prefix = Prefix0F3A; | |
244 } | |
245 return; | |
258 } | 246 } |
247 /* If reached, can't match special prefixes, fail. */ | |
248 desc->matched_prefix = NaClInstPrefixEnumSize; | |
259 } | 249 } |
260 | 250 |
261 /* Assuming we have matched byte OF, consume the corresponding | 251 /* Assuming we have matched byte OF, consume the corresponding |
262 * following (instruction) opcode byte, returning the most specific | 252 * following (instruction) opcode byte, returning the most specific |
263 * prefix the patterns can match (or NaClInstPrefixEnumSize if no such | 253 * prefix the patterns can match (or NaClInstPrefixEnumSize if no such |
264 * patterns exist). | 254 * patterns exist). |
265 */ | 255 */ |
266 static void NaClConsume0FXXNaClInstBytes(NaClInstState* state, | 256 static void NaClConsume0FXXNaClInstBytes(NaClInstState* state, |
267 NaClInstPrefixDescriptor* desc) { | 257 NaClInstPrefixDescriptor* desc) { |
268 if (state->prefix_mask & kPrefixREPNE) { | 258 if (NaClHasBit(state->prefix_mask, kPrefixREPNE)) { |
269 desc->matched_prefix = PrefixF20F; | 259 if (NaClExcludesBit(state->prefix_mask, kPrefixREP)) { |
270 } else if (state->prefix_mask & kPrefixREP) { | 260 /* Note: Flag OpcodeAllowsData16 will explicitly clarify |
271 desc->matched_prefix = PrefixF30F; | 261 * ambigous case of both REPNE and DATA16 prefixes. |
272 } else if (state->prefix_mask & kPrefixDATA16) { | 262 */ |
273 desc->matched_prefix = Prefix660F; | 263 desc->matched_prefix = PrefixF20F; |
264 return; | |
265 } | |
274 } else { | 266 } else { |
275 desc->matched_prefix = Prefix0F; | 267 if (NaClHasBit(state->prefix_mask, kPrefixREP)) { |
268 /* Note: Flag OpcodeAllowsData16 will explicitly clarify | |
269 * ambigous case of both REP and DATA16 prefixes. | |
270 */ | |
271 desc->matched_prefix = PrefixF30F; | |
272 } else if (NaClHasBit(state->prefix_mask, kPrefixDATA16)) { | |
273 desc->matched_prefix = Prefix660F; | |
274 } else { | |
275 desc->matched_prefix = Prefix0F; | |
276 } | |
277 return; | |
276 } | 278 } |
279 /* If reached, can't match special prefixes, fail. */ | |
280 desc->matched_prefix = NaClInstPrefixEnumSize; | |
277 } | 281 } |
278 | 282 |
279 /* Consume one of the x87 instructions that begin with D8-Df, and | 283 /* Consume one of the x87 instructions that begin with D8-Df, and |
280 * match the most specific prefix pattern the opcode bytes can match. | 284 * match the most specific prefix pattern the opcode bytes can match. |
281 */ | 285 */ |
282 static void NaClConsumeX87NaClInstBytes(NaClInstState* state, | 286 static void NaClConsumeX87NaClInstBytes(NaClInstState* state, |
283 NaClInstPrefixDescriptor* desc) { | 287 NaClInstPrefixDescriptor* desc) { |
284 if (state->bytes.length < state->length_limit) { | 288 if (state->bytes.length < state->length_limit) { |
285 /* Can be two byte opcode. */ | 289 /* Can be two byte opcode. */ |
286 desc->matched_prefix = PrefixD8 + | 290 desc->matched_prefix = |
287 (((unsigned) desc->opcode_byte) - 0xD8); | 291 (NaClInstPrefix) (PrefixD8 + |
292 (((unsigned) desc->opcode_byte) - 0xD8)); | |
288 desc->opcode_byte = NCInstBytesRead(&state->bytes); | 293 desc->opcode_byte = NCInstBytesRead(&state->bytes); |
294 DEBUG(NaClLog(LOG_INFO, "Consume inst byte %02"NACL_PRIx8".\n", | |
295 desc->opcode_byte)); | |
289 return; | 296 return; |
290 } | 297 } |
291 | 298 |
292 /* If reached, can only be single byte opcode, match as such. */ | 299 /* If reached, can only be single byte opcode, match as such. */ |
293 desc->matched_prefix = NoPrefix; | 300 desc->matched_prefix = NoPrefix; |
294 } | 301 } |
295 | 302 |
296 /* Consume the opcode bytes, and return the most specific prefix pattern | 303 /* Consume the opcode bytes, and return the most specific prefix pattern |
297 * the opcode bytes can match (or NaClInstPrefixEnumSize if no such pattern | 304 * the opcode bytes can match (or NaClInstPrefixEnumSize if no such pattern |
298 * exists). | 305 * exists). |
299 */ | 306 */ |
300 static void NaClConsumeInstBytes(NaClInstState* state, | 307 static void NaClConsumeInstBytes(NaClInstState* state, |
301 NaClInstPrefixDescriptor* desc) { | 308 NaClInstPrefixDescriptor* desc) { |
302 | 309 |
303 /* Initialize descriptor to the fail state. */ | 310 /* Initialize descriptor to the fail state. */ |
304 desc->opcode_byte = 0x0; | 311 desc->opcode_byte = 0x0; |
305 desc->matched_prefix = NaClInstPrefixEnumSize; | 312 desc->matched_prefix = NaClInstPrefixEnumSize; |
306 desc->next_length_adjustment = 0; | 313 desc->next_length_adjustment = 0; |
307 | 314 |
308 /* Be sure that we don't exceed the segment length. */ | 315 /* Be sure that we don't exceed the segment length. */ |
309 if (state->bytes.length >= state->length_limit) return; | 316 if (state->bytes.length >= state->length_limit) return; |
310 | 317 |
311 desc->opcode_byte = NCInstBytesRead(&state->bytes); | 318 desc->opcode_byte = NCInstBytesRead(&state->bytes); |
319 DEBUG(NaClLog(LOG_INFO, "Consume inst byte %02"NACL_PRIx8".\n", | |
320 desc->opcode_byte)); | |
312 switch (desc->opcode_byte) { | 321 switch (desc->opcode_byte) { |
313 case 0x0F: | 322 case 0x0F: |
314 if (state->bytes.length >= state->length_limit) return; | 323 if (state->bytes.length >= state->length_limit) return; |
315 desc->opcode_byte = NCInstBytesRead(&state->bytes); | 324 desc->opcode_byte = NCInstBytesRead(&state->bytes); |
325 DEBUG(NaClLog(LOG_INFO, "Consume inst byte %02"NACL_PRIx8".\n", | |
326 desc->opcode_byte)); | |
316 switch (desc->opcode_byte) { | 327 switch (desc->opcode_byte) { |
317 case 0x38: | 328 case 0x38: |
318 NaClConsume0F38XXNaClInstBytes(state, desc); | 329 NaClConsume0F38XXNaClInstBytes(state, desc); |
319 break; | 330 break; |
320 case 0x3a: | 331 case 0x3a: |
321 NaClConsume0F3AXXNaClInstBytes(state, desc); | 332 NaClConsume0F3AXXNaClInstBytes(state, desc); |
322 break; | 333 break; |
323 default: | 334 default: |
324 NaClConsume0FXXNaClInstBytes(state, desc); | 335 NaClConsume0FXXNaClInstBytes(state, desc); |
325 break; | 336 break; |
(...skipping 25 matching lines...) Expand all Loading... | |
351 static Bool NaClConsumeAndCheckOperandSize(NaClInstState* state) { | 362 static Bool NaClConsumeAndCheckOperandSize(NaClInstState* state) { |
352 state->operand_size = NaClExtractOpSize(state); | 363 state->operand_size = NaClExtractOpSize(state); |
353 DEBUG(NaClLog(LOG_INFO, | 364 DEBUG(NaClLog(LOG_INFO, |
354 "operand size = %"NACL_PRIu8"\n", state->operand_size)); | 365 "operand size = %"NACL_PRIu8"\n", state->operand_size)); |
355 if (state->inst->flags & | 366 if (state->inst->flags & |
356 (NACL_IFLAG(OperandSize_w) | NACL_IFLAG(OperandSize_v) | | 367 (NACL_IFLAG(OperandSize_w) | NACL_IFLAG(OperandSize_v) | |
357 NACL_IFLAG(OperandSize_o))) { | 368 NACL_IFLAG(OperandSize_o))) { |
358 NaClIFlags good = 1; | 369 NaClIFlags good = 1; |
359 switch (state->operand_size) { | 370 switch (state->operand_size) { |
360 case 2: | 371 case 2: |
361 good = (state->inst->flags & NACL_IFLAG(OperandSize_w)); | 372 good = NaClHasBit(state->inst->flags, NACL_IFLAG(OperandSize_w)); |
362 break; | 373 break; |
363 case 4: | 374 case 4: |
364 good = (state->inst->flags & NACL_IFLAG(OperandSize_v)); | 375 good = NaClHasBit(state->inst->flags, NACL_IFLAG(OperandSize_v)); |
365 break; | 376 break; |
366 case 8: | 377 case 8: |
367 good = (state->inst->flags & NACL_IFLAG(OperandSize_o)); | 378 good = NaClHasBit(state->inst->flags, NACL_IFLAG(OperandSize_o)); |
368 break; | 379 break; |
369 default: | 380 default: |
370 good = 0; | 381 good = 0; |
371 break; | 382 break; |
372 } | 383 } |
373 if (!good) { | 384 if (!good) { |
374 /* The flags associated with the opcode (instruction) don't | 385 /* The flags associated with the opcode (instruction) don't |
375 * allow the computed sizes, abort the match of the instruction. | 386 * allow the computed sizes, abort the match of the instruction. |
376 */ | 387 */ |
377 DEBUG(NaClLog(LOG_INFO, | 388 DEBUG(NaClLog(LOG_INFO, |
378 "Operand size %"NACL_PRIu8 | 389 "Operand size %"NACL_PRIu8 |
379 " doesn't match flag requirement!\n", | 390 " doesn't match flag requirement!\n", |
380 state->operand_size)); | 391 state->operand_size)); |
381 return FALSE; | 392 return FALSE; |
382 } | 393 } |
383 } | 394 } |
384 return TRUE; | 395 return TRUE; |
385 } | 396 } |
386 | 397 |
387 static Bool NaClConsumeAndCheckAddressSize(NaClInstState* state) { | 398 static Bool NaClConsumeAndCheckAddressSize(NaClInstState* state) { |
388 state->address_size = NaClExtractAddressSize(state); | 399 state->address_size = NaClExtractAddressSize(state); |
389 DEBUG(NaClLog(LOG_INFO, | 400 DEBUG(NaClLog(LOG_INFO, |
390 "Address size = %"NACL_PRIu8"\n", state->address_size)); | 401 "Address size = %"NACL_PRIu8"\n", state->address_size)); |
391 if (state->inst->flags & | 402 if (state->inst->flags & |
392 (NACL_IFLAG(AddressSize_w) | NACL_IFLAG(AddressSize_v) | | 403 (NACL_IFLAG(AddressSize_w) | NACL_IFLAG(AddressSize_v) | |
393 NACL_IFLAG(AddressSize_o))) { | 404 NACL_IFLAG(AddressSize_o))) { |
394 NaClIFlags good = 1; | 405 NaClIFlags good = 1; |
395 switch (state->address_size) { | 406 switch (state->address_size) { |
396 case 16: | 407 case 16: |
397 good = (state->inst->flags & NACL_IFLAG(AddressSize_w)); | 408 good = NaClHasBit(state->inst->flags, NACL_IFLAG(AddressSize_w)); |
398 break; | 409 break; |
399 case 32: | 410 case 32: |
400 good = (state->inst->flags & NACL_IFLAG(AddressSize_v)); | 411 good = NaClHasBit(state->inst->flags, NACL_IFLAG(AddressSize_v)); |
401 break; | 412 break; |
402 case 64: | 413 case 64: |
403 good = (state->inst->flags & NACL_IFLAG(AddressSize_o)); | 414 good = NaClHasBit(state->inst->flags, NACL_IFLAG(AddressSize_o)); |
404 break; | 415 break; |
405 default: | 416 default: |
406 good = 0; | 417 good = 0; |
407 break; | 418 break; |
408 } | 419 } |
409 if (!good) { | 420 if (!good) { |
410 /* The flags associated with the opcode (instruction) don't | 421 /* The flags associated with the opcode (instruction) don't |
411 * allow the computed sizes, abort the match of the instruction. | 422 * allow the computed sizes, abort the match of the instruction. |
412 */ | 423 */ |
413 DEBUG(NaClLog(LOG_INFO, | 424 DEBUG(NaClLog(LOG_INFO, |
414 "Address size %"NACL_PRIu8 | 425 "Address size %"NACL_PRIu8 |
415 " doesn't match flag requirement!\n", | 426 " doesn't match flag requirement!\n", |
416 state->address_size)); | 427 state->address_size)); |
417 return FALSE; | 428 return FALSE; |
418 } | 429 } |
419 } | 430 } |
420 return TRUE; | 431 return TRUE; |
421 } | 432 } |
422 | 433 |
423 /* Returns true if the instruction requires a ModRm bytes. */ | 434 /* Returns true if the instruction requires a ModRm bytes. */ |
424 static Bool NaClInstRequiresModRm(NaClInstState* state) { | 435 static Bool NaClInstRequiresModRm(NaClInstState* state) { |
425 return | 436 return (Bool) |
426 (NACL_EMPTY_IFLAGS != | 437 (NACL_EMPTY_IFLAGS != |
427 (state->inst->flags & NACL_IFLAG(OpcodeUsesModRm))); | 438 (state->inst->flags & NACL_IFLAG(OpcodeUsesModRm))); |
428 } | 439 } |
429 | 440 |
430 /* Consume the Mod/Rm byte of the instruction, if applicable. | 441 /* Consume the Mod/Rm byte of the instruction, if applicable. |
431 * Aborts the pattern match if any problems. | 442 * Aborts the pattern match if any problems. |
432 */ | 443 */ |
433 static Bool NaClConsumeModRm(NaClInstState* state) { | 444 static Bool NaClConsumeModRm(NaClInstState* state) { |
434 /* First check if the opcode (instruction) pattern specifies that | 445 /* First check if the opcode (instruction) pattern specifies that |
435 * a Mod/Rm byte is needed, and that reading it will not walk | 446 * a Mod/Rm byte is needed, and that reading it will not walk |
436 * past the end of the code segment. | 447 * past the end of the code segment. |
437 */ | 448 */ |
438 if (NaClInstRequiresModRm(state)) { | 449 if (NaClInstRequiresModRm(state)) { |
439 uint8_t byte; | 450 uint8_t byte; |
440 /* Has modrm byte. */ | 451 /* Has modrm byte. */ |
441 if (state->bytes.length >= state->length_limit) { | 452 if (state->bytes.length >= state->length_limit) { |
442 DEBUG(NaClLog(LOG_INFO, "Can't read mod/rm, no more bytes!\n")); | 453 DEBUG(NaClLog(LOG_INFO, "Can't read mod/rm, no more bytes!\n")); |
443 return FALSE; | 454 return FALSE; |
444 } | 455 } |
445 byte = NCInstBytesPeek(&state->bytes, 0); | 456 byte = NCInstBytesPeek(&state->bytes, 0); |
446 | 457 |
447 /* Note: Some instructions only allow values where the ModRm mod field | 458 /* Note: Some instructions only allow values where the ModRm mod field |
448 * is 0x3. Others only allow values where the ModRm mod field isn't 0x3. | 459 * is 0x3. Others only allow values where the ModRm mod field isn't 0x3. |
449 */ | 460 */ |
450 if (modrm_mod(byte) == 0x3) { | 461 if (modrm_mod(byte) == 0x3) { |
451 if (state->inst->flags & NACL_IFLAG(ModRmModIsnt0x3)) { | 462 if (NaClHasBit(state->inst->flags, NACL_IFLAG(ModRmModIsnt0x3))) { |
452 DEBUG(NaClLog(LOG_INFO, "Can't match, modrm mod field is 0x3\n")); | 463 DEBUG(NaClLog(LOG_INFO, "Can't match, modrm mod field is 0x3\n")); |
453 return FALSE; | 464 return FALSE; |
454 } | 465 } |
455 } else { | 466 } else { |
456 if (state->inst->flags & NACL_IFLAG(ModRmModIs0x3)) { | 467 if (NaClHasBit(state->inst->flags, NACL_IFLAG(ModRmModIs0x3))) { |
457 DEBUG(NaClLog(LOG_INFO, "Can't match, modrm mod field not 0x3\n")); | 468 DEBUG(NaClLog(LOG_INFO, "Can't match, modrm mod field not 0x3\n")); |
458 return FALSE; | 469 return FALSE; |
459 } | 470 } |
460 } | 471 } |
461 if ((state->inst->flags & NACL_IFLAG(ModRmRegSOperand)) && | 472 if ((NaClHasBit(state->inst->flags, NACL_IFLAG(ModRmRegSOperand))) && |
462 (modrm_reg(byte) > 5)) { | 473 (modrm_reg(byte) > 5)) { |
463 DEBUG(NaClLog(LOG_INFO, | 474 DEBUG(NaClLog(LOG_INFO, |
464 "Can't match, modrm reg field doesn't index segment\n")); | 475 "Can't match, modrm reg field doesn't index segment\n")); |
465 return FALSE; | 476 return FALSE; |
466 } | 477 } |
467 state->modrm = NCInstBytesRead(&state->bytes); | 478 state->modrm = NCInstBytesRead(&state->bytes); |
468 state->num_disp_bytes = 0; | 479 state->num_disp_bytes = 0; |
469 state->first_disp_byte = 0; | 480 state->first_disp_byte = 0; |
470 state->sib = 0; | 481 state->sib = 0; |
471 state->has_sib = FALSE; | 482 state->has_sib = FALSE; |
(...skipping 26 matching lines...) Expand all Loading... | |
498 } | 509 } |
499 return TRUE; | 510 return TRUE; |
500 } | 511 } |
501 | 512 |
502 /* Returns true if the instruction requires a SIB bytes. */ | 513 /* Returns true if the instruction requires a SIB bytes. */ |
503 static Bool NaClInstRequiresSib(NaClInstState* state) { | 514 static Bool NaClInstRequiresSib(NaClInstState* state) { |
504 /* Note: in 64-bit mode, 64-bit addressing is treated the same as 32-bit | 515 /* Note: in 64-bit mode, 64-bit addressing is treated the same as 32-bit |
505 * addressing. Hence, required for all but 16-bit addressing, when | 516 * addressing. Hence, required for all but 16-bit addressing, when |
506 * the right modrm bytes are specified. | 517 * the right modrm bytes are specified. |
507 */ | 518 */ |
508 return NaClInstRequiresModRm(state) && (16 != state->address_size) && | 519 return (Bool) |
509 (modrm_rm(state->modrm) == 0x04 && modrm_mod(state->modrm) != 0x3); | 520 (NaClInstRequiresModRm(state) && (16 != state->address_size) && |
521 (modrm_rm(state->modrm) == 0x04 && modrm_mod(state->modrm) != 0x3)); | |
510 } | 522 } |
511 | 523 |
512 /* Consume the SIB byte of the instruction, if applicable. Aborts the pattern | 524 /* Consume the SIB byte of the instruction, if applicable. Aborts the pattern |
513 * match if any problems are found. | 525 * match if any problems are found. |
514 */ | 526 */ |
515 static Bool NaClConsumeSib(NaClInstState* state) { | 527 static Bool NaClConsumeSib(NaClInstState* state) { |
516 /* First check that the opcode (instruction) pattern specifies that | 528 /* First check that the opcode (instruction) pattern specifies that |
517 * a SIB byte is needed, and that reading it will not walk past | 529 * a SIB byte is needed, and that reading it will not walk past |
518 * the end of the code segment. | 530 * the end of the code segment. |
519 */ | 531 */ |
(...skipping 334 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
854 * using opcode sequences have no (useful) operands, and hence | 866 * using opcode sequences have no (useful) operands, and hence |
855 * no additional information is needed. | 867 * no additional information is needed. |
856 */ | 868 */ |
857 state->inst = matching_inst; | 869 state->inst = matching_inst; |
858 NCInstBytesReadBytes(matching_length, &state->bytes); | 870 NCInstBytesReadBytes(matching_length, &state->bytes); |
859 DEBUG(NaClLog(LOG_INFO, "matched inst sequence [%d]!\n", matching_length)); | 871 DEBUG(NaClLog(LOG_INFO, "matched inst sequence [%d]!\n", matching_length)); |
860 return TRUE; | 872 return TRUE; |
861 } | 873 } |
862 } | 874 } |
863 | 875 |
864 /* Given the current location of the (relative) pc of the given instruction | 876 EXTERN_C_END |
865 * iterator, update the given state to hold the (found) matched opcode | |
866 * (instruction) pattern. If no matching pattern exists, set the state | |
867 * to a matched undefined opcode (instruction) pattern. In all cases, | |
868 * update the state to hold all information on the matched bytes of the | |
869 * instruction. Note: The iterator expects that the opcode field is | |
870 * changed from NULL to non-NULL by this fuction. | |
871 */ | |
872 void NaClDecodeInst(NaClInstIter* iter, NaClInstState* state) { | |
873 uint8_t opcode_length = 0; | |
874 const NaClInst* cand_insts; | |
875 Bool found_match = FALSE; | |
876 /* Start by consuming the prefix bytes, and getting the possible | |
877 * candidate opcode (instruction) patterns that can match, based | |
878 * on the consumed opcode bytes. | |
879 */ | |
880 NaClInstStateInit(iter, state); | |
881 if (NaClConsumeOpcodeSequence(state)) { | |
882 found_match = TRUE; | |
883 } else if (NaClConsumePrefixBytes(state)) { | |
884 NaClInstPrefixDescriptor prefix_desc; | |
885 Bool continue_loop = TRUE; | |
886 NaClConsumeInstBytes(state, &prefix_desc); | |
887 opcode_length = state->bytes.length; | |
888 while (continue_loop) { | |
889 /* Try matching all possible candidates, in the order they are specified | |
890 * (from the most specific prefix match, to the least specific prefix | |
891 * match). Quit when the first pattern is matched. | |
892 */ | |
893 if (prefix_desc.matched_prefix == NaClInstPrefixEnumSize) { | |
894 continue_loop = FALSE; | |
895 } else { | |
896 cand_insts = NaClGetNextInstCandidates(state, &prefix_desc, | |
897 &opcode_length); | |
898 while (cand_insts != NULL) { | |
899 NaClClearInstState(state, opcode_length); | |
900 state->inst = cand_insts; | |
901 DEBUG(NaClLog(LOG_INFO, "try opcode pattern:\n")); | |
902 DEBUG(NaClInstPrint(NaClLogGetGio(), state->inst)); | |
903 if (NaClConsumeAndCheckOperandSize(state) && | |
904 NaClConsumeAndCheckAddressSize(state) && | |
905 NaClConsumeModRm(state) && | |
906 NaClConsumeSib(state) && | |
907 NaClConsumeDispBytes(state) && | |
908 NaClConsumeImmediateBytes(state) && | |
909 NaClValidatePrefixFlags(state)) { | |
910 if (state->inst->flags & NACL_IFLAG(Opcode0F0F) && | |
911 /* Note: If all of the above code worked correctly, | |
912 * there should be no need for the following test. | |
913 * However, just to be safe, it is added. | |
914 */ | |
915 (state->num_imm_bytes == 1)) { | |
916 /* Special 3DNOW instructions where opcode is in parsed | |
917 * immediate byte at end of instruction. Look up in table, | |
918 * and replace if found. Otherwise, let the default 0F0F lookup | |
919 * act as the matching (invalid) instruction. | |
920 */ | |
921 const NaClInst* cand_inst; | |
922 uint8_t opcode_byte = state->bytes.byte[state->first_imm_byte]; | |
923 DEBUG(NaClLog(LOG_INFO, | |
924 "NaClConsume immediate byte opcode char: %" | |
925 NACL_PRIx8"\n", opcode_byte)); | |
926 cand_inst = g_OpcodeTable[Prefix0F0F][opcode_byte]; | |
927 if (NULL != cand_inst) { | |
928 state->inst = cand_inst; | |
929 DEBUG(NaClLog(LOG_INFO, "Replace with 3DNOW opcode:\n")); | |
930 DEBUG(NaClInstPrint(NaClLogGetGio(), state->inst)); | |
931 } | |
932 } | |
933 /* found a match, exit loop. */ | |
934 found_match = TRUE; | |
935 continue_loop = FALSE; | |
936 break; | |
937 } else { | |
938 /* match failed, try next candidate pattern. */ | |
939 cand_insts = cand_insts->next_rule; | |
940 } | |
941 } | |
942 DEBUG(if (! found_match) { | |
943 NaClLog(LOG_INFO, "no more candidates for this prefix\n"); | |
944 }); | |
945 } | |
946 } | |
947 } | |
948 | |
949 /* If we did not match a defined opcode, match the undefined opcode, | |
950 * forcing field opcode to be non-NULL. | |
951 */ | |
952 if (!found_match) { | |
953 DEBUG(NaClLog(LOG_INFO, "no instruction found, converting to undefined\n")); | |
954 | |
955 /* Can't figure out instruction, give up. */ | |
956 NaClClearInstState(state, opcode_length); | |
957 state->inst = &g_Undefined_Opcode; | |
958 if (state->bytes.length == 0 && state->bytes.length < state->length_limit) { | |
959 /* Make sure we eat at least one byte. */ | |
960 NCInstBytesRead(&state->bytes); | |
961 } | |
962 } | |
963 } | |
964 | |
965 const NaClInst* NaClInstStateInst(NaClInstState* state) { | |
966 return state->inst; | |
967 } | |
968 | |
969 NaClPcAddress NaClInstStateVpc(NaClInstState* state) { | |
970 return state->vpc; | |
971 } | |
972 | |
973 NaClExpVector* NaClInstStateExpVector(NaClInstState* state) { | |
974 if (!state->nodes.is_defined) { | |
975 state->nodes.is_defined = TRUE; | |
976 NaClBuildExpVector(state); | |
977 } | |
978 return &state->nodes; | |
979 } | |
980 | |
981 Bool NaClInstStateIsValid(NaClInstState* state) { | |
982 return InstInvalid != state->inst->name; | |
983 } | |
984 | |
985 uint8_t NaClInstStateLength(NaClInstState* state) { | |
986 return state->bytes.length; | |
987 } | |
988 | |
989 uint8_t NaClInstStateByte(NaClInstState* state, uint8_t index) { | |
990 assert(index < state->bytes.length); | |
991 return state->bytes.byte[index]; | |
992 } | |
993 | |
994 uint8_t NaClInstStateOperandSize(NaClInstState* state) { | |
995 return state->operand_size; | |
996 } | |
997 | |
998 uint8_t NaClInstStateAddressSize(NaClInstState* state) { | |
999 return state->address_size; | |
1000 } | |
1001 | |
1002 void NaClChangeOpcodesToXedsModel() { | |
1003 /* Changes opcodes to match xed. That is change: | |
1004 * 0f0f..1c: Pf2iw $Pq, $Qq => 0f0f..2c: Pf2iw $Pq, $Qq | |
1005 * 0f0f..1d: Pf2id $Pq, $Qq => 0f0f..2d: Pf2id $Pq, $Qq | |
1006 */ | |
1007 g_OpcodeTable[Prefix0F0F][0x2c] = g_OpcodeTable[Prefix0F0F][0x1c]; | |
1008 g_OpcodeTable[Prefix0F0F][0x1c] = NULL; | |
1009 g_OpcodeTable[Prefix0F0F][0x2d] = g_OpcodeTable[Prefix0F0F][0x1d]; | |
1010 g_OpcodeTable[Prefix0F0F][0x1d] = NULL; | |
1011 } | |
OLD | NEW |