| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright 2009 The Native Client Authors. All rights reserved. | 2 * Copyright (c) 2011 The Native Client Authors. All rights reserved. |
| 3 * Use of this source code is governed by a BSD-style license that can | 3 * Use of this source code is governed by a BSD-style license that can be |
| 4 * be found in the LICENSE file. | 4 * found in the LICENSE file. |
| 5 * Copyright 2009, Google Inc. | |
| 6 */ | 5 */ |
| 7 | 6 |
| 8 #include "native_client/src/trusted/service_runtime/nacl_config.h" | 7 #include "native_client/src/trusted/service_runtime/nacl_config.h" |
| 9 #include "native_client/src/trusted/validator_arm/validator.h" | 8 #include "native_client/src/trusted/validator_arm/validator.h" |
| 10 #include "native_client/src/include/nacl_macros.h" | 9 #include "native_client/src/include/nacl_macros.h" |
| 11 | 10 |
| 12 using nacl_arm_dec::Instruction; | 11 using nacl_arm_dec::Instruction; |
| 13 using nacl_arm_dec::ClassDecoder; | 12 using nacl_arm_dec::ClassDecoder; |
| 14 using nacl_arm_dec::Register; | 13 using nacl_arm_dec::Register; |
| 15 using nacl_arm_dec::RegisterList; | 14 using nacl_arm_dec::RegisterList; |
| (...skipping 16 matching lines...) Expand all Loading... |
| 32 enum PatternMatch { | 31 enum PatternMatch { |
| 33 // The pattern does not apply to the instructions it was given. | 32 // The pattern does not apply to the instructions it was given. |
| 34 NO_MATCH, | 33 NO_MATCH, |
| 35 // The pattern matches, and is safe; do not allow jumps to split it. | 34 // The pattern matches, and is safe; do not allow jumps to split it. |
| 36 PATTERN_SAFE, | 35 PATTERN_SAFE, |
| 37 // The pattern matches, and has detected a problem. | 36 // The pattern matches, and has detected a problem. |
| 38 PATTERN_UNSAFE | 37 PATTERN_UNSAFE |
| 39 }; | 38 }; |
| 40 | 39 |
| 41 /* | 40 /* |
| 42 * Ensures that all stores use a safe base address. A base address is safe if | 41 * Ensures that all loads/stores use a safe base address. A base address is |
| 43 * it | 42 * safe if it |
| 44 * 1. Has specific bits masked off by its immediate predecessor, or | 43 * 1. Has specific bits masked off by its immediate predecessor, or |
| 45 * 2. Is predicated on those bits being clear, as tested by its immediate | 44 * 2. Is predicated on those bits being clear, as tested by its immediate |
| 46 * predecessor, or | 45 * predecessor, or |
| 47 * 3. Is in a register defined as always containing a safe address. | 46 * 3. Is in a register defined as always containing a safe address. |
| 48 * | 47 * |
| 49 * This pattern concerns itself with case #1, early-exiting if it finds #2. | 48 * This pattern concerns itself with case #1, early-exiting if it finds #2. |
| 50 */ | 49 */ |
| 51 static PatternMatch check_store_mask(const SfiValidator &sfi, | 50 static PatternMatch check_loadstore_mask(const SfiValidator &sfi, |
| 52 const DecodedInstruction &first, | 51 const DecodedInstruction &first, |
| 53 const DecodedInstruction &second, | 52 const DecodedInstruction &second, |
| 54 ProblemSink *out) { | 53 ProblemSink *out) { |
| 55 if (second.base_address_register() == kRegisterNone /* not a store */ | 54 if (second.base_address_register() == kRegisterNone /* not a load/store */ |
| 56 || sfi.is_data_address_register(second.base_address_register())) { | 55 || sfi.is_data_address_register(second.base_address_register())) { |
| 57 return NO_MATCH; | 56 return NO_MATCH; |
| 58 } | 57 } |
| 59 | 58 |
| 59 if (second.base_address_register() == kRegisterPc |
| 60 && second.offset_is_immediate()) { |
| 61 /* PC + immediate addressing is always safe. */ |
| 62 return PATTERN_SAFE; |
| 63 } |
| 64 |
| 60 if (first.defines(second.base_address_register()) | 65 if (first.defines(second.base_address_register()) |
| 61 && first.clears_bits(sfi.data_address_mask()) | 66 && first.clears_bits(sfi.data_address_mask()) |
| 62 && first.always_precedes(second)) { | 67 && first.always_precedes(second)) { |
| 63 return PATTERN_SAFE; | 68 return PATTERN_SAFE; |
| 64 } | 69 } |
| 65 | 70 |
| 66 if (first.sets_Z_if_bits_clear(second.base_address_register(), | 71 if (first.sets_Z_if_bits_clear(second.base_address_register(), |
| 67 sfi.data_address_mask()) | 72 sfi.data_address_mask()) |
| 68 && second.is_conditional_on(first)) { | 73 && second.is_conditional_on(first)) { |
| 69 return PATTERN_SAFE; | 74 return PATTERN_SAFE; |
| 70 } | 75 } |
| 71 | 76 |
| 72 out->report_problem(second.addr(), second.safety(), kProblemUnsafeStore); | 77 out->report_problem(second.addr(), second.safety(), kProblemUnsafeLoadStore); |
| 73 return PATTERN_UNSAFE; | 78 return PATTERN_UNSAFE; |
| 74 } | 79 } |
| 75 | 80 |
| 76 /* | 81 /* |
| 77 * Ensures that all indirect branches use a safe destination address. A | 82 * Ensures that all indirect branches use a safe destination address. A |
| 78 * destination address is safe if it has specific bits masked off by its | 83 * destination address is safe if it has specific bits masked off by its |
| 79 * immediate predecessor. | 84 * immediate predecessor. |
| 80 */ | 85 */ |
| 81 static PatternMatch check_branch_mask(const SfiValidator &sfi, | 86 static PatternMatch check_branch_mask(const SfiValidator &sfi, |
| 82 const DecodedInstruction &first, | 87 const DecodedInstruction &first, |
| (...skipping 283 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 366 bool SfiValidator::apply_patterns(const DecodedInstruction &first, | 371 bool SfiValidator::apply_patterns(const DecodedInstruction &first, |
| 367 const DecodedInstruction &second, AddressSet *critical, ProblemSink *out) { | 372 const DecodedInstruction &second, AddressSet *critical, ProblemSink *out) { |
| 368 // Type for two-instruction pattern functions | 373 // Type for two-instruction pattern functions |
| 369 typedef PatternMatch (*TwoInstPattern)(const SfiValidator &, | 374 typedef PatternMatch (*TwoInstPattern)(const SfiValidator &, |
| 370 const DecodedInstruction &first, | 375 const DecodedInstruction &first, |
| 371 const DecodedInstruction &second, | 376 const DecodedInstruction &second, |
| 372 ProblemSink *out); | 377 ProblemSink *out); |
| 373 | 378 |
| 374 // The list of patterns -- defined in static functions up top. | 379 // The list of patterns -- defined in static functions up top. |
| 375 static const TwoInstPattern two_inst_patterns[] = { | 380 static const TwoInstPattern two_inst_patterns[] = { |
| 376 &check_store_mask, | 381 &check_loadstore_mask, |
| 377 &check_branch_mask, | 382 &check_branch_mask, |
| 378 &check_data_register_update, | 383 &check_data_register_update, |
| 379 }; | 384 }; |
| 380 | 385 |
| 381 bool complete_success = true; | 386 bool complete_success = true; |
| 382 | 387 |
| 383 for (uint32_t i = 0; i < NACL_ARRAY_SIZE(two_inst_patterns); i++) { | 388 for (uint32_t i = 0; i < NACL_ARRAY_SIZE(two_inst_patterns); i++) { |
| 384 PatternMatch r = two_inst_patterns[i](*this, first, second, out); | 389 PatternMatch r = two_inst_patterns[i](*this, first, second, out); |
| 385 switch (r) { | 390 switch (r) { |
| 386 case NO_MATCH: break; | 391 case NO_MATCH: break; |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 427 Instruction inst, | 432 Instruction inst, |
| 428 const ClassDecoder &decoder) | 433 const ClassDecoder &decoder) |
| 429 : vaddr_(vaddr), | 434 : vaddr_(vaddr), |
| 430 inst_(inst), | 435 inst_(inst), |
| 431 decoder_(&decoder), | 436 decoder_(&decoder), |
| 432 safety_(decoder.safety(inst_)), | 437 safety_(decoder.safety(inst_)), |
| 433 defs_(decoder.defs(inst_)) | 438 defs_(decoder.defs(inst_)) |
| 434 {} | 439 {} |
| 435 | 440 |
| 436 } // namespace | 441 } // namespace |
| OLD | NEW |