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

Side by Side Diff: src/trusted/validator/x86/ncval_seg_sfi/ncdecode_verbose.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 * ncdecode_verbose.c - Print routines for validator that are
9 * not to be loaded into sel_ldr.
10 */
11
12 #include "native_client/src/trusted/validator/x86/ncval_seg_sfi/ncdecode_verbose .h"
13
14 #include <stdio.h>
15 #include <stdlib.h>
16 #include <string.h>
17
18 #include "native_client/src/shared/gio/gio.h"
19 #include "native_client/src/shared/platform/nacl_log.h"
20 #include "native_client/src/trusted/validator/x86/ncval_seg_sfi/ncdecode.h"
21
22 #include "native_client/src/trusted/validator/x86/x86_insts_inl.c"
23
24 #if NACL_TARGET_SUBARCH == 64
25 #include "native_client/src/trusted/validator/x86/ncval_seg_sfi/gen/ncdisasmtab_ 64.h"
26 #else
27 #include "native_client/src/trusted/validator/x86/ncval_seg_sfi/gen/ncdisasmtab_ 32.h"
28 #endif
29
30 /* To turn on debugging of instruction decoding, change value of
31 * DEBUGGING to 1.
32 */
33 #define DEBUGGING 0
34
35 #include "native_client/src/shared/utils/debugging.h"
36
37 /* The following are conditionally added since they only have meaning
38 * if we are processing 64-bit instructions.
39 */
40 #if NACL_TARGET_SUBARCH == 64
41
42 /* Returns true if REX.W is defined in the REX prefix byte. */
43 static INLINE uint8_t GetRexPrefixW(const NCDecoderInst* dinst) {
44 /* Note: the field rexprefix is non-zero only if a rexprefix was found. */
45 return 0 != NaClRexW(dinst->inst.rexprefix);
46 }
47
48 /* Returns true if REX.R is defined in the REX prefix byte. */
49 static INLINE uint8_t GetRexPrefixR(const NCDecoderInst* dinst) {
50 /* Note: the field rexprefix is non-zero only if a rexprefix was found. */
51 return 0 != NaClRexR(dinst->inst.rexprefix);
52 }
53
54 #endif
55
56 /* Returns the index into the general purpose registers based on the
57 * value in the modrm.rm field of the instruction (taking into account
58 * the REX prefix if it appears).
59 */
60 static INLINE uint32_t state_modrm_reg(const NCDecoderInst* dinst) {
61 /* TODO(karl) This is no where near close to being correct. Currently,
62 * It only models r/m64 entry for instructions in the Intel documentation,
63 * which requires the W bit to be set (r/m32 entries do not use REX.w,
64 * and a different set of registers).
65 */
66 uint32_t index = modrm_regInline(dinst->inst.mrm);
67 #if NACL_TARGET_SUBARCH == 64
68 if (GetRexPrefixW(dinst) && GetRexPrefixR(dinst)) {
69 index += 8;
70 }
71 #endif
72 return index;
73 }
74
75 /* Returns the index for the first instruction opcode byte. */
76 static INLINE int NCOpcodeOffset(const NCDecoderInst* dinst) {
77 return dinst->inst.prefixbytes;
78 }
79
80 /* Returns the index for the modrm byte. */
81 static INLINE int NCMrmOffset(const NCDecoderInst* dinst) {
82 return NCOpcodeOffset(dinst) + dinst->inst.num_opbytes;
83 }
84
85 /* Returns the index of the sib byte (if it has one). */
86 static INLINE int NCSibOffset(const NCDecoderInst* dinst) {
87 /* Note: The sib byte follows the mrm byte. */
88 return NCMrmOffset(dinst) + 1;
89 }
90
91 /* Returns the beginning index for the displacement (if it has one). */
92 static int NCDispOffset(const NCDecoderInst* dinst) {
93 if (dinst->opinfo->hasmrmbyte) {
94 if (dinst->inst.hassibbyte) {
95 return NCSibOffset(dinst) + 1;
96 } else {
97 return NCMrmOffset(dinst) + 1;
98 }
99 } else {
100 return NCOpcodeOffset(dinst) + dinst->inst.num_opbytes;
101 }
102 }
103
104 /* Returns the beginning index for the immediate value. */
105 static INLINE int NCImmedOffset(const NCDecoderInst* dinst) {
106 return NCDispOffset(dinst) + dinst->inst.dispbytes;
107 }
108
109 /* later this will make decoding x87 instructions a bit more concise. */
110 static const char** kDisasmX87Op[8] = {kDisasm87D8,
111 kDisasm87D9,
112 kDisasm87DA,
113 kDisasm87DB,
114 kDisasm87DC,
115 kDisasm87DD,
116 kDisasm87DE,
117 kDisasm87DF};
118
119 const char** kDummyUsesToAvoidCompilerWarning[] = {kDisasm660F38Op,
120 kDisasmF20F38Op,
121 kDisasm660F3AOp};
122
123 /* disassembler stuff */
124 static const char* DisFmt(const NCDecoderInst *dinst) {
125 NCInstBytesPtr opbyte;
126 uint8_t opbyte0;
127 uint8_t opbyte1;
128 uint8_t pm = dinst->inst.opcode_prefixmask;
129 NCInstBytesPtrInitInc(&opbyte, &dinst->inst_bytes, NCOpcodeOffset(dinst));
130 opbyte0 = NCInstBytesByte(&opbyte, 0);
131
132 if (dinst->opinfo->insttype == NACLi_X87 ||
133 dinst->opinfo->insttype == NACLi_X87_FSINCOS) {
134 if (opbyte0 != kWAITOp) {
135 return kDisasmX87Op[opbyte0 - kFirstX87Opcode][dinst->inst.mrm];
136 }
137 }
138 if (dinst->opinfo->insttype == NACLi_FCMOV) {
139 return kDisasmX87Op[opbyte0 - kFirstX87Opcode][dinst->inst.mrm];
140 }
141 if (dinst->opinfo->insttype == NACLi_NOP) return "nop";
142 if (opbyte0 != kTwoByteOpcodeByte1) return kDisasm1ByteOp[opbyte0];
143 opbyte1 = NCInstBytesByte(&opbyte, 1);
144 if (opbyte1 == 0x0f) {
145 return kDisasm0F0FOp[
146 NCInstBytesByte(&opbyte, dinst->inst.bytes.length - 1)];
147 }
148 if (opbyte1 == 0x38) {
149 return kDisasm0F38Op[NCInstBytesByte(&opbyte, 2)];
150 }
151 if (opbyte1 == 0x3A) {
152 return kDisasm0F3AOp[NCInstBytesByte(&opbyte, 2)];
153 }
154 if (! (pm & (kPrefixDATA16 | kPrefixREPNE | kPrefixREP))) {
155 return kDisasm0FXXOp[opbyte1];
156 }
157 if (pm & kPrefixDATA16) return kDisasm660FXXOp[opbyte1];
158 if (pm & kPrefixREPNE) return kDisasmF20FXXOp[opbyte1];
159 if (pm & kPrefixREP) return kDisasmF30FXXOp[opbyte1];
160
161 /* no update; should be invalid */
162 return "internal error";
163 }
164
165 /* Returns the (sign extended) 32-bit integer immediate value. */
166 static int32_t ImmedValue32(const NCDecoderInst* dinst) {
167 NCInstBytesPtr addr;
168 NCInstBytesPtrInitInc(&addr, &dinst->inst_bytes,
169 NCImmedOffset(dinst));
170 return NCInstBytesInt32(&addr, dinst->inst.immbytes);
171 }
172
173 /* Returns the (sign extended) 64-bit integer immediate value. */
174 static int64_t ImmedValue64(const NCDecoderInst* dinst) {
175 NCInstBytesPtr addr;
176 NCInstBytesPtrInitInc(&addr, &dinst->inst_bytes,
177 NCImmedOffset(dinst));
178 return NCInstBytesInt64(&addr, dinst->inst.immbytes);
179 }
180
181 /* Returns the (sign extended) 32-bit integer displacement value. */
182 static int32_t DispValue32(const NCDecoderInst* dinst) {
183 NCInstBytesPtr addr;
184 NCInstBytesPtrInitInc(&addr, &dinst->inst_bytes,
185 NCDispOffset(dinst));
186 return NCInstBytesInt32(&addr, dinst->inst.dispbytes);
187 }
188
189 /* Defines the set of available general purpose registers. */
190 static const char* gp_regs[] = {
191 #if NACL_TARGET_SUBARCH == 64
192 /* TODO(karl) - Depending on whether the instruction uses r/m32
193 * of r/m64 forms (according to the Intel document), the list of
194 * (16) registers is different. Currently, we are only handling
195 * the r/m64 case.
196 */
197 "%rax", "%rcx", "%rdx", "%rbx", "%rsp", "%rbp", "%rsi", "%rdi",
198 "%r8", "%r9", "%r10", "%r11", "%r12", "%r13", "%r14", "%r15"
199 #else
200 "%eax", "%ecx", "%edx", "%ebx", "%esp", "%ebp", "%esi", "%edi"
201 #endif
202 };
203
204
205 static const char* mmx_regs[] = {
206 "%mm0", "%mm1", "%mm2", "%mm3", "%mm4", "%mm5", "%mm6", "%mm7"
207 };
208
209 static const char* xmm_regs[] = {
210 "%xmm0", "%xmm1", "%xmm2", "%xmm3", "%xmm4", "%xmm5", "%xmm6", "%xmm7"
211 };
212
213 static const char* seg_regs[] = {
214 "%es", "%cs", "%ss", "%ds", "%fs", "%gs"
215 };
216
217 /* Print out the sib byte of the parsed instruction in the given decoder state
218 * to the given file.
219 */
220 static void SibPrint(const NCDecoderInst* dinst, struct Gio* fp) {
221 uint8_t sib = NCInstBytesByte(&dinst->inst_bytes, NCSibOffset(dinst));
222
223 if (!dinst->inst.hassibbyte) {
224 /* This should not happen. */
225 gprintf(fp, "?");
226 } else if (sib_ss(sib) == 0) {
227 if (sib_base(sib) == 5) {
228 /* This code is JUST WRONG!. However, I am not fixing since
229 * the decoder printer is broken in so many other ways!. See tables
230 * 2-1 and 2-2 of "Intel 64 and IA-32 Architectures Software Developer's
231 * Manual" for details of what should be done (there are
232 * 3 cases, depending on the value of the mod field of the modrm
233 * byte).
234 * Note: While the changes here are not correct, they at least make
235 * sure that we process bytes that are actually in the instruction.
236 * That is, the code doesn't accidentally walk off the end of the
237 * parsed instruction.
238 */
239 gprintf(fp, "[0x%x]", DispValue32(dinst));
240 } else {
241 /* Has a base register */
242 if (sib_index(sib) == 4) {
243 /* No index */
244 gprintf(fp, "[%s]", gp_regs[sib_base(sib)]);
245 } else {
246 gprintf(fp, "[%s + %s]",
247 gp_regs[sib_base(sib)],
248 gp_regs[sib_index(sib)]);
249 }
250 }
251 } else {
252 if (sib_index(sib) == 4) {
253 /* No index */
254 gprintf(fp, "[%s]", gp_regs[sib_base(sib)]);
255 } else {
256 gprintf(fp, "[%s + %d * %s]",
257 gp_regs[sib_base(sib)],
258 1 << sib_ss(sib),
259 gp_regs[sib_index(sib)]);
260 }
261 }
262 }
263
264 static void SegPrefixPrint(const NCDecoderInst *dinst, struct Gio* fp) {
265 uint8_t pm = dinst->inst.prefixmask;
266 if (pm & kPrefixSEGCS) {
267 gprintf(fp, "cs:");
268 } else if (pm & kPrefixSEGSS) {
269 gprintf(fp, "ss:");
270 } else if (pm & kPrefixSEGFS) {
271 gprintf(fp, "fs:");
272 } else if (pm & kPrefixSEGGS) {
273 gprintf(fp, "gs:");
274 }
275 }
276
277 /* Append that we don't bother to translate the instruction argument,
278 * since it is NaCl illegal. Used to handle cases where we don't implement
279 * 16-bit modrm effective addresses.
280 */
281 static INLINE void NaClIllegalOp(struct Gio* fp) {
282 gprintf(fp, "*NaClIllegal*");
283 }
284
285 /* Print out the register (from the list of register names),
286 * that is referenced by the decoded instruction in the
287 * decoder state. If is_gp_regs is true, the register names
288 * correspond to general purpose register names. Otherwise,
289 * they are some other set, such as MMX or XMM.
290 */
291 static void RegMemPrint(const NCDecoderInst *dinst,
292 const char* reg_names[],
293 const uint8_t is_gp_regs,
294 struct Gio* fp) {
295 DEBUG( printf(
296 "reg mem print: sib_offset = %d, "
297 "disp_offset = %d, mrm.mod = %02x\n",
298 NCSibOffset(dinst), (int) NCDispOffset(dinst),
299 modrm_modInline(dinst->inst.mrm)) );
300 switch (modrm_modInline(dinst->inst.mrm)) {
301 case 0:
302 SegPrefixPrint(dinst, fp);
303 if (NaClHasBit(dinst->inst.prefixmask, kPrefixADDR16)) {
304 NaClIllegalOp(fp);
305 } else {
306 if (4 == modrm_rmInline(dinst->inst.mrm)) {
307 SibPrint(dinst, fp);
308 } else if (5 == modrm_rmInline(dinst->inst.mrm)) {
309 gprintf(fp, "[0x%x]", DispValue32(dinst));
310 } else {
311 gprintf(fp, "[%s]", gp_regs[modrm_rmInline(dinst->inst.mrm)]);
312 }
313 }
314 break;
315 case 1:
316 SegPrefixPrint(dinst, fp);
317 if (NaClHasBit(dinst->inst.prefixmask, kPrefixADDR16)) {
318 NaClIllegalOp(fp);
319 } else {
320 gprintf(fp, "0x%x", DispValue32(dinst));
321 if (4 == modrm_rmInline(dinst->inst.mrm)) {
322 SibPrint(dinst, fp);
323 } else {
324 gprintf(fp, "[%s]", gp_regs[modrm_rmInline(dinst->inst.mrm)]);
325 }
326 }
327 break;
328 case 2:
329 SegPrefixPrint(dinst, fp);
330 if (NaClHasBit(dinst->inst.prefixmask, kPrefixADDR16)) {
331 NaClIllegalOp(fp);
332 } else {
333 gprintf(fp, "0x%x", DispValue32(dinst));
334 if (4 == modrm_rmInline(dinst->inst.mrm)) {
335 SibPrint(dinst, fp);
336 } else {
337 gprintf(fp, "[%s]", gp_regs[modrm_rmInline(dinst->inst.mrm)]);
338 }
339 }
340 break;
341 case 3:
342 if (is_gp_regs) {
343 gprintf(fp, "%s", reg_names[state_modrm_reg(dinst)]);
344 } else {
345 gprintf(fp, "%s", reg_names[modrm_rmInline(dinst->inst.mrm)]);
346 }
347 break;
348 }
349 }
350
351 /* Parses the group name in token. Returns NOGROUP(0) if unable to parse. */
352 static NaClMRMGroups ParseGroupName(const char* token) {
353 if (!strncmp(token, "group", 5)) {
354 /* Matched group name prefix, recognize last two characters explicitly.*/
355 const char* suffix = token + 5;
356 switch (strlen(suffix)) {
357 case 1:
358 switch (suffix[0]) {
359 case '1':
360 return GROUP1;
361 case '2':
362 return GROUP2;
363 case '3':
364 return GROUP3;
365 case '4':
366 return GROUP4;
367 case '5':
368 return GROUP5;
369 case '6':
370 return GROUP6;
371 case '7':
372 return GROUP7;
373 case '8':
374 return GROUP8;
375 case '9':
376 return GROUP9;
377 case 'p':
378 return GROUPP;
379 default:
380 break;
381 }
382 break;
383 case 2:
384 if (suffix[0] == '1') {
385 switch(suffix[1]) {
386 case '0':
387 return GROUP10;
388 case '1':
389 return GROUP11;
390 case '2':
391 return GROUP12;
392 case '3':
393 return GROUP13;
394 case '4':
395 return GROUP14;
396 case '5':
397 return GROUP15;
398 case '6':
399 return GROUP16;
400 case '7':
401 return GROUP17;
402 case 'a':
403 return GROUP1A;
404 default:
405 break;
406 }
407 }
408 break;
409 default:
410 break;
411 }
412 }
413 return 0;
414 }
415
416 static void InstFormat(const char* format,
417 const NCDecoderInst *dinst,
418 struct Gio* fp) {
419 char token_buf[128];
420 char* fmt = token_buf;
421 int pos = 0;
422
423 strncpy(token_buf, format, sizeof(token_buf));
424
425 while (1) {
426 char* token = strtok(fmt, " ,\n");
427 DEBUG( printf("\ntoken = '%s'\n", token) );
428 if (NULL == token) {
429 break;
430 }
431 if (pos > 1) {
432 gprintf(fp, ", ");
433 } else if (pos > 0) {
434 gprintf(fp, " ");
435 }
436 if ('$' == token[0]) {
437 NaClMRMGroups group = ParseGroupName(token+1);
438 if (NOGROUP != group) {
439 int mrm = modrm_regInline(dinst->inst.mrm);
440 const char* opname = kDisasmModRMOp[group][mrm];
441 DEBUG( printf("case: group %d, opname = %s\n", group, opname) );
442 gprintf(fp, "%s", opname);
443 } else {
444 /* Tokens starting with a $ but not $group need formatting */
445 DEBUG( printf("case: $ and not group\n") );
446 switch (token[1]) {
447 case 'A':
448 gprintf(fp, "$A");
449 break;
450 case 'C':
451 gprintf(fp, "%%cr%d", modrm_regInline(dinst->inst.mrm));
452 break;
453 case 'D':
454 gprintf(fp, "%%dr%d", modrm_regInline(dinst->inst.mrm));
455 break;
456 case 'E':
457 case 'M': /* mod should never be 3 for 'M' */
458 /* TODO(sehr): byte and word accesses */
459 RegMemPrint(dinst, gp_regs, 1, fp);
460 break;
461 case 'F':
462 gprintf(fp, "eflags");
463 break;
464 case 'G':
465 gprintf(fp, "%s", gp_regs[modrm_regInline(dinst->inst.mrm)]);
466 break;
467 case 'I':
468 gprintf(fp, "0x%"NACL_PRIx64, ImmedValue64(dinst));
469 break;
470 case 'J':
471 gprintf(fp, "0x%"NACL_PRIxNaClPcAddress,
472 NCPrintableInstructionAddress(dinst)
473 + dinst->inst.bytes.length
474 + ImmedValue32(dinst));
475 break;
476 case 'O':
477 gprintf(fp, "[0x%"NACL_PRIx64"]", ImmedValue64(dinst));
478 break;
479 case 'P':
480 if ('R' == token[2]) {
481 gprintf(fp, "%%mm%d", modrm_rmInline(dinst->inst.mrm));
482 } else {
483 gprintf(fp, "%%mm%d", modrm_regInline(dinst->inst.mrm));
484 }
485 break;
486 case 'Q':
487 RegMemPrint(dinst, mmx_regs, 0, fp);
488 break;
489 case 'R':
490 gprintf(fp, "%s", gp_regs[modrm_rmInline(dinst->inst.mrm)]);
491 break;
492 case 'S':
493 gprintf(fp, "%s", seg_regs[modrm_regInline(dinst->inst.mrm)]);
494 break;
495 case 'V':
496 if ('R' == token[2]) {
497 gprintf(fp, "%%xmm%d", modrm_rmInline(dinst->inst.mrm));
498 } else {
499 gprintf(fp, "%%xmm%d", modrm_regInline(dinst->inst.mrm));
500 }
501 break;
502 case 'W':
503 RegMemPrint(dinst, xmm_regs, 0, fp);
504 break;
505 case 'X':
506 gprintf(fp, "ds:[esi]");
507 break;
508 case 'Y':
509 gprintf(fp, "es:[edi]");
510 break;
511 default:
512 gprintf(fp, "token('%s')", token);
513 break;
514 }
515 }
516 } else {
517 /* Print the token as is */
518 gprintf(fp, "%s", token);
519 }
520 fmt = NULL;
521 ++pos;
522 }
523 }
524
525 static void NCPrintInstTextUsingFormat(const char* format,
526 const NCDecoderInst *dinst,
527 struct Gio* fp) {
528 InstFormat(format, dinst, fp);
529 gprintf(fp, "\n");
530 }
531
532 void NCPrintInstWithoutHex(const NCDecoderInst *dinst, struct Gio* fp) {
533 DEBUG( printf("use format: %s\n", DisFmt(dinst)) );
534 NCPrintInstTextUsingFormat(DisFmt(dinst), dinst, fp);
535 }
536
537 void NCPrintInstWithHex(const NCDecoderInst *dinst, struct Gio *fp) {
538 int i;
539 DEBUG( printf("use format: %s\n", DisFmt(dinst)) );
540 gprintf(fp, " %"NACL_PRIxNaClPcAddress":\t%02x",
541 NCPrintableInstructionAddress(dinst),
542 NCInstBytesByte(&dinst->inst_bytes, 0));
543 for (i = 1; i < dinst->inst.bytes.length; i++) {
544 gprintf(fp, " %02x", NCInstBytesByte(&dinst->inst_bytes, i));
545 }
546 for (i = dinst->inst.bytes.length; i < 7; i++) gprintf(fp, " ");
547 gprintf(fp, "\t");
548 NCPrintInstWithoutHex(dinst, fp);
549 }
550
551 static Bool PrintInstLogGio(const NCDecoderInst *dinst) {
552 NCPrintInstWithHex(dinst, NaClLogGetGio());
553 return TRUE;
554 }
555
556 /* Defines a buffer size big enough to hold an instruction. */
557 #define MAX_INST_TEXT_SIZE 256
558
559 /* Defines an instruction print function. */
560 typedef void (*inst_print_fn)(const struct NCDecoderInst* inst,
561 struct Gio *file);
562
563 /* Print out the given instruction, using the given instruction print function,
564 * and return the printed text as a (malloc allocated) string.
565 */
566 static char* InstToStringConvert(const NCDecoderInst* dinst,
567 inst_print_fn print_fn) {
568 /* Print to a memory buffer, and then duplicate. */
569 struct GioMemoryFile filemem;
570 struct Gio *file = (struct Gio*) &filemem;
571 char buffer[MAX_INST_TEXT_SIZE];
572 char* result;
573
574 /* Note: Be sure to leave an extra byte to add the null character to
575 * the end of the string.
576 */
577 GioMemoryFileCtor(&filemem, buffer, MAX_INST_TEXT_SIZE - 1);
578 print_fn(dinst, file);
579 buffer[filemem.curpos < MAX_INST_TEXT_SIZE
580 ? filemem.curpos : MAX_INST_TEXT_SIZE] ='\0';
581 result = strdup(buffer);
582 GioMemoryFileDtor(file);
583 return result;
584 }
585
586 char* NCInstWithHexToString(const NCDecoderInst* dinst) {
587 return InstToStringConvert(dinst, NCPrintInstWithHex);
588 }
589
590 char* NCInstWithoutHexToString(const NCDecoderInst* dinst) {
591 return InstToStringConvert(dinst, NCPrintInstWithoutHex);
592 }
593
594 void NCDecodeSegment(uint8_t* mbase, NaClPcAddress vbase,
595 NaClMemorySize size) {
596 NCDecoderInst inst;
597 NCDecoderState dstate;
598 NCDecoderStateConstruct(&dstate, mbase, vbase, size, &inst, 1);
599 NCDecoderStateSetErrorReporter(&dstate, &kNCVerboseErrorReporter);
600 /* TODO(karl): Fix this so that we don't need to override the
601 * action function.
602 */
603 dstate.action_fn = PrintInstLogGio;
604 NCDecoderStateDecode(&dstate);
605 NCDecoderStateDestruct(&dstate);
606 }
607
608 static void NCVerboseErrorPrintInst(NaClErrorReporter* self,
609 NCDecoderInst* dinst) {
610 PrintInstLogGio(dinst);
611 }
612
613 NaClErrorReporter kNCVerboseErrorReporter = {
614 NCDecoderInstErrorReporter,
615 NaClVerboseErrorPrintf,
616 NaClVerboseErrorPrintfV,
617 (NaClPrintInst) NCVerboseErrorPrintInst
618 };
OLDNEW
« no previous file with comments | « src/trusted/validator/x86/ncval_seg_sfi/ncdecode_verbose.h ('k') | src/trusted/validator/x86/ncval_seg_sfi/ncvalidate.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698