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

Side by Side Diff: src/trusted/validator/x86/decoder/nc_inst_state.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) 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 /*
8 * Defines an instruction (decoder), based on the current location of
9 * the instruction iterator. The instruction decoder takes a list
10 * of candidate opcode (instruction) patterns, and searches for the
11 * first candidate that matches the requirements of the opcode pattern.
12 */
13
14 #include "native_client/src/trusted/validator/x86/decoder/nc_inst_state.h"
15
16 /* To turn on debugging of instruction decoding, change value of
17 * DEBUGGING to 1.
18 */
19 #define DEBUGGING 0
20
21 /*
22 * This .c file contains includes, static functions, and constants that are used
23 * in nc_inst_state.c, but have been factored out and put into this file, so
24 * that we can test them. That is, to allow nc_inst_state.c and
25 * nc_inst_state_Tests.cc to use them.
26 */
27 #include "native_client/src/trusted/validator/x86/decoder/nc_inst_state_statics. c"
28
29 /* Returns true if the parsed instruction may be replaceable with a (hard coded)
30 * opcode sequence. Used to prefer hard-coded opcode sequences over general
31 * matches. These hard-coded opcode sequences are special nop opcode sequences,
32 * most of which are generated by compilers and linkers. The need for these
33 * hard-coded sequences is to accept nops with prefixes that would not otherwise
34 * be accepted (such as "6666666666662e0f1f840000000000").
35 */
36 static Bool NaClMaybeHardCodedNop(NaClInstState* state) {
37 /* Note: This code is based on the hard-coded instructions
38 * defined in function NaClDefNops in
39 * src/trusted/validator_x86/ncdecode_tablegen.c.
40 * If you change the hard-coded instructions defined in this
41 * function, be sure that this predicate is updated accordingly to
42 * return true for all such hard-coded instructions (it can
43 * return true on other instructions without breaking the validator).
44 */
45
46 /* Check the first opcode byte to see if it is a special case. */
47 switch (state->bytes.byte[state->num_prefix_bytes]) {
48 case 0x90:
49 /* If the first opcode byte is 90, it can be the NOP instruction.
50 * Return true that this can be a nop.
51 */
52 if (state->num_opcode_bytes == 1) return TRUE;
53 break;
54 case 0x0f:
55 /* Check that the second opcode byte is 1F or 0B. That is,
56 * can the instruction be a NOP (0f1f) or the UD2 instruction.
57 */
58 if (state->num_opcode_bytes == 2) {
59 uint8_t opcode_2 =
60 state->bytes.byte[state->num_prefix_bytes + 1];
61 if ((opcode_2 == 0x1f) || (opcode_2 == 0x0b)) return TRUE;
62 }
63 break;
64 default:
65 break;
66 }
67 /* If reached, can't be a (hard-coded) NOP instruction. */
68 return FALSE;
69 }
70
71 /* Given the current location of the (relative) pc of the given instruction
72 * iterator, update the given state to hold the (found) matched opcode
73 * (instruction) pattern. If no matching pattern exists, set the state
74 * to a matched undefined opcode (instruction) pattern. In all cases,
75 * update the state to hold all information on the matched bytes of the
76 * instruction. Note: The iterator expects that the opcode field is
77 * changed from NULL to non-NULL by this fuction.
78 */
79 void NaClDecodeInst(NaClInstIter* iter, NaClInstState* state) {
80 uint8_t inst_length = 0;
81 const NaClInst* cand_insts;
82 Bool found_match = FALSE;
83
84 /* Start by consuming the prefix bytes, and getting the possible
85 * candidate opcode (instruction) patterns that can match, based
86 * on the consumed opcode bytes.
87 */
88 NaClInstStateInit(iter, state);
89 if (NaClConsumePrefixBytes(state)) {
90 NaClInstPrefixDescriptor prefix_desc;
91 Bool continue_loop = TRUE;
92 NaClConsumeInstBytes(state, &prefix_desc);
93 inst_length = state->bytes.length;
94 while (continue_loop) {
95 /* Try matching all possible candidates, in the order they are specified
96 * (from the most specific prefix match, to the least specific prefix
97 * match). Quit when the first pattern is matched.
98 */
99 if (prefix_desc.matched_prefix == NaClInstPrefixEnumSize) {
100 continue_loop = FALSE;
101 } else {
102 uint8_t cur_opcode_prefix = prefix_desc.opcode_prefix;
103 cand_insts = NaClGetNextInstCandidates(state, &prefix_desc,
104 &inst_length);
105 while (cand_insts != NULL) {
106 NaClClearInstState(state, inst_length);
107 state->inst = cand_insts;
108 DEBUG(NaClLog(LOG_INFO, "try opcode pattern:\n"));
109 DEBUG_OR_ERASE(NaClInstPrint(NaClLogGetGio(), state->decoder_tables,
110 state->inst));
111 if (NaClConsumeAndCheckOperandSize(state) &&
112 NaClConsumeAndCheckAddressSize(state) &&
113 NaClConsumeModRm(state) &&
114 NaClConsumeSib(state) &&
115 NaClConsumeDispBytes(state) &&
116 NaClConsumeImmediateBytes(state) &&
117 NaClValidatePrefixFlags(state)) {
118 if (state->inst->flags & NACL_IFLAG(Opcode0F0F) &&
119 /* Note: If all of the above code worked correctly,
120 * there should be no need for the following test.
121 * However, just to be safe, it is added.
122 */
123 (state->num_imm_bytes == 1)) {
124 /* Special 3DNOW instructions where opcode is in parsed
125 * immediate byte at end of instruction. Look up in table,
126 * and replace if found. Otherwise, let the default 0F0F lookup
127 * act as the matching (invalid) instruction.
128 */
129 const NaClInst* cand_inst;
130 uint8_t opcode_byte = state->bytes.byte[state->first_imm_byte];
131 DEBUG(NaClLog(LOG_INFO,
132 "NaClConsume immediate byte opcode char: %"
133 NACL_PRIx8"\n", opcode_byte));
134 cand_inst = NaClGetPrefixOpcodeInst(state->decoder_tables,
135 Prefix0F0F, opcode_byte);
136 if (NULL != cand_inst) {
137 state->inst = cand_inst;
138 DEBUG(NaClLog(LOG_INFO, "Replace with 3DNOW opcode:\n"));
139 DEBUG_OR_ERASE(NaClInstPrint(NaClLogGetGio(),
140 state->decoder_tables,
141 state->inst));
142 }
143 }
144
145 /* found a match, exit loop. */
146 found_match = TRUE;
147 continue_loop = FALSE;
148 state->num_opcode_bytes = inst_length - state->num_prefix_bytes;
149 state->opcode_prefix = cur_opcode_prefix;
150
151 /* If an instruction has both a general form, and a (hard-coded)
152 * explicit opcode sequence, prefer the latter for the match.
153 * Note: This selection to the (hard-coded) explicit opcode
154 * sequence is necessary if we are to handle special nops with
155 * multiple prefix bytes in the x86-64 validator.
156 */
157 if (NaClMaybeHardCodedNop(state)) {
158 NaClConsumeHardCodedNop(state);
159 }
160 break;
161 } else {
162 /* match failed, try next candidate pattern. */
163 cand_insts = NaClGetOpcodeInst(state->decoder_tables,
164 cand_insts->next_rule);
165 }
166 }
167 DEBUG(if (! found_match) {
168 NaClLog(LOG_INFO, "no more candidates for this prefix\n");
169 });
170 }
171 }
172 }
173
174 if (!found_match) {
175 /* No instruction matched. Double check that it can't be a hard-coded
176 * NOP instruction before we assume that we can't can accept the
177 * instruction.
178 */
179 if (NaClConsumeHardCodedNop(state)) return;
180
181 /* We did not match a defined opcode, match the undefined opcode,
182 * forcing the inst field to be non-NULL, and to read at least one byte.
183 */
184 DEBUG(NaClLog(LOG_INFO, "no instruction found, converting to undefined\n"));
185 state->inst = state->decoder_tables->undefined;
186 if (state->bytes.length == 0 && state->bytes.length < state->length_limit) {
187 /* Make sure we eat at least one byte. */
188 NCInstBytesReadInline(&state->bytes);
189 }
190 }
191 }
192
193 const NaClInst* NaClInstStateInst(NaClInstState* state) {
194 return state->inst;
195 }
196
197 NaClPcAddress NaClInstStatePrintableAddress(NaClInstState* state) {
198 return state->iter->segment->vbase + state->inst_addr;
199 }
200
201 NaClExpVector* NaClInstStateExpVector(NaClInstState* state) {
202 if (!state->nodes.is_defined) {
203 state->nodes.is_defined = TRUE;
204 NaClBuildExpVector(state);
205 }
206 return &state->nodes;
207 }
208
209 Bool NaClInstStateIsValid(NaClInstState* state) {
210 return InstInvalid != state->inst->name;
211 }
212
213 uint8_t NaClInstStateLength(NaClInstState* state) {
214 return state->bytes.length;
215 }
216
217 uint8_t NaClInstStateByte(NaClInstState* state, uint8_t index) {
218 assert(index < state->bytes.length);
219 return state->bytes.byte[index];
220 }
221
222 uint8_t NaClInstStateOperandSize(NaClInstState* state) {
223 return state->operand_size;
224 }
225
226 uint8_t NaClInstStateAddressSize(NaClInstState* state) {
227 return state->address_size;
228 }
OLDNEW
« no previous file with comments | « src/trusted/validator/x86/decoder/nc_inst_state.h ('k') | src/trusted/validator/x86/decoder/nc_inst_state_internal.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698