| OLD | NEW |
| (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 * input_tester.c | |
| 9 * Implements a decoder that matches the input enumeration fed into stdin. | |
| 10 */ | |
| 11 #ifndef NACL_TRUSTED_BUT_NOT_TCB | |
| 12 #error("This file is not meant for use in the TCB.") | |
| 13 #endif | |
| 14 | |
| 15 #include "native_client/src/trusted/validator/x86/testing/enuminsts/input_tester
.h" | |
| 16 | |
| 17 #include <stdio.h> | |
| 18 #include <string.h> | |
| 19 | |
| 20 #include "native_client/src/trusted/validator/types_memory_model.h" | |
| 21 #include "native_client/src/trusted/validator/x86/ncinstbuffer.h" | |
| 22 #include "native_client/src/trusted/validator/x86/testing/enuminsts/str_utils.h" | |
| 23 #include "native_client/src/trusted/validator/x86/testing/enuminsts/text2hex.h" | |
| 24 | |
| 25 #define kBufferSize 1024 | |
| 26 | |
| 27 /* Defines the virtual table for the input decoder. */ | |
| 28 static struct { | |
| 29 /* The virtual table that implements this decoder. */ | |
| 30 NaClEnumeratorDecoder base_; | |
| 31 /* The iput text line. */ | |
| 32 char line_[kBufferSize]; | |
| 33 /* The number of bytes in the last instruction read from the | |
| 34 * input stream. | |
| 35 */ | |
| 36 int num_bytes_; | |
| 37 /* The input line number associated with the last instruction | |
| 38 * read from the input stream. | |
| 39 */ | |
| 40 int line_number_; | |
| 41 /* The specified pc address when parsing. */ | |
| 42 NaClPcAddress pc_address_; | |
| 43 /* The instruction mnemonic, if defined. */ | |
| 44 char* mnemonic_; | |
| 45 /* The instruction arguments, if defined. */ | |
| 46 char* operands_; | |
| 47 /* Buffer used to hold mnemonic name and operands. */ | |
| 48 char buffer_[kBufferSize]; | |
| 49 /* Boolean flag defining if we have processed the first | |
| 50 * line of input, which specifies how to configure the | |
| 51 * the input decoder. | |
| 52 */ | |
| 53 Bool configured_; | |
| 54 } input_decoder; | |
| 55 | |
| 56 /* Defines the function to parse the first instruction in the enumerator | |
| 57 * text. Since we are accepting the input that was set up the input | |
| 58 * enumeration, there is nothing to do. | |
| 59 */ | |
| 60 static void ParseInst(const NaClEnumerator* enumerator, | |
| 61 const int pc_address) { | |
| 62 UNREFERENCED_PARAMETER(enumerator); | |
| 63 input_decoder.pc_address_ = pc_address; | |
| 64 input_decoder.mnemonic_ = NULL; | |
| 65 input_decoder.operands_ = NULL; | |
| 66 } | |
| 67 | |
| 68 /* Finds the instruction mnemonic, by looking at the end of the | |
| 69 * input line. Looks for a comment of the form '#mnemonic operands' | |
| 70 */ | |
| 71 static void AssembleDesc(const NaClEnumerator* enumerator) { | |
| 72 char* desc; | |
| 73 char* end; | |
| 74 UNREFERENCED_PARAMETER(enumerator); | |
| 75 | |
| 76 /* Start by looking for description. */ | |
| 77 desc = (char*) strip(strskip(input_decoder.line_, "#")); | |
| 78 if (desc == NULL) { | |
| 79 /* Not found, fill in a default value. */ | |
| 80 input_decoder.mnemonic_ = "???"; | |
| 81 input_decoder.operands_ = ""; | |
| 82 return; | |
| 83 } | |
| 84 /* Copy the description into the buffer, and then extract the needed parts. */ | |
| 85 cstrncpy(input_decoder.buffer_, desc, kBufferSize); | |
| 86 input_decoder.mnemonic_ = input_decoder.buffer_; | |
| 87 end = (char*) strfind(input_decoder.buffer_, " "); | |
| 88 if (end == NULL) { | |
| 89 /* No operands, clean up mnemonic. */ | |
| 90 rstrip(input_decoder.buffer_); | |
| 91 input_decoder.operands_ = ""; | |
| 92 return; | |
| 93 } | |
| 94 /* Has mnemonic and operands. Separate out parts. */ | |
| 95 *end = '\0'; | |
| 96 input_decoder.operands_ = (char*) strip(end + 1); | |
| 97 rstrip(input_decoder.operands_); | |
| 98 } | |
| 99 | |
| 100 /* Finds the instruction mnemonic, by looking at the end of the | |
| 101 * input line. Looks for a comment of the form '#mnemonic operands' | |
| 102 */ | |
| 103 static const char* GetInstMnemonic(const NaClEnumerator* enumerator) { | |
| 104 if (input_decoder.mnemonic_ != NULL) return input_decoder.mnemonic_; | |
| 105 AssembleDesc(enumerator); | |
| 106 return input_decoder.mnemonic_; | |
| 107 } | |
| 108 | |
| 109 /* Finst the instruction operands, by looking at the end of the | |
| 110 * input line. Looks for a comment of the form '#mnemonic operands' | |
| 111 */ | |
| 112 static const char* GetInstOperandsText(const NaClEnumerator* enumerator) { | |
| 113 if (input_decoder.operands_ != NULL) return input_decoder.operands_; | |
| 114 AssembleDesc(enumerator); | |
| 115 return input_decoder.operands_; | |
| 116 } | |
| 117 | |
| 118 | |
| 119 /* Prints out the disassembled instruction. */ | |
| 120 static void PrintInst(const NaClEnumerator* enumerator) { | |
| 121 int i; | |
| 122 | |
| 123 printf(" IN: %"NACL_PRIxNaClPcAddressAll": ", input_decoder.pc_address_); | |
| 124 for (i = 0; i < input_decoder.num_bytes_; ++i) { | |
| 125 printf("%02x ", enumerator->_itext[i]); | |
| 126 } | |
| 127 for (i = input_decoder.num_bytes_; i < MAX_INST_LENGTH; ++i) { | |
| 128 printf(" "); | |
| 129 } | |
| 130 | |
| 131 /* Print out decoding if included on the input line. */ | |
| 132 if (NULL == input_decoder.base_._get_inst_mnemonic_fn) { | |
| 133 printf("\n"); | |
| 134 } else { | |
| 135 printf("%s %s\n", GetInstMnemonic(enumerator), | |
| 136 GetInstOperandsText(enumerator)); | |
| 137 } | |
| 138 } | |
| 139 | |
| 140 /* Returns true if the instruction parsed a legal instruction. */ | |
| 141 static Bool IsInstLegal(const NaClEnumerator* enumerator) { | |
| 142 UNREFERENCED_PARAMETER(enumerator); | |
| 143 return TRUE; | |
| 144 } | |
| 145 | |
| 146 static size_t InstLength(const NaClEnumerator* enumerator) { | |
| 147 UNREFERENCED_PARAMETER(enumerator); | |
| 148 return (size_t) input_decoder.num_bytes_; | |
| 149 } | |
| 150 | |
| 151 static void InstallFlag(const NaClEnumerator* enumerator, | |
| 152 const char* flag_name, | |
| 153 const void* flag_address) { | |
| 154 UNREFERENCED_PARAMETER(enumerator); | |
| 155 UNREFERENCED_PARAMETER(flag_name); | |
| 156 UNREFERENCED_PARAMETER(flag_address); | |
| 157 } | |
| 158 | |
| 159 | |
| 160 /* Defines the registry function that creates a input decoder, and returns | |
| 161 * the decoder to be registered. | |
| 162 */ | |
| 163 NaClEnumeratorDecoder* RegisterInputDecoder(void) { | |
| 164 input_decoder.base_._id_name = "in"; | |
| 165 input_decoder.base_._legal_only = TRUE; | |
| 166 input_decoder.base_._parse_inst_fn = ParseInst; | |
| 167 input_decoder.base_._inst_length_fn = InstLength; | |
| 168 input_decoder.base_._print_inst_fn = PrintInst; | |
| 169 /* Initially assume that the input doesn't get information on | |
| 170 * mnemonic and operand text. Change (in InstallFlag) above if | |
| 171 * specified on command line. | |
| 172 */ | |
| 173 input_decoder.base_._get_inst_mnemonic_fn = NULL; | |
| 174 input_decoder.base_._get_inst_num_operands_fn = NULL; | |
| 175 input_decoder.base_._get_inst_operands_text_fn = NULL; | |
| 176 input_decoder.base_._writes_to_reserved_reg_fn = NULL; | |
| 177 input_decoder.base_._is_inst_legal_fn = IsInstLegal; | |
| 178 input_decoder.base_._maybe_inst_validates_fn = NULL; | |
| 179 input_decoder.base_._segment_validates_fn = NULL; | |
| 180 input_decoder.base_._install_flag_fn = InstallFlag; | |
| 181 input_decoder.base_._usage_message = "Defines legal instructions from stdin"; | |
| 182 input_decoder.num_bytes_ = 0; | |
| 183 input_decoder.line_number_ = 0; | |
| 184 input_decoder.pc_address_ = 0; | |
| 185 input_decoder.mnemonic_ = NULL; | |
| 186 input_decoder.operands_ = NULL; | |
| 187 input_decoder.configured_ = FALSE; | |
| 188 return &input_decoder.base_; | |
| 189 } | |
| 190 | |
| 191 int ReadAnInstruction(InstByteArray ibytes) { | |
| 192 input_decoder.num_bytes_ = 0; | |
| 193 while (input_decoder.num_bytes_ == 0) { | |
| 194 ++input_decoder.line_number_; | |
| 195 if (fgets(input_decoder.line_, kBufferSize, stdin) == NULL) return 0; | |
| 196 | |
| 197 /* If the line specifies that the input has opcode sequences plus | |
| 198 * descriptions, then install the virtuals to handle the input. | |
| 199 */ | |
| 200 if (!input_decoder.configured_) { | |
| 201 if (input_decoder.line_ == | |
| 202 strstr(input_decoder.line_, "#OPCODEPLUSDESC#")) { | |
| 203 input_decoder.base_._get_inst_mnemonic_fn = GetInstMnemonic; | |
| 204 input_decoder.base_._get_inst_operands_text_fn = GetInstOperandsText; | |
| 205 } | |
| 206 input_decoder.configured_ = TRUE; | |
| 207 } | |
| 208 | |
| 209 /* If the line is a progress line, print out the corresponding progress | |
| 210 * message. | |
| 211 */ | |
| 212 if (input_decoder.line_ == strstr(input_decoder.line_, "#PROGRESS#")) { | |
| 213 printf("%s", &input_decoder.line_[strlen("#PROGRESS#")]); | |
| 214 } | |
| 215 | |
| 216 /* Finally, convert the input into the corresponding sequence of bytes | |
| 217 * that defines the instruction. | |
| 218 */ | |
| 219 input_decoder.num_bytes_ = | |
| 220 Text2Bytes(ibytes, input_decoder.line_, "stdin", | |
| 221 input_decoder.line_number_); | |
| 222 } | |
| 223 return input_decoder.num_bytes_; | |
| 224 } | |
| OLD | NEW |