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

Side by Side Diff: src/trusted/validator/x86/testing/enuminsts/vdiff.c

Issue 10871078: Enable vdiff test on validator bots (Closed) Base URL: svn://svn.chromium.org/native_client/trunk/src/native_client
Patch Set: Minor cleanups Created 8 years, 3 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) 2012 The Native Client Authors. All rights reserved. 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 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 /* vdiff.c 7 /* vdiff.c
8 * exhaustive instruction enumeration test for x86 Native Client validators. 8 * exhaustive instruction enumeration test for x86 Native Client validators.
9 * 9 *
10 * This file is based on enuminsts.c, but specialized to comparing two 10 * This file is based on enuminsts.c, but specialized to comparing two
11 * validators instead of decoders. The enuminsts.c implementation also 11 * validators instead of decoders. The enuminsts.c implementation also
12 * had a bunch of Xed-specific logic which complicated the validator 12 * had a bunch of Xed-specific logic which complicated the validator
13 * comparison in unhelpful ways. 13 * comparison in unhelpful ways.
14 */ 14 */
15 15
16 #ifndef NACL_TRUSTED_BUT_NOT_TCB 16 #ifndef NACL_TRUSTED_BUT_NOT_TCB
17 #error("This file is not meant for use in the TCB.") 17 #error("This file is not meant for use in the TCB.")
18 #endif 18 #endif
19 #if NACL_WINDOWS
20 #define _CRT_RAND_S /* enable decl of rand_s() */
21 #endif
19 22
20 #include "native_client/src/trusted/validator/x86/testing/enuminsts/enuminsts.h" 23 #include "native_client/src/trusted/validator/x86/testing/enuminsts/enuminsts.h"
21 24
22 #include <ctype.h> 25 #include <ctype.h>
23 #include <stdio.h> 26 #include <stdio.h>
24 #include <string.h> 27 #include <string.h>
25 #include <stdlib.h> 28 #include <stdlib.h>
26 #include <stdarg.h> 29 #include <stdarg.h>
30 #include <time.h>
27 31
28 #include "native_client/src/include/portability_io.h" 32 #include "native_client/src/include/portability_io.h"
29 #include "native_client/src/shared/platform/nacl_log.h" 33 #include "native_client/src/shared/platform/nacl_log.h"
30 #include "native_client/src/shared/utils/flags.h" 34 #include "native_client/src/shared/utils/flags.h"
31 #include "native_client/src/trusted/validator/x86/testing/enuminsts/str_utils.h" 35 #include "native_client/src/trusted/validator/x86/testing/enuminsts/str_utils.h"
32 #include "native_client/src/trusted/validator/x86/testing/enuminsts/text2hex.h" 36 #include "native_client/src/trusted/validator/x86/testing/enuminsts/text2hex.h"
33 37
34 /* Defines the maximum buffer size used to hold text generated for the 38 /* Defines the maximum buffer size used to hold text generated for the
35 * disassembly of instructions, and corresponding error messages. 39 * disassembly of instructions, and corresponding error messages.
36 */ 40 */
37 #define kBufferSize 1024 41 #define kBufferSize 1024
38 42
39 /* When true, print more messages (i.e. verbosely). */ 43 /* When true, print more messages (i.e. verbosely). */
40 static Bool gVerbose = FALSE; 44 static Bool gVerbose = FALSE;
41 45
42 /* When true, don't print out messages. That is, only print instructions 46 /* When true, don't print out messages. That is, only print instructions
43 * defined by --print directives. 47 * defined by --print directives.
44 */ 48 */
45 static Bool gSilent = FALSE; 49 static Bool gSilent = FALSE;
46 50
47 /* When true, don't report consecutive errors for consecutive instructions 51 /* When true, don't report consecutive errors for consecutive instructions
48 * with the same instruction mnemonic. 52 * with the same instruction mnemonic.
49 */ 53 */
50 static Bool gSkipRepeatReports = FALSE; 54 static Bool gSkipRepeatReports = FALSE;
51 55
56 /* Set to true to enable checking of mnemonics (opcode names).
57 */
58 static Bool gCheckMnemonics = TRUE;
59
52 /* Count of errors that have a high certainty of being exploitable. */ 60 /* Count of errors that have a high certainty of being exploitable. */
53 static int gSawLethalError = 0; 61 static int gSawLethalError = 0;
54 62
55 /* Defines the assumed text address for the test instruction */ 63 /* Defines the assumed text address for the test instruction */
56 const int kTextAddress = 0x1000; 64 const int kTextAddress = 0x1000;
57 65
58 /* If non-negative, defines the prefix to test. */ 66 /* If non-negative, defines the prefix to test. */
59 static unsigned int gPrefix = 0; 67 static unsigned int gPrefix = 0;
60 68
61 /* If non-negative, defines the opcode to test. */ 69 /* If non-negative, defines the opcode to test. */
62 static int gOpcode = -1; 70 static int gOpcode = -1;
63 71
72 /* This option triggers a set of behaviors that help produce repeatable
73 * output, for easier diffs on the buildbots.
74 */
75 static Bool gEasyDiffMode;
76
64 /* The production and new R-DFA validators */ 77 /* The production and new R-DFA validators */
65 NaClEnumeratorDecoder* vProd; 78 NaClEnumeratorDecoder* vProd;
66 NaClEnumeratorDecoder* vDFA; 79 NaClEnumeratorDecoder* vDFA;
67 80
68 /* The name of the executable (i.e. argv[0] from the command line). */ 81 /* The name of the executable (i.e. argv[0] from the command line). */
69 static char *gArgv0 = "argv0"; 82 static const char *gArgv0 = "argv0";
83 #define FLAG_EasyDiff "--easydiff"
70 84
71 /* Records that unexpected internal error occurred. */ 85 /* Records that unexpected internal error occurred. */
72 void InternalError(const char *why) { 86 void InternalError(const char *why) {
73 fprintf(stderr, "%s: Internal Error: %s\n", gArgv0, why); 87 fprintf(stderr, "%s: Internal Error: %s\n", gArgv0, why);
74 gSawLethalError = 1; 88 gSawLethalError = 1;
75 } 89 }
76 90
77 /* Records that a fatal (i.e. non-recoverable) error occurred. */ 91 /* Records that a fatal (i.e. non-recoverable) error occurred. */
78 void ReportFatalError(const char* why) { 92 void ReportFatalError(const char* why) {
79 char buffer[kBufferSize]; 93 char buffer[kBufferSize];
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
138 } 152 }
139 153
140 static void CheckMnemonics(NaClEnumerator* pinst, NaClEnumerator* dinst) { 154 static void CheckMnemonics(NaClEnumerator* pinst, NaClEnumerator* dinst) {
141 const char* prod_opcode = vProd->_get_inst_mnemonic_fn(pinst); 155 const char* prod_opcode = vProd->_get_inst_mnemonic_fn(pinst);
142 const char* dfa_opcode = vDFA->_get_inst_mnemonic_fn(dinst); 156 const char* dfa_opcode = vDFA->_get_inst_mnemonic_fn(dinst);
143 157
144 if (0 != strcmp(prod_opcode, dfa_opcode)) { 158 if (0 != strcmp(prod_opcode, dfa_opcode)) {
145 /* avoid redundant messages... */ 159 /* avoid redundant messages... */
146 if (NotOpcodeRepeat(prod_opcode)) { 160 if (NotOpcodeRepeat(prod_opcode)) {
147 printf("Warning: OPCODE MISMATCH: %s != %s\n", prod_opcode, dfa_opcode); 161 printf("Warning: OPCODE MISMATCH: %s != %s\n", prod_opcode, dfa_opcode);
148 /* PrintDisassembledInstructionVariants(pinst, dinst); */
149 } 162 }
150 } 163 }
151 } 164 }
152 165
153 struct vdiff_stats { 166 struct vdiff_stats {
154 int64_t tried; 167 int64_t tried;
155 int64_t valid; 168 int64_t valid;
156 int64_t invalid; 169 int64_t invalid;
157 int64_t errors; 170 int64_t errors;
158 } gVDiffStats = {0, 0, 0, 0}; 171 } gVDiffStats = {0, 0, 0, 0};
159 172
160 static void IncrTried() { 173 static void IncrTried() {
161 gVDiffStats.tried += 1; 174 gVDiffStats.tried += 1;
162 } 175 }
163 176
164 static void IncrValid() { 177 static void IncrValid() {
165 gVDiffStats.valid += 1; 178 gVDiffStats.valid += 1;
166 } 179 }
167 180
168 static void IncrInvalid() { 181 static void IncrInvalid() {
169 gVDiffStats.invalid += 1; 182 gVDiffStats.invalid += 1;
170 } 183 }
171 184
172 static void IncrErrors() { 185 static void IncrErrors() {
173 gVDiffStats.errors += 1; 186 gVDiffStats.errors += 1;
174 } 187 }
175 188
176 static void PrintStats() { 189 static void PrintStats() {
177 printf("valid: %" NACL_PRIu64 "\n", gVDiffStats.valid); 190 if (!gEasyDiffMode) {
178 printf("invalid: %" NACL_PRIu64 "\n", gVDiffStats.invalid); 191 printf("Stats:\n");
192 printf("valid: %" NACL_PRIu64 "\n", gVDiffStats.valid);
193 printf("invalid: %" NACL_PRIu64 "\n", gVDiffStats.invalid);
194 }
179 printf("errors: %" NACL_PRIu64 "\n", gVDiffStats.errors); 195 printf("errors: %" NACL_PRIu64 "\n", gVDiffStats.errors);
180 printf("tried: %" NACL_PRIu64 "\n", gVDiffStats.tried); 196 printf("tried: %" NACL_PRIu64 "\n", gVDiffStats.tried);
181 printf(" =? %" NACL_PRIu64 " valid + invalid + errors\n", 197 printf(" =? %" NACL_PRIu64 " valid + invalid + errors\n",
182 gVDiffStats.valid + gVDiffStats.invalid + gVDiffStats.errors); 198 gVDiffStats.valid + gVDiffStats.invalid + gVDiffStats.errors);
183 } 199 }
184 200
185 static void InitInst(NaClEnumerator *nacle, 201 static void InitInst(NaClEnumerator *nacle,
186 uint8_t *itext, size_t nbytes) 202 uint8_t *itext, size_t nbytes)
187 { 203 {
188 memcpy(nacle->_itext, itext, nbytes); 204 memcpy(nacle->_itext, itext, nbytes);
(...skipping 24 matching lines...) Expand all
213 rdfa_okay = vDFA->_maybe_inst_validates_fn(&dinst); 229 rdfa_okay = vDFA->_maybe_inst_validates_fn(&dinst);
214 230
215 if (prod_okay) { 231 if (prod_okay) {
216 if (rdfa_okay) { 232 if (rdfa_okay) {
217 if (vProd->_inst_length_fn(&pinst) == 233 if (vProd->_inst_length_fn(&pinst) ==
218 vDFA->_inst_length_fn(&dinst)) { 234 vDFA->_inst_length_fn(&dinst)) {
219 /* Both validators see a legal instruction, */ 235 /* Both validators see a legal instruction, */
220 /* and they agree on critical details. */ 236 /* and they agree on critical details. */
221 IncrValid(); 237 IncrValid();
222 /* Warn if decoders disagree opcode name. */ 238 /* Warn if decoders disagree opcode name. */
223 CheckMnemonics(&pinst, &dinst); 239 if (gCheckMnemonics) CheckMnemonics(&pinst, &dinst);
224 } else { 240 } else {
225 DecoderError("LENGTH MISMATCH", &pinst, &dinst, ""); 241 DecoderError("LENGTH MISMATCH", &pinst, &dinst, "");
226 IncrErrors(); 242 IncrErrors();
227 } 243 }
228 } else { 244 } else {
229 /* Validators disagree on instruction legality */ 245 /* Validators disagree on instruction legality */
230 DecoderError("VALIDATORS DISAGREE", &pinst, &dinst, ""); 246 DecoderError("VALIDATORS DISAGREE", &pinst, &dinst, "");
231 IncrErrors(); 247 IncrErrors();
232 } 248 }
233 } else if (rdfa_okay) { 249 } else if (rdfa_okay) {
234 /* Validators disagree on instruction legality */ 250 /* Validators disagree on instruction legality */
235 DecoderError("VALIDATORS DISAGREE", &pinst, &dinst, ""); 251 DecoderError("VALIDATORS DISAGREE", &pinst, &dinst, "");
236 IncrErrors(); 252 IncrErrors();
237 } else { 253 } else {
238 /* Both validators see an illegal instruction */ 254 /* Both validators see an illegal instruction */
239 IncrInvalid(); 255 IncrInvalid();
240 } 256 }
241 257
242 /* no error */
243 if (gVerbose) { 258 if (gVerbose) {
244 PrintDisassembledInstructionVariants(&pinst, &dinst); 259 PrintDisassembledInstructionVariants(&pinst, &dinst);
245 } 260 }
246 } while (0); 261 } while (0);
247 } 262 }
248 263
264 /* A function type for instruction "TestAll" functions.
265 * Parameters:
266 * prefix: up to four bytes of prefix.
267 * prefix_length: size_t on [0..4] specifying length of prefix.
268 * print_prefix: For easy diff of test output, avoid printing
269 * the value of a randomly selected REX prefix.
270 */
271 typedef void (*TestAllFunction)(const unsigned int prefix,
272 const size_t prefix_length,
273 const char* print_prefix);
274
275 /* Create a char* rendition of a prefix string, appending bytes
276 * in ps. When using a randomly generated REX prefix on the bots,
277 * it's useful to avoid printing the actual REX prefix so that
278 * output can be diffed from run-to-run. For example, instead of
279 * printing "0F45" you might print "0FXX". Parameters:
280 * prefix: The part of the prefix value to print
281 * ps: 'postscript', string to append to prefix value
282 * str: where to put the ASCII version of the prefix
283 */
284 static char* StrPrefix(const unsigned int prefix, char* ps, char* str) {
285 sprintf(str, "%x%s", prefix, (ps == NULL) ? "" : ps);
286 return str;
287 }
288
249 /* Enumerate and test all 24-bit opcode+modrm+sib patterns for a 289 /* Enumerate and test all 24-bit opcode+modrm+sib patterns for a
250 * particular prefix. 290 * particular prefix.
251 */ 291 */
252 static void TestAllWithPrefix(unsigned int prefix, size_t prefix_length) { 292 static void TestAllWithPrefix(const unsigned int prefix,
253 const int kInstByteCount = NACL_ENUM_MAX_INSTRUCTION_BYTES; 293 const size_t prefix_length,
254 const int kIterByteCount = 3; 294 const char* print_prefix) {
295 const size_t kInstByteCount = NACL_ENUM_MAX_INSTRUCTION_BYTES;
296 const size_t kIterByteCount = 3;
255 InstByteArray itext; 297 InstByteArray itext;
256 size_t i; 298 size_t i;
257 int op, modrm, sib; 299 int op, modrm, sib;
258 int min_op; 300 int min_op;
259 int max_op; 301 int max_op;
260 302
261 if ((gPrefix > 0) && (gPrefix != prefix)) return; 303 if ((gPrefix > 0) && (gPrefix != prefix)) return;
262 304
263 PrintProgress("TestAllWithPrefix(%x)\n", prefix); 305 PrintProgress("TestAllWithPrefix(%s)\n", print_prefix);
264 /* set up prefix */ 306 /* set up prefix */
265 memcpy(itext, &prefix, prefix_length); 307 memcpy(itext, &prefix, prefix_length);
266 /* set up filler bytes */ 308 /* set up filler bytes */
267 for (i = prefix_length + kIterByteCount; 309 for (i = prefix_length + kIterByteCount;
268 i < NACL_ENUM_MAX_INSTRUCTION_BYTES; i++) { 310 i < NACL_ENUM_MAX_INSTRUCTION_BYTES; i++) {
269 itext[i] = (uint8_t)i; 311 itext[i] = (uint8_t)i;
270 } 312 }
271 if (gOpcode < 0) { 313 if (gOpcode < 0) {
272 min_op = 0; 314 min_op = 0;
273 max_op = 256; 315 max_op = 256;
274 } else { 316 } else {
275 min_op = gOpcode; 317 min_op = gOpcode;
276 max_op = gOpcode + 1; 318 max_op = gOpcode + 1;
277 } 319 }
278 for (op = min_op; op < max_op; op++) { 320 for (op = min_op; op < max_op; op++) {
279 itext[prefix_length] = op; 321 itext[prefix_length] = op;
280 PrintProgress("%02x 00 00\n", op); 322 PrintProgress("%02x 00 00\n", op);
281 for (modrm = 0; modrm < 256; modrm++) { 323 for (modrm = 0; modrm < 256; modrm++) {
282 itext[prefix_length + 1] = modrm; 324 itext[prefix_length + 1] = modrm;
283 for (sib = 0; sib < 256; sib++) { 325 for (sib = 0; sib < 256; sib++) {
284 itext[prefix_length + 2] = sib; 326 itext[prefix_length + 2] = sib;
285 TryOneInstruction(itext, kInstByteCount); 327 TryOneInstruction(itext, kInstByteCount);
286 } 328 }
287 } 329 }
288 } 330 }
289 } 331 }
290 332
333 #if NACL_TARGET_SUBARCH == 64
334 /* REX prefixes range from 0x40 to 0x4f. */
335 const uint32_t kREXBase = 0x40;
336 const uint32_t kREXRange = 0x10;
337 const uint32_t kREXMax = 0x50; /* kREXBase + kREXRange */
338
339 /* Generate a random REX prefix, to use for the entire run. */
340 static uint32_t RandomRexPrefix() {
341 static uint32_t static_rex_prefix = 0;
342
343 if (0 == static_rex_prefix) {
344 #if NACL_LINUX || NACL_OSX
345 static_rex_prefix = kREXBase + (random() % kREXRange);
346 #elif NACL_WINDOWS
347 if (rand_s(&static_rex_prefix) != 0) {
348 ReportFatalError("rand_s() failed\n");
349 } else {
350 static_rex_prefix = kREXBase + (static_rex_prefix % kREXRange);
351 }
352 #else
353 # error "Unknown operating system."
354 #endif
355 }
356 return static_rex_prefix;
357 }
358 #endif
359
360 #define AppendPrefixByte(oldprefix, pbyte) (((oldprefix) << 8) | (pbyte))
291 /* For x86-64, enhance the iteration by looping through REX prefixes. 361 /* For x86-64, enhance the iteration by looping through REX prefixes.
292 */ 362 */
293 static void TestAllWithPrefixREX(unsigned int prefix, size_t prefix_length) { 363 static void WithREX(TestAllFunction testall,
364 const unsigned int prefix,
365 const size_t prefix_length) {
366 char pstr[kBufferSize];
294 #if NACL_TARGET_SUBARCH == 64 367 #if NACL_TARGET_SUBARCH == 64
295 unsigned char REXp; 368 unsigned char irex;
296 unsigned int rprefix; 369 unsigned int rprefix;
297 /* test with REX prefixes */ 370 /* test with REX prefixes */
298 for (REXp = 0x40; REXp < 0x50; REXp++) { 371 printf("WithREX(testall, %x, %d, %d)\n", prefix,
299 rprefix = (prefix << 8 | REXp); 372 (int)prefix_length, gEasyDiffMode);
300 printf("Testing with prefix %x\n", rprefix); 373 if (gEasyDiffMode) {
301 TestAllWithPrefix(rprefix, prefix_length + 1); 374 printf("With random REX prefix.\n");
375 irex = RandomRexPrefix();
376 rprefix = AppendPrefixByte(prefix, irex);
377 testall(rprefix, prefix_length + 1, StrPrefix(prefix, "XX", pstr));
378 } else {
379 for (irex = kREXBase; irex < kREXMax; irex++) {
380 rprefix = AppendPrefixByte(prefix, irex);
381 printf("With REX prefix %x\n", rprefix);
382 testall(rprefix, prefix_length + 1, StrPrefix(rprefix, "", pstr));
383 }
302 } 384 }
303 #endif 385 #endif
304 /* test with no REX prefix */ 386 /* test with no REX prefix */
305 TestAllWithPrefix(prefix, prefix_length); 387 testall(prefix, prefix_length, StrPrefix(prefix, NULL, pstr));
306 } 388 }
389 #undef AppendPrefixByte
307 390
308 /* For all prefixes, call TestAllWithPrefix() to enumrate and test 391 /* For all prefixes, call TestAllWithPrefix() to enumrate and test
309 * all instructions. 392 * all instructions.
310 */ 393 */
311 static void TestAllInstructions() { 394 static void TestAllInstructions() {
312 gSkipRepeatReports = TRUE; 395 gSkipRepeatReports = TRUE;
313 /* NOTE: Prefix byte order needs to be reversed when written as 396 /* NOTE: Prefix byte order needs to be reversed when written as
314 * an integer. For example, for integer prefix 0x3a0f, 0f will 397 * an integer. For example, for integer prefix 0x3a0f, 0f will
315 * go in instruction byte 0, and 3a in byte 1. 398 * go in instruction byte 0, and 3a in byte 1.
316 */ 399 */
317 /* TODO(bradchen): extend enuminsts-64 to iterate over 64-bit prefixes. */ 400 WithREX(TestAllWithPrefix, 0, 0);
318 TestAllWithPrefixREX(0, 0); 401 WithREX(TestAllWithPrefix, 0x0f, 1); /* two-byte opcode */
319 TestAllWithPrefixREX(0x0f, 1); 402 WithREX(TestAllWithPrefix, 0x0ff2, 2); /* SSE2 */
320 TestAllWithPrefixREX(0x0ff2, 2); 403 WithREX(TestAllWithPrefix, 0x0ff3, 2); /* SSE */
321 TestAllWithPrefixREX(0x0ff3, 2); 404 WithREX(TestAllWithPrefix, 0x0f66, 2); /* SSE2 */
322 TestAllWithPrefixREX(0x0f66, 2); 405 WithREX(TestAllWithPrefix, 0x380f, 2); /* SSSE3 */
323 TestAllWithPrefixREX(0x0f0f, 2); 406 WithREX(TestAllWithPrefix, 0x3a0f, 2); /* SSE4 */
324 TestAllWithPrefixREX(0x380f, 2); 407 WithREX(TestAllWithPrefix, 0x380f66, 3); /* SSE4+ */
325 TestAllWithPrefixREX(0x3a0f, 2); 408 WithREX(TestAllWithPrefix, 0x380ff2, 3); /* SSE4+ */
326 TestAllWithPrefixREX(0x380f66, 3); 409 WithREX(TestAllWithPrefix, 0x3a0f66, 3); /* SSE4+ */
327 TestAllWithPrefixREX(0x380ff2, 3);
328 TestAllWithPrefixREX(0x3a0f66, 3);
329 } 410 }
330 411
331 /* Used to test one instruction at a time, for example, in regression 412 /* Used to test one instruction at a time, for example, in regression
332 * testing, or for instruction arguments from the command line. 413 * testing, or for instruction arguments from the command line.
333 */ 414 */
334 static void TestOneInstruction(char *asciihex) { 415 static void TestOneInstruction(const char *asciihex) {
335 InstByteArray ibytes; 416 InstByteArray ibytes;
336 int nbytes; 417 int nbytes;
337 418
338 nbytes = Text2Bytes(ibytes, asciihex, "Command-line argument", -1); 419 nbytes = Text2Bytes(ibytes, asciihex, "Command-line argument", -1);
339 if (nbytes == 0) return; 420 if (nbytes == 0) return;
340 if (gVerbose) { 421 if (gVerbose) {
341 int i; 422 int i;
342 printf("trying %s (", asciihex); 423 printf("trying %s (", asciihex);
343 for (i = 0; i < nbytes; ++i) { 424 for (i = 0; i < nbytes; ++i) {
344 printf("%02x", ibytes[i]); 425 printf("%02x", ibytes[i]);
(...skipping 28 matching lines...) Expand all
373 */ 454 */
374 TestOneInstruction("262e7e00"); 455 TestOneInstruction("262e7e00");
375 TestOneInstruction("2e3e7900"); 456 TestOneInstruction("2e3e7900");
376 /* From the AMD manual, "An instruction may have only one REX prefix */ 457 /* From the AMD manual, "An instruction may have only one REX prefix */
377 /* which must immediately precede the opcode or first excape byte */ 458 /* which must immediately precede the opcode or first excape byte */
378 /* in the instruction encoding." */ 459 /* in the instruction encoding." */
379 TestOneInstruction("406601d8"); /* illegal; REX before data16 */ 460 TestOneInstruction("406601d8"); /* illegal; REX before data16 */
380 TestOneInstruction("664001d8"); /* legal; REX after data16 */ 461 TestOneInstruction("664001d8"); /* legal; REX after data16 */
381 TestOneInstruction("414001d8"); /* illegal; two REX bytes */ 462 TestOneInstruction("414001d8"); /* illegal; two REX bytes */
382 463
383 /* Reset the opcode repeat test, so as not to silence erros */ 464 /* Reset the opcode repeat test, so as not to silence errors */
384 /* that happened in the regression suite. */ 465 /* that happened in the regression suite. */
385 (void)NotOpcodeRepeat(""); 466 (void)NotOpcodeRepeat("");
386 } 467 }
387 468
388 /* Define decoders that can be registered. */ 469 /* Define decoders that can be registered. */
389 extern NaClEnumeratorDecoder* RegisterNaClDecoder(); 470 extern NaClEnumeratorDecoder* RegisterNaClDecoder();
390 extern NaClEnumeratorDecoder* RegisterRagelDecoder(); 471 extern NaClEnumeratorDecoder* RegisterRagelDecoder();
391 472
392 /* Initialize the set of available decoders. */ 473 /* Initialize the set of available decoders. */
393 static void NaClInitializeAvailableDecoders() { 474 static void VDiffInitializeAvailableDecoders() {
394 vProd = RegisterNaClDecoder(); 475 vProd = RegisterNaClDecoder();
395 vDFA = RegisterRagelDecoder(); 476 vDFA = RegisterRagelDecoder();
396 } 477 }
397 478
398 int main(int argc, char *argv[]) { 479 static int ParseArgv(const int argc, const char* argv[]) {
399 int testargs; 480 int nextarg;
481
482 gArgv0 = argv[0];
483 nextarg = 1;
484 if (nextarg < argc &&
485 0 == strcmp(argv[nextarg], FLAG_EasyDiff)) {
486 gEasyDiffMode = TRUE;
487 gCheckMnemonics = FALSE;
488 nextarg += 1;
489 }
490 return nextarg;
491 }
492
493 int main(const int argc, const char *argv[]) {
494 int nextarg;
400 495
401 NaClLogModuleInit(); 496 NaClLogModuleInit();
402 NaClLogSetVerbosity(LOG_FATAL); 497 NaClLogSetVerbosity(LOG_FATAL);
403 NaClInitializeAvailableDecoders(); 498 #if NACL_LINUX || NACL_OSX
499 srandom(time(NULL));
500 #endif
501 VDiffInitializeAvailableDecoders();
404 502
405 gArgv0 = argv[0]; 503 nextarg = ParseArgv(argc, argv);
406 testargs = 1; 504 if (nextarg == argc) {
407
408 if (testargs == argc) {
409 if (gPrefix == 0) RunRegressionTests(); 505 if (gPrefix == 0) RunRegressionTests();
410 TestAllInstructions(); 506 TestAllInstructions();
411 } else { 507 } else {
412 int i; 508 int i;
413 gVerbose = TRUE; 509 gVerbose = TRUE;
414 for (i = testargs; i < argc; ++i) { 510 for (i = nextarg; i < argc; ++i) {
415 TestOneInstruction(argv[i]); 511 TestOneInstruction(argv[i]);
416 } 512 }
417 } 513 }
418 PrintStats(); 514 PrintStats();
419 } 515 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698