OLD | NEW |
1 /* | 1 /* |
2 * Copyright (c) 2012 The Native Client Authors. All rights reserved. | 2 * Copyright (c) 2012 The Native Client Authors. All rights reserved. |
3 * Use of this source code is governed by a BSD-style license that can be | 3 * Use of this source code is governed by a BSD-style license that can be |
4 * found in the LICENSE file. | 4 * found in the LICENSE file. |
5 */ | 5 */ |
6 | 6 |
7 #ifndef NACL_TRUSTED_BUT_NOT_TCB | 7 #ifndef NACL_TRUSTED_BUT_NOT_TCB |
8 #error This file is not meant for use in the TCB | 8 #error This file is not meant for use in the TCB |
9 #endif | 9 #endif |
10 | 10 |
11 /* | 11 /* |
12 * Small unit tests for the ARM validator | 12 * Small unit tests for the ARM validator |
13 * | 13 * |
14 * Also see validator_large_tests.cc, | 14 * Also see validator_large_tests.cc, |
15 * and validator_tests.h for the testing infrastructure. | 15 * and validator_tests.h for the testing infrastructure. |
16 */ | 16 */ |
17 | 17 |
18 #include "native_client/src/trusted/validator_arm/validator_tests.h" | 18 #include "native_client/src/trusted/validator_arm/validator_tests.h" |
19 | 19 |
20 using nacl_val_arm_test::ProblemRecord; | 20 using nacl_val_arm_test::ProblemRecord; |
21 using nacl_val_arm_test::ProblemSpy; | 21 using nacl_val_arm_test::ProblemSpy; |
22 using nacl_val_arm_test::ValidatorTests; | 22 using nacl_val_arm_test::ValidatorTests; |
23 using nacl_val_arm_test::kDefaultBaseAddr; | 23 using nacl_val_arm_test::kDefaultBaseAddr; |
24 using nacl_val_arm_test::kCodeRegionSize; | 24 using nacl_val_arm_test::kCodeRegionSize; |
25 using nacl_val_arm_test::kDataRegionSize; | 25 using nacl_val_arm_test::kDataRegionSize; |
26 using nacl_val_arm_test::kAbiReadOnlyRegisters; | 26 using nacl_val_arm_test::kAbiReadOnlyRegisters; |
27 using nacl_val_arm_test::kAbiDataAddrRegisters; | 27 using nacl_val_arm_test::kAbiDataAddrRegisters; |
28 using nacl_val_arm_test::arm_inst; | 28 using nacl_val_arm_test::arm_inst; |
| 29 using nacl_arm_dec::kNop; |
29 using nacl_arm_dec::Instruction; | 30 using nacl_arm_dec::Instruction; |
30 using nacl_arm_dec::ClassDecoder; | 31 using nacl_arm_dec::ClassDecoder; |
31 | 32 |
32 namespace { | 33 namespace { |
33 | 34 |
34 // Holds instruction and message to print if there is an issue when it | 35 // Holds instruction and message to print if there is an issue when it |
35 // is tested. | 36 // is tested. |
36 struct AnnotatedInstruction { | 37 struct AnnotatedInstruction { |
37 arm_inst inst; | 38 arm_inst inst; |
38 const char *about; | 39 const char *about; |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
89 Instruction test(ChangeInstCond(test_inst, cond)); | 90 Instruction test(ChangeInstCond(test_inst, cond)); |
90 const ClassDecoder& decoder = tester->decode(test); | 91 const ClassDecoder& decoder = tester->decode(test); |
91 Instruction sentinel(decoder.dynamic_code_replacement_sentinel(test)); | 92 Instruction sentinel(decoder.dynamic_code_replacement_sentinel(test)); |
92 EXPECT_TRUE(test.Equals(sentinel)) << | 93 EXPECT_TRUE(test.Equals(sentinel)) << |
93 std::hex << test.Bits() << "->" << | 94 std::hex << test.Bits() << "->" << |
94 std::hex << sentinel.Bits() << ": " << insts[i].about; | 95 std::hex << sentinel.Bits() << ": " << insts[i].about; |
95 } | 96 } |
96 } | 97 } |
97 } | 98 } |
98 | 99 |
| 100 TEST_F(ValidatorTests, NopBundle) { |
| 101 vector<arm_inst> code(_validator.InstructionsPerBundle(), kNop); |
| 102 validation_should_pass(&code[0], code.size(), kDefaultBaseAddr, |
| 103 "NOP bundle"); |
| 104 } |
| 105 |
99 /* | 106 /* |
100 * Primitive tests checking various constructor properties. Any of these | 107 * Primitive tests checking various constructor properties. Any of these |
101 * failing would be a very bad sign indeed. | 108 * failing would be a very bad sign indeed. |
102 */ | 109 */ |
103 | 110 |
104 TEST_F(ValidatorTests, RecognizesDataAddressRegisters) { | 111 TEST_F(ValidatorTests, RecognizesDataAddressRegisters) { |
105 // Note that the logic below needs to be kept in sync with the definition | 112 // Note that the logic below needs to be kept in sync with the definition |
106 // of kAbiDataAddrRegisters at the top of this file. | 113 // of kAbiDataAddrRegisters at the top of this file. |
107 // | 114 // |
108 // This test is pretty trivial -- we can exercise the data_address_register | 115 // This test is pretty trivial -- we can exercise the data_address_register |
(...skipping 408 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
517 EXPECT_EQ(nacl_arm_val::kProblemUnsafe, first.problem()) | 524 EXPECT_EQ(nacl_arm_val::kProblemUnsafe, first.problem()) |
518 << "Instruction must be marked unsafe: " | 525 << "Instruction must be marked unsafe: " |
519 << undefined_insts[i].about; | 526 << undefined_insts[i].about; |
520 } | 527 } |
521 } | 528 } |
522 | 529 |
523 TEST_F(ValidatorTests, PcRelativeFirstInst) { | 530 TEST_F(ValidatorTests, PcRelativeFirstInst) { |
524 // Note: This tests the fix for issue 2771. | 531 // Note: This tests the fix for issue 2771. |
525 static const arm_inst pcrel_boundary_tests[] = { | 532 static const arm_inst pcrel_boundary_tests[] = { |
526 0xe59f0000, // ldr r0, [pc, #0] | 533 0xe59f0000, // ldr r0, [pc, #0] |
527 0xe320f000, // nop {0} | 534 kNop, |
528 0xe320f000, // nop {0} | 535 kNop, |
529 0xe320f000, // nop {0}" | 536 kNop, |
530 }; | 537 }; |
531 validation_should_pass(pcrel_boundary_tests, | 538 validation_should_pass(pcrel_boundary_tests, |
532 NACL_ARRAY_SIZE(pcrel_boundary_tests), | 539 NACL_ARRAY_SIZE(pcrel_boundary_tests), |
533 kDefaultBaseAddr, | 540 kDefaultBaseAddr, |
534 "pc relative first instruction in first bundle"); | 541 "pc relative first instruction in first bundle"); |
535 } | 542 } |
536 | 543 |
537 TEST_F(ValidatorTests, PcRelativeFirst2ndBundle) { | 544 TEST_F(ValidatorTests, PcRelativeFirst2ndBundle) { |
538 // Note: This tests the fix for issue 2771. | 545 // Note: This tests the fix for issue 2771. |
539 static const arm_inst pcrel_boundary_tests[] = { | 546 static const arm_inst pcrel_boundary_tests[] = { |
540 0xe320f000, // nop {0} | 547 kNop, |
541 0xe320f000, // nop {0} | 548 kNop, |
542 0xe320f000, // nop {0} | 549 kNop, |
543 0xe320f000, // nop {0} | 550 kNop, |
544 0xe59f0000, // ldr r0, [pc, #0] | 551 0xe59f0000, // ldr r0, [pc, #0] |
545 }; | 552 }; |
546 validation_should_pass(pcrel_boundary_tests, | 553 validation_should_pass(pcrel_boundary_tests, |
547 NACL_ARRAY_SIZE(pcrel_boundary_tests), | 554 NACL_ARRAY_SIZE(pcrel_boundary_tests), |
548 kDefaultBaseAddr, | 555 kDefaultBaseAddr, |
549 "pc relative first instruction in 2nd bundle"); | 556 "pc relative first instruction in 2nd bundle"); |
550 } | 557 } |
551 | 558 |
552 TEST_F(ValidatorTests, SafeConditionalBicLdrTest) { | 559 TEST_F(ValidatorTests, SafeConditionalBicLdrTest) { |
553 // Test if we fixed bug with conditional Bic Loads (issue 2769). | 560 // Test if we fixed bug with conditional Bic Loads (issue 2769). |
(...skipping 368 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
922 "disallow."); | 929 "disallow."); |
923 } | 930 } |
924 } | 931 } |
925 } | 932 } |
926 } | 933 } |
927 } | 934 } |
928 } | 935 } |
929 | 936 |
930 // TODO(karl): Add pattern rules and test cases for using bfc to update SP. | 937 // TODO(karl): Add pattern rules and test cases for using bfc to update SP. |
931 | 938 |
| 939 TEST_F(ValidatorTests, UnmaskedSpUpdate) { |
| 940 vector<arm_inst> code(_validator.InstructionsPerBundle(), kNop); |
| 941 for (vector<arm_inst>::size_type i = 0; i < code.size(); ++i) { |
| 942 std::fill(code.begin(), code.end(), kNop); |
| 943 code[i] = 0xE1A0D000; // MOV SP, R0 |
| 944 validation_should_fail(&code[0], code.size(), kDefaultBaseAddr, |
| 945 "unmasked SP update"); |
| 946 } |
| 947 } |
| 948 |
| 949 TEST_F(ValidatorTests, MaskedSpUpdate) { |
| 950 vector<arm_inst> code(_validator.InstructionsPerBundle() * 2, kNop); |
| 951 for (vector<arm_inst>::size_type i = 0; i < code.size() - 1; ++i) { |
| 952 std::fill(code.begin(), code.end(), kNop); |
| 953 code[i] = 0xE1A0D000; // MOV SP, R0 |
| 954 code[i + 1] = 0xE3CDD2FF; // BIC SP, SP, #-268435441 ; 0xf000000f |
| 955 if (i == _validator.InstructionsPerBundle() - 1) { |
| 956 validation_should_fail(&code[0], code.size(), kDefaultBaseAddr, |
| 957 "masked SP update straddling a bundle boundary" |
| 958 " (this is technically safe, but we simplify the " |
| 959 "validator by disallowing instruction pairs that " |
| 960 "straddle a bundle boundary)"); |
| 961 } else { |
| 962 validation_should_pass(&code[0], code.size(), kDefaultBaseAddr, |
| 963 "masked SP update"); |
| 964 } |
| 965 } |
| 966 } |
| 967 |
932 TEST_F(ValidatorTests, AddConstToSpTest) { | 968 TEST_F(ValidatorTests, AddConstToSpTest) { |
933 // Show that we can add a constant to the stack pointer is fine, | 969 // Show that we can add a constant to the stack pointer is fine, |
934 // so long as we follow it with a mask instruction. | 970 // so long as we follow it with a mask instruction. |
935 static const arm_inst sp_inst[] = { | 971 static const arm_inst sp_inst[] = { |
936 0xe28dd00c, // add sp, sp, #12 | 972 0xe28dd00c, // add sp, sp, #12 |
937 0xe3cdd2ff, // bic sp, sp, #-268435441 ; 0xf000000f | 973 0xe3cdd2ff, // bic sp, sp, #-268435441 ; 0xf000000f |
938 }; | 974 }; |
939 validation_should_pass(sp_inst, | 975 validation_should_pass(sp_inst, |
940 NACL_ARRAY_SIZE(sp_inst), | 976 NACL_ARRAY_SIZE(sp_inst), |
941 kDefaultBaseAddr, | 977 kDefaultBaseAddr, |
(...skipping 209 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1151 // when pointing at the head. | 1187 // when pointing at the head. |
1152 // Note that we don't actually put anything malicious in the literal pool, | 1188 // Note that we don't actually put anything malicious in the literal pool, |
1153 // and we still shouldn't be able to jump in the middle of it. | 1189 // and we still shouldn't be able to jump in the middle of it. |
1154 const size_t bundle_pos = _validator.InstructionsPerBundle(); | 1190 const size_t bundle_pos = _validator.InstructionsPerBundle(); |
1155 vector<arm_inst> code(3 * bundle_pos); | 1191 vector<arm_inst> code(3 * bundle_pos); |
1156 for (size_t b_pos = 0; b_pos < code.size(); ++b_pos) { | 1192 for (size_t b_pos = 0; b_pos < code.size(); ++b_pos) { |
1157 if ((bundle_pos <= b_pos) && (b_pos < bundle_pos * 2)) { | 1193 if ((bundle_pos <= b_pos) && (b_pos < bundle_pos * 2)) { |
1158 // Don't try putting the branch in the middle of the literal pool. | 1194 // Don't try putting the branch in the middle of the literal pool. |
1159 continue; | 1195 continue; |
1160 } | 1196 } |
1161 std::fill(code.begin(), code.end(), 0xE320F000); // NOP | 1197 std::fill(code.begin(), code.end(), kNop); |
1162 code[bundle_pos] = nacl_arm_dec::kLiteralPoolHead; | 1198 code[bundle_pos] = nacl_arm_dec::kLiteralPoolHead; |
1163 for (size_t b_target = 0; b_target < code.size(); ++b_target) { | 1199 for (size_t b_target = 0; b_target < code.size(); ++b_target) { |
1164 // PC reads as current instruction address plus 8 (e.g. two instructions | 1200 // PC reads as current instruction address plus 8 (e.g. two instructions |
1165 // ahead of b_pos). | 1201 // ahead of b_pos). |
1166 // imm24 is encoded with the bottom two bits zeroed out, which we | 1202 // imm24 is encoded with the bottom two bits zeroed out, which we |
1167 // implicitly do by working with instructions instead of bytes. | 1203 // implicitly do by working with instructions instead of bytes. |
1168 uint32_t imm24 = (b_target - b_pos - 2) & 0x00FFFFFF; | 1204 uint32_t imm24 = (b_target - b_pos - 2) & 0x00FFFFFF; |
1169 code[b_pos] = 0xEA000000 | imm24; // B #imm | 1205 code[b_pos] = 0xEA000000 | imm24; // B #imm |
1170 bool target_in_pool = (bundle_pos < b_target) && | 1206 bool target_in_pool = (bundle_pos < b_target) && |
1171 (b_target < bundle_pos * 2); // Excluding head. | 1207 (b_target < bundle_pos * 2); // Excluding head. |
(...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1292 } | 1328 } |
1293 } | 1329 } |
1294 | 1330 |
1295 }; // anonymous namespace | 1331 }; // anonymous namespace |
1296 | 1332 |
1297 // Test driver function. | 1333 // Test driver function. |
1298 int main(int argc, char *argv[]) { | 1334 int main(int argc, char *argv[]) { |
1299 testing::InitGoogleTest(&argc, argv); | 1335 testing::InitGoogleTest(&argc, argv); |
1300 return RUN_ALL_TESTS(); | 1336 return RUN_ALL_TESTS(); |
1301 } | 1337 } |
OLD | NEW |