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(NaClEnumerator* enumerator, int pc_address) { | |
Brad Chen
2012/03/28 17:26:43
const int pc_address?
What is the enumerator for?
Karl
2012/03/28 18:25:28
It is there because of the API expected by callers
| |
58 input_decoder.pc_address_ = pc_address; | |
59 input_decoder.mnemonic_ = NULL; | |
60 input_decoder.operands_ = NULL; | |
61 } | |
62 | |
63 /* Finds the instruction mnemonic, by looking at the end of the | |
64 * input line. Looks for a comment of the form '#mnemonic operands' | |
65 */ | |
66 static void AssembleDesc(NaClEnumerator* enumerator) { | |
Brad Chen
2012/03/28 17:26:43
Please make these parameters const if they are not
Karl
2012/03/28 18:25:28
At one time, API functions updated the enumerator.
| |
67 char* desc; | |
68 char* end; | |
69 /* Start by looking for description. */ | |
70 desc = (char*) strip(strskip(input_decoder.line_, "#")); | |
71 if (desc == NULL) { | |
72 /* Not found, fill in a default value. */ | |
73 input_decoder.mnemonic_ = "???"; | |
74 input_decoder.operands_ = ""; | |
75 return; | |
76 } | |
77 /* Copy the description into the buffer, and then extract the needed parts. */ | |
78 cstrncpy(input_decoder.buffer_, desc, kBufferSize); | |
79 input_decoder.mnemonic_ = input_decoder.buffer_; | |
80 end = (char*) strfind(input_decoder.buffer_, " "); | |
81 if (end == NULL) { | |
82 /* No operands, clean up mnemonic. */ | |
83 rstrip(input_decoder.buffer_); | |
84 input_decoder.operands_ = ""; | |
85 return; | |
86 } | |
87 /* Has mnemonic and operands. Separate out parts. */ | |
88 *end = '\0'; | |
89 input_decoder.operands_ = (char*) strip(end + 1); | |
90 rstrip(input_decoder.operands_); | |
91 } | |
92 | |
93 /* Finds the instruction mnemonic, by looking at the end of the | |
94 * input line. Looks for a comment of the form '#mnemonic operands' | |
95 */ | |
96 static const char* GetInstMnemonic(NaClEnumerator* enumerator) { | |
97 if (input_decoder.mnemonic_ != NULL) return input_decoder.mnemonic_; | |
98 AssembleDesc(enumerator); | |
99 return input_decoder.mnemonic_; | |
100 } | |
101 | |
102 /* Finst the instruction operands, by looking at the end of the | |
103 * input line. Looks for a comment of the form '#mnemonic operands' | |
104 */ | |
105 static const char* GetInstOperandsText(NaClEnumerator* enumerator) { | |
106 if (input_decoder.operands_ != NULL) return input_decoder.operands_; | |
107 AssembleDesc(enumerator); | |
108 return input_decoder.operands_; | |
109 } | |
110 | |
111 | |
112 /* Prints out the disassembled instruction. */ | |
113 static void PrintInst(NaClEnumerator* enumerator) { | |
114 size_t i; | |
115 const char* desc; | |
116 size_t num_bytes; | |
117 printf(" IN: %"NACL_PRIxNaClPcAddressAll": ", input_decoder.pc_address_); | |
118 for (i = 0; i < input_decoder.num_bytes_; ++i) { | |
119 printf("%02x ", enumerator->_itext[i]); | |
120 } | |
121 for (i = input_decoder.num_bytes_; i < MAX_INST_LENGTH; ++i) { | |
122 printf(" "); | |
123 } | |
124 | |
125 /* Print out decoding if included on the input line. */ | |
126 if (NULL == input_decoder.base_._get_inst_mnemonic_fn) { | |
127 printf("\n"); | |
128 } else { | |
129 printf("%s %s\n", GetInstMnemonic(enumerator), | |
130 GetInstOperandsText(enumerator)); | |
131 } | |
132 } | |
133 | |
134 /* Returns true if the instruction parsed a legal instruction. */ | |
135 static Bool IsInstLegal(NaClEnumerator* enumerator) { | |
136 return TRUE; | |
137 } | |
138 | |
139 static size_t InstLength(NaClEnumerator* enumerator) { | |
140 return (size_t) input_decoder.num_bytes_; | |
141 } | |
142 | |
143 static void InstallFlag(NaClEnumerator* enumerator, | |
144 const char* flag_name, | |
145 void* flag_address) { | |
146 } | |
147 | |
148 | |
149 /* Defines the registry function that creates a input decoder, and returns | |
150 * the decoder to be registered. | |
151 */ | |
152 NaClEnumeratorDecoder* RegisterInputDecoder() { | |
153 input_decoder.base_._id_name = "in"; | |
154 input_decoder.base_._legal_only = TRUE; | |
155 input_decoder.base_._parse_inst_fn = ParseInst; | |
156 input_decoder.base_._inst_length_fn = InstLength; | |
157 input_decoder.base_._print_inst_fn = PrintInst; | |
158 /* Initially assume that the input doesn't get information on | |
159 * mnemonic and operand text. Change (in InstallFlag) above if | |
160 * specified on command line. | |
161 */ | |
162 input_decoder.base_._get_inst_mnemonic_fn = NULL; | |
163 input_decoder.base_._get_inst_num_operands_fn = NULL; | |
164 input_decoder.base_._get_inst_operands_text_fn = NULL; | |
165 input_decoder.base_._writes_to_reserved_reg_fn = NULL; | |
166 input_decoder.base_._is_inst_legal_fn = IsInstLegal; | |
167 input_decoder.base_._maybe_inst_validates_fn = NULL; | |
168 input_decoder.base_._segment_validates_fn = NULL; | |
169 input_decoder.base_._install_flag_fn = InstallFlag; | |
170 input_decoder.base_._usage_message = "Defines legal instructions from stdin"; | |
171 input_decoder.num_bytes_ = 0; | |
172 input_decoder.line_number_ = 0; | |
173 input_decoder.pc_address_ = 0; | |
174 input_decoder.mnemonic_ = NULL; | |
175 input_decoder.operands_ = NULL; | |
176 input_decoder.configured_ = FALSE; | |
177 return &input_decoder.base_; | |
178 } | |
179 | |
180 int ReadAnInstruction(uint8_t ibytes[NACL_ENUM_MAX_INSTRUCTION_BYTES]) { | |
Brad Chen
2012/03/28 17:26:43
Would a typedef for this array make this code clea
Karl
2012/03/28 18:25:28
Done.
| |
181 input_decoder.num_bytes_ = 0; | |
182 while (input_decoder.num_bytes_ == 0) { | |
183 ++input_decoder.line_number_; | |
184 if (fgets(input_decoder.line_, kBufferSize, stdin) == NULL) return 0; | |
185 | |
186 /* If the line specifies that the input has opcode sequences plus | |
187 * descriptions, then install the virtuals to handle the input. | |
188 */ | |
189 if (!input_decoder.configured_) { | |
190 if (input_decoder.line_ == | |
191 strstr(input_decoder.line_, "#OPCODEPLUSDESC#")) { | |
192 input_decoder.base_._get_inst_mnemonic_fn = GetInstMnemonic; | |
193 input_decoder.base_._get_inst_operands_text_fn = GetInstOperandsText; | |
194 } | |
195 input_decoder.configured_ = TRUE; | |
196 } | |
197 | |
198 /* If the line is a progress line, print out the corresponding progress | |
199 * message. | |
200 */ | |
201 if (input_decoder.line_ == strstr(input_decoder.line_, "#PROGRESS#")) { | |
202 printf("%s", &input_decoder.line_[strlen("#PROGRESS#")]); | |
203 } | |
204 | |
205 /* Finally, convert the input into the corresponding sequence of bytes | |
206 * that defines the instruction. | |
207 */ | |
208 input_decoder.num_bytes_ = | |
209 Text2Bytes(ibytes, input_decoder.line_, "stdin", | |
210 input_decoder.line_number_); | |
211 } | |
212 return input_decoder.num_bytes_; | |
213 } | |
OLD | NEW |