OLD | NEW |
---|---|
1 /* | 1 /* |
2 * Copyright (c) 2012 The Native Client Authors. All rights reserved. | 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 | 3 * Use of this source code is governed by a BSD-style license that can be |
4 * found in the LICENSE file. | 4 * found in the LICENSE file. |
5 */ | 5 */ |
6 | 6 |
7 /* vdiff.c | 7 /* vdiff.c |
8 * exhaustive instruction enumeration test for x86 Native Client validators. | 8 * exhaustive instruction enumeration test for x86 Native Client validators. |
9 * | 9 * |
10 * This file is based on enuminsts.c, but specialized to comparing two | 10 * This file is based on enuminsts.c, but specialized to comparing two |
11 * validators instead of decoders. The enuminsts.c implementation also | 11 * validators instead of decoders. The enuminsts.c implementation also |
12 * had a bunch of Xed-specific logic which complicated the validator | 12 * had a bunch of Xed-specific logic which complicated the validator |
13 * comparison in unhelpful ways. | 13 * comparison in unhelpful ways. |
14 */ | 14 */ |
15 | 15 |
16 #ifndef NACL_TRUSTED_BUT_NOT_TCB | 16 #ifndef NACL_TRUSTED_BUT_NOT_TCB |
17 #error("This file is not meant for use in the TCB.") | 17 #error("This file is not meant for use in the TCB.") |
18 #endif | 18 #endif |
19 #if NACL_WINDOWS | |
20 #define _CRT_RAND_S /* enable decl of rand_s() */ | |
21 #endif | |
19 | 22 |
20 #include "native_client/src/trusted/validator/x86/testing/enuminsts/enuminsts.h" | 23 #include "native_client/src/trusted/validator/x86/testing/enuminsts/enuminsts.h" |
21 | 24 |
22 #include <ctype.h> | 25 #include <ctype.h> |
23 #include <stdio.h> | 26 #include <stdio.h> |
24 #include <string.h> | 27 #include <string.h> |
25 #include <stdlib.h> | 28 #include <stdlib.h> |
26 #include <stdarg.h> | 29 #include <stdarg.h> |
30 #include <time.h> | |
27 | 31 |
28 #include "native_client/src/include/portability_io.h" | 32 #include "native_client/src/include/portability_io.h" |
29 #include "native_client/src/shared/platform/nacl_log.h" | 33 #include "native_client/src/shared/platform/nacl_log.h" |
30 #include "native_client/src/shared/utils/flags.h" | 34 #include "native_client/src/shared/utils/flags.h" |
31 #include "native_client/src/trusted/validator/x86/testing/enuminsts/str_utils.h" | 35 #include "native_client/src/trusted/validator/x86/testing/enuminsts/str_utils.h" |
32 #include "native_client/src/trusted/validator/x86/testing/enuminsts/text2hex.h" | 36 #include "native_client/src/trusted/validator/x86/testing/enuminsts/text2hex.h" |
33 | 37 |
34 /* Defines the maximum buffer size used to hold text generated for the | 38 /* Defines the maximum buffer size used to hold text generated for the |
35 * disassembly of instructions, and corresponding error messages. | 39 * disassembly of instructions, and corresponding error messages. |
36 */ | 40 */ |
37 #define kBufferSize 1024 | 41 #define kBufferSize 1024 |
38 | 42 |
39 /* When true, print more messages (i.e. verbosely). */ | 43 /* When true, print more messages (i.e. verbosely). */ |
40 static Bool gVerbose = FALSE; | 44 static Bool gVerbose = FALSE; |
41 | 45 |
42 /* When true, don't print out messages. That is, only print instructions | 46 /* When true, don't print out messages. That is, only print instructions |
43 * defined by --print directives. | 47 * defined by --print directives. |
44 */ | 48 */ |
45 static Bool gSilent = FALSE; | 49 static Bool gSilent = FALSE; |
46 | 50 |
47 /* When true, don't report consecutive errors for consecutive instructions | 51 /* When true, don't report consecutive errors for consecutive instructions |
48 * with the same instruction mnemonic. | 52 * with the same instruction mnemonic. |
49 */ | 53 */ |
50 static Bool gSkipRepeatReports = FALSE; | 54 static Bool gSkipRepeatReports = FALSE; |
51 | 55 |
56 /* Set to true to enable checking of mnemonics (opcode names). | |
57 */ | |
58 static Bool gCheckMnemonics = TRUE; | |
59 | |
52 /* Count of errors that have a high certainty of being exploitable. */ | 60 /* Count of errors that have a high certainty of being exploitable. */ |
53 static int gSawLethalError = 0; | 61 static int gSawLethalError = 0; |
54 | 62 |
55 /* Defines the assumed text address for the test instruction */ | 63 /* Defines the assumed text address for the test instruction */ |
56 const int kTextAddress = 0x1000; | 64 const int kTextAddress = 0x1000; |
57 | 65 |
58 /* If non-negative, defines the prefix to test. */ | 66 /* If non-negative, defines the prefix to test. */ |
59 static unsigned int gPrefix = 0; | 67 static unsigned int gPrefix = 0; |
60 | 68 |
61 /* If non-negative, defines the opcode to test. */ | 69 /* If non-negative, defines the opcode to test. */ |
62 static int gOpcode = -1; | 70 static int gOpcode = -1; |
63 | 71 |
72 /* This option triggers a set of behaviors that help produce repeatable | |
73 * output, for easier diffs on the buildbots. | |
74 */ | |
75 static Bool gEasyDiffMode; | |
76 | |
64 /* The production and new R-DFA validators */ | 77 /* The production and new R-DFA validators */ |
65 NaClEnumeratorDecoder* vProd; | 78 NaClEnumeratorDecoder* vProd; |
66 NaClEnumeratorDecoder* vDFA; | 79 NaClEnumeratorDecoder* vDFA; |
67 | 80 |
68 /* The name of the executable (i.e. argv[0] from the command line). */ | 81 /* The name of the executable (i.e. argv[0] from the command line). */ |
69 static char *gArgv0 = "argv0"; | 82 static const char *gArgv0 = "argv0"; |
83 #define FLAG_EasyDiff "--easydiff" | |
70 | 84 |
71 /* Records that unexpected internal error occurred. */ | 85 /* Records that unexpected internal error occurred. */ |
72 void InternalError(const char *why) { | 86 void InternalError(const char *why) { |
73 fprintf(stderr, "%s: Internal Error: %s\n", gArgv0, why); | 87 fprintf(stderr, "%s: Internal Error: %s\n", gArgv0, why); |
74 gSawLethalError = 1; | 88 gSawLethalError = 1; |
75 } | 89 } |
76 | 90 |
77 /* Records that a fatal (i.e. non-recoverable) error occurred. */ | 91 /* Records that a fatal (i.e. non-recoverable) error occurred. */ |
78 void ReportFatalError(const char* why) { | 92 void ReportFatalError(const char* why) { |
79 char buffer[kBufferSize]; | 93 char buffer[kBufferSize]; |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
138 } | 152 } |
139 | 153 |
140 static void CheckMnemonics(NaClEnumerator* pinst, NaClEnumerator* dinst) { | 154 static void CheckMnemonics(NaClEnumerator* pinst, NaClEnumerator* dinst) { |
141 const char* prod_opcode = vProd->_get_inst_mnemonic_fn(pinst); | 155 const char* prod_opcode = vProd->_get_inst_mnemonic_fn(pinst); |
142 const char* dfa_opcode = vDFA->_get_inst_mnemonic_fn(dinst); | 156 const char* dfa_opcode = vDFA->_get_inst_mnemonic_fn(dinst); |
143 | 157 |
144 if (0 != strcmp(prod_opcode, dfa_opcode)) { | 158 if (0 != strcmp(prod_opcode, dfa_opcode)) { |
145 /* avoid redundant messages... */ | 159 /* avoid redundant messages... */ |
146 if (NotOpcodeRepeat(prod_opcode)) { | 160 if (NotOpcodeRepeat(prod_opcode)) { |
147 printf("Warning: OPCODE MISMATCH: %s != %s\n", prod_opcode, dfa_opcode); | 161 printf("Warning: OPCODE MISMATCH: %s != %s\n", prod_opcode, dfa_opcode); |
148 /* PrintDisassembledInstructionVariants(pinst, dinst); */ | |
149 } | 162 } |
150 } | 163 } |
151 } | 164 } |
152 | 165 |
153 struct vdiff_stats { | 166 struct vdiff_stats { |
154 int64_t tried; | 167 int64_t tried; |
155 int64_t valid; | 168 int64_t valid; |
156 int64_t invalid; | 169 int64_t invalid; |
157 int64_t errors; | 170 int64_t errors; |
158 } gVDiffStats = {0, 0, 0, 0}; | 171 } gVDiffStats = {0, 0, 0, 0}; |
159 | 172 |
160 static void IncrTried() { | 173 static void IncrTried() { |
161 gVDiffStats.tried += 1; | 174 gVDiffStats.tried += 1; |
162 } | 175 } |
163 | 176 |
164 static void IncrValid() { | 177 static void IncrValid() { |
165 gVDiffStats.valid += 1; | 178 gVDiffStats.valid += 1; |
166 } | 179 } |
167 | 180 |
168 static void IncrInvalid() { | 181 static void IncrInvalid() { |
169 gVDiffStats.invalid += 1; | 182 gVDiffStats.invalid += 1; |
170 } | 183 } |
171 | 184 |
172 static void IncrErrors() { | 185 static void IncrErrors() { |
173 gVDiffStats.errors += 1; | 186 gVDiffStats.errors += 1; |
174 } | 187 } |
175 | 188 |
176 static void PrintStats() { | 189 static void PrintStats() { |
177 printf("valid: %" NACL_PRIu64 "\n", gVDiffStats.valid); | 190 if (!gEasyDiffMode) { |
178 printf("invalid: %" NACL_PRIu64 "\n", gVDiffStats.invalid); | 191 printf("valid: %" NACL_PRIu64 "\n", gVDiffStats.valid); |
192 printf("invalid: %" NACL_PRIu64 "\n", gVDiffStats.invalid); | |
193 } | |
179 printf("errors: %" NACL_PRIu64 "\n", gVDiffStats.errors); | 194 printf("errors: %" NACL_PRIu64 "\n", gVDiffStats.errors); |
180 printf("tried: %" NACL_PRIu64 "\n", gVDiffStats.tried); | 195 printf("tried: %" NACL_PRIu64 "\n", gVDiffStats.tried); |
181 printf(" =? %" NACL_PRIu64 " valid + invalid + errors\n", | 196 printf(" =? %" NACL_PRIu64 " valid + invalid + errors\n", |
182 gVDiffStats.valid + gVDiffStats.invalid + gVDiffStats.errors); | 197 gVDiffStats.valid + gVDiffStats.invalid + gVDiffStats.errors); |
183 } | 198 } |
184 | 199 |
185 static void InitInst(NaClEnumerator *nacle, | 200 static void InitInst(NaClEnumerator *nacle, |
186 uint8_t *itext, size_t nbytes) | 201 uint8_t *itext, size_t nbytes) |
187 { | 202 { |
188 memcpy(nacle->_itext, itext, nbytes); | 203 memcpy(nacle->_itext, itext, nbytes); |
(...skipping 24 matching lines...) Expand all Loading... | |
213 rdfa_okay = vDFA->_maybe_inst_validates_fn(&dinst); | 228 rdfa_okay = vDFA->_maybe_inst_validates_fn(&dinst); |
214 | 229 |
215 if (prod_okay) { | 230 if (prod_okay) { |
216 if (rdfa_okay) { | 231 if (rdfa_okay) { |
217 if (vProd->_inst_length_fn(&pinst) == | 232 if (vProd->_inst_length_fn(&pinst) == |
218 vDFA->_inst_length_fn(&dinst)) { | 233 vDFA->_inst_length_fn(&dinst)) { |
219 /* Both validators see a legal instruction, */ | 234 /* Both validators see a legal instruction, */ |
220 /* and they agree on critical details. */ | 235 /* and they agree on critical details. */ |
221 IncrValid(); | 236 IncrValid(); |
222 /* Warn if decoders disagree opcode name. */ | 237 /* Warn if decoders disagree opcode name. */ |
223 CheckMnemonics(&pinst, &dinst); | 238 if (gCheckMnemonics) CheckMnemonics(&pinst, &dinst); |
224 } else { | 239 } else { |
225 DecoderError("LENGTH MISMATCH", &pinst, &dinst, ""); | 240 DecoderError("LENGTH MISMATCH", &pinst, &dinst, ""); |
226 IncrErrors(); | 241 IncrErrors(); |
227 } | 242 } |
228 } else { | 243 } else { |
229 /* Validators disagree on instruction legality */ | 244 /* Validators disagree on instruction legality */ |
230 DecoderError("VALIDATORS DISAGREE", &pinst, &dinst, ""); | 245 DecoderError("VALIDATORS DISAGREE", &pinst, &dinst, ""); |
231 IncrErrors(); | 246 IncrErrors(); |
232 } | 247 } |
233 } else if (rdfa_okay) { | 248 } else if (rdfa_okay) { |
234 /* Validators disagree on instruction legality */ | 249 /* Validators disagree on instruction legality */ |
235 DecoderError("VALIDATORS DISAGREE", &pinst, &dinst, ""); | 250 DecoderError("VALIDATORS DISAGREE", &pinst, &dinst, ""); |
236 IncrErrors(); | 251 IncrErrors(); |
237 } else { | 252 } else { |
238 /* Both validators see an illegal instruction */ | 253 /* Both validators see an illegal instruction */ |
239 IncrInvalid(); | 254 IncrInvalid(); |
240 } | 255 } |
241 | 256 |
242 /* no error */ | |
243 if (gVerbose) { | 257 if (gVerbose) { |
244 PrintDisassembledInstructionVariants(&pinst, &dinst); | 258 PrintDisassembledInstructionVariants(&pinst, &dinst); |
245 } | 259 } |
246 } while (0); | 260 } while (0); |
247 } | 261 } |
248 | 262 |
263 /* A function type for instruction "TestAll" functions. | |
264 * Parameters: | |
265 * prefix: up to four bytes of prefix. | |
266 * prefix_length: size_t on [0..4] specifying length of prefix. | |
267 * print_prefix: For easy diff of test output, avoid printing | |
268 * the value of a randomly selected REX prefix. | |
269 */ | |
270 typedef void (*TestAllFunction)(const unsigned int prefix, | |
271 const size_t prefix_length, | |
272 const char* print_prefix); | |
273 | |
274 /* Create a char* rendition of a prefix string, appending bytes | |
275 * in ps. This is used to create output that is easy to diff when | |
276 * a random REX byte is used. | |
277 */ | |
278 static char* StrPrefix(const unsigned int prefix, char* ps, char* str) { | |
Karl
2012/08/28 21:23:52
It is not clear to me what the arguments here are.
Brad Chen
2012/08/28 22:09:42
Done.
| |
279 sprintf(str, "%x%s", prefix, (ps == NULL) ? "" : ps); | |
280 return str; | |
281 } | |
282 | |
249 /* Enumerate and test all 24-bit opcode+modrm+sib patterns for a | 283 /* Enumerate and test all 24-bit opcode+modrm+sib patterns for a |
250 * particular prefix. | 284 * particular prefix. |
251 */ | 285 */ |
252 static void TestAllWithPrefix(unsigned int prefix, size_t prefix_length) { | 286 static void TestAllWithPrefix(const unsigned int prefix, |
253 const int kInstByteCount = NACL_ENUM_MAX_INSTRUCTION_BYTES; | 287 const size_t prefix_length, |
254 const int kIterByteCount = 3; | 288 const char* print_prefix) { |
289 const size_t kInstByteCount = NACL_ENUM_MAX_INSTRUCTION_BYTES; | |
290 const size_t kIterByteCount = 3; | |
255 InstByteArray itext; | 291 InstByteArray itext; |
256 size_t i; | 292 size_t i; |
257 int op, modrm, sib; | 293 int op, modrm, sib; |
258 int min_op; | 294 int min_op; |
259 int max_op; | 295 int max_op; |
260 | 296 |
261 if ((gPrefix > 0) && (gPrefix != prefix)) return; | 297 if ((gPrefix > 0) && (gPrefix != prefix)) return; |
262 | 298 |
263 PrintProgress("TestAllWithPrefix(%x)\n", prefix); | 299 PrintProgress("TestAllWithPrefix(%s)\n", print_prefix); |
264 /* set up prefix */ | 300 /* set up prefix */ |
265 memcpy(itext, &prefix, prefix_length); | 301 memcpy(itext, &prefix, prefix_length); |
266 /* set up filler bytes */ | 302 /* set up filler bytes */ |
267 for (i = prefix_length + kIterByteCount; | 303 for (i = prefix_length + kIterByteCount; |
268 i < NACL_ENUM_MAX_INSTRUCTION_BYTES; i++) { | 304 i < NACL_ENUM_MAX_INSTRUCTION_BYTES; i++) { |
269 itext[i] = (uint8_t)i; | 305 itext[i] = (uint8_t)i; |
270 } | 306 } |
271 if (gOpcode < 0) { | 307 if (gOpcode < 0) { |
272 min_op = 0; | 308 min_op = 0; |
273 max_op = 256; | 309 max_op = 256; |
274 } else { | 310 } else { |
275 min_op = gOpcode; | 311 min_op = gOpcode; |
276 max_op = gOpcode + 1; | 312 max_op = gOpcode + 1; |
277 } | 313 } |
278 for (op = min_op; op < max_op; op++) { | 314 for (op = min_op; op < max_op; op++) { |
279 itext[prefix_length] = op; | 315 itext[prefix_length] = op; |
280 PrintProgress("%02x 00 00\n", op); | 316 PrintProgress("%02x 00 00\n", op); |
281 for (modrm = 0; modrm < 256; modrm++) { | 317 for (modrm = 0; modrm < 256; modrm++) { |
282 itext[prefix_length + 1] = modrm; | 318 itext[prefix_length + 1] = modrm; |
283 for (sib = 0; sib < 256; sib++) { | 319 for (sib = 0; sib < 256; sib++) { |
284 itext[prefix_length + 2] = sib; | 320 itext[prefix_length + 2] = sib; |
285 TryOneInstruction(itext, kInstByteCount); | 321 TryOneInstruction(itext, kInstByteCount); |
286 } | 322 } |
287 } | 323 } |
288 } | 324 } |
289 } | 325 } |
290 | 326 |
327 #if NACL_TARGET_SUBARCH == 64 | |
328 /* REX prefixes range from 0x40 to 0x4f. */ | |
329 const uint32_t kREXBase = 0x40; | |
330 const uint32_t kREXRange = 0x10; | |
331 const uint32_t kREXMax = 0x50; /* kREXBase + kREXRange */ | |
Karl
2012/08/28 21:23:52
Add a blank line here?
Brad Chen
2012/08/28 22:09:42
Done.
| |
332 /* Generate a random REX prefix, to use for the entire run. */ | |
333 static uint32_t RandomRexPrefix() { | |
334 static uint32_t static_rex_prefix = 0; | |
335 | |
336 if (0 == static_rex_prefix) { | |
337 #if NACL_LINUX || NACL_OSX | |
338 static_rex_prefix = kREXBase + (random() % kREXRange); | |
339 #elif NACL_WINDOWS | |
340 if (rand_s(&static_rex_prefix) != 0) { | |
341 ReportFatalError("rand_s() failed\n"); | |
342 } else { | |
343 static_rex_prefix = kREXBase + (static_rex_prefix % kREXRange); | |
344 } | |
345 #else | |
346 # error "Unknown operating system." | |
347 #endif | |
348 } | |
349 return static_rex_prefix; | |
350 } | |
351 #endif | |
352 | |
291 /* For x86-64, enhance the iteration by looping through REX prefixes. | 353 /* For x86-64, enhance the iteration by looping through REX prefixes. |
292 */ | 354 */ |
293 static void TestAllWithPrefixREX(unsigned int prefix, size_t prefix_length) { | 355 static void WithREX(TestAllFunction testall, |
356 const unsigned int prefix, | |
357 const size_t prefix_length) { | |
358 char pstr[kBufferSize]; | |
294 #if NACL_TARGET_SUBARCH == 64 | 359 #if NACL_TARGET_SUBARCH == 64 |
295 unsigned char REXp; | 360 unsigned char irex; |
296 unsigned int rprefix; | 361 unsigned int rprefix; |
297 /* test with REX prefixes */ | 362 /* test with REX prefixes */ |
298 for (REXp = 0x40; REXp < 0x50; REXp++) { | 363 printf("WithREX(testall, %x, %d, %d)\n", prefix, |
299 rprefix = (prefix << 8 | REXp); | 364 (int)prefix_length, gEasyDiffMode); |
300 printf("Testing with prefix %x\n", rprefix); | 365 if (gEasyDiffMode) { |
301 TestAllWithPrefix(rprefix, prefix_length + 1); | 366 printf("With random REX prefix.\n"); |
367 irex = RandomRexPrefix(); | |
368 rprefix = (prefix << 8 | irex); | |
Karl
2012/08/28 21:23:52
Could this operation be converted to a MACRO. It a
Brad Chen
2012/08/28 22:09:42
Done.
| |
369 testall(rprefix, prefix_length + 1, StrPrefix(prefix, "XX", pstr)); | |
370 } else { | |
371 for (irex = kREXBase; irex < kREXMax; irex++) { | |
372 rprefix = (prefix << 8 | irex); | |
373 printf("With REX prefix %x\n", rprefix); | |
374 testall(rprefix, prefix_length + 1, StrPrefix(rprefix, "", pstr)); | |
375 } | |
302 } | 376 } |
303 #endif | 377 #endif |
304 /* test with no REX prefix */ | 378 /* test with no REX prefix */ |
305 TestAllWithPrefix(prefix, prefix_length); | 379 testall(prefix, prefix_length, StrPrefix(prefix, NULL, pstr)); |
306 } | 380 } |
307 | 381 |
308 /* For all prefixes, call TestAllWithPrefix() to enumrate and test | 382 /* For all prefixes, call TestAllWithPrefix() to enumrate and test |
309 * all instructions. | 383 * all instructions. |
310 */ | 384 */ |
311 static void TestAllInstructions() { | 385 static void TestAllInstructions() { |
312 gSkipRepeatReports = TRUE; | 386 gSkipRepeatReports = TRUE; |
313 /* NOTE: Prefix byte order needs to be reversed when written as | 387 /* NOTE: Prefix byte order needs to be reversed when written as |
314 * an integer. For example, for integer prefix 0x3a0f, 0f will | 388 * an integer. For example, for integer prefix 0x3a0f, 0f will |
315 * go in instruction byte 0, and 3a in byte 1. | 389 * go in instruction byte 0, and 3a in byte 1. |
316 */ | 390 */ |
317 /* TODO(bradchen): extend enuminsts-64 to iterate over 64-bit prefixes. */ | 391 WithREX(TestAllWithPrefix, 0, 0); |
318 TestAllWithPrefixREX(0, 0); | 392 WithREX(TestAllWithPrefix, 0x0f, 1); /* two-byte opcode */ |
319 TestAllWithPrefixREX(0x0f, 1); | 393 WithREX(TestAllWithPrefix, 0x0ff2, 2); /* SSE2 */ |
320 TestAllWithPrefixREX(0x0ff2, 2); | 394 WithREX(TestAllWithPrefix, 0x0ff3, 2); /* SSE */ |
321 TestAllWithPrefixREX(0x0ff3, 2); | 395 WithREX(TestAllWithPrefix, 0x0f66, 2); /* SSE2 */ |
322 TestAllWithPrefixREX(0x0f66, 2); | 396 WithREX(TestAllWithPrefix, 0x380f, 2); /* SSSE3 */ |
323 TestAllWithPrefixREX(0x0f0f, 2); | 397 WithREX(TestAllWithPrefix, 0x3a0f, 2); /* SSE4 */ |
324 TestAllWithPrefixREX(0x380f, 2); | 398 WithREX(TestAllWithPrefix, 0x380f66, 3); /* SSE4+ */ |
325 TestAllWithPrefixREX(0x3a0f, 2); | 399 WithREX(TestAllWithPrefix, 0x380ff2, 3); /* SSE4+ */ |
326 TestAllWithPrefixREX(0x380f66, 3); | 400 WithREX(TestAllWithPrefix, 0x3a0f66, 3); /* SSE4+ */ |
327 TestAllWithPrefixREX(0x380ff2, 3); | |
328 TestAllWithPrefixREX(0x3a0f66, 3); | |
329 } | 401 } |
330 | 402 |
331 /* Used to test one instruction at a time, for example, in regression | 403 /* Used to test one instruction at a time, for example, in regression |
332 * testing, or for instruction arguments from the command line. | 404 * testing, or for instruction arguments from the command line. |
333 */ | 405 */ |
334 static void TestOneInstruction(char *asciihex) { | 406 static void TestOneInstruction(const char *asciihex) { |
335 InstByteArray ibytes; | 407 InstByteArray ibytes; |
336 int nbytes; | 408 int nbytes; |
337 | 409 |
338 nbytes = Text2Bytes(ibytes, asciihex, "Command-line argument", -1); | 410 nbytes = Text2Bytes(ibytes, asciihex, "Command-line argument", -1); |
339 if (nbytes == 0) return; | 411 if (nbytes == 0) return; |
340 if (gVerbose) { | 412 if (gVerbose) { |
341 int i; | 413 int i; |
342 printf("trying %s (", asciihex); | 414 printf("trying %s (", asciihex); |
343 for (i = 0; i < nbytes; ++i) { | 415 for (i = 0; i < nbytes; ++i) { |
344 printf("%02x", ibytes[i]); | 416 printf("%02x", ibytes[i]); |
(...skipping 28 matching lines...) Expand all Loading... | |
373 */ | 445 */ |
374 TestOneInstruction("262e7e00"); | 446 TestOneInstruction("262e7e00"); |
375 TestOneInstruction("2e3e7900"); | 447 TestOneInstruction("2e3e7900"); |
376 /* From the AMD manual, "An instruction may have only one REX prefix */ | 448 /* From the AMD manual, "An instruction may have only one REX prefix */ |
377 /* which must immediately precede the opcode or first excape byte */ | 449 /* which must immediately precede the opcode or first excape byte */ |
378 /* in the instruction encoding." */ | 450 /* in the instruction encoding." */ |
379 TestOneInstruction("406601d8"); /* illegal; REX before data16 */ | 451 TestOneInstruction("406601d8"); /* illegal; REX before data16 */ |
380 TestOneInstruction("664001d8"); /* legal; REX after data16 */ | 452 TestOneInstruction("664001d8"); /* legal; REX after data16 */ |
381 TestOneInstruction("414001d8"); /* illegal; two REX bytes */ | 453 TestOneInstruction("414001d8"); /* illegal; two REX bytes */ |
382 | 454 |
383 /* Reset the opcode repeat test, so as not to silence erros */ | 455 /* Reset the opcode repeat test, so as not to silence errors */ |
384 /* that happened in the regression suite. */ | 456 /* that happened in the regression suite. */ |
385 (void)NotOpcodeRepeat(""); | 457 (void)NotOpcodeRepeat(""); |
386 } | 458 } |
387 | 459 |
388 /* Define decoders that can be registered. */ | 460 /* Define decoders that can be registered. */ |
389 extern NaClEnumeratorDecoder* RegisterNaClDecoder(); | 461 extern NaClEnumeratorDecoder* RegisterNaClDecoder(); |
390 extern NaClEnumeratorDecoder* RegisterRagelDecoder(); | 462 extern NaClEnumeratorDecoder* RegisterRagelDecoder(); |
391 | 463 |
392 /* Initialize the set of available decoders. */ | 464 /* Initialize the set of available decoders. */ |
393 static void NaClInitializeAvailableDecoders() { | 465 static void VDiffInitializeAvailableDecoders() { |
394 vProd = RegisterNaClDecoder(); | 466 vProd = RegisterNaClDecoder(); |
395 vDFA = RegisterRagelDecoder(); | 467 vDFA = RegisterRagelDecoder(); |
396 } | 468 } |
397 | 469 |
398 int main(int argc, char *argv[]) { | 470 static int ParseArgv(const int argc, const char* argv[]) { |
399 int testargs; | 471 int nextarg; |
472 | |
473 gArgv0 = argv[0]; | |
474 nextarg = 1; | |
475 if (nextarg < argc && | |
476 0 == strcmp(argv[nextarg], FLAG_EasyDiff)) { | |
477 gEasyDiffMode = TRUE; | |
478 gCheckMnemonics = FALSE; | |
479 nextarg += 1; | |
480 } | |
481 return nextarg; | |
482 } | |
483 | |
484 int main(const int argc, const char *argv[]) { | |
485 int nextarg; | |
400 | 486 |
401 NaClLogModuleInit(); | 487 NaClLogModuleInit(); |
402 NaClLogSetVerbosity(LOG_FATAL); | 488 NaClLogSetVerbosity(LOG_FATAL); |
403 NaClInitializeAvailableDecoders(); | 489 #if NACL_LINUX || NACL_OSX |
490 srandom(time(NULL)); | |
491 #endif | |
492 VDiffInitializeAvailableDecoders(); | |
404 | 493 |
405 gArgv0 = argv[0]; | 494 nextarg = ParseArgv(argc, argv); |
406 testargs = 1; | 495 if (nextarg == argc) { |
407 | |
408 if (testargs == argc) { | |
409 if (gPrefix == 0) RunRegressionTests(); | 496 if (gPrefix == 0) RunRegressionTests(); |
410 TestAllInstructions(); | 497 TestAllInstructions(); |
411 } else { | 498 } else { |
412 int i; | 499 int i; |
413 gVerbose = TRUE; | 500 gVerbose = TRUE; |
414 for (i = testargs; i < argc; ++i) { | 501 for (i = nextarg; i < argc; ++i) { |
415 TestOneInstruction(argv[i]); | 502 TestOneInstruction(argv[i]); |
416 } | 503 } |
417 } | 504 } |
418 PrintStats(); | 505 PrintStats(); |
419 } | 506 } |
OLD | NEW |