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