2 * Copyright (c) 2012 The Native Client Authors. All rights reserved.
3 * Use of this source code is governed by a BSD-style license that can be
4 * found in the LICENSE file.
8 * exhaustive instruction enumeration test for x86 Native Client validators.
10 * This file is based on enuminsts.c, but specialized to comparing two
11 * validators instead of decoders. The enuminsts.c implementation also
12 * had a bunch of Xed-specific logic which complicated the validator
13 * comparison in unhelpful ways.
16 #ifndef NACL_TRUSTED_BUT_NOT_TCB
17 #error("This file is not meant for use in the TCB.")
20 #define _CRT_RAND_S /* enable decl of rand_s() */
23 #include "native_client/src/trusted/validator/x86/testing/enuminsts/enuminsts.h"
32 #include "native_client/src/include/portability_io.h"
33 #include "native_client/src/shared/platform/nacl_log.h"
34 #include "native_client/src/shared/utils/flags.h"
35 #include "native_client/src/trusted/validator/x86/testing/enuminsts/str_utils.h"
36 #include "native_client/src/trusted/validator/x86/testing/enuminsts/text2hex.h"
38 /* Defines the maximum buffer size used to hold text generated for the
39 * disassembly of instructions, and corresponding error messages.
41 #define kBufferSize 1024
43 /* When true, print more messages (i.e. verbosely). */
44 static Bool gVerbose = FALSE;
46 /* When true, don't print out messages. That is, only print instructions
47 * defined by --print directives.
49 static Bool gSilent = FALSE;
51 /* Count of errors that have a high certainty of being exploitable. */
52 static int gSawLethalError = 0;
54 /* Defines the assumed text address for the test instruction */
55 const int kTextAddress = 0x1000;
57 /* If non-negative, defines the prefix to test. */
58 static unsigned int gPrefix = 0;
60 /* If non-negative, defines the opcode to test. */
61 static int gOpcode = -1;
63 /* This option triggers a set of behaviors that help produce repeatable
64 * output, for easier diffs on the buildbots.
66 static Bool gEasyDiffMode;
68 /* The production and new R-DFA validators */
69 NaClEnumeratorDecoder* vProd;
70 NaClEnumeratorDecoder* vDFA;
72 /* The name of the executable (i.e. argv[0] from the command line). */
73 static const char *gArgv0 = "argv0";
74 #define FLAG_EasyDiff "--easydiff"
76 /* Records that unexpected internal error occurred. */
77 void InternalError(const char *why) {
78 fprintf(stderr, "%s: Internal Error: %s\n", gArgv0, why);
82 /* Records that a fatal (i.e. non-recoverable) error occurred. */
83 void ReportFatalError(const char* why) {
84 char buffer[kBufferSize];
85 SNPRINTF(buffer, kBufferSize, "%s - quitting!", why);
86 InternalError(buffer);
90 /* Prints out the instruction each decoder disassembled */
91 static void PrintDisassembledInstructionVariants(NaClEnumerator *pinst,
92 NaClEnumerator *dinst) {
93 vProd->_print_inst_fn(pinst);
94 vDFA->_print_inst_fn(dinst);
97 /* Prints out progress messages. */
98 static void PrintVProgress(const char* format, va_list ap) {
100 /* Generating opcode sequences, so add special prefix so that we
101 * can print these out when read by the corresponding input decoder.
103 printf("#PROGRESS#");
108 static void PrintProgress(const char* format, ...) ATTRIBUTE_FORMAT_PRINTF(1,2);
110 /* Prints out progress messages. */
111 static void PrintProgress(const char* format, ...) {
113 va_start(ap, format);
114 PrintVProgress(format, ap);
118 /* Report a disagreement between decoders.
120 static void DecoderError(const char *why,
121 NaClEnumerator *pinst,
122 NaClEnumerator *dinst,
123 const char *details) {
124 /* If reached, did not skip, so report the error. */
125 printf("**** ERROR: %s: %s\n", why, (details == NULL ? "" : details));
126 PrintDisassembledInstructionVariants(pinst, dinst);
129 static void PrintBytes(FILE *f, uint8_t* bytes, size_t len) {
131 for (i = 0; i < len; i++) {
132 fprintf(f, "%02x", bytes[i]);
142 } gVDiffStats = {0, 0, 0, 0, 0};
144 static void IncrTried(void) {
145 gVDiffStats.tried += 1;
148 static void IncrValid(void) {
149 gVDiffStats.valid += 1;
152 static void IncrInvalid(void) {
153 gVDiffStats.invalid += 1;
156 static void IncrErrors(void) {
157 gVDiffStats.errors += 1;
160 static void IncrIgnored(void) {
161 gVDiffStats.ignored += 1;
164 static void PrintStats(void) {
166 if (!gEasyDiffMode) {
167 printf("valid: %" NACL_PRIu64 "\n", gVDiffStats.valid);
168 printf("invalid: %" NACL_PRIu64 "\n", gVDiffStats.invalid);
170 printf("errors: %" NACL_PRIu64 "\n", gVDiffStats.errors);
171 printf("tried: %" NACL_PRIu64 "\n", gVDiffStats.tried);
172 printf("ignored: %" NACL_PRIu64 "\n", gVDiffStats.ignored);
173 printf(" =? %" NACL_PRIu64 " valid + invalid + errors + ignored\n",
174 gVDiffStats.valid + gVDiffStats.invalid + gVDiffStats.errors +
175 gVDiffStats.ignored);
178 static void InitInst(NaClEnumerator *nacle,
179 uint8_t *itext, size_t nbytes)
181 memcpy(nacle->_itext, itext, nbytes);
182 nacle->_num_bytes = nbytes;
185 /* Print out decodings if specified on the command line. */
186 /* Test comparison for a single instruction. */
187 static void TryOneInstruction(uint8_t *itext, size_t nbytes) {
188 NaClEnumerator pinst; /* for prod validator */
189 NaClEnumerator dinst; /* for dfa validator */
190 Bool prod_okay, rdfa_okay;
195 printf("================");
196 PrintBytes(stdout, itext, nbytes);
200 /* Try to parse the sequence of test bytes. */
201 InitInst(&pinst, itext, nbytes);
202 InitInst(&dinst, itext, nbytes);
203 vProd->_parse_inst_fn(&pinst, kTextAddress);
204 vDFA->_parse_inst_fn(&dinst, kTextAddress);
205 prod_okay = vProd->_maybe_inst_validates_fn(&pinst);
206 rdfa_okay = vDFA->_maybe_inst_validates_fn(&dinst);
208 if (prod_okay && rdfa_okay) {
209 if (vProd->_inst_length_fn(&pinst) ==
210 vDFA->_inst_length_fn(&dinst)) {
211 /* Both validators see a legal instruction, */
212 /* and they agree on critical details. */
215 DecoderError("LENGTH MISMATCH", &pinst, &dinst, "");
218 } else if (prod_okay && !rdfa_okay) {
220 * 32bit production validator by design is unable to distingush a lot of
221 * instructions (the ones which work only with memory or only with
222 * registers). To avoid commiting multimegabyte golden file don't count
223 * these differences as substantial. It's not a security problem if we
224 * reject some valid x86 instructions and if we'll lose something
225 * important hopefully developers will remind us.
227 if (NACL_ARCH(NACL_BUILD_ARCH) == NACL_x86 &&
228 NACL_TARGET_SUBARCH == 32) {
231 /* Validators disagree on instruction legality */
232 DecoderError("VALIDATORS DISAGREE (prod accepts, RDFA rejects)",
238 } else if (!prod_okay && rdfa_okay) {
239 /* Validators disagree on instruction legality */
240 DecoderError("VALIDATORS DISAGREE (prod rejects, RDFA accepts)",
246 /* Both validators see an illegal instruction */
251 PrintDisassembledInstructionVariants(&pinst, &dinst);
256 /* A function type for instruction "TestAll" functions.
258 * prefix: up to four bytes of prefix.
259 * prefix_length: size_t on [0..4] specifying length of prefix.
260 * print_prefix: For easy diff of test output, avoid printing
261 * the value of a randomly selected REX prefix.
263 typedef void (*TestAllFunction)(const unsigned int prefix,
264 const size_t prefix_length,
265 const char* print_prefix);
267 /* Create a char* rendition of a prefix string, appending bytes
268 * in ps. When using a randomly generated REX prefix on the bots,
269 * it's useful to avoid printing the actual REX prefix so that
270 * output can be diffed from run-to-run. For example, instead of
271 * printing "0F45" you might print "0FXX". Parameters:
272 * prefix: The part of the prefix value to print
273 * ps: 'postscript', string to append to prefix value
274 * str: where to put the ASCII version of the prefix
276 static char* StrPrefix(const unsigned int prefix, char* ps, char* str) {
277 sprintf(str, "%x%s", prefix, (ps == NULL) ? "" : ps);
281 /* Enumerate and test all 24-bit opcode+modrm+sib patterns for a
284 static void TestAllWithPrefix(const unsigned int prefix,
285 const size_t prefix_length,
286 const char* print_prefix) {
287 const size_t kInstByteCount = NACL_ENUM_MAX_INSTRUCTION_BYTES;
288 const size_t kIterByteCount = 3;
295 if ((gPrefix > 0) && (gPrefix != prefix)) return;
297 PrintProgress("TestAllWithPrefix(%s)\n", print_prefix);
299 memcpy(itext, &prefix, prefix_length);
300 /* set up filler bytes */
301 for (i = prefix_length + kIterByteCount; i < kInstByteCount; i++) {
302 itext[i] = (uint8_t)i;
309 max_op = gOpcode + 1;
311 for (op = min_op; op < max_op; op++) {
312 itext[prefix_length] = op;
313 if (!gEasyDiffMode) PrintProgress("%02x 00 00\n", op);
314 for (modrm = 0; modrm < 256; modrm++) {
315 itext[prefix_length + 1] = modrm;
316 for (sib = 0; sib < 256; sib++) {
317 itext[prefix_length + 2] = sib;
318 TryOneInstruction(itext, kInstByteCount);
324 /* For 3DNow!, the operand byte goes at the end. Format is:
325 * 0F 0F [ModRM] [SIB] [displacement] imm8_opcode
326 * See AMD doc 24594, page 435.
328 static void TestAll3DNow(const unsigned int prefix,
329 const size_t prefix_length,
330 const char* print_prefix) {
331 const size_t kInstByteCount = NACL_ENUM_MAX_INSTRUCTION_BYTES;
332 const size_t kIterByteCount = 3;
337 if ((gPrefix > 0) && (gPrefix != prefix)) return;
339 PrintProgress("TestAll3DNow(%s)\n", print_prefix);
341 memcpy(itext, &prefix, prefix_length);
342 /* set up filler bytes */
343 for (i = prefix_length + kIterByteCount; i < kInstByteCount; i++) {
344 itext[i] = (uint8_t)i;
347 for (op = 0; op < 256; op++) {
348 if (!gEasyDiffMode) PrintProgress("%02x 00 00\n", op);
349 /* Use opcode as fill byte, forcing iteration through 3DNow opcodes. */
350 for (i = prefix_length + 2; i < kIterByteCount; i++) itext[i] = op;
352 for (modrm = 0; modrm < 256; modrm++) {
353 itext[prefix_length] = modrm;
354 for (sib = 0; sib < 256; sib++) {
355 itext[prefix_length + 1] = sib;
356 TryOneInstruction(itext, kInstByteCount);
362 #if NACL_TARGET_SUBARCH == 64
363 /* REX prefixes range from 0x40 to 0x4f. */
364 const uint32_t kREXBase = 0x40;
365 const uint32_t kREXRange = 0x10;
366 const uint32_t kREXMax = 0x50; /* kREXBase + kREXRange */
368 /* Generate a random REX prefix, to use for the entire run. */
369 static uint32_t RandomRexPrefix(void) {
370 static uint32_t static_rex_prefix = 0;
372 if (0 == static_rex_prefix) {
373 #if NACL_LINUX || NACL_OSX
374 static_rex_prefix = kREXBase + (random() % kREXRange);
376 if (rand_s(&static_rex_prefix) != 0) {
377 ReportFatalError("rand_s() failed\n");
379 static_rex_prefix = kREXBase + (static_rex_prefix % kREXRange);
382 # error "Unknown operating system."
385 return static_rex_prefix;
389 #define AppendPrefixByte(oldprefix, pbyte) (((oldprefix) << 8) | (pbyte))
390 /* For x86-64, enhance the iteration by looping through REX prefixes.
392 static void WithREX(TestAllFunction testall,
393 const unsigned int prefix,
394 const size_t prefix_length) {
395 char pstr[kBufferSize];
396 #if NACL_TARGET_SUBARCH == 64
398 unsigned int rprefix;
399 /* test with REX prefixes */
400 printf("WithREX(testall, %x, %d, %d)\n", prefix,
401 (int)prefix_length, gEasyDiffMode);
403 printf("With random REX prefix.\n");
404 irex = RandomRexPrefix();
405 rprefix = AppendPrefixByte(prefix, irex);
406 testall(rprefix, prefix_length + 1, StrPrefix(prefix, "XX", pstr));
408 for (irex = kREXBase; irex < kREXMax; irex++) {
409 rprefix = AppendPrefixByte(prefix, irex);
410 printf("With REX prefix %x\n", rprefix);
411 testall(rprefix, prefix_length + 1, StrPrefix(rprefix, "", pstr));
415 /* test with no REX prefix */
416 testall(prefix, prefix_length, StrPrefix(prefix, NULL, pstr));
418 #undef AppendPrefixByte
420 /* For all prefixes, call TestAllWithPrefix() to enumrate and test
423 static void TestAllInstructions(void) {
424 /* NOTE: Prefix byte order needs to be reversed when written as
425 * an integer. For example, for integer prefix 0x3a0f, 0f will
426 * go in instruction byte 0, and 3a in byte 1.
428 WithREX(TestAllWithPrefix, 0, 0);
429 WithREX(TestAllWithPrefix, 0x0f, 1); /* two-byte opcode */
430 WithREX(TestAllWithPrefix, 0x0ff2, 2); /* SSE2 */
431 WithREX(TestAllWithPrefix, 0x0ff3, 2); /* SSE */
432 WithREX(TestAllWithPrefix, 0x0f66, 2); /* SSE2 */
433 WithREX(TestAllWithPrefix, 0x380f, 2); /* SSSE3 */
434 WithREX(TestAllWithPrefix, 0x3a0f, 2); /* SSE4 */
435 WithREX(TestAllWithPrefix, 0x380f66, 3); /* SSE4+ */
436 WithREX(TestAllWithPrefix, 0x380ff2, 3); /* SSE4+ */
437 WithREX(TestAllWithPrefix, 0x3a0f66, 3); /* SSE4+ */
438 WithREX(TestAllWithPrefix, 0x0ff366, 3); /* SSE4+ */
439 WithREX(TestAll3DNow, 0x0f0f, 2);
442 /* Used to test one instruction at a time, for example, in regression
443 * testing, or for instruction arguments from the command line.
445 static void TestOneInstruction(const char *asciihex) {
446 InstByteArray ibytes;
449 nbytes = Text2Bytes(ibytes, asciihex, "Command-line argument", -1);
450 if (nbytes == 0) return;
453 printf("trying %s (", asciihex);
454 for (i = 0; i < nbytes; ++i) {
455 printf("%02x", ibytes[i]);
459 TryOneInstruction(ibytes, (size_t) nbytes);
462 /* A set of test cases that have caused problems in the past.
463 * This is a bit stale; most of the test cases came from xed_compare.py.
464 * Mostly this program has been tested by TestAllInstructions(),
465 * possible since this program is much faster than xed_compare.py
467 static void RunRegressionTests(void) {
468 TestOneInstruction("0024c2");
469 TestOneInstruction("017967");
470 TestOneInstruction("0f12c0");
471 TestOneInstruction("0f13c0");
472 TestOneInstruction("0f17c0");
473 TestOneInstruction("0f01c1");
474 TestOneInstruction("0f00300000112233445566778899aa");
475 TestOneInstruction("cc");
476 TestOneInstruction("C3");
477 TestOneInstruction("0f00290000112233445566778899aa");
478 TestOneInstruction("80e4f7");
479 TestOneInstruction("e9a0ffffff");
480 TestOneInstruction("4883ec08");
481 TestOneInstruction("0f00040500112233445566778899aa");
482 /* Below are newly discovered mistakes in call instructions, where the wrong
483 * byte length was required by x86-64 nacl validator.
485 TestOneInstruction("262e7e00");
486 TestOneInstruction("2e3e7900");
487 /* From the AMD manual, "An instruction may have only one REX prefix */
488 /* which must immediately precede the opcode or first excape byte */
489 /* in the instruction encoding." */
490 TestOneInstruction("406601d8"); /* illegal; REX before data16 */
491 TestOneInstruction("664001d8"); /* legal; REX after data16 */
492 TestOneInstruction("414001d8"); /* illegal; two REX bytes */
494 /* And some tests for degenerate prefix patterns */
495 TestOneInstruction("666690");
496 TestOneInstruction("6690");
497 TestOneInstruction("666666666666666666666690");
498 TestOneInstruction("66454490");
499 TestOneInstruction("66454f90");
500 TestOneInstruction("456690");
503 /* Define decoders that can be registered. */
504 extern NaClEnumeratorDecoder* RegisterNaClDecoder(void);
505 extern NaClEnumeratorDecoder* RegisterRagelDecoder(void);
507 /* Initialize the set of available decoders. */
508 static void VDiffInitializeAvailableDecoders(void) {
509 vProd = RegisterNaClDecoder();
510 vDFA = RegisterRagelDecoder();
513 static int ParseArgv(const int argc, const char* argv[]) {
518 if (nextarg < argc &&
519 0 == strcmp(argv[nextarg], FLAG_EasyDiff)) {
520 gEasyDiffMode = TRUE;
526 static char g_standard_output_buffer[4 << 10];
528 int main(const int argc, const char *argv[]) {
532 NaClLogSetVerbosity(LOG_FATAL);
533 if (0 != setvbuf(stdout, g_standard_output_buffer, _IOLBF,
534 sizeof g_standard_output_buffer)) {
535 NaClLog(LOG_FATAL, "vdiff: setvbuf failed\n");
537 #if NACL_LINUX || NACL_OSX
540 VDiffInitializeAvailableDecoders();
542 nextarg = ParseArgv(argc, argv);
543 if (nextarg == argc) {
544 if (gPrefix == 0) RunRegressionTests();
545 TestAllInstructions();
549 for (i = nextarg; i < argc; ++i) {
550 TestOneInstruction(argv[i]);
555 /* exit with non-zero error code if there were errors. */
556 exit(gVDiffStats.errors != 0);