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.
7 #ifndef NACL_TRUSTED_BUT_NOT_TCB
8 #error("This file is not meant for use in the TCB")
11 #include "native_client/src/trusted/validator_x86/ncenuminsts.h"
13 #include "native_client/src/shared/platform/nacl_log.h"
14 #include "native_client/src/trusted/validator/ncvalidate.h"
15 #include "native_client/src/trusted/validator/x86/decoder/ncop_exps.h"
16 #include "native_client/src/trusted/validator/x86/decoder/nc_inst_iter.h"
17 #include "native_client/src/trusted/validator/x86/decoder/nc_inst_state.h"
18 #include "native_client/src/trusted/validator_x86/ncdis_decode_tables.h"
19 #include "native_client/src/trusted/validator/x86/ncval_reg_sfi/ncvalidate_iter.h"
20 #include "native_client/src/trusted/validator/x86/ncval_reg_sfi/ncvalidate_iter_internal.h"
21 #include "native_client/src/trusted/validator/x86/ncval_reg_sfi/nc_illegal.h"
22 #include "native_client/src/trusted/validator/x86/ncval_reg_sfi/nc_memory_protect.h"
23 #include "native_client/src/trusted/validator/x86/nc_segment.h"
25 /* To turn on debugging of instruction decoding, change value of
30 #include "native_client/src/shared/utils/debugging.h"
32 NaClInstStruct *NaClParseInst(uint8_t* ibytes, size_t isize,
33 const NaClPcAddress vbase) {
35 /* WARNING: This version of the code uses a global to return the
36 * decoded instruction, forcing the use to be in a single thread.
37 * The following two (static) locals are used to hold the decoded
38 * instruction until the next call to the function.
40 static NaClInstIter* ND_iterator = NULL;
41 static NaClSegment ND_segment;
43 NaClSegmentInitialize(ibytes, vbase, isize, &ND_segment);
44 if (ND_iterator != NULL) {
45 NaClInstIterDestroy(ND_iterator);
47 ND_iterator = NaClInstIterCreate(kNaClDecoderTables, &ND_segment);
48 return NaClInstIterGetState(ND_iterator);
51 uint8_t NaClInstLength(NaClInstStruct *inst) {
52 return NaClInstStateLength(inst);
55 char *NaClInstToStr(NaClInstStruct *inst) {
56 return NaClInstStateInstructionToString(inst);
59 const char *NaClOpcodeName(NaClInstStruct *inst) {
60 const struct NaClInst *nacl_opcode = NaClInstStateInst(inst);
61 return NaClMnemonicName(nacl_opcode->name);
64 Bool NaClInstDecodesCorrectly(NaClInstStruct *inst) {
65 return NaClInstStateIsValid(inst);
68 Bool NaClInstValidates(uint8_t* mbase,
71 NaClInstStruct* inst) {
73 NaClValidatorState* state;
74 Bool validates = FALSE;
75 NaClCPUFeaturesX86 cpu_features;
77 NaClGetCurrentCPUFeaturesX86((NaClCPUFeatures *) &cpu_features);
78 NACL_FLAGS_unsafe_single_inst_mode = TRUE;
79 state = NaClValidatorStateCreate(vbase, (NaClMemorySize) size, RegR15, FALSE,
82 NaClSegmentInitialize(mbase, vbase, (NaClMemorySize) size, &segment);
83 NaClBaseRegisterMemoryInitialize(state);
84 state->cur_iter = NaClInstIterCreate(kNaClDecoderTables, &segment);
85 if (NULL == state->cur_iter) break;
86 state->cur_inst_state = NaClInstIterGetState(state->cur_iter);
87 state->cur_inst = NaClInstStateInst(state->cur_inst_state);
88 state->cur_inst_vector = NaClInstStateExpVector(state->cur_inst_state);
89 NaClValidateInstructionLegal(state);
90 NaClBaseRegisterValidator(state);
91 /* induce call to NaClMaybeReportPreviousBad() */
92 NaClBaseRegisterSummarize(state);
93 NaClMemoryReferenceValidator(state);
94 NaClJumpValidator(state);
95 validates = NaClValidatesOk(state);
96 NaClInstIterDestroy(state->cur_iter);
97 state->cur_iter = NULL;
98 state->cur_inst_state = NULL;
99 state->cur_inst = NULL;
100 state->cur_inst_vector = NULL;
102 NaClValidatorStateDestroy(state);
103 /* Strictly speaking this shouldn't be necessary, as the mode */
104 /* should only be used from tests. Disabling it here as a */
105 /* defensive tactic. */
106 NACL_FLAGS_unsafe_single_inst_mode = FALSE;
110 Bool NaClSegmentValidates(uint8_t* mbase,
112 NaClPcAddress vbase) {
113 NaClCPUFeaturesX86 cpu_features;
114 NaClValidationStatus status;
115 /* TODO(pasko): Validator initialization can be slow, make it run only once.
117 const struct NaClValidatorInterface *validator = NaClCreateValidator();
119 /* check if NaCl thinks the given code segment is valid. */
120 validator->SetAllCPUFeatures((NaClCPUFeatures *) &cpu_features);
121 status = validator->Validate(
123 /* stubout_mode= */ FALSE, /* readonly_text= */ FALSE,
124 (NaClCPUFeatures *) &cpu_features, NULL, NULL);
126 case NaClValidationSucceeded: