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

Unified Diff: src/trusted/validator_x86/nc_inst_state_statics.c

Issue 6883091: Start unit testing for functions in nc_inst_state.c (Closed) Base URL: svn://svn.chromium.org/native_client/trunk/src/native_client/
Patch Set: '' Created 9 years, 8 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/nc_inst_state_statics.c
===================================================================
--- src/trusted/validator_x86/nc_inst_state_statics.c (revision 4929)
+++ src/trusted/validator_x86/nc_inst_state_statics.c (working copy)
@@ -5,17 +5,14 @@
*/
/*
- * 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.
+ * This 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.
*/
Brad Chen 2011/04/25 21:47:27 It would probably make sense to put in a #define p
Karl 2011/06/24 18:15:00 Done.
#include <stdio.h>
#include <assert.h>
-
-#include "native_client/src/trusted/validator_x86/nc_inst_state.h"
-
#include "native_client/src/shared/platform/nacl_log.h"
#include "native_client/src/trusted/validator_x86/nc_inst_iter.h"
#include "native_client/src/trusted/validator_x86/nc_inst_state_internal.h"
@@ -28,14 +25,12 @@
#else
#include "gen/native_client/src/trusted/validator_x86/nc_opcode_table.h"
#endif
+#include "native_client/src/trusted/validator_x86/RexPrefixes.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"
+EXTERN_C_BEGIN
+
/* Given the current location of the instruction iterator, initialize
* the given state (to match).
*/
@@ -73,22 +68,22 @@
* instruction of the given state.
*/
static int NaClExtractOpSize(NaClInstState* state) {
- if (state->inst->flags & NACL_IFLAG(OperandSize_b)) {
+ if (NaClHasBit(state->inst->flags, NACL_IFLAG(OperandSize_b))) {
return 1;
}
if (NACL_TARGET_SUBARCH == 64) {
- if ((state->rexprefix && state->rexprefix & 0x8) ||
- (state->inst->flags & NACL_IFLAG(OperandSizeForce64))) {
+ if ((state->rexprefix && NaClRexW(state->rexprefix)) ||
+ (NaClHasBit(state->inst->flags, NACL_IFLAG(OperandSizeForce64)))) {
return 8;
}
}
- if ((state->prefix_mask & kPrefixDATA16) &&
+ if (NaClHasBit(state->prefix_mask, kPrefixDATA16) &&
(NACL_EMPTY_IFLAGS ==
(state->inst->flags & NACL_IFLAG(SizeIgnoresData16)))) {
return 2;
}
if ((NACL_TARGET_SUBARCH == 64) &&
- (state->inst->flags & NACL_IFLAG(OperandSizeDefaultIs64))) {
+ NaClHasBit(state->inst->flags, NACL_IFLAG(OperandSizeDefaultIs64))) {
return 8;
}
return 4;
@@ -99,9 +94,9 @@
*/
static int NaClExtractAddressSize(NaClInstState* state) {
if (NACL_TARGET_SUBARCH == 64) {
- return (state->prefix_mask & kPrefixADDR16) ? 32 : 64;
+ return NaClHasBit(state->prefix_mask, kPrefixADDR16) ? 32 : 64;
} else {
- return (state->prefix_mask & kPrefixADDR16) ? 16 : 32;
+ return NaClHasBit(state->prefix_mask, kPrefixADDR16) ? 16 : 32;
}
}
@@ -183,28 +178,12 @@
* prefix to occur anywhere.
*/
if (rex_index >= 0) {
- return (rex_index + 1) == state->num_prefix_bytes;
+ return (Bool) ((rex_index + 1) == state->num_prefix_bytes);
}
}
return TRUE;
}
-/* Structure holding the results of consuming the opcode bytes of the
- * instruction.
- */
-typedef struct {
- /* The (last) byte of the matched opcode. */
- uint8_t opcode_byte;
- /* The most specific prefix that the opcode bytes can match
- * (or OpcodePrefixEnumSize if no such patterns exist).
- */
- NaClInstPrefix matched_prefix;
- /* The number of bytes to subtract from the instruction length,
- * the next time GetNextNaClInstCandidates is called.
- */
- uint8_t next_length_adjustment;
-} NaClInstPrefixDescriptor;
-
/* Assuming we have matched the byte sequence OF 38, consume the corresponding
* following (instruction) opcode byte, returning the most specific prefix the
* patterns can match (or NaClInstPrefixEnumSize if no such patterns exist);
@@ -220,17 +199,23 @@
}
desc->opcode_byte = NCInstBytesRead(&state->bytes);
- if (state->prefix_mask & kPrefixREPNE) {
- desc->matched_prefix = PrefixF20F38;
+ DEBUG(NaClLog(LOG_INFO, "Consume inst byte %02"NACL_PRIx8".\n",
+ desc->opcode_byte));
+ if (NaClExcludesBit(state->prefix_mask, kPrefixREP)) {
+ if (NaClHasBit(state->prefix_mask, kPrefixREPNE)) {
+ /* Note: Flag OpcodeAllowsData16 will explicitly clarify
+ * ambigous case of both REP and DATA16 prefixes.
+ */
+ desc->matched_prefix = PrefixF20F38;
+ } else if (NaClHasBit(state->prefix_mask, kPrefixDATA16)) {
+ desc->matched_prefix = Prefix660F38;
+ } else {
+ desc->matched_prefix = Prefix0F38;
+ }
+ return;
}
- else if (state->prefix_mask & kPrefixDATA16) {
- desc->matched_prefix = Prefix660F38;
- } else if ((state->prefix_mask & ~kPrefixREX) == 0) {
- desc->matched_prefix = Prefix0F38;
- } else {
- /* Other prefixes like F3 cause an undefined instruction error. */
- desc->matched_prefix = NaClInstPrefixEnumSize;
- }
+ /* If reached, can't match special prefixes, fail. */
+ desc->matched_prefix = NaClInstPrefixEnumSize;
}
/* Assuming we have matched the byte sequence OF 3A, consume the corresponding
@@ -248,14 +233,19 @@
}
desc->opcode_byte = NCInstBytesRead(&state->bytes);
- if (state->prefix_mask & kPrefixDATA16) {
- desc->matched_prefix = Prefix660F3A;
- } else if ((state->prefix_mask & ~kPrefixREX) == 0) {
- desc->matched_prefix = Prefix0F3A;
- } else {
- /* Other prefixes like F3 cause an undefined instruction error. */
- desc->matched_prefix = NaClInstPrefixEnumSize;
+ DEBUG(NaClLog(LOG_INFO, "Consume inst byte %02"NACL_PRIx8".\n",
+ desc->opcode_byte));
+ if (NaClExcludesBit(state->prefix_mask, kPrefixREP) &&
+ NaClExcludesBit(state->prefix_mask, kPrefixREPNE)) {
+ if (NaClHasBit(state->prefix_mask, kPrefixDATA16)) {
+ desc->matched_prefix = Prefix660F3A;
+ } else {
+ desc->matched_prefix = Prefix0F3A;
+ }
+ return;
}
+ /* If reached, can't match special prefixes, fail. */
+ desc->matched_prefix = NaClInstPrefixEnumSize;
}
/* Assuming we have matched byte OF, consume the corresponding
@@ -265,15 +255,29 @@
*/
static void NaClConsume0FXXNaClInstBytes(NaClInstState* state,
NaClInstPrefixDescriptor* desc) {
- if (state->prefix_mask & kPrefixREPNE) {
- desc->matched_prefix = PrefixF20F;
- } else if (state->prefix_mask & kPrefixREP) {
- desc->matched_prefix = PrefixF30F;
- } else if (state->prefix_mask & kPrefixDATA16) {
- desc->matched_prefix = Prefix660F;
+ if (NaClHasBit(state->prefix_mask, kPrefixREPNE)) {
+ if (NaClExcludesBit(state->prefix_mask, kPrefixREP)) {
+ /* Note: Flag OpcodeAllowsData16 will explicitly clarify
+ * ambigous case of both REPNE and DATA16 prefixes.
+ */
+ desc->matched_prefix = PrefixF20F;
+ return;
+ }
} else {
- desc->matched_prefix = Prefix0F;
+ if (NaClHasBit(state->prefix_mask, kPrefixREP)) {
+ /* Note: Flag OpcodeAllowsData16 will explicitly clarify
+ * ambigous case of both REP and DATA16 prefixes.
+ */
+ desc->matched_prefix = PrefixF30F;
+ } else if (NaClHasBit(state->prefix_mask, kPrefixDATA16)) {
+ desc->matched_prefix = Prefix660F;
+ } else {
+ desc->matched_prefix = Prefix0F;
+ }
+ return;
}
+ /* If reached, can't match special prefixes, fail. */
+ desc->matched_prefix = NaClInstPrefixEnumSize;
}
/* Consume one of the x87 instructions that begin with D8-Df, and
@@ -283,9 +287,12 @@
NaClInstPrefixDescriptor* desc) {
if (state->bytes.length < state->length_limit) {
/* Can be two byte opcode. */
- desc->matched_prefix = PrefixD8 +
- (((unsigned) desc->opcode_byte) - 0xD8);
+ desc->matched_prefix =
+ (NaClInstPrefix) (PrefixD8 +
+ (((unsigned) desc->opcode_byte) - 0xD8));
desc->opcode_byte = NCInstBytesRead(&state->bytes);
+ DEBUG(NaClLog(LOG_INFO, "Consume inst byte %02"NACL_PRIx8".\n",
+ desc->opcode_byte));
return;
}
@@ -309,10 +316,14 @@
if (state->bytes.length >= state->length_limit) return;
desc->opcode_byte = NCInstBytesRead(&state->bytes);
+ DEBUG(NaClLog(LOG_INFO, "Consume inst byte %02"NACL_PRIx8".\n",
+ desc->opcode_byte));
switch (desc->opcode_byte) {
case 0x0F:
if (state->bytes.length >= state->length_limit) return;
desc->opcode_byte = NCInstBytesRead(&state->bytes);
+ DEBUG(NaClLog(LOG_INFO, "Consume inst byte %02"NACL_PRIx8".\n",
+ desc->opcode_byte));
switch (desc->opcode_byte) {
case 0x38:
NaClConsume0F38XXNaClInstBytes(state, desc);
@@ -358,13 +369,13 @@
NaClIFlags good = 1;
switch (state->operand_size) {
case 2:
- good = (state->inst->flags & NACL_IFLAG(OperandSize_w));
+ good = NaClHasBit(state->inst->flags, NACL_IFLAG(OperandSize_w));
break;
case 4:
- good = (state->inst->flags & NACL_IFLAG(OperandSize_v));
+ good = NaClHasBit(state->inst->flags, NACL_IFLAG(OperandSize_v));
break;
case 8:
- good = (state->inst->flags & NACL_IFLAG(OperandSize_o));
+ good = NaClHasBit(state->inst->flags, NACL_IFLAG(OperandSize_o));
break;
default:
good = 0;
@@ -394,13 +405,13 @@
NaClIFlags good = 1;
switch (state->address_size) {
case 16:
- good = (state->inst->flags & NACL_IFLAG(AddressSize_w));
+ good = NaClHasBit(state->inst->flags, NACL_IFLAG(AddressSize_w));
break;
case 32:
- good = (state->inst->flags & NACL_IFLAG(AddressSize_v));
+ good = NaClHasBit(state->inst->flags, NACL_IFLAG(AddressSize_v));
break;
case 64:
- good = (state->inst->flags & NACL_IFLAG(AddressSize_o));
+ good = NaClHasBit(state->inst->flags, NACL_IFLAG(AddressSize_o));
break;
default:
good = 0;
@@ -422,7 +433,7 @@
/* Returns true if the instruction requires a ModRm bytes. */
static Bool NaClInstRequiresModRm(NaClInstState* state) {
- return
+ return (Bool)
(NACL_EMPTY_IFLAGS !=
(state->inst->flags & NACL_IFLAG(OpcodeUsesModRm)));
}
@@ -448,17 +459,17 @@
* is 0x3. Others only allow values where the ModRm mod field isn't 0x3.
*/
if (modrm_mod(byte) == 0x3) {
- if (state->inst->flags & NACL_IFLAG(ModRmModIsnt0x3)) {
+ if (NaClHasBit(state->inst->flags, NACL_IFLAG(ModRmModIsnt0x3))) {
DEBUG(NaClLog(LOG_INFO, "Can't match, modrm mod field is 0x3\n"));
return FALSE;
}
} else {
- if (state->inst->flags & NACL_IFLAG(ModRmModIs0x3)) {
+ if (NaClHasBit(state->inst->flags, NACL_IFLAG(ModRmModIs0x3))) {
DEBUG(NaClLog(LOG_INFO, "Can't match, modrm mod field not 0x3\n"));
return FALSE;
}
}
- if ((state->inst->flags & NACL_IFLAG(ModRmRegSOperand)) &&
+ if ((NaClHasBit(state->inst->flags, NACL_IFLAG(ModRmRegSOperand))) &&
(modrm_reg(byte) > 5)) {
DEBUG(NaClLog(LOG_INFO,
"Can't match, modrm reg field doesn't index segment\n"));
@@ -505,8 +516,9 @@
* addressing. Hence, required for all but 16-bit addressing, when
* the right modrm bytes are specified.
*/
- return NaClInstRequiresModRm(state) && (16 != state->address_size) &&
- (modrm_rm(state->modrm) == 0x04 && modrm_mod(state->modrm) != 0x3);
+ return (Bool)
+ (NaClInstRequiresModRm(state) && (16 != state->address_size) &&
+ (modrm_rm(state->modrm) == 0x04 && modrm_mod(state->modrm) != 0x3));
}
/* Consume the SIB byte of the instruction, if applicable. Aborts the pattern
@@ -861,151 +873,4 @@
}
}
-/* 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 opcode_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 (NaClConsumeOpcodeSequence(state)) {
- found_match = TRUE;
- } else if (NaClConsumePrefixBytes(state)) {
- NaClInstPrefixDescriptor prefix_desc;
- Bool continue_loop = TRUE;
- NaClConsumeInstBytes(state, &prefix_desc);
- opcode_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 {
- cand_insts = NaClGetNextInstCandidates(state, &prefix_desc,
- &opcode_length);
- while (cand_insts != NULL) {
- NaClClearInstState(state, opcode_length);
- state->inst = cand_insts;
- DEBUG(NaClLog(LOG_INFO, "try opcode pattern:\n"));
- DEBUG(NaClInstPrint(NaClLogGetGio(), 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 = g_OpcodeTable[Prefix0F0F][opcode_byte];
- if (NULL != cand_inst) {
- state->inst = cand_inst;
- DEBUG(NaClLog(LOG_INFO, "Replace with 3DNOW opcode:\n"));
- DEBUG(NaClInstPrint(NaClLogGetGio(), state->inst));
- }
- }
- /* found a match, exit loop. */
- found_match = TRUE;
- continue_loop = FALSE;
- break;
- } else {
- /* match failed, try next candidate pattern. */
- cand_insts = cand_insts->next_rule;
- }
- }
- DEBUG(if (! found_match) {
- NaClLog(LOG_INFO, "no more candidates for this prefix\n");
- });
- }
- }
- }
-
- /* If we did not match a defined opcode, match the undefined opcode,
- * forcing field opcode to be non-NULL.
- */
- if (!found_match) {
- DEBUG(NaClLog(LOG_INFO, "no instruction found, converting to undefined\n"));
-
- /* Can't figure out instruction, give up. */
- NaClClearInstState(state, opcode_length);
- state->inst = &g_Undefined_Opcode;
- if (state->bytes.length == 0 && state->bytes.length < state->length_limit) {
- /* Make sure we eat at least one byte. */
- NCInstBytesRead(&state->bytes);
- }
- }
-}
-
-const NaClInst* NaClInstStateInst(NaClInstState* state) {
- return state->inst;
-}
-
-NaClPcAddress NaClInstStateVpc(NaClInstState* state) {
- return state->vpc;
-}
-
-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;
-}
-
-void NaClChangeOpcodesToXedsModel() {
- /* Changes opcodes to match xed. That is change:
- * 0f0f..1c: Pf2iw $Pq, $Qq => 0f0f..2c: Pf2iw $Pq, $Qq
- * 0f0f..1d: Pf2id $Pq, $Qq => 0f0f..2d: Pf2id $Pq, $Qq
- */
- g_OpcodeTable[Prefix0F0F][0x2c] = g_OpcodeTable[Prefix0F0F][0x1c];
- g_OpcodeTable[Prefix0F0F][0x1c] = NULL;
- g_OpcodeTable[Prefix0F0F][0x2d] = g_OpcodeTable[Prefix0F0F][0x1d];
- g_OpcodeTable[Prefix0F0F][0x1d] = NULL;
-}
+EXTERN_C_END

Powered by Google App Engine
This is Rietveld 408576698