Chromium Code Reviews| 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, #0xf000000f | |
|
Mark Seaborn
2012/11/13 00:30:18
Why not 0xc0000000 for the mask? Bear in mind htt
JF
2012/11/13 00:49:42
There's a bunch of other code below that does the
| |
| 955 if (i == _validator.InstructionsPerBundle() - 1) { | |
| 956 validation_should_fail(&code[0], code.size(), kDefaultBaseAddr, | |
|
Mark Seaborn
2012/11/13 00:30:18
Can you comment here that this is not actually uns
JF
2012/11/13 00:49:42
Done.
| |
| 957 "masked SP update straddling a bundle boundary"); | |
| 958 } else { | |
| 959 validation_should_pass(&code[0], code.size(), kDefaultBaseAddr, | |
| 960 "masked SP update"); | |
| 961 } | |
| 962 } | |
| 963 } | |
| 964 | |
| 932 TEST_F(ValidatorTests, AddConstToSpTest) { | 965 TEST_F(ValidatorTests, AddConstToSpTest) { |
| 933 // Show that we can add a constant to the stack pointer is fine, | 966 // Show that we can add a constant to the stack pointer is fine, |
| 934 // so long as we follow it with a mask instruction. | 967 // so long as we follow it with a mask instruction. |
| 935 static const arm_inst sp_inst[] = { | 968 static const arm_inst sp_inst[] = { |
| 936 0xe28dd00c, // add sp, sp, #12 | 969 0xe28dd00c, // add sp, sp, #12 |
| 937 0xe3cdd2ff, // bic sp, sp, #-268435441 ; 0xf000000f | 970 0xe3cdd2ff, // bic sp, sp, #-268435441 ; 0xf000000f |
| 938 }; | 971 }; |
| 939 validation_should_pass(sp_inst, | 972 validation_should_pass(sp_inst, |
| 940 NACL_ARRAY_SIZE(sp_inst), | 973 NACL_ARRAY_SIZE(sp_inst), |
| 941 kDefaultBaseAddr, | 974 kDefaultBaseAddr, |
| (...skipping 209 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1151 // when pointing at the head. | 1184 // when pointing at the head. |
| 1152 // Note that we don't actually put anything malicious in the literal pool, | 1185 // 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. | 1186 // and we still shouldn't be able to jump in the middle of it. |
| 1154 const size_t bundle_pos = _validator.InstructionsPerBundle(); | 1187 const size_t bundle_pos = _validator.InstructionsPerBundle(); |
| 1155 vector<arm_inst> code(3 * bundle_pos); | 1188 vector<arm_inst> code(3 * bundle_pos); |
| 1156 for (size_t b_pos = 0; b_pos < code.size(); ++b_pos) { | 1189 for (size_t b_pos = 0; b_pos < code.size(); ++b_pos) { |
| 1157 if ((bundle_pos <= b_pos) && (b_pos < bundle_pos * 2)) { | 1190 if ((bundle_pos <= b_pos) && (b_pos < bundle_pos * 2)) { |
| 1158 // Don't try putting the branch in the middle of the literal pool. | 1191 // Don't try putting the branch in the middle of the literal pool. |
| 1159 continue; | 1192 continue; |
| 1160 } | 1193 } |
| 1161 std::fill(code.begin(), code.end(), 0xE320F000); // NOP | 1194 std::fill(code.begin(), code.end(), kNop); |
| 1162 code[bundle_pos] = nacl_arm_dec::kLiteralPoolHead; | 1195 code[bundle_pos] = nacl_arm_dec::kLiteralPoolHead; |
| 1163 for (size_t b_target = 0; b_target < code.size(); ++b_target) { | 1196 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 | 1197 // PC reads as current instruction address plus 8 (e.g. two instructions |
| 1165 // ahead of b_pos). | 1198 // ahead of b_pos). |
| 1166 // imm24 is encoded with the bottom two bits zeroed out, which we | 1199 // imm24 is encoded with the bottom two bits zeroed out, which we |
| 1167 // implicitly do by working with instructions instead of bytes. | 1200 // implicitly do by working with instructions instead of bytes. |
| 1168 uint32_t imm24 = (b_target - b_pos - 2) & 0x00FFFFFF; | 1201 uint32_t imm24 = (b_target - b_pos - 2) & 0x00FFFFFF; |
| 1169 code[b_pos] = 0xEA000000 | imm24; // B #imm | 1202 code[b_pos] = 0xEA000000 | imm24; // B #imm |
| 1170 bool target_in_pool = (bundle_pos < b_target) && | 1203 bool target_in_pool = (bundle_pos < b_target) && |
| 1171 (b_target < bundle_pos * 2); // Excluding head. | 1204 (b_target < bundle_pos * 2); // Excluding head. |
| (...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1292 } | 1325 } |
| 1293 } | 1326 } |
| 1294 | 1327 |
| 1295 }; // anonymous namespace | 1328 }; // anonymous namespace |
| 1296 | 1329 |
| 1297 // Test driver function. | 1330 // Test driver function. |
| 1298 int main(int argc, char *argv[]) { | 1331 int main(int argc, char *argv[]) { |
| 1299 testing::InitGoogleTest(&argc, argv); | 1332 testing::InitGoogleTest(&argc, argv); |
| 1300 return RUN_ALL_TESTS(); | 1333 return RUN_ALL_TESTS(); |
| 1301 } | 1334 } |
| OLD | NEW |