Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(143)

Side by Side Diff: src/trusted/validator/x86/testing/enuminsts/nacl_tester.c

Issue 625923004: Delete old x86 validator. (Closed) Base URL: svn://svn.chromium.org/native_client/trunk/src/native_client
Patch Set: rebase master Created 6 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(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 * nacl_tester.c
9 * Uses the NaCl x86 validator/decoder to implement a NaClEnumeratorDecoder.
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/enuminsts.h"
16
17 #include <ctype.h>
18 #include <string.h>
19 #include "native_client/src/trusted/validator_x86/ncenuminsts.h"
20 #include "native_client/src/trusted/validator/x86/testing/enuminsts/str_utils.h"
21
22 #define kBufferSize 1024
23
24 /* Defines the virtual table for the nacl decoder. */
25 struct {
26 /* The virtual table that implements this decoder. */
27 NaClEnumeratorDecoder _base;
28 /* Defines the NaCl state to use to parse instructions. */
29 NaClInstStruct *_inst;
30 /* Defines if we are ignoring the instruction (i.e. an instruction
31 * that isn't xed implemented.
32 */
33 Bool _ignore_instruction;
34 /* Defines the pc address associated with the instruction. */
35 NaClPcAddress _pc_address;
36 /* If non-empty, the corresponding disassembly. */
37 char _disassembly[kBufferSize];
38 /* If non-empty, the simplified corresponding assembly, where
39 * the opcode byte sequence has been removed.
40 */
41 char _simplified_disassembly[kBufferSize];
42 /* If non-empty, the corresponding instruction mnemonic. */
43 char _mnemonic[kBufferSize];
44 /* if non-empty, the lowercase mnemonic. */
45 char _mnemonic_lower[kBufferSize];
46 /* If non-empty, stores the operands of the corresponding instruction. */
47 char _operands[kBufferSize];
48 /* True if we should translate special opcodes to matching xed nops. */
49 Bool _translate_to_xed_nops;
50 /* True if we shouldn't accept instructions that aren't also implemented
51 * in xed.
52 */
53 Bool _ignore_instructions_not_xed_implemented;
54 } nacl_decoder;
55
56 static Bool IsInstLegal(const NaClEnumerator *enumerator) {
57 UNREFERENCED_PARAMETER(enumerator);
58 #if 0
59 /* This forces an incorrect legality report for 00 24 c2, useful for */
60 /* testing that related problems are being reported. */
61 if (enumerator->_itext[0] == 0 &&
62 enumerator->_itext[1] == 0x24 &&
63 enumerator->_itext[2] == 0xc2) return 0;
64 #endif
65 return !nacl_decoder._ignore_instruction &&
66 NaClInstDecodesCorrectly(nacl_decoder._inst);
67 }
68
69 /* Instructions we assume that the NaCl validator accept and are valid, but
70 * are not legal according to xed.
71 */
72 static Bool NaClIsntXedImplemented(const NaClEnumerator *enumerator) {
73 static const char* nacl_but_not_xed[] = {
74 "Pf2iw",
75 "Pf2id"
76 };
77 const char* name = NaClOpcodeName(nacl_decoder._inst);
78 size_t i;
79 UNREFERENCED_PARAMETER(enumerator);
80 for (i = 0; i < NACL_ARRAY_SIZE(nacl_but_not_xed); ++i) {
81 if (0 == strcmp(name, nacl_but_not_xed[i])) {
82 return TRUE;
83 }
84 }
85 return FALSE;
86 }
87
88 /* Defines the funcdtion to parse the first instruction. */
89 static void ParseInst(const NaClEnumerator* enumerator,
90 const int pc_address) {
91 nacl_decoder._inst = NULL;
92 nacl_decoder._ignore_instruction = FALSE;
93 nacl_decoder._pc_address = pc_address;
94 nacl_decoder._disassembly[0] = 0;
95 nacl_decoder._simplified_disassembly[0] = 0;
96 nacl_decoder._mnemonic[0] = 0;
97 nacl_decoder._mnemonic_lower[0] = 0;
98 nacl_decoder._operands[0] = 0;
99 nacl_decoder._inst =
100 NaClParseInst((uint8_t *)enumerator->_itext,
101 enumerator->_num_bytes, pc_address);
102 if (nacl_decoder._ignore_instructions_not_xed_implemented &&
103 IsInstLegal(enumerator)) {
104 nacl_decoder._ignore_instruction = NaClIsntXedImplemented(enumerator);
105 }
106 }
107
108
109 /* Returns the disassembled instruction. */
110 static const char* Disassemble(const NaClEnumerator* enumerator) {
111 char* stmp;
112
113 UNREFERENCED_PARAMETER(enumerator);
114 /* First see if we have cached it. If so, return it. */
115 if (nacl_decoder._disassembly[0] != 0) return nacl_decoder._disassembly;
116
117 stmp = NaClInstToStr(nacl_decoder._inst);
118 cstrncpy(nacl_decoder._disassembly, stmp, kBufferSize);
119 free(stmp);
120 return nacl_decoder._disassembly;
121 }
122
123 /* Returns the lower case name of the instruction. */
124 static const char* GetInstMnemonicLower(const NaClEnumerator* enumerator) {
125 char mnemonic[kBufferSize];
126 size_t i;
127
128 UNREFERENCED_PARAMETER(enumerator);
129 if (nacl_decoder._mnemonic_lower[0] != 0)
130 return nacl_decoder._mnemonic_lower;
131
132 cstrncpy(mnemonic, NaClOpcodeName(nacl_decoder._inst), kBufferSize);
133 for (i = 0; i < kBufferSize; ++i) {
134 mnemonic[i] = tolower(mnemonic[i]);
135 if (mnemonic[i] == '\0') break;
136 }
137 cstrncpy(nacl_decoder._mnemonic_lower, mnemonic, kBufferSize);
138 return nacl_decoder._mnemonic_lower;
139 }
140
141 /* Defines nacl/xed mnemonic renaming pairs. */
142 typedef struct {
143 const char* nacl_name;
144 const char* xed_name;
145 } NaClToXedPairs;
146
147 /* Returns the disassembled instruction with the opcode byte sequence
148 * removed.
149 */
150 static const char* SimplifiedDisassembly(const NaClEnumerator *enumerator) {
151 const char* disassembly;
152 const char* mnemonic;
153 const char* start;
154
155 /* First see if we have cache it. If so, return it. */
156 if (nacl_decoder._simplified_disassembly[0] != 0)
157 return nacl_decoder._simplified_disassembly;
158
159 /* Take first guess of simplified assembly. */
160 /* Find start of instruction mnemonic, and define as start of simplified
161 * disassembly.
162 */
163 disassembly = Disassemble(enumerator);
164 mnemonic = GetInstMnemonicLower(enumerator);
165 start = strfind(disassembly, mnemonic);
166 if (NULL == start) {
167 /* Don't know how to simplify, give up and just use disassembly. */
168 cstrncpy(nacl_decoder._simplified_disassembly, disassembly, kBufferSize);
169 return nacl_decoder._simplified_disassembly;
170 }
171 cstrncpy(nacl_decoder._simplified_disassembly, start, kBufferSize);
172 rstrip(nacl_decoder._simplified_disassembly);
173
174 /* Now handle special cases where we should treat the nacl instruction as a
175 * nop, so that they will match xed instructions.
176 */
177 if (nacl_decoder._translate_to_xed_nops) {
178 static const NaClToXedPairs pairs[] = {
179 { "xchg %eax, %eax" , "nop" },
180 { "xchg %rax, %rax" , "nop" },
181 { "xchg %ax, %ax" , "nop" },
182 };
183 size_t i;
184 char buf[kBufferSize];
185 const char* desc = strfind(nacl_decoder._simplified_disassembly, mnemonic);
186 if (NULL == desc) return nacl_decoder._simplified_disassembly;
187 cstrncpy(buf, desc, kBufferSize);
188 rstrip(buf);
189 for (i = 0; i < NACL_ARRAY_SIZE(pairs); ++i) {
190 if (0 == strcmp(nacl_decoder._simplified_disassembly,
191 pairs[i].nacl_name)) {
192 cstrncpy(nacl_decoder._simplified_disassembly,
193 pairs[i].xed_name, kBufferSize);
194 cstrncpy(nacl_decoder._mnemonic, pairs[i].xed_name, kBufferSize);
195 }
196 }
197 }
198 return nacl_decoder._simplified_disassembly;
199 }
200
201 /* Returns the mnemonic name for the disassembled instruction. */
202 static const char* GetInstMnemonic(const NaClEnumerator* enumerator) {
203 char mnemonic[kBufferSize];
204 const char* disassembly;
205
206 /* First see if we have cached it. If so, return it. */
207 if (nacl_decoder._mnemonic[0] != 0) return nacl_decoder._mnemonic;
208
209 /* Force simplifications if needed. Use mnemonic if defined. */
210 disassembly = SimplifiedDisassembly(enumerator);
211 (void) disassembly; /* TODO(bradchen): use or remove this variable */
212 if (nacl_decoder._mnemonic[0] != 0) return nacl_decoder._mnemonic;
213
214 /* If reached, we haven't cached it, so find the name from the
215 * disassembled instruction and cache it.
216 */
217 cstrncpy(mnemonic, GetInstMnemonicLower(enumerator), kBufferSize);
218
219 /* Now fix mnemonic to corresponding xed name if needed. */
220 if ((mnemonic[0] == 'p') && (mnemonic[1] == 'f') && (mnemonic[2] == 'r')) {
221 static const NaClToXedPairs pairs[] = {
222 { "pfrsqrt", "pfsqrt" },
223 { "pfrcpit1", "pfcpit1" }
224 };
225 size_t i;
226 for (i = 0; i < NACL_ARRAY_SIZE(pairs); ++i) {
227 if (0 == strcmp(mnemonic, pairs[i].nacl_name)) {
228 const char* start =
229 strfind(nacl_decoder._simplified_disassembly, mnemonic);
230 if (NULL != start) {
231 /* replace nacl_name with xed name in simplified disassembly. */
232 cstrncpy(mnemonic, pairs[i].xed_name, kBufferSize);
233 }
234 }
235 }
236 }
237
238 /* Install mnemonic and return. */
239 cstrncpy(nacl_decoder._mnemonic, mnemonic, kBufferSize);
240 return nacl_decoder._mnemonic;
241 }
242
243 /* Returns the text for the operands. To be used by the driver
244 * to compare accross decoders.
245 */
246 static const char* GetInstOperandsText(const NaClEnumerator* enumerator) {
247 char operands[kBufferSize];
248 const char* disassembly;
249 const char* after_mnemonic;
250
251 /* First see if we have cached it. If so, return it. */
252 if (nacl_decoder._operands[0] != 0) return nacl_decoder._operands;
253
254 disassembly = SimplifiedDisassembly(enumerator);
255 after_mnemonic = strskip(disassembly, GetInstMnemonicLower(enumerator));
256 if (NULL == after_mnemonic) after_mnemonic = disassembly;
257 cstrncpy(operands, after_mnemonic, kBufferSize);
258 strnzapchar(operands, '%');
259 strnzapchar(operands, '\n');
260 cstrncpy(nacl_decoder._operands, strip(operands), kBufferSize);
261 return nacl_decoder._operands;
262 }
263
264 /* Prints out the disassembled instruction. */
265 static void PrintInst(const NaClEnumerator* enumerator) {
266 printf(" NaCl: %s", Disassemble(enumerator));
267 }
268
269 /* Returns the number of bytes in the disassembled instruction. */
270 static size_t InstLength(const NaClEnumerator* enumerator) {
271 UNREFERENCED_PARAMETER(enumerator);
272 #if 0
273 /* This forces an incorrect length report for 00 24 c2, useful for */
274 /* testing that length problems are being reported. */
275 if (enumerator->_itext[0] == 0 &&
276 enumerator->_itext[1] == 0x24 &&
277 enumerator->_itext[2] == 0xc2) return 4;
278 #endif
279 return (size_t) NaClInstLength(nacl_decoder._inst);
280 }
281
282 /* Returns true if the instruction decodes, and static (single instruction)
283 * validator tests pass.
284 */
285 static Bool MaybeInstValidates(const NaClEnumerator *enumerator) {
286 return NaClInstValidates((uint8_t*) enumerator->_itext,
287 NaClInstLength(nacl_decoder._inst),
288 nacl_decoder._pc_address,
289 nacl_decoder._inst);
290 }
291
292 /* Runs the validator on the given code segment. */
293 static Bool SegmentValidates(const NaClEnumerator *enumerator,
294 const uint8_t* segment,
295 const size_t size,
296 const int pc_address) {
297 UNREFERENCED_PARAMETER(enumerator);
298 return NaClSegmentValidates((uint8_t*) segment, size, pc_address);
299 }
300
301 /* Installs NaCl-specific flags. */
302 static void InstallFlag(const NaClEnumerator* enumerator,
303 const char* flag_name,
304 const void* flag_address) {
305 UNREFERENCED_PARAMETER(enumerator);
306 if (0 == strcmp(flag_name, "--nops")) {
307 nacl_decoder._translate_to_xed_nops = *((Bool*) flag_address);
308 } else if (0 == strcmp(flag_name, "--xedimplemented")) {
309 nacl_decoder._ignore_instructions_not_xed_implemented =
310 *((Bool*) flag_address);
311 }
312 }
313
314 /* Generates a decoder for the (sel_ldr) nacl validator. */
315 NaClEnumeratorDecoder* RegisterNaClDecoder(void) {
316 nacl_decoder._base._id_name = "nacl";
317 nacl_decoder._base._parse_inst_fn = ParseInst;
318 nacl_decoder._base._inst_length_fn = InstLength;
319 nacl_decoder._base._print_inst_fn = PrintInst;
320 nacl_decoder._base._get_inst_mnemonic_fn = GetInstMnemonic;
321 nacl_decoder._base._get_inst_num_operands_fn = NULL;
322 nacl_decoder._base._get_inst_operands_text_fn = GetInstOperandsText;
323 nacl_decoder._base._writes_to_reserved_reg_fn = NULL;
324 nacl_decoder._base._is_inst_legal_fn = IsInstLegal;
325 nacl_decoder._base._maybe_inst_validates_fn = MaybeInstValidates;
326 nacl_decoder._base._segment_validates_fn = SegmentValidates;
327 nacl_decoder._base._install_flag_fn = InstallFlag;
328 nacl_decoder._base._usage_message =
329 "Runs nacl decoder to decode instructions";
330 return &nacl_decoder._base;
331 }
OLDNEW
« no previous file with comments | « src/trusted/validator/x86/testing/enuminsts/input_tester.c ('k') | src/trusted/validator/x86/testing/enuminsts/out_file » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698