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

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

Issue 625923004: Delete old x86 validator. (Closed) Base URL: svn://svn.chromium.org/native_client/trunk/src/native_client
Patch Set: rebase master Created 6 years, 2 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 side-by-side diff with in-line comments
Download patch
Index: src/trusted/validator/x86/testing/enuminsts/vdiff.c
diff --git a/src/trusted/validator/x86/testing/enuminsts/vdiff.c b/src/trusted/validator/x86/testing/enuminsts/vdiff.c
deleted file mode 100644
index fd905adff75f5549da85617882ebfec1a5838907..0000000000000000000000000000000000000000
--- a/src/trusted/validator/x86/testing/enuminsts/vdiff.c
+++ /dev/null
@@ -1,557 +0,0 @@
-/*
- * Copyright (c) 2012 The Native Client Authors. All rights reserved.
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-/* vdiff.c
- * exhaustive instruction enumeration test for x86 Native Client validators.
- *
- * This file is based on enuminsts.c, but specialized to comparing two
- * validators instead of decoders. The enuminsts.c implementation also
- * had a bunch of Xed-specific logic which complicated the validator
- * comparison in unhelpful ways.
- */
-
-#ifndef NACL_TRUSTED_BUT_NOT_TCB
-#error("This file is not meant for use in the TCB.")
-#endif
-#if NACL_WINDOWS
-#define _CRT_RAND_S /* enable decl of rand_s() */
-#endif
-
-#include "native_client/src/trusted/validator/x86/testing/enuminsts/enuminsts.h"
-
-#include <ctype.h>
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-#include <stdarg.h>
-#include <time.h>
-
-#include "native_client/src/include/portability_io.h"
-#include "native_client/src/shared/platform/nacl_log.h"
-#include "native_client/src/shared/utils/flags.h"
-#include "native_client/src/trusted/validator/x86/testing/enuminsts/str_utils.h"
-#include "native_client/src/trusted/validator/x86/testing/enuminsts/text2hex.h"
-
-/* Defines the maximum buffer size used to hold text generated for the
- * disassembly of instructions, and corresponding error messages.
- */
-#define kBufferSize 1024
-
-/* When true, print more messages (i.e. verbosely). */
-static Bool gVerbose = FALSE;
-
-/* When true, don't print out messages. That is, only print instructions
- * defined by --print directives.
- */
-static Bool gSilent = FALSE;
-
-/* Count of errors that have a high certainty of being exploitable. */
-static int gSawLethalError = 0;
-
-/* Defines the assumed text address for the test instruction */
-const int kTextAddress = 0x1000;
-
-/* If non-negative, defines the prefix to test. */
-static unsigned int gPrefix = 0;
-
-/* If non-negative, defines the opcode to test. */
-static int gOpcode = -1;
-
-/* This option triggers a set of behaviors that help produce repeatable
- * output, for easier diffs on the buildbots.
- */
-static Bool gEasyDiffMode;
-
-/* The production and new R-DFA validators */
-NaClEnumeratorDecoder* vProd;
-NaClEnumeratorDecoder* vDFA;
-
-/* The name of the executable (i.e. argv[0] from the command line). */
-static const char *gArgv0 = "argv0";
-#define FLAG_EasyDiff "--easydiff"
-
-/* Records that unexpected internal error occurred. */
-void InternalError(const char *why) {
- fprintf(stderr, "%s: Internal Error: %s\n", gArgv0, why);
- gSawLethalError = 1;
-}
-
-/* Records that a fatal (i.e. non-recoverable) error occurred. */
-void ReportFatalError(const char* why) {
- char buffer[kBufferSize];
- SNPRINTF(buffer, kBufferSize, "%s - quitting!", why);
- InternalError(buffer);
- exit(1);
-}
-
-/* Prints out the instruction each decoder disassembled */
-static void PrintDisassembledInstructionVariants(NaClEnumerator *pinst,
- NaClEnumerator *dinst) {
- vProd->_print_inst_fn(pinst);
- vDFA->_print_inst_fn(dinst);
-}
-
-/* Prints out progress messages. */
-static void PrintVProgress(const char* format, va_list ap) {
- if (gSilent) {
- /* Generating opcode sequences, so add special prefix so that we
- * can print these out when read by the corresponding input decoder.
- */
- printf("#PROGRESS#");
- }
- vprintf(format, ap);
-}
-
-static void PrintProgress(const char* format, ...) ATTRIBUTE_FORMAT_PRINTF(1,2);
-
-/* Prints out progress messages. */
-static void PrintProgress(const char* format, ...) {
- va_list ap;
- va_start(ap, format);
- PrintVProgress(format, ap);
- va_end(ap);
-}
-
-/* Report a disagreement between decoders.
- */
-static void DecoderError(const char *why,
- NaClEnumerator *pinst,
- NaClEnumerator *dinst,
- const char *details) {
- /* If reached, did not skip, so report the error. */
- printf("**** ERROR: %s: %s\n", why, (details == NULL ? "" : details));
- PrintDisassembledInstructionVariants(pinst, dinst);
-}
-
-static void PrintBytes(FILE *f, uint8_t* bytes, size_t len) {
- size_t i;
- for (i = 0; i < len; i++) {
- fprintf(f, "%02x", bytes[i]);
- }
-}
-
-struct vdiff_stats {
- int64_t tried;
- int64_t valid;
- int64_t invalid;
- int64_t errors;
- int64_t ignored;
-} gVDiffStats = {0, 0, 0, 0, 0};
-
-static void IncrTried(void) {
- gVDiffStats.tried += 1;
-}
-
-static void IncrValid(void) {
- gVDiffStats.valid += 1;
-}
-
-static void IncrInvalid(void) {
- gVDiffStats.invalid += 1;
-}
-
-static void IncrErrors(void) {
- gVDiffStats.errors += 1;
-}
-
-static void IncrIgnored(void) {
- gVDiffStats.ignored += 1;
-}
-
-static void PrintStats(void) {
- printf("Stats:\n");
- if (!gEasyDiffMode) {
- printf("valid: %" NACL_PRIu64 "\n", gVDiffStats.valid);
- printf("invalid: %" NACL_PRIu64 "\n", gVDiffStats.invalid);
- }
- printf("errors: %" NACL_PRIu64 "\n", gVDiffStats.errors);
- printf("tried: %" NACL_PRIu64 "\n", gVDiffStats.tried);
- printf("ignored: %" NACL_PRIu64 "\n", gVDiffStats.ignored);
- printf(" =? %" NACL_PRIu64 " valid + invalid + errors + ignored\n",
- gVDiffStats.valid + gVDiffStats.invalid + gVDiffStats.errors +
- gVDiffStats.ignored);
-}
-
-static void InitInst(NaClEnumerator *nacle,
- uint8_t *itext, size_t nbytes)
-{
- memcpy(nacle->_itext, itext, nbytes);
- nacle->_num_bytes = nbytes;
-}
-
-/* Print out decodings if specified on the command line. */
-/* Test comparison for a single instruction. */
-static void TryOneInstruction(uint8_t *itext, size_t nbytes) {
- NaClEnumerator pinst; /* for prod validator */
- NaClEnumerator dinst; /* for dfa validator */
- Bool prod_okay, rdfa_okay;
-
- IncrTried();
- do {
- if (gVerbose) {
- printf("================");
- PrintBytes(stdout, itext, nbytes);
- printf("\n");
- }
-
- /* Try to parse the sequence of test bytes. */
- InitInst(&pinst, itext, nbytes);
- InitInst(&dinst, itext, nbytes);
- vProd->_parse_inst_fn(&pinst, kTextAddress);
- vDFA->_parse_inst_fn(&dinst, kTextAddress);
- prod_okay = vProd->_maybe_inst_validates_fn(&pinst);
- rdfa_okay = vDFA->_maybe_inst_validates_fn(&dinst);
-
- if (prod_okay && rdfa_okay) {
- if (vProd->_inst_length_fn(&pinst) ==
- vDFA->_inst_length_fn(&dinst)) {
- /* Both validators see a legal instruction, */
- /* and they agree on critical details. */
- IncrValid();
- } else {
- DecoderError("LENGTH MISMATCH", &pinst, &dinst, "");
- IncrErrors();
- }
- } else if (prod_okay && !rdfa_okay) {
- /*
- * 32bit production validator by design is unable to distingush a lot of
- * instructions (the ones which work only with memory or only with
- * registers). To avoid commiting multimegabyte golden file don't count
- * these differences as substantial. It's not a security problem if we
- * reject some valid x86 instructions and if we'll lose something
- * important hopefully developers will remind us.
- */
- if (NACL_ARCH(NACL_BUILD_ARCH) == NACL_x86 &&
- NACL_TARGET_SUBARCH == 32) {
- IncrIgnored();
- } else {
- /* Validators disagree on instruction legality */
- DecoderError("VALIDATORS DISAGREE (prod accepts, RDFA rejects)",
- &pinst,
- &dinst,
- "");
- IncrErrors();
- }
- } else if (!prod_okay && rdfa_okay) {
- /* Validators disagree on instruction legality */
- DecoderError("VALIDATORS DISAGREE (prod rejects, RDFA accepts)",
- &pinst,
- &dinst,
- "");
- IncrErrors();
- } else {
- /* Both validators see an illegal instruction */
- IncrInvalid();
- }
-
- if (gVerbose) {
- PrintDisassembledInstructionVariants(&pinst, &dinst);
- }
- } while (0);
-}
-
-/* A function type for instruction "TestAll" functions.
- * Parameters:
- * prefix: up to four bytes of prefix.
- * prefix_length: size_t on [0..4] specifying length of prefix.
- * print_prefix: For easy diff of test output, avoid printing
- * the value of a randomly selected REX prefix.
- */
-typedef void (*TestAllFunction)(const unsigned int prefix,
- const size_t prefix_length,
- const char* print_prefix);
-
-/* Create a char* rendition of a prefix string, appending bytes
- * in ps. When using a randomly generated REX prefix on the bots,
- * it's useful to avoid printing the actual REX prefix so that
- * output can be diffed from run-to-run. For example, instead of
- * printing "0F45" you might print "0FXX". Parameters:
- * prefix: The part of the prefix value to print
- * ps: 'postscript', string to append to prefix value
- * str: where to put the ASCII version of the prefix
- */
-static char* StrPrefix(const unsigned int prefix, char* ps, char* str) {
- sprintf(str, "%x%s", prefix, (ps == NULL) ? "" : ps);
- return str;
-}
-
-/* Enumerate and test all 24-bit opcode+modrm+sib patterns for a
- * particular prefix.
- */
-static void TestAllWithPrefix(const unsigned int prefix,
- const size_t prefix_length,
- const char* print_prefix) {
- const size_t kInstByteCount = NACL_ENUM_MAX_INSTRUCTION_BYTES;
- const size_t kIterByteCount = 3;
- InstByteArray itext;
- size_t i;
- int op, modrm, sib;
- int min_op;
- int max_op;
-
- if ((gPrefix > 0) && (gPrefix != prefix)) return;
-
- PrintProgress("TestAllWithPrefix(%s)\n", print_prefix);
- /* set up prefix */
- memcpy(itext, &prefix, prefix_length);
- /* set up filler bytes */
- for (i = prefix_length + kIterByteCount; i < kInstByteCount; i++) {
- itext[i] = (uint8_t)i;
- }
- if (gOpcode < 0) {
- min_op = 0;
- max_op = 256;
- } else {
- min_op = gOpcode;
- max_op = gOpcode + 1;
- }
- for (op = min_op; op < max_op; op++) {
- itext[prefix_length] = op;
- if (!gEasyDiffMode) PrintProgress("%02x 00 00\n", op);
- for (modrm = 0; modrm < 256; modrm++) {
- itext[prefix_length + 1] = modrm;
- for (sib = 0; sib < 256; sib++) {
- itext[prefix_length + 2] = sib;
- TryOneInstruction(itext, kInstByteCount);
- }
- }
- }
-}
-
-/* For 3DNow!, the operand byte goes at the end. Format is:
- * 0F 0F [ModRM] [SIB] [displacement] imm8_opcode
- * See AMD doc 24594, page 435.
- */
-static void TestAll3DNow(const unsigned int prefix,
- const size_t prefix_length,
- const char* print_prefix) {
- const size_t kInstByteCount = NACL_ENUM_MAX_INSTRUCTION_BYTES;
- const size_t kIterByteCount = 3;
- InstByteArray itext;
- size_t i;
- int op, modrm, sib;
-
- if ((gPrefix > 0) && (gPrefix != prefix)) return;
-
- PrintProgress("TestAll3DNow(%s)\n", print_prefix);
- /* set up prefix */
- memcpy(itext, &prefix, prefix_length);
- /* set up filler bytes */
- for (i = prefix_length + kIterByteCount; i < kInstByteCount; i++) {
- itext[i] = (uint8_t)i;
- }
-
- for (op = 0; op < 256; op++) {
- if (!gEasyDiffMode) PrintProgress("%02x 00 00\n", op);
- /* Use opcode as fill byte, forcing iteration through 3DNow opcodes. */
- for (i = prefix_length + 2; i < kIterByteCount; i++) itext[i] = op;
-
- for (modrm = 0; modrm < 256; modrm++) {
- itext[prefix_length] = modrm;
- for (sib = 0; sib < 256; sib++) {
- itext[prefix_length + 1] = sib;
- TryOneInstruction(itext, kInstByteCount);
- }
- }
- }
-}
-
-#if NACL_TARGET_SUBARCH == 64
-/* REX prefixes range from 0x40 to 0x4f. */
-const uint32_t kREXBase = 0x40;
-const uint32_t kREXRange = 0x10;
-const uint32_t kREXMax = 0x50; /* kREXBase + kREXRange */
-
-/* Generate a random REX prefix, to use for the entire run. */
-static uint32_t RandomRexPrefix(void) {
- static uint32_t static_rex_prefix = 0;
-
- if (0 == static_rex_prefix) {
-#if NACL_LINUX || NACL_OSX
- static_rex_prefix = kREXBase + (random() % kREXRange);
-#elif NACL_WINDOWS
- if (rand_s(&static_rex_prefix) != 0) {
- ReportFatalError("rand_s() failed\n");
- } else {
- static_rex_prefix = kREXBase + (static_rex_prefix % kREXRange);
- }
-#else
-# error "Unknown operating system."
-#endif
- }
- return static_rex_prefix;
-}
-#endif
-
-#define AppendPrefixByte(oldprefix, pbyte) (((oldprefix) << 8) | (pbyte))
-/* For x86-64, enhance the iteration by looping through REX prefixes.
- */
-static void WithREX(TestAllFunction testall,
- const unsigned int prefix,
- const size_t prefix_length) {
- char pstr[kBufferSize];
-#if NACL_TARGET_SUBARCH == 64
- unsigned char irex;
- unsigned int rprefix;
- /* test with REX prefixes */
- printf("WithREX(testall, %x, %d, %d)\n", prefix,
- (int)prefix_length, gEasyDiffMode);
- if (gEasyDiffMode) {
- printf("With random REX prefix.\n");
- irex = RandomRexPrefix();
- rprefix = AppendPrefixByte(prefix, irex);
- testall(rprefix, prefix_length + 1, StrPrefix(prefix, "XX", pstr));
- } else {
- for (irex = kREXBase; irex < kREXMax; irex++) {
- rprefix = AppendPrefixByte(prefix, irex);
- printf("With REX prefix %x\n", rprefix);
- testall(rprefix, prefix_length + 1, StrPrefix(rprefix, "", pstr));
- }
- }
-#endif
- /* test with no REX prefix */
- testall(prefix, prefix_length, StrPrefix(prefix, NULL, pstr));
-}
-#undef AppendPrefixByte
-
-/* For all prefixes, call TestAllWithPrefix() to enumrate and test
- * all instructions.
- */
-static void TestAllInstructions(void) {
- /* NOTE: Prefix byte order needs to be reversed when written as
- * an integer. For example, for integer prefix 0x3a0f, 0f will
- * go in instruction byte 0, and 3a in byte 1.
- */
- WithREX(TestAllWithPrefix, 0, 0);
- WithREX(TestAllWithPrefix, 0x0f, 1); /* two-byte opcode */
- WithREX(TestAllWithPrefix, 0x0ff2, 2); /* SSE2 */
- WithREX(TestAllWithPrefix, 0x0ff3, 2); /* SSE */
- WithREX(TestAllWithPrefix, 0x0f66, 2); /* SSE2 */
- WithREX(TestAllWithPrefix, 0x380f, 2); /* SSSE3 */
- WithREX(TestAllWithPrefix, 0x3a0f, 2); /* SSE4 */
- WithREX(TestAllWithPrefix, 0x380f66, 3); /* SSE4+ */
- WithREX(TestAllWithPrefix, 0x380ff2, 3); /* SSE4+ */
- WithREX(TestAllWithPrefix, 0x3a0f66, 3); /* SSE4+ */
- WithREX(TestAllWithPrefix, 0x0ff366, 3); /* SSE4+ */
- WithREX(TestAll3DNow, 0x0f0f, 2);
-}
-
-/* Used to test one instruction at a time, for example, in regression
- * testing, or for instruction arguments from the command line.
- */
-static void TestOneInstruction(const char *asciihex) {
- InstByteArray ibytes;
- int nbytes;
-
- nbytes = Text2Bytes(ibytes, asciihex, "Command-line argument", -1);
- if (nbytes == 0) return;
- if (gVerbose) {
- int i;
- printf("trying %s (", asciihex);
- for (i = 0; i < nbytes; ++i) {
- printf("%02x", ibytes[i]);
- }
- printf(")\n");
- }
- TryOneInstruction(ibytes, (size_t) nbytes);
-}
-
-/* A set of test cases that have caused problems in the past.
- * This is a bit stale; most of the test cases came from xed_compare.py.
- * Mostly this program has been tested by TestAllInstructions(),
- * possible since this program is much faster than xed_compare.py
- */
-static void RunRegressionTests(void) {
- TestOneInstruction("0024c2");
- TestOneInstruction("017967");
- TestOneInstruction("0f12c0");
- TestOneInstruction("0f13c0");
- TestOneInstruction("0f17c0");
- TestOneInstruction("0f01c1");
- TestOneInstruction("0f00300000112233445566778899aa");
- TestOneInstruction("cc");
- TestOneInstruction("C3");
- TestOneInstruction("0f00290000112233445566778899aa");
- TestOneInstruction("80e4f7");
- TestOneInstruction("e9a0ffffff");
- TestOneInstruction("4883ec08");
- TestOneInstruction("0f00040500112233445566778899aa");
- /* Below are newly discovered mistakes in call instructions, where the wrong
- * byte length was required by x86-64 nacl validator.
- */
- TestOneInstruction("262e7e00");
- TestOneInstruction("2e3e7900");
- /* From the AMD manual, "An instruction may have only one REX prefix */
- /* which must immediately precede the opcode or first excape byte */
- /* in the instruction encoding." */
- TestOneInstruction("406601d8"); /* illegal; REX before data16 */
- TestOneInstruction("664001d8"); /* legal; REX after data16 */
- TestOneInstruction("414001d8"); /* illegal; two REX bytes */
-
- /* And some tests for degenerate prefix patterns */
- TestOneInstruction("666690");
- TestOneInstruction("6690");
- TestOneInstruction("666666666666666666666690");
- TestOneInstruction("66454490");
- TestOneInstruction("66454f90");
- TestOneInstruction("456690");
-}
-
-/* Define decoders that can be registered. */
-extern NaClEnumeratorDecoder* RegisterNaClDecoder(void);
-extern NaClEnumeratorDecoder* RegisterRagelDecoder(void);
-
-/* Initialize the set of available decoders. */
-static void VDiffInitializeAvailableDecoders(void) {
- vProd = RegisterNaClDecoder();
- vDFA = RegisterRagelDecoder();
-}
-
-static int ParseArgv(const int argc, const char* argv[]) {
- int nextarg;
-
- gArgv0 = argv[0];
- nextarg = 1;
- if (nextarg < argc &&
- 0 == strcmp(argv[nextarg], FLAG_EasyDiff)) {
- gEasyDiffMode = TRUE;
- nextarg += 1;
- }
- return nextarg;
-}
-
-static char g_standard_output_buffer[4 << 10];
-
-int main(const int argc, const char *argv[]) {
- int nextarg;
-
- NaClLogModuleInit();
- NaClLogSetVerbosity(LOG_FATAL);
- if (0 != setvbuf(stdout, g_standard_output_buffer, _IOLBF,
- sizeof g_standard_output_buffer)) {
- NaClLog(LOG_FATAL, "vdiff: setvbuf failed\n");
- }
-#if NACL_LINUX || NACL_OSX
- srandom(time(NULL));
-#endif
- VDiffInitializeAvailableDecoders();
-
- nextarg = ParseArgv(argc, argv);
- if (nextarg == argc) {
- if (gPrefix == 0) RunRegressionTests();
- TestAllInstructions();
- } else {
- int i;
- gVerbose = TRUE;
- for (i = nextarg; i < argc; ++i) {
- TestOneInstruction(argv[i]);
- }
- }
- PrintStats();
-
- /* exit with non-zero error code if there were errors. */
- exit(gVDiffStats.errors != 0);
-}
« no previous file with comments | « src/trusted/validator/x86/testing/enuminsts/text2hex.c ('k') | src/trusted/validator/x86/testing/enuminsts/xed_tester.c » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698