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.
8 * ncdecode.h - table driven decoder for Native Client.
10 * This header file contains type declarations and constants
11 * used by the decoder input table
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_
16 #include "native_client/src/shared/utils/types.h"
17 #include "native_client/src/trusted/validator/ncvalidate.h"
18 #include "native_client/src/trusted/validator/x86/error_reporter.h"
19 #include "native_client/src/trusted/validator/x86/ncinstbuffer.h"
20 #include "native_client/src/trusted/validator/x86/x86_insts.h"
25 struct NCDecoderState;
27 /* Function type for a decoder action. Returns TRUE if action
28 * was applied successfully.
30 typedef Bool (*NCDecoderStateAction)(const struct NCDecoderInst* dinst);
32 /* Function type for other decoder state methods. */
33 typedef void (*NCDecoderStateMethod)(struct NCDecoderState* vstate);
41 /* these comments facilitate counting */
47 /* these comments facilitate counting */
53 /* these comments facilitate counting */
60 /* kModRMOpcodeGroups doesn't work as a const int since it is used */
61 /* as an array dimension */
62 #define kNaClMRMGroupsRange 20
64 /* Define the maximum value that can be encoded in the modrm mod field. */
65 #define kModRMOpcodeGroupSize 8
67 /* Define the maximum register value that can be encoded into the opcode
70 #define kMaxRegisterIndexInOpcode 7
72 /* information derived from the opcode, wherever it happens to be */
85 IMM_MOV_DATAV, /* Special case for 64-bits MOVs (b8 through bf). */
86 /* Don't add to this enum without update kNCDecodeImmediateTypeRange */
87 /* and updating the tables below which are sized using this constant */
88 } NCDecodeImmediateType;
89 #define kNCDecodeImmediateTypeRange 12
91 /* 255 will force an error */
92 static const uint8_t kImmTypeToSize66[kNCDecodeImmediateTypeRange] =
93 { 0, 0, 1, 2, 3, 4, 2, (NACL_TARGET_SUBARCH == 64 ? 8 : 4), 0, 0, 6, 2};
94 static const uint8_t kImmTypeToSize67[kNCDecodeImmediateTypeRange] =
95 { 0, 0, 1, 2, 3, 4, 4, 2, 0, 0, 4, 4};
96 static const uint8_t kImmTypeToSize[kNCDecodeImmediateTypeRange] =
97 { 0, 0, 1, 2, 3, 4, 4, (NACL_TARGET_SUBARCH == 64 ? 8 : 4), 0, 0, 6, 4 };
99 /* Defines how to decode operands for byte codes. */
101 /* Assume the default size of the operands is 64-bits (if
102 * not specified in prefix bits).
104 DECODE_OPS_DEFAULT_64,
105 /* Assume the default size of the operands is 32-bits (if
106 * not specified in prefix bits).
108 DECODE_OPS_DEFAULT_32,
109 /* Force the size of the operands to 64 bits (prefix bits are
115 /* Models information on an x86-32 bit instruction. */
117 NaClInstType insttype;
118 uint8_t hasmrmbyte; /* 1 if this inst has an mrm byte, else 0 */
119 uint8_t immtype; /* IMM_NONE, IMM_FIXED1, etc. */
120 uint8_t opinmrm; /* set to 1..8 if you must find opcode in MRM byte */
123 /* Models a node in a trie of NOP instructions. */
124 typedef struct NCNopTrieNode {
125 /* The matching byte for the trie node. */
126 uint8_t matching_byte;
127 /* The matching modeled nop, if byte matched. */
128 struct OpInfo *matching_opinfo;
129 /* Node to match remaining bytes. */
130 struct NCNopTrieNode* success;
131 /* Node to match remaining bytes. */
132 struct NCNopTrieNode* fail;
135 /* Predefined value to communicate that the lock prefix was not
136 * found in an instruction.
138 static const uint8_t kNoLockPrefixIndex = 0xFF;
140 /* Models a parsed x86-32 bit instruction. */
142 /* The bytes used to parse the x86-32 instruction (may have added
143 * zero filler if the instruction straddles the memory segment).
146 /* The number of prefix bytes in the instruction. */
147 uint8_t prefixbytes; /* 0..4 */
148 /* Number of opcode bytes in the instruction. */
150 /* non-zero if the instruction contains an SIB byte. */
152 /* The ModRm byte. */
154 /* A NCDecodeImmediateType describing the type of immediate value(s)
155 * the instruction has.
158 /* The number of bytes that define the immediate value(s). */
160 /* The number of displacement bytes defined by the instruction. */
162 /* The set of prefix masks defined by the prefix bytes. */
164 /* The prefix form used to select multibyte instructions, or 0 if
165 * not used. That is, if 66, f2, or f3 is used to select the instruction,
166 * then this value is non-zero. For example SSE3 instructions.
168 uint32_t opcode_prefixmask;
169 /* True if it has a rex prefix. */
171 /* Index of lock prefix (F0), or kNoLockPrefixIndex if the lock prefix
174 uint8_t lock_prefix_index;
177 /* Models data collected about the parsed instruction. */
178 typedef struct NCDecoderInst {
179 /* The address of the instruction, relative to the begining of the code
182 NaClPcAddress inst_addr;
183 /* The instruction rule used to decode the instruction. */
184 const struct OpInfo* opinfo;
185 /* The low level details of the instructionm, extracted during parsing. */
186 struct InstInfo inst;
187 /* Pointer to bytes of the parsed instruction (int inst) for easier access. */
188 const NCInstBytesPtr inst_bytes;
189 /* The decoder state the instruction appears in. */
190 struct NCDecoderState* dstate;
191 /* Corresopnding index of this instruction wrt to inst_buffer in
192 * in the corresponding decoder state NCDecoderState.
195 /* The number of instructions parsed so far (including this instrruction).
196 * Used to detect when one tries to get a previous instruction that doesn't
200 /* True if the instruction is unchanged while dynamically replacing code.
201 * False if the instruction has changed or if code replacement is not being
202 * performed (i.e. normal validation.)
207 /* Given a (decoded) instruction, return the instruction that appeared
208 * n elements before it, or NULL if no such instruction exists.
211 * dinst - The instruction to look up relative to.
212 * n - number of elements back to look.
214 extern NCDecoderInst *PreviousInst(const NCDecoderInst* dinst, int n);
216 /* Models decoding instructions in a memory region.
218 * Note: This struct is modeling a notion of a (virtual) base class to parse
219 * a window of k instructions. In this model, we consider NCDecoderState a
220 * class that can be (singly) inherited by derived classes. This code
221 * assumes that the "this" pointer can be cast to a derived class
222 * using a C cast. This implies that derived classes should have the
223 * field NCDecoderState as its first field.
227 * NCDecoderState dstate;
228 * NCDecoder inst_buffer[BUF_SIZE]; // window of BUF_SIZE instructions.
229 * NCDecoderStateConstruct(&dstate, mbase, vbase, size,
230 * inst_buffer, BUF_SIZE);
231 * NCDecoderStateDecode(&dstate);
232 * NCDecoderStateDestruct(&dstate);
234 * Note: The old API for this class is further down in this file,
235 * and should be considered deprecated.
237 typedef struct NCDecoderState {
240 /* The instruction buffer is an array of instructions, used
241 * by the decoder to define a window of decoded instructions.
242 * This window automatically moves as instructions are decoded
243 * so that one can always see the current decoded instruction,
244 * and some (fixed) number of previously decoded instructions.
246 NCDecoderInst* inst_buffer;
248 /* The number of elements in inst_buffer. Must be greater than zero. */
249 size_t inst_buffer_size;
251 /* Remaining memory to decode. It is allocated on
252 * the stack to make it thread-local, and included here
253 * so that all decoder states have access to it.
255 NCRemainingMemory memory;
257 /* The begining of the memory segment to decode. */
260 /* The (virtual) base address of the memory segment. */
263 /* The number of bytes in the memory segment. */
266 /* The index of the current instruction within inst_buffer. */
267 size_t cur_inst_index;
269 /* Holds the error reporting object to use. */
270 NaClErrorReporter* error_reporter;
272 /* Member function to apply actions to a decoded instruction. */
273 NCDecoderStateAction action_fn;
275 /* Member function to process new segment. */
276 NCDecoderStateMethod new_segment_fn;
278 /* Member function called to report an error with the validity of the
281 NCDecoderStateMethod segmentation_error_fn;
283 /* Member function called to report other errors while processing the
286 NCDecoderStateMethod internal_error_fn;
290 * Construct a decoder state.
293 * this - The instance to be constructed.
294 * mbase - The begining of the memory segment to decode.
295 * vbase - The (virtual) base address of the memory segment.
296 * sz - The number of bytes in the memory segment.
298 * Note: Constructors of subclasses of NCDecoderState should
299 * call this constructor first, to initialize the decoder state.
301 extern void NCDecoderStateConstruct(NCDecoderState* tthis,
302 uint8_t* mbase, NaClPcAddress vbase,
304 NCDecoderInst* inst_buffer,
305 size_t inst_buffer_size);
307 /* Define an error reporter to use to report error messages.
308 * Note: By default, a decoder state uses the null error reporter,
309 * which doesn't report error messages.
311 * WARNING: Be sure the error reporter is expecting a NCDecoderInst* for
312 * the print_inst method.
314 void NCDecoderStateSetErrorReporter(NCDecoderState* tthis,
315 NaClErrorReporter* reporter);
318 /* A default, null error reporter for a NCDecoderInst* instruction. */
319 extern NaClErrorReporter kNCNullErrorReporter;
322 * Decodes the memory segment associated with the decoder state.
323 * Returns TRUE if able to apply action to all decoded instructions.
326 * this - The decoder state.
328 extern Bool NCDecoderStateDecode(NCDecoderState* tthis);
331 * Destruct a decoder state.
334 * this - The decoder state.
336 * Note: Destructors of subclasses of NCDecoderState should
337 * call this destructor last, after the subinstance has been destructed.
339 extern void NCDecoderStateDestruct(NCDecoderState* tthis);
341 /* "Printable" means the value returned by this function can be used for
342 * printing user-readable output, but it should not be used to influence if the
343 * validation algorithm passes or fails. The validation algorithm should not
344 * depend on vbase - in other words, it should not depend on where the code is
345 * being mapped in memory.
347 static INLINE NaClPcAddress NCPrintableInstructionAddress(
348 const NCDecoderInst *dinst) {
349 return dinst->dstate->vbase + dinst->inst_addr;
352 struct NCDecoderStatePair;
354 /* Models a method that does a compare/update on a pair of instructions from
355 * the pairwise instruction decoder. Returns true if the action succeeded.
357 typedef Bool (*NCDecoderStatePairAction)(struct NCDecoderStatePair* tthis,
358 struct NCDecoderInst* dinst_old,
359 struct NCDecoderInst* dinst_new);
361 /* Models decoding a pair of instruction segments, compariing/updating
362 * them as appropriate. Assumes that two instruction segments are the same,
363 * except for some (constant-sized) changes. At the instruction level,
364 * the instruction lengths are assumed to be the same. Typically, this is
365 * because the one instruction segment was an updated version of a
366 * previous instruction segment.
370 * NCDecoderState dstate_old;
371 * NCDecoderState dstate_new;
372 * NCDecoderStatePair dstate_pair;
373 * ... Code that constructs dstate_old and dstate_new.
374 * NCDecoderStatePair Construct(&dstate_pair, &dstate_old, &dstate_new);
375 * NCDecoderStatePairDecode(&dstate_pair);
376 * NCDecoderStatePairDestruct(&dstate_pair);
378 typedef struct NCDecoderStatePair {
381 /* The old decoder state. */
382 NCDecoderState* old_dstate;
384 /* The new decoder state. */
385 NCDecoderState* new_dstate;
387 /* The (virtual method) action to apply to each instruction. */
388 NCDecoderStatePairAction action_fn;
390 /* Utility function that copies a single instruction in memory, can be used in
393 NaClCopyInstructionFunc copy_func;
394 } NCDecoderStatePair;
397 * Construct a decoder state pair.
400 * tthis - The decoder state pair to construct.
401 * old_dstate - A constructed old decoder state to use.
402 * new_dstate - A constructed new decoder state to use.
404 * Note: Constructors of subclasses of NCDecoderStatePair should
405 * call this constructor first, to initialize the decoder pair fields.
407 extern void NCDecoderStatePairConstruct(
408 NCDecoderStatePair* tthis,
409 NCDecoderState* old_dstate,
410 NCDecoderState* new_dstate,
411 NaClCopyInstructionFunc copy_func);
414 * Decode the memory segments in each instruction state, applying
415 * the appropriate action on each instruction till either:
416 * (1) The instruction lengths differ.
417 * (2) The action returns false.
418 * Returns true if no instruction lengths differ, and the action
419 * returns true for all found instructions.
421 extern Bool NCDecoderStatePairDecode(NCDecoderStatePair* tthis);
424 * Destruct a decoder state pair.
426 * Note: Destructors of subclasses of NCDecoderStatePair should
427 * call this distructor last, after the subinstance has been destructed.
429 extern void NCDecoderStatePairDestruct(NCDecoderStatePair* tthis);
433 #endif /* NATIVE_CLIENT_SRC_TRUSTED_VALIDATOR_X86_NCVAL_SEG_SFI_NCDECODE_H_ */