| OLD | NEW |
| (Empty) |
| 1 /* | |
| 2 * Copyright (c) 2012 The Native Client Authors. All rights reserved. | |
| 3 * Use of this source code is governed by a BSD-style license that can be | |
| 4 * found in the LICENSE file. | |
| 5 */ | |
| 6 | |
| 7 /* Some useful utilities for validator patterns. */ | |
| 8 | |
| 9 #include "native_client/src/trusted/validator/x86/ncval_reg_sfi/ncvalidate_utils
.h" | |
| 10 | |
| 11 #include "native_client/src/include/portability_io.h" | |
| 12 #include "native_client/src/shared/platform/nacl_log.h" | |
| 13 #include "native_client/src/trusted/validator/x86/decoder/nc_decode_tables.h" | |
| 14 #include "native_client/src/trusted/validator/x86/decoder/nc_inst_iter.h" | |
| 15 #include "native_client/src/trusted/validator/x86/decoder/nc_inst_state_internal
.h" | |
| 16 #include "native_client/src/trusted/validator/x86/decoder/nc_inst_trans.h" | |
| 17 #include "native_client/src/trusted/validator/x86/ncval_reg_sfi/ncvalidate_iter.
h" | |
| 18 #include "native_client/src/trusted/validator/x86/ncval_reg_sfi/ncvalidate_iter_
internal.h" | |
| 19 | |
| 20 /* To turn on debugging of instruction decoding, change value of | |
| 21 * DEBUGGING to 1. | |
| 22 */ | |
| 23 #define DEBUGGING 0 | |
| 24 | |
| 25 #include "native_client/src/shared/utils/debugging.h" | |
| 26 | |
| 27 #include "native_client/src/trusted/validator/x86/decoder/ncopcode_desc_inl.c" | |
| 28 #include "native_client/src/trusted/validator/x86/decoder/ncop_exps_inl.c" | |
| 29 #include "native_client/src/trusted/validator/x86/decoder/nc_inst_iter_inl.c" | |
| 30 | |
| 31 const NaClOpFlags NaClOpSetOrUse = NACL_OPFLAG(OpSet) | NACL_OPFLAG(OpUse); | |
| 32 | |
| 33 Bool NaClIsBinaryUsingRegisters(const NaClInst* inst, | |
| 34 NaClMnemonic name, | |
| 35 NaClExpVector* vector, | |
| 36 NaClOpKind reg_1, | |
| 37 NaClOpKind reg_2) { | |
| 38 return name == inst->name && | |
| 39 2 == NaClGetInstNumberOperandsInline(inst) && | |
| 40 /* Note: Since the vector contains a list of operand expressions, the | |
| 41 * first operand reference is always at index zero, and its first child | |
| 42 * (where the register would be defined) is at index 1. | |
| 43 */ | |
| 44 ExprRegister == vector->node[1].kind && | |
| 45 reg_1 == NaClGetExpRegisterInline(&vector->node[1]) && | |
| 46 /* Note: Since the first subtree is a register operand, it uses | |
| 47 * nodes 0 and 1 in the vector (node 0 is the operand reference, and | |
| 48 * node 1 is its child defining a register value). The second operand | |
| 49 * reference therefore lies at node 2, and if the operand is defined by | |
| 50 * a register, it is the first kid of node 2, which is node 3. | |
| 51 */ | |
| 52 ExprRegister == vector->node[3].kind && | |
| 53 reg_2 == NaClGetExpRegisterInline(&vector->node[3]); | |
| 54 } | |
| 55 | |
| 56 Bool NaClIsMovUsingRegisters(const NaClDecodeTables* tables, | |
| 57 const NaClInst* inst, | |
| 58 NaClExpVector* vector, | |
| 59 NaClOpKind reg_set, | |
| 60 NaClOpKind reg_use) { | |
| 61 return NaClIsBinaryUsingRegisters(inst, InstMov, vector, reg_set, reg_use) && | |
| 62 NACL_OPFLAG(OpSet) == | |
| 63 (NaClGetInstOperandInline(tables, inst, 0)->flags & NaClOpSetOrUse) && | |
| 64 NACL_OPFLAG(OpUse) == | |
| 65 (NaClGetInstOperandInline(tables, inst, 1)->flags & NaClOpSetOrUse); | |
| 66 } | |
| 67 | |
| 68 Bool NaClIsBinarySetUsingRegisters(const NaClDecodeTables* tables, | |
| 69 const NaClInst* inst, | |
| 70 NaClMnemonic name, | |
| 71 NaClExpVector* vector, | |
| 72 NaClOpKind reg_1, | |
| 73 NaClOpKind reg_2) { | |
| 74 return NaClIsBinaryUsingRegisters(inst, name, vector, reg_1, reg_2) && | |
| 75 NaClOpSetOrUse == | |
| 76 (NaClGetInstOperandInline(tables, inst, 0)->flags & NaClOpSetOrUse) && | |
| 77 NACL_OPFLAG(OpUse) == | |
| 78 (NaClGetInstOperandInline(tables, inst, 1)->flags & NaClOpSetOrUse); | |
| 79 } | |
| 80 | |
| 81 Bool NaClOperandOneIsRegisterSet(NaClInstState* inst, | |
| 82 NaClOpKind reg_name) { | |
| 83 /* Note: Since the vector contains a list of operand expressions, the | |
| 84 * first operand reference is always at index zero, and its first child | |
| 85 * (where the register would be defined) is at index 1. | |
| 86 */ | |
| 87 Bool result = FALSE; | |
| 88 NaClExpVector* vector = NaClInstStateExpVector(inst); | |
| 89 DEBUG(NaClLog(LOG_INFO, | |
| 90 "->NaClOperandOneIsRegisterSet %s\n", | |
| 91 NaClOpKindName(reg_name))); | |
| 92 DEBUG(NaClExpVectorPrint(NaClLogGetGio(), inst)); | |
| 93 if (vector->number_expr_nodes >= 2) { | |
| 94 NaClExp* op_reg = &vector->node[1]; | |
| 95 result = (ExprRegister == op_reg->kind && | |
| 96 reg_name == NaClGetExpRegisterInline(op_reg) && | |
| 97 (op_reg->flags & NACL_EFLAG(ExprSet))); | |
| 98 } | |
| 99 DEBUG(NaClLog(LOG_INFO, | |
| 100 "<-NaClOperandOneIsRegisterSet = %"NACL_PRIdBool"\n", result)); | |
| 101 return result; | |
| 102 } | |
| 103 | |
| 104 Bool NaClOperandOneZeroExtends(NaClInstState* state) { | |
| 105 Bool result = FALSE; | |
| 106 const NaClInst* inst = NaClInstStateInst(state); | |
| 107 DEBUG(NaClLog(LOG_INFO, "->NaClOperandOneZeroExtends\n")); | |
| 108 DEBUG_OR_ERASE(NaClInstPrint(NaClLogGetGio(), state->decoder_tables, inst)); | |
| 109 result = (1 <= NaClGetInstNumberOperandsInline(inst) && | |
| 110 (NaClGetInstOperandInline(state->decoder_tables, inst, 0)->flags & | |
| 111 NACL_OPFLAG(OperandZeroExtends_v)) && | |
| 112 4 == NaClInstStateOperandSize(state)); | |
| 113 DEBUG(NaClLog(LOG_INFO, | |
| 114 "<-NcOPerandOneZeroExtends = %"NACL_PRIdBool"\n", result)); | |
| 115 return result; | |
| 116 } | |
| 117 | |
| 118 static INLINE Bool NaClAssignsRegisterWithZeroExtends(NaClInstState* state, | |
| 119 NaClOpKind reg_name) { | |
| 120 return NaClOperandOneIsRegisterSet(state, reg_name) && | |
| 121 NaClOperandOneZeroExtends(state); | |
| 122 } | |
| 123 | |
| 124 Bool NaClAssignsRegisterWithZeroExtends32( | |
| 125 struct NaClValidatorState* state, | |
| 126 size_t distance, | |
| 127 NaClOpKind reg32) { | |
| 128 Bool result = FALSE; | |
| 129 DEBUG(NaClLog(LOG_INFO, "zero extend precond? %s %u\n", | |
| 130 NaClOpKindName(reg32), (unsigned) distance)); | |
| 131 #ifdef NCVAL_TESTING | |
| 132 /* Assume we match previous instructions when generating pre/post | |
| 133 * conditions. | |
| 134 */ | |
| 135 if (distance > 0) return TRUE; | |
| 136 #endif | |
| 137 | |
| 138 if (NaClInstIterHasLookbackStateInline(state->cur_iter, distance)) { | |
| 139 result = NaClAssignsRegisterWithZeroExtends( | |
| 140 NaClInstIterGetLookbackStateInline(state->cur_iter, distance), reg32); | |
| 141 } | |
| 142 | |
| 143 DEBUG(if (result) | |
| 144 NaClValidatorMessage( | |
| 145 LOG_INFO, state, "zero extends = %d\n", result)); | |
| 146 return result; | |
| 147 } | |
| 148 | |
| 149 Bool NaClAssignsRegisterWithZeroExtends64( | |
| 150 struct NaClValidatorState* state, | |
| 151 size_t distance, | |
| 152 NaClOpKind reg64) { | |
| 153 NaClOpKind reg32 = NaClGet32For64BitReg(reg64); | |
| 154 return (RegUnknown != reg32) && | |
| 155 NaClAssignsRegisterWithZeroExtends32(state, distance, reg32); | |
| 156 } | |
| OLD | NEW |