| OLD | NEW |
| (Empty) |
| 1 /* | |
| 2 * Copyright (c) 2012 The Native Client Authors. All rights reserved. | |
| 3 * Use of this source code is governed by a BSD-style license that can be | |
| 4 * found in the LICENSE file. | |
| 5 */ | |
| 6 | |
| 7 /* | |
| 8 * This file contains includes, static functions, and constants that are used | |
| 9 * in nc_inst_state.c, but have been factored out and put into this file, so | |
| 10 * that we can test them. That is, to allow nc_inst_state.c and | |
| 11 * nc_inst_state_Tests.cc to use them. | |
| 12 */ | |
| 13 | |
| 14 #ifndef NATIVE_CLIENT_SRC_TRUSTED_VALIDATOR_X86_DECODER_NC_INST_STATE_STATICS_C_
_ | |
| 15 #define NATIVE_CLIENT_SRC_TRUSTED_VALIDATOR_X86_DECODER_NC_INST_STATE_STATICS_C_
_ | |
| 16 | |
| 17 #include <stdio.h> | |
| 18 #include <assert.h> | |
| 19 #include "native_client/src/shared/platform/nacl_log.h" | |
| 20 #include "native_client/src/shared/utils/debugging.h" | |
| 21 #include "native_client/src/trusted/validator/x86/decoder/nc_decode_tables.h" | |
| 22 #include "native_client/src/trusted/validator/x86/decoder/nc_inst_iter.h" | |
| 23 #include "native_client/src/trusted/validator/x86/decoder/nc_inst_state_internal
.h" | |
| 24 #include "native_client/src/trusted/validator/x86/decoder/nc_inst_trans.h" | |
| 25 #include "native_client/src/trusted/validator/x86/decoder/ncop_exps.h" | |
| 26 #include "native_client/src/trusted/validator/x86/decoder/ncopcode_desc.h" | |
| 27 #include "native_client/src/trusted/validator/x86/nc_segment.h" | |
| 28 | |
| 29 #include "native_client/src/trusted/validator/x86/ncinstbuffer_inl.c" | |
| 30 #include "native_client/src/trusted/validator/x86/x86_insts_inl.c" | |
| 31 | |
| 32 EXTERN_C_BEGIN | |
| 33 | |
| 34 /* Given the current location of the instruction iterator, initialize | |
| 35 * the given state (to match). | |
| 36 */ | |
| 37 static void NaClInstStateInit(NaClInstIter* iter, NaClInstState* state) { | |
| 38 NaClMemorySize limit; | |
| 39 NCInstBytesInitInline(&state->bytes); | |
| 40 state->iter = iter; | |
| 41 state->decoder_tables = iter->decoder_tables; | |
| 42 state->inst_addr = iter->index; | |
| 43 limit = iter->segment->size - iter->index; | |
| 44 if (limit > NACL_MAX_BYTES_PER_X86_INSTRUCTION) { | |
| 45 limit = NACL_MAX_BYTES_PER_X86_INSTRUCTION; | |
| 46 } | |
| 47 state->length_limit = (uint8_t) limit; | |
| 48 DEBUG(NaClLog(LOG_INFO, | |
| 49 "length limit = %"NACL_PRIu8"\n", state->length_limit)); | |
| 50 state->num_prefix_bytes = 0; | |
| 51 state->opcode_prefix = 0; | |
| 52 state->num_opcode_bytes = 0; | |
| 53 state->rexprefix = 0; | |
| 54 state->num_rex_prefixes = 0; | |
| 55 state->modrm = 0; | |
| 56 state->has_prefix_duplicates = FALSE; | |
| 57 state->has_ambig_segment_prefixes = FALSE; | |
| 58 state->has_sib = FALSE; | |
| 59 state->sib = 0; | |
| 60 state->num_disp_bytes = 0; | |
| 61 state->first_disp_byte = 0; | |
| 62 state->num_imm_bytes = 0; | |
| 63 state->first_imm_byte = 0; | |
| 64 state->num_imm2_bytes = 0; | |
| 65 state->prefix_mask = 0; | |
| 66 state->inst = NULL; | |
| 67 state->nodes.is_defined = FALSE; | |
| 68 state->nodes.number_expr_nodes = 0; | |
| 69 state->unchanged = FALSE; | |
| 70 } | |
| 71 | |
| 72 /* Returns true if data 66 prefix is specified for the instruction, | |
| 73 * and the isntruction doesn't ignore the data 66 prefix. | |
| 74 */ | |
| 75 #define NACL_PREFIX_INST_DATA66(state) \ | |
| 76 (NaClHasBit((state)->prefix_mask, kPrefixDATA16) && \ | |
| 77 (NACL_EMPTY_IFLAGS == \ | |
| 78 ((state)->inst->flags & NACL_IFLAG(SizeIgnoresData16)))) | |
| 79 | |
| 80 /* Computes the number of bytes defined for operands of the matched | |
| 81 * instruction of the given state. Returns 0 if the operand size could | |
| 82 * not be computed, due to ambiguities in the prefix bytes. | |
| 83 */ | |
| 84 static int NaClExtractOpSize(NaClInstState* state) { | |
| 85 if (NaClHasBit(state->inst->flags, NACL_IFLAG(OperandSize_b))) { | |
| 86 return 1; | |
| 87 } | |
| 88 if (NACL_TARGET_SUBARCH == 64) { | |
| 89 if (NaClRexW(state->rexprefix)) { | |
| 90 if (NACL_PREFIX_INST_DATA66(state)) | |
| 91 /* According to the AMD and INTEL manuals, if both prefix 66 and | |
| 92 * rex.w is specified, the rex.w should be used. However, rather | |
| 93 * than tempt fate, we disallow this combination of prefixes for | |
| 94 * any such instruction, since the same effect can be achieved | |
| 95 * without the 66 prefix. | |
| 96 */ | |
| 97 return 0; | |
| 98 return 8; | |
| 99 } | |
| 100 if (NaClHasBit(state->inst->flags, NACL_IFLAG(OperandSizeForce64))) { | |
| 101 return 8; | |
| 102 } | |
| 103 if (NACL_PREFIX_INST_DATA66(state)) | |
| 104 return 2; | |
| 105 else if (NaClHasBit(state->inst->flags, NACL_IFLAG(OperandSizeDefaultIs64))) | |
| 106 return 8; | |
| 107 else | |
| 108 return 4; | |
| 109 } else if (NACL_PREFIX_INST_DATA66(state)) | |
| 110 return 2; | |
| 111 else | |
| 112 return 4; | |
| 113 } | |
| 114 | |
| 115 /* Computes the number of bits defined for addresses of the matched | |
| 116 * instruction of the given state. | |
| 117 */ | |
| 118 static int NaClExtractAddressSize(NaClInstState* state) { | |
| 119 if (NACL_TARGET_SUBARCH == 64) { | |
| 120 return NaClHasBit(state->prefix_mask, kPrefixADDR16) ? 32 : 64; | |
| 121 } else { | |
| 122 return NaClHasBit(state->prefix_mask, kPrefixADDR16) ? 16 : 32; | |
| 123 } | |
| 124 } | |
| 125 | |
| 126 /* Manual implies only 4 bytes is allowed, but I have found up to 6. | |
| 127 * Why don't we allow any number, so long as (1) There is room for | |
| 128 * at least one opcode byte, and (2) we don't exceed the max bytes. | |
| 129 */ | |
| 130 static const int kNaClMaximumPrefixBytes = | |
| 131 NACL_MAX_BYTES_PER_X86_INSTRUCTION - 1; | |
| 132 | |
| 133 /* Captures ambiguous segment prefix forms. Used to make | |
| 134 * detection of multiple prefix segment bytes. | |
| 135 */ | |
| 136 static const uint32_t segment_prefix_forms = | |
| 137 kPrefixSEGCS | kPrefixSEGSS | kPrefixSEGFS | | |
| 138 kPrefixSEGGS | kPrefixSEGES | kPrefixSEGDS; | |
| 139 | |
| 140 /* Match any prefix bytes that can be associated with the instruction | |
| 141 * currently being matched. | |
| 142 */ | |
| 143 static Bool NaClConsumePrefixBytes(NaClInstState* state) { | |
| 144 uint8_t next_byte; | |
| 145 int i; | |
| 146 uint32_t prefix_form; | |
| 147 for (i = 0; i < kNaClMaximumPrefixBytes; ++i) { | |
| 148 /* Quit early if no more bytes in segment. */ | |
| 149 if (state->bytes.length >= state->length_limit) break; | |
| 150 | |
| 151 /* Look up the corresponding prefix bit associated | |
| 152 * with the next byte in the segment, and record it. | |
| 153 */ | |
| 154 next_byte = NCRemainingMemoryLookaheadInline(state->bytes.memory,0); | |
| 155 prefix_form = state->decoder_tables->prefix_mask[next_byte]; | |
| 156 if (prefix_form == 0) break; | |
| 157 next_byte = NCInstBytesReadInline(&state->bytes); | |
| 158 DEBUG(NaClLog(LOG_INFO, | |
| 159 "Consume prefix[%d]: %02"NACL_PRIx8" => %"NACL_PRIx32"\n", | |
| 160 i, next_byte, prefix_form)); | |
| 161 /* Before updating prefix mask, determine if the prefix byte is | |
| 162 * a duplicate. | |
| 163 */ | |
| 164 if ((state->prefix_mask & prefix_form)) { | |
| 165 state->has_prefix_duplicates = TRUE; | |
| 166 DEBUG(NaClLog(LOG_INFO, | |
| 167 "duplicate prefix %02"NACL_PRIx8" detected.\n", next_byte)); | |
| 168 } else if ((prefix_form & segment_prefix_forms) && | |
| 169 (state->prefix_mask & segment_prefix_forms)) { | |
| 170 state->has_ambig_segment_prefixes = TRUE; | |
| 171 DEBUG(NaClLog(LOG_INFO, | |
| 172 "ambiguos segment prefix %02"NACL_PRIx8" detected.\n", | |
| 173 next_byte)); | |
| 174 } | |
| 175 state->prefix_mask |= prefix_form; | |
| 176 ++state->num_prefix_bytes; | |
| 177 DEBUG(NaClLog(LOG_INFO, | |
| 178 " prefix mask: %08"NACL_PRIx32"\n", state->prefix_mask)); | |
| 179 | |
| 180 /* If the prefix byte is a REX prefix, record its value, since | |
| 181 * bits 5-8 of this prefix bit may be needed later. | |
| 182 */ | |
| 183 if ((NACL_TARGET_SUBARCH == 64) && prefix_form == kPrefixREX) { | |
| 184 state->rexprefix = next_byte; | |
| 185 DEBUG(NaClLog(LOG_INFO, | |
| 186 " rexprefix = %02"NACL_PRIx8"\n", state->rexprefix)); | |
| 187 ++state->num_rex_prefixes; | |
| 188 } | |
| 189 } | |
| 190 return TRUE; | |
| 191 } | |
| 192 | |
| 193 /* Assuming we have matched the byte sequence OF 38, consume the corresponding | |
| 194 * following (instruction) opcode byte, returning the most specific prefix the | |
| 195 * patterns can match (or NaClInstPrefixEnumSize if no such patterns exist); | |
| 196 */ | |
| 197 static void NaClConsume0F38XXNaClInstBytes(NaClInstState* state, | |
| 198 NaClInstPrefixDescriptor* desc) { | |
| 199 /* Fail if there are no more bytes. Otherwise, read the next | |
| 200 * byte. | |
| 201 */ | |
| 202 if (state->bytes.length >= state->length_limit) { | |
| 203 desc->matched_prefix = NaClInstPrefixEnumSize; | |
| 204 return; | |
| 205 } | |
| 206 | |
| 207 desc->opcode_byte = NCInstBytesReadInline(&state->bytes); | |
| 208 DEBUG(NaClLog(LOG_INFO, "Consume inst byte %02"NACL_PRIx8".\n", | |
| 209 desc->opcode_byte)); | |
| 210 if (NaClExcludesBit(state->prefix_mask, kPrefixREP)) { | |
| 211 if (NaClHasBit(state->prefix_mask, kPrefixREPNE)) { | |
| 212 /* Note: Flag OpcodeAllowsData16 will explicitly clarify | |
| 213 * ambigous case of both REP and DATA16 prefixes. | |
| 214 */ | |
| 215 desc->matched_prefix = PrefixF20F38; | |
| 216 desc->opcode_prefix = kValueREPNE; | |
| 217 } else if (NaClHasBit(state->prefix_mask, kPrefixDATA16)) { | |
| 218 desc->matched_prefix = Prefix660F38; | |
| 219 desc->opcode_prefix = kValueDATA16; | |
| 220 } else { | |
| 221 desc->matched_prefix = Prefix0F38; | |
| 222 } | |
| 223 return; | |
| 224 } | |
| 225 /* If reached, can't match special prefixes, fail. */ | |
| 226 desc->matched_prefix = NaClInstPrefixEnumSize; | |
| 227 } | |
| 228 | |
| 229 /* Assuming we have matched the byte sequence OF 3A, consume the corresponding | |
| 230 * following (instruction) opcode byte, returning the most specific prefix the | |
| 231 * patterns can match (or NaClInstPrefixEnumSize if no such patterns exist). | |
| 232 */ | |
| 233 static void NaClConsume0F3AXXNaClInstBytes(NaClInstState* state, | |
| 234 NaClInstPrefixDescriptor* desc) { | |
| 235 /* Fail if there are no more bytes. Otherwise, read the next | |
| 236 * byte and choose appropriate prefix. | |
| 237 */ | |
| 238 if (state->bytes.length >= state->length_limit) { | |
| 239 desc->matched_prefix = NaClInstPrefixEnumSize; | |
| 240 return; | |
| 241 } | |
| 242 | |
| 243 desc->opcode_byte = NCInstBytesReadInline(&state->bytes); | |
| 244 DEBUG(NaClLog(LOG_INFO, "Consume inst byte %02"NACL_PRIx8".\n", | |
| 245 desc->opcode_byte)); | |
| 246 if (NaClExcludesBit(state->prefix_mask, kPrefixREP) && | |
| 247 NaClExcludesBit(state->prefix_mask, kPrefixREPNE)) { | |
| 248 if (NaClHasBit(state->prefix_mask, kPrefixDATA16)) { | |
| 249 desc->matched_prefix = Prefix660F3A; | |
| 250 desc->opcode_prefix = kValueDATA16; | |
| 251 } else { | |
| 252 desc->matched_prefix = Prefix0F3A; | |
| 253 } | |
| 254 return; | |
| 255 } | |
| 256 /* If reached, can't match special prefixes, fail. */ | |
| 257 desc->matched_prefix = NaClInstPrefixEnumSize; | |
| 258 } | |
| 259 | |
| 260 /* Assuming we have matched byte OF, consume the corresponding | |
| 261 * following (instruction) opcode byte, returning the most specific | |
| 262 * prefix the patterns can match (or NaClInstPrefixEnumSize if no such | |
| 263 * patterns exist). | |
| 264 */ | |
| 265 static void NaClConsume0FXXNaClInstBytes(NaClInstState* state, | |
| 266 NaClInstPrefixDescriptor* desc) { | |
| 267 if (NaClHasBit(state->prefix_mask, kPrefixREPNE)) { | |
| 268 if (NaClExcludesBit(state->prefix_mask, kPrefixREP)) { | |
| 269 /* Note: Flag OpcodeAllowsData16 will explicitly clarify | |
| 270 * ambigous case of both REPNE and DATA16 prefixes. | |
| 271 */ | |
| 272 desc->matched_prefix = PrefixF20F; | |
| 273 desc->opcode_prefix = kValueREPNE; | |
| 274 return; | |
| 275 } | |
| 276 } else { | |
| 277 if (NaClHasBit(state->prefix_mask, kPrefixREP)) { | |
| 278 /* Note: Flag OpcodeAllowsData16 will explicitly clarify | |
| 279 * ambigous case of both REP and DATA16 prefixes. | |
| 280 */ | |
| 281 desc->matched_prefix = PrefixF30F; | |
| 282 desc->opcode_prefix = kValueREP; | |
| 283 } else if (NaClHasBit(state->prefix_mask, kPrefixDATA16)) { | |
| 284 desc->matched_prefix = Prefix660F; | |
| 285 desc->opcode_prefix = kValueDATA16; | |
| 286 } else { | |
| 287 desc->matched_prefix = Prefix0F; | |
| 288 } | |
| 289 return; | |
| 290 } | |
| 291 /* If reached, can't match special prefixes, fail. */ | |
| 292 desc->matched_prefix = NaClInstPrefixEnumSize; | |
| 293 } | |
| 294 | |
| 295 /* Consume one of the x87 instructions that begin with D8-Df, and | |
| 296 * match the most specific prefix pattern the opcode bytes can match. | |
| 297 */ | |
| 298 static void NaClConsumeX87NaClInstBytes(NaClInstState* state, | |
| 299 NaClInstPrefixDescriptor* desc) { | |
| 300 if (state->bytes.length < state->length_limit) { | |
| 301 /* Can be two byte opcode. */ | |
| 302 desc->matched_prefix = | |
| 303 (NaClInstPrefix) (PrefixD8 + | |
| 304 (((unsigned) desc->opcode_byte) - 0xD8)); | |
| 305 desc->opcode_byte = NCInstBytesReadInline(&state->bytes); | |
| 306 DEBUG(NaClLog(LOG_INFO, "Consume inst byte %02"NACL_PRIx8".\n", | |
| 307 desc->opcode_byte)); | |
| 308 return; | |
| 309 } | |
| 310 | |
| 311 /* If reached, can only be single byte opcode, match as such. */ | |
| 312 desc->matched_prefix = NoPrefix; | |
| 313 } | |
| 314 | |
| 315 /* Consume the opcode bytes, and return the most specific prefix pattern | |
| 316 * the opcode bytes can match (or NaClInstPrefixEnumSize if no such pattern | |
| 317 * exists). | |
| 318 */ | |
| 319 static void NaClConsumeInstBytes(NaClInstState* state, | |
| 320 NaClInstPrefixDescriptor* desc) { | |
| 321 | |
| 322 /* Initialize descriptor to the fail state. */ | |
| 323 desc->opcode_prefix = 0; | |
| 324 desc->opcode_byte = 0x0; | |
| 325 desc->matched_prefix = NaClInstPrefixEnumSize; | |
| 326 desc->next_length_adjustment = 0; | |
| 327 | |
| 328 /* Be sure that we don't exceed the segment length. */ | |
| 329 if (state->bytes.length >= state->length_limit) return; | |
| 330 | |
| 331 desc->opcode_byte = NCInstBytesReadInline(&state->bytes); | |
| 332 DEBUG(NaClLog(LOG_INFO, "Consume inst byte %02"NACL_PRIx8".\n", | |
| 333 desc->opcode_byte)); | |
| 334 switch (desc->opcode_byte) { | |
| 335 case 0x0F: | |
| 336 if (state->bytes.length >= state->length_limit) return; | |
| 337 desc->opcode_byte = NCInstBytesReadInline(&state->bytes); | |
| 338 DEBUG(NaClLog(LOG_INFO, "Consume inst byte %02"NACL_PRIx8".\n", | |
| 339 desc->opcode_byte)); | |
| 340 switch (desc->opcode_byte) { | |
| 341 case 0x38: | |
| 342 NaClConsume0F38XXNaClInstBytes(state, desc); | |
| 343 break; | |
| 344 case 0x3a: | |
| 345 NaClConsume0F3AXXNaClInstBytes(state, desc); | |
| 346 break; | |
| 347 default: | |
| 348 NaClConsume0FXXNaClInstBytes(state, desc); | |
| 349 break; | |
| 350 } | |
| 351 break; | |
| 352 case 0xD8: | |
| 353 case 0xD9: | |
| 354 case 0xDA: | |
| 355 case 0xDB: | |
| 356 case 0xDC: | |
| 357 case 0xDD: | |
| 358 case 0xDE: | |
| 359 case 0xDF: | |
| 360 NaClConsumeX87NaClInstBytes(state, desc); | |
| 361 break; | |
| 362 default: | |
| 363 desc->matched_prefix = NoPrefix; | |
| 364 break; | |
| 365 } | |
| 366 DEBUG(NaClLog(LOG_INFO, | |
| 367 "matched prefix = %s\n", | |
| 368 NaClInstPrefixName(desc->matched_prefix))); | |
| 369 } | |
| 370 | |
| 371 /* Compute the operand and address sizes for the instruction. Then, verify | |
| 372 * that the opcode (instruction) pattern allows for such sizes. Aborts | |
| 373 * the pattern match if any problems. | |
| 374 */ | |
| 375 static Bool NaClConsumeAndCheckOperandSize(NaClInstState* state) { | |
| 376 /* Get and check that operand size is defined. */ | |
| 377 state->operand_size = NaClExtractOpSize(state); | |
| 378 DEBUG(NaClLog(LOG_INFO, | |
| 379 "operand size = %"NACL_PRIu8"\n", state->operand_size)); | |
| 380 if (0 == state->operand_size) { | |
| 381 DEBUG(NaClLog(LOG_INFO, | |
| 382 "Fails: operand size is zero.\n")); | |
| 383 return FALSE; | |
| 384 } | |
| 385 | |
| 386 /* Check if instruction has flags specifying legal sizes. If so, | |
| 387 * make sure that the size matches. | |
| 388 */ | |
| 389 if (state->inst->flags & | |
| 390 (NACL_IFLAG(OperandSize_w) | NACL_IFLAG(OperandSize_v) | | |
| 391 NACL_IFLAG(OperandSize_o))) { | |
| 392 NaClIFlags good = 1; | |
| 393 switch (state->operand_size) { | |
| 394 case 2: | |
| 395 good = NaClHasBit(state->inst->flags, NACL_IFLAG(OperandSize_w)); | |
| 396 break; | |
| 397 case 4: | |
| 398 good = NaClHasBit(state->inst->flags, NACL_IFLAG(OperandSize_v)); | |
| 399 break; | |
| 400 case 8: | |
| 401 good = NaClHasBit(state->inst->flags, NACL_IFLAG(OperandSize_o)); | |
| 402 break; | |
| 403 default: | |
| 404 good = 0; | |
| 405 break; | |
| 406 } | |
| 407 if (!good) { | |
| 408 /* The flags associated with the opcode (instruction) don't | |
| 409 * allow the computed sizes, abort the match of the instruction. | |
| 410 */ | |
| 411 DEBUG(NaClLog(LOG_INFO, | |
| 412 "Operand size %"NACL_PRIu8 | |
| 413 " doesn't match flag requirement!\n", | |
| 414 state->operand_size)); | |
| 415 return FALSE; | |
| 416 } | |
| 417 | |
| 418 /* Do special check for case where Rex.w and data 66 specified, and | |
| 419 * the data 66 isn't part of the opcode prefix. In such cases, we | |
| 420 * disallow both, since they are conflicting operand size specifications. | |
| 421 */ | |
| 422 if (NaClRexW(state->rexprefix) && | |
| 423 NaClHasBit(state->prefix_mask, kPrefixDATA16) && | |
| 424 /* The following checks that both 16 and 64 bit operand | |
| 425 * sizes are allowed. | |
| 426 */ | |
| 427 NaClHasBits(state->inst->flags, | |
| 428 NACL_IFLAG(OperandSize_w) | | |
| 429 NACL_IFLAG(OperandSize_o)) && | |
| 430 /* This clause allows cases where the 66 prefix changes | |
| 431 * the opcode rather than the operand size. Both flags are | |
| 432 * set iff the 66 modifies the opcode. See function | |
| 433 * NaClAddRepPrefixFlagsIfApplicable in generator/ncdecode_tablegen.c | |
| 434 * for details. | |
| 435 */ | |
| 436 !NaClHasBits(state->inst->flags, | |
| 437 NACL_IFLAG(OpcodeAllowsData16) | | |
| 438 NACL_IFLAG(SizeIgnoresData16))) { | |
| 439 DEBUG(NaClLog(LOG_INFO, | |
| 440 "Can't specify both data prefix 66 and Rex.w\n")); | |
| 441 return FALSE; | |
| 442 } | |
| 443 } | |
| 444 return TRUE; | |
| 445 } | |
| 446 | |
| 447 static Bool NaClConsumeAndCheckAddressSize(NaClInstState* state) { | |
| 448 state->address_size = NaClExtractAddressSize(state); | |
| 449 DEBUG(NaClLog(LOG_INFO, | |
| 450 "Address size = %"NACL_PRIu8"\n", state->address_size)); | |
| 451 if (state->inst->flags & | |
| 452 (NACL_IFLAG(AddressSize_w) | NACL_IFLAG(AddressSize_v) | | |
| 453 NACL_IFLAG(AddressSize_o))) { | |
| 454 NaClIFlags good = 1; | |
| 455 switch (state->address_size) { | |
| 456 case 16: | |
| 457 good = NaClHasBit(state->inst->flags, NACL_IFLAG(AddressSize_w)); | |
| 458 break; | |
| 459 case 32: | |
| 460 good = NaClHasBit(state->inst->flags, NACL_IFLAG(AddressSize_v)); | |
| 461 break; | |
| 462 case 64: | |
| 463 good = NaClHasBit(state->inst->flags, NACL_IFLAG(AddressSize_o)); | |
| 464 break; | |
| 465 default: | |
| 466 good = 0; | |
| 467 break; | |
| 468 } | |
| 469 if (!good) { | |
| 470 /* The flags associated with the opcode (instruction) don't | |
| 471 * allow the computed sizes, abort the match of the instruction. | |
| 472 */ | |
| 473 DEBUG(NaClLog(LOG_INFO, | |
| 474 "Address size %"NACL_PRIu8 | |
| 475 " doesn't match flag requirement!\n", | |
| 476 state->address_size)); | |
| 477 return FALSE; | |
| 478 } | |
| 479 } | |
| 480 return TRUE; | |
| 481 } | |
| 482 | |
| 483 /* Returns true if the instruction requires a ModRm bytes. */ | |
| 484 static Bool NaClInstRequiresModRm(NaClInstState* state) { | |
| 485 return (Bool) | |
| 486 (NACL_EMPTY_IFLAGS != | |
| 487 (state->inst->flags & NACL_IFLAG(OpcodeUsesModRm))); | |
| 488 } | |
| 489 | |
| 490 /* Consume the Mod/Rm byte of the instruction, if applicable. | |
| 491 * Aborts the pattern match if any problems. | |
| 492 */ | |
| 493 static Bool NaClConsumeModRm(NaClInstState* state) { | |
| 494 /* First check if the opcode (instruction) pattern specifies that | |
| 495 * a Mod/Rm byte is needed, and that reading it will not walk | |
| 496 * past the end of the code segment. | |
| 497 */ | |
| 498 if (NaClInstRequiresModRm(state)) { | |
| 499 uint8_t byte; | |
| 500 /* Has modrm byte. */ | |
| 501 if (state->bytes.length >= state->length_limit) { | |
| 502 DEBUG(NaClLog(LOG_INFO, "Can't read mod/rm, no more bytes!\n")); | |
| 503 return FALSE; | |
| 504 } | |
| 505 byte = NCInstBytesPeekInline(&state->bytes, 0); | |
| 506 | |
| 507 /* Note: Some instructions only allow values where the ModRm mod field | |
| 508 * is 0x3. Others only allow values where the ModRm mod field isn't 0x3. | |
| 509 */ | |
| 510 if (modrm_modInline(byte) == 0x3) { | |
| 511 if (NaClHasBit(state->inst->flags, NACL_IFLAG(ModRmModIsnt0x3))) { | |
| 512 DEBUG(NaClLog(LOG_INFO, "Can't match, modrm mod field is 0x3\n")); | |
| 513 return FALSE; | |
| 514 } | |
| 515 } else { | |
| 516 if (NaClHasBit(state->inst->flags, NACL_IFLAG(ModRmModIs0x3))) { | |
| 517 DEBUG(NaClLog(LOG_INFO, "Can't match, modrm mod field not 0x3\n")); | |
| 518 return FALSE; | |
| 519 } | |
| 520 } | |
| 521 if ((NaClHasBit(state->inst->flags, NACL_IFLAG(ModRmRegSOperand))) && | |
| 522 (modrm_regInline(byte) > 5)) { | |
| 523 DEBUG(NaClLog(LOG_INFO, | |
| 524 "Can't match, modrm reg field doesn't index segment\n")); | |
| 525 return FALSE; | |
| 526 } | |
| 527 state->modrm = NCInstBytesReadInline(&state->bytes); | |
| 528 state->num_disp_bytes = 0; | |
| 529 state->first_disp_byte = 0; | |
| 530 state->sib = 0; | |
| 531 state->has_sib = FALSE; | |
| 532 DEBUG(NaClLog(LOG_INFO, "consume modrm = %02"NACL_PRIx8"\n", state->modrm)); | |
| 533 | |
| 534 /* Consume the remaining opcode value in the mod/rm byte | |
| 535 * if applicable. | |
| 536 */ | |
| 537 if (state->inst->flags & NACL_IFLAG(OpcodeInModRm)) { | |
| 538 const NaClInst* inst = state->inst; | |
| 539 if (modrm_opcodeInline(state->modrm) != | |
| 540 NaClGetOpcodeInModRm(inst->opcode_ext)) { | |
| 541 DEBUG( | |
| 542 NaClLog(LOG_INFO, | |
| 543 "Discarding, opcode in mrm byte (%02"NACL_PRIx8") " | |
| 544 "does not match\n", | |
| 545 modrm_opcodeInline(state->modrm))); | |
| 546 return FALSE; | |
| 547 } | |
| 548 if (state->inst->flags & NACL_IFLAG(OpcodeInModRmRm)) { | |
| 549 if (modrm_rmInline(state->modrm) != | |
| 550 NaClGetOpcodeInModRmRm(inst->opcode_ext)) { | |
| 551 DEBUG(NaClLog(LOG_INFO, | |
| 552 "Discarding, opcode in mrm rm field (%02"NACL_PRIx8") " | |
| 553 "does not match\n", | |
| 554 modrm_rmInline(state->modrm))); | |
| 555 return FALSE; | |
| 556 } | |
| 557 } | |
| 558 } | |
| 559 } | |
| 560 return TRUE; | |
| 561 } | |
| 562 | |
| 563 /* Returns true if the instruction requires a SIB bytes. */ | |
| 564 static Bool NaClInstRequiresSib(NaClInstState* state) { | |
| 565 /* Note: in 64-bit mode, 64-bit addressing is treated the same as 32-bit | |
| 566 * addressing. Hence, required for all but 16-bit addressing, when | |
| 567 * the right modrm bytes are specified. | |
| 568 */ | |
| 569 return (Bool) | |
| 570 (NaClInstRequiresModRm(state) && (16 != state->address_size) && | |
| 571 (modrm_rmInline(state->modrm) == | |
| 572 0x04 && modrm_modInline(state->modrm) != 0x3)); | |
| 573 } | |
| 574 | |
| 575 /* Consume the SIB byte of the instruction, if applicable. Aborts the pattern | |
| 576 * match if any problems are found. | |
| 577 */ | |
| 578 static Bool NaClConsumeSib(NaClInstState* state) { | |
| 579 /* First check that the opcode (instruction) pattern specifies that | |
| 580 * a SIB byte is needed, and that reading it will not walk past | |
| 581 * the end of the code segment. | |
| 582 */ | |
| 583 state->sib = 0; | |
| 584 state->has_sib = NaClInstRequiresSib(state); | |
| 585 DEBUG(NaClLog(LOG_INFO, "has sib = %d\n", (int) state->has_sib)); | |
| 586 if (state->has_sib) { | |
| 587 if (state->bytes.length >= state->length_limit) { | |
| 588 DEBUG(NaClLog(LOG_INFO, "Can't consume sib, no more bytes!\n")); | |
| 589 return FALSE; | |
| 590 } | |
| 591 /* Read the SIB byte and record. */ | |
| 592 state->sib = NCInstBytesReadInline(&state->bytes); | |
| 593 DEBUG(NaClLog(LOG_INFO, "sib = %02"NACL_PRIx8"\n", state->sib)); | |
| 594 if (sib_base(state->sib) == 0x05 && modrm_modInline(state->modrm) > 2) { | |
| 595 DEBUG(NaClLog(LOG_INFO, | |
| 596 "Sib byte implies modrm.mod field <= 2, match fails\n")); | |
| 597 return FALSE; | |
| 598 } | |
| 599 } | |
| 600 return TRUE; | |
| 601 } | |
| 602 | |
| 603 static int NaClGetNumDispBytes(NaClInstState* state) { | |
| 604 if (NaClInstRequiresModRm(state)) { | |
| 605 if (16 == state->address_size) { | |
| 606 /* Corresponding to table 2-1 of the Intel manual. */ | |
| 607 switch (modrm_modInline(state->modrm)) { | |
| 608 case 0x0: | |
| 609 if (modrm_rmInline(state->modrm) == 0x06) { | |
| 610 return 4; /* disp16 */ | |
| 611 } | |
| 612 break; | |
| 613 case 0x1: | |
| 614 return 1; /* disp8 */ | |
| 615 case 0x2: | |
| 616 return 2; /* disp16 */ | |
| 617 default: | |
| 618 break; | |
| 619 } | |
| 620 } else { | |
| 621 /* Note: in 64-bit mode, 64-bit addressing is treated the same as 32-bit | |
| 622 * addressing. Hence, this section covers the 32-bit addressing. | |
| 623 */ | |
| 624 switch(modrm_modInline(state->modrm)) { | |
| 625 case 0x0: | |
| 626 if (modrm_rmInline(state->modrm) == 0x05) { | |
| 627 return 4; /* disp32 */ | |
| 628 } else if (state->has_sib && sib_base(state->sib) == 0x5) { | |
| 629 return 4; | |
| 630 } | |
| 631 break; | |
| 632 case 0x1: | |
| 633 return 1; /* disp8 */ | |
| 634 case 0x2: | |
| 635 return 4; /* disp32 */ | |
| 636 default: | |
| 637 break; | |
| 638 } | |
| 639 } | |
| 640 } | |
| 641 return 0; | |
| 642 } | |
| 643 | |
| 644 /* Consume the needed displacement bytes, if applicable. Abort the | |
| 645 * pattern match if any problems are found. | |
| 646 */ | |
| 647 static Bool NaClConsumeDispBytes(NaClInstState* state) { | |
| 648 /* First check if the opcode (instruction) pattern specifies that | |
| 649 * displacement bytes should be read, and that reading it will not | |
| 650 * walk past the end of the code segment. | |
| 651 */ | |
| 652 state->num_disp_bytes = NaClGetNumDispBytes(state); | |
| 653 DEBUG(NaClLog(LOG_INFO, | |
| 654 "num disp bytes = %"NACL_PRIu8"\n", state->num_disp_bytes)); | |
| 655 state->first_disp_byte = state->bytes.length; | |
| 656 if (state->num_disp_bytes > 0) { | |
| 657 int new_length = state->bytes.length + state->num_disp_bytes; | |
| 658 if (new_length > state->length_limit) { | |
| 659 DEBUG(NaClLog(LOG_INFO, "Can't consume disp, no more bytes!\n")); | |
| 660 return FALSE; | |
| 661 } | |
| 662 /* Read the displacement bytes. */ | |
| 663 state->first_disp_byte = state->bytes.length; | |
| 664 NCInstBytesReadBytesInline(state->num_disp_bytes, &state->bytes); | |
| 665 } | |
| 666 return TRUE; | |
| 667 } | |
| 668 | |
| 669 /* Returns the number of immediate bytes to parse. */ | |
| 670 static int NaClGetNumImmedBytes(NaClInstState* state) { | |
| 671 /* First see if immediate bytes is specified. */ | |
| 672 if (0 == NaClHasBit(state->inst->flags, | |
| 673 (NACL_IFLAG(OpcodeHasImmed) | | |
| 674 NACL_IFLAG(OpcodeHasImmed_v) | | |
| 675 NACL_IFLAG(OpcodeHasImmed_b) | | |
| 676 NACL_IFLAG(OpcodeHasImmed_w) | | |
| 677 NACL_IFLAG(OpcodeHasImmed_o) | | |
| 678 NACL_IFLAG(OpcodeHasImmed_Addr) | | |
| 679 NACL_IFLAG(OpcodeHasImmed_z) | | |
| 680 NACL_IFLAG(OpcodeHasImmed_p)))) return 0; | |
| 681 | |
| 682 /* Now handle specific requests. */ | |
| 683 if (state->inst->flags & NACL_IFLAG(OpcodeHasImmed)) { | |
| 684 return state->operand_size; | |
| 685 } | |
| 686 if (state->inst->flags & NACL_IFLAG(OpcodeHasImmed_v)) { | |
| 687 return 4; | |
| 688 } else if (state->inst->flags & NACL_IFLAG(OpcodeHasImmed_b)) { | |
| 689 return 1; | |
| 690 } else if (state->inst->flags & NACL_IFLAG(OpcodeHasImmed_w)) { | |
| 691 return 2; | |
| 692 } else if (state->inst->flags & NACL_IFLAG(OpcodeHasImmed_p)) { | |
| 693 return 6; | |
| 694 } else if (state->inst->flags & NACL_IFLAG(OpcodeHasImmed_o)) { | |
| 695 return 8; | |
| 696 } else if (state->inst->flags & NACL_IFLAG(OpcodeHasImmed_Addr)) { | |
| 697 return NaClExtractAddressSize(state) / 8; | |
| 698 } else if (state->inst->flags & NACL_IFLAG(OpcodeHasImmed_z)) { | |
| 699 if (state->operand_size == 2) { | |
| 700 return 2; | |
| 701 } else { | |
| 702 return 4; | |
| 703 } | |
| 704 } else { | |
| 705 return 0; | |
| 706 } | |
| 707 } | |
| 708 | |
| 709 /* Returns the number of immedidate bytes to parse if a second immediate | |
| 710 * number appears in the instruction (zero if no second immediate value). | |
| 711 */ | |
| 712 static int NaClGetNumImmed2Bytes(NaClInstState* state) { | |
| 713 if (state->inst->flags & NACL_IFLAG(OpcodeHasImmed2_b)) { | |
| 714 return 1; | |
| 715 } else if (state->inst->flags & NACL_IFLAG(OpcodeHasImmed2_w)) { | |
| 716 return 2; | |
| 717 } else if (state->inst->flags & NACL_IFLAG(OpcodeHasImmed2_v)) { | |
| 718 return 4; | |
| 719 } else { | |
| 720 return 0; | |
| 721 } | |
| 722 } | |
| 723 | |
| 724 /* Consume the needed immediate bytes, if applicable. Abort the | |
| 725 * pattern match if any problems are found. | |
| 726 */ | |
| 727 static Bool NaClConsumeImmediateBytes(NaClInstState* state) { | |
| 728 /* find out how many immediate bytes are expected. */ | |
| 729 state->num_imm_bytes = NaClGetNumImmedBytes(state); | |
| 730 DEBUG(NaClLog(LOG_INFO, | |
| 731 "num immediate bytes = %"NACL_PRIu8"\n", state->num_imm_bytes)); | |
| 732 state->first_imm_byte = 0; | |
| 733 if (state->num_imm_bytes > 0) { | |
| 734 int new_length; | |
| 735 /* Before reading immediate bytes, be sure that we won't walk | |
| 736 * past the end of the code segment. | |
| 737 */ | |
| 738 new_length = state->bytes.length + state->num_imm_bytes; | |
| 739 if (new_length > state->length_limit) { | |
| 740 DEBUG(NaClLog(LOG_INFO, "Can't consume immediate, no more bytes!\n")); | |
| 741 return FALSE; | |
| 742 } | |
| 743 /* Read the immediate bytes. */ | |
| 744 state->first_imm_byte = state->bytes.length; | |
| 745 NCInstBytesReadBytesInline(state->num_imm_bytes, &state->bytes); | |
| 746 } | |
| 747 /* Before returning, see if second immediate value specified. */ | |
| 748 state->num_imm2_bytes = NaClGetNumImmed2Bytes(state); | |
| 749 DEBUG(NaClLog(LOG_INFO, "num immediate 2 bytes = %"NACL_PRIu8"\n", | |
| 750 state->num_imm2_bytes)); | |
| 751 if (state->num_imm2_bytes > 0) { | |
| 752 int new_length; | |
| 753 /* Before reading immediate bytes, be sure that we don't walk | |
| 754 * past the end of the code segment. | |
| 755 */ | |
| 756 new_length = state->bytes.length + state->num_imm2_bytes; | |
| 757 if (new_length > state->length_limit) { | |
| 758 DEBUG(NaClLog(LOG_INFO, "Can't consume 2nd immediate, no more bytes!\n")); | |
| 759 return FALSE; | |
| 760 } | |
| 761 /* Read the immediate bytes. */ | |
| 762 NCInstBytesReadBytesInline(state->num_imm2_bytes, &state->bytes); | |
| 763 } | |
| 764 return TRUE; | |
| 765 } | |
| 766 | |
| 767 /* Validate that any opcode (instruction) pattern prefix assumptions are | |
| 768 * met by prefix bits. If not, abort the pattern match. | |
| 769 */ | |
| 770 static Bool NaClValidatePrefixFlags(NaClInstState* state) { | |
| 771 /* Check lock prefix assumptions. */ | |
| 772 if (state->prefix_mask & kPrefixLOCK) { | |
| 773 if (state->inst->flags & NACL_IFLAG(OpcodeLockable)) { | |
| 774 /* Only allow if all destination operands are memory stores. */ | |
| 775 uint32_t i; | |
| 776 Bool has_lockable_dest = FALSE; | |
| 777 NaClExpVector* vector = NaClInstStateExpVector(state); | |
| 778 DEBUG(NaClLog(LOG_INFO, "checking if lock valid on:\n"); | |
| 779 NaClExpVectorPrint(NaClLogGetGio(), state)); | |
| 780 for (i = 0; i < vector->number_expr_nodes; ++i) { | |
| 781 NaClExp* node = &vector->node[i]; | |
| 782 DEBUG(NaClLog(LOG_INFO, " checking node %d\n", i)); | |
| 783 if ((NACL_EMPTY_EFLAGS != (node->flags & NACL_EFLAG(ExprSet))) && | |
| 784 (node->kind == ExprMemOffset)) { | |
| 785 has_lockable_dest = TRUE; | |
| 786 break; | |
| 787 } | |
| 788 } | |
| 789 if (!has_lockable_dest) { | |
| 790 DEBUG(NaClLog(LOG_INFO, "Instruction doesn't allow lock prefix " | |
| 791 "on non-memory destination")); | |
| 792 return FALSE; | |
| 793 } | |
| 794 } else { | |
| 795 DEBUG(NaClLog(LOG_INFO, "Instruction doesn't allow lock prefix\n")); | |
| 796 return FALSE; | |
| 797 } | |
| 798 } | |
| 799 /* Check REX prefix assumptions. */ | |
| 800 if (NACL_TARGET_SUBARCH == 64 && | |
| 801 (state->prefix_mask & kPrefixREX)) { | |
| 802 if (state->inst->flags & | |
| 803 (NACL_IFLAG(OpcodeUsesRexW) | NACL_IFLAG(OpcodeHasRexR) | | |
| 804 NACL_IFLAG(OpcodeRex))) { | |
| 805 if (((state->inst->flags & NACL_IFLAG(OpcodeUsesRexW)) && | |
| 806 0 == (state->rexprefix & 0x8)) || | |
| 807 ((state->inst->flags & NACL_IFLAG(OpcodeHasRexR)) && | |
| 808 0 == (state->rexprefix & 0x4))) { | |
| 809 DEBUG(NaClLog(LOG_INFO, "can't match REX prefix requirement\n")); | |
| 810 return FALSE; | |
| 811 } | |
| 812 } | |
| 813 } | |
| 814 return TRUE; | |
| 815 } | |
| 816 | |
| 817 /* Move back to point just after the prefix sequence (defined by | |
| 818 * inst_length). | |
| 819 */ | |
| 820 static void NaClClearInstState(NaClInstState* state, uint8_t inst_length) { | |
| 821 if (state->bytes.length != inst_length) { | |
| 822 NCInstBytesResetInline(&state->bytes); | |
| 823 NCInstBytesReadBytesInline(inst_length, &state->bytes); | |
| 824 } | |
| 825 state->modrm = 0; | |
| 826 state->has_sib = FALSE; | |
| 827 state->sib = 0; | |
| 828 state->num_disp_bytes = 0; | |
| 829 state->first_disp_byte = 0; | |
| 830 state->num_imm_bytes = 0; | |
| 831 state->first_imm_byte = 0; | |
| 832 state->num_imm2_bytes = 0; | |
| 833 state->operand_size = 32; | |
| 834 state->address_size = 32; | |
| 835 state->nodes.is_defined = FALSE; | |
| 836 state->nodes.number_expr_nodes = 0; | |
| 837 } | |
| 838 | |
| 839 /* Move back to the beginning of the instruction, so that we can reparse. */ | |
| 840 static void NaClResetInstState(NaClInstState* state) { | |
| 841 if (state->bytes.length > 0) { | |
| 842 NCInstBytesResetInline(&state->bytes); | |
| 843 } | |
| 844 state->num_prefix_bytes = 0; | |
| 845 state->opcode_prefix = 0; | |
| 846 state->num_opcode_bytes = 0; | |
| 847 state->rexprefix = 0; | |
| 848 state->num_rex_prefixes = 0; | |
| 849 state->modrm = 0; | |
| 850 state->has_prefix_duplicates = FALSE; | |
| 851 state->has_ambig_segment_prefixes = FALSE; | |
| 852 state->has_sib = FALSE; | |
| 853 state->sib = 0; | |
| 854 state->num_disp_bytes = 0; | |
| 855 state->first_disp_byte = 0; | |
| 856 state->num_imm_bytes = 0; | |
| 857 state->first_imm_byte = 0; | |
| 858 state->num_imm2_bytes = 0; | |
| 859 state->prefix_mask = 0; | |
| 860 state->inst = NULL; | |
| 861 state->nodes.is_defined = FALSE; | |
| 862 state->nodes.number_expr_nodes = 0; | |
| 863 } | |
| 864 | |
| 865 /* Get the corresponding instruction for the given offset. */ | |
| 866 static const NaClInst* NaClGetOpcodeInst(const NaClDecodeTables *tables, | |
| 867 NaClOpcodeArrayOffset offset) { | |
| 868 return (NACL_OPCODE_NULL_OFFSET == offset) | |
| 869 ? NULL | |
| 870 : &tables->opcodes_table[offset]; | |
| 871 } | |
| 872 | |
| 873 /* Get the corresponding instruction for the given prefix and opcode. */ | |
| 874 static const NaClInst* NaClGetPrefixOpcodeInst(const NaClDecodeTables *tables, | |
| 875 NaClInstPrefix prefix, | |
| 876 uint8_t opcode) { | |
| 877 const NaClPrefixOpcodeSelector* selector = &tables->opcode_selectors[prefix]; | |
| 878 if ((opcode >= selector->first_opcode) && | |
| 879 (opcode <= selector->last_opcode)) { | |
| 880 return NaClGetOpcodeInst( | |
| 881 tables, | |
| 882 tables->opcode_entries[ | |
| 883 selector->table_offset + (opcode - selector->first_opcode)]); | |
| 884 } | |
| 885 return NULL; | |
| 886 } | |
| 887 | |
| 888 /* | |
| 889 * Given the opcode prefix descriptor, return the list of candidate opcodes to | |
| 890 * try and match against the byte stream in the given state. Before returning, | |
| 891 * this function automatically advances the opcode prefix descriptor to describe | |
| 892 * the next list to use if the returned list doesn't provide any matches. | |
| 893 * | |
| 894 * Parameters: | |
| 895 * state - The state of the instruction being decoded. | |
| 896 * desc - The description of how the opcode bytes have been matched. | |
| 897 * The value passed in is the currrent match, the value at exit is | |
| 898 * the value to be used the next time this function is called (to | |
| 899 * get the next set of possible instructions). | |
| 900 * opcode_length - The length (in bytes) of the opcode for the returned | |
| 901 * candidate opcodes. | |
| 902 */ | |
| 903 static const NaClInst* NaClGetNextInstCandidates( | |
| 904 NaClInstState* state, NaClInstPrefixDescriptor* desc, | |
| 905 uint8_t* inst_length) { | |
| 906 const NaClInst* cand_insts; | |
| 907 if (desc->next_length_adjustment) { | |
| 908 (*inst_length) += desc->next_length_adjustment; | |
| 909 desc->opcode_byte = state->bytes.byte[*inst_length - 1]; | |
| 910 } | |
| 911 cand_insts = NaClGetPrefixOpcodeInst(state->decoder_tables, | |
| 912 desc->matched_prefix, | |
| 913 desc->opcode_byte); | |
| 914 DEBUG(NaClLog(LOG_INFO, "Lookup candidates using [%s][%x]\n", | |
| 915 NaClInstPrefixName(desc->matched_prefix), desc->opcode_byte)); | |
| 916 switch (desc->matched_prefix) { | |
| 917 case Prefix660F: | |
| 918 desc->matched_prefix = Prefix0F; | |
| 919 desc->opcode_prefix = 0; | |
| 920 break; | |
| 921 case Prefix660F38: | |
| 922 desc->matched_prefix = Prefix0F38; | |
| 923 desc->opcode_prefix = 0; | |
| 924 break; | |
| 925 case Prefix660F3A: | |
| 926 desc->matched_prefix = Prefix0F3A; | |
| 927 desc->opcode_prefix = 0; | |
| 928 break; | |
| 929 case PrefixD8: | |
| 930 case PrefixD9: | |
| 931 case PrefixDA: | |
| 932 case PrefixDB: | |
| 933 case PrefixDC: | |
| 934 case PrefixDD: | |
| 935 case PrefixDE: | |
| 936 case PrefixDF: | |
| 937 desc->matched_prefix = NoPrefix; | |
| 938 desc->next_length_adjustment = -1; | |
| 939 break; | |
| 940 default: | |
| 941 /* No more simplier prefices, give up search after current lookup. */ | |
| 942 desc->matched_prefix = NaClInstPrefixEnumSize; | |
| 943 break; | |
| 944 } | |
| 945 return cand_insts; | |
| 946 } | |
| 947 | |
| 948 static Bool NaClConsumeHardCodedNop(NaClInstState* state) { | |
| 949 uint8_t next_byte; | |
| 950 const NaClInstNode* next; | |
| 951 uint8_t next_length = 0; | |
| 952 const NaClInst* matching_inst = NULL; | |
| 953 uint8_t matching_length = 0; | |
| 954 | |
| 955 next_byte = NCInstByteInline(&state->bytes, next_length); | |
| 956 next = state->decoder_tables->hard_coded; | |
| 957 | |
| 958 /* Find maximal match in trie. */ | |
| 959 while (NULL != next) { | |
| 960 if (next_byte == next->matching_byte) { | |
| 961 DEBUG(NaClLog(LOG_INFO, | |
| 962 "NaClConsume opcode char: %"NACL_PRIx8"\n", next_byte)); | |
| 963 next_length++; | |
| 964 if (NACL_OPCODE_NULL_OFFSET != next->matching_inst) { | |
| 965 matching_inst = NaClGetOpcodeInst(state->decoder_tables, | |
| 966 next->matching_inst); | |
| 967 matching_length = next_length; | |
| 968 } | |
| 969 if (next_length < state->length_limit) { | |
| 970 next = next->success; | |
| 971 if (next != NULL) { | |
| 972 next_byte = NCInstByteInline(&state->bytes, next_length); | |
| 973 } | |
| 974 } else { | |
| 975 break; | |
| 976 } | |
| 977 } else if (next->matching_byte < next_byte) { | |
| 978 next = next->fail; | |
| 979 } else { | |
| 980 break; | |
| 981 } | |
| 982 } | |
| 983 if (NULL == matching_inst) { | |
| 984 return FALSE; | |
| 985 } else { | |
| 986 /* TODO(karl) Make this more general. Currently assumes that no | |
| 987 * additional processing (other than opcode selection) is needed. | |
| 988 * This is currently safe only because all instructions modeled | |
| 989 * using opcode sequences have no (useful) operands, and hence | |
| 990 * no additional information is needed. | |
| 991 */ | |
| 992 NaClResetInstState(state); | |
| 993 state->inst = matching_inst; | |
| 994 NCInstBytesReadBytesInline(matching_length, &state->bytes); | |
| 995 DEBUG(NaClLog(LOG_INFO, "matched inst sequence [%d]!\n", matching_length)); | |
| 996 return TRUE; | |
| 997 } | |
| 998 } | |
| 999 | |
| 1000 EXTERN_C_END | |
| 1001 | |
| 1002 #endif /* NATIVE_CLIENT_SRC_TRUSTED_VALIDATOR_X86_DECODER_NC_INST_STATE_STATIC
S_C__ */ | |
| OLD | NEW |