| Index: src/trusted/validator/x86/decoder/nc_inst_state.c
|
| diff --git a/src/trusted/validator/x86/decoder/nc_inst_state.c b/src/trusted/validator/x86/decoder/nc_inst_state.c
|
| deleted file mode 100644
|
| index 9266d9855db952352af8055f83a5fa86a4432236..0000000000000000000000000000000000000000
|
| --- a/src/trusted/validator/x86/decoder/nc_inst_state.c
|
| +++ /dev/null
|
| @@ -1,228 +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.
|
| - */
|
| -
|
| -/*
|
| - * Defines an instruction (decoder), based on the current location of
|
| - * the instruction iterator. The instruction decoder takes a list
|
| - * of candidate opcode (instruction) patterns, and searches for the
|
| - * first candidate that matches the requirements of the opcode pattern.
|
| - */
|
| -
|
| -#include "native_client/src/trusted/validator/x86/decoder/nc_inst_state.h"
|
| -
|
| -/* To turn on debugging of instruction decoding, change value of
|
| - * DEBUGGING to 1.
|
| - */
|
| -#define DEBUGGING 0
|
| -
|
| -/*
|
| - * This .c file contains includes, static functions, and constants that are used
|
| - * in nc_inst_state.c, but have been factored out and put into this file, so
|
| - * that we can test them. That is, to allow nc_inst_state.c and
|
| - * nc_inst_state_Tests.cc to use them.
|
| - */
|
| -#include "native_client/src/trusted/validator/x86/decoder/nc_inst_state_statics.c"
|
| -
|
| -/* Returns true if the parsed instruction may be replaceable with a (hard coded)
|
| - * opcode sequence. Used to prefer hard-coded opcode sequences over general
|
| - * matches. These hard-coded opcode sequences are special nop opcode sequences,
|
| - * most of which are generated by compilers and linkers. The need for these
|
| - * hard-coded sequences is to accept nops with prefixes that would not otherwise
|
| - * be accepted (such as "6666666666662e0f1f840000000000").
|
| - */
|
| -static Bool NaClMaybeHardCodedNop(NaClInstState* state) {
|
| - /* Note: This code is based on the hard-coded instructions
|
| - * defined in function NaClDefNops in
|
| - * src/trusted/validator_x86/ncdecode_tablegen.c.
|
| - * If you change the hard-coded instructions defined in this
|
| - * function, be sure that this predicate is updated accordingly to
|
| - * return true for all such hard-coded instructions (it can
|
| - * return true on other instructions without breaking the validator).
|
| - */
|
| -
|
| - /* Check the first opcode byte to see if it is a special case. */
|
| - switch (state->bytes.byte[state->num_prefix_bytes]) {
|
| - case 0x90:
|
| - /* If the first opcode byte is 90, it can be the NOP instruction.
|
| - * Return true that this can be a nop.
|
| - */
|
| - if (state->num_opcode_bytes == 1) return TRUE;
|
| - break;
|
| - case 0x0f:
|
| - /* Check that the second opcode byte is 1F or 0B. That is,
|
| - * can the instruction be a NOP (0f1f) or the UD2 instruction.
|
| - */
|
| - if (state->num_opcode_bytes == 2) {
|
| - uint8_t opcode_2 =
|
| - state->bytes.byte[state->num_prefix_bytes + 1];
|
| - if ((opcode_2 == 0x1f) || (opcode_2 == 0x0b)) return TRUE;
|
| - }
|
| - break;
|
| - default:
|
| - break;
|
| - }
|
| - /* If reached, can't be a (hard-coded) NOP instruction. */
|
| - return FALSE;
|
| -}
|
| -
|
| -/* Given the current location of the (relative) pc of the given instruction
|
| - * iterator, update the given state to hold the (found) matched opcode
|
| - * (instruction) pattern. If no matching pattern exists, set the state
|
| - * to a matched undefined opcode (instruction) pattern. In all cases,
|
| - * update the state to hold all information on the matched bytes of the
|
| - * instruction. Note: The iterator expects that the opcode field is
|
| - * changed from NULL to non-NULL by this fuction.
|
| - */
|
| -void NaClDecodeInst(NaClInstIter* iter, NaClInstState* state) {
|
| - uint8_t inst_length = 0;
|
| - const NaClInst* cand_insts;
|
| - Bool found_match = FALSE;
|
| -
|
| - /* Start by consuming the prefix bytes, and getting the possible
|
| - * candidate opcode (instruction) patterns that can match, based
|
| - * on the consumed opcode bytes.
|
| - */
|
| - NaClInstStateInit(iter, state);
|
| - if (NaClConsumePrefixBytes(state)) {
|
| - NaClInstPrefixDescriptor prefix_desc;
|
| - Bool continue_loop = TRUE;
|
| - NaClConsumeInstBytes(state, &prefix_desc);
|
| - inst_length = state->bytes.length;
|
| - while (continue_loop) {
|
| - /* Try matching all possible candidates, in the order they are specified
|
| - * (from the most specific prefix match, to the least specific prefix
|
| - * match). Quit when the first pattern is matched.
|
| - */
|
| - if (prefix_desc.matched_prefix == NaClInstPrefixEnumSize) {
|
| - continue_loop = FALSE;
|
| - } else {
|
| - uint8_t cur_opcode_prefix = prefix_desc.opcode_prefix;
|
| - cand_insts = NaClGetNextInstCandidates(state, &prefix_desc,
|
| - &inst_length);
|
| - while (cand_insts != NULL) {
|
| - NaClClearInstState(state, inst_length);
|
| - state->inst = cand_insts;
|
| - DEBUG(NaClLog(LOG_INFO, "try opcode pattern:\n"));
|
| - DEBUG_OR_ERASE(NaClInstPrint(NaClLogGetGio(), state->decoder_tables,
|
| - state->inst));
|
| - if (NaClConsumeAndCheckOperandSize(state) &&
|
| - NaClConsumeAndCheckAddressSize(state) &&
|
| - NaClConsumeModRm(state) &&
|
| - NaClConsumeSib(state) &&
|
| - NaClConsumeDispBytes(state) &&
|
| - NaClConsumeImmediateBytes(state) &&
|
| - NaClValidatePrefixFlags(state)) {
|
| - if (state->inst->flags & NACL_IFLAG(Opcode0F0F) &&
|
| - /* Note: If all of the above code worked correctly,
|
| - * there should be no need for the following test.
|
| - * However, just to be safe, it is added.
|
| - */
|
| - (state->num_imm_bytes == 1)) {
|
| - /* Special 3DNOW instructions where opcode is in parsed
|
| - * immediate byte at end of instruction. Look up in table,
|
| - * and replace if found. Otherwise, let the default 0F0F lookup
|
| - * act as the matching (invalid) instruction.
|
| - */
|
| - const NaClInst* cand_inst;
|
| - uint8_t opcode_byte = state->bytes.byte[state->first_imm_byte];
|
| - DEBUG(NaClLog(LOG_INFO,
|
| - "NaClConsume immediate byte opcode char: %"
|
| - NACL_PRIx8"\n", opcode_byte));
|
| - cand_inst = NaClGetPrefixOpcodeInst(state->decoder_tables,
|
| - Prefix0F0F, opcode_byte);
|
| - if (NULL != cand_inst) {
|
| - state->inst = cand_inst;
|
| - DEBUG(NaClLog(LOG_INFO, "Replace with 3DNOW opcode:\n"));
|
| - DEBUG_OR_ERASE(NaClInstPrint(NaClLogGetGio(),
|
| - state->decoder_tables,
|
| - state->inst));
|
| - }
|
| - }
|
| -
|
| - /* found a match, exit loop. */
|
| - found_match = TRUE;
|
| - continue_loop = FALSE;
|
| - state->num_opcode_bytes = inst_length - state->num_prefix_bytes;
|
| - state->opcode_prefix = cur_opcode_prefix;
|
| -
|
| - /* If an instruction has both a general form, and a (hard-coded)
|
| - * explicit opcode sequence, prefer the latter for the match.
|
| - * Note: This selection to the (hard-coded) explicit opcode
|
| - * sequence is necessary if we are to handle special nops with
|
| - * multiple prefix bytes in the x86-64 validator.
|
| - */
|
| - if (NaClMaybeHardCodedNop(state)) {
|
| - NaClConsumeHardCodedNop(state);
|
| - }
|
| - break;
|
| - } else {
|
| - /* match failed, try next candidate pattern. */
|
| - cand_insts = NaClGetOpcodeInst(state->decoder_tables,
|
| - cand_insts->next_rule);
|
| - }
|
| - }
|
| - DEBUG(if (! found_match) {
|
| - NaClLog(LOG_INFO, "no more candidates for this prefix\n");
|
| - });
|
| - }
|
| - }
|
| - }
|
| -
|
| - if (!found_match) {
|
| - /* No instruction matched. Double check that it can't be a hard-coded
|
| - * NOP instruction before we assume that we can't can accept the
|
| - * instruction.
|
| - */
|
| - if (NaClConsumeHardCodedNop(state)) return;
|
| -
|
| - /* We did not match a defined opcode, match the undefined opcode,
|
| - * forcing the inst field to be non-NULL, and to read at least one byte.
|
| - */
|
| - DEBUG(NaClLog(LOG_INFO, "no instruction found, converting to undefined\n"));
|
| - state->inst = state->decoder_tables->undefined;
|
| - if (state->bytes.length == 0 && state->bytes.length < state->length_limit) {
|
| - /* Make sure we eat at least one byte. */
|
| - NCInstBytesReadInline(&state->bytes);
|
| - }
|
| - }
|
| -}
|
| -
|
| -const NaClInst* NaClInstStateInst(NaClInstState* state) {
|
| - return state->inst;
|
| -}
|
| -
|
| -NaClPcAddress NaClInstStatePrintableAddress(NaClInstState* state) {
|
| - return state->iter->segment->vbase + state->inst_addr;
|
| -}
|
| -
|
| -NaClExpVector* NaClInstStateExpVector(NaClInstState* state) {
|
| - if (!state->nodes.is_defined) {
|
| - state->nodes.is_defined = TRUE;
|
| - NaClBuildExpVector(state);
|
| - }
|
| - return &state->nodes;
|
| -}
|
| -
|
| -Bool NaClInstStateIsValid(NaClInstState* state) {
|
| - return InstInvalid != state->inst->name;
|
| -}
|
| -
|
| -uint8_t NaClInstStateLength(NaClInstState* state) {
|
| - return state->bytes.length;
|
| -}
|
| -
|
| -uint8_t NaClInstStateByte(NaClInstState* state, uint8_t index) {
|
| - assert(index < state->bytes.length);
|
| - return state->bytes.byte[index];
|
| -}
|
| -
|
| -uint8_t NaClInstStateOperandSize(NaClInstState* state) {
|
| - return state->operand_size;
|
| -}
|
| -
|
| -uint8_t NaClInstStateAddressSize(NaClInstState* state) {
|
| - return state->address_size;
|
| -}
|
|
|