| Index: src/trusted/validator/x86/ncval_reg_sfi/ncvalidate_iter.c
 | 
| diff --git a/src/trusted/validator/x86/ncval_reg_sfi/ncvalidate_iter.c b/src/trusted/validator/x86/ncval_reg_sfi/ncvalidate_iter.c
 | 
| deleted file mode 100644
 | 
| index 4d16b1dfe0ed58e1dc0f7a7c14b1581a35a5f558..0000000000000000000000000000000000000000
 | 
| --- a/src/trusted/validator/x86/ncval_reg_sfi/ncvalidate_iter.c
 | 
| +++ /dev/null
 | 
| @@ -1,948 +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.
 | 
| - */
 | 
| -
 | 
| -/*
 | 
| - * ncvalidate_iter.c
 | 
| - * Validate x86 instructions for Native Client
 | 
| - *
 | 
| - */
 | 
| -
 | 
| -#include "native_client/src/trusted/validator/x86/ncval_reg_sfi/ncvalidate_iter.h"
 | 
| -
 | 
| -#include <assert.h>
 | 
| -#include <string.h>
 | 
| -
 | 
| -#include "native_client/src/include/portability_io.h"
 | 
| -#include "native_client/src/shared/platform/nacl_check.h"
 | 
| -#include "native_client/src/shared/platform/nacl_log.h"
 | 
| -#include "native_client/src/trusted/validator/x86/decoder/ncop_exps.h"
 | 
| -#include "native_client/src/trusted/validator/x86/decoder/nc_inst_state_internal.h"
 | 
| -#include "native_client/src/trusted/validator/x86/halt_trim.h"
 | 
| -#include "native_client/src/trusted/validator/x86/nc_segment.h"
 | 
| -#include "native_client/src/trusted/validator/x86/ncval_reg_sfi/ncvalidate_iter_internal.h"
 | 
| -#include "native_client/src/trusted/validator/x86/ncval_reg_sfi/ncval_decode_tables.h"
 | 
| -#include "native_client/src/trusted/validator/x86/ncval_reg_sfi/nc_illegal.h"
 | 
| -#include "native_client/src/trusted/validator/x86/ncval_reg_sfi/nc_jumps.h"
 | 
| -#include "native_client/src/trusted/validator/x86/ncval_reg_sfi/nc_jumps_detailed.h"
 | 
| -#include "native_client/src/trusted/validator/x86/ncval_reg_sfi/nc_memory_protect.h"
 | 
| -#ifdef NCVAL_TESTING
 | 
| -#include "native_client/src/trusted/validator/x86/ncval_reg_sfi/nc_postconds.h"
 | 
| -#endif
 | 
| -#include "native_client/src/trusted/validator_x86/ncdis_decode_tables.h"
 | 
| -
 | 
| -/* To turn on debugging of instruction decoding, change value of
 | 
| - * DEBUGGING to 1.
 | 
| - */
 | 
| -#define DEBUGGING 0
 | 
| -
 | 
| -#include "native_client/src/shared/utils/debugging.h"
 | 
| -
 | 
| -#include "native_client/src/trusted/validator/x86/decoder/nc_inst_iter_inl.c"
 | 
| -
 | 
| -/* When >= 0, only print that many errors before quiting. When
 | 
| - * < 0, print all errors.
 | 
| - */
 | 
| -int NACL_FLAGS_max_reported_errors =
 | 
| -#ifdef NCVAL_TESTING
 | 
| -    /* Turn off error reporting when generating pre/post conditions.
 | 
| -     * Note: conditional code for NCVAL_TESTING will reset the
 | 
| -     * quit flag after each instruction. Hence, by using 0, we
 | 
| -     * effectively turn off printing of errors as the default. However,
 | 
| -     * one can override this on the command line to force errors to
 | 
| -     * be printed as well.
 | 
| -     */
 | 
| -    0
 | 
| -#else
 | 
| -    100
 | 
| -#endif
 | 
| -    ;
 | 
| -
 | 
| -Bool NACL_FLAGS_validator_trace_instructions = FALSE;
 | 
| -
 | 
| -Bool NACL_FLAGS_validator_trace_inst_internals = FALSE;
 | 
| -
 | 
| -Bool NACL_FLAGS_ncval_annotate = TRUE;
 | 
| -
 | 
| -Bool NACL_FLAGS_unsafe_single_inst_mode = FALSE;
 | 
| -
 | 
| -#ifdef NCVAL_TESTING
 | 
| -Bool NACL_FLAGS_report_conditions_on_all = FALSE;
 | 
| -
 | 
| -void NaClConditionAppend(char* condition,
 | 
| -                         char** buffer,
 | 
| -                         size_t* remaining_buffer_size) {
 | 
| -  size_t bsize = strlen(condition);
 | 
| -  *buffer = condition + bsize;
 | 
| -  if (bsize > 0) {
 | 
| -    /* Add that we are adding an alternative. */
 | 
| -    SNPRINTF(*buffer, NCVAL_CONDITION_SIZE - bsize,
 | 
| -             "&");
 | 
| -    bsize = strlen(condition);
 | 
| -    *buffer = condition + bsize;
 | 
| -  }
 | 
| -  *remaining_buffer_size = NCVAL_CONDITION_SIZE - bsize;
 | 
| -}
 | 
| -#endif
 | 
| -
 | 
| -/* Define the stop instruction. */
 | 
| -const uint8_t kNaClFullStop = 0xf4;   /* x86 HALT opcode */
 | 
| -
 | 
| -void NaClValidatorFlagsSetTraceVerbose(void) {
 | 
| -  NACL_FLAGS_validator_trace_instructions = TRUE;
 | 
| -  NACL_FLAGS_validator_trace_inst_internals = TRUE;
 | 
| -}
 | 
| -
 | 
| -int NaClValidatorStateGetMaxReportedErrors(NaClValidatorState *vstate) {
 | 
| -  return vstate->quit_after_error_count;
 | 
| -}
 | 
| -
 | 
| -void NaClValidatorStateSetMaxReportedErrors(NaClValidatorState *vstate,
 | 
| -                                            int new_value) {
 | 
| -  vstate->quit_after_error_count = new_value;
 | 
| -  vstate->quit = NaClValidatorQuit(vstate);
 | 
| -}
 | 
| -
 | 
| -Bool NaClValidatorStateGetTraceInstructions(NaClValidatorState *vstate) {
 | 
| -  return vstate->trace_instructions;
 | 
| -}
 | 
| -
 | 
| -void NaClValidatorStateSetTraceInstructions(NaClValidatorState *vstate,
 | 
| -                                            Bool new_value) {
 | 
| -  vstate->trace_instructions = new_value;
 | 
| -}
 | 
| -
 | 
| -Bool NaClValidatorStateGetTraceInstInternals(NaClValidatorState *vstate) {
 | 
| -  return vstate->trace_inst_internals;
 | 
| -}
 | 
| -
 | 
| -void NaClValidatorStateSetTraceInstInternals(NaClValidatorState *vstate,
 | 
| -                                             Bool new_value) {
 | 
| -  vstate->trace_inst_internals = new_value;
 | 
| -}
 | 
| -
 | 
| -static INLINE Bool NaClValidatorStateTraceInline(NaClValidatorState *vstate) {
 | 
| -  return vstate->trace_instructions || vstate->trace_inst_internals;
 | 
| -}
 | 
| -
 | 
| -
 | 
| -Bool NaClValidatorStateTrace(NaClValidatorState *vstate) {
 | 
| -  return NaClValidatorStateTraceInline(vstate);
 | 
| -}
 | 
| -
 | 
| -void NaClValidatorStateSetTraceVerbose(NaClValidatorState *vstate) {
 | 
| -  vstate->trace_instructions = TRUE;
 | 
| -  vstate->trace_inst_internals = TRUE;
 | 
| -}
 | 
| -
 | 
| -int NaClValidatorStateGetLogVerbosity(NaClValidatorState *vstate) {
 | 
| -  return vstate->log_verbosity;
 | 
| -}
 | 
| -
 | 
| -void NaClValidatorStateSetLogVerbosity(NaClValidatorState *vstate,
 | 
| -                                       Bool new_value) {
 | 
| -  vstate->log_verbosity = new_value;
 | 
| -}
 | 
| -
 | 
| -Bool NaClValidatorStateGetDoStubOut(NaClValidatorState *vstate) {
 | 
| -  return vstate->do_stub_out;
 | 
| -}
 | 
| -
 | 
| -void NaClValidatorStateSetDoStubOut(NaClValidatorState *vstate,
 | 
| -                                    Bool new_value) {
 | 
| -  vstate->do_stub_out = new_value;
 | 
| -  /* We also turn off error diagnostics, under the assumption
 | 
| -   * you don't want them. (Note: if the user wants them,
 | 
| -   * you can run ncval to get them).
 | 
| -   */
 | 
| -  if (new_value) {
 | 
| -    NaClValidatorStateSetMaxReportedErrors(vstate, 0);
 | 
| -  }
 | 
| -}
 | 
| -
 | 
| -static void NaClValidatorTrace(NaClValidatorState* vstate) {
 | 
| -  struct Gio* g = NaClLogGetGio();
 | 
| -  NaClInstState* inst_state = NaClInstIterGetStateInline(vstate->cur_iter);
 | 
| -  (*vstate->error_reporter->printf)
 | 
| -      (vstate->error_reporter, "-> visit: ");
 | 
| -  if (NaClValidatorStateGetTraceInstructions(vstate)) {
 | 
| -    (*vstate->error_reporter->print_inst)(vstate->error_reporter,
 | 
| -                                         (void*) NaClInstStateInst(inst_state));
 | 
| -  }
 | 
| -  if (NaClValidatorStateGetTraceInstInternals(vstate)) {
 | 
| -    NaClExpVectorPrint(g, inst_state);
 | 
| -  }
 | 
| -}
 | 
| -
 | 
| -/* TODO(karl) Move the print routines to a separate module. */
 | 
| -
 | 
| -/* Returns true if an error message should be printed for the given level, in
 | 
| - * the current validator state.
 | 
| - * Parameters:
 | 
| - *   vstate - The validator state (may be NULL).
 | 
| - *   level - The log level of the validator message.
 | 
| - */
 | 
| -static INLINE Bool NaClPrintValidatorMessages(
 | 
| -    NaClValidatorState *vstate, int level) {
 | 
| -  if (NULL == vstate) {
 | 
| -    /* Validator not defined yet, only used log verbosity to decide if message
 | 
| -     * should be printed.
 | 
| -     */
 | 
| -    return level <= NaClLogGetVerbosity();
 | 
| -  } else {
 | 
| -    return (vstate->quit_after_error_count != 0) &&
 | 
| -        (level <= vstate->log_verbosity) &&
 | 
| -        (level <= NaClLogGetVerbosity());
 | 
| -  }
 | 
| -}
 | 
| -
 | 
| -static INLINE const char *NaClLogLevelLabel(int level) {
 | 
| -  switch (level) {
 | 
| -    case LOG_WARNING:
 | 
| -      return "WARNING: ";
 | 
| -    case LOG_ERROR:
 | 
| -      return "ERROR: ";
 | 
| -    case LOG_FATAL:
 | 
| -      return "FATAL: ";
 | 
| -    default:
 | 
| -      return "";
 | 
| -  }
 | 
| -}
 | 
| -
 | 
| -/* Records that an error message has just been reported.
 | 
| - * Parameters:
 | 
| - *   vstate - The validator state (may be NULL).
 | 
| - *   level - The log level of the validator message.
 | 
| - */
 | 
| -static void NaClRecordErrorReported(NaClValidatorState *vstate, int level) {
 | 
| -  if ((vstate != NULL) && ((level == LOG_ERROR) || (level == LOG_FATAL)) &&
 | 
| -      (vstate->quit_after_error_count > 0) &&
 | 
| -      !vstate->do_stub_out) {
 | 
| -    --(vstate->quit_after_error_count);
 | 
| -    vstate->quit = NaClValidatorQuit(vstate);
 | 
| -    if (vstate->quit_after_error_count == 0) {
 | 
| -      (*vstate->error_reporter->printf)(
 | 
| -          vstate->error_reporter,
 | 
| -          "%sError limit reached. Validator quitting!\n",
 | 
| -          NaClLogLevelLabel(LOG_INFO));
 | 
| -    }
 | 
| -  }
 | 
| -}
 | 
| -
 | 
| -/* Records the number of error validator messages generated for the state.
 | 
| - * Parameters:
 | 
| - *   vstate - The validator state (may be NULL).
 | 
| - *   level - The log level of the validator message.
 | 
| - * Returns - Updated error level, based on state.
 | 
| - */
 | 
| -static INLINE int NaClRecordIfValidatorError(NaClValidatorState *vstate,
 | 
| -                                             int level) {
 | 
| -  /* Note: don't quit if stubbing out, so all problems are fixed. */
 | 
| -  if (((level == LOG_ERROR) || (level == LOG_FATAL)) &&
 | 
| -      (NULL != vstate) && !vstate->do_stub_out) {
 | 
| -    vstate->validates_ok = FALSE;
 | 
| -    vstate->quit = NaClValidatorQuit(vstate);
 | 
| -  }
 | 
| -  return level;
 | 
| -}
 | 
| -
 | 
| -/* The low-level implementation for stubbing out an instruction. Always use
 | 
| - * this function to (ultimately) stub out instructions. This makes it possible
 | 
| - * to detect when the validator modifies the code.
 | 
| - */
 | 
| -void NCStubOutMem(NaClValidatorState *state, void *ptr, size_t num) {
 | 
| -  state->did_stub_out = TRUE;
 | 
| -  memset(ptr, kNaClFullStop, num);
 | 
| -}
 | 
| -
 | 
| -/* Does stub out of instruction in validator state. */
 | 
| -static void NaClStubOutInst(NaClValidatorState *state, NaClInstState* inst) {
 | 
| -  NCRemainingMemory *memory = inst->bytes.memory;
 | 
| -  NCStubOutMem(state, memory->mpc, memory->read_length);
 | 
| -}
 | 
| -
 | 
| -/* Does a printf using the error reporter of the state if defined.
 | 
| - * Uses NaClLogGetGio() if undefined.
 | 
| - */
 | 
| -static INLINE void NaClPrintVMessage(NaClValidatorState* vstate,
 | 
| -                                     const char* format,
 | 
| -                                     va_list ap) {
 | 
| -  if (vstate) {
 | 
| -    vstate->error_reporter->printf_v(vstate->error_reporter, format, ap);
 | 
| -  } else {
 | 
| -    gvprintf(NaClLogGetGio(), format, ap);
 | 
| -  }
 | 
| -}
 | 
| -
 | 
| -/* Forward declaration to define printf arguments. */
 | 
| -static void NaClPrintMessage(NaClValidatorState* vstate,
 | 
| -                             const char* format,
 | 
| -                             ...) ATTRIBUTE_FORMAT_PRINTF(2, 3);
 | 
| -
 | 
| -/* Does a printf using the error reporter of the state if defined.
 | 
| - * Uses NaClLogGetGio() if undefined.
 | 
| - */
 | 
| -static INLINE void NaClPrintMessage(NaClValidatorState* vstate,
 | 
| -                                    const char* format,
 | 
| -                                    ...) {
 | 
| -  va_list ap;
 | 
| -  va_start(ap, format);
 | 
| -  NaClPrintVMessage(vstate, format, ap);
 | 
| -  va_end(ap);
 | 
| -}
 | 
| -
 | 
| -/* Print out a predefined prefix for messages, along with the serverity
 | 
| - * of the message.
 | 
| - */
 | 
| -static void NaClPrintValidatorPrefix(int level,
 | 
| -                                     NaClValidatorState* vstate,
 | 
| -                                     Bool visible_level) {
 | 
| -  NaClPrintMessage(vstate, "VALIDATOR: ");
 | 
| -  if (visible_level) NaClPrintMessage(vstate, "%s", NaClLogLevelLabel(level));
 | 
| -}
 | 
| -
 | 
| -/* Prints out an instruction on behalf of the validator. */
 | 
| -static void NaClValidatorPrintInst(int level,
 | 
| -                                   NaClValidatorState *vstate,
 | 
| -                                   NaClInstState *inst) {
 | 
| -  NaClPrintValidatorPrefix(level, vstate, FALSE);
 | 
| -  if (vstate) {
 | 
| -    vstate->error_reporter->print_inst(vstate->error_reporter, (void*) inst);
 | 
| -  } else {
 | 
| -    NaClInstStateInstPrint(NaClLogGetGio(), inst);
 | 
| -  }
 | 
| -}
 | 
| -
 | 
| -void NaClValidatorMessage(int level,
 | 
| -                          NaClValidatorState *vstate,
 | 
| -                          const char *format,
 | 
| -                          ...) {
 | 
| -  level = NaClRecordIfValidatorError(vstate, level);
 | 
| -  if (NaClPrintValidatorMessages(vstate, level)) {
 | 
| -    va_list ap;
 | 
| -    NaClPrintValidatorPrefix(level, vstate, TRUE);
 | 
| -    va_start(ap, format);
 | 
| -    NaClPrintVMessage(vstate, format, ap);
 | 
| -    va_end(ap);
 | 
| -    NaClRecordErrorReported(vstate, level);
 | 
| -  }
 | 
| -}
 | 
| -
 | 
| -void NaClValidatorVarargMessage(int level,
 | 
| -                                NaClValidatorState *vstate,
 | 
| -                                const char *format,
 | 
| -                                va_list ap) {
 | 
| -  level = NaClRecordIfValidatorError(vstate, level);
 | 
| -  if (NaClPrintValidatorMessages(vstate, level)) {
 | 
| -    NaClPrintValidatorPrefix(level, vstate, TRUE);
 | 
| -    NaClPrintVMessage(vstate, format, ap);
 | 
| -    NaClRecordErrorReported(vstate, level);
 | 
| -  }
 | 
| -}
 | 
| -
 | 
| -static void NaClValidatorPcAddressMess(
 | 
| -    int level,
 | 
| -    NaClValidatorState *vstate,
 | 
| -    NaClPcAddress addr,
 | 
| -    const char *format,
 | 
| -    va_list ap) {
 | 
| -  level = NaClRecordIfValidatorError(vstate, level);
 | 
| -  if (NaClPrintValidatorMessages(vstate, level)) {
 | 
| -    NaClPrintValidatorPrefix(level, vstate, !NACL_FLAGS_ncval_annotate);
 | 
| -    NaClPrintMessage(vstate, "%"NACL_PRIxNaClPcAddress ": ", addr);
 | 
| -    NaClPrintVMessage(vstate, format, ap);
 | 
| -    NaClRecordErrorReported(vstate, level);
 | 
| -  }
 | 
| -}
 | 
| -
 | 
| -void NaClValidatorPcAddressMessage(int level,
 | 
| -                                   NaClValidatorState *vstate,
 | 
| -                                   NaClPcAddress addr,
 | 
| -                                   const char *format,
 | 
| -                                   ...) {
 | 
| -  va_list ap;
 | 
| -  va_start(ap, format);
 | 
| -  NaClValidatorPcAddressMess(level, vstate, vstate->vbase + addr, format, ap);
 | 
| -  va_end(ap);
 | 
| -}
 | 
| -
 | 
| -void NaClValidatorInstMessage(int level,
 | 
| -                              NaClValidatorState *vstate,
 | 
| -                              NaClInstState *inst,
 | 
| -                              const char *format,
 | 
| -                              ...) {
 | 
| -  if (NACL_FLAGS_ncval_annotate) {
 | 
| -    va_list ap;
 | 
| -    va_start(ap, format);
 | 
| -    NaClValidatorPcAddressMess(level, vstate,
 | 
| -                               NaClInstStatePrintableAddress(inst),
 | 
| -                               format, ap);
 | 
| -    va_end(ap);
 | 
| -  } else {
 | 
| -    level = NaClRecordIfValidatorError(vstate, level);
 | 
| -    if (NaClPrintValidatorMessages(vstate, level)) {
 | 
| -      va_list ap;
 | 
| -      NaClValidatorPrintInst(level, vstate, inst);
 | 
| -      NaClPrintValidatorPrefix(level, vstate, TRUE);
 | 
| -      va_start(ap, format);
 | 
| -      NaClPrintVMessage(vstate, format, ap);
 | 
| -      va_end(ap);
 | 
| -      NaClRecordErrorReported(vstate, level);
 | 
| -    }
 | 
| -  }
 | 
| -  if (vstate->do_stub_out && (level <= LOG_ERROR)) {
 | 
| -    NaClStubOutInst(vstate, inst);
 | 
| -  }
 | 
| -}
 | 
| -
 | 
| -void NaClValidatorTwoInstMessage(int level,
 | 
| -                                 NaClValidatorState *vstate,
 | 
| -                                 NaClInstState *inst1,
 | 
| -                                 NaClInstState *inst2,
 | 
| -                                 const char *format,
 | 
| -                                 ...) {
 | 
| -  level = NaClRecordIfValidatorError(vstate, level);
 | 
| -  if (NaClPrintValidatorMessages(vstate, level)) {
 | 
| -    va_list ap;
 | 
| -    NaClPrintValidatorPrefix(level, vstate, TRUE);
 | 
| -    va_start(ap, format);
 | 
| -    NaClPrintVMessage(vstate, format, ap);
 | 
| -    va_end(ap);
 | 
| -    NaClPrintMessage(vstate, "\n                                   ");
 | 
| -    NaClValidatorPrintInst(level, vstate, inst1);
 | 
| -    NaClPrintMessage(vstate, "                                   ");
 | 
| -    NaClValidatorPrintInst(level, vstate, inst2);
 | 
| -    NaClRecordErrorReported(vstate, level);
 | 
| -  }
 | 
| -  if (vstate->do_stub_out && (level <= LOG_ERROR)) {
 | 
| -    NaClStubOutInst(vstate, inst2);
 | 
| -  }
 | 
| -}
 | 
| -
 | 
| -Bool NaClValidatorQuit(NaClValidatorState *vstate) {
 | 
| -  return !vstate->validates_ok && (vstate->quit_after_error_count == 0);
 | 
| -}
 | 
| -
 | 
| -Bool NaClValidatorDidStubOut(NaClValidatorState *vstate) {
 | 
| -  return vstate->did_stub_out;
 | 
| -}
 | 
| -
 | 
| -static void NaClNullErrorPrintInst(NaClErrorReporter* self,
 | 
| -                                   struct NaClInstState* inst) {}
 | 
| -
 | 
| -NaClErrorReporter kNaClNullErrorReporter = {
 | 
| -  NaClNullErrorReporter,
 | 
| -  NaClNullErrorPrintf,
 | 
| -  NaClNullErrorPrintfV,
 | 
| -  (NaClPrintInst) NaClNullErrorPrintInst
 | 
| -};
 | 
| -
 | 
| -/* Update caches associated the current instruction state associated with
 | 
| - * the iterator of the validator state. This routine should be called everytime
 | 
| - * the iterator (of the validator state) is advanced.
 | 
| - */
 | 
| -static INLINE void NaClUpdateCaches(NaClValidatorState *vstate) {
 | 
| -#ifdef NCVAL_TESTING
 | 
| -  /* Initialize the pre/post conditions to the empty condition. */
 | 
| -  strcpy(&vstate->precond[0], "");
 | 
| -  strcpy(&vstate->postcond[0], "");
 | 
| -#endif
 | 
| -  vstate->cur_inst_state = NaClInstIterGetStateInline(vstate->cur_iter);
 | 
| -  vstate->cur_inst = NaClInstStateInst(vstate->cur_inst_state);
 | 
| -  vstate->cur_inst_vector = NaClInstStateExpVector(vstate->cur_inst_state);
 | 
| -}
 | 
| -
 | 
| -/* Returns true if the current position of the instruction iterator (for
 | 
| - * the validator state) points to an instruction (i.e. not at the end of
 | 
| - * the segment).
 | 
| - */
 | 
| -static INLINE Bool NaClValidatorStateIterHasNextInline(
 | 
| -    NaClValidatorState *vstate) {
 | 
| -  Bool result;
 | 
| -  if (NULL == vstate->cur_iter) return FALSE;
 | 
| -  result = NaClInstIterHasNextInline(vstate->cur_iter);
 | 
| -  if (result && NULL == vstate->cur_inst_state) {
 | 
| -    /* If reached, this is the first query to check if there is
 | 
| -     * a next instruction. Update the caches to match.
 | 
| -     */
 | 
| -    NaClUpdateCaches(vstate);
 | 
| -  }
 | 
| -  return result;
 | 
| -}
 | 
| -
 | 
| -Bool NaClValidatorStateIterHasNext(NaClValidatorState *vstate) {
 | 
| -  return NaClValidatorStateIterHasNextInline(vstate);
 | 
| -}
 | 
| -
 | 
| -/* Move past the current instruction defined by the iterator of the
 | 
| - * validator state.
 | 
| - */
 | 
| -static INLINE void NaClValidatorStateIterAdvanceInline(
 | 
| -    NaClValidatorState *vstate) {
 | 
| -  NaClInstIterAdvanceInline(vstate->cur_iter);
 | 
| -  NaClUpdateCaches(vstate);
 | 
| -}
 | 
| -
 | 
| -void NaClValidatorStateIterAdvance(NaClValidatorState *vstate) {
 | 
| -  NaClValidatorStateIterAdvanceInline(vstate);
 | 
| -}
 | 
| -
 | 
| -/* Iterator of the validator state is no longer needed, clean up any
 | 
| - * caches associated with the iterator.
 | 
| - */
 | 
| -static void NaClValidatorStateIterFinishInline(NaClValidatorState *vstate) {
 | 
| -  vstate->cur_inst_state = NULL;
 | 
| -  vstate->cur_inst = NULL;
 | 
| -  vstate->cur_inst_vector = NULL;
 | 
| -}
 | 
| -
 | 
| -void NaClValidatorStateIterFinish(NaClValidatorState *vstate) {
 | 
| -  NaClValidatorStateIterFinishInline(vstate);
 | 
| -}
 | 
| -
 | 
| -NaClValidatorState *NaClValidatorStateCreate(
 | 
| -    const NaClPcAddress vbase,
 | 
| -    const NaClMemorySize codesize,
 | 
| -    const NaClOpKind base_register,
 | 
| -    const int readonly_text,
 | 
| -    const NaClCPUFeaturesX86 *features) {
 | 
| -  NaClValidatorState *vstate;
 | 
| -  NaClValidatorState *return_value = NULL;
 | 
| -  const int bundle_size = 32;
 | 
| -  DEBUG(NaClLog(LOG_INFO,
 | 
| -                "Validator Create: vbase = %"NACL_PRIxNaClPcAddress", "
 | 
| -                "sz = %"NACL_PRIxNaClMemorySize", bundle_size = %u\n",
 | 
| -                vbase, codesize, bundle_size));
 | 
| -  if (features == NULL)
 | 
| -    return NULL;
 | 
| -  vstate = (NaClValidatorState*) malloc(sizeof(NaClValidatorState));
 | 
| -  if (vstate != NULL) {
 | 
| -    return_value = vstate;
 | 
| -    vstate->decoder_tables = kNaClValDecoderTables;
 | 
| -    vstate->vbase = vbase;
 | 
| -    vstate->bundle_size = bundle_size;
 | 
| -    vstate->codesize = codesize;
 | 
| -    vstate->bundle_mask = bundle_size - 1;
 | 
| -    NaClCopyCPUFeaturesX86(&vstate->cpu_features, features);
 | 
| -    vstate->base_register = base_register;
 | 
| -    vstate->validates_ok = TRUE;
 | 
| -    vstate->did_stub_out = FALSE;
 | 
| -    vstate->quit_after_error_count = NACL_FLAGS_max_reported_errors;
 | 
| -#ifdef NCVAL_TESTING
 | 
| -    vstate->validates_ok_with_conditions = TRUE;
 | 
| -    vstate->report_conditions_on_all = NACL_FLAGS_report_conditions_on_all;
 | 
| -#endif
 | 
| -    vstate->error_reporter = &kNaClNullErrorReporter;
 | 
| -    vstate->print_opcode_histogram = NACL_FLAGS_opcode_histogram;
 | 
| -    vstate->trace_instructions = NACL_FLAGS_validator_trace_instructions;
 | 
| -    vstate->trace_inst_internals = NACL_FLAGS_validator_trace_inst_internals;
 | 
| -    vstate->log_verbosity = LOG_INFO;
 | 
| -    vstate->cur_iter = NULL;
 | 
| -    NaClValidatorStateIterFinishInline(vstate);
 | 
| -    vstate->quit = NaClValidatorQuit(return_value);
 | 
| -    vstate->do_stub_out = FALSE;
 | 
| -    vstate->readonly_text = readonly_text;
 | 
| -    vstate->do_detailed = FALSE;
 | 
| -    NaClOpcodeHistogramInitialize(vstate);
 | 
| -    NaClCpuCheckMemoryInitialize(vstate);
 | 
| -    NaClBaseRegisterMemoryInitialize(vstate);
 | 
| -    if (!NaClJumpValidatorInitialize(vstate)) {
 | 
| -      NaClValidatorStateDestroy(vstate);
 | 
| -      return_value = NULL;
 | 
| -    }
 | 
| -  }
 | 
| -  return return_value;
 | 
| -}
 | 
| -
 | 
| -Bool NaClValidatorStateIterReset(NaClValidatorState *vstate) {
 | 
| -  /* Record infromation needed to reset the iterator, based on the
 | 
| -   * current iterator
 | 
| -   */
 | 
| -  size_t lookback_size = lookback_size = vstate->cur_iter->buffer_size;
 | 
| -  NaClSegment* segment = vstate->cur_iter->segment;
 | 
| -
 | 
| -  if (NULL == vstate->cur_iter) return FALSE;
 | 
| -
 | 
| -  /* Before deleting, be sure to clean up cached information. and
 | 
| -   * the destroy the current validator. */
 | 
| -  NaClValidatorStateIterFinishInline(vstate);
 | 
| -  NaClInstIterDestroy(vstate->cur_iter);
 | 
| -
 | 
| -  /* Now create a new instruction iterator. */
 | 
| -  vstate->cur_iter = NaClInstIterCreateWithLookback(
 | 
| -      vstate->decoder_tables, segment, lookback_size);
 | 
| -
 | 
| -  if (NULL == vstate->cur_iter) return FALSE;
 | 
| -  return TRUE;
 | 
| -}
 | 
| -
 | 
| -#ifdef NCVAL_TESTING
 | 
| -void NaClPrintConditions(NaClValidatorState *state) {
 | 
| -  /* To save space, only report on instructions that have non-empty
 | 
| -   * pre/post conditions.
 | 
| -   */
 | 
| -  if ((strlen(state->precond) > 0) || (strlen(state->postcond) > 0)) {
 | 
| -    printf("%"NACL_PRIxNaClPcAddress": ",
 | 
| -           NaClInstStatePrintableAddress(state->cur_inst_state));
 | 
| -    if ('\0' != state->precond[0]) {
 | 
| -      printf("%s", state->precond);
 | 
| -    }
 | 
| -    if ('\0' != state->postcond[0]) {
 | 
| -      if ('\0' != state->precond[0]) printf(" ");
 | 
| -      printf("-> %s", state->postcond);
 | 
| -    }
 | 
| -    printf("\n");
 | 
| -  }
 | 
| -}
 | 
| -#endif
 | 
| -
 | 
| -/* Given we are at the instruction defined by the instruction iterator, for
 | 
| - * a segment, apply all applicable validator functions.
 | 
| - */
 | 
| -static INLINE void NaClApplyValidators(NaClValidatorState *vstate) {
 | 
| -  if (vstate->quit) return;
 | 
| -  DEBUG(NaClLog(LOG_INFO, "iter state:\n");
 | 
| -        NaClInstStateInstPrint(NaClLogGetGio(),
 | 
| -                               NaClInstIterGetState(vstate->cur_iter)));
 | 
| -  if (NaClValidatorStateTraceInline(vstate)) {
 | 
| -    NaClValidatorTrace(vstate);
 | 
| -  }
 | 
| -  NaClCpuCheck(vstate, vstate->cur_iter);
 | 
| -  NaClValidateInstructionLegal(vstate);
 | 
| -  NaClBaseRegisterValidator(vstate);
 | 
| -  NaClMemoryReferenceValidator(vstate);
 | 
| -  NaClJumpValidator(vstate);
 | 
| -  if (vstate->print_opcode_histogram) {
 | 
| -    NaClOpcodeHistogramRecord(vstate);
 | 
| -  }
 | 
| -#ifdef NCVAL_TESTING
 | 
| -  /* Collect post conditions for instructions that are non-last.
 | 
| -   * Only print pre/post conditions for valid instructions (ignoring
 | 
| -   * pre/post conditions).
 | 
| -   */
 | 
| -  if (NaClValidatesOk(vstate) || vstate->report_conditions_on_all) {
 | 
| -    NaClAddAssignsRegisterWithZeroExtendsPostconds(vstate);
 | 
| -    NaClAddLeaSafeAddressPostconds(vstate);
 | 
| -    NaClPrintConditions(vstate);
 | 
| -  }
 | 
| -  /* Reset the exit flags, so that errors do not stop
 | 
| -   * other instructions from firing errors. By reseting these flags,
 | 
| -   * it allows us to only print pre/post conditions for instructions
 | 
| -   * that are not marked illegal.
 | 
| -   */
 | 
| -  if (!vstate->validates_ok) vstate->validates_ok_with_conditions = FALSE;
 | 
| -  vstate->validates_ok = TRUE;
 | 
| -  vstate->quit = FALSE;
 | 
| -#endif
 | 
| -}
 | 
| -
 | 
| -/* Given that we have just iterated through all instructions in a segment,
 | 
| - * apply post validators rules (before we collect the iterator).
 | 
| - */
 | 
| -static INLINE void NaClApplyPostValidators(NaClValidatorState *vstate) {
 | 
| -  DEBUG(NaClLog(LOG_INFO, "applying post validators...\n"));
 | 
| -  if (vstate->quit || (NULL == vstate->cur_iter)) return;
 | 
| -
 | 
| -  /* Before doing anything else, process remaining (forward) information
 | 
| -   * stored by the validator, to see if any errors should be reported
 | 
| -   * about the last instruction processed.
 | 
| -   */
 | 
| -  NaClBaseRegisterSummarize(vstate);
 | 
| -
 | 
| -  /* Now do the summarizing steps of the validator. */
 | 
| -  if (vstate->do_detailed) {
 | 
| -    NaClJumpValidatorSummarizeDetailed(vstate);
 | 
| -  } else {
 | 
| -    NaClJumpValidatorSummarize(vstate);
 | 
| -  }
 | 
| -  if (NaClValidatorStateTrace(vstate)) {
 | 
| -    (vstate->error_reporter->printf)
 | 
| -        (vstate->error_reporter, "<- visit\n");
 | 
| -  }
 | 
| -}
 | 
| -
 | 
| -/* The maximum lookback for the instruction iterator of the segment.
 | 
| - * Note: Allows for two memory patterns (4 instructions for each pattern).
 | 
| - */
 | 
| -static const size_t kLookbackSize = 8;
 | 
| -
 | 
| -void NaClValidateSegment(uint8_t *mbase, NaClPcAddress vbase,
 | 
| -                         NaClMemorySize size, NaClValidatorState *vstate) {
 | 
| -  NaClSegment segment;
 | 
| -  do {
 | 
| -    /* Sanity checks */
 | 
| -    /* TODO(ncbray): remove redundant vbase/size args. */
 | 
| -    if ((vbase & vstate->bundle_mask) != 0) {
 | 
| -      NaClValidatorMessage(LOG_ERROR, vstate,
 | 
| -                           "Code segment starts at 0x%"NACL_PRIxNaClPcAddress
 | 
| -                           ", which isn't aligned properly.\n",
 | 
| -                           vbase);
 | 
| -      break;
 | 
| -    }
 | 
| -    if (vbase != vstate->vbase) {
 | 
| -      NaClValidatorMessage(LOG_ERROR, vstate, "Mismatched vbase address\n");
 | 
| -      break;
 | 
| -    }
 | 
| -    if (size != vstate->codesize) {
 | 
| -      NaClValidatorMessage(LOG_ERROR, vstate, "Mismatched code size\n");
 | 
| -      break;
 | 
| -    }
 | 
| -    if (vbase > vbase + size) {
 | 
| -      NaClValidatorMessage(LOG_ERROR, vstate, "Text segment too big for given "
 | 
| -                           "vbase (address overflow)\n");
 | 
| -      break;
 | 
| -    }
 | 
| -
 | 
| -    size = NCHaltTrimSize(mbase, size, vstate->bundle_size);
 | 
| -    vstate->codesize = size;
 | 
| -
 | 
| -    if (size == 0) {
 | 
| -      NaClValidatorMessage(LOG_ERROR, vstate, "Bad text segment (zero size)\n");
 | 
| -      break;
 | 
| -    }
 | 
| -
 | 
| -    NaClSegmentInitialize(mbase, vbase, size, &segment);
 | 
| -
 | 
| -    vstate->cur_iter = NaClInstIterCreateWithLookback(vstate->decoder_tables,
 | 
| -                                                      &segment, kLookbackSize);
 | 
| -    if (NULL == vstate->cur_iter) {
 | 
| -      NaClValidatorMessage(LOG_ERROR, vstate, "Not enough memory\n");
 | 
| -      break;
 | 
| -    }
 | 
| -    for (; NaClValidatorStateIterHasNextInline(vstate);
 | 
| -         NaClValidatorStateIterAdvanceInline(vstate)) {
 | 
| -      NaClApplyValidators(vstate);
 | 
| -      if (vstate->quit) break;
 | 
| -    }
 | 
| -    NaClValidatorStateIterFinish(vstate);
 | 
| -  } while (0);
 | 
| -  NaClApplyPostValidators(vstate);
 | 
| -  NaClInstIterDestroy(vstate->cur_iter);
 | 
| -  vstate->cur_iter = NULL;
 | 
| -  if (vstate->print_opcode_histogram) {
 | 
| -    NaClOpcodeHistogramPrintStats(vstate);
 | 
| -  }
 | 
| -#ifdef NCVAL_TESTING
 | 
| -  /* Update failure to catch instructions that may have validated
 | 
| -   * incorrectly.
 | 
| -   */
 | 
| -  if (vstate->validates_ok)
 | 
| -    vstate->validates_ok = vstate->validates_ok_with_conditions;
 | 
| -#endif
 | 
| -}
 | 
| -
 | 
| -void NaClValidateSegmentUsingTables(uint8_t* mbase,
 | 
| -                                    NaClPcAddress vbase,
 | 
| -                                    NaClMemorySize sz,
 | 
| -                                    NaClValidatorState* vstate,
 | 
| -                                    const struct NaClDecodeTables* tables) {
 | 
| -  vstate->decoder_tables = tables;
 | 
| -  NaClValidateSegment(mbase, vbase, sz, vstate);
 | 
| -}
 | 
| -
 | 
| -Bool NaClValidatesOk(NaClValidatorState *vstate) {
 | 
| -  return vstate->validates_ok;
 | 
| -}
 | 
| -
 | 
| -void NaClValidatorStateDestroy(NaClValidatorState *vstate) {
 | 
| -  if (NULL != vstate) {
 | 
| -    NaClJumpValidatorCleanUp(vstate);
 | 
| -    free(vstate);
 | 
| -  }
 | 
| -}
 | 
| -
 | 
| -/*
 | 
| - * Check that iter_new is a valid replacement for iter_old.
 | 
| - * If a validation error occurs, vstate->validates_ok will be set to false by
 | 
| - * NaClValidatorInstMessage when it is given LOG_ERROR, see the end of this
 | 
| - * function.
 | 
| - * Return value: TRUE if the instruction was changed, FALSE if it's identical.
 | 
| - */
 | 
| -static Bool NaClValidateInstReplacement(NaClInstIter *iter_old,
 | 
| -                                        NaClInstIter *iter_new,
 | 
| -                                        struct NaClValidatorState *vstate) {
 | 
| -  NaClInstState *istate_old, *istate_new;
 | 
| -  NaClExpVector *exp_old, *exp_new;
 | 
| -  uint32_t i;
 | 
| -  Bool inst_changed = FALSE;
 | 
| -  int parent_index;
 | 
| -
 | 
| -  istate_old = NaClInstIterGetStateInline(iter_old);
 | 
| -  istate_new = NaClInstIterGetStateInline(iter_new);
 | 
| -
 | 
| -  /* Location/length must match.  Assumes vbase is the same. */
 | 
| -  if (istate_new->inst_addr != istate_old->inst_addr ||
 | 
| -      istate_new->bytes.length != istate_old->bytes.length) {
 | 
| -    NaClValidatorTwoInstMessage(LOG_ERROR, vstate, istate_old, istate_new,
 | 
| -          "Code modification: instructions length/addresses do not match");
 | 
| -    inst_changed = TRUE;
 | 
| -    return inst_changed;
 | 
| -  }
 | 
| -
 | 
| -
 | 
| -  do {
 | 
| -    /* fast check if the replacement is identical */
 | 
| -    if ((istate_old->bytes.memory->read_length ==
 | 
| -         istate_new->bytes.memory->read_length) &&
 | 
| -        !memcmp(istate_old->bytes.memory->mpc, istate_new->bytes.memory->mpc,
 | 
| -                istate_old->bytes.memory->read_length))
 | 
| -      return inst_changed;
 | 
| -
 | 
| -    inst_changed = TRUE;
 | 
| -
 | 
| -    if (istate_old->num_prefix_bytes != istate_new->num_prefix_bytes)
 | 
| -      break;
 | 
| -    if (istate_old->num_rex_prefixes != istate_new->num_rex_prefixes)
 | 
| -      break;
 | 
| -    if (istate_old->rexprefix != istate_new->rexprefix)
 | 
| -      break;
 | 
| -    if (istate_old->modrm != istate_new->modrm)
 | 
| -      break;
 | 
| -    if (istate_old->has_sib != istate_new->has_sib)
 | 
| -      break;
 | 
| -    if (istate_old->has_sib && istate_old->sib != istate_new->sib)
 | 
| -      break;
 | 
| -    if (istate_old->operand_size != istate_new->operand_size)
 | 
| -      break;
 | 
| -    if (istate_old->address_size != istate_new->address_size)
 | 
| -      break;
 | 
| -    if (istate_old->prefix_mask != istate_new->prefix_mask)
 | 
| -      break;
 | 
| -
 | 
| -    /*
 | 
| -     * these are pointers, but they reference entries in a static table,
 | 
| -     * so if the two instructions are the same, then these pointers must
 | 
| -     * reference the same entry
 | 
| -     */
 | 
| -    if (istate_old->inst != istate_new->inst)
 | 
| -      break;
 | 
| -
 | 
| -    exp_old = NaClInstStateExpVector(istate_old);
 | 
| -    exp_new = NaClInstStateExpVector(istate_new);
 | 
| -
 | 
| -    /* check if the instruction operands are identical */
 | 
| -    if (exp_old->number_expr_nodes != exp_new->number_expr_nodes)
 | 
| -      break;
 | 
| -
 | 
| -    for (i = 0; i < exp_old->number_expr_nodes; i++) {
 | 
| -      /* Allow nodes that are identical. */
 | 
| -      if (exp_old->node[i].kind  != exp_new->node[i].kind) goto error_exit;
 | 
| -      if (exp_old->node[i].flags != exp_new->node[i].flags) goto error_exit;
 | 
| -      if (exp_old->node[i].value == exp_new->node[i].value) continue;
 | 
| -
 | 
| -      /*
 | 
| -       * Only constant values may differ. However it is important not to
 | 
| -       * allow constant modification of sandboxing instructions. Note neither
 | 
| -       * of the instructions allowed for modification is used for sandboxing.
 | 
| -       */
 | 
| -      if (exp_old->node[i].kind != ExprConstant) goto error_exit;
 | 
| -
 | 
| -      switch (istate_old->inst->name) {
 | 
| -
 | 
| -        case InstCall:
 | 
| -          /* allow different constants in direct calls */
 | 
| -          if (!NaClHasBit(exp_old->node[i].flags, NACL_EFLAG(ExprJumpTarget)))
 | 
| -            break;
 | 
| -          parent_index = NaClGetExpParentIndex(exp_old, i);
 | 
| -          if (parent_index < 0) break;
 | 
| -          if (exp_old->node[parent_index].kind == OperandReference) continue;
 | 
| -          break;
 | 
| -
 | 
| -        case InstMov:
 | 
| -          parent_index = NaClGetExpParentIndex(exp_old, i);
 | 
| -          if (parent_index < 0) break;
 | 
| -          switch (exp_old->node[parent_index].kind) {
 | 
| -            case OperandReference:
 | 
| -              /*
 | 
| -               * allow different constants in operand of mov
 | 
| -               * e.g. mov $rax, 0xdeadbeef
 | 
| -               */
 | 
| -              if (NaClHasBit(exp_old->node[i].flags, NACL_EFLAG(ExprUsed)))
 | 
| -                continue;
 | 
| -              break;
 | 
| -            case ExprMemOffset:
 | 
| -              /*
 | 
| -               * allow different displacements in memory reference of mov
 | 
| -               * instructions e.g. mov $rax, [$r15+$rbx*2+0x7fff]
 | 
| -               *
 | 
| -               * Note: displacement is the fourth node after ExprMemOffset*
 | 
| -               * node
 | 
| -               */
 | 
| -              if (4 == (i - parent_index)) continue;
 | 
| -              break;
 | 
| -            default:
 | 
| -              break;
 | 
| -          }
 | 
| -          break;
 | 
| -        default:
 | 
| -          break;
 | 
| -      }
 | 
| -
 | 
| -      /* If reached, we found a value that differed, and wasn't one
 | 
| -       * of the expected constants that can differ.
 | 
| -       */
 | 
| -      goto error_exit;
 | 
| -    }
 | 
| -
 | 
| -    /* This return signifies there is no error in validation. */
 | 
| -    return inst_changed;
 | 
| -  } while (0);
 | 
| -
 | 
| -error_exit:
 | 
| -  /* This logging function is the mechanism that sets the validator state
 | 
| -   * to indicate an error.
 | 
| -   */
 | 
| -  NaClValidatorTwoInstMessage(LOG_ERROR, vstate, istate_old, istate_new,
 | 
| -                      "Code modification: failed to modify instruction");
 | 
| -  return inst_changed;
 | 
| -}
 | 
| -
 | 
| -/*
 | 
| - * Validate a new code block as a replacement for an existing block.
 | 
| - * Note: The code location (vbase) must be bundle aligned and the segment size
 | 
| - * must also be a multiple of bundle size (checked in
 | 
| - * NaClValidateCodeReplacement).This is to ensure all NaCl psuedo-instructions
 | 
| - * and guard sequences are properly inspected and maintained.
 | 
| - */
 | 
| -void NaClValidateSegmentPair(uint8_t *mbase_old, uint8_t *mbase_new,
 | 
| -                           NaClPcAddress vbase, size_t size,
 | 
| -                           struct NaClValidatorState *vstate) {
 | 
| -  NaClSegment segment_old, segment_new;
 | 
| -  NaClInstIter *iter_old = NULL;
 | 
| -  NaClInstIter *iter_new = NULL;
 | 
| -
 | 
| -  NaClSegmentInitialize(mbase_old, vbase, size, &segment_old);
 | 
| -  NaClSegmentInitialize(mbase_new, vbase, size, &segment_new);
 | 
| -  do {
 | 
| -    iter_old = NaClInstIterCreateWithLookback(vstate->decoder_tables,
 | 
| -                                              &segment_old, kLookbackSize);
 | 
| -    if (NULL == iter_old) break;
 | 
| -    iter_new = NaClInstIterCreateWithLookback(vstate->decoder_tables,
 | 
| -                                              &segment_new, kLookbackSize);
 | 
| -    if (NULL == iter_new) break;
 | 
| -    vstate->cur_iter = iter_new;
 | 
| -    while (NaClInstIterHasNextInline(iter_old) &&
 | 
| -           NaClValidatorStateIterHasNextInline(vstate)) {
 | 
| -      vstate->cur_inst_state->unchanged =
 | 
| -          !NaClValidateInstReplacement(iter_old, iter_new, vstate);
 | 
| -      NaClApplyValidators(vstate);
 | 
| -      if (vstate->quit) break;
 | 
| -      NaClInstIterAdvanceInline(iter_old);
 | 
| -      NaClValidatorStateIterAdvanceInline(vstate);
 | 
| -    }
 | 
| -    if (NaClInstIterHasNextInline(iter_old) ||
 | 
| -        NaClInstIterHasNextInline(iter_new)) {
 | 
| -      NaClValidatorMessage(
 | 
| -          LOG_ERROR, vstate,
 | 
| -          "Code modification: code segments have different "
 | 
| -          "number of instructions\n");
 | 
| -    }
 | 
| -  } while (0);
 | 
| -  NaClValidatorStateIterFinish(vstate);
 | 
| -  NaClApplyPostValidators(vstate);
 | 
| -  vstate->cur_iter = NULL;
 | 
| -  NaClInstIterDestroy(iter_old);
 | 
| -  NaClInstIterDestroy(iter_new);
 | 
| -}
 | 
| 
 |