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

Side by Side Diff: src/trusted/validator/x86/decoder/generator/ncval_simplify.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 unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 /*
2 * Copyright (c) 2011 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 /*
8 * Simplifies instruction set to what is needed for the
9 * (x86-64) ncval_reg_sfi validator.
10 *
11 * There are two parts to this story. First, the decoder used by the
12 * ncval_reg_sfi validator use the decoder in:
13 * native_client/src/trusted/validator/x86/decoder
14 *
15 * This decoder is based on instruction flags. If the instruction flags
16 * are not changed, the same sequence of bytes will be parsed, independent
17 * of the instruction mnemonic. Therefore, it is safe to change the
18 * instruction mnemonic to a "don't care" name unless it is explicitly
19 * used in some rule of the validator. The static validator validator_names
20 * in function NaClNcvalSimplifyMnemonic lists all instruction mnemonics that
21 * are currently used by the validator.
22 *
23 * Secondly, the ncval_reg_sfi validator checks general purpose registers,
24 * segment registers, and memory references to make sure that data and
25 * branching have been sandboxed properly. Hence, any argument to an x86
26 * instruction that can be shown that it will never access one of these
27 * forms can be omitted without breaking the validator. Hence, this code
28 * removes all such arguments. See function NaClNcvalKeepOperand for details
29 * on what arguments are removed.
30 *
31 * Finally, for pragmatic reasons (i.e. readability), if an instruction is
32 * modified by this simplification, it is marked as a "partial instruction",
33 * so that the corresponding (ncdis) disassembler can correctly communicate
34 * that a partial match (rather than an actual instruction decoding) was applied
35 * to the given bits. The printed partial match communicates what was kept for
36 * validation purposes.
37 */
38
39 #ifndef NACL_TRUSTED_BUT_NOT_TCB
40 #error("This file is not meant for use in the TCB")
41 #endif
42
43 #include "native_client/src/trusted/validator/x86/decoder/generator/ncval_simpli fy.h"
44
45 #include <string.h>
46 #include "native_client/src/include/nacl_macros.h"
47 #include "native_client/src/trusted/validator/x86/x86_insts.h"
48 #include "native_client/src/trusted/validator/x86/decoder/generator/nc_compress. h"
49
50 /* To turn on debugging of instruction decoding, change value of
51 * DEBUGGING to 1.
52 */
53 #define DEBUGGING 0
54
55 #include "native_client/src/shared/utils/debugging.h"
56
57 /* Returns true if the data extracted by the operand may be needed
58 * for register sfi sandboxing.
59 */
60 static Bool NaClNcvalKeepOperand(NaClOp *operand) {
61 /* Operands in the ncval_seg_sfi (x86-64) validator are not inspected
62 * by the validator, unless they are general purpose register, segment
63 * registers, or memory references. The following list are all operand
64 * specifiers that can't contain any of the above, and hence, are not
65 * used by the validator. This list is used to safely determine if
66 * an operand can be removed.
67 */
68 static NaClOpKind unnecessary_opkinds[] = {
69 RegDR0, /* Debug registers. */
70 RegDR1,
71 RegDR2,
72 RegDR3,
73 RegDR4,
74 RegDR5,
75 RegDR6,
76 RegDR7,
77 RegDR8,
78 RegDR9,
79 RegDR10,
80 RegDR11,
81 RegDR12,
82 RegDR13,
83 RegDR14,
84 RegDR15,
85 RegEFLAGS, /* Program status and control registers. */
86 RegRFLAGS,
87 St_Operand, /* Floating point stack registers. */
88 RegST0,
89 RegST1,
90 RegST2,
91 RegST3,
92 RegST4,
93 RegST5,
94 RegST6,
95 RegST7,
96 Mmx_G_Operand, /* Mxx registers. */
97 Mmx_Gd_Operand,
98 RegMMX0,
99 RegMMX1,
100 RegMMX2,
101 RegMMX3,
102 RegMMX4,
103 RegMMX5,
104 RegMMX6,
105 RegMMX7,
106 Xmm_G_Operand, /* Xmm registers. */
107 Xmm_Go_Operand,
108 RegXMM0,
109 RegXMM1,
110 RegXMM2,
111 RegXMM3,
112 RegXMM4,
113 RegXMM5,
114 RegXMM6,
115 RegXMM7,
116 RegXMM8,
117 RegXMM9,
118 RegXMM10,
119 RegXMM11,
120 RegXMM12,
121 RegXMM13,
122 RegXMM14,
123 RegXMM15,
124 };
125 size_t i;
126 for (i = 0; i < NACL_ARRAY_SIZE(unnecessary_opkinds); ++i) {
127 if (operand->kind == unnecessary_opkinds[i]) return FALSE;
128 }
129 return TRUE;
130 }
131
132 /* Returns the instruction mnemonic to use for an instruction. The
133 * mnemonic is changed only if the (x86-64) ncval_reg_sfi validator
134 * doesn't need to know the corresponding instruction mnemonic.
135 */
136 static NaClMnemonic NaClNcvalSimplifyMnemonic(NaClModeledInst *inst) {
137 /* List of white listed names that must be kept for the validator,
138 * since they are used as part of the pattern checking of the validator.
139 */
140 static NaClMnemonic validator_names[] = {
141 InstAnd,
142 InstAdd,
143 InstCall,
144 InstInvalid,
145 InstLea,
146 InstMov,
147 InstOr,
148 InstPop,
149 InstPush,
150 InstSub
151 };
152 NaClMnemonic name = inst->name;
153 size_t i;
154 for (i = 0; i < NACL_ARRAY_SIZE(validator_names); ++i) {
155 if (name == validator_names[i]) return name;
156 }
157 /* If not white listed, change to dont care. */
158 if (NaClHasBit(inst->flags, NACL_IFLAG(ConditionalJump))) {
159 return InstDontCareCondJump;
160 }
161 if (NaClHasBit(inst->flags, NACL_IFLAG(JumpInstruction))) {
162 return InstDontCareJump;
163 }
164 return InstDontCare;
165 }
166
167 /* Fixes format strings used to define the instruction operand
168 * to its simplified form, by removing any implicit braces used
169 * when defining the operand for the instruction.
170 */
171 static const char* RemoveImplicitFromFormat(const char* str) {
172 size_t str_len = strlen(str);
173 if ((str_len > 0) && (str[0] == '{') && (str[str_len-1] == '}')) {
174 char* simp_str = (char*) malloc(str_len-1);
175 if (NULL == simp_str) return str; /* This should not happen. */
176 strncpy(simp_str, str+1, str_len-1);
177 simp_str[str_len-2] = '\0';
178 return simp_str;
179 }
180 return str;
181 }
182
183 /* Simplify the given instruction and return the simplified instruction,
184 * based on expectations of the (x86-64) ncval_reg_sfi validator.
185 */
186 static void NaClNcvalSimplifyInst(NaClInstTables *inst_tables,
187 NaClModeledInst *inst) {
188 size_t i;
189 NaClMnemonic simplified_name;
190 size_t fill = 0;
191 Bool is_partial = FALSE;
192
193 if (NULL == inst) return;
194
195 /* First simplify additional rules associated with the given instruction. */
196 NaClNcvalSimplifyInst(inst_tables, inst->next_rule);
197
198 /* Ignore invalid instructions. */
199 if (NACLi_INVALID == inst->insttype) return;
200
201 /* Remove unnecessary operands. */
202 if (NaClHasBit(inst->flags, NACL_IFLAG(NaClIllegal))) {
203 /* Remove all arguments. We don't need to process arguments.
204 * Validation will fail regardless.
205 */
206 inst->num_operands = 0;
207 inst->name = InstDontCare;
208 is_partial = TRUE;
209 } else {
210 /* Simplify the instruction mnemonic. */
211 simplified_name = NaClNcvalSimplifyMnemonic(inst);
212 if (simplified_name != inst->name) {
213 uint8_t num_operands;
214 inst->name = simplified_name;
215 is_partial = TRUE;
216
217 /* We have simplified the modeled instruction, and hence
218 * the modeled instruction is now a pattern, rather than'
219 * an x86 instruction. Remove operands that aren't needed,
220 * because the operand is never going to be used by the validator.
221 */
222 num_operands = inst->num_operands;
223 for (i = 0; i < num_operands; i++) {
224 if (NaClNcvalKeepOperand(&inst->operands[i])) {
225 inst->operands[fill++] = inst->operands[i];
226 } else {
227 inst->num_operands--;
228 is_partial = TRUE;
229 }
230 }
231 }
232 }
233
234 /* Check if we modified anything. If so, we need to clean
235 * up the instruction so that (all) useful information is printed
236 * by the decoder print functions (i.e. as a pattern rather than
237 * an x86 instruction).
238 */
239 if (is_partial) {
240 uint8_t num_operands = inst->num_operands;
241 NaClAddBits(inst->flags, NACL_IFLAG(PartialInstruction));
242 for (i = 0; i < num_operands; i++) {
243 if (NaClHasBit(inst->operands[i].flags, NACL_OPFLAG(OpImplicit))) {
244 NaClRemoveBits(inst->operands[i].flags, NACL_OPFLAG(OpImplicit));
245 inst->operands[i].format_string =
246 RemoveImplicitFromFormat(inst->operands[i].format_string);
247 }
248 }
249 }
250 }
251
252 /* Simplify instructions in the given trie node. */
253 static void NaClNcvalSimplifyNode(NaClInstTables *inst_tables,
254 NaClModeledInstNode* node) {
255 if (NULL == node) return;
256 NaClNcvalSimplifyInst(inst_tables, node->matching_inst);
257 NaClNcvalSimplifyNode(inst_tables, node->success);
258 NaClNcvalSimplifyNode(inst_tables, node->fail);
259 }
260
261 void NaClNcvalInstSimplify(NaClInstTables* inst_tables) {
262 int i;
263 NaClInstPrefix prefix;
264
265 /* Simplify the undefined instruction. */
266 NaClNcvalSimplifyInst(inst_tables, inst_tables->undefined_inst);
267
268 /* Simplify all instructions in the instruction opcode table. */
269 for (prefix = NoPrefix; prefix < NaClInstPrefixEnumSize; ++prefix) {
270 for (i = 0; i < NCDTABLESIZE; ++i) {
271 NaClNcvalSimplifyInst(inst_tables, inst_tables->inst_table[i][prefix]);
272 }
273 }
274
275 /* Simplify instructions in the instruction trie. */
276 NaClNcvalSimplifyNode(inst_tables, inst_tables->inst_node_root);
277 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698