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 |