| 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 */ |
| 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 |