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 |