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

Side by Side Diff: src/trusted/validator_x86/nc_inst_state_statics.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 * This file contains includes, static functions, and constants that are used
9 * the instruction iterator. The instruction decoder takes a list 9 * in nc_inst_state.c, but have been factored out and put into this file, so
10 * of candidate opcode (instruction) patterns, and searches for the 10 * that we can test them. That is, to allow nc_inst_state.c and
11 * first candidate that matches the requirements of the opcode pattern. 11 * nc_inst_state_Tests.cc to use them.
12 */ 12 */
Brad Chen 2011/04/25 21:47:27 It would probably make sense to put in a #define p
Karl 2011/06/24 18:15:00 Done.
13 13
14 #include <stdio.h> 14 #include <stdio.h>
15 #include <assert.h> 15 #include <assert.h>
16
17 #include "native_client/src/trusted/validator_x86/nc_inst_state.h"
18
19 #include "native_client/src/shared/platform/nacl_log.h" 16 #include "native_client/src/shared/platform/nacl_log.h"
20 #include "native_client/src/trusted/validator_x86/nc_inst_iter.h" 17 #include "native_client/src/trusted/validator_x86/nc_inst_iter.h"
21 #include "native_client/src/trusted/validator_x86/nc_inst_state_internal.h" 18 #include "native_client/src/trusted/validator_x86/nc_inst_state_internal.h"
22 #include "native_client/src/trusted/validator_x86/nc_inst_trans.h" 19 #include "native_client/src/trusted/validator_x86/nc_inst_trans.h"
23 #include "native_client/src/trusted/validator_x86/nc_segment.h" 20 #include "native_client/src/trusted/validator_x86/nc_segment.h"
24 #include "native_client/src/trusted/validator_x86/ncop_exps.h" 21 #include "native_client/src/trusted/validator_x86/ncop_exps.h"
25 #include "native_client/src/trusted/validator_x86/ncopcode_desc.h" 22 #include "native_client/src/trusted/validator_x86/ncopcode_desc.h"
26 #ifdef _WIN64 23 #ifdef _WIN64
27 #include "gen/native_client/src/trusted/validator_x86/nc_opcode_table64.h" 24 #include "gen/native_client/src/trusted/validator_x86/nc_opcode_table64.h"
28 #else 25 #else
29 #include "gen/native_client/src/trusted/validator_x86/nc_opcode_table.h" 26 #include "gen/native_client/src/trusted/validator_x86/nc_opcode_table.h"
30 #endif 27 #endif
31 28 #include "native_client/src/trusted/validator_x86/RexPrefixes.h"
32 /* To turn on debugging of instruction decoding, change value of
33 * DEBUGGING to 1.
34 */
35 #define DEBUGGING 0
36 29
37 #include "native_client/src/shared/utils/debugging.h" 30 #include "native_client/src/shared/utils/debugging.h"
38 31
32 EXTERN_C_BEGIN
33
39 /* Given the current location of the instruction iterator, initialize 34 /* Given the current location of the instruction iterator, initialize
40 * the given state (to match). 35 * the given state (to match).
41 */ 36 */
42 static void NaClInstStateInit(NaClInstIter* iter, NaClInstState* state) { 37 static void NaClInstStateInit(NaClInstIter* iter, NaClInstState* state) {
43 NaClMemorySize limit; 38 NaClMemorySize limit;
44 NCInstBytesInit(&state->bytes); 39 NCInstBytesInit(&state->bytes);
45 state->vpc = iter->segment->vbase + iter->index; 40 state->vpc = iter->segment->vbase + iter->index;
46 limit = iter->segment->size - iter->index; 41 limit = iter->segment->size - iter->index;
47 if (limit > NACL_MAX_BYTES_PER_X86_INSTRUCTION) { 42 if (limit > NACL_MAX_BYTES_PER_X86_INSTRUCTION) {
48 limit = NACL_MAX_BYTES_PER_X86_INSTRUCTION; 43 limit = NACL_MAX_BYTES_PER_X86_INSTRUCTION;
(...skipping 17 matching lines...) Expand all
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
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
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
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
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 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698