Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(396)

Side by Side Diff: src/trusted/validator_x86/nc_inst_state.c

Issue 6883091: Start unit testing for functions in nc_inst_state.c (Closed) Base URL: svn://svn.chromium.org/native_client/trunk/src/native_client/
Patch Set: '' Created 9 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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 * Defines an instruction (decoder), based on the current location of
9 * the instruction iterator. The instruction decoder takes a list 9 * the instruction iterator. The instruction decoder takes a list
10 * of candidate opcode (instruction) patterns, and searches for the 10 * of candidate opcode (instruction) patterns, and searches for the
11 * first candidate that matches the requirements of the opcode pattern. 11 * first candidate that matches the requirements of the opcode pattern.
12 */ 12 */
13 13
14 #include <stdio.h>
15 #include <assert.h>
16 14
17 #include "native_client/src/trusted/validator_x86/nc_inst_state.h" 15 #include "native_client/src/trusted/validator_x86/nc_inst_state.h"
18 16
19 #include "native_client/src/shared/platform/nacl_log.h"
20 #include "native_client/src/trusted/validator_x86/nc_inst_iter.h"
21 #include "native_client/src/trusted/validator_x86/nc_inst_state_internal.h"
22 #include "native_client/src/trusted/validator_x86/nc_inst_trans.h"
23 #include "native_client/src/trusted/validator_x86/nc_segment.h"
24 #include "native_client/src/trusted/validator_x86/ncop_exps.h"
25 #include "native_client/src/trusted/validator_x86/ncopcode_desc.h"
26 #ifdef _WIN64
27 #include "gen/native_client/src/trusted/validator_x86/nc_opcode_table64.h"
28 #else
29 #include "gen/native_client/src/trusted/validator_x86/nc_opcode_table.h"
30 #endif
31
32 /* To turn on debugging of instruction decoding, change value of 17 /* To turn on debugging of instruction decoding, change value of
33 * DEBUGGING to 1. 18 * DEBUGGING to 1.
34 */ 19 */
35 #define DEBUGGING 0 20 #define DEBUGGING 0
36 21
37 #include "native_client/src/shared/utils/debugging.h" 22 #include "native_client/src/trusted/validator_x86/nc_inst_state_statics.c"
38
39 /* Given the current location of the instruction iterator, initialize
40 * the given state (to match).
41 */
42 static void NaClInstStateInit(NaClInstIter* iter, NaClInstState* state) {
43 NaClMemorySize limit;
44 NCInstBytesInit(&state->bytes);
45 state->vpc = iter->segment->vbase + iter->index;
46 limit = iter->segment->size - iter->index;
47 if (limit > NACL_MAX_BYTES_PER_X86_INSTRUCTION) {
48 limit = NACL_MAX_BYTES_PER_X86_INSTRUCTION;
49 }
50 state->length_limit = (uint8_t) limit;
51 DEBUG(NaClLog(LOG_INFO,
52 "length limit = %"NACL_PRIu8"\n", state->length_limit));
53 state->num_prefix_bytes = 0;
54 state->rexprefix = 0;
55 state->num_rex_prefixes = 0;
56 state->modrm = 0;
57 state->has_prefix_duplicates = FALSE;
58 state->has_ambig_segment_prefixes = FALSE;
59 state->has_sib = FALSE;
60 state->sib = 0;
61 state->num_disp_bytes = 0;
62 state->first_disp_byte = 0;
63 state->num_imm_bytes = 0;
64 state->first_imm_byte = 0;
65 state->num_imm2_bytes = 0;
66 state->prefix_mask = 0;
67 state->inst = NULL;
68 state->nodes.is_defined = FALSE;
69 state->nodes.number_expr_nodes = 0;
70 }
71
72 /* Computes the number of bytes defined for operands of the matched
73 * instruction of the given state.
74 */
75 static int NaClExtractOpSize(NaClInstState* state) {
76 if (state->inst->flags & NACL_IFLAG(OperandSize_b)) {
77 return 1;
78 }
79 if (NACL_TARGET_SUBARCH == 64) {
80 if ((state->rexprefix && state->rexprefix & 0x8) ||
81 (state->inst->flags & NACL_IFLAG(OperandSizeForce64))) {
82 return 8;
83 }
84 }
85 if ((state->prefix_mask & kPrefixDATA16) &&
86 (NACL_EMPTY_IFLAGS ==
87 (state->inst->flags & NACL_IFLAG(SizeIgnoresData16)))) {
88 return 2;
89 }
90 if ((NACL_TARGET_SUBARCH == 64) &&
91 (state->inst->flags & NACL_IFLAG(OperandSizeDefaultIs64))) {
92 return 8;
93 }
94 return 4;
95 }
96
97 /* Computes the number of bits defined for addresses of the matched
98 * instruction of the given state.
99 */
100 static int NaClExtractAddressSize(NaClInstState* state) {
101 if (NACL_TARGET_SUBARCH == 64) {
102 return (state->prefix_mask & kPrefixADDR16) ? 32 : 64;
103 } else {
104 return (state->prefix_mask & kPrefixADDR16) ? 16 : 32;
105 }
106 }
107
108 /* 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
110 * at least one opcode byte, and (2) we don't exceed the max bytes.
111 */
112 static const int kNaClMaximumPrefixBytes =
113 NACL_MAX_BYTES_PER_X86_INSTRUCTION - 1;
114
115 /* Captures ambiguous segment prefix forms. Used to make
116 * detection of multiple prefix segment bytes.
117 */
118 static const uint32_t segment_prefix_forms =
119 kPrefixSEGCS | kPrefixSEGSS | kPrefixSEGFS |
120 kPrefixSEGGS | kPrefixSEGES | kPrefixSEGDS;
121
122 /* Match any prefix bytes that can be associated with the instruction
123 * currently being matched.
124 */
125 static Bool NaClConsumePrefixBytes(NaClInstState* state) {
126 uint8_t next_byte;
127 int i;
128 uint32_t prefix_form;
129 int rex_index = -1;
130 for (i = 0; i < kNaClMaximumPrefixBytes; ++i) {
131 /* Quit early if no more bytes in segment. */
132 if (state->bytes.length >= state->length_limit) break;
133
134 /* Look up the corresponding prefix bit associated
135 * with the next byte in the segment, and record it.
136 */
137 next_byte = NCRemainingMemoryLookahead(state->bytes.memory,0);
138 prefix_form = kNaClPrefixTable[next_byte];
139 if (prefix_form == 0) break;
140 next_byte = NCInstBytesRead(&state->bytes);
141 DEBUG(NaClLog(LOG_INFO,
142 "Consume prefix[%d]: %02"NACL_PRIx8" => %"NACL_PRIx32"\n",
143 i, next_byte, prefix_form));
144 /* Before updating prefix mask, determine if the prefix byte is
145 * a duplicate.
146 */
147 if ((state->prefix_mask & prefix_form)) {
148 state->has_prefix_duplicates = TRUE;
149 DEBUG(NaClLog(LOG_INFO,
150 "duplicate prefix %02"NACL_PRIx8" detected.\n", next_byte));
151 } else if ((prefix_form & segment_prefix_forms) &&
152 (state->prefix_mask & segment_prefix_forms)) {
153 state->has_ambig_segment_prefixes = TRUE;
154 DEBUG(NaClLog(LOG_INFO,
155 "ambiguos segment prefix %02"NACL_PRIx8" detected.\n",
156 next_byte));
157 }
158 state->prefix_mask |= prefix_form;
159 ++state->num_prefix_bytes;
160 DEBUG(NaClLog(LOG_INFO,
161 " prefix mask: %08"NACL_PRIx32"\n", state->prefix_mask));
162
163 /* If the prefix byte is a REX prefix, record its value, since
164 * bits 5-8 of this prefix bit may be needed later.
165 */
166 if (NACL_TARGET_SUBARCH == 64) {
167 if (prefix_form == kPrefixREX) {
168 state->rexprefix = next_byte;
169 DEBUG(NaClLog(LOG_INFO,
170 " rexprefix = %02"NACL_PRIx8"\n", state->rexprefix));
171 ++state->num_rex_prefixes;
172 rex_index = i;
173 }
174 }
175 }
176 if (NACL_TARGET_SUBARCH == 64) {
177 /* REX prefix must be last, unless FO exists. If FO
178 * exists, it must be after REX (Intel Manual).
179 *
180 * NOTE: (karl) It appears that this constraint is violated
181 * with compiled code of /bin/ld_static. According to AMD,
182 * the rex prefix must be last. Changing code to allow REX
183 * prefix to occur anywhere.
184 */
185 if (rex_index >= 0) {
186 return (rex_index + 1) == state->num_prefix_bytes;
187 }
188 }
189 return TRUE;
190 }
191
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
209 * following (instruction) opcode byte, returning the most specific prefix the
210 * patterns can match (or NaClInstPrefixEnumSize if no such patterns exist);
211 */
212 static void NaClConsume0F38XXNaClInstBytes(NaClInstState* state,
213 NaClInstPrefixDescriptor* desc) {
214 /* Fail if there are no more bytes. Otherwise, read the next
215 * byte.
216 */
217 if (state->bytes.length >= state->length_limit) {
218 desc->matched_prefix = NaClInstPrefixEnumSize;
219 return;
220 }
221
222 desc->opcode_byte = NCInstBytesRead(&state->bytes);
223 if (state->prefix_mask & kPrefixREPNE) {
224 desc->matched_prefix = PrefixF20F38;
225 }
226 else if (state->prefix_mask & kPrefixDATA16) {
227 desc->matched_prefix = Prefix660F38;
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 }
235
236 /* Assuming we have matched the byte sequence OF 3A, consume the corresponding
237 * following (instruction) opcode byte, returning the most specific prefix the
238 * patterns can match (or NaClInstPrefixEnumSize if no such patterns exist).
239 */
240 static void NaClConsume0F3AXXNaClInstBytes(NaClInstState* state,
241 NaClInstPrefixDescriptor* desc) {
242 /* Fail if there are no more bytes. Otherwise, read the next
243 * byte and choose appropriate prefix.
244 */
245 if (state->bytes.length >= state->length_limit) {
246 desc->matched_prefix = NaClInstPrefixEnumSize;
247 return;
248 }
249
250 desc->opcode_byte = NCInstBytesRead(&state->bytes);
251 if (state->prefix_mask & kPrefixDATA16) {
252 desc->matched_prefix = Prefix660F3A;
253 } else if ((state->prefix_mask & ~kPrefixREX) == 0) {
254 desc->matched_prefix = Prefix0F3A;
255 } else {
256 /* Other prefixes like F3 cause an undefined instruction error. */
257 desc->matched_prefix = NaClInstPrefixEnumSize;
258 }
259 }
260
261 /* Assuming we have matched byte OF, consume the corresponding
262 * following (instruction) opcode byte, returning the most specific
263 * prefix the patterns can match (or NaClInstPrefixEnumSize if no such
264 * patterns exist).
265 */
266 static void NaClConsume0FXXNaClInstBytes(NaClInstState* state,
267 NaClInstPrefixDescriptor* desc) {
268 if (state->prefix_mask & kPrefixREPNE) {
269 desc->matched_prefix = PrefixF20F;
270 } else if (state->prefix_mask & kPrefixREP) {
271 desc->matched_prefix = PrefixF30F;
272 } else if (state->prefix_mask & kPrefixDATA16) {
273 desc->matched_prefix = Prefix660F;
274 } else {
275 desc->matched_prefix = Prefix0F;
276 }
277 }
278
279 /* Consume one of the x87 instructions that begin with D8-Df, and
280 * match the most specific prefix pattern the opcode bytes can match.
281 */
282 static void NaClConsumeX87NaClInstBytes(NaClInstState* state,
283 NaClInstPrefixDescriptor* desc) {
284 if (state->bytes.length < state->length_limit) {
285 /* Can be two byte opcode. */
286 desc->matched_prefix = PrefixD8 +
287 (((unsigned) desc->opcode_byte) - 0xD8);
288 desc->opcode_byte = NCInstBytesRead(&state->bytes);
289 return;
290 }
291
292 /* If reached, can only be single byte opcode, match as such. */
293 desc->matched_prefix = NoPrefix;
294 }
295
296 /* Consume the opcode bytes, and return the most specific prefix pattern
297 * the opcode bytes can match (or NaClInstPrefixEnumSize if no such pattern
298 * exists).
299 */
300 static void NaClConsumeInstBytes(NaClInstState* state,
301 NaClInstPrefixDescriptor* desc) {
302
303 /* Initialize descriptor to the fail state. */
304 desc->opcode_byte = 0x0;
305 desc->matched_prefix = NaClInstPrefixEnumSize;
306 desc->next_length_adjustment = 0;
307
308 /* Be sure that we don't exceed the segment length. */
309 if (state->bytes.length >= state->length_limit) return;
310
311 desc->opcode_byte = NCInstBytesRead(&state->bytes);
312 switch (desc->opcode_byte) {
313 case 0x0F:
314 if (state->bytes.length >= state->length_limit) return;
315 desc->opcode_byte = NCInstBytesRead(&state->bytes);
316 switch (desc->opcode_byte) {
317 case 0x38:
318 NaClConsume0F38XXNaClInstBytes(state, desc);
319 break;
320 case 0x3a:
321 NaClConsume0F3AXXNaClInstBytes(state, desc);
322 break;
323 default:
324 NaClConsume0FXXNaClInstBytes(state, desc);
325 break;
326 }
327 break;
328 case 0xD8:
329 case 0xD9:
330 case 0xDA:
331 case 0xDB:
332 case 0xDC:
333 case 0xDD:
334 case 0xDE:
335 case 0xDF:
336 NaClConsumeX87NaClInstBytes(state, desc);
337 break;
338 default:
339 desc->matched_prefix = NoPrefix;
340 break;
341 }
342 DEBUG(NaClLog(LOG_INFO,
343 "matched prefix = %s\n",
344 NaClInstPrefixName(desc->matched_prefix)));
345 }
346
347 /* Compute the operand and address sizes for the instruction. Then, verify
348 * that the opcode (instruction) pattern allows for such sizes. Aborts
349 * the pattern match if any problems.
350 */
351 static Bool NaClConsumeAndCheckOperandSize(NaClInstState* state) {
352 state->operand_size = NaClExtractOpSize(state);
353 DEBUG(NaClLog(LOG_INFO,
354 "operand size = %"NACL_PRIu8"\n", state->operand_size));
355 if (state->inst->flags &
356 (NACL_IFLAG(OperandSize_w) | NACL_IFLAG(OperandSize_v) |
357 NACL_IFLAG(OperandSize_o))) {
358 NaClIFlags good = 1;
359 switch (state->operand_size) {
360 case 2:
361 good = (state->inst->flags & NACL_IFLAG(OperandSize_w));
362 break;
363 case 4:
364 good = (state->inst->flags & NACL_IFLAG(OperandSize_v));
365 break;
366 case 8:
367 good = (state->inst->flags & NACL_IFLAG(OperandSize_o));
368 break;
369 default:
370 good = 0;
371 break;
372 }
373 if (!good) {
374 /* The flags associated with the opcode (instruction) don't
375 * allow the computed sizes, abort the match of the instruction.
376 */
377 DEBUG(NaClLog(LOG_INFO,
378 "Operand size %"NACL_PRIu8
379 " doesn't match flag requirement!\n",
380 state->operand_size));
381 return FALSE;
382 }
383 }
384 return TRUE;
385 }
386
387 static Bool NaClConsumeAndCheckAddressSize(NaClInstState* state) {
388 state->address_size = NaClExtractAddressSize(state);
389 DEBUG(NaClLog(LOG_INFO,
390 "Address size = %"NACL_PRIu8"\n", state->address_size));
391 if (state->inst->flags &
392 (NACL_IFLAG(AddressSize_w) | NACL_IFLAG(AddressSize_v) |
393 NACL_IFLAG(AddressSize_o))) {
394 NaClIFlags good = 1;
395 switch (state->address_size) {
396 case 16:
397 good = (state->inst->flags & NACL_IFLAG(AddressSize_w));
398 break;
399 case 32:
400 good = (state->inst->flags & NACL_IFLAG(AddressSize_v));
401 break;
402 case 64:
403 good = (state->inst->flags & NACL_IFLAG(AddressSize_o));
404 break;
405 default:
406 good = 0;
407 break;
408 }
409 if (!good) {
410 /* The flags associated with the opcode (instruction) don't
411 * allow the computed sizes, abort the match of the instruction.
412 */
413 DEBUG(NaClLog(LOG_INFO,
414 "Address size %"NACL_PRIu8
415 " doesn't match flag requirement!\n",
416 state->address_size));
417 return FALSE;
418 }
419 }
420 return TRUE;
421 }
422
423 /* Returns true if the instruction requires a ModRm bytes. */
424 static Bool NaClInstRequiresModRm(NaClInstState* state) {
425 return
426 (NACL_EMPTY_IFLAGS !=
427 (state->inst->flags & NACL_IFLAG(OpcodeUsesModRm)));
428 }
429
430 /* Consume the Mod/Rm byte of the instruction, if applicable.
431 * Aborts the pattern match if any problems.
432 */
433 static Bool NaClConsumeModRm(NaClInstState* state) {
434 /* First check if the opcode (instruction) pattern specifies that
435 * a Mod/Rm byte is needed, and that reading it will not walk
436 * past the end of the code segment.
437 */
438 if (NaClInstRequiresModRm(state)) {
439 uint8_t byte;
440 /* Has modrm byte. */
441 if (state->bytes.length >= state->length_limit) {
442 DEBUG(NaClLog(LOG_INFO, "Can't read mod/rm, no more bytes!\n"));
443 return FALSE;
444 }
445 byte = NCInstBytesPeek(&state->bytes, 0);
446
447 /* 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.
449 */
450 if (modrm_mod(byte) == 0x3) {
451 if (state->inst->flags & NACL_IFLAG(ModRmModIsnt0x3)) {
452 DEBUG(NaClLog(LOG_INFO, "Can't match, modrm mod field is 0x3\n"));
453 return FALSE;
454 }
455 } else {
456 if (state->inst->flags & NACL_IFLAG(ModRmModIs0x3)) {
457 DEBUG(NaClLog(LOG_INFO, "Can't match, modrm mod field not 0x3\n"));
458 return FALSE;
459 }
460 }
461 if ((state->inst->flags & NACL_IFLAG(ModRmRegSOperand)) &&
462 (modrm_reg(byte) > 5)) {
463 DEBUG(NaClLog(LOG_INFO,
464 "Can't match, modrm reg field doesn't index segment\n"));
465 return FALSE;
466 }
467 state->modrm = NCInstBytesRead(&state->bytes);
468 state->num_disp_bytes = 0;
469 state->first_disp_byte = 0;
470 state->sib = 0;
471 state->has_sib = FALSE;
472 DEBUG(NaClLog(LOG_INFO, "consume modrm = %02"NACL_PRIx8"\n", state->modrm));
473
474 /* Consume the remaining opcode value in the mod/rm byte
475 * if applicable.
476 */
477 if (state->inst->flags & NACL_IFLAG(OpcodeInModRm)) {
478 const NaClInst* inst = state->inst;
479 if (modrm_opcode(state->modrm) != inst->opcode[inst->num_opcode_bytes]) {
480 DEBUG(
481 NaClLog(LOG_INFO,
482 "Discarding, opcode in mrm byte (%02"NACL_PRIx8") "
483 "does not match\n",
484 modrm_opcode(state->modrm)));
485 return FALSE;
486 }
487 if (state->inst->flags & NACL_IFLAG(OpcodeInModRmRm)) {
488 if (modrm_rm(state->modrm) !=
489 state->inst->opcode[state->inst->num_opcode_bytes+1]) {
490 DEBUG(NaClLog(LOG_INFO,
491 "Discarding, opcode in mrm rm field (%02"NACL_PRIx8") "
492 "does not match\n",
493 modrm_rm(state->modrm)));
494 return FALSE;
495 }
496 }
497 }
498 }
499 return TRUE;
500 }
501
502 /* Returns true if the instruction requires a SIB bytes. */
503 static Bool NaClInstRequiresSib(NaClInstState* state) {
504 /* 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
506 * the right modrm bytes are specified.
507 */
508 return NaClInstRequiresModRm(state) && (16 != state->address_size) &&
509 (modrm_rm(state->modrm) == 0x04 && modrm_mod(state->modrm) != 0x3);
510 }
511
512 /* Consume the SIB byte of the instruction, if applicable. Aborts the pattern
513 * match if any problems are found.
514 */
515 static Bool NaClConsumeSib(NaClInstState* state) {
516 /* First check that the opcode (instruction) pattern specifies that
517 * a SIB byte is needed, and that reading it will not walk past
518 * the end of the code segment.
519 */
520 state->sib = 0;
521 state->has_sib = NaClInstRequiresSib(state);
522 DEBUG(NaClLog(LOG_INFO, "has sib = %d\n", (int) state->has_sib));
523 if (state->has_sib) {
524 if (state->bytes.length >= state->length_limit) {
525 DEBUG(NaClLog(LOG_INFO, "Can't consume sib, no more bytes!\n"));
526 return FALSE;
527 }
528 /* Read the SIB byte and record. */
529 state->sib = NCInstBytesRead(&state->bytes);
530 DEBUG(NaClLog(LOG_INFO, "sib = %02"NACL_PRIx8"\n", state->sib));
531 if (sib_base(state->sib) == 0x05 && modrm_mod(state->modrm) > 2) {
532 DEBUG(NaClLog(LOG_INFO,
533 "Sib byte implies modrm.mod field <= 2, match fails\n"));
534 return FALSE;
535 }
536 }
537 return TRUE;
538 }
539
540 static int NaClGetNumDispBytes(NaClInstState* state) {
541 if (NaClInstRequiresModRm(state)) {
542 if (16 == state->address_size) {
543 /* Corresponding to table 2-1 of the Intel manual. */
544 switch (modrm_mod(state->modrm)) {
545 case 0x0:
546 if (modrm_rm(state->modrm) == 0x06) {
547 return 4; /* disp16 */
548 }
549 break;
550 case 0x1:
551 return 1; /* disp8 */
552 case 0x2:
553 return 2; /* disp16 */
554 default:
555 break;
556 }
557 } else {
558 /* Note: in 64-bit mode, 64-bit addressing is treated the same as 32-bit
559 * addressing. Hence, this section covers the 32-bit addressing.
560 */
561 switch(modrm_mod(state->modrm)) {
562 case 0x0:
563 if (modrm_rm(state->modrm) == 0x05) {
564 return 4; /* disp32 */
565 } else if (state->has_sib && sib_base(state->sib) == 0x5) {
566 return 4;
567 }
568 break;
569 case 0x1:
570 return 1; /* disp8 */
571 case 0x2:
572 return 4; /* disp32 */
573 default:
574 break;
575 }
576 }
577 }
578 return 0;
579 }
580
581 /* Consume the needed displacement bytes, if applicable. Abort the
582 * pattern match if any problems are found.
583 */
584 static Bool NaClConsumeDispBytes(NaClInstState* state) {
585 /* First check if the opcode (instruction) pattern specifies that
586 * displacement bytes should be read, and that reading it will not
587 * walk past the end of the code segment.
588 */
589 state->num_disp_bytes = NaClGetNumDispBytes(state);
590 DEBUG(NaClLog(LOG_INFO,
591 "num disp bytes = %"NACL_PRIu8"\n", state->num_disp_bytes));
592 state->first_disp_byte = state->bytes.length;
593 if (state->num_disp_bytes > 0) {
594 int new_length = state->bytes.length + state->num_disp_bytes;
595 if (new_length > state->length_limit) {
596 DEBUG(NaClLog(LOG_INFO, "Can't consume disp, no more bytes!\n"));
597 return FALSE;
598 }
599 /* Read the displacement bytes. */
600 state->first_disp_byte = state->bytes.length;
601 NCInstBytesReadBytes(state->num_disp_bytes, &state->bytes);
602 }
603 return TRUE;
604 }
605
606 /* Returns the number of immediate bytes to parse. */
607 static int NaClGetNumImmedBytes(NaClInstState* state) {
608 if (state->inst->flags & NACL_IFLAG(OpcodeHasImmed)) {
609 return state->operand_size;
610 }
611 if (state->inst->flags & NACL_IFLAG(OpcodeHasImmed_v)) {
612 return 4;
613 } else if (state->inst->flags & NACL_IFLAG(OpcodeHasImmed_b)) {
614 return 1;
615 } else if (state->inst->flags & NACL_IFLAG(OpcodeHasImmed_w)) {
616 return 2;
617 } else if (state->inst->flags & NACL_IFLAG(OpcodeHasImmed_o)) {
618 return 8;
619 } else if (state->inst->flags & NACL_IFLAG(OpcodeHasImmed_Addr)) {
620 return NaClExtractAddressSize(state) / 8;
621 } else if (state->inst->flags & NACL_IFLAG(OpcodeHasImmed_z)) {
622 if (state->operand_size == 2) {
623 return 2;
624 } else {
625 return 4;
626 }
627 } else {
628 return 0;
629 }
630 }
631
632 /* Returns the number of immedidate bytes to parse if a second immediate
633 * number appears in the instruction (zero if no second immediate value).
634 */
635 static int NaClGetNumImmed2Bytes(NaClInstState* state) {
636 if (state->inst->flags & NACL_IFLAG(OpcodeHasImmed2_b)) {
637 return 1;
638 } else if (state->inst->flags & NACL_IFLAG(OpcodeHasImmed2_w)) {
639 return 2;
640 } else if (state->inst->flags & NACL_IFLAG(OpcodeHasImmed2_v)) {
641 return 4;
642 } else {
643 return 0;
644 }
645 }
646
647 /* Consume the needed immediate bytes, if applicable. Abort the
648 * pattern match if any problems are found.
649 */
650 static Bool NaClConsumeImmediateBytes(NaClInstState* state) {
651 /* find out how many immediate bytes are expected. */
652 state->num_imm_bytes = NaClGetNumImmedBytes(state);
653 DEBUG(NaClLog(LOG_INFO,
654 "num immediate bytes = %"NACL_PRIu8"\n", state->num_imm_bytes));
655 state->first_imm_byte = 0;
656 if (state->num_imm_bytes > 0) {
657 int new_length;
658 /* Before reading immediate bytes, be sure that we won't walk
659 * past the end of the code segment.
660 */
661 new_length = state->bytes.length + state->num_imm_bytes;
662 if (new_length > state->length_limit) {
663 DEBUG(NaClLog(LOG_INFO, "Can't consume immediate, no more bytes!\n"));
664 return FALSE;
665 }
666 /* Read the immediate bytes. */
667 state->first_imm_byte = state->bytes.length;
668 NCInstBytesReadBytes(state->num_imm_bytes, &state->bytes);
669 }
670 /* Before returning, see if second immediate value specified. */
671 state->num_imm2_bytes = NaClGetNumImmed2Bytes(state);
672 DEBUG(NaClLog(LOG_INFO, "num immediate 2 bytes = %"NACL_PRIu8"\n",
673 state->num_imm2_bytes));
674 if (state->num_imm2_bytes > 0) {
675 int new_length;
676 /* Before reading immediate bytes, be sure that we don't walk
677 * past the end of the code segment.
678 */
679 new_length = state->bytes.length + state->num_imm2_bytes;
680 if (new_length > state->length_limit) {
681 DEBUG(NaClLog(LOG_INFO, "Can't consume 2nd immediate, no more bytes!\n"));
682 return FALSE;
683 }
684 /* Read the immediate bytes. */
685 NCInstBytesReadBytes(state->num_imm2_bytes, &state->bytes);
686 }
687 return TRUE;
688 }
689
690 /* Validate that any opcode (instruction) pattern prefix assumptions are
691 * met by prefix bits. If not, abort the pattern match.
692 */
693 static Bool NaClValidatePrefixFlags(NaClInstState* state) {
694 /* Check lock prefix assumptions. */
695 if (state->prefix_mask & kPrefixLOCK) {
696 if (state->inst->flags & NACL_IFLAG(OpcodeLockable)) {
697 /* Only allow if all destination operands are memory stores. */
698 uint32_t i;
699 Bool has_lockable_dest = FALSE;
700 NaClExpVector* vector = NaClInstStateExpVector(state);
701 DEBUG(NaClLog(LOG_INFO, "checking if lock valid on:\n");
702 NaClExpVectorPrint(NaClLogGetGio(), vector));
703 for (i = 0; i < vector->number_expr_nodes; ++i) {
704 NaClExp* node = &vector->node[i];
705 DEBUG(NaClLog(LOG_INFO, " checking node %d\n", i));
706 if ((NACL_EMPTY_EFLAGS != (node->flags & NACL_EFLAG(ExprDest))) &&
707 (node->kind == ExprMemOffset)) {
708 has_lockable_dest = TRUE;
709 break;
710 }
711 }
712 if (!has_lockable_dest) {
713 DEBUG(NaClLog(LOG_INFO, "Instruction doesn't allow lock prefix "
714 "on non-memory destination"));
715 return FALSE;
716 }
717 } else {
718 DEBUG(NaClLog(LOG_INFO, "Instruction doesn't allow lock prefix\n"));
719 return FALSE;
720 }
721 }
722 /* Check REX prefix assumptions. */
723 if (NACL_TARGET_SUBARCH == 64 &&
724 (state->prefix_mask & kPrefixREX)) {
725 if (state->inst->flags &
726 (NACL_IFLAG(OpcodeUsesRexW) | NACL_IFLAG(OpcodeHasRexR) |
727 NACL_IFLAG(OpcodeRex))) {
728 if (((state->inst->flags & NACL_IFLAG(OpcodeUsesRexW)) &&
729 0 == (state->rexprefix & 0x8)) ||
730 ((state->inst->flags & NACL_IFLAG(OpcodeHasRexR)) &&
731 0 == (state->rexprefix & 0x4))) {
732 DEBUG(NaClLog(LOG_INFO, "can't match REX prefix requirement\n"));
733 return FALSE;
734 }
735 }
736 }
737 return TRUE;
738 }
739
740 static void NaClClearInstState(NaClInstState* state, uint8_t opcode_length) {
741 if (state->bytes.length != opcode_length) {
742 NCInstBytesReset(&state->bytes);
743 NCInstBytesReadBytes(opcode_length, &state->bytes);
744 }
745 state->modrm = 0;
746 state->has_sib = FALSE;
747 state->sib = 0;
748 state->num_disp_bytes = 0;
749 state->first_disp_byte = 0;
750 state->num_imm_bytes = 0;
751 state->first_imm_byte = 0;
752 state->num_imm2_bytes = 0;
753 state->operand_size = 32;
754 state->address_size = 32;
755 state->nodes.is_defined = FALSE;
756 state->nodes.number_expr_nodes = 0;
757 }
758
759 /*
760 * Given the opcode prefix descriptor, return the list of candidate opcodes to
761 * try and match against the byte stream in the given state. Before returning,
762 * this function automatically advances the opcode prefix descriptor to describe
763 * the next list to use if the returned list doesn't provide any matches.
764 *
765 * Parameters:
766 * state - The state of the instruction being decoded.
767 * desc - The description of how the opcode bytes have been matched.
768 * The value passed in is the currrent match, the value at exit is
769 * the value to be used the next time this function is called (to
770 * get the next set of possible instructions).
771 * opcode_length - The length (in bytes) of the opcode for the returned
772 * candidate opcodes.
773 */
774 static const NaClInst* NaClGetNextInstCandidates(
775 NaClInstState* state, NaClInstPrefixDescriptor* desc,
776 uint8_t* opcode_length) {
777 const NaClInst* cand_insts;
778 if (desc->next_length_adjustment) {
779 (*opcode_length) += desc->next_length_adjustment;
780 desc->opcode_byte = state->bytes.byte[*opcode_length - 1];
781 }
782 cand_insts = g_OpcodeTable[desc->matched_prefix][desc->opcode_byte];
783 DEBUG(NaClLog(LOG_INFO, "Lookup candidates using [%s][%x]\n",
784 NaClInstPrefixName(desc->matched_prefix), desc->opcode_byte));
785 switch (desc->matched_prefix) {
786 case Prefix660F:
787 desc->matched_prefix = Prefix0F;
788 break;
789 case Prefix660F38:
790 desc->matched_prefix = Prefix0F38;
791 break;
792 case Prefix660F3A:
793 desc->matched_prefix = Prefix0F3A;
794 break;
795 case PrefixD8:
796 case PrefixD9:
797 case PrefixDA:
798 case PrefixDB:
799 case PrefixDC:
800 case PrefixDD:
801 case PrefixDE:
802 case PrefixDF:
803 desc->matched_prefix = NoPrefix;
804 desc->next_length_adjustment = -1;
805 break;
806 default:
807 /* No more simplier prefices, give up search after current lookup. */
808 desc->matched_prefix = NaClInstPrefixEnumSize;
809 break;
810 }
811 return cand_insts;
812 }
813
814 static Bool NaClConsumeOpcodeSequence(NaClInstState* state) {
815 uint8_t next_byte;
816 const NaClInstNode* next;
817 uint8_t next_length = 0;
818 const NaClInst* matching_inst = NULL;
819 uint8_t matching_length = 0;
820
821 /* Cut quick if first byte not applicable. */
822 if (state->bytes.length + next_length >= state->length_limit) return FALSE;
823 next_byte = NCInstBytesPeek(&state->bytes, next_length);
824 next = g_OpcodeSeq + 0;
825
826 /* Find maximal match in trie. */
827 while (NULL != next) {
828 if (next_byte == next->matching_byte) {
829 DEBUG(NaClLog(LOG_INFO,
830 "NaClConsume opcode char: %"NACL_PRIx8"\n", next_byte));
831 next_length++;
832 if (NULL != next->matching_inst) {
833 matching_inst = next->matching_inst;
834 matching_length = next_length;
835 }
836 if (next_length < state->length_limit) {
837 next_byte = NCInstBytesPeek(&state->bytes, next_length);
838 next = next->success;
839 } else {
840 break;
841 }
842 } else if (next->matching_byte < next_byte) {
843 next = next->fail;
844 } else {
845 break;
846 }
847 }
848 if (NULL == matching_inst) {
849 return FALSE;
850 } else {
851 /* TODO(karl) Make this more general. Currently assumes that no
852 * additional processing (other than opcode selection) is needed.
853 * This is currently safe only because all instructions modeled
854 * using opcode sequences have no (useful) operands, and hence
855 * no additional information is needed.
856 */
857 state->inst = matching_inst;
858 NCInstBytesReadBytes(matching_length, &state->bytes);
859 DEBUG(NaClLog(LOG_INFO, "matched inst sequence [%d]!\n", matching_length));
860 return TRUE;
861 }
862 }
863 23
864 /* Given the current location of the (relative) pc of the given instruction 24 /* Given the current location of the (relative) pc of the given instruction
865 * iterator, update the given state to hold the (found) matched opcode 25 * iterator, update the given state to hold the (found) matched opcode
866 * (instruction) pattern. If no matching pattern exists, set the state 26 * (instruction) pattern. If no matching pattern exists, set the state
867 * to a matched undefined opcode (instruction) pattern. In all cases, 27 * to a matched undefined opcode (instruction) pattern. In all cases,
868 * update the state to hold all information on the matched bytes of the 28 * update the state to hold all information on the matched bytes of the
869 * instruction. Note: The iterator expects that the opcode field is 29 * instruction. Note: The iterator expects that the opcode field is
870 * changed from NULL to non-NULL by this fuction. 30 * changed from NULL to non-NULL by this fuction.
871 */ 31 */
872 void NaClDecodeInst(NaClInstIter* iter, NaClInstState* state) { 32 void NaClDecodeInst(NaClInstIter* iter, NaClInstState* state) {
(...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after
1002 void NaClChangeOpcodesToXedsModel() { 162 void NaClChangeOpcodesToXedsModel() {
1003 /* Changes opcodes to match xed. That is change: 163 /* Changes opcodes to match xed. That is change:
1004 * 0f0f..1c: Pf2iw $Pq, $Qq => 0f0f..2c: Pf2iw $Pq, $Qq 164 * 0f0f..1c: Pf2iw $Pq, $Qq => 0f0f..2c: Pf2iw $Pq, $Qq
1005 * 0f0f..1d: Pf2id $Pq, $Qq => 0f0f..2d: Pf2id $Pq, $Qq 165 * 0f0f..1d: Pf2id $Pq, $Qq => 0f0f..2d: Pf2id $Pq, $Qq
1006 */ 166 */
1007 g_OpcodeTable[Prefix0F0F][0x2c] = g_OpcodeTable[Prefix0F0F][0x1c]; 167 g_OpcodeTable[Prefix0F0F][0x2c] = g_OpcodeTable[Prefix0F0F][0x1c];
1008 g_OpcodeTable[Prefix0F0F][0x1c] = NULL; 168 g_OpcodeTable[Prefix0F0F][0x1c] = NULL;
1009 g_OpcodeTable[Prefix0F0F][0x2d] = g_OpcodeTable[Prefix0F0F][0x1d]; 169 g_OpcodeTable[Prefix0F0F][0x2d] = g_OpcodeTable[Prefix0F0F][0x1d];
1010 g_OpcodeTable[Prefix0F0F][0x1d] = NULL; 170 g_OpcodeTable[Prefix0F0F][0x1d] = NULL;
1011 } 171 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698