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

Unified Diff: src/trusted/validator/x86/ncval_reg_sfi/ncvalidate_iter.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/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);
-}

Powered by Google App Engine
This is Rietveld 408576698