OLD | NEW |
| (Empty) |
1 /* | |
2 * Copyright (c) 2011 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 // Unit tests for code in nc_inst_state.cc (and nc_inst_state_statics.c). | |
8 | |
9 #ifndef NACL_TRUSTED_BUT_NOT_TCB | |
10 #error("This file is not meant for use in the TCB") | |
11 #endif | |
12 | |
13 // To turn on debugging of instruction decoding, change value of | |
14 // DEBUGGING to 1. | |
15 #define DEBUGGING 0 | |
16 | |
17 #include "gtest/gtest.h" | |
18 #include "native_client/src/include/nacl_macros.h" | |
19 #include "native_client/src/trusted/validator/x86/decoder/nc_inst_state.h" | |
20 #include "native_client/src/trusted/validator_x86/ncdis_decode_tables.h" | |
21 | |
22 // Include static functions, so that we can test. | |
23 extern "C" { | |
24 #include "native_client/src/trusted/validator/x86/decoder/nc_inst_state_statics.
c" | |
25 }; | |
26 | |
27 namespace { | |
28 | |
29 // Size of buffer to use to contain bytes of an instruction. | |
30 static const size_t kBufferSize = 24; | |
31 | |
32 // Test harness for routines in nc_inst_state.c and nc_inst_state_statics.c. | |
33 class NcInstStateTests : public ::testing::Test { | |
34 protected: | |
35 NcInstStateTests(); | |
36 void SetUp(); | |
37 void TearDown(); | |
38 | |
39 // Plant the given byte as the next input byte in the input buffer. | |
40 // Uses plant_index to determine the current end of the input buffer. | |
41 void Plant(uint8_t byte); | |
42 | |
43 // Reset test state to a cleared input buffer, and (re)initialize | |
44 // the instruction state. | |
45 void Reset(); | |
46 | |
47 // Routine to add dummy calls so that compilation errors are not defined | |
48 // for static routines we have not tested. | |
49 void dummy(); | |
50 | |
51 // Reinitializes instruction state. | |
52 void ResetState(); | |
53 | |
54 // Resets the instruction pattern, and its flags to a default initial | |
55 // state. | |
56 void ResetInstPattern(); | |
57 | |
58 // Fills the input buffer with unlikely bytes, and initializes | |
59 // the reader to the beginning of the input buffer. | |
60 void ResetInput(); | |
61 | |
62 // Fills the input buffer with unlikely bytes, and set the plant | |
63 // index to the beginning of the input buffer. | |
64 void ResetInputBuffer(); | |
65 | |
66 // Verify that we have consumed the given number of prefix bytes, with | |
67 // the given number of rex prefixes, and that the prefix mask is set | |
68 // to the given mask. | |
69 // | |
70 // Parameters are: | |
71 // num_bytes - Number of prefix bytes read. | |
72 // num_rex - Number of prefix bytes that were rex prefixes. | |
73 // mask - prefix mask that should have been generated. | |
74 void VerifyConsumedPrefixBytes(uint8_t num_bytes, uint8_t num_rex, | |
75 uint32_t mask); | |
76 | |
77 // Run tests that verify that the call to NaClConsume0F38XXNaClInstBytes | |
78 // behaved as expected. Assumes the call was made through a call | |
79 // to NaClConsumeInstBytes. | |
80 void VerifyConsume0F38XXInstructions(); | |
81 | |
82 // Run tests that verify that the call to NaClConsume0F3AXXNaClInstBytes | |
83 // behaved as expected. Assumes the call was made through a call | |
84 // to NaClConsumeInstBytes. | |
85 void VerifyConsume0F3AXXInstructions(); | |
86 | |
87 // Run tests that verify that the call to NaClConsume0FXXNaClInstBytes | |
88 // behaved as expected. Assumes the call was made through a call | |
89 // to NaClConsumeInstBytes. | |
90 void VerifyConsume0FXXInstructions(); | |
91 | |
92 // Run tests that verify that the call to NaClConsumeX87NaClInstBytes | |
93 // behaved as expected. Assumes the call was made through a call | |
94 // to NaClConsumeInstBytes. | |
95 void VerifyConsumeX87Instructions(); | |
96 | |
97 // Run tests that verify that the call to NaClConsumeInstBytes consumed | |
98 // a single byte. | |
99 void VerifyConsumeOneByteInstructions(); | |
100 | |
101 // The instruction state to test. | |
102 struct NaClInstState* _state; | |
103 // The instruction iterator to use. | |
104 struct NaClInstIter* _iter; | |
105 // The memory segment to test. | |
106 struct NaClSegment _segment; | |
107 // The memory buffer in the memory segment. | |
108 uint8_t _buffer[kBufferSize]; | |
109 // The instruction pattern to match against. | |
110 struct NaClInst _inst_pattern; | |
111 // The index of where the next planted byte should | |
112 // be added to the input buffer. | |
113 size_t _plant_index; | |
114 }; | |
115 | |
116 // Helper function to convert Bool to bool. This function is defined | |
117 // to get around a visual studio warning for 64-bits, which causes | |
118 // our trybots to fail (in our build system, compiler warnings are converted | |
119 // to compiler errors). | |
120 static inline bool Bool2bool(Bool b) { | |
121 return b ? true : false; | |
122 } | |
123 | |
124 NcInstStateTests::NcInstStateTests() { | |
125 ResetInputBuffer(); | |
126 NaClSegmentInitialize(_buffer, 0, kBufferSize, &_segment); | |
127 } | |
128 | |
129 void NcInstStateTests::SetUp() { | |
130 _iter = NaClInstIterCreate(kNaClDecoderTables, &_segment); | |
131 _state = NaClInstIterGetUndecodedState(_iter); | |
132 ResetInput(); | |
133 ResetState(); | |
134 } | |
135 | |
136 void NcInstStateTests::TearDown() { | |
137 NaClInstIterDestroy(_iter); | |
138 } | |
139 | |
140 void NcInstStateTests::Reset() { | |
141 ResetInput(); | |
142 ResetState(); | |
143 } | |
144 | |
145 void NcInstStateTests::ResetState() { | |
146 NaClInstStateInit(_iter, _state); | |
147 ResetInstPattern(); | |
148 } | |
149 | |
150 void NcInstStateTests::ResetInstPattern() { | |
151 _inst_pattern.flags = NACL_EMPTY_IFLAGS; | |
152 _state->inst = &_inst_pattern; | |
153 } | |
154 | |
155 void NcInstStateTests::ResetInputBuffer() { | |
156 // Fill input buffer with unlikely byte codes. | |
157 for (size_t i = 0; i < kBufferSize; ++i) { | |
158 _buffer[i] = 'X'; | |
159 } | |
160 // Mark start point for planting data into | |
161 // the input buffer. | |
162 _plant_index = 0; | |
163 } | |
164 | |
165 void NcInstStateTests::ResetInput() { | |
166 ResetInputBuffer(); | |
167 NCInstBytesReset(&_state->bytes); | |
168 } | |
169 | |
170 void NcInstStateTests::Plant(uint8_t byte) { | |
171 // TODO(Karl): Why do we get a compile time error if we use ASSERT. | |
172 ASSERT_LT(_plant_index, kBufferSize) << | |
173 "Planted too many bytes, buffer overflow!"; | |
174 _buffer[_plant_index++] = byte; | |
175 // Need to reset memory so that peek byte is set. | |
176 NCRemainingMemoryReset(_state->bytes.memory); | |
177 } | |
178 | |
179 void NcInstStateTests::VerifyConsumedPrefixBytes( | |
180 uint8_t num_bytes, uint8_t num_rex, uint32_t mask) { | |
181 EXPECT_EQ(num_bytes, _state->bytes.length); | |
182 EXPECT_EQ(num_bytes, _state->num_prefix_bytes); | |
183 EXPECT_EQ(mask, _state->prefix_mask); | |
184 EXPECT_EQ(num_rex, _state->num_rex_prefixes); | |
185 } | |
186 | |
187 void NcInstStateTests::VerifyConsume0F38XXInstructions() { | |
188 NaClInstPrefixDescriptor desc; | |
189 uint32_t prefix_mask = _state->prefix_mask; | |
190 // Note: This code assumes that the prefix mask may have | |
191 // other flags set before this routine is called. Hence, | |
192 // we must be careful when updating and checking the | |
193 // mask. | |
194 | |
195 // Test for all possible XX. | |
196 for (int i = 0; i < NCDTABLESIZE; ++i) { | |
197 // Test successfully matching 0f38XX | |
198 _state->prefix_mask = prefix_mask; | |
199 Plant(0x0f); | |
200 Plant(0x38); | |
201 Plant(i); | |
202 NaClConsumeInstBytes(_state, &desc); | |
203 if (NaClHasBit(_state->prefix_mask, kPrefixREP)) { | |
204 EXPECT_EQ(NaClInstPrefixEnumSize, desc.matched_prefix); | |
205 } else if (NaClHasBit(_state->prefix_mask, kPrefixREPNE)) { | |
206 EXPECT_EQ(PrefixF20F38, desc.matched_prefix); | |
207 } else if (NaClHasBit(_state->prefix_mask, kPrefixDATA16)) { | |
208 EXPECT_EQ(Prefix660F38, desc.matched_prefix); | |
209 } else { | |
210 EXPECT_EQ(Prefix0F38, desc.matched_prefix); | |
211 } | |
212 EXPECT_EQ((uint8_t) i, desc.opcode_byte); | |
213 EXPECT_EQ((uint8_t) 0, desc.next_length_adjustment); | |
214 ResetInput(); | |
215 ResetState(); | |
216 } | |
217 | |
218 // Now verify if that there isn't an XX byte, things short curcuit correctly. | |
219 _state->prefix_mask = prefix_mask; | |
220 Plant(0x0f); | |
221 Plant(0x38); | |
222 _state->length_limit = 2; | |
223 NaClConsumeInstBytes(_state, &desc); | |
224 EXPECT_EQ(NaClInstPrefixEnumSize, desc.matched_prefix); | |
225 EXPECT_EQ((uint8_t) 0, desc.next_length_adjustment); | |
226 ResetInput(); | |
227 ResetState(); | |
228 } | |
229 | |
230 void NcInstStateTests::VerifyConsume0F3AXXInstructions() { | |
231 NaClInstPrefixDescriptor desc; | |
232 uint32_t prefix_mask = _state->prefix_mask; | |
233 // Note: This code assumes that the prefix mask may have | |
234 // other flags set before this routine is called. Hence, | |
235 // we must be careful when updating and checking the | |
236 // mask. | |
237 | |
238 // Test for all possible XX. | |
239 for (int i = 0; i < NCDTABLESIZE; ++i) { | |
240 // Test successfully matching 0F3AXX | |
241 _state->prefix_mask = prefix_mask; | |
242 Plant(0x0f); | |
243 Plant(0x3a); | |
244 Plant(i); | |
245 NaClConsumeInstBytes(_state, &desc); | |
246 if (NaClHasBit(_state->prefix_mask, kPrefixREP) || | |
247 NaClHasBit(_state->prefix_mask, kPrefixREPNE)) { | |
248 EXPECT_EQ(NaClInstPrefixEnumSize, desc.matched_prefix); | |
249 } else if (NaClHasBit(_state->prefix_mask, kPrefixDATA16)) { | |
250 EXPECT_EQ(Prefix660F3A, desc.matched_prefix); | |
251 } else { | |
252 EXPECT_EQ(Prefix0F3A, desc.matched_prefix); | |
253 } | |
254 EXPECT_EQ((uint8_t) i, desc.opcode_byte); | |
255 EXPECT_EQ((uint8_t) 0, desc.next_length_adjustment); | |
256 ResetInput(); | |
257 ResetState(); | |
258 } | |
259 | |
260 // Now verify if that there isn't an XX byte, things short curcuit correctly. | |
261 _state->prefix_mask = prefix_mask; | |
262 Plant(0x0f); | |
263 Plant(0x3a); | |
264 _state->length_limit = 2; | |
265 NaClConsumeInstBytes(_state, &desc); | |
266 EXPECT_EQ(NaClInstPrefixEnumSize, desc.matched_prefix); | |
267 EXPECT_EQ((uint8_t) 0, desc.next_length_adjustment); | |
268 ResetInput(); | |
269 ResetState(); | |
270 } | |
271 | |
272 void NcInstStateTests::VerifyConsume0FXXInstructions() { | |
273 NaClInstPrefixDescriptor desc; | |
274 uint32_t prefix_mask = _state->prefix_mask; | |
275 // Note: This code assumes that the prefix mask may have | |
276 // other flags set before this routine is called. Hence, | |
277 // we must be careful when updating and checking the | |
278 // mask. | |
279 | |
280 // Test for all possible XX. | |
281 for (int i = 0; i < NCDTABLESIZE; ++i) { | |
282 if (i == 0x38 || i == 0x3a) continue; // exclude special lookup cases. | |
283 // Test successfully matching 0fXX | |
284 _state->prefix_mask = prefix_mask; | |
285 Plant(0x0f); | |
286 Plant(i); | |
287 NaClConsumeInstBytes(_state, &desc); | |
288 if (NaClHasBit(_state->prefix_mask, kPrefixREP)) { | |
289 if (NaClHasBit(_state->prefix_mask, kPrefixREPNE)) { | |
290 EXPECT_EQ(NaClInstPrefixEnumSize, desc.matched_prefix); | |
291 } else { | |
292 EXPECT_EQ(PrefixF30F, desc.matched_prefix); | |
293 } | |
294 } else if (NaClHasBit(_state->prefix_mask, kPrefixREPNE)) { | |
295 EXPECT_EQ(PrefixF20F, desc.matched_prefix); | |
296 } else if (NaClHasBit(_state->prefix_mask, kPrefixDATA16)) { | |
297 EXPECT_EQ(Prefix660F, desc.matched_prefix); | |
298 } else { | |
299 EXPECT_EQ(Prefix0F, desc.matched_prefix); | |
300 } | |
301 EXPECT_EQ((uint8_t) i, desc.opcode_byte); | |
302 EXPECT_EQ((uint8_t) 0, desc.next_length_adjustment); | |
303 ResetInput(); | |
304 ResetState(); | |
305 } | |
306 | |
307 // Now verify if that there isn't an XX byte, things short curcuit correctly. | |
308 _state->prefix_mask = prefix_mask; | |
309 Plant(0x0f); | |
310 _state->length_limit = 1; | |
311 NaClConsumeInstBytes(_state, &desc); | |
312 EXPECT_EQ(NaClInstPrefixEnumSize, desc.matched_prefix); | |
313 EXPECT_EQ((uint8_t) 0, desc.next_length_adjustment); | |
314 ResetInput(); | |
315 ResetState(); | |
316 } | |
317 | |
318 void NcInstStateTests::VerifyConsumeX87Instructions() { | |
319 NaClInstPrefixDescriptor desc; | |
320 uint32_t prefix_mask = _state->prefix_mask; | |
321 // Note: This code assumes that the prefix mask may have | |
322 // other flags set before this routine is called. Hence, | |
323 // we must be careful when updating and checking the | |
324 // mask. | |
325 | |
326 // Try for all possible x87 initial bytes. | |
327 for (uint8_t byte1 = 0xD8; byte1 <= 0xDF; ++byte1) { | |
328 // Test for all possible XX. | |
329 for (int i = 0; i < NCDTABLESIZE; ++i) { | |
330 // Test successfully matching byte1 XX | |
331 _state->prefix_mask = prefix_mask; | |
332 Plant(byte1); | |
333 Plant(i); | |
334 NaClConsumeInstBytes(_state, &desc); | |
335 NaClInstPrefix prefix = (NaClInstPrefix) (PrefixD8 + (byte1 - 0xD8)); | |
336 EXPECT_EQ(prefix, desc.matched_prefix); | |
337 EXPECT_EQ((uint8_t) i, desc.opcode_byte); | |
338 EXPECT_EQ((uint8_t) 0, desc.next_length_adjustment); | |
339 ResetInput(); | |
340 ResetState(); | |
341 } | |
342 | |
343 // Now verify if that there isn't an XX byte, things short curcuit | |
344 // correctly. For this context, it should return matching a single | |
345 // byte instruction with no prefix. | |
346 _state->prefix_mask = prefix_mask; | |
347 Plant(byte1); | |
348 _state->length_limit = 1; | |
349 NaClConsumeInstBytes(_state, &desc); | |
350 EXPECT_EQ(NoPrefix, desc.matched_prefix); | |
351 EXPECT_EQ((uint8_t) 0, desc.next_length_adjustment); | |
352 ResetInput(); | |
353 ResetState(); | |
354 } | |
355 } | |
356 | |
357 void NcInstStateTests::VerifyConsumeOneByteInstructions() { | |
358 NaClInstPrefixDescriptor desc; | |
359 uint32_t prefix_mask = _state->prefix_mask; | |
360 // Note: This code assumes that the prefix mask may have | |
361 // other flags set before this routine is called. Hence, | |
362 // we must be careful when updating and checking the | |
363 // mask. | |
364 | |
365 // Test for all possible XX. | |
366 for (int i = 0; i < NCDTABLESIZE; ++i) { | |
367 // exclude special lookup cases. | |
368 if (i == 0x0f || (i >= 0xD8 && i <= 0xDF)) continue; | |
369 // Test successfully XX | |
370 _state->prefix_mask = prefix_mask; | |
371 Plant(i); | |
372 NaClConsumeInstBytes(_state, &desc); | |
373 EXPECT_EQ(NoPrefix, desc.matched_prefix); | |
374 EXPECT_EQ((uint8_t) i, desc.opcode_byte); | |
375 EXPECT_EQ((uint8_t) 0, desc.next_length_adjustment); | |
376 ResetInput(); | |
377 ResetState(); | |
378 } | |
379 | |
380 // Now verify if that there isn't an XX byte, things short curcuit correctly. | |
381 _state->prefix_mask = prefix_mask; | |
382 _state->length_limit = 0; | |
383 NaClConsumeInstBytes(_state, &desc); | |
384 EXPECT_EQ(NaClInstPrefixEnumSize, desc.matched_prefix); | |
385 EXPECT_EQ((uint8_t) 0, desc.next_length_adjustment); | |
386 ResetInput(); | |
387 ResetState(); | |
388 } | |
389 | |
390 void NcInstStateTests::dummy() { | |
391 NaClInstPrefixDescriptor prefix_desc; | |
392 prefix_desc.opcode_byte = 0x0; | |
393 prefix_desc.next_length_adjustment = 0; | |
394 prefix_desc.matched_prefix = NoPrefix; | |
395 NaClConsumeAndCheckOperandSize(_state); | |
396 NaClConsumeAndCheckAddressSize(_state); | |
397 NaClConsumeModRm(_state); | |
398 NaClConsumeSib(_state); | |
399 NaClConsumeDispBytes(_state); | |
400 NaClConsumeImmediateBytes(_state); | |
401 NaClValidatePrefixFlags(_state); | |
402 NaClClearInstState(_state, 0); | |
403 NaClGetNextInstCandidates(_state, &prefix_desc, NULL); | |
404 NaClConsumeHardCodedNop(_state); | |
405 } | |
406 | |
407 // Test function NaClExtactOpSize, which returns the expected | |
408 // number of bytes to represent operands. | |
409 TEST_F(NcInstStateTests, TestExtractOpSize) { | |
410 // Test 32 amd 64 bit assumptions. | |
411 | |
412 // Test explicit size restrictors. Note: Only b should make a difference | |
413 // in matching the pattern, since v, w, and o are used as excluders rather | |
414 // than for matching (i.e. don't match unless operand size should be | |
415 // 1). | |
416 _inst_pattern.flags = NACL_IFLAG(OperandSize_b); | |
417 EXPECT_EQ(1, NaClExtractOpSize(_state)) << "bytes are of size 1\n"; | |
418 _inst_pattern.flags = NACL_IFLAG(OperandSize_w); | |
419 EXPECT_EQ(4, NaClExtractOpSize(_state)); | |
420 _inst_pattern.flags = NACL_IFLAG(OperandSize_v); | |
421 EXPECT_EQ(4, NaClExtractOpSize(_state)); | |
422 _inst_pattern.flags = NACL_IFLAG(OperandSize_o); | |
423 EXPECT_EQ(4, NaClExtractOpSize(_state)); | |
424 ResetState(); | |
425 | |
426 // See if we interpret the Data16 prefix correctly. | |
427 _state->prefix_mask = kPrefixDATA16; | |
428 EXPECT_EQ(2, NaClExtractOpSize(_state)); | |
429 _inst_pattern.flags = NACL_IFLAG(SizeIgnoresData16); | |
430 EXPECT_EQ(4, NaClExtractOpSize(_state)); | |
431 ResetState(); | |
432 | |
433 // Test strictly 64-bit assumptions. | |
434 if (NACL_TARGET_SUBARCH == 64) { | |
435 // Check that we return a size 64 if the REX.W bit is set. | |
436 for (uint8_t rex = NaClRexMin; rex <= NaClRexMax; ++rex) { | |
437 _state->rexprefix = rex; | |
438 if (NaClRexW(rex)) { | |
439 EXPECT_EQ(8, NaClExtractOpSize(_state)); | |
440 } else { | |
441 EXPECT_EQ(4, NaClExtractOpSize(_state)); | |
442 } | |
443 } | |
444 ResetState(); | |
445 | |
446 // If we force the size to 64, it returns size 64. | |
447 _inst_pattern.flags = NACL_IFLAG(OperandSizeForce64); | |
448 EXPECT_EQ(8, NaClExtractOpSize(_state)); | |
449 ResetState(); | |
450 | |
451 // Now repeat the tests, but with the default size set to 64 bits, | |
452 // which replaces the default size of 4 with 8. | |
453 | |
454 // Test explicit size restrictors. Note: Only b should make a difference | |
455 // in matching the pattern, since v, w, and o are used as excluders rather | |
456 // than for matching (i.e. don't match unless operand size matches). | |
457 _inst_pattern.flags = | |
458 NACL_IFLAG(OperandSize_b) | NACL_IFLAG(OperandSizeDefaultIs64); | |
459 EXPECT_EQ(1, NaClExtractOpSize(_state)) << "bytes are of size 1\n"; | |
460 _inst_pattern.flags = | |
461 NACL_IFLAG(OperandSize_w) | NACL_IFLAG(OperandSizeDefaultIs64); | |
462 EXPECT_EQ(8, NaClExtractOpSize(_state)); | |
463 _inst_pattern.flags = | |
464 NACL_IFLAG(OperandSize_v) | NACL_IFLAG(OperandSizeDefaultIs64); | |
465 EXPECT_EQ(8, NaClExtractOpSize(_state)); | |
466 _inst_pattern.flags = | |
467 NACL_IFLAG(OperandSize_o) | NACL_IFLAG(OperandSizeDefaultIs64); | |
468 EXPECT_EQ(8, NaClExtractOpSize(_state)); | |
469 ResetState(); | |
470 | |
471 // See if we interpret the Data16 prefix correctly. | |
472 _state->prefix_mask = kPrefixDATA16; | |
473 _inst_pattern.flags = NACL_IFLAG(OperandSizeDefaultIs64); | |
474 EXPECT_EQ(2, NaClExtractOpSize(_state)); | |
475 _inst_pattern.flags = | |
476 NACL_IFLAG(SizeIgnoresData16) | NACL_IFLAG(OperandSizeDefaultIs64); | |
477 EXPECT_EQ(8, NaClExtractOpSize(_state)); | |
478 ResetState(); | |
479 | |
480 // Check that we return a size 64 independent of the REX.W bit. | |
481 _inst_pattern.flags = NACL_IFLAG(OperandSizeDefaultIs64); | |
482 for (uint8_t rex = NaClRexMin; rex <= NaClRexMax; ++rex) { | |
483 _state->rexprefix = rex; | |
484 EXPECT_EQ(8, NaClExtractOpSize(_state)); | |
485 } | |
486 } | |
487 } | |
488 | |
489 // Test function NaClExtractAddressSize, which returns the expected | |
490 // number of bits in operands corresponding to addresses. | |
491 TEST_F(NcInstStateTests, TestExtractAddressSize) { | |
492 // Depending on whether we are in 32/64 bit mode, there are two | |
493 // different address sizes. | |
494 int small_address; | |
495 int large_address; | |
496 if (NACL_TARGET_SUBARCH == 64) { | |
497 small_address = 32; | |
498 large_address = 64; | |
499 } else { | |
500 small_address = 16; | |
501 large_address = 32; | |
502 } | |
503 EXPECT_EQ(large_address, NaClExtractAddressSize(_state)); | |
504 _state->prefix_mask = kPrefixADDR16; | |
505 EXPECT_EQ(small_address, NaClExtractAddressSize(_state)); | |
506 } | |
507 | |
508 extern "C" { | |
509 // Define acceptable prefixes, and the corresponding flag that | |
510 // should be set (except for rex prefixes). | |
511 static const struct prefix_pairs { | |
512 uint8_t byte; | |
513 uint32_t mask; | |
514 } prefix_values[] = { | |
515 {kValueSEGCS, kPrefixSEGCS}, | |
516 {kValueSEGSS, kPrefixSEGSS}, | |
517 {kValueSEGFS, kPrefixSEGFS}, | |
518 {kValueSEGGS, kPrefixSEGGS}, | |
519 {kValueDATA16, kPrefixDATA16}, | |
520 {kValueADDR16, kPrefixADDR16}, | |
521 {kValueREPNE, kPrefixREPNE}, | |
522 {kValueREP, kPrefixREP}, | |
523 {kValueLOCK, kPrefixLOCK}, | |
524 {kValueSEGES, kPrefixSEGES}, | |
525 {kValueSEGDS, kPrefixSEGDS} | |
526 }; | |
527 }; | |
528 | |
529 // Test function NaClConsumePrefixBytes to verify it only recognizes | |
530 // valid prefix values. | |
531 TEST_F(NcInstStateTests, ConsumesKnownPrefixBytes) { | |
532 for (int byte = 0; byte < NCDTABLESIZE; ++byte) { | |
533 bool byte_categorized = false; | |
534 Plant(byte); | |
535 EXPECT_TRUE(Bool2bool(NaClConsumePrefixBytes(_state))); | |
536 if (NACL_TARGET_SUBARCH == 64 && | |
537 byte >= NaClRexMin && byte <= NaClRexMax) { | |
538 VerifyConsumedPrefixBytes(1, 1, kPrefixREX); | |
539 byte_categorized = true; | |
540 } else { | |
541 for (size_t j = 0; j < NACL_ARRAY_SIZE(prefix_values); ++j) { | |
542 if (byte == prefix_values[j].byte) { | |
543 VerifyConsumedPrefixBytes(1, 0, prefix_values[j].mask); | |
544 byte_categorized = true; | |
545 } | |
546 } | |
547 } | |
548 if (!byte_categorized) { | |
549 VerifyConsumedPrefixBytes(0, 0, 0); | |
550 } | |
551 ResetInput(); | |
552 ResetState(); | |
553 } | |
554 } | |
555 | |
556 // Test function NaClConsumePrefixBytes to verify it can recognize | |
557 // pairs of non-rex prefix bytes. | |
558 TEST_F(NcInstStateTests, ConsumeNonRexPrefixBytePairs) { | |
559 // First try some pairs within non-rex prefix bytes. | |
560 for (size_t i = 0; i < NACL_ARRAY_SIZE(prefix_values) - 1; ++i) { | |
561 Plant(prefix_values[i].byte); | |
562 Plant(prefix_values[i+1].byte); | |
563 EXPECT_TRUE(Bool2bool(NaClConsumePrefixBytes(_state))); | |
564 VerifyConsumedPrefixBytes(2, 0, | |
565 prefix_values[i].mask | prefix_values[i+1].mask); | |
566 ResetInput(); | |
567 ResetState(); | |
568 } | |
569 } | |
570 | |
571 // Test Function NaClConsumePrefixBytes to verify it can recognize | |
572 // a Rex prefix followed by a non-rex prefix. | |
573 TEST_F(NcInstStateTests, ConsumeRexThenNonRexPrefixPairs) { | |
574 if (NACL_TARGET_SUBARCH == 64) { | |
575 // Try some pairs where one is rex. | |
576 for (size_t i = 0; i < NACL_ARRAY_SIZE(prefix_values); ++i) { | |
577 for (uint8_t rex = NaClRexMin; rex <= NaClRexMax; ++rex) { | |
578 Plant(rex); | |
579 Plant(prefix_values[i].byte); | |
580 EXPECT_TRUE(Bool2bool(NaClConsumePrefixBytes(_state))); | |
581 VerifyConsumedPrefixBytes(2, 1, prefix_values[i].mask | kPrefixREX); | |
582 ResetInput(); | |
583 ResetState(); | |
584 } | |
585 } | |
586 } | |
587 } | |
588 | |
589 // Test Function NaClConsumePrefixBytes to verify it can recognize | |
590 // a non-rex prefix, followed by a rex prefix. | |
591 TEST_F(NcInstStateTests, ConsumeNonRexThenRexPrefixPairs) { | |
592 if (NACL_TARGET_SUBARCH == 64) { | |
593 // Try some pairs where one is rex. | |
594 for (size_t i = 0; i < NACL_ARRAY_SIZE(prefix_values); ++i) { | |
595 for (uint8_t rex = NaClRexMin; rex <= NaClRexMax; ++rex) { | |
596 Plant(prefix_values[i].byte); | |
597 Plant(rex); | |
598 EXPECT_TRUE(Bool2bool(NaClConsumePrefixBytes(_state))); | |
599 VerifyConsumedPrefixBytes(2, 1, prefix_values[i].mask | kPrefixREX); | |
600 ResetInput(); | |
601 ResetState(); | |
602 } | |
603 } | |
604 } | |
605 } | |
606 | |
607 // Test function NaClConsumePrefixBytes on multiple rex prefixes. | |
608 TEST_F(NcInstStateTests, ConsumeMultipleRexPrefixes) { | |
609 if (NACL_TARGET_SUBARCH == 64) { | |
610 for (uint8_t rex1 = NaClRexMin; rex1 <= NaClRexMax; ++rex1) { | |
611 for (uint8_t rex2 = NaClRexMin; rex2 <= NaClRexMax; ++rex2) { | |
612 Plant(rex1); | |
613 Plant(rex2); | |
614 EXPECT_TRUE(Bool2bool(NaClConsumePrefixBytes(_state))); | |
615 VerifyConsumedPrefixBytes(2, 2, kPrefixREX); | |
616 ResetInput(); | |
617 ResetState(); | |
618 } | |
619 } | |
620 } | |
621 } | |
622 | |
623 // Test function NaClConsumePrefixBytes to see if we allow multiple | |
624 // copies of the same (non-rex) prefix. | |
625 TEST_F(NcInstStateTests, ConsumeDuplicatePrefixes) { | |
626 // Try with non rex prefixes. | |
627 for (size_t i = 0; i < NACL_ARRAY_SIZE(prefix_values); ++i) { | |
628 Plant(prefix_values[i].byte); | |
629 Plant(prefix_values[i].byte); | |
630 EXPECT_TRUE(Bool2bool(NaClConsumePrefixBytes(_state))); | |
631 VerifyConsumedPrefixBytes(2, 0, prefix_values[i].mask); | |
632 ResetInput(); | |
633 ResetState(); | |
634 } | |
635 } | |
636 | |
637 // Test if we can recognize 14 prefix bytes. | |
638 TEST_F(NcInstStateTests, Consume14PrefixBytes) { | |
639 for (int i = 0; i < 14; ++i) { | |
640 Plant(kValueDATA16); | |
641 } | |
642 EXPECT_TRUE(Bool2bool(NaClConsumePrefixBytes(_state))); | |
643 VerifyConsumedPrefixBytes(14, 0, kPrefixDATA16); | |
644 } | |
645 | |
646 // Test that we can't accept 15 prefix bytes. | |
647 TEST_F(NcInstStateTests, Consume15PrefixBytes) { | |
648 for (int i = 0; i < 15; ++i) { | |
649 Plant(kValueDATA16); | |
650 } | |
651 EXPECT_TRUE(Bool2bool(NaClConsumePrefixBytes(_state))); | |
652 EXPECT_EQ((uint8_t) 14, _state->bytes.length); | |
653 } | |
654 | |
655 // Defines the set of prefix bytes that effect multibyte instructions | |
656 // (i.e. REP, REPNE, and DATA16), and all possible combinations of | |
657 // these prefixes. | |
658 static const uint32_t kMultibytePrefixes[] = { | |
659 0, | |
660 kPrefixREP, | |
661 kPrefixREP | kPrefixREPNE, | |
662 kPrefixREP | kPrefixREPNE | kPrefixDATA16, | |
663 kPrefixREPNE, | |
664 kPrefixREPNE | kPrefixDATA16, | |
665 kPrefixDATA16 | |
666 }; | |
667 | |
668 // Test function NaClConsume0F38XXNaClInstBytes, as called through | |
669 // function NaClConsumeInstBytes. | |
670 TEST_F(NcInstStateTests, ConsumeOF38XXInstructions) { | |
671 // First try effects of just multibyte prefixes. | |
672 for (size_t i = 0; i < NACL_ARRAY_SIZE(kMultibytePrefixes); ++i) { | |
673 _state->prefix_mask = kMultibytePrefixes[i]; | |
674 VerifyConsume0F38XXInstructions(); | |
675 | |
676 // Verify that adding a rex prefix don't effect anything. | |
677 _state->prefix_mask = kMultibytePrefixes[i] | kPrefixREX; | |
678 VerifyConsume0F38XXInstructions(); | |
679 | |
680 // Now try adding other possible prefixes to see if they break anything. | |
681 for (size_t j = 0; j < NACL_ARRAY_SIZE(prefix_values); ++j) { | |
682 _state->prefix_mask = kMultibytePrefixes[i] | prefix_values[i].mask; | |
683 VerifyConsume0F38XXInstructions(); | |
684 | |
685 // Verify that adding a rex prefix don't effect anything. | |
686 _state->prefix_mask = kMultibytePrefixes[i] | prefix_values[i].mask | |
687 | kPrefixREX; | |
688 VerifyConsume0F38XXInstructions(); | |
689 } | |
690 } | |
691 } | |
692 | |
693 // Test function NaClConsume0F3AXXNaClInstBytes, as called through | |
694 // function NaClConsumeInstBytes. | |
695 TEST_F(NcInstStateTests, ConsumeOF3AXXInstructions) { | |
696 // First try effects of just multibyte prefixes. | |
697 for (size_t i = 0; i < NACL_ARRAY_SIZE(kMultibytePrefixes); ++i) { | |
698 _state->prefix_mask = kMultibytePrefixes[i]; | |
699 VerifyConsume0F3AXXInstructions(); | |
700 | |
701 // Verify that adding a rex prefix don't effect anything. | |
702 _state->prefix_mask = kMultibytePrefixes[i] | kPrefixREX; | |
703 VerifyConsume0F3AXXInstructions(); | |
704 | |
705 // Now try adding other possible prefixes to see if they break anything. | |
706 for (size_t j = 0; j < NACL_ARRAY_SIZE(prefix_values); ++j) { | |
707 _state->prefix_mask = kMultibytePrefixes[i] | prefix_values[i].mask; | |
708 VerifyConsume0F3AXXInstructions(); | |
709 | |
710 // Verify that adding a rex prefix don't effect anything. | |
711 _state->prefix_mask = kMultibytePrefixes[i] | prefix_values[i].mask | |
712 | kPrefixREX; | |
713 VerifyConsume0F3AXXInstructions(); | |
714 } | |
715 } | |
716 } | |
717 | |
718 // Test function NaClConsume0FXXNaClInstBytes, as called through | |
719 // function NaClConsumeInstBytes. | |
720 TEST_F(NcInstStateTests, ConsumeOFXXInstructions) { | |
721 // First try effects of just multibyte prefixes. | |
722 for (size_t i = 0; i < NACL_ARRAY_SIZE(kMultibytePrefixes); ++i) { | |
723 _state->prefix_mask = kMultibytePrefixes[i]; | |
724 VerifyConsume0FXXInstructions(); | |
725 | |
726 // Verify that adding a rex prefix don't effect anything. | |
727 _state->prefix_mask = kMultibytePrefixes[i] | kPrefixREX; | |
728 VerifyConsume0FXXInstructions(); | |
729 | |
730 // Now try adding other possible prefixes to see if they break anything. | |
731 for (size_t j = 0; j < NACL_ARRAY_SIZE(prefix_values); ++j) { | |
732 _state->prefix_mask = kMultibytePrefixes[i] | prefix_values[i].mask; | |
733 VerifyConsume0FXXInstructions(); | |
734 | |
735 // Verify that adding a rex prefix don't effect anything. | |
736 _state->prefix_mask = kMultibytePrefixes[i] | prefix_values[i].mask | |
737 | kPrefixREX; | |
738 VerifyConsume0FXXInstructions(); | |
739 } | |
740 } | |
741 } | |
742 | |
743 // Test function NaClConsumeX87NaClInstBytes, as called through | |
744 // function NaClConsumeInstBytes. | |
745 TEST_F(NcInstStateTests, ConsumeX87Instructions) { | |
746 // First try effects of just multibyte prefixes. | |
747 for (size_t i = 0; i < NACL_ARRAY_SIZE(kMultibytePrefixes); ++i) { | |
748 _state->prefix_mask = kMultibytePrefixes[i]; | |
749 VerifyConsumeX87Instructions(); | |
750 | |
751 // Verify that adding a rex prefix don't effect anything. | |
752 _state->prefix_mask = kMultibytePrefixes[i] | kPrefixREX; | |
753 VerifyConsumeX87Instructions(); | |
754 | |
755 // Now try adding other possible prefixes to see if they break anything. | |
756 for (size_t j = 0; j < NACL_ARRAY_SIZE(prefix_values); ++j) { | |
757 _state->prefix_mask = kMultibytePrefixes[i] | prefix_values[i].mask; | |
758 VerifyConsumeX87Instructions(); | |
759 | |
760 // Verify that adding a rex prefix don't effect anything. | |
761 _state->prefix_mask = kMultibytePrefixes[i] | prefix_values[i].mask | |
762 | kPrefixREX; | |
763 VerifyConsumeX87Instructions(); | |
764 } | |
765 } | |
766 } | |
767 | |
768 // Test function NaClConsumeInstBytes for one byte instruction values. | |
769 TEST_F(NcInstStateTests, ConsumeOneByteInstructions) { | |
770 // First try effects of just multibyte prefixes. | |
771 for (size_t i = 0; i < NACL_ARRAY_SIZE(kMultibytePrefixes); ++i) { | |
772 _state->prefix_mask = kMultibytePrefixes[i]; | |
773 VerifyConsumeOneByteInstructions(); | |
774 | |
775 // Verify that adding a rex prefix don't effect anything. | |
776 _state->prefix_mask = kMultibytePrefixes[i] | kPrefixREX; | |
777 VerifyConsumeOneByteInstructions(); | |
778 | |
779 // Now try adding other possible prefixes to see if they break anything. | |
780 for (size_t j = 0; j < NACL_ARRAY_SIZE(prefix_values); ++j) { | |
781 _state->prefix_mask = kMultibytePrefixes[i] | prefix_values[i].mask; | |
782 VerifyConsumeOneByteInstructions(); | |
783 | |
784 // Verify that adding a rex prefix don't effect anything. | |
785 _state->prefix_mask = kMultibytePrefixes[i] | prefix_values[i].mask | |
786 | kPrefixREX; | |
787 VerifyConsumeOneByteInstructions(); | |
788 } | |
789 } | |
790 } | |
791 | |
792 }; // anonymous namespace | |
793 | |
794 int main(int argc, char *argv[]) { | |
795 NaClLogModuleInit(); | |
796 testing::InitGoogleTest(&argc, argv); | |
797 return RUN_ALL_TESTS(); | |
798 } | |
OLD | NEW |