Upstream version 11.39.266.0
[platform/framework/web/crosswalk.git] / src / native_client / src / trusted / validator / x86 / ncval_seg_sfi / ncdecode.c
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.c - table driven decoder for Native Client
9  *
10  * Most x86 decoders I've looked at are big case statements. While
11  * this organization is fairly transparent and obvious, it tends to
12  * lead to messy control flow (gotos, etc.) that make the decoder
13  * more complicated, hence harder to maintain and harder to validate.
14  *
15  * This decoder is table driven, which will hopefully result in
16  * substantially less code. Although the code+tables may be more
17  * lines of code than a decoder built around a switch statement,
18  * the smaller amount of actual procedural code and the regular
19  * structure of the tables should make it easier to understand,
20  * debug, and easier to become confident the decoder is correct.
21  *
22  * As it is specialized to Native Client, this decoder can also
23  * benefit from any exclusions or simplifications we decide to
24  * make in the dialect of x86 machine code accepted by Native
25  * Client. Any such simplifications should ultimately be easily
26  * recognized by inspection of the decoder configuration tables.
27  * ALSO, the decoder mostly needs to worry about accurate
28  * instruction lengths and finding opcodes. It does not need
29  * to completely resolve the operands of all instructions.
30  */
31
32 #include "native_client/src/trusted/validator/x86/ncval_seg_sfi/ncdecode.h"
33 #include "native_client/src/trusted/validator/x86/ncval_seg_sfi/ncdecode_aux.h"
34
35 #include <stdio.h>
36 #include <assert.h>
37
38 #if NACL_TARGET_SUBARCH == 64
39 #include "native_client/src/trusted/validator/x86/ncval_seg_sfi/gen/ncdecodetab_64.h"
40 #else
41 #include "native_client/src/trusted/validator/x86/ncval_seg_sfi/gen/ncdecodetab_32.h"
42 #endif
43
44 /* To turn on debugging of instruction decoding, change value of
45  * DEBUGGING to 1.
46  */
47 #define DEBUGGING 0
48
49 #include "native_client/src/shared/utils/debugging.h"
50
51 #include "native_client/src/trusted/validator/x86/ncinstbuffer_inl.c"
52 #include "native_client/src/trusted/validator/x86/x86_insts_inl.c"
53
54 /* Generates a print name for the given NCDecodeImmediateType. */
55 static const char* NCDecodeImmediateTypeName(NCDecodeImmediateType type) {
56   DEBUG_OR_ERASE(
57       switch(type) {
58         case IMM_UNKNOWN: return "IMM_UNKNOWN";
59         case IMM_NONE: return "IMM_NONE";
60         case IMM_FIXED1: return "IMM_FIXED1";
61         case IMM_FIXED2: return "IMM_FIXED2";
62         case IMM_FIXED3: return "IMM_FIXED3";
63         case IMM_FIXED4: return "IMM_FIXED4";
64         case IMM_DATAV: return "IMM_DATAV";
65         case IMM_ADDRV: return "IMM_ADDRV";
66         case IMM_GROUP3_F6: return "IMM_GROUP3_F6";
67         case IMM_GROUP3_F7: return "IMM_GROUP3_F7";
68         case IMM_FARPTR: return "IMM_FARPTR";
69         case IMM_MOV_DATAV: return "IMM_MOV_DATAV";
70         default: assert(0);
71       });
72   /* NOTREACHED */
73   return NULL;
74 }
75
76 /* Prints out the contents of the given OpInfo. Should only be called
77  * inside a DEBUG macro (i.e. for debugging only).
78  */
79 static void PrintOpInfo(const struct OpInfo* info) {
80   DEBUG_OR_ERASE(printf("opinfo(%s, hasmrm=%u, immtype=%s, opinmrm=%d)\n",
81                         NaClInstTypeString(info->insttype),
82                         info->hasmrmbyte,
83                         NCDecodeImmediateTypeName(info->immtype),
84                         info->opinmrm));
85 }
86
87 /* later this will make decoding x87 instructions a bit more concise. */
88 static const struct OpInfo* kDecodeX87Op[8] = { kDecode87D8,
89                                                 kDecode87D9,
90                                                 kDecode87DA,
91                                                 kDecode87DB,
92                                                 kDecode87DC,
93                                                 kDecode87DD,
94                                                 kDecode87DE,
95                                                 kDecode87DF };
96
97 static Bool NullDecoderAction(const struct NCDecoderInst* dinst) {
98   UNREFERENCED_PARAMETER(dinst);
99   return TRUE;
100 }
101 static void NullDecoderMethod(struct NCDecoderState* dstate) {
102   UNREFERENCED_PARAMETER(dstate);
103 }
104
105 /* API to virtual methods of a decoder state. */
106 void NCDecoderStateNewSegment(NCDecoderState* tthis) {
107   (tthis->new_segment_fn)(tthis);
108 }
109
110 static Bool NCDecoderStateApplyAction(NCDecoderState* tthis,
111                                       NCDecoderInst* dinst) {
112   return (tthis->action_fn)(dinst);
113 }
114
115 static void NCDecoderStateSegmentationError(NCDecoderState* tthis) {
116   (tthis->segmentation_error_fn)(tthis);
117 }
118
119 static void NCDecoderStateInternalError(NCDecoderState* tthis) {
120   (tthis->internal_error_fn)(tthis);
121 }
122
123 /* Error Condition Handling */
124 static void ErrorSegmentation(NCDecoderInst* dinst) {
125   NCDecoderState* dstate = dinst->dstate;
126   NaClErrorReporter* reporter = dstate->error_reporter;
127   (*reporter->printf)(dstate->error_reporter, "ErrorSegmentation\n");
128   /* When the decoder is used by the NaCl validator    */
129   /* the validator provides an error handler that does */
130   /* the necessary bookeeping to track these errors.   */
131   NCDecoderStateSegmentationError(dstate);
132 }
133
134 static void ErrorInternal(NCDecoderInst* dinst) {
135   NCDecoderState* dstate = dinst->dstate;
136   NaClErrorReporter* reporter = dstate->error_reporter;
137   (*reporter->printf)(reporter, "ErrorInternal\n");
138   /* When the decoder is used by the NaCl validator    */
139   /* the validator provides an error handler that does */
140   /* the necessary bookeeping to track these errors.   */
141   NCDecoderStateInternalError(dstate);
142 }
143
144 /* Defines how to handle errors found while parsing the memory segment. */
145 static void NCRemainingMemoryInternalError(NCRemainingMemoryError error,
146                                            struct NCRemainingMemory* memory) {
147   /* Don't do anything for memory overflow! Let NCDecodeSegment generate
148    * the corresponding segmentation error. This allows us to back out overflow
149    * if a predefined nop is matched.
150    */
151   if (NCRemainingMemoryOverflow != error) {
152     NCDecoderState* dstate = (NCDecoderState*) memory->error_fn_state;
153     NCRemainingMemoryReportError(error, memory);
154     ErrorInternal(&dstate->inst_buffer[dstate->cur_inst_index]);
155   }
156 }
157
158 static INLINE void InitDecoder(struct NCDecoderInst* dinst) {
159   NCInstBytesInitInline(&dinst->inst.bytes);
160   dinst->inst.prefixbytes = 0;
161   dinst->inst.prefixmask = 0;
162   dinst->inst.opcode_prefixmask = 0;
163   dinst->inst.num_opbytes = 1;  /* unless proven otherwise. */
164   dinst->inst.hassibbyte = 0;
165   dinst->inst.mrm = 0;
166   dinst->inst.immtype = IMM_UNKNOWN;
167   dinst->inst.immbytes = 0;
168   dinst->inst.dispbytes = 0;
169   dinst->inst.rexprefix = 0;
170   dinst->inst.lock_prefix_index = kNoLockPrefixIndex;
171   dinst->opinfo = NULL;
172 }
173
174 /* Returns the number of bytes defined for the operand of the instruction. */
175 static int ExtractOperandSize(NCDecoderInst* dinst) {
176   if (NACL_TARGET_SUBARCH == 64 &&
177       dinst->inst.rexprefix && dinst->inst.rexprefix & 0x8) {
178     return 8;
179   }
180   if (dinst->inst.prefixmask & kPrefixDATA16) {
181     return 2;
182   }
183   return 4;
184 }
185
186 /* at most four prefix bytes are allowed */
187 static void ConsumePrefixBytes(struct NCDecoderInst* dinst) {
188   uint8_t nb;
189   int ii;
190   uint32_t prefix_form;
191
192   for (ii = 0; ii < kMaxPrefixBytes; ++ii) {
193     nb = NCRemainingMemoryGetNext(&dinst->dstate->memory);
194     prefix_form = kPrefixTable[nb];
195     if (prefix_form == 0) return;
196     DEBUG( printf("Consume prefix[%d]: %02x => %x\n", ii, nb, prefix_form) );
197     dinst->inst.prefixmask |= prefix_form;
198     dinst->inst.prefixmask |= kPrefixTable[nb];
199     dinst->inst.prefixbytes += 1;
200     NCInstBytesReadInline(&dinst->inst.bytes);
201     DEBUG( printf("  prefix mask: %08x\n", dinst->inst.prefixmask) );
202     if (NACL_TARGET_SUBARCH == 64 && prefix_form == kPrefixREX) {
203       dinst->inst.rexprefix = nb;
204       /* REX prefix must be last prefix. */
205       return;
206     }
207     if (prefix_form == kPrefixLOCK) {
208       /* Note: we don't have to worry about duplicates, since
209        * ValidatePrefixes in ncvalidate.c will not allow such
210        * a possibility.
211        */
212       dinst->inst.lock_prefix_index = (uint8_t) ii;
213     }
214   }
215 }
216
217 static const struct OpInfo* GetExtendedOpInfo(NCDecoderInst* dinst,
218                                               uint8_t opbyte2) {
219   uint32_t pm;
220   pm = dinst->inst.prefixmask;
221   if ((pm & (kPrefixDATA16 | kPrefixREPNE | kPrefixREP)) == 0) {
222     return &kDecode0FXXOp[opbyte2];
223   } else if (pm & kPrefixDATA16) {
224     dinst->inst.prefixmask &= ~kPrefixDATA16;
225     dinst->inst.opcode_prefixmask = kPrefixDATA16;
226     return &kDecode660FXXOp[opbyte2];
227   } else if (pm & kPrefixREPNE) {
228     dinst->inst.prefixmask &= ~kPrefixREPNE;
229     dinst->inst.opcode_prefixmask = kPrefixREPNE;
230     return &kDecodeF20FXXOp[opbyte2];
231   } else if (pm & kPrefixREP) {
232     dinst->inst.prefixmask &= ~kPrefixREP;
233     dinst->inst.opcode_prefixmask = kPrefixREP;
234     return &kDecodeF30FXXOp[opbyte2];
235   }
236   ErrorInternal(dinst);
237   return dinst->opinfo;
238 }
239
240 static void GetX87OpInfo(NCDecoderInst* dinst) {
241   /* WAIT is an x87 instruction but not in the coproc opcode space. */
242   uint8_t op1 = NCInstBytesByteInline(&dinst->inst_bytes,
243                                       dinst->inst.prefixbytes);
244   if (op1 < kFirstX87Opcode || op1 > kLastX87Opcode) {
245     if (op1 != kWAITOp) ErrorInternal(dinst);
246     return;
247   }
248   dinst->opinfo = &kDecodeX87Op[op1 - kFirstX87Opcode][dinst->inst.mrm];
249   DEBUG( printf("NACL_X87 op1 = %02x, ", op1);
250          PrintOpInfo(dinst->opinfo) );
251 }
252
253 static void ConsumeOpcodeBytes(NCDecoderInst* dinst) {
254   uint8_t opcode = NCInstBytesReadInline(&dinst->inst.bytes);
255   dinst->opinfo = &kDecode1ByteOp[opcode];
256   DEBUG( printf("NACLi_1BYTE: opcode = %02x, ", opcode);
257          PrintOpInfo(dinst->opinfo) );
258   if (opcode == kTwoByteOpcodeByte1) {
259     uint8_t opcode2 = NCInstBytesReadInline(&dinst->inst.bytes);
260     dinst->opinfo = GetExtendedOpInfo(dinst, opcode2);
261     DEBUG( printf("NACLi_2BYTE: opcode2 = %02x, ", opcode2);
262            PrintOpInfo(dinst->opinfo) );
263     dinst->inst.num_opbytes = 2;
264     if (dinst->opinfo->insttype == NACLi_3BYTE) {
265       uint8_t opcode3 = NCInstBytesReadInline(&dinst->inst.bytes);
266       uint32_t pm;
267       pm = dinst->inst.opcode_prefixmask;
268       dinst->inst.num_opbytes = 3;
269
270       DEBUG( printf("NACLi_3BYTE: opcode3 = %02x, ", opcode3) );
271       switch (opcode2) {
272       case 0x38:        /* SSSE3, SSE4 */
273         if (pm & kPrefixDATA16) {
274           dinst->opinfo = &kDecode660F38Op[opcode3];
275         } else if (pm & kPrefixREPNE) {
276           dinst->opinfo = &kDecodeF20F38Op[opcode3];
277         } else if (pm == 0) {
278           dinst->opinfo = &kDecode0F38Op[opcode3];
279         } else {
280           /* Other prefixes like F3 cause an undefined instruction error. */
281           /* Note from decoder table that NACLi_3BYTE is only used with   */
282           /* data16 and repne prefixes.                                   */
283           ErrorInternal(dinst);
284         }
285         break;
286       case 0x3A:        /* SSSE3, SSE4 */
287         if (pm & kPrefixDATA16) {
288           dinst->opinfo = &kDecode660F3AOp[opcode3];
289         } else if (pm == 0) {
290           dinst->opinfo = &kDecode0F3AOp[opcode3];
291         } else {
292           /* Other prefixes like F3 cause an undefined instruction error. */
293           /* Note from decoder table that NACLi_3BYTE is only used with   */
294           /* data16 and repne prefixes.                                   */
295           ErrorInternal(dinst);
296         }
297         break;
298       default:
299         /* if this happens there is a decoding table bug */
300         ErrorInternal(dinst);
301         break;
302       }
303       DEBUG( PrintOpInfo(dinst->opinfo) );
304     }
305   }
306   dinst->inst.immtype = dinst->opinfo->immtype;
307 }
308
309 static void ConsumeModRM(NCDecoderInst* dinst) {
310   if (dinst->opinfo->hasmrmbyte != 0) {
311     const uint8_t mrm = NCInstBytesReadInline(&dinst->inst.bytes);
312     DEBUG( printf("Mod/RM byte: %02x\n", mrm) );
313     dinst->inst.mrm = mrm;
314     if (dinst->opinfo->insttype == NACLi_X87 ||
315         dinst->opinfo->insttype == NACLi_X87_FSINCOS) {
316       GetX87OpInfo(dinst);
317     }
318     if (dinst->opinfo->opinmrm) {
319       const struct OpInfo* mopinfo =
320         &kDecodeModRMOp[dinst->opinfo->opinmrm][modrm_opcodeInline(mrm)];
321       dinst->opinfo = mopinfo;
322       DEBUG( printf("NACLi_opinmrm: modrm.opcode = %x, ",
323                     modrm_opcodeInline(mrm));
324              PrintOpInfo(dinst->opinfo) );
325       if (dinst->inst.immtype == IMM_UNKNOWN) {
326         assert(0);
327         dinst->inst.immtype = mopinfo->immtype;
328       }
329       /* handle weird case for 0xff TEST Ib/Iv */
330       if (modrm_opcodeInline(mrm) == 0) {
331         if (dinst->inst.immtype == IMM_GROUP3_F6) {
332           dinst->inst.immtype = IMM_FIXED1;
333         }
334         if (dinst->inst.immtype == IMM_GROUP3_F7) {
335           dinst->inst.immtype = IMM_DATAV;
336         }
337       }
338       DEBUG( printf("  immtype = %s\n",
339                     NCDecodeImmediateTypeName(dinst->inst.immtype)) );
340     }
341     if (dinst->inst.prefixmask & kPrefixADDR16) {
342       switch (modrm_modInline(mrm)) {
343         case 0:
344           if (modrm_rmInline(mrm) == 0x06) {
345             dinst->inst.dispbytes = 2;        /* disp16 */
346           } else {
347             dinst->inst.dispbytes = 0;
348           }
349           break;
350         case 1:
351           dinst->inst.dispbytes = 1;           /* disp8 */
352           break;
353         case 2:
354           dinst->inst.dispbytes = 2;           /* disp16 */
355           break;
356         case 3:
357           dinst->inst.dispbytes = 0;           /* no disp */
358           break;
359         default:
360           ErrorInternal(dinst);
361       }
362       dinst->inst.hassibbyte = 0;
363     } else {
364       switch (modrm_modInline(mrm)) {
365         case 0:
366           if (modrm_rmInline(mrm) == 0x05) {
367             dinst->inst.dispbytes = 4;         /* disp32 */
368           } else {
369             dinst->inst.dispbytes = 0;
370           }
371           break;
372         case 1:
373           dinst->inst.dispbytes = 1;           /* disp8 */
374           break;
375         case 2:
376           dinst->inst.dispbytes = 4;           /* disp32 */
377           break;
378         case 3:
379           dinst->inst.dispbytes = 0;           /* no disp */
380           break;
381         default:
382           ErrorInternal(dinst);
383       }
384       dinst->inst.hassibbyte = ((modrm_rmInline(mrm) == 0x04) &&
385                                  (modrm_modInline(mrm) != 3));
386     }
387   }
388   DEBUG( printf("  dispbytes = %d, hasibbyte = %d\n",
389                 dinst->inst.dispbytes, dinst->inst.hassibbyte) );
390 }
391
392 static INLINE void ConsumeSIB(NCDecoderInst* dinst) {
393   if (dinst->inst.hassibbyte != 0) {
394     const uint8_t sib = NCInstBytesReadInline(&dinst->inst.bytes);
395     if (sib_base(sib) == 0x05) {
396       switch (modrm_modInline(dinst->inst.mrm)) {
397       case 0: dinst->inst.dispbytes = 4; break;
398       case 1: dinst->inst.dispbytes = 1; break;
399       case 2: dinst->inst.dispbytes = 4; break;
400       case 3:
401       default:
402         ErrorInternal(dinst);
403       }
404     }
405     DEBUG( printf("sib byte: %02x, dispbytes = %d\n",
406                   sib, dinst->inst.dispbytes) );
407   }
408 }
409
410 static INLINE void ConsumeID(NCDecoderInst* dinst) {
411   if (dinst->inst.immtype == IMM_UNKNOWN) {
412     ErrorInternal(dinst);
413   }
414   /* NOTE: NaCl allows at most one prefix byte (for 32-bit mode) */
415   if (dinst->inst.immtype == IMM_MOV_DATAV) {
416     dinst->inst.immbytes = ExtractOperandSize(dinst);
417   } else if (dinst->inst.prefixmask & kPrefixDATA16) {
418     dinst->inst.immbytes = kImmTypeToSize66[dinst->inst.immtype];
419   } else if (dinst->inst.prefixmask & kPrefixADDR16) {
420     dinst->inst.immbytes = kImmTypeToSize67[dinst->inst.immtype];
421   } else {
422     dinst->inst.immbytes = kImmTypeToSize[dinst->inst.immtype];
423   }
424   NCInstBytesReadBytesInline((ssize_t) dinst->inst.immbytes,
425                              &dinst->inst.bytes);
426   NCInstBytesReadBytesInline((ssize_t) dinst->inst.dispbytes,
427                              &dinst->inst.bytes);
428   DEBUG(printf("ID: %d disp bytes, %d imm bytes\n",
429                dinst->inst.dispbytes, dinst->inst.immbytes));
430 }
431
432 /* Actually this routine is special for 3DNow instructions */
433 static INLINE void MaybeGet3ByteOpInfo(NCDecoderInst* dinst) {
434   if (dinst->opinfo->insttype == NACLi_3DNOW) {
435     uint8_t opbyte1 = NCInstBytesByteInline(&dinst->inst_bytes,
436                                       dinst->inst.prefixbytes);
437     uint8_t opbyte2 = NCInstBytesByteInline(&dinst->inst_bytes,
438                                       dinst->inst.prefixbytes + 1);
439     if (opbyte1 == kTwoByteOpcodeByte1 &&
440         opbyte2 == k3DNowOpcodeByte2) {
441       uint8_t immbyte =
442           NCInstBytesByteInline(&dinst->inst_bytes,
443                                 dinst->inst.bytes.length - 1);
444       dinst->opinfo = &kDecode0F0FOp[immbyte];
445       DEBUG( printf(
446                  "NACLi_3DNOW: byte1 = %02x, byte2 = %02x, immbyte = %02x,\n  ",
447                  opbyte1, opbyte2, immbyte);
448              PrintOpInfo(dinst->opinfo) );
449     }
450   }
451 }
452
453 /* Gets an instruction nindex away from the given instruction.
454  * WARNING: Does not do bounds checking, other than rolling the
455  * index as needed to stay within the (circular) instruction buffer.
456  */
457 static NCDecoderInst* NCGetInstDiff(const NCDecoderInst* dinst,
458                                       int nindex) {
459   /* Note: This code also handles increments, so that we can
460    * use the same code for both.
461    */
462   size_t index = (dinst->inst_index + nindex) % dinst->dstate->inst_buffer_size;
463   return &dinst->dstate->inst_buffer[index];
464 }
465
466 struct NCDecoderInst* PreviousInst(const NCDecoderInst* dinst,
467                                    int nindex) {
468   if ((nindex > 0) && (((size_t) nindex) < dinst->inst_count)) {
469     return NCGetInstDiff(dinst, -nindex);
470   } else {
471     return NULL;
472   }
473 }
474
475 /* Initialize the decoder state fields, assuming constructor parameter
476  * fields mbase, vbase, size, inst_buffer, and inst_buffer_size have
477  * already been set.
478  */
479 static void NCDecoderStateInitFields(NCDecoderState* this) {
480   size_t dbindex;
481   this->error_reporter = &kNCNullErrorReporter;
482   NCRemainingMemoryInit(this->mbase, this->size, &this->memory);
483   this->memory.error_fn = NCRemainingMemoryInternalError;
484   this->memory.error_fn_state = (void*) this;
485   for (dbindex = 0; dbindex < this->inst_buffer_size; ++dbindex) {
486     this->inst_buffer[dbindex].dstate = this;
487     this->inst_buffer[dbindex].inst_index = dbindex;
488     this->inst_buffer[dbindex].inst_count = 1;
489     this->inst_buffer[dbindex].inst_addr = 0;
490     this->inst_buffer[dbindex].unchanged = FALSE;
491     NCInstBytesInitMemory(&this->inst_buffer[dbindex].inst.bytes,
492                           &this->memory);
493     NCInstBytesPtrInit((NCInstBytesPtr*) &this->inst_buffer[dbindex].inst_bytes,
494                        &this->inst_buffer[dbindex].inst.bytes);
495   }
496   this->cur_inst_index = 0;
497 }
498
499 void NCDecoderStateConstruct(NCDecoderState* this,
500                              uint8_t* mbase, NaClPcAddress vbase,
501                              NaClMemorySize size,
502                              NCDecoderInst* inst_buffer,
503                              size_t inst_buffer_size) {
504
505   /* Start by setting up virtual functions. */
506   this->action_fn = NullDecoderAction;
507   this->new_segment_fn = NullDecoderMethod;
508   this->segmentation_error_fn = NullDecoderMethod;
509   this->internal_error_fn = NullDecoderMethod;
510
511   /* Initialize the user-provided fields. */
512   this->mbase = mbase;
513   this->vbase = vbase;
514   this->size = size;
515   this->inst_buffer = inst_buffer;
516   this->inst_buffer_size = inst_buffer_size;
517
518   NCDecoderStateInitFields(this);
519 }
520
521 void NCDecoderStateDestruct(NCDecoderState* this) {
522   /* Currently, there is nothing to do. */
523 }
524
525 /* "Printable" means the value returned by this function can be used for
526  * printing user-readable output, but it should not be used to influence if the
527  * validation algorithm passes or fails.  The validation algorithm should not
528  * depend on vbase - in other words, it should not depend on where the code is
529  * being mapped in memory.
530  */
531 static INLINE NaClPcAddress NCPrintableVLimit(NCDecoderState *dstate) {
532   return dstate->vbase + dstate->size;
533 }
534
535 /* Modify the current instruction pointer to point to the next instruction
536  * in the ring buffer.  Reset the state of that next instruction.
537  */
538 static NCDecoderInst* IncrementInst(NCDecoderInst* inst) {
539   /* giving PreviousInst a positive number will get NextInst
540    * better to keep the buffer switching logic in one place
541    */
542   NCDecoderInst* next_inst = NCGetInstDiff(inst, 1);
543   next_inst->inst_addr = inst->inst_addr + inst->inst.bytes.length;
544   next_inst->dstate->cur_inst_index = next_inst->inst_index;
545   next_inst->inst_count = inst->inst_count + 1;
546   next_inst->unchanged = FALSE;
547   return next_inst;
548 }
549
550 /* Get the i-th byte of the current instruction being parsed. */
551 static uint8_t GetInstByte(NCDecoderInst* dinst, ssize_t i) {
552   if (i < dinst->inst.bytes.length) {
553     return dinst->inst.bytes.byte[i];
554   } else {
555     return NCRemainingMemoryLookaheadInline(&dinst->dstate->memory,
556                                             i - dinst->inst.bytes.length);
557   }
558 }
559
560 /* Consume a predefined nop byte sequence, if a match can be found.
561  * Further, if found, replace the currently matched instruction with
562  * the consumed predefined nop.
563  */
564 static void ConsumePredefinedNop(NCDecoderInst* dinst) {
565   /* Do maximal match of possible nops */
566   uint8_t pos = 0;
567   struct OpInfo* matching_opinfo = NULL;
568   ssize_t matching_length = 0;
569   NCNopTrieNode* next = (NCNopTrieNode*) (kNcNopTrieNode + 0);
570   uint8_t byte = GetInstByte(dinst, pos);
571   while (NULL != next) {
572     if (byte == next->matching_byte) {
573       DEBUG(printf("NOP match byte: 0x%02x\n", (int) byte));
574       byte = GetInstByte(dinst, ++pos);
575       if (NULL != next->matching_opinfo) {
576         DEBUG(printf("NOP matched rule! %d\n", pos));
577         matching_opinfo = next->matching_opinfo;
578         matching_length = pos;
579       }
580       next = next->success;
581     } else {
582       next = next->fail;
583     }
584   }
585   if (NULL == matching_opinfo) {
586     DEBUG(printf("NOP match failed!\n"));
587   } else {
588     DEBUG(printf("NOP match succeeds! Using last matched rule.\n"));
589     NCRemainingMemoryResetInline(&dinst->dstate->memory);
590     InitDecoder(dinst);
591     NCInstBytesReadBytesInline(matching_length, &dinst->inst.bytes);
592     dinst->opinfo = matching_opinfo;
593   }
594 }
595
596 /* If we didn't find a good instruction, try to consume one of the
597  * predefined NOP's.
598  */
599 static void MaybeConsumePredefinedNop(NCDecoderInst* dinst) {
600   switch (dinst->opinfo->insttype) {
601     case NACLi_UNDEFINED:
602     case NACLi_INVALID:
603     case NACLi_ILLEGAL:
604       ConsumePredefinedNop(dinst);
605       break;
606     default:
607       break;
608   }
609 }
610
611 /* All of the actions needed to read one additional instruction into mstate.
612  */
613 void NCConsumeNextInstruction(struct NCDecoderInst* inst) {
614   DEBUG( printf("Decoding instruction at %"NACL_PRIxNaClPcAddress":\n",
615                 inst->inst_addr) );
616   InitDecoder(inst);
617   ConsumePrefixBytes(inst);
618   ConsumeOpcodeBytes(inst);
619   ConsumeModRM(inst);
620   ConsumeSIB(inst);
621   ConsumeID(inst);
622   MaybeGet3ByteOpInfo(inst);
623   MaybeConsumePredefinedNop(inst);
624 }
625
626 void NCDecoderStateSetErrorReporter(NCDecoderState* this,
627                                     NaClErrorReporter* reporter) {
628   switch (reporter->supported_reporter) {
629     case NaClNullErrorReporter:
630     case NCDecoderInstErrorReporter:
631       this->error_reporter = reporter;
632       return;
633     default:
634       break;
635   }
636   (*reporter->printf)(
637       reporter,
638       "*** FATAL: using unsupported error reporter! ***\n"
639       "*** NCDecoderInstErrorReporter expected but found %s***\n",
640       NaClErrorReporterSupportedName(reporter->supported_reporter));
641   exit(1);
642 }
643
644 static void NCNullErrorPrintInst(NaClErrorReporter* self,
645                                  struct NCDecoderInst* inst) {}
646
647 NaClErrorReporter kNCNullErrorReporter = {
648   NaClNullErrorReporter,
649   NaClNullErrorPrintf,
650   NaClNullErrorPrintfV,
651   (NaClPrintInst) NCNullErrorPrintInst,
652 };
653
654 Bool NCDecoderStateDecode(NCDecoderState* this) {
655   NCDecoderInst* dinst = &this->inst_buffer[this->cur_inst_index];
656   DEBUG( printf("DecodeSegment(%p[%"NACL_PRIxNaClPcAddress"])\n",
657                 (void*) this->memory.mpc, (NaClPcAddress) this->size) );
658   NCDecoderStateNewSegment(this);
659   while (dinst->inst_addr < this->size) {
660     NCConsumeNextInstruction(dinst);
661     if (this->memory.overflow_count) {
662       NaClPcAddress newpc = (NCPrintableInstructionAddress(dinst)
663                              + dinst->inst.bytes.length);
664       (*this->error_reporter->printf)(
665           this->error_reporter,
666           "%"NACL_PRIxNaClPcAddress" > %"NACL_PRIxNaClPcAddress
667           " (read overflow of %d bytes)\n",
668           newpc, NCPrintableVLimit(this), this->memory.overflow_count);
669       ErrorSegmentation(dinst);
670       return FALSE;
671     }
672     if (!NCDecoderStateApplyAction(this, dinst)) return FALSE;
673     /* get ready for next round */
674     dinst = IncrementInst(dinst);
675   }
676   return TRUE;
677 }
678
679 /* Default action for a decoder state pair. */
680 static Bool NullNCDecoderStatePairAction(struct NCDecoderStatePair* tthis,
681                                          NCDecoderInst* old_inst,
682                                          NCDecoderInst* new_inst) {
683   return TRUE;
684 }
685
686 void NCDecoderStatePairConstruct(NCDecoderStatePair* tthis,
687                                  NCDecoderState* old_dstate,
688                                  NCDecoderState* new_dstate,
689                                  NaClCopyInstructionFunc copy_func) {
690   tthis->old_dstate = old_dstate;
691   tthis->new_dstate = new_dstate;
692   tthis->action_fn = NullNCDecoderStatePairAction;
693   tthis->copy_func = copy_func;
694 }
695
696 void NCDecoderStatePairDestruct(NCDecoderStatePair* tthis) {
697 }
698
699 Bool NCDecoderStatePairDecode(NCDecoderStatePair* tthis) {
700   NCDecoderInst* old_dinst =
701       &tthis->old_dstate->inst_buffer[tthis->old_dstate->cur_inst_index];
702   NCDecoderInst* new_dinst =
703       &tthis->new_dstate->inst_buffer[tthis->new_dstate->cur_inst_index];
704
705   /* Verify that the size of the code segments is the same, and has not
706    * been changed.
707    */
708   if (tthis->old_dstate->size != tthis->new_dstate->size) {
709     /* If sizes differ, then they can't be the same, except for some
710      * (constant-sized) changes. Hence fail to decode.
711      */
712     ErrorSegmentation(new_dinst);
713     return FALSE;
714   }
715
716   /* Since the sizes of the segments are the same, only one limit
717    * needs to be checked. Hence, we will track the limit of the new
718    * decoder state.
719    */
720   DEBUG( printf("NCDecoderStatePairDecode(%"NACL_PRIxNaClPcAddress")\n",
721                 (NaClPcAddress) tthis->new_dstate->size));
722
723   /* Initialize decoder statements for decoding segment, by calling
724    * the corresponding virtual in the decoder.
725    */
726   NCDecoderStateNewSegment(tthis->old_dstate);
727   NCDecoderStateNewSegment(tthis->new_dstate);
728
729   /* Walk through both instruction segments, checking that
730    * they decode similarly.
731    */
732   while (new_dinst->inst_addr < tthis->new_dstate->size) {
733
734     NCConsumeNextInstruction(old_dinst);
735     NCConsumeNextInstruction(new_dinst);
736
737
738     /* Verify that the instruction lengths match. */
739     if (old_dinst->inst.bytes.length !=
740         new_dinst->inst.bytes.length) {
741       ErrorInternal(new_dinst);
742       return FALSE;
743     }
744
745     /* Verify that we haven't walked past the end of the segment
746      * in either decoder state.
747      *
748      * Note: Since instruction lengths are the same, and the
749      * segment lengths are the same, if overflow occurs on one
750      * segment, it must occur on the other.
751      */
752     if (new_dinst->inst_addr > tthis->new_dstate->size) {
753       NaClErrorReporter* reporter = new_dinst->dstate->error_reporter;
754       (*reporter->printf)(
755           reporter,
756           "%"NACL_PRIxNaClPcAddress" > %"NACL_PRIxNaClPcAddress"\n",
757           NCPrintableInstructionAddress(new_dinst),
758           NCPrintableVLimit(tthis->new_dstate));
759       ErrorSegmentation(new_dinst);
760       return FALSE;
761     }
762
763     /* Apply the action to the instructions, and continue
764      * only if the action succeeds.
765      */
766     if (! (tthis->action_fn)(tthis, old_dinst, new_dinst)) {
767       return FALSE;
768     }
769
770     /* Move to next instruction. */
771     old_dinst = IncrementInst(old_dinst);
772     new_dinst = IncrementInst(new_dinst);
773   }
774   return TRUE;
775 }