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 : #ifndef NACL_TRUSTED_BUT_NOT_TCB
8 : #error This file is not meant for use in the TCB
9 : #endif
10 :
11 : /*
12 : * Small unit tests for the ARM validator
13 : *
14 : * Also see validator_large_tests.cc,
15 : * and validator_tests.h for the testing infrastructure.
16 : */
17 :
18 : #include "native_client/src/trusted/validator_arm/validator_tests.h"
19 :
20 : using nacl_val_arm_test::ProblemRecord;
21 : using nacl_val_arm_test::ProblemSpy;
22 : using nacl_val_arm_test::ValidatorTests;
23 : using nacl_val_arm_test::kDefaultBaseAddr;
24 : using nacl_val_arm_test::kBytesPerBundle;
25 : using nacl_val_arm_test::kCodeRegionSize;
26 : using nacl_val_arm_test::kDataRegionSize;
27 : using nacl_val_arm_test::kAbiReadOnlyRegisters;
28 : using nacl_val_arm_test::kAbiDataAddrRegisters;
29 : using nacl_val_arm_test::arm_inst;
30 : using nacl_arm_dec::kArm32InstSize;
31 : using nacl_arm_dec::kNop;
32 : using nacl_arm_dec::kLiteralPoolHead;
33 : using nacl_arm_dec::kFailValidation;
34 : using nacl_arm_dec::Instruction;
35 : using nacl_arm_dec::ClassDecoder;
36 :
37 : namespace {
38 :
39 : const arm_inst kSvc0 = 0xEF000000; // SVC #0
40 :
41 : // Holds instruction and message to print if there is an issue when it
42 : // is tested.
43 : struct AnnotatedInstruction {
44 : arm_inst inst;
45 : const char *about;
46 : };
47 :
48 2070 : arm_inst ChangeInstCond(Instruction inst, Instruction::Condition cond) {
49 2070 : return ValidatorTests::ChangeCond(inst.Bits(), cond);
50 : }
51 :
52 : // Tests if a list of instructions generate the same dynamic code
53 : // replacement sentinel.
54 6 : void test_if_dynamic_code_replacement_sentinels_match(
55 : const ValidatorTests* tester,
56 : const AnnotatedInstruction* insts,
57 : size_t num_insts,
58 : arm_inst expected_sentinel) {
59 6 : const Instruction expected_inst(expected_sentinel);
60 :
61 : // Try each instruction.
62 42 : for (size_t i = 0; i < num_insts; i++) {
63 36 : Instruction test_inst(insts[i].inst);
64 :
65 : // Try each possible condition (conditions shouldn't affect this virtual).
66 576 : for (Instruction::Condition cond = Instruction::EQ;
67 : cond < Instruction::UNCONDITIONAL;
68 : cond = Instruction::Next(cond)) {
69 540 : Instruction test(ChangeInstCond(test_inst, cond));
70 540 : Instruction expected(ChangeInstCond(expected_inst, cond));
71 :
72 540 : const ClassDecoder& decoder = tester->decode(test);
73 540 : Instruction sentinel(decoder.dynamic_code_replacement_sentinel(test));
74 540 : EXPECT_TRUE(expected.Equals(sentinel)) <<
75 0 : std::hex << test.Bits() << "->" <<
76 0 : std::hex << sentinel.Bits() << " != " <<
77 540 : std::hex << expected.Bits() << ": " << insts[i].about;
78 : }
79 : }
80 6 : }
81 :
82 : // Tests if a list of instructions generate the same dynamic code replacement
83 : // sentinel.
84 6 : void test_if_dynamic_code_replacement_sentinels_unchanged(
85 : const ValidatorTests* tester,
86 : const AnnotatedInstruction* insts,
87 : size_t num_insts) {
88 : // Try each instruction.
89 61 : for (size_t i = 0; i < num_insts; i++) {
90 55 : Instruction test_inst(insts[i].inst);
91 :
92 : // Try each possible condition (conditions shouldn't affect this virtual).
93 880 : for (Instruction::Condition cond = Instruction::EQ;
94 : cond < Instruction::UNCONDITIONAL;
95 : cond = Instruction::Next(cond)) {
96 825 : Instruction test(ChangeInstCond(test_inst, cond));
97 825 : const ClassDecoder& decoder = tester->decode(test);
98 825 : Instruction sentinel(decoder.dynamic_code_replacement_sentinel(test));
99 825 : EXPECT_TRUE(test.Equals(sentinel)) <<
100 0 : std::hex << test.Bits() << "->" <<
101 825 : std::hex << sentinel.Bits() << ": " << insts[i].about;
102 : }
103 : }
104 6 : }
105 :
106 : // Test that the old code can be replaced by the new code.
107 4 : void TestDynamicCodeReplacement(
108 : SfiValidator *validator,
109 : bool expected_result,
110 : const vector<arm_inst>& old_code,
111 : const vector<arm_inst>& new_code,
112 : const char *msg) {
113 4 : EXPECT_EQ(old_code.size(), new_code.size());
114 :
115 4 : size_t size = old_code.size() * kArm32InstSize / CHAR_BIT;
116 4 : CodeSegment new_segment((uint8_t *) &new_code[0], kDefaultBaseAddr, size);
117 4 : CodeSegment old_segment((uint8_t *) &old_code[0], kDefaultBaseAddr, size);
118 :
119 4 : EXPECT_EQ(expected_result,
120 : validator->ValidateSegmentPair(old_segment, new_segment, NULL)) <<
121 0 : "Code replacement expected different validation result for " << msg;
122 4 : }
123 :
124 : // Verify that there is enough room in ViolationSet to include all
125 : // elements in enum Violation.
126 5 : TEST_F(ValidatorTests, ViolationsFitInViolationSet) {
127 1 : EXPECT_LT(static_cast<size_t>(nacl_arm_dec::OTHER_VIOLATION),
128 1 : sizeof(nacl_arm_dec::ViolationSet) * CHAR_BIT);
129 1 : }
130 :
131 5 : TEST_F(ValidatorTests, NopBundle) {
132 1 : vector<arm_inst> code(_validator->InstructionsPerBundle(), kNop);
133 1 : validation_should_pass(&code[0], code.size(), kDefaultBaseAddr,
134 2 : "NOP bundle");
135 1 : }
136 :
137 : /*
138 : * Primitive tests checking various constructor properties. Any of these
139 : * failing would be a very bad sign indeed.
140 : */
141 :
142 5 : TEST_F(ValidatorTests, RecognizesDataAddressRegisters) {
143 : // Note that the logic below needs to be kept in sync with the definition
144 : // of kAbiDataAddrRegisters at the top of this file.
145 : //
146 : // This test is pretty trivial -- we can exercise the data_address_register
147 : // functionality more deeply with pattern tests below.
148 17 : for (int i = 0; i < 16; i++) {
149 16 : Register r(i);
150 16 : if (r.Equals(nacl_arm_dec::Register::Sp())) {
151 1 : EXPECT_TRUE(_validator->is_data_address_register(r))
152 0 : << "Stack pointer must be a data address register.";
153 : } else {
154 15 : EXPECT_FALSE(_validator->is_data_address_register(r))
155 0 : << "Only the stack pointer must be a data address register.";
156 : }
157 : }
158 1 : }
159 :
160 5 : TEST_F(ValidatorTests, GeneratesCorrectMasksFromSizes) {
161 1 : EXPECT_EQ(0xC0000000, _validator->data_address_mask());
162 1 : EXPECT_EQ(0xE000000F, _validator->code_address_mask());
163 :
164 : // Reinitialize the validator to test a different bundle size.
165 : SfiValidator *new_validator = new SfiValidator(32,
166 : kCodeRegionSize,
167 : kDataRegionSize,
168 : kAbiReadOnlyRegisters,
169 : kAbiDataAddrRegisters,
170 1 : _validator->CpuFeatures());
171 1 : delete _validator;
172 1 : _validator = new_validator;
173 :
174 1 : EXPECT_EQ(0xC0000000, _validator->data_address_mask())
175 0 : << "Changes in bundle size should not affect the data mask.";
176 1 : EXPECT_EQ(0xE000001F, _validator->code_address_mask())
177 0 : << "Changes in bundle size must affect the code mask.";
178 1 : }
179 :
180 : // Code validation tests
181 :
182 5 : TEST_F(ValidatorTests, DirectBranchTargetCalculation) {
183 1 : const nacl_arm_dec::Arm32DecoderState decode_state;
184 : // Try decoding PC-relative branches from interesting PCs.
185 : uint32_t start_addrs[] = { 0x00000000, 0x00010000, 0x00020000, 0x06789abc,
186 1 : 0x12345678, 0x3fffffff, 0xdeadbeef, 0xff000000, };
187 9 : for (size_t a = 0; a < NACL_ARRAY_SIZE(start_addrs); ++a) {
188 8 : uint32_t start_addr = start_addrs[a];
189 : // All PC-relative branches supported by NaCl.
190 : arm_inst insts[] = {
191 : 0xea000000, // B PC+8+0
192 : 0xeb000000, // BL PC+8+0
193 8 : };
194 24 : for (arm_inst* inst = insts;
195 : inst < insts + NACL_ARRAY_SIZE(insts);
196 : ++inst) {
197 256 : for (Instruction::Condition cond = Instruction::EQ;
198 : cond <= Instruction::AL;
199 : cond = Instruction::Next(cond)) {
200 240 : *inst = ChangeCond(*inst, cond);
201 984240 : for (int32_t imm = -2050; imm < 2050; ++imm) {
202 : // For all PC-relative branches that NaCl supports:
203 : // imm24(23:0);
204 : // imm32 = SignExtend(imm24:'00', 32);
205 : // targetAddress = Align(PC,4) + imm32;
206 : // Where:
207 : // The PC value of an instruction is its address plus 8 for an
208 : // ARM instruction. The Align(PC, 4) value of an instruction is
209 : // its PC value ANDed with 0xFFFFFFFC to force it to be
210 : // word-aligned. There is no difference between the PC and
211 : // Align(PC, 4) values for an ARM instruction.
212 984000 : *inst = (*inst & 0xff000000) | ((imm >> 2) & 0x00ffffff);
213 984000 : const uint8_t *bytes = reinterpret_cast<const uint8_t *>(inst);
214 984000 : CodeSegment segment(bytes, start_addr, sizeof(arm_inst));
215 : nacl_arm_val::DecodedInstruction inst(start_addr, segment[start_addr],
216 : decode_state.decode(
217 984000 : segment[start_addr]));
218 984000 : EXPECT_TRUE(inst.is_relative_branch());
219 984000 : EXPECT_EQ(start_addr + 8 + (imm & 0xfffffffc), inst.branch_target());
220 : }
221 : }
222 : }
223 1 : }
224 1 : }
225 :
226 : // Here are examples of every form of safe store permitted in a Native Client
227 : // program. These stores have common properties:
228 : // 1. The high nibble is 0, to allow tests to write an arbitrary predicate.
229 : // 2. They address memory only through r1 (assumed to be the first register
230 : // in the about text).
231 : // 3. They do not do anything dumb, like try to alter SP or PC.
232 : static const AnnotatedInstruction examples_of_safe_stores[] = {
233 : // Single-register stores
234 : { 0x05810000, "str r0, [r1]: simple no-displacement store" },
235 : { 0x05810123, "str r0, [r1, #0x123]: positive displacement" },
236 : { 0x05010123, "str r0, [r1, #-0x123]: negative displacement" },
237 : { 0x05A10123, "str r0, [r1, #0x123]!: positive disp + writeback" },
238 : { 0x05210123, "str r0, [r1, #-0x123]!: negative disp + writeback" },
239 : { 0x04810123, "str r0, [r1], #0x123: positive post-indexing" },
240 : { 0x04010123, "str r0, [r1], #-0x123: negative post-indexing" },
241 : { 0x06810002, "str r0, [r1], r2: positive register post-indexing" },
242 : { 0x06010002, "str r0, [r1], -r2: negative register post-indexing" },
243 :
244 : // Two-register store
245 : { 0x01C120F0, "strd r2, r3, [r1]: basic 64-bit store" },
246 : { 0x01C124F2, "strd r2, r3, [r1, #42]: positive disp 64-bit store" },
247 : { 0x014124F2, "strd r2, r3, [r1, #-42]: negative disp 64-bit store" },
248 : { 0x01E124F2, "strd r2, r3, [r1, #42]!: positive disp 64-bit store + wb" },
249 : { 0x016124F2, "strd r2, r3, [r1, #-42]!: negative disp 64-bit store + wb" },
250 : { 0x00C124F2, "strd r2, r3, [r1], #42: post-inc 64-bit store" },
251 : { 0x004124F2, "strd r2, r3, [r1], #-42: post-dec 64-bit store" },
252 :
253 : // Store-exclusive
254 : { 0x01810F92, "strex r0, r2, [r1]: store exclusive" },
255 :
256 : // Store-multiple
257 : // Note: It is illegal to store r9 (NaCl constraint), so it must
258 : // be ommitted from the register sets.
259 : { 0x0881FDFF, "stm r1, { r0-r8, r10-r15 }: store multiple, no writeback" },
260 : // Note: can't store registers whose number is less than Rt when there is
261 : // writeback. E.g. stm r1! { r0-r15 } is unknown.
262 : { 0x08A1FDFE, "stm r1!, { r1-r8, r10-r15 }: store multiple, writeback" },
263 : { 0x08A1FDFC, "stm r1!, { r2-r8, r10-r15 }: store multiple, writeback" },
264 :
265 : // Stores from the floating point / vector register file
266 : // These all compile to STC instructions.
267 : { 0x0D810B00, "vstr d0, [r1]: direct vector store" },
268 : { 0x0D810B99, "vstr d0, [r1, #0x99]: positive displacement vector store" },
269 : { 0x0D010B99, "vstr d0, [r1, #-0x99]: negative displacement vector store" },
270 : { 0x0C810B10, "vstmia r1, { d0-d7 }: no writeback" },
271 : { 0x0CA10B10, "vstmia r1!, { d0-d7 }: writeback" },
272 : };
273 :
274 : // Note: We assume that r3 is used for the operand, if it isn't the same
275 : // as the destination (i.e. r1).
276 : static const AnnotatedInstruction examples_of_safe_masks[] = {
277 : { 0x03C11103, "bic r1, r1, #0xC0000000: simple in-place mask (form 1)" },
278 : { 0x03C114C0, "bic r1, r1, #0xC0000000: simple in-place mask (form 2)" },
279 : { 0x03C314C0, "bic r1, r3, #0xC0000000: mask with register move" },
280 : { 0x03C114FF, "bic r1, r1, #0xFF000000: overzealous but correct mask" },
281 : };
282 :
283 5 : TEST_F(ValidatorTests, SafeMaskedStores) {
284 : // Produces many examples of masked stores using the safe store table (above)
285 : // and the list of possible masking instructions (below).
286 : //
287 : // Each mask instruction must leave a valid (data) address in r1.
288 16 : for (unsigned p = 0; p < 15; p++) {
289 : // Conditionally executed instructions have a top nibble of 0..14.
290 : // 15 is an escape sequence used to fit in additional encodings.
291 15 : arm_inst predicate = p << 28;
292 :
293 75 : for (unsigned m = 0; m < NACL_ARRAY_SIZE(examples_of_safe_masks); m++) {
294 1560 : for (unsigned s = 0; s < NACL_ARRAY_SIZE(examples_of_safe_stores); s++) {
295 1500 : ostringstream message;
296 1500 : message << examples_of_safe_masks[m].about
297 1500 : << ", "
298 3000 : << examples_of_safe_stores[s].about
299 1500 : << " (predicate #" << p << ")";
300 : arm_inst program[] = {
301 : examples_of_safe_masks[m].inst | predicate,
302 : examples_of_safe_stores[s].inst | predicate,
303 1500 : };
304 : validation_should_pass2(program,
305 : 2,
306 : kDefaultBaseAddr,
307 1500 : message.str());
308 1500 : }
309 : }
310 : }
311 1 : }
312 :
313 : static const AnnotatedInstruction examples_of_safe_unconditional_stores[] = {
314 : // Vector stores
315 : { 0xF481A5AF, "vst2.16 {d10[2],d12[2]}, [r1]: simple vector store" },
316 : { 0xF401A64F, "vst1.16 {d10-d12}, [r1]: larger vector store" },
317 : { 0xF4010711, "vst1.8 {d0}, [r1, :64], r1: register post-increment" },
318 : };
319 :
320 5 : TEST_F(ValidatorTests, SafeUnconditionalMaskedStores) {
321 : // Produces many examples of unconditional masked stores using the safe
322 : // unconditional store table (above) and the list of possible masking
323 : // instructions (below).
324 : //
325 : // Each mask instruction must leave a valid (data) address in r1.
326 :
327 5 : for (unsigned m = 0; m < NACL_ARRAY_SIZE(examples_of_safe_masks); m++) {
328 16 : for (unsigned s = 0;
329 : s < NACL_ARRAY_SIZE(examples_of_safe_unconditional_stores);
330 : s++) {
331 12 : ostringstream message;
332 12 : message << examples_of_safe_masks[m].about
333 12 : << ", "
334 24 : << examples_of_safe_unconditional_stores[s].about;
335 : arm_inst program[] = {
336 : ValidatorTests::ChangeCond(examples_of_safe_masks[m].inst,
337 12 : Instruction::AL),
338 : examples_of_safe_unconditional_stores[s].inst,
339 12 : };
340 : validation_should_pass2(program,
341 : 2,
342 : kDefaultBaseAddr,
343 12 : message.str());
344 12 : }
345 : }
346 1 : }
347 :
348 5 : TEST_F(ValidatorTests, SafeConditionalStores) {
349 : // Produces many examples of conditional stores using the safe store table
350 : // (above) and the list of possible conditional guards (below).
351 : //
352 : // Each conditional guard must set the Z flag iff r1 contains a valid address.
353 : static const AnnotatedInstruction guards[] = {
354 : { 0x03110103, "tst r1, #0xC0000000: precise guard, GCC encoding" },
355 : { 0x031104C0, "tst r1, #0xC0000000: precise guard, alternative encoding" },
356 : { 0x031101C3, "tst r1, #0xF0000000: overzealous (but correct) guard" },
357 : };
358 :
359 : // Reinitialize the validator to test both allowing and disallowing
360 : // conditional memory accesses.
361 3 : for (int allow_cond = 0; allow_cond <= 1; ++allow_cond) {
362 : NaClCPUFeaturesArm cpu_features;
363 2 : NaClCopyCPUFeaturesArm(&cpu_features, _validator->CpuFeatures());
364 : NaClSetCPUFeatureArm(&cpu_features, NaClCPUFeatureArm_CanUseTstMem,
365 2 : allow_cond);
366 2 : delete _validator;
367 : _validator = new SfiValidator(kBytesPerBundle,
368 : kCodeRegionSize,
369 : kDataRegionSize,
370 : kAbiReadOnlyRegisters,
371 : kAbiDataAddrRegisters,
372 2 : &cpu_features);
373 :
374 : // Currently we only support *unconditional* conditional stores.
375 : // Meaning the guard is unconditional and the store is if-equal.
376 : // e.g.: tst.al rbase, #mask
377 : // str.eq rval, [rbase]
378 32 : for (Instruction::Condition guard_cond = Instruction::EQ;
379 : guard_cond <= Instruction::AL;
380 : guard_cond = Instruction::Next(guard_cond)) {
381 480 : for (Instruction::Condition store_cond = Instruction::EQ;
382 : store_cond <= Instruction::AL;
383 : store_cond = Instruction::Next(store_cond)) {
384 1800 : for (size_t guard = 0;
385 : guard < NACL_ARRAY_SIZE(guards);
386 : guard++) {
387 1350 : arm_inst guard_inst = guards[guard].inst;
388 4050 : for (int use_same_base = 0; use_same_base <= 1; ++use_same_base) {
389 : // Alternate between using the same rbase for tst and str.
390 : // TODO(jfb) This is hackish, and should be better handled
391 : // throughout these tests. AnnotatedInstruction is
392 : // probably the right place for this.
393 2700 : unsigned base = use_same_base ? 1 : 2; // Rn is now r1 or r2.
394 2700 : guard_inst &= 0xFFF0FFFF; // Rn is at (19:16).
395 2700 : guard_inst |= base << 16;
396 70200 : for (size_t store = 0;
397 : store < NACL_ARRAY_SIZE(examples_of_safe_stores);
398 : store++) {
399 67500 : arm_inst store_inst = examples_of_safe_stores[store].inst;
400 67500 : ostringstream message;
401 67500 : message << guards[guard].about << " with condition "
402 135000 : << Instruction::ToString(guard_cond)
403 : << (use_same_base ?
404 : " and same base registers," :
405 135000 : " and different base registers,")
406 67500 : << " followed by "
407 135000 : << examples_of_safe_stores[store].about
408 67500 : << " with condition "
409 135000 : << Instruction::ToString(store_cond);
410 : arm_inst program[] = {
411 67500 : ValidatorTests::ChangeCond(guard_inst, guard_cond),
412 67500 : ValidatorTests::ChangeCond(store_inst, store_cond),
413 135000 : };
414 67500 : if (allow_cond &&
415 : use_same_base &&
416 : (guard_cond == Instruction::AL) &&
417 : (store_cond == Instruction::EQ)) {
418 : validation_should_pass2(program,
419 : 2,
420 : kDefaultBaseAddr,
421 75 : message.str());
422 : } else {
423 : validation_should_fail(program,
424 : 2,
425 : kDefaultBaseAddr,
426 67425 : message.str());
427 : }
428 67500 : }
429 : }
430 : }
431 : }
432 : }
433 : }
434 1 : }
435 :
436 : static const AnnotatedInstruction examples_of_invalid_masks[] = {
437 : { 0x01A01003, "mov r1, r3: not even a mask" },
438 : { 0x03C31000, "bic r1, r3, #0: doesn't mask anything" },
439 : { 0x03C31102, "bic r1, r3, #0x80000000: doesn't mask enough bits" },
440 : { 0x03C311C1, "bic r1, r3, #0x70000000: masks the wrong bits" },
441 : };
442 :
443 5 : TEST_F(ValidatorTests, InvalidMasksOnSafeStores) {
444 16 : for (unsigned p = 0; p < 15; p++) {
445 : // Conditionally executed instructions have a top nibble of 0..14.
446 : // 15 is an escape sequence used to fit in additional encodings.
447 15 : arm_inst predicate = p << 28;
448 :
449 75 : for (unsigned m = 0; m < NACL_ARRAY_SIZE(examples_of_invalid_masks); m++) {
450 1560 : for (unsigned s = 0; s < NACL_ARRAY_SIZE(examples_of_safe_stores); s++) {
451 1500 : ostringstream message;
452 1500 : message << examples_of_invalid_masks[m].about
453 1500 : << ", "
454 3000 : << examples_of_safe_stores[s].about
455 1500 : << " (predicate #" << p << ")";
456 : arm_inst program[] = {
457 : examples_of_invalid_masks[m].inst | predicate,
458 : examples_of_safe_stores[s].inst | predicate,
459 1500 : };
460 :
461 1500 : ProblemSpy spy;
462 : validation_should_fail(program,
463 : NACL_ARRAY_SIZE(program),
464 : kDefaultBaseAddr,
465 : message.str(),
466 1500 : &spy);
467 1500 : vector<ProblemRecord> problems = spy.get_problems();
468 :
469 : // EXPECT/continue rather than ASSERT so that we run the other cases.
470 1500 : EXPECT_EQ(1U, problems.size());
471 1500 : if (problems.size() != 1) continue;
472 :
473 1500 : ProblemRecord first = problems[0];
474 1500 : EXPECT_EQ(kDefaultBaseAddr + 4, first.vaddr())
475 0 : << "Problem report must point to the store: "
476 0 : << message.str();
477 1500 : EXPECT_FALSE(nacl_arm_dec::IsSafetyViolation(first.violation()))
478 0 : << "Store should not be unsafe even though the mask is bogys:"
479 0 : << message.str();
480 1500 : EXPECT_EQ(nacl_arm_dec::LOADSTORE_VIOLATION, first.violation())
481 0 : << message.str();
482 1500 : }
483 : }
484 : }
485 1 : }
486 :
487 5 : TEST_F(ValidatorTests, InvalidGuardsOnSafeStores) {
488 : static const AnnotatedInstruction invalid_guards[] = {
489 : { 0x03110100, "tst r1, #0: always sets Z" },
490 : { 0x03110102, "tst r1, #0x80000000: doesn't test enough bits" },
491 : { 0x031101C1, "tst r1, #0x70000000: doesn't test the right bits" },
492 : { 0x01A01003, "mov r1, r3: not even a test" },
493 : { 0x03310103, "teq r1, #0xC0000000: does the inverse of what we want" },
494 : { 0x03510103, "cmp r1, #0xC0000000: does the inverse of what we want" },
495 : };
496 :
497 : // We don't currently support conditional versions of the conditional guard.
498 : //
499 : // TODO(cbiffle): verify this in the test
500 : static const arm_inst guard_predicate = 0xE0000000; // unconditional
501 : static const arm_inst store_predicate = 0x00000000; // if-equal
502 :
503 7 : for (unsigned m = 0; m < NACL_ARRAY_SIZE(invalid_guards); m++) {
504 156 : for (unsigned s = 0; s < NACL_ARRAY_SIZE(examples_of_safe_stores); s++) {
505 150 : ostringstream message;
506 150 : message << invalid_guards[m].about
507 150 : << ", "
508 300 : << examples_of_safe_stores[s].about;
509 : arm_inst program[] = {
510 : invalid_guards[m].inst | guard_predicate,
511 : examples_of_safe_stores[s].inst | store_predicate,
512 150 : };
513 :
514 150 : ProblemSpy spy;
515 : validation_should_fail(program,
516 : NACL_ARRAY_SIZE(program),
517 : kDefaultBaseAddr,
518 : message.str(),
519 150 : &spy);
520 150 : vector<ProblemRecord> problems = spy.get_problems();
521 :
522 : // EXPECT/continue rather than ASSERT so that we run the other cases.
523 150 : EXPECT_EQ(1U, problems.size());
524 150 : if (problems.size() != 1) continue;
525 :
526 150 : ProblemRecord first = problems[0];
527 150 : EXPECT_EQ(kDefaultBaseAddr + 4, first.vaddr())
528 0 : << "Problem report must point to the store: "
529 0 : << message.str();
530 150 : EXPECT_FALSE(nacl_arm_dec::IsSafetyViolation(first.violation()))
531 0 : << "Store should not be unsafe even though guard is bogus:"
532 150 : << message;
533 150 : EXPECT_EQ(nacl_arm_dec::LOADSTORE_VIOLATION, first.violation())
534 0 : << message;
535 150 : }
536 : }
537 1 : }
538 :
539 5 : TEST_F(ValidatorTests, ValidMasksOnUnsafeStores) {
540 : static const AnnotatedInstruction invalid_stores[] = {
541 : { 0x07810002, "str r0, [r1, r2]: register-plus-register addressing" },
542 : { 0x07010002, "str r0, [r1, -r2]: register-minus-register addressing" },
543 : { 0x07810182, "str r0, [r1, r2, LSL #3]: complicated addressing 1" },
544 : { 0x07018482, "str r0, [r1, -r2, ASR #16]: complicated addressing 2" },
545 : };
546 :
547 16 : for (unsigned p = 0; p < 15; p++) {
548 : // Conditionally executed instructions have a top nibble of 0..14.
549 : // 15 is an escape sequence used to fit in additional encodings.
550 15 : arm_inst predicate = p << 28;
551 :
552 75 : for (unsigned m = 0; m < NACL_ARRAY_SIZE(examples_of_safe_masks); m++) {
553 300 : for (unsigned s = 0; s < NACL_ARRAY_SIZE(invalid_stores); s++) {
554 240 : ostringstream message;
555 240 : message << examples_of_safe_masks[m].about
556 240 : << ", "
557 480 : << invalid_stores[s].about
558 240 : << " (predicate #" << p << ")";
559 : arm_inst program[] = {
560 : examples_of_safe_masks[m].inst | predicate,
561 : invalid_stores[s].inst | predicate,
562 240 : };
563 :
564 240 : ProblemSpy spy;
565 : validation_should_fail(program,
566 : NACL_ARRAY_SIZE(program),
567 : kDefaultBaseAddr,
568 : message.str(),
569 240 : &spy);
570 240 : vector<ProblemRecord> problems = spy.get_problems();
571 :
572 : // EXPECT/continue rather than ASSERT so that we run the other cases.
573 240 : EXPECT_EQ(1U, problems.size());
574 240 : if (problems.size() != 1) continue;
575 :
576 240 : ProblemRecord first = problems[0];
577 240 : EXPECT_EQ(kDefaultBaseAddr + 4, first.vaddr())
578 0 : << "Problem report must point to the store: "
579 0 : << message.str();
580 240 : EXPECT_TRUE(nacl_arm_dec::IsSafetyViolation(first.violation()));
581 240 : }
582 : }
583 : }
584 1 : }
585 :
586 5 : TEST_F(ValidatorTests, ScaryUndefinedInstructions) {
587 : // These instructions are undefined today (ARMv7-A) but may become defined
588 : // tomorrow. We ban them since we can't reason about their side effects.
589 : static const AnnotatedInstruction undefined_insts[] = {
590 : { 0xE05DEA9D, "An undefined instruction in the multiply space" },
591 : };
592 2 : for (unsigned i = 0; i < NACL_ARRAY_SIZE(undefined_insts); i++) {
593 1 : arm_inst program[] = { undefined_insts[i].inst };
594 :
595 1 : ProblemSpy spy;
596 : validation_should_fail(program,
597 : NACL_ARRAY_SIZE(program),
598 : kDefaultBaseAddr,
599 : undefined_insts[i].about,
600 1 : &spy);
601 1 : vector<ProblemRecord> problems = spy.get_problems();
602 :
603 : // EXPECT/continue rather than ASSERT so that we run the other cases.
604 1 : EXPECT_EQ(1U, problems.size());
605 1 : if (problems.size() != 1) continue;
606 :
607 1 : ProblemRecord first = problems[0];
608 1 : EXPECT_EQ(kDefaultBaseAddr, first.vaddr())
609 0 : << "Problem report must point to the only instruction: "
610 1 : << undefined_insts[i].about;
611 1 : EXPECT_TRUE(nacl_arm_dec::IsSafetyViolation(first.violation()))
612 0 : << "Instruction must be flagged by the decoder as unsafe:"
613 1 : << undefined_insts[i].about;
614 1 : EXPECT_EQ(nacl_arm_dec::UNDEFINED_VIOLATION, first.violation())
615 0 : << "Instruction must be flagged as UNDEFINED:"
616 1 : << undefined_insts[i].about;
617 1 : }
618 1 : }
619 :
620 5 : TEST_F(ValidatorTests, PcRelativeFirstInst) {
621 : // Note: This tests the fix for issue 2771.
622 : static const arm_inst pcrel_boundary_tests[] = {
623 : 0xe59f0000, // ldr r0, [pc, #0]
624 : kNop,
625 : kNop,
626 : kNop,
627 : };
628 : validation_should_pass(pcrel_boundary_tests,
629 : NACL_ARRAY_SIZE(pcrel_boundary_tests),
630 : kDefaultBaseAddr,
631 1 : "pc relative first instruction in first bundle");
632 1 : }
633 :
634 5 : TEST_F(ValidatorTests, PcRelativeFirst2ndBundle) {
635 : // Note: This tests the fix for issue 2771.
636 : static const arm_inst pcrel_boundary_tests[] = {
637 : kNop,
638 : kNop,
639 : kNop,
640 : kNop,
641 : 0xe59f0000, // ldr r0, [pc, #0]
642 : };
643 : validation_should_pass(pcrel_boundary_tests,
644 : NACL_ARRAY_SIZE(pcrel_boundary_tests),
645 : kDefaultBaseAddr,
646 1 : "pc relative first instruction in 2nd bundle");
647 1 : }
648 :
649 5 : TEST_F(ValidatorTests, SafeConditionalBicLdrTest) {
650 : // Test if we fixed bug with conditional Bic Loads (issue 2769).
651 : static const arm_inst bic_ldr_safe_test[] = {
652 : 0x03c22103, // biceq r2, r2, #-1073741824 ; 0xc0000000
653 : 0x01920f9f, // ldrexeq r0, [r2]
654 : };
655 : validation_should_pass(bic_ldr_safe_test,
656 : NACL_ARRAY_SIZE(bic_ldr_safe_test),
657 : kDefaultBaseAddr,
658 1 : "Safe conditional bic ldr test");
659 1 : }
660 :
661 5 : TEST_F(ValidatorTests, ConditionalBicsLdrTest) {
662 : // Test if we fail because Bic updates the flags register, making
663 : // the conditional Bic load incorrect (issue 2769).
664 : static const arm_inst bics_ldr_unsafe_test[] = {
665 : 0x03d22103, // bicseq r2, r2, #-1073741824 ; 0xc0000000
666 : 0x01920f9f, // ldrexeq r0, [r2]
667 : };
668 :
669 1 : ProblemSpy spy;
670 : validation_should_fail(bics_ldr_unsafe_test,
671 : NACL_ARRAY_SIZE(bics_ldr_unsafe_test),
672 : kDefaultBaseAddr,
673 : "Conditional bics ldr test",
674 1 : &spy);
675 1 : vector<ProblemRecord> problems = spy.get_problems();
676 :
677 1 : EXPECT_EQ(1U, problems.size());
678 2 : if (problems.size() == 0) return;
679 :
680 1 : ProblemRecord problem = problems[0];
681 1 : EXPECT_EQ(kDefaultBaseAddr + 4, problem.vaddr())
682 0 : << "Problem report should point to the ldr instruction.";
683 1 : EXPECT_FALSE(nacl_arm_dec::IsSafetyViolation(problem.violation()));
684 1 : EXPECT_EQ(nacl_arm_dec::LOADSTORE_VIOLATION, problem.violation());
685 : }
686 :
687 5 : TEST_F(ValidatorTests, DifferentConditionsBicLdrTest) {
688 : // Test if we fail because the Bic and Ldr instructions have
689 : // different conditional flags.
690 : static const arm_inst bic_ldr_diff_conds[] = {
691 : 0x03c22103, // biceq r2, r2, #-1073741824 ; 0xc0000000
692 : 0xc1920f9f, // ldrexgt r0, [r2]
693 : };
694 :
695 1 : ProblemSpy spy;
696 : validation_should_fail(bic_ldr_diff_conds,
697 : NACL_ARRAY_SIZE(bic_ldr_diff_conds),
698 : kDefaultBaseAddr,
699 : "Different conditions bic ldr test",
700 1 : &spy);
701 1 : vector<ProblemRecord> problems = spy.get_problems();
702 :
703 1 : EXPECT_EQ(1U, problems.size());
704 2 : if (problems.size() == 0) return;
705 :
706 1 : ProblemRecord problem = problems[0];
707 1 : EXPECT_EQ(kDefaultBaseAddr + 4, problem.vaddr())
708 0 : << "Problem report should point to the ldr instruction.";
709 1 : EXPECT_FALSE(nacl_arm_dec::IsSafetyViolation(problem.violation()));
710 1 : EXPECT_EQ(nacl_arm_dec::LOADSTORE_VIOLATION, problem.violation());
711 : }
712 :
713 5 : TEST_F(ValidatorTests, BfcLdrInst) {
714 : static const arm_inst bfc_inst[] = {
715 : 0xe7df2f1f, // bfc r2, #30, #2
716 : 0xe1920f9f, // ldrex r0, [r2]
717 : };
718 : validation_should_fail(bfc_inst,
719 : NACL_ARRAY_SIZE(bfc_inst),
720 : kDefaultBaseAddr,
721 : "Bfc Ldr instruction mask has a mask that's "
722 : "technically safe, but we disallow it out of "
723 1 : "paranoia");
724 1 : }
725 :
726 5 : TEST_F(ValidatorTests, BfcLdrInstMaskTooBigTest) {
727 : static const arm_inst bfc_inst[] = {
728 : 0xe7df2e9f, // bfc r2, #29, #3
729 : 0xe1920f9f, // ldrex r0, [r2]
730 : };
731 : validation_should_fail(bfc_inst,
732 : NACL_ARRAY_SIZE(bfc_inst),
733 : kDefaultBaseAddr,
734 : "Bfc Ldr instruction mask has a mask that's "
735 : "technically safe (even too wide!), but we "
736 1 : "disallow it out of paranoia");
737 1 : }
738 :
739 5 : TEST_F(ValidatorTests, BfcLdrInstMaskWrongPlaceTest) {
740 : static const arm_inst bfc_inst[] = {
741 : 0xe7da2c9f, // bfc r2, #25, #2
742 : 0xe1920f9f, // ldrex r0, [r2]
743 : };
744 : validation_should_fail(bfc_inst,
745 : NACL_ARRAY_SIZE(bfc_inst),
746 : kDefaultBaseAddr,
747 : "Bfc Ldr instruction mask has a mask that's "
748 : "not safe, and anyways we disallow it out of "
749 1 : "paranoia");
750 1 : }
751 :
752 : // Test effects of virtual dynamic_code_replacement_sentinel on the movw
753 : // instruction.
754 5 : TEST_F(ValidatorTests, DynamicCodeReplacementSentinelMovw) {
755 : // Test cases where the sentinel changes for movw.
756 : const AnnotatedInstruction inst[] = {
757 : {0xe30a3aaa, "movw r3, #43690 ; 0xaaaa"},
758 : {0xe3053555, "movw r3, #21845 ; 0x5555"},
759 1 : };
760 :
761 : // Test cases where the sentinel doesn't change for movw.
762 : test_if_dynamic_code_replacement_sentinels_match(
763 : static_cast<const ValidatorTests*>(this),
764 1 : inst, NACL_ARRAY_SIZE(inst), 0xe3003000);
765 : const AnnotatedInstruction unchanged[] = {
766 : // If already the sentinel, nothing changes.
767 : {0xe3003000, "movw r3, #0 ; 0x0000"},
768 : // Note: These instructions may not validate for other reasons,
769 : // but we are only testing the virtual
770 : // dynamic_code_replacement_sentinel, and that it doesn't
771 : // apply changes when the register is in {r9, sp, lr, pc}.
772 : {0xe3059555, "movw r9, #21845 ; 0x5555"},
773 : {0xe305d555, "movw sp, #21845 ; 0x5555"},
774 : {0xe305e555, "movw lr, #21845 ; 0x5555"},
775 : {0xe305f555, "movw pc, #21845 ; 0x5555"},
776 1 : };
777 : test_if_dynamic_code_replacement_sentinels_unchanged(
778 : static_cast<const ValidatorTests*>(this),
779 1 : unchanged, NACL_ARRAY_SIZE(unchanged));
780 1 : }
781 :
782 : // Test effects of virtual dynamic_code_replacement_sentinel on the movt
783 : // instruction.
784 5 : TEST_F(ValidatorTests, DynamicCodeReplacementSentinelMovt) {
785 : // Test cases where the sentinel changes for movt.
786 : const AnnotatedInstruction inst[] = {
787 : {0xe34a5aaa, "movt r5, #43690 ; 0xaaaa"},
788 : {0xe3455555, "movt r5, #21845 ; 0x5555"},
789 1 : };
790 : test_if_dynamic_code_replacement_sentinels_match(
791 : static_cast<const ValidatorTests*>(this),
792 1 : inst, NACL_ARRAY_SIZE(inst), 0xe3405000);
793 :
794 : // Test cases where the sentinel doesn't change for movt.
795 : const AnnotatedInstruction unchanged[] = {
796 : // If already the sentinel, nothing changes.
797 : {0xe3405000, "movt r5, #0 ; 0x0000"},
798 : // Note: These instructions may not validate for other reasons,
799 : // but we are only testing the virtual
800 : // dynamic_code_replacement_sentinel, and that it doesn't
801 : // apply changes when the register is in {r9, sp, lr, pc}.
802 : {0xe3459555, "movt r9, #21845 ; 0x5555"},
803 : {0xe345d555, "movt sp, #21845 ; 0x5555"},
804 : {0xe345e555, "movt lr, #21845 ; 0x5555"},
805 : {0xe345f555, "movt pc, #21845 ; 0x5555"},
806 1 : };
807 : test_if_dynamic_code_replacement_sentinels_unchanged(
808 : static_cast<const ValidatorTests*>(this),
809 1 : unchanged, NACL_ARRAY_SIZE(unchanged));
810 1 : }
811 :
812 : // Test effects of virtual dynamic_code_replacement_sentinel on the orr
813 : // instruction.
814 5 : TEST_F(ValidatorTests, DynamicCodeReplacementSentinelOrr) {
815 : // Test cases where the sentinel changes for orr.
816 : const AnnotatedInstruction orr[] = {
817 : {0xe38454aa, "orr r5, r4, #-1442840576 ; 0xaa000000"},
818 : {0xe38458aa, "orr r5, r4, #11141120 ; 0xaa0000"},
819 : {0xe3845caa, "orr r5, r4, #43520 ; 0xaa00"},
820 : {0xe38450aa, "orr r5, r4, #170 ; 0xaa"},
821 : {0xe3845455, "orr r5, r4, #1426063360 ; 0x55000000"},
822 : {0xe3845855, "orr r5, r4, #5570560 ; 0x550000"},
823 : {0xe3845c55, "orr r5, r4, #21760 ; 0x5500"},
824 : {0xe3845055, "orr r5, r4, #85 ; 0x55"},
825 1 : };
826 : test_if_dynamic_code_replacement_sentinels_match(
827 : static_cast<const ValidatorTests*>(this),
828 1 : orr, NACL_ARRAY_SIZE(orr), 0xe3845000);
829 : const AnnotatedInstruction orrs[] = {
830 : {0xe39454aa, "orrs r5, r4, #-1442840576 ; 0xaa000000"},
831 : {0xe39458aa, "orrs r5, r4, #11141120 ; 0xaa0000"},
832 : {0xe3945caa, "orrs r5, r4, #43520 ; 0xaa00"},
833 : {0xe39450aa, "orrs r5, r4, #170 ; 0xaa"},
834 : {0xe3945455, "orrs r5, r4, #1426063360 ; 0x55000000"},
835 : {0xe3945855, "orrs r5, r4, #5570560 ; 0x550000"},
836 : {0xe3945c55, "orrs r5, r4, #21760 ; 0x5500"},
837 : {0xe3945055, "orrs r5, r4, #85 ; 0x55"},
838 1 : };
839 : test_if_dynamic_code_replacement_sentinels_match(
840 : static_cast<const ValidatorTests*>(this),
841 1 : orrs, NACL_ARRAY_SIZE(orrs), 0xe3945000);
842 :
843 : // Test cases where the sentinel doesn't change for orr.
844 : const AnnotatedInstruction unchanged[] = {
845 : // Note: These instructions may not validate for other reasons,
846 : // but we are only testing the virtual
847 : // dynamic_code_replacement_sentinel, and that it doesn't
848 : // apply changes when the register is in {r9, sp, lr, pc}.
849 : {0xe3849055, "orr r9, r4, #85 ; 0x55"},
850 : {0xe384d055, "orr sp, r4, #85 ; 0x55"},
851 : {0xe384e055, "orr lr, r4, #85 ; 0x55"},
852 : {0xe384f055, "orr pc, r4, #85 ; 0x55"},
853 : {0xe3949055, "orrs r9, r4, #85 ; 0x55"},
854 : {0xe394d055, "orrs sp, r4, #85 ; 0x55"},
855 : {0xe394e055, "orrs lr, r4, #85 ; 0x55"},
856 : {0xe394f055, "orrs pc, r4, #85 ; 0x55"},
857 1 : };
858 : test_if_dynamic_code_replacement_sentinels_unchanged(
859 : static_cast<const ValidatorTests*>(this),
860 1 : unchanged, NACL_ARRAY_SIZE(unchanged));
861 1 : }
862 :
863 : // Test effects of virtual dynamic_code_replacement_sentinel on the mvn
864 : // instruction.
865 5 : TEST_F(ValidatorTests, DynamicCodeReplacementSentinelMvn) {
866 : // Test cases where the sentinel changes for mvn.
867 : const AnnotatedInstruction mvn[] = {
868 : {0xe3e064aa, "mvn r6, #-1442840576 ; 0xaa000000"},
869 : {0xe3e068aa, "mvn r6, #11141120 ; 0xaa0000"},
870 : {0xe3e06caa, "mvn r6, #43520 ; 0xaa00"},
871 : {0xe3e060aa, "mvn r6, #170 ; 0xaa"},
872 : {0xe3e06455, "mvn r6, #1426063360 ; 0x55000000"},
873 : {0xe3e06855, "mvn r6, #5570560 ; 0x550000"},
874 : {0xe3e06c55, "mvn r6, #21760 ; 0x5500"},
875 : {0xe3e06055, "mvn r6, #85 ; 0x55"},
876 1 : };
877 : test_if_dynamic_code_replacement_sentinels_match(
878 : static_cast<const ValidatorTests*>(this),
879 1 : mvn, NACL_ARRAY_SIZE(mvn), 0xe3e06000);
880 : const AnnotatedInstruction mvns[] = {
881 : {0xe3f064aa, "mvns r6, #-1442840576 ; 0xaa000000"},
882 : {0xe3f068aa, "mvns r6, #11141120 ; 0xaa0000"},
883 : {0xe3f06caa, "mvns r6, #43520 ; 0xaa00"},
884 : {0xe3f060aa, "mvns r6, #170 ; 0xaa"},
885 : {0xe3f06455, "mvns r6, #1426063360 ; 0x55000000"},
886 : {0xe3f06855, "mvns r6, #5570560 ; 0x550000"},
887 : {0xe3f06c55, "mvns r6, #21760 ; 0x5500"},
888 : {0xe3f06055, "mvns r6, #85 ; 0x55"},
889 1 : };
890 : test_if_dynamic_code_replacement_sentinels_match(
891 : static_cast<const ValidatorTests*>(this),
892 1 : mvns, NACL_ARRAY_SIZE(mvns), 0xe3f06000);
893 :
894 : // Test cases where the sentinel doesn't change for orr.
895 : const AnnotatedInstruction unchanged[] = {
896 : // Note: These instructions may not validate for other reasons,
897 : // but we are only testing the virtual
898 : // dynamic_code_replacement_sentinel, and that it doesn't
899 : // apply changes when the register is in {r9, sp, lr, pc}.
900 : {0xe3e09055, "mvn r9, #85 ; 0x55"},
901 : {0xe3e0d055, "mvn sp, #85 ; 0x55"},
902 : {0xe3e0e055, "mvn lr, #85 ; 0x55"},
903 : {0xe3e0f055, "mvn pc, #85 ; 0x55"},
904 : {0xe3f09055, "mvns r9, #85 ; 0x55"},
905 : {0xe3f0d055, "mvns sp, #85 ; 0x55"},
906 : {0xe3f0e055, "mvns lr, #85 ; 0x55"},
907 : {0xe3f0f055, "mvns pc, #85 ; 0x55"},
908 1 : };
909 : test_if_dynamic_code_replacement_sentinels_unchanged(
910 : static_cast<const ValidatorTests*>(this),
911 1 : unchanged, NACL_ARRAY_SIZE(unchanged));
912 1 : }
913 :
914 : // Test other instructions for which dynamic code replacement can't be applied.
915 5 : TEST_F(ValidatorTests, DynamicCodeReplacementSentinelOther) {
916 : test_if_dynamic_code_replacement_sentinels_unchanged(
917 : static_cast<const ValidatorTests*>(this),
918 1 : examples_of_safe_stores, NACL_ARRAY_SIZE(examples_of_safe_stores));
919 : test_if_dynamic_code_replacement_sentinels_unchanged(
920 : static_cast<const ValidatorTests*>(this),
921 1 : examples_of_safe_masks, NACL_ARRAY_SIZE(examples_of_safe_masks));
922 1 : }
923 :
924 5 : TEST_F(ValidatorTests, DynamicCodeReplacementLiteralPool) {
925 : // Start with an evil-looking value, and replace with another evil-looking
926 : // value. It should work because these are all data in two consecutive
927 : // literal pools, not actual instructions.
928 1 : vector<arm_inst>::size_type bundle_size(_validator->InstructionsPerBundle());
929 1 : vector<arm_inst>::size_type size(bundle_size * 2);
930 1 : vector<arm_inst> old_code(size, kSvc0);
931 1 : vector<arm_inst> new_code(size, kFailValidation);
932 1 : old_code[0] = new_code[0] =
933 1 : old_code[bundle_size] = new_code[bundle_size] =
934 1 : kLiteralPoolHead;
935 : TestDynamicCodeReplacement(
936 : _validator, true, old_code, new_code,
937 1 : "literal pool data change");
938 :
939 : // Change the new code so that its first bundle is still a literal
940 : // pool but its second isn't. This should now fail validation because
941 : // the data is now executable code.
942 1 : new_code[bundle_size] = kNop;
943 : TestDynamicCodeReplacement(
944 : _validator, false, old_code, new_code,
945 1 : "literal pool becoming non-literal pool");
946 :
947 : // Change the old code so that its second bundle also isn't a literal
948 : // pool. This should also fail, not because the code is dangerous
949 : // (which it is, but that's checked separately), but because the old
950 : // instructions can't be substituted for the new.
951 1 : old_code[bundle_size] = kNop;
952 : TestDynamicCodeReplacement(
953 : _validator, false, old_code, new_code,
954 1 : "literal pool followed by non-literal pool with invalid replacement");
955 :
956 : // Change the new code's second bundle to a literal pool, which it
957 : // wasn't in the old. This should also fail because we don't allow the
958 : // user to dynamically create literal pools where none existed before.
959 1 : new_code[bundle_size] = kLiteralPoolHead;
960 : TestDynamicCodeReplacement(
961 : _validator, false, old_code, new_code,
962 1 : "non-literal pool becoming literal pool");
963 1 : }
964 :
965 : struct AlwaysDominatesTestInfo {
966 : arm_inst inst[2];
967 : const char* name[2];
968 : bool first_inst_can_set_flags;
969 : };
970 5 : TEST_F(ValidatorTests, AlwaysDominatesTest) {
971 : // Test always_dominates, with all conditional combinations of:
972 : AlwaysDominatesTestInfo test[] = {
973 : { {
974 : // BIC (potentially setting flags) followed by a branch.
975 : 0xe3cee2fe, // bic[s]CC lr, lr, #-536870897 ; 0xe000000f
976 : 0xe12fff1e, // bxCC lr
977 : }, { "bic", "bx" }, true },
978 1 : };
979 :
980 2 : for (AlwaysDominatesTestInfo* t = &test[0];
981 : t != &test[NACL_ARRAY_SIZE(test)];
982 : ++t) {
983 3 : for (int s = 0; s < (t->first_inst_can_set_flags ? 2 : 1); ++s) {
984 2 : if (t->first_inst_can_set_flags) {
985 2 : t->inst[0] = SetSBit(t->inst[0], s);
986 : }
987 :
988 : Instruction::Condition cond[2];
989 64 : for (cond[0] = Instruction::EQ;
990 32 : cond[0] <= Instruction::AL;
991 30 : cond[0] = Instruction::Next(cond[0])) {
992 960 : for (cond[1] = Instruction::EQ;
993 480 : cond[1] <= Instruction::AL;
994 450 : cond[1] = Instruction::Next(cond[1])) {
995 450 : t->inst[0] = ChangeCond(t->inst[0], cond[0]);
996 450 : t->inst[1] = ChangeCond(t->inst[1], cond[1]);
997 :
998 : std::string name0(std::string(t->name[0]) + (s ? "s" : "") +
999 450 : Instruction::ToString(cond[0]));
1000 : std::string name1(std::string(t->name[1]) +
1001 450 : Instruction::ToString(cond[1]));
1002 450 : ostringstream message;
1003 450 : message << name0 <<
1004 900 : " (0x" << std::hex << std::setfill('0') << std::setw(8) <<
1005 900 : static_cast<uint32_t>(t->inst[0]) <<
1006 900 : std::resetiosflags(std::ios_base::showbase) << ") "
1007 450 : "with a correct mask, followed by " << name1 <<
1008 900 : " (0x" << std::hex << std::setfill('0') << std::setw(8) <<
1009 900 : static_cast<uint32_t>(t->inst[1]) <<
1010 900 : std::resetiosflags(std::ios_base::showbase) << "): ";
1011 :
1012 450 : if (s) {
1013 : validation_should_fail(t->inst, NACL_ARRAY_SIZE(t->inst),
1014 : kDefaultBaseAddr,
1015 : message.str() + name0 + " sets flags "
1016 : "when it's only supposed to enforce SFI on "
1017 : "the subsequent " + name1 + ", we "
1018 : "could allow this but it makes the "
1019 : "validator's code more complex and it's "
1020 : "harder to reason about back-to-back "
1021 : "conditional instructions with "
1022 : "intervening flag setting (especially with "
1023 225 : "ARM's partial NZCV flag setting).");
1024 225 : } else if (cond[0] == Instruction::AL) {
1025 : validation_should_pass(t->inst, NACL_ARRAY_SIZE(t->inst),
1026 : kDefaultBaseAddr,
1027 : message.str() + "an unconditional " +
1028 : name0 + " always dominates the "
1029 : "subsequent " + name1 +
1030 15 : " instruction.");
1031 210 : } else if (cond[1] == Instruction::AL) {
1032 14 : EXPECT_NE(cond[0], Instruction::AL);
1033 : validation_should_fail(t->inst, NACL_ARRAY_SIZE(t->inst),
1034 : kDefaultBaseAddr,
1035 : message.str() + name0 + " is "
1036 : "conditional, but the subsequent " +
1037 14 : name1 + " isn't.");
1038 196 : } else if ((cond[1] == cond[0]) ||
1039 : // TODO(jfb) Put back mixed-condition handling.
1040 : // See issue #3221.
1041 : /*
1042 : (cond[1] == Instruction::EQ && cond[0] == Instruction::LS) ||
1043 : (cond[1] == Instruction::CC && cond[0] == Instruction::LS) ||
1044 : (cond[1] == Instruction::HI && cond[0] == Instruction::NE) ||
1045 : (cond[1] == Instruction::HI && cond[0] == Instruction::CS) ||
1046 : (cond[1] == Instruction::GT && cond[0] == Instruction::NE) ||
1047 : (cond[1] == Instruction::GT && cond[0] == Instruction::GE) ||
1048 : (cond[1] == Instruction::LE && cond[0] == Instruction::EQ) ||
1049 : (cond[1] == Instruction::LE && cond[0] == Instruction::LS) ||
1050 : (cond[1] == Instruction::LE && cond[0] == Instruction::LT) */
1051 : false) {
1052 : validation_should_pass(t->inst, NACL_ARRAY_SIZE(t->inst),
1053 : kDefaultBaseAddr,
1054 : message.str() + name1 + "'s "
1055 : "condition being true necessarily implies "
1056 : "that " + name0 + "'s condition was "
1057 14 : "also true.");
1058 : } else {
1059 : validation_should_fail(t->inst, NACL_ARRAY_SIZE(t->inst),
1060 : kDefaultBaseAddr,
1061 : message.str() + name1 + "'s condition "
1062 : "being true doesn't necessarily imply "
1063 : "that " + name0 + "'s condition was "
1064 : "also true, err on the side of caution and "
1065 182 : "disallow.");
1066 : }
1067 450 : }
1068 : }
1069 : }
1070 : }
1071 1 : }
1072 :
1073 5 : TEST_F(ValidatorTests, UnmaskedSpUpdate) {
1074 1 : vector<arm_inst> code(_validator->InstructionsPerBundle(), kNop);
1075 5 : for (vector<arm_inst>::size_type i = 0; i < code.size(); ++i) {
1076 4 : std::fill(code.begin(), code.end(), kNop);
1077 4 : code[i] = 0xE1A0D000; // MOV SP, R0
1078 4 : validation_should_fail(&code[0], code.size(), kDefaultBaseAddr,
1079 8 : "unmasked SP update");
1080 1 : }
1081 1 : }
1082 :
1083 5 : TEST_F(ValidatorTests, MaskedSpUpdate) {
1084 1 : vector<arm_inst> code(_validator->InstructionsPerBundle() * 2, kNop);
1085 8 : for (vector<arm_inst>::size_type i = 0; i < code.size() - 1; ++i) {
1086 7 : std::fill(code.begin(), code.end(), kNop);
1087 7 : code[i] = 0xE1A0D000; // MOV SP, R0
1088 7 : code[i + 1] = 0xE3CDD2FF; // BIC SP, SP, #-268435441 ; 0xf000000f
1089 7 : if (i == _validator->InstructionsPerBundle() - 1) {
1090 1 : validation_should_fail(&code[0], code.size(), kDefaultBaseAddr,
1091 : "masked SP update straddling a bundle boundary"
1092 : " (this is technically safe, but we simplify the "
1093 : "validator by disallowing instruction pairs that "
1094 2 : "straddle a bundle boundary)");
1095 : } else {
1096 6 : validation_should_pass(&code[0], code.size(), kDefaultBaseAddr,
1097 12 : "masked SP update");
1098 : }
1099 1 : }
1100 1 : }
1101 :
1102 5 : TEST_F(ValidatorTests, AddConstToSpTest) {
1103 : // Show that we can add a constant to the stack pointer is fine,
1104 : // so long as we follow it with a mask instruction.
1105 : static const arm_inst sp_inst[] = {
1106 : 0xe28dd00c, // add sp, sp, #12
1107 : 0xe3cdd2ff, // bic sp, sp, #-268435441 ; 0xf000000f
1108 : };
1109 : validation_should_pass(sp_inst,
1110 : NACL_ARRAY_SIZE(sp_inst),
1111 : kDefaultBaseAddr,
1112 1 : "Add constant (12) to sp, then mask with bic");
1113 1 : }
1114 :
1115 5 : TEST_F(ValidatorTests, BicSpFirstInstTest) {
1116 : // Show that if we bit clear SP as the first instruction, it is ok.
1117 : static const arm_inst bic_inst[] = {
1118 : 0xe3cdd2ff, // bic sp, sp, #-268435441 ; 0xf000000f
1119 : };
1120 : validation_should_pass(bic_inst,
1121 : NACL_ARRAY_SIZE(bic_inst),
1122 : kDefaultBaseAddr,
1123 1 : "Bit clear sp as first instruction.");
1124 1 : }
1125 :
1126 5 : TEST_F(ValidatorTests, BicSpSecondInstTest) {
1127 : // Show that if we bit clear SP as the second instruction, and
1128 : // the first doesn't update SP, we are ok.
1129 : static const arm_inst bic_inst[] = {
1130 : kNop,
1131 : 0xe3cdd2ff, // bic sp, sp, #-268435441 ; 0xf000000f
1132 : };
1133 : validation_should_pass(bic_inst,
1134 : NACL_ARRAY_SIZE(bic_inst),
1135 : kDefaultBaseAddr,
1136 1 : "Bit clear sp as second instruction.");
1137 1 : }
1138 :
1139 5 : TEST_F(ValidatorTests, AddConstToSpBicTestDoesFollows) {
1140 : // Run test where we conditionally add a constant to a stack pointer,
1141 : // followed by a mask.
1142 : // Note: Implicitly tests always_postdominates.
1143 15 : for (int cond = Instruction::EQ; cond < Instruction::AL; ++cond) {
1144 : arm_inst inst[] = {
1145 : 0x028dd00c, // addeq sp, sp, #12
1146 : 0xe3cdd2ff, // bic sp, sp, #-268435441 ; 0xf000000f
1147 14 : };
1148 14 : inst[0] = ChangeCond(inst[0], static_cast<Instruction::Condition>(cond));
1149 : validation_should_pass(inst,
1150 : NACL_ARRAY_SIZE(inst),
1151 : kDefaultBaseAddr,
1152 : "Add constant (12) to sp, then mask with bic, "
1153 14 : "tests always_postdominates succeeds");
1154 : }
1155 1 : }
1156 :
1157 5 : TEST_F(ValidatorTests, AddConstToSpBicTestDoesntFollows) {
1158 : // Run test where we add a constant to a stack pointer, followed
1159 : // by a conditional mask.
1160 : // Note: Implicitly tests always_postdominates.
1161 15 : for (int cond = Instruction::EQ; cond < Instruction::AL; ++cond) {
1162 : arm_inst inst[] = {
1163 : 0xe28dd00c, // add sp, sp, #12
1164 : 0x03cdd2ff, // biceq sp, sp, #-268435441 ; 0xf000000f
1165 14 : };
1166 14 : inst[1] = ChangeCond(inst[1], static_cast<Instruction::Condition>(cond));
1167 : validation_should_fail(inst,
1168 : NACL_ARRAY_SIZE(inst),
1169 : kDefaultBaseAddr,
1170 : "Add constant (12) to sp, then mask with bic, "
1171 14 : "tests always_postdominates fails");
1172 : }
1173 1 : }
1174 :
1175 5 : TEST_F(ValidatorTests, CheckVectorLoadPcRelative) {
1176 : // Run test where we do a vector load using a pc relative address.
1177 : // Corresponds to issue 2906.
1178 : static const arm_inst load_inst[] = {
1179 : 0xed9f0b04, // vldr d0, [pc, #16]
1180 : };
1181 : validation_should_pass(load_inst,
1182 : NACL_ARRAY_SIZE(load_inst),
1183 : kDefaultBaseAddr,
1184 1 : "Load vector register using pc relative address");
1185 1 : }
1186 :
1187 5 : TEST_F(ValidatorTests, CheckPushSpUnpredictable) {
1188 : // Run test to verify that "Push {sp}", encoding A2 on a8-248 of ARM manual,
1189 : // is unpredictable (i.e. unsafe).
1190 : all_cond_values_fail(0xe52dd004, // push {sp}
1191 : kDefaultBaseAddr,
1192 1 : "push {sp} (A2 a8-248) should be unpredictable");
1193 1 : }
1194 :
1195 5 : TEST_F(ValidatorTests, ConditionalBreakpoints) {
1196 1 : arm_inst bkpt = 0xE1200070; // BKPT #0
1197 1 : arm_inst pool_head = kLiteralPoolHead;
1198 15 : for (Instruction::Condition cond = Instruction::EQ;
1199 : cond < Instruction::AL;
1200 : cond = Instruction::Next(cond)) {
1201 14 : bkpt = ChangeCond(bkpt, cond);
1202 14 : pool_head = ChangeCond(pool_head, cond);
1203 14 : EXPECT_FALSE(validate(&bkpt, 1, kDefaultBaseAddr))
1204 0 : << "conditional breakpoint should be unpredictable";
1205 14 : EXPECT_FALSE(validate(&pool_head, 1, kDefaultBaseAddr))
1206 0 : << "conditional literal pool head should be unpredictable";
1207 : }
1208 1 : }
1209 :
1210 5 : TEST_F(ValidatorTests, CheckLoadStoreWritebackUnpredictable) {
1211 : // See issue #2816: compilers used to emit some unpredictable load/store
1212 : // instructions with writeback, and the validator accepted them for a while.
1213 : //
1214 : // Theses unpredictables have writeback and either Rn=Rt or Rn=Rt2.
1215 : //
1216 : // The instructions are all from A5.2.8 Extra Load/Store Instructions:
1217 : // cccc 000P UaWa nnnn tttt xxxx 1bb1 xxxx
1218 : // With an exclusion for data-processing and miscellaneous as noted below.
1219 : //
1220 : // Nibbles 0 and 2 are either zeroes/Rm (register variants) or
1221 : // imm4H/imm4L (integer variant). Only test when they're all zero.
1222 1 : arm_inst templ = 0x00000090;
1223 5 : for (uint32_t op2 = 0; op2 <= 0x3; ++op2) { // op2 is in inst(6:5).
1224 132 : for (uint32_t op1 = 0; op1 <= 0x1F; ++op1) { // op1 is in inst(24:20).
1225 128 : if (!(op1 & 0x2))
1226 64 : continue; // Only undefined with writeback.
1227 64 : if ((op2 == 0x0) ||
1228 : ((op1 & 0x13) == 0x03) ||
1229 : (((op1 & 0x13) == 0x02) && ((op2 & 0x2) == 0x0)))
1230 32 : continue; // Not in A5.2.8: actually Data-processing and miscellaneous.
1231 : // Dual load/store encode Rt2 as Rt+1.
1232 32 : bool is_dual = ((op1 & 0x01) == 0x00) && ((op2 == 0x2) || (op2 == 0x3));
1233 512 : for (uint32_t n = 0; n < 15; ++n) { // Ignore Rn=PC, it can't writeback.
1234 480 : uint32_t t = n;
1235 480 : arm_inst base = (templ | (op1 << 20) | (t << 12) | (op2 << 5));
1236 480 : arm_inst inst = base | (n << 16); // Rn=Rt.
1237 480 : arm_inst inst_dual = base | ((n + 1) << 16); // Rn=Rt2.
1238 : all_cond_values_fail(inst, kDefaultBaseAddr, "extra load/store "
1239 : "with writeback and Rn==Rt should be "
1240 480 : "unpredictable");
1241 480 : if (is_dual) {
1242 : all_cond_values_fail(inst_dual, kDefaultBaseAddr, "extra load/store "
1243 : "with writeback and Rn==Rt2 should be "
1244 240 : "unpredictable");
1245 : }
1246 : }
1247 : }
1248 : }
1249 1 : }
1250 :
1251 5 : TEST_F(ValidatorTests, LiteralPoolHeadIsBreakpoint) {
1252 1 : EXPECT_EQ(kLiteralPoolHead & 0xFFF000F0, 0xE1200070) // BKPT #0
1253 : << ("the literal pool head should be a breakpoint: "
1254 0 : "it needs to act as a roadblock");
1255 1 : }
1256 :
1257 5 : TEST_F(ValidatorTests, Breakpoint) {
1258 1 : EXPECT_EQ(nacl_arm_dec::kBreakpoint & 0xFFF000F0,
1259 : 0xE1200070) // BKPT #0
1260 : << ("the breakpoint instruction should be a breakpoint: "
1261 0 : "it needs to trap");
1262 1 : }
1263 :
1264 5 : TEST_F(ValidatorTests, HaltFill) {
1265 1 : EXPECT_EQ(nacl_arm_dec::kHaltFill & 0xFFF000F0,
1266 : 0xE7F000F0) // UDF #0
1267 : << ("the halt fill instruction should be UDF: "
1268 0 : "it needs to trap");
1269 1 : }
1270 :
1271 5 : TEST_F(ValidatorTests, AbortNow) {
1272 1 : EXPECT_EQ(nacl_arm_dec::kAbortNow & 0xFFF000F0,
1273 : 0xE7F000F0) // UDF #0
1274 : << ("the abort now instruction should be UDF: "
1275 0 : "it needs to trap");
1276 1 : }
1277 :
1278 5 : TEST_F(ValidatorTests, FailValidation) {
1279 1 : EXPECT_EQ(kFailValidation & 0xFFF000F0, 0xE7F000F0) // UDF #0
1280 : << ("the fail validation instruction should be UDF: "
1281 0 : "it needs to trap");
1282 1 : }
1283 :
1284 5 : TEST_F(ValidatorTests, UDFAndBKPTValidateAsExpected) {
1285 65536 : for (uint32_t i = 0; i < 0xFFFF; ++i) {
1286 65535 : arm_inst bkpt_inst = 0xE1200070 | ((i & 0xFFF0) << 4) | (i & 0xF);
1287 65535 : arm_inst udf_inst = 0xE7F000F0 | ((i & 0xFFF0) << 4) | (i & 0xF);
1288 65535 : EXPECT_EQ(validate(&bkpt_inst, 1, kDefaultBaseAddr),
1289 : ((bkpt_inst == kLiteralPoolHead) ||
1290 65535 : (bkpt_inst == nacl_arm_dec::kBreakpoint)));
1291 65535 : EXPECT_EQ(validate(&udf_inst, 1, kDefaultBaseAddr),
1292 : ((udf_inst == nacl_arm_dec::kHaltFill) ||
1293 65535 : (udf_inst == nacl_arm_dec::kAbortNow)));
1294 : // Tautological note: kFailValidation should fail validation.
1295 : }
1296 1 : }
1297 :
1298 5 : TEST_F(ValidatorTests, LiteralPoolHeadInstruction) {
1299 : // Make sure that literal pools are handled properly: they should be preceded
1300 : // by a special breakpoint instruction at the start of the bundle, and can
1301 : // then contain any bits that would otherwise look malicious.
1302 : // Each literal pool bundle has to start with such a literal pool head.
1303 1 : vector<arm_inst> literal_pool(_validator->InstructionsPerBundle(), kSvc0);
1304 1 : literal_pool[0] = 0xE1200070; // BKPT #0
1305 : // Try out all BKPT encodings, and make sure only one of them works.
1306 65537 : for (uint32_t imm16 = 0; imm16 <= 0xFFFF; ++imm16) {
1307 65536 : literal_pool[0] = (literal_pool[0] & 0xFFF000F0) |
1308 : (imm16 & 0xF) |
1309 65536 : ((imm16 & 0xFFF0) << 8);
1310 65536 : if (literal_pool[0] == kLiteralPoolHead) {
1311 0 : validation_should_pass(&literal_pool.front(),
1312 : literal_pool.size(),
1313 : kDefaultBaseAddr,
1314 : "valid literal pool: "
1315 0 : "starts with special BKPT");
1316 : } else {
1317 65536 : validation_should_fail(&literal_pool.front(),
1318 : literal_pool.size(),
1319 : kDefaultBaseAddr,
1320 : "invalid literal pool: "
1321 131072 : "starts with just a regular BKPT");
1322 : }
1323 1 : }
1324 1 : }
1325 :
1326 5 : TEST_F(ValidatorTests, LiteralPoolHeadPosition) {
1327 : // Literal pools should only work when the head instruction is indeed at
1328 : // the head.
1329 1 : vector<arm_inst> literal_pool(_validator->InstructionsPerBundle());
1330 5 : for (size_t pos = 0; pos < literal_pool.size(); ++pos) {
1331 4 : std::fill(literal_pool.begin(), literal_pool.end(), kSvc0);
1332 4 : if (pos != literal_pool.size() - 1) {
1333 : // We do one iteration without a literal pool head at all.
1334 3 : literal_pool[pos] = kLiteralPoolHead;
1335 : }
1336 4 : if (pos == 0) {
1337 1 : validation_should_pass(&literal_pool.front(),
1338 : literal_pool.size(),
1339 : kDefaultBaseAddr,
1340 : "valid literal pool: "
1341 2 : "starts with special head instruction");
1342 : } else {
1343 3 : validation_should_fail(&literal_pool.front(),
1344 : literal_pool.size(),
1345 : kDefaultBaseAddr,
1346 : "invalid literal pool: "
1347 6 : "doesn't start with special head instruction");
1348 : }
1349 1 : }
1350 1 : }
1351 :
1352 5 : TEST_F(ValidatorTests, LiteralPoolBig) {
1353 : // Literal pools should be a single bundle wide, each must be preceded by
1354 : // a pool head.
1355 1 : vector<arm_inst> literal_pools(2 * _validator->InstructionsPerBundle());
1356 9 : for (size_t pos = 0; pos < literal_pools.size(); ++pos) {
1357 8 : std::fill(literal_pools.begin(), literal_pools.end(), kSvc0);
1358 8 : literal_pools[pos] = kLiteralPoolHead;
1359 8 : validation_should_fail(&literal_pools.front(),
1360 : literal_pools.size(),
1361 : kDefaultBaseAddr,
1362 16 : "invalid literal pool: two pools, one head");
1363 1 : }
1364 1 : }
1365 :
1366 5 : TEST_F(ValidatorTests, LiteralPoolBranch) {
1367 : // Branching to a literal pool should only work at the head.
1368 : // Construct a code region with a bundle of code, then a bundle-wide
1369 : // literal pool, then another bundle of code.
1370 : // Add a branch from different code locations, pointing at different
1371 : // parts of the code. Pointing in the literal pool should fail, except
1372 : // when pointing at the head.
1373 : // Note that we don't actually put anything malicious in the literal pool,
1374 : // and we still shouldn't be able to jump in the middle of it.
1375 1 : const size_t bundle_pos = _validator->InstructionsPerBundle();
1376 1 : vector<arm_inst> code(3 * bundle_pos);
1377 13 : for (size_t b_pos = 0; b_pos < code.size(); ++b_pos) {
1378 12 : if ((bundle_pos <= b_pos) && (b_pos < bundle_pos * 2)) {
1379 : // Don't try putting the branch in the middle of the literal pool.
1380 4 : continue;
1381 : }
1382 8 : std::fill(code.begin(), code.end(), kNop);
1383 8 : code[bundle_pos] = kLiteralPoolHead;
1384 104 : for (size_t b_target = 0; b_target < code.size(); ++b_target) {
1385 : // PC reads as current instruction address plus 8 (e.g. two instructions
1386 : // ahead of b_pos).
1387 : // imm24 is encoded with the bottom two bits zeroed out, which we
1388 : // implicitly do by working with instructions instead of bytes.
1389 96 : uint32_t imm24 = (b_target - b_pos - 2) & 0x00FFFFFF;
1390 96 : code[b_pos] = 0xEA000000 | imm24; // B #imm
1391 : bool target_in_pool = (bundle_pos < b_target) &&
1392 96 : (b_target < bundle_pos * 2); // Excluding head.
1393 96 : if (target_in_pool) {
1394 24 : validation_should_fail(&code.front(),
1395 : code.size(),
1396 : kDefaultBaseAddr,
1397 48 : "branch inside a literal pool");
1398 : } else {
1399 72 : validation_should_pass(&code.front(),
1400 : code.size(),
1401 : kDefaultBaseAddr,
1402 144 : "branch around or at head of a literal pool");
1403 : }
1404 : }
1405 1 : }
1406 1 : }
1407 :
1408 5 : TEST_F(ValidatorTests, Preloads) {
1409 : // Preloads leak information on some ARM CPUs and are therefore treated
1410 : // similar to no-destination loads. They come in three flavors:
1411 : // - PLD{W} [<Rn>, #+/-<imm12>] simply needs to mask Rn.
1412 : // - PLD <label> doesn't need masking: its immediate is limited to 12 bits.
1413 : // - PLD{W} [<Rn>,+/-<Rm>{, <shift>}] is disallowed.
1414 : // The same applies for PLI, which has analogous variants.
1415 :
1416 : // PLD{W} [<Rn>, #+/-<imm12>] as well as PLI.
1417 : // PLD{W}: 1111 0101 UR01 nnnn 1111 iiii iiii iiii
1418 : // PLI: 1111 0100 U101 nnnn 1111 iiii iiii iiii
1419 3 : for (uint32_t is_pld = 0; is_pld <= 1; ++is_pld) {
1420 5 : for (uint32_t r = is_pld ? 0 : 1; r <= 1; ++r) {
1421 9 : for (uint32_t u = 0; u <= 1; ++u) {
1422 6 : uint32_t rn = 0x1; // TODO(jfb) The BIC patterns only test Rn==R1.
1423 24582 : for (uint32_t imm12 = 0; imm12 <= 0xFFF; ++imm12) {
1424 : arm_inst pl_inst = 0xF410F000 |
1425 24576 : (is_pld << 24) | (u << 23) | (r << 22) | (rn << 16) | imm12;
1426 : validation_should_fail(&pl_inst, 1, kDefaultBaseAddr,
1427 24576 : "unmasked preloads");
1428 122880 : for (size_t m = 0; m < NACL_ARRAY_SIZE(examples_of_safe_masks);
1429 : ++m) {
1430 : arm_inst program[] = {
1431 : ChangeCond(examples_of_safe_masks[m].inst,
1432 98304 : Instruction::AL),
1433 : pl_inst,
1434 98304 : };
1435 : validation_should_pass(program, NACL_ARRAY_SIZE(program),
1436 : kDefaultBaseAddr,
1437 98304 : "masked preload with safe mask");
1438 : }
1439 122880 : for (size_t m = 0; m < NACL_ARRAY_SIZE(examples_of_invalid_masks);
1440 : ++m) {
1441 : arm_inst program[] = {
1442 : ChangeCond(examples_of_invalid_masks[m].inst,
1443 98304 : Instruction::AL),
1444 : pl_inst,
1445 98304 : };
1446 : validation_should_fail(program, NACL_ARRAY_SIZE(program),
1447 : kDefaultBaseAddr,
1448 98304 : "masked preload with invalid mask");
1449 : }
1450 : }
1451 : }
1452 : }
1453 : }
1454 :
1455 : // PLD <label> as well as PLI.
1456 : // PLD: 1111 0101 U101 1111 1111 iiii iiii iiii
1457 : // PLI: 1111 0100 U101 1111 1111 iiii iiii iiii
1458 3 : for (uint32_t is_pld = 0; is_pld <= 1; ++is_pld) {
1459 6 : for (uint32_t u = 0; u <= 1; ++u) {
1460 16388 : for (uint32_t imm12 = 0; imm12 <= 0xFFF; ++imm12) {
1461 : arm_inst pl_inst = 0xF45FF000 |
1462 16384 : (is_pld << 24) | (u << 23) | imm12;
1463 : validation_should_pass(&pl_inst, 1, kDefaultBaseAddr,
1464 16384 : "unmasked literal preloads");
1465 : }
1466 : }
1467 : }
1468 :
1469 : // PLD{W} [<Rn>, +/-Rm{, shift}] as well as PLI.
1470 : // PLD{W}: 1111 0111 UR01 nnnn 1111 iiii itt0 mmmm
1471 : // PLI: 1111 0110 U101 nnnn 1111 iiii itt0 mmmm
1472 3 : for (uint32_t is_pld = 0; is_pld <= 1; ++is_pld) {
1473 5 : for (uint32_t r = is_pld ? 0 : 1; r <= 1; ++r) {
1474 9 : for (uint32_t u = 0; u <= 1; ++u) {
1475 30 : for (uint32_t t = 0; t <= 3; ++t) {
1476 408 : for (uint32_t rm = 0; rm <= 0xF; ++rm) {
1477 384 : uint32_t rn = 0x1; // TODO(jfb) The BIC patterns only test Rn==R1.
1478 12672 : for (uint32_t imm5 = 0; imm5 <= 0x1F; ++imm5) {
1479 : arm_inst pl_inst = 0xF610F000 |
1480 : (is_pld << 24) | (u << 23) | (r << 22) | (rn << 16) |
1481 12288 : (imm5 << 7) | (t << 5) | rm;
1482 : validation_should_fail(&pl_inst, 1, kDefaultBaseAddr,
1483 12288 : "unmasked register-register preloads");
1484 61440 : for (size_t m = 0; m < NACL_ARRAY_SIZE(examples_of_safe_masks);
1485 : ++m) {
1486 : arm_inst program[] = {
1487 : ChangeCond(examples_of_safe_masks[m].inst,
1488 49152 : Instruction::AL),
1489 : pl_inst,
1490 49152 : };
1491 : validation_should_fail(program, NACL_ARRAY_SIZE(program),
1492 : kDefaultBaseAddr,
1493 : "masked register-register preload "
1494 49152 : "with safe mask");
1495 : }
1496 61440 : for (size_t m = 0; m < NACL_ARRAY_SIZE(examples_of_invalid_masks);
1497 : ++m) {
1498 : arm_inst program[] = {
1499 : ChangeCond(examples_of_invalid_masks[m].inst,
1500 49152 : Instruction::AL),
1501 : pl_inst,
1502 49152 : };
1503 : validation_should_fail(program, NACL_ARRAY_SIZE(program),
1504 : kDefaultBaseAddr,
1505 : "masked register-register preload "
1506 49152 : "with invalid mask");
1507 : }
1508 : }
1509 : }
1510 : }
1511 : }
1512 : }
1513 : }
1514 1 : }
1515 :
1516 5 : TEST_F(ValidatorTests, LoadThreadLocalPtr) {
1517 : // Verify that we recognize valid load thread local pointer instructions.
1518 : static const AnnotatedInstruction loadr9_insts[] = {
1519 : {0xe5990000, "ldr<c> r0, [r9]"},
1520 : {0xe5990004, "ldr<c> r0, [r9, #4]"},
1521 : };
1522 :
1523 : // Try each load instruction
1524 3 : for (size_t i = 0; i < NACL_ARRAY_SIZE(loadr9_insts); ++i) {
1525 2 : Instruction test_base(loadr9_insts[i].inst);
1526 :
1527 : // Try each possible condition.
1528 32 : for (Instruction::Condition cond = Instruction::EQ;
1529 : cond < Instruction::UNCONDITIONAL;
1530 : cond = Instruction::Next(cond)) {
1531 30 : Instruction test_cond(ChangeInstCond(test_base, cond));
1532 :
1533 : // Try each register to assign (i.e. replace r0).
1534 510 : for (uint32_t r = 0; r < 16; ++r) {
1535 480 : Register reg(r);
1536 480 : Instruction test(test_cond);
1537 480 : test.SetBits(15, 12, r); // I.e. set Rt(15:12) to r;
1538 :
1539 : // Generate string describing instruction being tested.
1540 480 : ostringstream message;
1541 480 : string msg(loadr9_insts[i].about);
1542 480 : const char* r0 = "r0";
1543 480 : msg.replace(msg.find(r0), strlen(r0), reg.ToString());
1544 480 : const char* cc = "<c>";
1545 480 : msg.replace(msg.find(cc), strlen(cc), Instruction::ToString(cond));
1546 480 : message << "Test '" << msg << "'";
1547 :
1548 : // Test the generated instruction.
1549 480 : arm_inst insts[1] = { test.Bits() };
1550 480 : if (IsValidSingleInstructionDestinationRegister(reg)) {
1551 : validation_should_pass(insts, NACL_ARRAY_SIZE(insts),
1552 390 : kDefaultBaseAddr, message.str());
1553 : } else {
1554 : validation_should_fail(insts, NACL_ARRAY_SIZE(insts),
1555 90 : kDefaultBaseAddr, message.str());
1556 : }
1557 480 : }
1558 : }
1559 : }
1560 1 : }
1561 :
1562 5 : TEST_F(ValidatorTests, UseR9) {
1563 : // Verify that we report about illegal uses of thread local pointer.
1564 : static const AnnotatedInstruction use_r9_insts[] = {
1565 : {0xe0892009, "add r2, r9, r9"},
1566 : { 0x03C99103, "bic r9, r9, #0xC0000000: simple in-place mask (form 1)" },
1567 : { 0x03C91103, "bic r1, r9, #0xC0000000: mask with register move (form 1)" },
1568 : { 0x03C19103, "bic r9, r1, #0xC0000000: mask with register move (form 1)" },
1569 : { 0x03C994C0, "bic r9, r9, #0xC0000000: simple in-place mask (form 2)" },
1570 : { 0x03C914C0, "bic r1, r9, #0xC0000000: mask with register move (form 2)" },
1571 : { 0x03C394C0, "bic r9, r3, #0xC0000000: mask with register move (form 2)" },
1572 : { 0x03C994FF, "bic r9, r9, #0xFF000000: overzealous but correct mask" },
1573 : {0xe7df9f1f, "bfc r9, #30, #2"},
1574 : // TODO(karl): Add load/store examples, when implemented, like:
1575 : // STR r9, [rt]; MOV rd, r9; MOV sd, r9
1576 : };
1577 :
1578 : // Try each test instruction.
1579 10 : for (size_t i = 0; i < NACL_ARRAY_SIZE(use_r9_insts); ++i) {
1580 9 : Instruction test(use_r9_insts[i].inst);
1581 :
1582 : // Try each possible condition.
1583 144 : for (Instruction::Condition cond = Instruction::EQ;
1584 : cond < Instruction::UNCONDITIONAL;
1585 : cond = Instruction::Next(cond)) {
1586 135 : Instruction test_cond(ChangeInstCond(test, cond));
1587 :
1588 135 : ostringstream message;
1589 135 : message << "Test use of r9 with cond=" << Instruction::ToString(cond)
1590 270 : << ": " << use_r9_insts[i].about;
1591 : validation_should_fail(&use_r9_insts[i].inst, 1, kDefaultBaseAddr,
1592 135 : message.str());
1593 135 : }
1594 : }
1595 1 : }
1596 :
1597 : }; // anonymous namespace
1598 :
1599 : // Test driver function.
1600 1 : int main(int argc, char *argv[]) {
1601 1 : testing::InitGoogleTest(&argc, argv);
1602 1 : return RUN_ALL_TESTS();
1603 3 : }
|