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 : * ncdecode.h - table driven decoder for Native Client.
9 : *
10 : * This header file contains type declarations and constants
11 : * used by the decoder input table
12 : */
13 : #ifndef NATIVE_CLIENT_SRC_TRUSTED_VALIDATOR_X86_NCVAL_SEG_SFI_NCDECODE_H_
14 : #define NATIVE_CLIENT_SRC_TRUSTED_VALIDATOR_X86_NCVAL_SEG_SFI_NCDECODE_H_
15 :
16 : #include "native_client/src/shared/utils/types.h"
17 : #include "native_client/src/trusted/validator/x86/error_reporter.h"
18 : #include "native_client/src/trusted/validator/x86/ncinstbuffer.h"
19 : #include "native_client/src/trusted/validator/x86/x86_insts.h"
20 :
21 : EXTERN_C_BEGIN
22 :
23 : struct NCDecoderInst;
24 : struct NCDecoderState;
25 :
26 : /* Function type for a decoder action. Returns TRUE if action
27 : * was applied successfully.
28 : */
29 : typedef Bool (*NCDecoderStateAction)(const struct NCDecoderInst* dinst);
30 :
31 : /* Function type for other decoder state methods. */
32 : typedef void (*NCDecoderStateMethod)(struct NCDecoderState* vstate);
33 :
34 : typedef enum {
35 : NOGROUP = 0,
36 : GROUP1,
37 : GROUP2,
38 : GROUP3,
39 : GROUP4,
40 : /* these comments facilitate counting */
41 : GROUP5,
42 : GROUP6,
43 : GROUP7,
44 : GROUP8,
45 : GROUP9,
46 : /* these comments facilitate counting */
47 : GROUP10,
48 : GROUP11,
49 : GROUP12,
50 : GROUP13,
51 : GROUP14,
52 : /* these comments facilitate counting */
53 : GROUP15,
54 : GROUP16,
55 : GROUP17,
56 : GROUP1A,
57 : GROUPP
58 : } NaClMRMGroups;
59 : /* kModRMOpcodeGroups doesn't work as a const int since it is used */
60 : /* as an array dimension */
61 : #define kNaClMRMGroupsRange 20
62 :
63 : /* Define the maximum value that can be encoded in the modrm mod field. */
64 : #define kModRMOpcodeGroupSize 8
65 :
66 : /* Define the maximum register value that can be encoded into the opcode
67 : * byte.
68 : */
69 : #define kMaxRegisterIndexInOpcode 7
70 :
71 : /* information derived from the opcode, wherever it happens to be */
72 : typedef enum {
73 : IMM_UNKNOWN = 0,
74 : IMM_NONE = 1,
75 : IMM_FIXED1 = 2,
76 : IMM_FIXED2 = 3,
77 : IMM_FIXED3 = 4,
78 : IMM_FIXED4 = 5,
79 : IMM_DATAV = 6,
80 : IMM_ADDRV = 7,
81 : IMM_GROUP3_F6 = 8,
82 : IMM_GROUP3_F7 = 9,
83 : IMM_FARPTR = 10,
84 : IMM_MOV_DATAV, /* Special case for 64-bits MOVs (b8 through bf). */
85 : /* Don't add to this enum without update kNCDecodeImmediateTypeRange */
86 : /* and updating the tables below which are sized using this constant */
87 : } NCDecodeImmediateType;
88 : #define kNCDecodeImmediateTypeRange 12
89 :
90 : /* 255 will force an error */
91 : static const uint8_t kImmTypeToSize66[kNCDecodeImmediateTypeRange] =
92 : { 0, 0, 1, 2, 3, 4, 2, (NACL_TARGET_SUBARCH == 64 ? 8 : 4), 0, 0, 6, 2};
93 : static const uint8_t kImmTypeToSize67[kNCDecodeImmediateTypeRange] =
94 : { 0, 0, 1, 2, 3, 4, 4, 2, 0, 0, 4, 4};
95 : static const uint8_t kImmTypeToSize[kNCDecodeImmediateTypeRange] =
96 : { 0, 0, 1, 2, 3, 4, 4, (NACL_TARGET_SUBARCH == 64 ? 8 : 4), 0, 0, 6, 4 };
97 :
98 : /* Defines how to decode operands for byte codes. */
99 : typedef enum {
100 : /* Assume the default size of the operands is 64-bits (if
101 : * not specified in prefix bits).
102 : */
103 : DECODE_OPS_DEFAULT_64,
104 : /* Assume the default size of the operands is 32-bits (if
105 : * not specified in prefix bits).
106 : */
107 : DECODE_OPS_DEFAULT_32,
108 : /* Force the size of the operands to 64 bits (prefix bits are
109 : * ignored).
110 : */
111 : DECODE_OPS_FORCE_64
112 : } DecodeOpsKind;
113 :
114 : /* Models information on an x86-32 bit instruction. */
115 : struct OpInfo {
116 : NaClInstType insttype;
117 : uint8_t hasmrmbyte; /* 1 if this inst has an mrm byte, else 0 */
118 : uint8_t immtype; /* IMM_NONE, IMM_FIXED1, etc. */
119 : uint8_t opinmrm; /* set to 1..8 if you must find opcode in MRM byte */
120 : };
121 :
122 : /* Models a node in a trie of NOP instructions. */
123 : typedef struct NCNopTrieNode {
124 : /* The matching byte for the trie node. */
125 : uint8_t matching_byte;
126 : /* The matching modeled nop, if byte matched. */
127 : struct OpInfo *matching_opinfo;
128 : /* Node to match remaining bytes. */
129 : struct NCNopTrieNode* success;
130 : /* Node to match remaining bytes. */
131 : struct NCNopTrieNode* fail;
132 : } NCNopTrieNode;
133 :
134 : /* Predefined value to communicate that the lock prefix was not
135 : * found in an instruction.
136 : */
137 : static const uint8_t kNoLockPrefixIndex = 0xFF;
138 :
139 : /* Models a parsed x86-32 bit instruction. */
140 : struct InstInfo {
141 : /* The bytes used to parse the x86-32 instruction (may have added
142 : * zero filler if the instruction straddles the memory segment).
143 : */
144 : NCInstBytes bytes;
145 : /* The number of prefix bytes in the instruction. */
146 : uint8_t prefixbytes; /* 0..4 */
147 : /* Number of opcode bytes in the instruction. */
148 : uint8_t num_opbytes;
149 : /* non-zero if the instruction contains an SIB byte. */
150 : uint8_t hassibbyte;
151 : /* The ModRm byte. */
152 : uint8_t mrm;
153 : /* A NCDecodeImmediateType describing the type of immediate value(s)
154 : * the instruction has.
155 : */
156 : uint8_t immtype;
157 : /* The number of bytes that define the immediate value(s). */
158 : uint8_t immbytes;
159 : /* The number of displacement bytes defined by the instruction. */
160 : uint8_t dispbytes;
161 : /* The set of prefix masks defined by the prefix bytes. */
162 : uint32_t prefixmask;
163 : /* The prefix form used to select multibyte instructions, or 0 if
164 : * not used. That is, if 66, f2, or f3 is used to select the instruction,
165 : * then this value is non-zero. For example SSE3 instructions.
166 : */
167 : uint32_t opcode_prefixmask;
168 : /* True if it has a rex prefix. */
169 : uint8_t rexprefix;
170 : /* Index of lock prefix (F0), or kNoLockPrefixIndex if the lock prefix
171 : * isn't specified.
172 : */
173 : uint8_t lock_prefix_index;
174 : };
175 :
176 : /* Models data collected about the parsed instruction. */
177 : typedef struct NCDecoderInst {
178 : /* The address of the instruction, relative to the begining of the code
179 : * segment.
180 : */
181 : NaClPcAddress inst_addr;
182 : /* The instruction rule used to decode the instruction. */
183 : const struct OpInfo* opinfo;
184 : /* The low level details of the instructionm, extracted during parsing. */
185 : struct InstInfo inst;
186 : /* Pointer to bytes of the parsed instruction (int inst) for easier access. */
187 : const NCInstBytesPtr inst_bytes;
188 : /* The decoder state the instruction appears in. */
189 : struct NCDecoderState* dstate;
190 : /* Corresopnding index of this instruction wrt to inst_buffer in
191 : * in the corresponding decoder state NCDecoderState.
192 : */
193 : size_t inst_index;
194 : /* The number of instructions parsed so far (including this instrruction).
195 : * Used to detect when one tries to get a previous instruction that doesn't
196 : * exist.
197 : */
198 : size_t inst_count;
199 : /* True if the instruction is unchanged while dynamically replacing code.
200 : * False if the instruction has changed or if code replacement is not being
201 : * performed (i.e. normal validation.)
202 : */
203 : Bool unchanged;
204 : } NCDecoderInst;
205 :
206 : /* Given a (decoded) instruction, return the instruction that appeared
207 : * n elements before it, or NULL if no such instruction exists.
208 : *
209 : * Parameters:
210 : * dinst - The instruction to look up relative to.
211 : * n - number of elements back to look.
212 : */
213 : extern NCDecoderInst *PreviousInst(const NCDecoderInst* dinst, int n);
214 :
215 : /* Models decoding instructions in a memory region.
216 : *
217 : * Note: This struct is modeling a notion of a (virtual) base class to parse
218 : * a window of k instructions. In this model, we consider NCDecoderState a
219 : * class that can be (singly) inherited by derived classes. This code
220 : * assumes that the "this" pointer can be cast to a derived class
221 : * using a C cast. This implies that derived classes should have the
222 : * field NCDecoderState as its first field.
223 : *
224 : * Typical use is:
225 : *
226 : * NCDecoderState dstate;
227 : * NCDecoder inst_buffer[BUF_SIZE]; // window of BUF_SIZE instructions.
228 : * NCDecoderStateConstruct(&dstate, mbase, vbase, size,
229 : * inst_buffer, BUF_SIZE);
230 : * NCDecoderStateDecode(&dstate);
231 : * NCDecoderStateDestruct(&dstate);
232 : *
233 : * Note: The old API for this class is further down in this file,
234 : * and should be considered deprecated.
235 : */
236 : typedef struct NCDecoderState {
237 : /* PROTECTED: */
238 :
239 : /* The instruction buffer is an array of instructions, used
240 : * by the decoder to define a window of decoded instructions.
241 : * This window automatically moves as instructions are decoded
242 : * so that one can always see the current decoded instruction,
243 : * and some (fixed) number of previously decoded instructions.
244 : */
245 : NCDecoderInst* inst_buffer;
246 :
247 : /* The number of elements in inst_buffer. Must be greater than zero. */
248 : size_t inst_buffer_size;
249 :
250 : /* Remaining memory to decode. It is allocated on
251 : * the stack to make it thread-local, and included here
252 : * so that all decoder states have access to it.
253 : */
254 : NCRemainingMemory memory;
255 :
256 : /* The begining of the memory segment to decode. */
257 : uint8_t* mbase;
258 :
259 : /* The (virtual) base address of the memory segment. */
260 : NaClPcAddress vbase;
261 :
262 : /* The number of bytes in the memory segment. */
263 : NaClMemorySize size;
264 :
265 : /* The index of the current instruction within inst_buffer. */
266 : size_t cur_inst_index;
267 :
268 : /* Holds the error reporting object to use. */
269 : NaClErrorReporter* error_reporter;
270 :
271 : /* Member function to apply actions to a decoded instruction. */
272 : NCDecoderStateAction action_fn;
273 :
274 : /* Member function to process new segment. */
275 : NCDecoderStateMethod new_segment_fn;
276 :
277 : /* Member function called to report an error with the validity of the
278 : * memory segment.
279 : */
280 : NCDecoderStateMethod segmentation_error_fn;
281 :
282 : /* Member function called to report other errors while processing the
283 : * memory segment.
284 : */
285 : NCDecoderStateMethod internal_error_fn;
286 : } NCDecoderState;
287 :
288 : /*
289 : * Construct a decoder state.
290 : *
291 : * Parameters are:
292 : * this - The instance to be constructed.
293 : * mbase - The begining of the memory segment to decode.
294 : * vbase - The (virtual) base address of the memory segment.
295 : * sz - The number of bytes in the memory segment.
296 : *
297 : * Note: Constructors of subclasses of NCDecoderState should
298 : * call this constructor first, to initialize the decoder state.
299 : */
300 : extern void NCDecoderStateConstruct(NCDecoderState* tthis,
301 : uint8_t* mbase, NaClPcAddress vbase,
302 : NaClMemorySize sz,
303 : NCDecoderInst* inst_buffer,
304 : size_t inst_buffer_size);
305 :
306 : /* Define an error reporter to use to report error messages.
307 : * Note: By default, a decoder state uses the null error reporter,
308 : * which doesn't report error messages.
309 : *
310 : * WARNING: Be sure the error reporter is expecting a NCDecoderInst* for
311 : * the print_inst method.
312 : */
313 : void NCDecoderStateSetErrorReporter(NCDecoderState* tthis,
314 : NaClErrorReporter* reporter);
315 :
316 :
317 : /* A default, null error reporter for a NCDecoderInst* instruction. */
318 : extern NaClErrorReporter kNCNullErrorReporter;
319 :
320 : /*
321 : * Decodes the memory segment associated with the decoder state.
322 : * Returns TRUE if able to apply action to all decoded instructions.
323 : *
324 : * Parameters are:
325 : * this - The decoder state.
326 : */
327 : extern Bool NCDecoderStateDecode(NCDecoderState* tthis);
328 :
329 : /*
330 : * Destruct a decoder state.
331 : *
332 : * Parameters are:
333 : * this - The decoder state.
334 : *
335 : * Note: Destructors of subclasses of NCDecoderState should
336 : * call this destructor last, after the subinstance has been destructed.
337 : */
338 : extern void NCDecoderStateDestruct(NCDecoderState* tthis);
339 :
340 : /* "Printable" means the value returned by this function can be used for
341 : * printing user-readable output, but it should not be used to influence if the
342 : * validation algorithm passes or fails. The validation algorithm should not
343 : * depend on vbase - in other words, it should not depend on where the code is
344 : * being mapped in memory.
345 : */
346 : static INLINE NaClPcAddress NCPrintableInstructionAddress(
347 2421 : const NCDecoderInst *dinst) {
348 2421 : return dinst->dstate->vbase + dinst->inst_addr;
349 : }
350 :
351 : struct NCDecoderStatePair;
352 :
353 : /* Models a method that does a compare/update on a pair of instructions from
354 : * the pairwise instruction decoder. Returns true if the action succeeded.
355 : */
356 : typedef Bool (*NCDecoderStatePairAction)(struct NCDecoderStatePair* tthis,
357 : struct NCDecoderInst* dinst_old,
358 : struct NCDecoderInst* dinst_new);
359 :
360 : /* Models decoding a pair of instruction segments, compariing/updating
361 : * them as appropriate. Assumes that two instruction segments are the same,
362 : * except for some (constant-sized) changes. At the instruction level,
363 : * the instruction lengths are assumed to be the same. Typically, this is
364 : * because the one instruction segment was an updated version of a
365 : * previous instruction segment.
366 : *
367 : * Typical use is:
368 : *
369 : * NCDecoderState dstate_old;
370 : * NCDecoderState dstate_new;
371 : * NCDecoderStatePair dstate_pair;
372 : * ... Code that constructs dstate_old and dstate_new.
373 : * NCDecoderStatePair Construct(&dstate_pair, &dstate_old, &dstate_new);
374 : * NCDecoderStatePairDecode(&dstate_pair);
375 : * NCDecoderStatePairDestruct(&dstate_pair);
376 : */
377 : typedef struct NCDecoderStatePair {
378 : /* PROTECTED: */
379 :
380 : /* The old decoder state. */
381 : NCDecoderState* old_dstate;
382 :
383 : /* The new decoder state. */
384 : NCDecoderState* new_dstate;
385 :
386 : /* The (virtual method) action to apply to each instruction. */
387 : NCDecoderStatePairAction action_fn;
388 : } NCDecoderStatePair;
389 :
390 : /*
391 : * Construct a decoder state pair.
392 : *
393 : * Parameters are:
394 : * tthis - The decoder state pair to construct.
395 : * old_dstate - A constructed old decoder state to use.
396 : * new_dstate - A constructed new decoder state to use.
397 : *
398 : * Note: Constructors of subclasses of NCDecoderStatePair should
399 : * call this constructor first, to initialize the decoder pair fields.
400 : */
401 : extern void NCDecoderStatePairConstruct(NCDecoderStatePair* tthis,
402 : NCDecoderState* old_dstate,
403 : NCDecoderState* new_dstate);
404 :
405 : /*
406 : * Decode the memory segments in each instruction state, applying
407 : * the appropriate action on each instruction till either:
408 : * (1) The instruction lengths differ.
409 : * (2) The action returns false.
410 : * Returns true if no instruction lengths differ, and the action
411 : * returns true for all found instructions.
412 : */
413 : extern Bool NCDecoderStatePairDecode(NCDecoderStatePair* tthis);
414 :
415 : /*
416 : * Destruct a decoder state pair.
417 : *
418 : * Note: Destructors of subclasses of NCDecoderStatePair should
419 : * call this distructor last, after the subinstance has been destructed.
420 : */
421 : extern void NCDecoderStatePairDestruct(NCDecoderStatePair* tthis);
422 :
423 : EXTERN_C_END
424 :
425 : #endif /* NATIVE_CLIENT_SRC_TRUSTED_VALIDATOR_X86_NCVAL_SEG_SFI_NCDECODE_H_ */
|