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

Unified Diff: src/trusted/validator/x86/testing/enuminsts/enuminsts.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/enuminsts.c
diff --git a/src/trusted/validator/x86/testing/enuminsts/enuminsts.c b/src/trusted/validator/x86/testing/enuminsts/enuminsts.c
deleted file mode 100644
index 52df96f9f47bb279807ab2dfe081ebceb5cd1124..0000000000000000000000000000000000000000
--- a/src/trusted/validator/x86/testing/enuminsts/enuminsts.c
+++ /dev/null
@@ -1,1331 +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.
- */
-
-/* enuminsts.c
- * exhaustive instruction enumeration test for x86 Native Client decoder.
- */
-
-/* TODO(karl) - Fix the calls to the decoder for x86-32 to use the same decoder
- * as the x86-32 validator, and document how to properly test the
- * x86-32 decoder.
- */
-#ifndef NACL_TRUSTED_BUT_NOT_TCB
-#error("This file is not meant for use in the TCB.")
-#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 "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/input_tester.h"
-#include "native_client/src/trusted/validator/x86/testing/enuminsts/str_utils.h"
-#include "native_client/src/trusted/validator/x86/testing/enuminsts/text2hex.h"
-
-/* When non-zero, prints out additional debugging messages. */
-#define kDebug 0
-
-/* 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;
-
-/* When true, don't report consecutive errors for consecutive instructions
- * with the same instruction mnemonic.
- */
-static Bool gSkipRepeatReports = FALSE;
-
-/* When true, check opcode mnemonic differences when processing each
- * instruction.
- */
-static Bool gCheckMnemonics = TRUE;
-
-/* When true, check for operand differences when processing each instruction. */
-static Bool gCheckOperands = 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;
-
-/* If true, check if nacl instruction is NACL legal. */
-static Bool gNaClLegal = FALSE;
-
-/* If true, check if nacl instruction is also implemented in xed. */
-static Bool gXedImplemented = FALSE;
-
-/* If true, don't bother to do operand compares for nop's. */
-static Bool gNoCompareNops = FALSE;
-
-/* If true, only skip contiguous errors. */
-static Bool gSkipContiguous = FALSE;
-
-static const char* target_machine = "x86-"
-#if NACL_TARGET_SUBARCH == 64
- "64"
-#else
- "32"
-#endif
- ;
-
-/* Defines maximum number of available decoders (See comments on
- * struct NaClEnumeratorDecoder in enuminst.h for details on what
- * a decoder is.
- */
-#define NACL_MAX_AVAILABLE_DECODERS 10
-
-/* Holds the set of available decoders. */
-NaClEnumeratorDecoder* kAvailableDecoders[NACL_MAX_AVAILABLE_DECODERS];
-
-/* Holds the number of (pre)registered available decoders. */
-size_t kNumAvailableDecoders;
-
-/* This struct holds a list of instruction opcode sequences that we
- * want to treat specially. Used to filter out problem cases from
- * the enumeration.
- */
-typedef struct {
- /* Pointer to array of bytes for the instruction. */
- uint8_t* bytes_;
- /* The size of bytes_. */
- size_t bytes_size_;
- /* Pointer to array of instructions. Each element is
- * the index into bytes_ where the corresponding byte sequence
- * of the instruction begins. The next element in the array is
- * the end point for the current instruction.
- */
- size_t* insts_;
- /* The size of insts_. */
- size_t insts_size_;
- /* Number of instructions stored in insts_. */
- size_t num_insts_;
- /* Number of bytes stored in bytes_. */
- size_t num_bytes_;
-} InstList;
-
-/* This struct holds state concerning an instruction, both from the
- * various available decoders. Some of the state information is
- * redundant, preserved to avoid having to recompute it.
- */
-typedef struct {
- /* Holds the set of decoders to enumerate over. */
- NaClEnumerator _enumerator;
- /* True if a decoder or comparison failed due to an error with
- * the way the instruction was decoded.
- */
- Bool _decoder_error;
-} ComparedInstruction;
-
-/* The state to use to compare instructions. */
-static ComparedInstruction gCinst;
-
-/* The name of the executable (i.e. argv[0] from the command line). */
-static char *gArgv0 = "argv0";
-
-static INLINE const char* BoolName(Bool b) {
- return b ? "true" : "false";
-}
-
-/* Print out the bindings to command line arguments. */
-static void PrintBindings(ComparedInstruction* cinst) {
- size_t i;
- for (i = 0; i < cinst->_enumerator._num_decoders; ++i) {
- fprintf(stderr, "--%s\n", cinst->_enumerator._decoder[i]->_id_name);
- }
- fprintf(stderr, "--checkmnemonics=%s\n", BoolName(gCheckMnemonics));
- fprintf(stderr, "--checkoperands=%s\n", BoolName(gCheckOperands));
- for (i = 0; i < cinst->_enumerator._num_decoders; ++i) {
- fprintf(stderr, "--%s=%s\n",
- (cinst->_enumerator._decoder[i]->_legal_only
- ? "legal" : "illegal"),
- cinst->_enumerator._decoder[i]->_id_name);
- }
- fprintf(stderr, "--nacllegal=%s\n", BoolName(gNaClLegal));
-#ifdef NACL_REVISION
- fprintf(stderr, "--nacl_revision=%d\n", NACL_REVISION);
-#endif
- if (gOpcode >= 0) fprintf(stderr, "--opcode=0x%02x\n", gOpcode);
- for (i = 0; i < cinst->_enumerator._num_decoders; ++i) {
- if (cinst->_enumerator._decoder[i]->_print_opcode_sequence) {
- fprintf(stderr, "--opcode_bytes=%s\n",
- cinst->_enumerator._decoder[i]->_id_name);
- }
- }
- for (i = 0; i < cinst->_enumerator._num_decoders; ++i) {
- if (cinst->_enumerator._decoder[i]->_print_opcode_sequence_plus_desc) {
- fprintf(stderr, "--opcode_bytes_plus_desc=%s\n",
- cinst->_enumerator._decoder[i]->_id_name);
- }
- }
- for (i = 0; i < cinst->_enumerator._num_decoders; ++i) {
- if (cinst->_enumerator._decoder[i]->_print) {
- fprintf(stderr, "--print=%s\n", cinst->_enumerator._decoder[i]->_id_name);
- }
- }
-#ifdef NACL_XED_DECODER
- fprintf(stderr, "--pin_version=\"%s\"\n", NACL_PINV);
-#endif
- if (gPrefix > 0) fprintf(stderr, "--prefix=0x%08x\n", gPrefix);
- fprintf(stderr, "--nops=%s\n", BoolName(gNoCompareNops));
- fprintf(stderr, "--skipcontiguous=%s\n", BoolName(gSkipContiguous));
- fprintf(stderr, "--verbose=%s\n", BoolName(gVerbose));
- fprintf(stderr, "--xedimplemented=%s\n", BoolName(gXedImplemented));
- exit(1);
-}
-
-/* Prints out summary of how to use this executable. and then exits. */
-static void Usage(void) {
- size_t i;
- fprintf(stderr, "usage: %s [decoders] [options] [hexbytes ...]\n",
- gArgv0);
- fprintf(stderr, "\n");
- fprintf(stderr, " Compare %s instruction decoders\n",
- target_machine);
- fprintf(stderr, "\n");
- fprintf(stderr, " With no arguments, enumerate all %s instructions.\n",
- target_machine);
- fprintf(stderr, " With arguments, decode each sequence of "
- "opcode bytes.\n");
- fprintf(stderr, "\n");
- fprintf(stderr, "Available decoders are (select using --name):\n");
- fprintf(stderr, "\n");
- for (i = 0; i < kNumAvailableDecoders; ++i) {
- fprintf(stderr, " %s: %s\n",
- kAvailableDecoders[i]->_id_name,
- kAvailableDecoders[i]->_usage_message);
- }
- fprintf(stderr, "\n");
- fprintf(stderr, "One or more filters are required:\n");
- fprintf(stderr, " --illegal=XX: Filter instructions to only consider "
- "those instructions\n");
- fprintf(stderr, " that are illegal instructions, as defined by "
- "decoder XX\n");
- fprintf(stderr, " --legal=XX: Filter instructions to only consider "
- "those instructions\n");
- fprintf(stderr, " that are legal instructions, as defined by "
- "decoder XX\n");
- fprintf(stderr, " --print=XX: Prints out set of enumerated "
- "instructions,\n");
- fprintf(stderr, " for the specified decoder XX (may be "
- "repeated).\n");
- fprintf(stderr, " Also registers decoder XX if needed.\n");
-
- fprintf(stderr, "\nAdditional options:\n");
- fprintf(stderr, " --bindings: Prints out current (command-line) "
- "bindings\n");
- fprintf(stderr, " --checkmnemonics: enables opcode mnemonic "
- "comparisons\n");
- fprintf(stderr, " --checkoperands: enables operand comparison (slow)\n");
- fprintf(stderr, " --ignore_mnemonic=file: ignore mnemonic name "
- "comparison\n");
- fprintf(stderr, " for instruction sequences in file (may be "
- "repeated)\n");
- fprintf(stderr, " --ignored=<file>: ignore instruction sequences "
- "in file (may be repeated)\n");
- fprintf(stderr, " --nacllegal: use validator checks/instruction type)\n");
- fprintf(stderr, " in addition to decoder errors with nacl\n");
- fprintf(stderr, " instruction filters.\n");
-#ifdef NACL_REVISION
- fprintf(stderr, " --nacl_revision: print nacl revision used to build\n"
- " the nacl decoder\n");
-#endif
- fprintf(stderr, " --opcode=XX: only process given opcode XX for "
- "each prefix\n");
- fprintf(stderr, " --opcode_bytes=XX: Prints out opcode bytes for set of\n"
- " enumerated instructions. To be used by decoder --in\n");
- fprintf(stderr,
- " --opcode_bytes_plus_desc=XX: Prints out opcode bytes for set\n"
- " of enumerated instruction, plus a print description (as a\n"
- " comment). To be used by decoder --n\n");
-#ifdef NACL_XED_DECODER
- fprintf(stderr, " --pin_version: Prints out pin version used for xed "
- "decoder\n");
-#endif
- fprintf(stderr, " --prefix=XX: only process given prefix XX\n");
- fprintf(stderr, " --nops: Don't operand compare nops.\n");
- fprintf(stderr, " --skipcontiguous: Only skip contiguous errors\n");
- fprintf(stderr, " --verbose: add verbose comments to output\n");
- fprintf(stderr, " --xedimplemented: only compare NaCl instruction that "
- "are also implemented in xed\n");
- exit(gSawLethalError);
-}
-
-/* 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);
-}
-
-/* Returns true if the given opcode sequence text is in the
- * given instruction list.
- */
-static Bool InInstructionList(InstList* list, uint8_t* itext, size_t nbytes) {
- size_t i;
- size_t j;
- if (NULL == list) return FALSE;
- for (i = 0; i < list->num_insts_; ++i) {
- Bool found_match = TRUE;
- size_t start = list->insts_[i];
- size_t end = list->insts_[i + 1];
- size_t inst_bytes = (end - start);
- if (inst_bytes < nbytes) continue;
- for (j = 0; j < inst_bytes; j++) {
- if (itext[j] != list->bytes_[start + j]) {
- found_match = FALSE;
- break;
- }
- }
- if (found_match) {
- return TRUE;
- }
- }
- return FALSE;
-}
-
-/* Takes the given text and sends it to each of the instruction
- * decoders to decode the first instruction in the given text.
- * Commonly the decoded instruction will be shorter than nbytes.
- */
-static void ParseFirstInstruction(ComparedInstruction *cinst,
- uint8_t *itext, size_t nbytes) {
- size_t i;
- memcpy(cinst->_enumerator._itext, itext, nbytes);
- cinst->_enumerator._num_bytes = nbytes;
- cinst->_decoder_error = FALSE;
- for (i = 0; i < cinst->_enumerator._num_decoders; ++i) {
- cinst->_enumerator._decoder[i]->
- _parse_inst_fn(&cinst->_enumerator, kTextAddress);
- }
-}
-
-/* Prints out the instruction each decoder disassembled */
-static void PrintDisassembledInstructionVariants(ComparedInstruction* cinst) {
- size_t i;
- for (i = 0; i < cinst->_enumerator._num_decoders; ++i) {
- cinst->_enumerator._decoder[i]->_print_inst_fn(&cinst->_enumerator);
- }
-}
-
-/* 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);
-}
-
-/* Initial value for last bad opcode. */
-#define NOT_AN_OPCODE "not an opcode"
-
-/* Holds the name of the last (bad) mnemonic name matched.
- * Uses the mnemonic name associated with instructions decoded
- * by the first decoder.
- */
-static char last_bad_mnemonic[kBufferSize] = NOT_AN_OPCODE;
-
-/* Returns how many decoder errors were skipped for an opcode. */
-static int nSkipped = 0;
-
-/* Changes the last bad mnemonic name to the new value. */
-static void ChangeLastBadMnemonic(const char* new_value) {
- cstrncpy(last_bad_mnemonic, new_value, kBufferSize);
-}
-
-/* Reset the counters for skipping decoder errors, assuming
- * the last_bad_opcode (if non-null) was the given value.
- */
-static void ResetSkipCounts(const char* last_opcode) {
- nSkipped = 0;
- ChangeLastBadMnemonic((last_opcode == NULL) ? "not an opcode" : last_opcode);
-}
-
-/* Report number of instructions with errors that were skipped, and
- * then reset the skip counts.
- */
-static void ReportOnSkippedErrors(ComparedInstruction* cinst,
- const char* mnemonic) {
- UNREFERENCED_PARAMETER(cinst);
- if (nSkipped > 0 && gSilent) {
- printf("...skipped %d errors for %s\n", nSkipped, last_bad_mnemonic);
- }
- ResetSkipCounts(mnemonic);
-}
-
-/* Report a disagreement between decoders. To reduce
- * noice from uninteresting related errors, gSkipRepeatReports will
- * avoid printing consecutive errors for the same opcode.
- */
-static void DecoderError(const char *why,
- ComparedInstruction *cinst,
- const char *details) {
- size_t i;
- cinst->_decoder_error = TRUE;
-
- /* Don't print errors when running silently. In such cases we
- * are generating valid opcode sequences for a decoder, and problems
- * should be ignored.
- */
- if (gSilent) return;
-
- /* Check if we have already reported for instruction mnemonic,
- * based on the mnemonic used by the first decoder.
- */
- if (gSkipRepeatReports) {
- /* Look for first possible name for instruction. */
- for (i = 0; i < cinst->_enumerator._num_decoders; ++i) {
- NaClEnumeratorDecoder *decoder = cinst->_enumerator._decoder[i];
- const char* mnemonic;
- if (NULL == decoder->_get_inst_mnemonic_fn) continue;
- mnemonic = cinst->_enumerator._decoder[0]->
- _get_inst_mnemonic_fn(&cinst->_enumerator);
- if (strcmp(mnemonic, last_bad_mnemonic) == 0) {
- nSkipped += 1;
- return;
- }
- }
- }
-
- /* If reached, did not skip, so report the error. */
- printf("**** ERROR: %s: %s\n", why, (details == NULL ? "" : details));
- PrintDisassembledInstructionVariants(cinst);
-}
-
-#if NACL_TARGET_SUBARCH == 64
-/* The instructions:
- * 48 89 e5 mov rbp, rsp
- * 4a 89 e5 mov rbp, rsp
- * look bad based on the simple rule, but are safe because they are
- * moving a safe address between two protected registers.
- */
-static int IsSpecialSafeRegWrite(ComparedInstruction *cinst) {
- uint8_t byte0 = cinst->_enumerator._itext[0];
- uint8_t byte1 = cinst->_enumerator._itext[1];
- uint8_t byte2 = cinst->_enumerator._itext[2];
-
- return ((byte0 == 0x48 && byte1 == 0x89 && byte2 == 0xe5) ||
- (byte0 == 0x48 && byte1 == 0x89 && byte2 == 0xec) ||
- (byte0 == 0x48 && byte1 == 0x8b && byte2 == 0xe5) ||
- (byte0 == 0x48 && byte1 == 0x8b && byte2 == 0xec) ||
- (byte0 == 0x4a && byte1 == 0x89 && byte2 == 0xe5) ||
- (byte0 == 0x4a && byte1 == 0x89 && byte2 == 0xec) ||
- (byte0 == 0x4a && byte1 == 0x8b && byte2 == 0xe5) ||
- (byte0 == 0x4a && byte1 == 0x8b && byte2 == 0xec));
-}
-
-/* If we get this far, and Xed says it writes a NaCl reserved
- * register, this is a lethal error.
- */
-static Bool BadRegWrite(ComparedInstruction *cinst) {
- size_t i;
- NaClEnumeratorDecoder* xed_decoder = NULL;
- size_t noperands;
- size_t ilength;
-
- /* First see if there is a xed decoder to compare against. */
- for (i = 0; i < cinst->_enumerator._num_decoders; ++i) {
- if (0 == strcmp("xed", cinst->_enumerator._decoder[i]->_id_name)) {
- xed_decoder = cinst->_enumerator._decoder[i];
- break;
- }
- }
-
- /* Quit if we don't have the right support for this function. */
- if ((NULL == xed_decoder) ||
- !xed_decoder->_is_inst_legal_fn(&cinst->_enumerator) ||
- (NULL == xed_decoder->_get_inst_num_operands_fn) ||
- (NULL == xed_decoder->_writes_to_reserved_reg_fn)) return 0;
-
- /* If reached, we found the xed decoder. */
- noperands = xed_decoder->_get_inst_num_operands_fn(&cinst->_enumerator);
- ilength = xed_decoder->_inst_length_fn(&cinst->_enumerator);
- for (i = 0; i < cinst->_enumerator._num_decoders; ++i) {
- size_t j;
- NaClEnumeratorDecoder* other_decoder = cinst->_enumerator._decoder[i];
-
- /* don't compare against self. */
- if (xed_decoder == other_decoder) break;
-
- /* don't compare if the other decoder doesn't know how to validate. */
- if (NULL == other_decoder->_segment_validates_fn) break;
- if (!other_decoder->_is_inst_legal_fn(&cinst->_enumerator)) break;
-
- for (j = 0; j < noperands ; j++) {
- if (xed_decoder->_writes_to_reserved_reg_fn(&cinst->_enumerator, j)) {
- if (other_decoder->_segment_validates_fn(&cinst->_enumerator,
- cinst->_enumerator._itext,
- ilength,
- kTextAddress)) {
- char sbuf[kBufferSize];
- /* Report problem if other decoder accepted instruction, but is
- * not one of the special safe writes.
- */
- if (!IsSpecialSafeRegWrite(cinst)) continue;
- gSawLethalError = 1;
- SNPRINTF(sbuf, kBufferSize, "(%s) xed operand %d\n",
- other_decoder->_id_name, (int) j);
- DecoderError("ILLEGAL REGISTER WRITE", cinst, sbuf);
- return TRUE;
- }
- }
- }
- }
- return FALSE;
-}
-#endif
-
-/* Compare operands of each decoder's disassembled instruction, reporting
- * an error if decoders disagree.
- */
-static Bool AreInstOperandsEqual(ComparedInstruction *cinst) {
- size_t i;
- size_t num_decoders = 0;
- const char* operands[NACL_MAX_ENUM_DECODERS];
- NaClEnumeratorDecoder* operands_decoder[NACL_MAX_ENUM_DECODERS];
- NaClEnumerator* enumerator = &cinst->_enumerator;
-
- /* If no decoders, vacuously true. */
- if (0 == enumerator->_num_decoders) return FALSE;
-
- /* Collect operand lists and corresponding decoders. */
- for (i = 0; i < enumerator->_num_decoders; ++i) {
- /* Start by verifying that we can find operands. */
- NaClEnumeratorDecoder *decoder = enumerator->_decoder[i];
- if (NULL == decoder->_get_inst_operands_text_fn) continue;
- if (!decoder->_is_inst_legal_fn(enumerator)) continue;
-
- /* HACK ALERT! Special case "nops" by removing operands. We do this
- * assuming it doesn't matter what the argumnents are, the effect is
- * the same.
- */
- if (gNoCompareNops &&
- (NULL != decoder->_get_inst_mnemonic_fn) &&
- (0 == strcmp("nop", decoder->_get_inst_mnemonic_fn(enumerator)))) {
- operands[num_decoders] = "";
- operands_decoder[num_decoders++] = decoder;
- continue;
- }
-
- /* Not special case, record operand and decoder. */
- operands[num_decoders] = decoder->_get_inst_operands_text_fn(enumerator);
- if (NULL == operands[num_decoders]) operands[num_decoders] = "";
- operands_decoder[num_decoders++] = decoder;
- }
-
- /* Now test if operands compare between decoders. */
- for (i = 1; i < num_decoders; ++i) {
- if (0 != strncmp(operands[i-1], operands[i], kBufferSize)) {
- char sbuf[kBufferSize];
- SNPRINTF(sbuf, kBufferSize, "(%s) '%s' != (%s)'%s'",
- operands_decoder[i-1]->_id_name, operands[i-1],
- operands_decoder[i]->_id_name, operands[i]);
- DecoderError("OPERAND MISMATCH", cinst, sbuf);
- return FALSE;
- }
- }
-
- if (kDebug && (num_decoders > 0)) {
- printf("operands match: %s\n", operands[0]);
- }
- return TRUE;
-}
-
-/* If non-null, the list of instructions for which mnemonics should
- * not be compared.
- */
-static InstList* kIgnoreMnemonics = NULL;
-
-/* Compares mnemonic names between decoder's disassembled instructions,
- * returning true if they agree on the mnemonic name.
- */
-static Bool AreInstMnemonicsEqual(ComparedInstruction *cinst) {
- size_t i;
- size_t num_decoders = 0;
- const char* name[NACL_MAX_ENUM_DECODERS];
- NaClEnumeratorDecoder* name_decoder[NACL_MAX_ENUM_DECODERS];
-
- /* If no decoders, vacuously true. */
- if (0 == cinst->_enumerator._num_decoders) return 0;
-
- /* Collect mnemonics of corresponding decoders (if defined). */
- for (i = 0; i < cinst->_enumerator._num_decoders; ++i) {
- /* Start by verifying that we can get name name. */
- NaClEnumeratorDecoder *decoder = cinst->_enumerator._decoder[i];
- if (NULL == decoder->_get_inst_mnemonic_fn) continue;
- if (!decoder->_is_inst_legal_fn(&cinst->_enumerator)) continue;
-
- /* If on ignore list, ignore. */
- if (InInstructionList(kIgnoreMnemonics,
- cinst->_enumerator._itext,
- decoder->_inst_length_fn(&cinst->_enumerator)))
- continue;
-
- /* Record mnemonic name and decoder for comparisons below. */
- name[num_decoders] = decoder->_get_inst_mnemonic_fn(&cinst->_enumerator);
- name_decoder[num_decoders++] = decoder;
- }
-
- /* Now compare mnemonics that were defined. */
- for (i = 1; i < num_decoders; ++i) {
- if (strncmp(name[i-1], name[i], kBufferSize) != 0) {
- char sbuf[kBufferSize];
- SNPRINTF(sbuf, kBufferSize, "(%s) %s != (%s) %s",
- name_decoder[i-1]->_id_name, name[i-1],
- name_decoder[i]->_id_name, name[i]);
- DecoderError("MNEMONIC MISMATCH", cinst, sbuf);
- return FALSE;
- }
- }
-
- if (kDebug && (num_decoders > 0)) {
- printf("names match: %s\n", name[0]);
- }
- return TRUE;
-}
-
-/* Returns true if the decoder decodes the instruction correctly,
- * and also (to the best it can determine) validates when
- * specified to do so on the command line.
- */
-static Bool ConsiderInstLegal(NaClEnumerator* enumerator,
- NaClEnumeratorDecoder* decoder) {
- if (!decoder->_is_inst_legal_fn(enumerator)) return FALSE;
- if (!gNaClLegal) return TRUE;
- if (NULL == decoder->_maybe_inst_validates_fn) return TRUE;
- return decoder->_maybe_inst_validates_fn(enumerator);
-}
-
-/* Returns true only if the legal filters allow the instruction to
- * be processed.
- */
-static Bool RemovedByInstLegalFilters(ComparedInstruction* cinst) {
- size_t i;
- for (i = 0; i < cinst->_enumerator._num_decoders; ++i) {
- if (ConsiderInstLegal(&cinst->_enumerator,
- cinst->_enumerator._decoder[i])
- != cinst->_enumerator._decoder[i]->_legal_only) {
- return TRUE;
- }
- }
- return FALSE;
-}
-
-/* Returns true if the instruction has the same length for all decoders.
- * Reports length differences if found.
- */
-static Bool AreInstructionLengthsEqual(ComparedInstruction *cinst) {
- size_t i;
- size_t num_decoders = 0;
- size_t length[NACL_MAX_ENUM_DECODERS];
- NaClEnumeratorDecoder* length_decoder[NACL_MAX_ENUM_DECODERS];
-
- /* If no decoders, vacuously true. */
- if (0 == cinst->_enumerator._num_decoders) return TRUE;
-
- /* Collect the instruction length for each decoder. */
- for (i = 0; i < cinst->_enumerator._num_decoders; ++i) {
- if (cinst->_enumerator._decoder[i]->
- _is_inst_legal_fn(&cinst->_enumerator)) {
- length[num_decoders] = cinst->_enumerator._decoder[i]->
- _inst_length_fn(&cinst->_enumerator);
- length_decoder[num_decoders] = cinst->_enumerator._decoder[i];
- ++num_decoders;
- }
- }
-
- /* Print out where lengths differ, if they differ. */
- for (i = 1; i < num_decoders; ++i) {
- if (length[i-1] != length[i]) {
- char sbuf[kBufferSize];
- SNPRINTF(sbuf, kBufferSize, "(%s) %"NACL_PRIuS" != (%s) %"NACL_PRIuS,
- length_decoder[i-1]->_id_name, length[i-1],
- length_decoder[i]->_id_name, length[i]);
- DecoderError("LENGTH MISMATCH", cinst, sbuf);
- gSawLethalError = 1;
- return FALSE;
- }
- }
-
- if (kDebug && (num_decoders > 0)) {
- printf("length match: %"NACL_PRIuS"\n", length[0]);
- }
- return TRUE;
-}
-
-/* Print out decodings if specified on the command line. Returns true
- * instruction(s) are printed. This function is used
- */
-static Bool PrintInst(ComparedInstruction *cinst) {
- Bool result = FALSE;
- size_t i;
- for (i = 0; i < cinst->_enumerator._num_decoders; ++i) {
- NaClEnumeratorDecoder* decoder = cinst->_enumerator._decoder[i];
- if (decoder->_print) {
- cinst->_enumerator._decoder[i]->_print_inst_fn(&cinst->_enumerator);
- result = TRUE;
- }
- if (decoder->_print_opcode_sequence ||
- decoder->_print_opcode_sequence_plus_desc) {
- size_t length = decoder->_inst_length_fn(&cinst->_enumerator);
- for (i = 0; i < length; ++i) {
- printf("%02x", cinst->_enumerator._itext[i]);
- }
- if (decoder->_print_opcode_sequence_plus_desc &&
- decoder->_is_inst_legal_fn(&cinst->_enumerator) &&
- (NULL != decoder->_get_inst_mnemonic_fn) &&
- (NULL != decoder->_get_inst_operands_text_fn)) {
- printf("#%s %s", decoder->_get_inst_mnemonic_fn(&cinst->_enumerator),
- decoder->_get_inst_operands_text_fn(&cinst->_enumerator));
- }
- printf("\n");
- result = TRUE;
- }
- }
- return result;
-}
-
-/* If non-null, the list of instruction bytes to ignore. */
-static InstList* kIgnoredInstructions = NULL;
-
-/* Test comparison for a single instruction.
- */
-static void TryOneInstruction(ComparedInstruction *cinst,
- uint8_t *itext, size_t nbytes) {
- do {
- if (gVerbose) {
- size_t i;
- printf("================");
- for (i = 0; i < nbytes; ++i) {
- printf("%02x", itext[i]);
- }
- printf("\n");
- }
-
- /* Try to parse the sequence of test bytes. */
- ParseFirstInstruction(cinst, itext, nbytes);
-
- /* Don't bother to compare ignored instructions. */
- if (InInstructionList(kIgnoredInstructions, itext, nbytes)) break;
-
- /* Apply filters */
- if (RemovedByInstLegalFilters(cinst)) break;
-
- /* Apply comparison checks to the decoded instructions. */
- if (!AreInstructionLengthsEqual(cinst)) break;
- if (gCheckMnemonics && !AreInstMnemonicsEqual(cinst)) break;
- if (gCheckOperands && !AreInstOperandsEqual(cinst)) break;
-#if NACL_TARGET_SUBARCH == 64
- if (BadRegWrite(cinst)) break;
-#endif
-
- /* Print the instruction if print specified. */
- if (PrintInst(cinst)) break;
- /* no error */
- if (gVerbose) {
- PrintDisassembledInstructionVariants(cinst);
- }
- } while (0);
-
- /* saw error; should have already printed stuff. Only
- * report on skipped errors if we found an error-free
- * instruction.
- */
- if (gSkipContiguous && (!cinst->_decoder_error)) {
- ReportOnSkippedErrors(cinst, NULL);
- }
-}
-
-/* Returns true if for all decoders recognize legal instructions, they use
- * less than len bytes.
- */
-static Bool IsLegalInstShorterThan(ComparedInstruction *cinst, size_t len) {
- size_t i;
- Bool found_legal = FALSE;
- for (i = 0; i < cinst->_enumerator._num_decoders; ++i) {
- if (cinst->_enumerator._decoder[i]->
- _is_inst_legal_fn(&cinst->_enumerator)) {
- found_legal = TRUE;
- if (cinst->_enumerator._decoder[i]->_inst_length_fn(&cinst->_enumerator)
- >= len) return FALSE;
- }
- }
- return found_legal;
-}
-
-/* Enumerate and test all 24-bit opcode+modrm+sib patterns for a
- * particular prefix.
- */
-static void TestAllWithPrefix(ComparedInstruction *cinst,
- unsigned int prefix, size_t prefix_length) {
- const int kInstByteCount = NACL_ENUM_MAX_INSTRUCTION_BYTES;
- const int 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(%x)\n", prefix);
- /* set up prefix */
- memcpy(itext, &prefix, prefix_length);
- /* set up filler bytes */
- for (i = prefix_length + kIterByteCount;
- i < NACL_ENUM_MAX_INSTRUCTION_BYTES; 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;
- ResetSkipCounts(NULL);
- 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(cinst, itext, kInstByteCount);
- /* If all decoders decode without using the sib byte, don't
- * bother to try more variants.
- */
- if (IsLegalInstShorterThan(cinst, prefix_length + 3)) break;
- }
- /* If all decoders decode without using the modrm byte, don't
- * bother to try more variants.
- */
- if (IsLegalInstShorterThan(cinst, prefix_length + 2)) break;
- }
- /* Force flushing of skipped errors, since we are now moving on
- * to the next opcode.
- */
- ReportOnSkippedErrors(cinst, NULL);
- }
-}
-
-/* For x86-64, enhance the iteration by looping through REX prefixes.
- */
-static void TestAllWithPrefixREX(ComparedInstruction *cinst,
- unsigned int prefix, size_t prefix_length) {
-#if NACL_TARGET_SUBARCH == 64
- unsigned char REXp;
- unsigned int rprefix;
- /* test with REX prefixes */
- for (REXp = 0x40; REXp < 0x50; REXp++) {
- rprefix = (prefix << 8 | REXp);
- printf("Testing with prefix %x\n", rprefix);
- TestAllWithPrefix(cinst, rprefix, prefix_length + 1);
- }
-#endif
- /* test with no REX prefix */
- TestAllWithPrefix(cinst, prefix, prefix_length);
-}
-
-/* For all prefixes, call TestAllWithPrefix() to enumrate and test
- * all instructions.
- */
-static void TestAllInstructions(ComparedInstruction *cinst) {
- gSkipRepeatReports = TRUE;
- /* 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.
- */
- /* TODO(bradchen): extend enuminsts-64 to iterate over 64-bit prefixes. */
- TestAllWithPrefixREX(cinst, 0, 0);
- TestAllWithPrefixREX(cinst, 0x0f, 1);
- TestAllWithPrefixREX(cinst, 0x0ff2, 2);
- TestAllWithPrefixREX(cinst, 0x0ff3, 2);
- TestAllWithPrefixREX(cinst, 0x0f66, 2);
- TestAllWithPrefixREX(cinst, 0x0f0f, 2);
- TestAllWithPrefixREX(cinst, 0x380f, 2);
- TestAllWithPrefixREX(cinst, 0x3a0f, 2);
- TestAllWithPrefixREX(cinst, 0x380f66, 3);
- TestAllWithPrefixREX(cinst, 0x380ff2, 3);
- TestAllWithPrefixREX(cinst, 0x3a0f66, 3);
-}
-
-/* Enumerate and test each instruction on stdin. */
-static void TestInputInstructions(ComparedInstruction *cinst) {
- int i;
- InstByteArray itext;
- int num_bytes = 0;
- while (TRUE) {
- num_bytes = ReadAnInstruction(itext);
- if (num_bytes == 0) return;
- for (i = num_bytes; i < NACL_ENUM_MAX_INSTRUCTION_BYTES; ++i) {
- itext[i] = (uint8_t) i;
- }
- TryOneInstruction(cinst, itext, NACL_ENUM_MAX_INSTRUCTION_BYTES);
- }
-}
-
-/* Used to test one instruction at a time, for example, in regression
- * testing, or for instruction arguments from the command line.
- */
-static void TestOneInstruction(ComparedInstruction *cinst, 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(cinst, 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(ComparedInstruction *cinst) {
- TestOneInstruction(cinst, "0024c2");
- TestOneInstruction(cinst, "017967");
- TestOneInstruction(cinst, "0f12c0");
- TestOneInstruction(cinst, "0f13c0");
- TestOneInstruction(cinst, "0f17c0");
- TestOneInstruction(cinst, "0f01c1");
- TestOneInstruction(cinst, "0f00300000112233445566778899aa");
- TestOneInstruction(cinst, "cc");
- TestOneInstruction(cinst, "C3");
- TestOneInstruction(cinst, "0f00290000112233445566778899aa");
- TestOneInstruction(cinst, "80e4f7");
- TestOneInstruction(cinst, "e9a0ffffff");
- TestOneInstruction(cinst, "4883ec08");
- TestOneInstruction(cinst, "0f00040500112233445566778899aa");
- /* Below are newly discovered mistakes in call instructions, where the wrong
- * byte length was required by x86-64 nacl validator.
- */
- TestOneInstruction(cinst, "262e7e00");
- TestOneInstruction(cinst, "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(cinst, "406601d8"); /* illegal; REX before data16 */
- TestOneInstruction(cinst, "664001d8"); /* legal; REX after data16 */
- TestOneInstruction(cinst, "414001d8"); /* illegal; two REX bytes */
-}
-
-/* Returns the decoder with the given name, if it is registered. Otherwise,
- * returns NULL.
- */
-static NaClEnumeratorDecoder*
-NaClGetRegisteredDecoder(ComparedInstruction* cinst,
- const char* decoder_name) {
- size_t i;
- for (i = 0; i < cinst->_enumerator._num_decoders; ++i) {
- if (0 == strcmp(cinst->_enumerator._decoder[i]->_id_name, decoder_name)) {
- return cinst->_enumerator._decoder[i];
- }
- }
- return NULL;
-}
-
-/* Register the decoder with the given name, returning the corresponding
- * decoder.
- */
-static NaClEnumeratorDecoder*
-NaClRegisterEnumeratorDecoder(ComparedInstruction* cinst,
- const char* decoder_name) {
- size_t i;
- /* First check if already registered. If so, simply return it. */
- NaClEnumeratorDecoder* decoder =
- NaClGetRegisteredDecoder(cinst, decoder_name);
- if (NULL != decoder) return decoder;
-
- /* If reached, not registered yet. See if one with the given name
- * is available (i.e. preregistered).
- */
- for (i = 0; i < kNumAvailableDecoders; ++i) {
- decoder = kAvailableDecoders[i];
- if (0 == strcmp(decoder->_id_name, decoder_name)) {
- if (cinst->_enumerator._num_decoders < NACL_MAX_ENUM_DECODERS) {
- cinst->_enumerator._decoder[cinst->_enumerator._num_decoders++] =
- decoder;
- return decoder;
- }
- }
- }
-
- /* If reached, can't find a decoder with the given name, abort. */
- fprintf(stderr, "Can't find decoder '%s', aborting!\n", decoder_name);
- exit(1);
-}
-
-/* Install legal filter values for corresponding available decoders. */
-static void NaClInstallLegalFilter(ComparedInstruction* cinst,
- const char* decoder_name,
- Bool new_value) {
- NaClRegisterEnumeratorDecoder(cinst, decoder_name)->_legal_only = new_value;
-}
-
-/* The initial size for bytes_ when creating an instruction list.
- */
-static const size_t kInitialInstBytesSize = 1024;
-
-/* The initial size for insts_ when creating an instruction list.
- */
-static const size_t kInitialInstListInstsSize = 256;
-
-/* Creates an initially empty list of instructions. */
-static InstList* CreateEmptyInstList(void) {
- InstList* list = (InstList*) malloc(sizeof(InstList));
- if (NULL == list) ReportFatalError("Out of memory");
- list->bytes_ = (uint8_t*) malloc(kInitialInstBytesSize);
- list->bytes_size_ = kInitialInstBytesSize;
- list->insts_ = (size_t*) malloc(kInitialInstListInstsSize);
- list->insts_size_ = kInitialInstListInstsSize;
- list->insts_[0] = 0;
- list->num_insts_ = 0;
- list->num_bytes_ = 0;
- return list;
-}
-/* Expands the bytes_ field of the instruction list so that
- * more instructions can be added.
- */
-static void ExpandInstListBytes(InstList* list) {
- size_t i;
- uint8_t* new_buffer;
- size_t new_size = list->bytes_size_ *2;
- if (new_size < list->bytes_size_) {
- ReportFatalError("Instruction list file too big");
- }
- new_buffer = (uint8_t*) malloc(new_size);
- if (NULL == new_buffer) ReportFatalError("Out of memory");
- for (i = 0; i < list->num_bytes_; ++i) {
- new_buffer[i] = list->bytes_[i];
- }
- free(list->bytes_);
- list->bytes_ = new_buffer;
- list->bytes_size_ = new_size;
-}
-
-/* Expands the insts_ field of the instruction list so that
- * more instructions can be added.
- */
-static void ExpandInstListInsts(InstList* list) {
- size_t i;
- size_t* new_buffer;
- size_t new_size = list->insts_size_ * 2;
-
- if (new_size < list->insts_size_)
- ReportFatalError("Instruction list file too big");
- new_buffer = (size_t*) malloc(new_size);
- if (NULL == new_buffer) ReportFatalError("Out of memory");
- for (i = 0; i < list->num_insts_; ++i) {
- new_buffer[i] = list->insts_[i];
- }
- free(list->insts_);
- list->insts_ = new_buffer;
- list->insts_size_ = new_size;
-}
-
-/* Reads the bytes defined in line, and coverts it to the corresponding
- * ignored instruction. Then adds it to the list of ignored instructions.
- */
-static void ReadInstListInst(InstList* list,
- char line[kBufferSize],
- const char* context,
- int line_number) {
- int i;
- InstByteArray ibytes;
- int num_bytes = Text2Bytes(ibytes, line, context, line_number);
-
- /* Ignore line if no opcode sequence. */
- if (num_bytes == 0) return;
-
- /* First update the instruction pointers. */
- if (list->num_insts_ == list->insts_size_) {
- ExpandInstListInsts(list);
- }
- ++list->num_insts_;
- list->insts_[list->num_insts_] =
- list->insts_[list->num_insts_ - 1];
-
- /* Now install the bytes. */
- for (i = 0; i < num_bytes; ++i) {
- /* Be sure we have room for the byte. */
- if (list->num_bytes_ == list->bytes_size_) {
- ExpandInstListBytes(list);
- }
-
- /* Record into the ignore instruction list. */
- list->bytes_[list->num_bytes_++] = ibytes[i];
- list->insts_[list->num_insts_] = list->num_bytes_;
- }
-}
-
-/* Reads a file containing a list of instruction bytes to ignore,
- * and adds it to the end of the list of instructions.
- */
-static void GetInstList(InstList** list,
- FILE* file,
- const char* filename) {
- char line[kBufferSize];
- int line_number = 0;
- if (NULL == *list) {
- *list = CreateEmptyInstList();
- }
- while (TRUE) {
- ++line_number;
- if (fgets(line, kBufferSize, file) == NULL) return;
- ReadInstListInst(*list, line, filename, line_number);
- }
- return;
-}
-
-/* Read the file containing a list of instruction bytes,
- * and adds it to the end of the list of instructions.
- */
-static void ReadInstList(InstList** list, const char* filename) {
- FILE* file = fopen(filename, "r");
- if (NULL == file) {
- char buffer[kBufferSize];
- SNPRINTF(buffer, kBufferSize, "%s: unable to open", filename);
- ReportFatalError(buffer);
- }
- GetInstList(list, file, filename);
- fclose(file);
-}
-
-/* Very simple command line arg parsing. Returns index to the first
- * arg that doesn't begin with '--', or argc if there are none.
- */
-static int ParseArgs(ComparedInstruction* cinst, int argc, char *argv[]) {
- int i;
- uint32_t prefix;
- uint32_t opcode;
- char* cstr_value;
- Bool bool_value;
- int opcode_bytes_count = 0;
-
- for (i = 1; i < argc; i++) {
- if (argv[i][0] == '-') {
- do {
- if (strcmp(argv[i], "--help") == 0) {
- Usage();
- } else if (GrokBoolFlag("--checkoperands", argv[i], &gCheckOperands) ||
- GrokBoolFlag("--nacllegal", argv[i],
- &gNaClLegal) ||
- GrokBoolFlag("--xedimplemented", argv[i],
- &gXedImplemented) ||
- GrokBoolFlag("--nops", argv[i], &gNoCompareNops)||
- GrokBoolFlag("--skipcontiguous", argv[i],
- &gSkipContiguous) ||
- GrokBoolFlag("--verbose", argv[i], &gVerbose)) {
- } else if (GrokBoolFlag("--bindings", argv[i], &bool_value) &&
- bool_value) {
- PrintBindings(cinst);
-#ifdef NACL_XED_DECODER
- } else if (GrokBoolFlag("--pin_version", argv[i], &bool_value) &&
- bool_value) {
- fprintf(stderr, "pin version: %s\n", NACL_PINV);
-#endif
-#ifdef NACL_REVISION
- } else if (GrokBoolFlag("--nacl_revision", argv[i], &bool_value) &&
- bool_value) {
- fprintf(stderr, "nacl revsion: %d\n", NACL_REVISION);
-#endif
- } else if (GrokCstringFlag("--opcode_bytes", argv[i], &cstr_value)) {
- NaClEnumeratorDecoder* decoder =
- NaClRegisterEnumeratorDecoder(cinst, cstr_value);
- decoder->_print_opcode_sequence = TRUE;
- decoder->_print_opcode_sequence_plus_desc = FALSE;
- gSilent = TRUE;
- ++opcode_bytes_count;
- } else if (GrokCstringFlag("--opcode_bytes_plus_desc",
- argv[i], &cstr_value)) {
- NaClEnumeratorDecoder* decoder =
- NaClRegisterEnumeratorDecoder(cinst, cstr_value);
- decoder->_print_opcode_sequence = FALSE;
- decoder->_print_opcode_sequence_plus_desc = TRUE;
- if ((NULL == decoder->_get_inst_mnemonic_fn) ||
- (NULL == decoder->_get_inst_operands_text_fn)) {
- fprintf(stderr, "%s doesn't define how to print out description\n",
- argv[i]);
- }
- gSilent = TRUE;
- ++opcode_bytes_count;
- /* Print out a special message to be picked up by the input decoder,
- * so that it will look for instruction mnemonic and operands.
- */
- printf("#OPCODEPLUSDESC#\n");
- } else if (GrokCstringFlag("--ignored", argv[i], &cstr_value)) {
- ReadInstList(&kIgnoredInstructions, cstr_value);
- } else if (GrokCstringFlag("--ignore_mnemonic", argv[i], &cstr_value)) {
- ReadInstList(&kIgnoreMnemonics, cstr_value);
- } else if (GrokCstringFlag("--print", argv[i], &cstr_value)) {
- NaClRegisterEnumeratorDecoder(cinst, cstr_value)->_print = TRUE;
- gSilent = TRUE;
- } else if (GrokUint32HexFlag("--prefix", argv[i], &prefix)) {
- gPrefix = (int) prefix;
- printf("using prefix %x\n", gPrefix);
- } else if (GrokUint32HexFlag("--opcode", argv[i], &opcode) &&
- opcode < 256) {
- gOpcode = (int) opcode;
- printf("using opcode %x\n", gOpcode);
- } else if (GrokCstringFlag("--legal", argv[i], &cstr_value)) {
- NaClInstallLegalFilter(cinst, cstr_value, TRUE);
- } else if (GrokCstringFlag("--illegal", argv[i], &cstr_value)) {
- NaClInstallLegalFilter(cinst, cstr_value, FALSE);
- } else if (argv[i] == strfind(argv[i], "--")) {
- NaClRegisterEnumeratorDecoder(cinst, argv[i] + 2);
- } else {
- fprintf(stderr, "Can't recognize option %s\n", argv[i]);
- exit(1);
- }
- if (opcode_bytes_count > 1) {
- fprintf(stderr, "Can't have more than one opcode_bytes command "
- "line argument\n");
- exit(1);
- }
- } while (0);
- } else return i;
- }
- return argc;
-}
-
-/* Define set of available enumerator decoders. */
-static void NaClPreregisterEnumeratorDecoder(ComparedInstruction* cinst,
- NaClEnumeratorDecoder* decoder) {
- UNREFERENCED_PARAMETER(cinst);
- if (kNumAvailableDecoders >= NACL_MAX_AVAILABLE_DECODERS) {
- fprintf(stderr, "Too many preregistered enumerator decoders\n");
- exit(1);
- }
- decoder->_legal_only = TRUE;
- decoder->_print = FALSE;
- decoder->_print_opcode_sequence = FALSE;
- decoder->_print_opcode_sequence_plus_desc = FALSE;
- kAvailableDecoders[kNumAvailableDecoders++] = decoder;
-}
-
-/* Define decoders that can be registered. */
-extern NaClEnumeratorDecoder* RegisterXedDecoder(void);
-extern NaClEnumeratorDecoder* RegisterNaClDecoder(void);
-extern NaClEnumeratorDecoder* RegisterRagelDecoder(void);
-
-/* Initialize the set of available decoders. */
-static void NaClInitializeAvailableDecoders(void) {
- kNumAvailableDecoders = 0;
-#ifdef NACL_XED_DECODER
- NaClPreregisterEnumeratorDecoder(&gCinst, RegisterXedDecoder());
-#endif
-#ifdef NACL_RAGEL_DECODER
- NaClPreregisterEnumeratorDecoder(&gCinst, RegisterRagelDecoder());
-#endif
- NaClPreregisterEnumeratorDecoder(&gCinst, RegisterNaClDecoder());
- NaClPreregisterEnumeratorDecoder(&gCinst, RegisterInputDecoder());
-}
-
-/* Initialize the ComparedInstruction data structure. */
-static void NaClInitializeComparedInstruction(ComparedInstruction* cinst) {
- cinst->_enumerator._num_decoders = 0;
-}
-
-/* Install parsed globals, as appropriate into the corresponding
- * decoders.
- */
-static void InstallFlags(NaClEnumerator* enumerator) {
- size_t i;
- for (i = 0; i < enumerator->_num_decoders; ++i) {
- enumerator->_decoder[i]->_install_flag_fn(enumerator,
- "--nops",
- &gNoCompareNops);
- enumerator->_decoder[i]->_install_flag_fn(enumerator,
- "--xedimplemented",
- &gXedImplemented);
- }
-}
-
-int main(int argc, char *argv[]) {
- int testargs;
-
- NaClLogModuleInit();
- NaClLogSetVerbosity(LOG_FATAL);
- NaClInitializeAvailableDecoders();
- NaClInitializeComparedInstruction(&gCinst);
-
- gArgv0 = argv[0];
- if (argc == 1) Usage();
-
- testargs = ParseArgs(&gCinst, argc, argv);
- InstallFlags(&gCinst._enumerator);
-
-
- if (gCinst._enumerator._num_decoders == 0) {
- fprintf(stderr, "No decoder specified, can't continue\n");
- exit(1);
- }
-
- if (testargs == argc) {
- if (NULL == NaClGetRegisteredDecoder(&gCinst, "in")) {
- if (gPrefix == 0) RunRegressionTests(&gCinst);
- TestAllInstructions(&gCinst);
- } else {
- TestInputInstructions(&gCinst);
- }
- } else {
- int i;
- gVerbose = TRUE;
- for (i = testargs; i < argc; ++i) {
- TestOneInstruction(&gCinst, argv[i]);
- }
- }
- exit(gSawLethalError);
-}

Powered by Google App Engine
This is Rietveld 408576698