Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 /* | 1 /* |
| 2 * Copyright 2009 The Native Client Authors. All rights reserved. | 2 * Copyright 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 |
| 4 * be found in the LICENSE file. | 4 * be found in the LICENSE file. |
| 5 * Copyright 2009, Google Inc. | 5 * Copyright 2011, Google Inc. |
| 6 */ | 6 */ |
| 7 | 7 |
| 8 #ifndef NATIVE_CLIENT_SRC_TRUSTED_VALIDATOR_ARM_V2_VALIDATOR_H | 8 #ifndef NATIVE_CLIENT_SRC_TRUSTED_VALIDATOR_ARM_V2_VALIDATOR_H |
| 9 #define NATIVE_CLIENT_SRC_TRUSTED_VALIDATOR_ARM_V2_VALIDATOR_H | 9 #define NATIVE_CLIENT_SRC_TRUSTED_VALIDATOR_ARM_V2_VALIDATOR_H |
| 10 | 10 |
| 11 /* | 11 /* |
| 12 * MRM DEBUG Header, clean this out | |
| 13 */ | |
| 14 #include <stdio.h> | |
| 15 | |
| 16 /* | |
| 12 * The SFI validator, and some utility classes it uses. | 17 * The SFI validator, and some utility classes it uses. |
| 13 */ | 18 */ |
| 14 | 19 |
| 15 #include <stdint.h> | 20 #include <stdint.h> |
| 16 #include <stdlib.h> | 21 #include <stdlib.h> |
| 17 #include <vector> | 22 #include <vector> |
| 18 | 23 |
| 19 #include "native_client/src/include/nacl_string.h" | 24 #include "native_client/src/include/nacl_string.h" |
| 20 #include "native_client/src/trusted/validator_arm/address_set.h" | 25 #include "native_client/src/trusted/validator_arm/address_set.h" |
| 21 #include "native_client/src/trusted/validator_arm/decode.h" | 26 #include "native_client/src/trusted/validator_arm/decode.h" |
| (...skipping 22 matching lines...) Expand all Loading... | |
| 44 Bundle(uint32_t virtual_base, uint32_t size_bytes) | 49 Bundle(uint32_t virtual_base, uint32_t size_bytes) |
| 45 : virtual_base_(virtual_base), size_(size_bytes) {} | 50 : virtual_base_(virtual_base), size_(size_bytes) {} |
| 46 | 51 |
| 47 uint32_t begin_addr() const { return virtual_base_; } | 52 uint32_t begin_addr() const { return virtual_base_; } |
| 48 uint32_t end_addr() const { return virtual_base_ + size_; } | 53 uint32_t end_addr() const { return virtual_base_ + size_; } |
| 49 | 54 |
| 50 bool operator!=(const Bundle &other) const { | 55 bool operator!=(const Bundle &other) const { |
| 51 // Note that all Bundles are currently assumed to be the same size. | 56 // Note that all Bundles are currently assumed to be the same size. |
| 52 return virtual_base_ != other.virtual_base_; | 57 return virtual_base_ != other.virtual_base_; |
| 53 } | 58 } |
| 59 bool operator==(const Bundle &other) const { | |
| 60 return virtual_base_ == other.virtual_base_; | |
| 61 } | |
| 54 | 62 |
| 55 private: | 63 private: |
| 56 uint32_t virtual_base_; | 64 uint32_t virtual_base_; |
| 57 uint32_t size_; | 65 uint32_t size_; |
| 58 }; | 66 }; |
| 59 | 67 |
| 68 class SfiValidator; | |
| 69 | |
| 70 // A possible result from a validator pattern. | |
| 71 enum PatternMatchMode { | |
| 72 // The pattern does not apply to the instructions it was given. | |
| 73 NO_MATCH_MODE, | |
| 74 // The pattern matches, and is safe; do not allow jumps to split it. | |
| 75 PATTERN_SAFE_MODE, | |
| 76 // The pattern matches, and has detected a problem. | |
| 77 PATTERN_UNSAFE_MODE | |
| 78 }; | |
| 79 | |
| 80 // Full result from a pattern. Describes whether it matched, and if it did, | |
| 81 // specifies how long the matching pattern was. | |
| 82 typedef struct { | |
| 83 PatternMatchMode pm_mode; | |
| 84 int8_t size; | |
| 85 } PatternMatch; | |
| 86 | |
| 87 /* Pattern matching type */ | |
| 88 typedef PatternMatch (*Pattern)(const SfiValidator &, | |
| 89 DecodedInstruction insns[], | |
| 90 ProblemSink *out); | |
| 60 | 91 |
| 61 /* | 92 /* |
| 62 * The SFI validator itself. The validator is controlled by the following | 93 * The SFI validator itself. The validator is controlled by the following |
| 63 * inputs: | 94 * inputs: |
| 64 * bytes_per_bundle: the number of bytes in each bundle of instructions. | 95 * bytes_per_bundle: the number of bytes in each bundle of instructions. |
| 65 * Currently this tends to be 16, but we've evaluated alternatives. | 96 * Currently this tends to be 16, but we've evaluated alternatives. |
| 66 * code_region_bytes: number of bytes in the code region, starting at address | 97 * code_region_bytes: number of bytes in the code region, starting at address |
| 67 * 0 and including the trampolines, etc. Must be a power of two. | 98 * 0 and including the trampolines, etc. Must be a power of two. |
| 68 * data_region_bits: number of bytes in the data region, starting at address | 99 * data_region_bits: number of bytes in the data region, starting at address |
| 69 * 0 and including the code region. Must be a power of two. | 100 * 0 and including the code region. Must be a power of two. |
| 70 * read_only_registers: registers that untrusted code must not alter (but may | 101 * read_only_registers: registers that untrusted code must not alter (but may |
| 71 * read). This currently applies to r9, where we store some thread state. | 102 * read). This currently applies to r9, where we store some thread state. |
| 72 * data_address_registers: registers that must contain a valid data-region | 103 * data_address_registers: registers that must contain a valid data-region |
| 73 * address at all times. This currently applies to the stack pointer, but | 104 * address at all times. This currently applies to the stack pointer, but |
| 74 * could be extended to include a frame pointer for C-like languages. | 105 * could be extended to include a frame pointer for C-like languages. |
| 75 * | 106 * |
| 76 * The values of these inputs will typically be taken from the headers of | 107 * The values of these inputs will typically be taken from the headers of |
| 77 * untrusted code -- either by the ABI version they indicate, or (perhaps in | 108 * untrusted code -- either by the ABI version they indicate, or (perhaps in |
| 78 * the future) explicit indicators of what SFI model they follow. | 109 * the future) explicit indicators of what SFI model they follow. |
| 79 */ | 110 */ |
| 80 class SfiValidator { | 111 class SfiValidator { |
| 81 public: | 112 public: |
| 82 SfiValidator(uint32_t bytes_per_bundle, | 113 SfiValidator(uint32_t bytes_per_bundle, |
| 83 uint32_t code_region_bytes, | 114 uint32_t code_region_bytes, |
| 84 uint32_t data_region_bytes, | 115 uint32_t data_region_bytes, |
| 85 nacl_arm_dec::RegisterList read_only_registers, | 116 nacl_arm_dec::RegisterList read_only_registers, |
| 86 nacl_arm_dec::RegisterList data_address_registers); | 117 nacl_arm_dec::RegisterList data_address_registers, |
| 118 uint8_t thumb); | |
| 87 | 119 |
| 88 /* | 120 /* |
| 89 * The main validator entry point. Validates the provided CodeSegments, | 121 * The main validator entry point. Validates the provided CodeSegments, |
| 90 * which must be in sorted order, reporting any problems through the | 122 * which must be in sorted order, reporting any problems through the |
| 91 * ProblemSink. | 123 * ProblemSink. |
| 92 * | 124 * |
| 93 * Returns true iff no problems were found. | 125 * Returns true iff no problems were found. |
| 94 */ | 126 */ |
| 95 bool validate(const std::vector<CodeSegment> &, ProblemSink *out); | 127 bool validate(const std::vector<CodeSegment> &, ProblemSink *out); |
| 96 | 128 |
| 97 /* | 129 /* |
| 98 * Checks whether the given Register always holds a valid data region address. | 130 * Checks whether the given Register always holds a valid data region address. |
| 99 * This implies that the register is safe to use in unguarded stores. | 131 * This implies that the register is safe to use in unguarded stores. |
| 100 */ | 132 */ |
| 101 bool is_data_address_register(nacl_arm_dec::Register) const; | 133 bool is_data_address_register(nacl_arm_dec::Register) const; |
| 102 | 134 |
| 103 uint32_t data_address_mask() const { return data_address_mask_; } | 135 uint32_t data_address_mask() const { return data_address_mask_; } |
| 104 uint32_t code_address_mask() const { return code_address_mask_; } | 136 uint32_t code_address_mask() const { return code_address_mask_; } |
| 137 uint32_t code_address_ormask() const { return code_address_ormask_; } | |
| 105 | 138 |
| 106 nacl_arm_dec::RegisterList read_only_registers() const { | 139 nacl_arm_dec::RegisterList read_only_registers() const { |
| 107 return read_only_registers_; | 140 return read_only_registers_; |
| 108 } | 141 } |
| 109 nacl_arm_dec::RegisterList data_address_registers() const { | 142 nacl_arm_dec::RegisterList data_address_registers() const { |
| 110 return data_address_registers_; | 143 return data_address_registers_; |
| 111 } | 144 } |
| 112 | 145 |
| 113 // Returns the Bundle containing a given address. | 146 // Returns the Bundle containing a given address. |
| 114 const Bundle bundle_for_address(uint32_t) const; | 147 const Bundle bundle_for_address(uint32_t) const; |
| 115 | 148 |
| 116 /* | 149 /* |
| 117 * Change masks: this is useful for debugging and cannot be completely | 150 * Change masks: this is useful for debugging and cannot be completely |
| 118 * controlled with constructor arguments | 151 * controlled with constructor arguments |
| 119 */ | 152 */ |
| 120 void change_masks(uint32_t code_address_mask, uint32_t data_address_mask) { | 153 void change_masks(uint32_t code_address_mask, |
| 121 code_address_mask_ = code_address_mask; | 154 uint32_t code_address_ormask, |
| 122 data_address_mask_ = data_address_mask; | 155 uint32_t data_address_mask) { |
| 156 code_address_mask_ = code_address_mask; | |
| 157 code_address_ormask_ = code_address_ormask; | |
| 158 data_address_mask_ = data_address_mask; | |
| 123 } | 159 } |
| 124 | 160 |
| 125 private: | 161 private: |
| 126 bool is_bundle_head(uint32_t address) const; | 162 bool is_bundle_head(uint32_t address) const; |
| 127 | 163 |
| 128 /* | 164 /* |
| 129 * Validates a straight-line execution of the code, applying patterns. This | 165 * Validates a straight-line execution of the code, applying patterns. This |
| 130 * is the first validation pass, which fills out the AddressSets for | 166 * is the first validation pass, which fills out the AddressSets for |
| 131 * consumption by later analyses. | 167 * consumption by later analyses. |
| 132 * branches: gets filled in with the address of every direct branch. | 168 * branches: gets filled in with the address of every direct branch. |
| 133 * critical: gets filled in with every address that isn't safe to jump to, | 169 * critical: gets filled in with every address that isn't safe to jump to, |
| 134 * because it would split an otherwise-safe pseudo-op. | 170 * because it would split an otherwise-safe pseudo-op. |
| 135 * | 171 * |
| 136 * Returns true iff no problems were found. | 172 * Returns true iff no problems were found. |
| 137 */ | 173 */ |
| 138 bool validate_fallthrough(const CodeSegment &, ProblemSink *, | 174 bool validate_fallthrough(const CodeSegment &, ProblemSink *, |
| 139 AddressSet *branches, AddressSet *critical); | 175 AddressSet *branches, AddressSet *critical); |
| 140 | 176 |
| 141 /* | 177 /* |
| 142 * Factor of validate_fallthrough, above. Checks a single instruction using | |
| 143 * the instruction patterns defined in the .cc file, with two possible | |
| 144 * results: | |
| 145 * 1. No patterns matched, or all were safe: nothing happens. | |
| 146 * 2. Patterns matched and were unsafe: problems get sent to 'out'. | |
| 147 */ | |
| 148 bool apply_patterns(const DecodedInstruction &, ProblemSink *out); | |
| 149 | |
| 150 /* | |
| 151 * Factor of validate_fallthrough, above. Checks a pair of instructions using | 178 * Factor of validate_fallthrough, above. Checks a pair of instructions using |
| 152 * the instruction patterns defined in the .cc file, with three possible | 179 * the instruction patterns defined in the .cc file, with three possible |
| 153 * results: | 180 * results: |
| 154 * 1. No patterns matched: nothing happens. | 181 * 1. No patterns matched: nothing happens. |
| 155 * 2. Patterns matched and were safe: the addresses are filled into | 182 * 2. Patterns matched and were safe: the addresses are filled into |
| 156 * 'critical' for use by the second pass. | 183 * 'critical' for use by the second pass. |
| 157 * 3. Patterns matched and were unsafe: problems get sent to 'out'. | 184 * 3. Patterns matched and were unsafe: problems get sent to 'out'. |
| 158 */ | 185 */ |
| 159 bool apply_patterns(const DecodedInstruction &first, | 186 bool apply_patterns(DecodedInstruction insns[], |
| 160 const DecodedInstruction &second, AddressSet *critical, ProblemSink *out); | 187 const Pattern patterns[], unsigned int nPatterns, |
| 188 AddressSet *critical, ProblemSink *out); | |
| 161 | 189 |
| 162 /* | 190 /* |
| 163 * Validates all branches found by a previous pass, checking destinations. | 191 * Validates all branches found by a previous pass, checking destinations. |
| 164 * Returns true iff no problems were found. | 192 * Returns true iff no problems were found. |
| 165 */ | 193 */ |
| 166 bool validate_branches(const std::vector<CodeSegment> &, | 194 bool validate_branches(const std::vector<CodeSegment> &, |
| 167 const AddressSet &branches, const AddressSet &critical, | 195 const AddressSet &branches, const AddressSet &critical, |
| 168 ProblemSink *); | 196 ProblemSink *); |
| 169 | 197 |
| 170 | 198 |
| 171 uint32_t bytes_per_bundle_; | 199 uint32_t bytes_per_bundle_; |
| 172 uint32_t data_address_mask_; | 200 uint32_t data_address_mask_; |
| 173 uint32_t code_address_mask_; | 201 uint32_t code_address_mask_; |
| 202 uint32_t code_address_ormask_; | |
| 174 uint32_t code_region_bytes_; | 203 uint32_t code_region_bytes_; |
| 175 // Registers which cannot be modified by untrusted code. | 204 // Registers which cannot be modified by untrusted code. |
| 176 nacl_arm_dec::RegisterList read_only_registers_; | 205 nacl_arm_dec::RegisterList read_only_registers_; |
| 177 // Registers which must always contain a valid data region address. | 206 // Registers which must always contain a valid data region address. |
| 178 nacl_arm_dec::RegisterList data_address_registers_; | 207 nacl_arm_dec::RegisterList data_address_registers_; |
| 208 bool thumb_; | |
| 179 const nacl_arm_dec::DecoderState *decode_state_; | 209 const nacl_arm_dec::DecoderState *decode_state_; |
| 180 }; | 210 }; |
| 181 | 211 |
| 212 /* | |
| 213 * Defines the maximal pattern size to be made available to the pattern | |
| 214 * matcher. | |
| 215 * I know 5 seems a little big, but it is required for the IT matcher. | |
| 216 * 16 is a hack, it is a magic number to make sure that the second pattern | |
|
Karl
2011/08/30 19:53:52
What 16?
| |
| 217 * matching phase interacts properly with breakpoint. | |
| 218 */ | |
| 219 const uint8_t kMaxPattern = 5; | |
| 182 | 220 |
| 183 /* | 221 /* |
| 184 * A facade that combines an Instruction with its address and a ClassDecoder. | 222 * A facade that combines an Instruction with its address and a ClassDecoder. |
| 185 * This makes the patterns substantially easier to write and read than managing | 223 * This makes the patterns substantially easier to write and read than managing |
| 186 * all three variables separately. | 224 * all three variables separately. |
| 187 * | 225 * |
| 188 * ClassDecoders do all decoding on-demand, with no caching. DecodedInstruction | 226 * ClassDecoders do all decoding on-demand, with no caching. DecodedInstruction |
| 189 * has knowledge of the validator, and pairs a ClassDecoder with a constant | 227 * has knowledge of the validator, and pairs a ClassDecoder with a constant |
| 190 * Instruction -- so it can cache commonly used values, and does. Caching | 228 * Instruction -- so it can cache commonly used values, and does. Caching |
| 191 * safety and defs doubles validator performance. Add other values only | 229 * safety and defs doubles validator performance. Add other values only |
| 192 * under guidance of a profiler. | 230 * under guidance of a profiler. |
| 193 */ | 231 */ |
| 194 class DecodedInstruction { | 232 class DecodedInstruction { |
| 195 public: | 233 public: |
| 196 DecodedInstruction(uint32_t vaddr, nacl_arm_dec::Instruction inst, | 234 DecodedInstruction(uint32_t vaddr, nacl_arm_dec::Instruction inst, |
| 197 const nacl_arm_dec::ClassDecoder &decoder); | 235 const nacl_arm_dec::ClassDecoder &decoder); |
| 198 // We permit the default copy ctor and assignment operator. | 236 // We permit the default copy ctor and assignment operator. |
| 199 | 237 |
| 200 uint32_t addr() const { return vaddr_; } | 238 uint32_t addr() const { return vaddr_; } |
| 201 | 239 |
| 202 /* | 240 /* |
| 203 * Checks that 'this' always precedes 'other' -- meaning that if 'other' | 241 * Checks that 'this' always precedes 'other' -- meaning that if 'other' |
| 204 * executes, 'this' is guaranteed to have executed. This is important if | 242 * executes, 'this' is guaranteed to have executed. This is important if |
| 205 * 'this' produces a sandboxed value that 'other' must consume. | 243 * 'this' produces a sandboxed value that 'other' must consume. |
| 206 * | 244 * |
| 207 * Note that this function can't see the bundle size, so this result does not | 245 * Note that this function can't see the bundle size, so this result does not |
| 208 * take it into account. The SfiValidator reasons on this separately. | 246 * take it into account. The SfiValidator reasons on this separately. |
| 209 */ | 247 */ |
| 210 bool always_precedes(const DecodedInstruction &other) const { | 248 bool always_precedes(const DecodedInstruction &other) const { |
| 211 return inst_.condition() == other.inst_.condition(); | 249 return condition() == other.condition(); |
| 212 } | 250 } |
| 213 | 251 // TODO(mrm) These predicates will all be able to lie without an IT predicator |
| 214 /* | 252 /* |
| 215 * Checks that 'this' always follows 'other' -- meaning that if 'other' | 253 * Checks that 'this' always follows 'other' -- meaning that if 'other' |
| 216 * executes, 'this' is guaranteed to follow. This is important if 'other' | 254 * executes, 'this' is guaranteed to follow. This is important if 'other' |
| 217 * produces an unsafe value that 'this' fixes before it can leak out. | 255 * produces an unsafe value that 'this' fixes before it can leak out. |
| 218 * | 256 * |
| 219 * Note that this function can't see the bundle size, so this result does not | 257 * Note that this function can't see the bundle size, so this result does not |
| 220 * take it into account. The SfiValidator reasons on this separately. | 258 * take it into account. The SfiValidator reasons on this separately. |
| 221 */ | 259 */ |
| 222 bool always_follows(const DecodedInstruction &other) const { | 260 bool always_follows(const DecodedInstruction &other) const { |
| 223 return inst_.condition() == other.inst_.condition() | 261 return condition() == condition() |
|
Karl
2011/08/30 19:53:52
Why compare condition to itself?
| |
| 224 && !other.defines(nacl_arm_dec::kRegisterFlags); | 262 && !other.defines(nacl_arm_dec::kRegisterFlags); |
| 225 } | 263 } |
| 226 | 264 |
| 227 /* | 265 /* |
| 228 * Checks that the execution of 'this' is conditional on the test result | 266 * Checks that the execution of 'this' is conditional on the test result |
| 229 * (specifically, the Z flag being set) from 'other' -- which must be | 267 * (specifically, the Z flag being set) from 'other' -- which must be |
| 230 * adjacent for this simple check to be meaningful. | 268 * adjacent for this simple check to be meaningful. |
| 231 */ | 269 */ |
| 232 bool is_conditional_on(const DecodedInstruction &other) const { | 270 bool is_conditional_on(const DecodedInstruction &other) const { |
| 233 return inst_.condition() == nacl_arm_dec::Instruction::EQ | 271 return condition() == nacl_arm_dec::Instruction::EQ |
| 234 && other.inst_.condition() == nacl_arm_dec::Instruction::AL | 272 && other.condition() == nacl_arm_dec::Instruction::AL |
| 235 && other.defines(nacl_arm_dec::kRegisterFlags); | 273 && other.defines(nacl_arm_dec::kRegisterFlags); |
| 236 } | 274 } |
| 237 | 275 |
| 238 // The methods below mirror those on ClassDecoder, but are cached and cheap. | 276 // The methods below mirror those on ClassDecoder, but are cached and cheap. |
| 239 nacl_arm_dec::SafetyLevel safety() const { return safety_; } | 277 nacl_arm_dec::SafetyLevel safety() const { return safety_; } |
| 240 nacl_arm_dec::RegisterList defs() const { return defs_; } | 278 nacl_arm_dec::RegisterList defs() const { return defs_; } |
| 241 | 279 |
| 280 /* Passes through queries about the it status */ | |
| 281 nacl_arm_dec::ITCond it() const { | |
| 282 return decoder_->it_sequence(inst_); | |
| 283 } | |
| 284 | |
| 285 /* Passes through queries about it safety */ | |
| 286 nacl_arm_dec::ITSafety it_safe() const { | |
| 287 return decoder_->it_safe(inst_); | |
| 288 } | |
| 289 | |
| 290 // Calculates the size of the current instruction. It is here instead of | |
| 291 // ClassDecoder because it needs the vaddr. | |
| 292 nacl_arm_dec::Instruction::Condition condition() const { | |
| 293 if (vaddr_ & 1) { | |
| 294 if (condition_ != nacl_arm_dec::Instruction::UNCONDITIONAL) | |
| 295 return condition_; | |
| 296 return decoder_->condition(inst_); | |
| 297 } else { | |
| 298 return inst_.condition(); | |
| 299 } | |
| 300 } | |
| 301 uint8_t size() const { | |
| 302 if (vaddr_ & 1) { | |
| 303 switch (inst_.bits(15, 11)) { | |
| 304 case 0x1D: // 0b11101 | |
| 305 case 0x1E: // 0b11110 | |
| 306 case 0x1F: return 4; // 0b11111 | |
| 307 default: return 2; | |
| 308 } | |
| 309 } else { | |
| 310 return 4; | |
| 311 } | |
| 312 } | |
| 313 | |
| 242 // The methods below pull values from ClassDecoder on demand. | 314 // The methods below pull values from ClassDecoder on demand. |
| 243 bool is_relative_branch() const { | 315 bool is_relative_branch() const { |
| 244 return decoder_->is_relative_branch(inst_); | 316 return decoder_->is_relative_branch(inst_); |
| 245 } | 317 } |
| 246 | 318 |
| 247 const nacl_arm_dec::Register branch_target_register() const { | 319 const nacl_arm_dec::Register branch_target_register() const { |
| 248 return decoder_->branch_target_register(inst_); | 320 return decoder_->branch_target_register(inst_); |
| 249 } | 321 } |
| 250 | 322 |
| 251 bool is_literal_pool_head() const { | 323 bool is_literal_pool_head() const { |
| 252 return decoder_->is_literal_pool_head(inst_); | 324 return decoder_->is_literal_pool_head(inst_); |
| 253 } | 325 } |
| 254 | 326 |
| 255 uint32_t branch_target() const { | 327 uint32_t branch_target() const { |
| 256 return vaddr_ + decoder_->branch_target_offset(inst_); | 328 return vaddr_ + decoder_->branch_target_offset(inst_); |
| 257 } | 329 } |
| 258 | 330 |
| 259 const nacl_arm_dec::Register base_address_register() const { | 331 const nacl_arm_dec::Register base_address_register() const { |
| 260 return decoder_->base_address_register(inst_); | 332 return decoder_->base_address_register(inst_); |
| 261 } | 333 } |
| 262 | 334 |
| 335 bool sets_bits(uint32_t mask) const { | |
| 336 return decoder_->sets_bits(inst_, mask); | |
| 337 } | |
| 338 | |
| 263 bool clears_bits(uint32_t mask) const { | 339 bool clears_bits(uint32_t mask) const { |
| 264 return decoder_->clears_bits(inst_, mask); | 340 return decoder_->clears_bits(inst_, mask); |
| 265 } | 341 } |
| 266 | 342 |
| 267 bool sets_Z_if_bits_clear(nacl_arm_dec::Register r, uint32_t mask) const { | 343 bool sets_Z_if_bits_clear(nacl_arm_dec::Register r, uint32_t mask) const { |
| 268 return decoder_->sets_Z_if_bits_clear(inst_, r, mask); | 344 return decoder_->sets_Z_if_bits_clear(inst_, r, mask); |
| 269 } | 345 } |
| 270 | 346 |
| 271 nacl_arm_dec::RegisterList immediate_addressing_defs() const { | 347 nacl_arm_dec::RegisterList immediate_addressing_defs() const { |
| 272 return decoder_->immediate_addressing_defs(inst_); | 348 return decoder_->immediate_addressing_defs(inst_); |
| 273 } | 349 } |
| 274 | 350 |
| 275 // Some convenience methods, defined in terms of ClassDecoder: | 351 // Some convenience methods, defined in terms of ClassDecoder: |
| 276 bool defines(nacl_arm_dec::Register r) const { | 352 bool defines(nacl_arm_dec::Register r) const { |
| 277 return defs().contains_all(r); | 353 return defs().contains_all(r); |
| 278 } | 354 } |
| 279 | 355 |
| 280 bool defines_any(nacl_arm_dec::RegisterList rl) const { | 356 bool defines_any(nacl_arm_dec::RegisterList rl) const { |
| 281 return defs().contains_any(rl); | 357 return defs().contains_any(rl); |
| 282 } | 358 } |
| 283 | 359 |
| 284 bool defines_all(nacl_arm_dec::RegisterList rl) const { | 360 bool defines_all(nacl_arm_dec::RegisterList rl) const { |
| 285 return defs().contains_all(rl); | 361 return defs().contains_all(rl); |
| 286 } | 362 } |
| 287 | 363 |
| 364 /* | |
| 365 * Overrides the conditional for this insn, if thumb mode is active. | |
| 366 * It should be used only once on any given insn, as it should originate | |
| 367 * only from within an IT block, and IT blocks must not overlap. | |
| 368 */ | |
| 369 void set_condition(nacl_arm_dec::Instruction::Condition condition) { | |
| 370 condition_ = condition; | |
| 371 } | |
| 372 | |
| 288 private: | 373 private: |
| 289 uint32_t vaddr_; | 374 uint32_t vaddr_; |
| 290 nacl_arm_dec::Instruction inst_; | 375 nacl_arm_dec::Instruction inst_; |
| 291 const nacl_arm_dec::ClassDecoder *decoder_; | 376 const nacl_arm_dec::ClassDecoder *decoder_; |
| 292 | 377 |
| 293 nacl_arm_dec::SafetyLevel safety_; | 378 nacl_arm_dec::SafetyLevel safety_; |
| 294 nacl_arm_dec::RegisterList defs_; | 379 nacl_arm_dec::RegisterList defs_; |
| 380 nacl_arm_dec::Instruction::Condition condition_; | |
| 295 }; | 381 }; |
| 296 | 382 |
| 297 | 383 |
| 298 /* | 384 /* |
| 299 * Describes a memory region that contains executable code. Note that the code | 385 * Describes a memory region that contains executable code. Note that the code |
| 300 * need not live in its final location -- we pretend the code lives at the | 386 * need not live in its final location -- we pretend the code lives at the |
| 301 * provided start_addr, regardless of where the base pointer actually points. | 387 * provided start_addr, regardless of where the base pointer actually points. |
| 302 */ | 388 */ |
| 303 class CodeSegment { | 389 class CodeSegment { |
| 304 public: | 390 public: |
| 305 CodeSegment(const uint8_t *base, uint32_t start_addr, size_t size) | 391 CodeSegment(const uint8_t *base, uint32_t start_addr, size_t size) |
| 306 : base_(base), start_addr_(start_addr), size_(size) {} | 392 : base_(base), start_addr_(start_addr), size_(size) {} |
| 307 | 393 |
| 308 uint32_t begin_addr() const { return start_addr_; } | 394 uint32_t begin_addr() const { return start_addr_; } |
| 309 uint32_t end_addr() const { return start_addr_ + size_; } | 395 uint32_t end_addr() const { return start_addr_ + size_; } |
| 310 uint32_t size() const { return size_; } | 396 uint32_t size() const { return size_; } |
| 311 bool contains_address(uint32_t a) const { | 397 bool contains_address(uint32_t a) const { |
| 312 return (a >= begin_addr()) && (a < end_addr()); | 398 return (a >= begin_addr()) && (a < end_addr()); |
| 313 } | 399 } |
| 314 | 400 |
| 315 const nacl_arm_dec::Instruction operator[](uint32_t address) const { | 401 const nacl_arm_dec::Instruction operator[](uint32_t address) const { |
| 316 const uint8_t *element = &base_[address - start_addr_]; | 402 const uint8_t *element = &base_[address - start_addr_]; |
| 317 return nacl_arm_dec::Instruction( | 403 // Special case to allow addresses two from the end to be read |
| 318 *reinterpret_cast<const uint32_t *>(element)); | 404 if ((address - start_addr_) + 2 < size_) { |
| 405 return nacl_arm_dec::Instruction( | |
| 406 *reinterpret_cast<const uint32_t *>(element)); | |
| 407 } else if ((address - start_addr_) + 2 == size_) { | |
| 408 return nacl_arm_dec::Instruction(((uint32_t) | |
| 409 (*reinterpret_cast<const uint16_t *>(element)))); | |
| 410 } else { | |
| 411 fprintf(stderr, "Out of bounds access to code segment: %x\n", address); | |
| 412 exit(1); | |
| 413 } | |
| 319 } | 414 } |
| 320 | 415 |
| 321 bool operator<(const CodeSegment &other) const { | 416 bool operator<(const CodeSegment &other) const { |
| 322 return start_addr_ < other.start_addr_; | 417 return start_addr_ < other.start_addr_; |
| 323 } | 418 } |
| 324 | |
|
Karl
2011/08/30 19:53:52
Nit. Why blank line removed?
| |
| 325 private: | 419 private: |
| 326 const uint8_t *base_; | 420 const uint8_t *base_; |
| 327 uint32_t start_addr_; | 421 uint32_t start_addr_; |
| 328 size_t size_; | 422 size_t size_; |
| 329 }; | 423 }; |
| 330 | 424 |
| 331 | 425 |
| 332 /* | 426 /* |
| 333 * A class that consumes reports of validation problems, and may decide whether | 427 * A class that consumes reports of validation problems, and may decide whether |
| 334 * to continue validating, or early-exit. | 428 * to continue validating, or early-exit. |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 373 | 467 |
| 374 /* | 468 /* |
| 375 * Strings used to describe the current set of validator problems. These may | 469 * Strings used to describe the current set of validator problems. These may |
| 376 * be worth splitting into a separate header file, so that dev tools can | 470 * be worth splitting into a separate header file, so that dev tools can |
| 377 * process them into localized messages without needing to pull in the whole | 471 * process them into localized messages without needing to pull in the whole |
| 378 * validator...we'll see. | 472 * validator...we'll see. |
| 379 */ | 473 */ |
| 380 | 474 |
| 381 // An instruction is unsafe -- more information in the SafetyLevel. | 475 // An instruction is unsafe -- more information in the SafetyLevel. |
| 382 const char * const kProblemUnsafe = "kProblemUnsafe"; | 476 const char * const kProblemUnsafe = "kProblemUnsafe"; |
| 477 // An instruction runs off the end of a segment | |
| 478 const char * const kProblemStraddlesSegment = "kProblemStraddlesSegment"; | |
| 479 // An IT instruction is unconditional, meaning the condition is uninvertable. | |
| 480 const char * const kProblemUnconditionalIT = "kProblemUnconditionalIT"; | |
| 383 // A branch would break a pseudo-operation pattern. | 481 // A branch would break a pseudo-operation pattern. |
| 384 const char * const kProblemBranchSplitsPattern = "kProblemBranchSplitsPattern"; | 482 const char * const kProblemBranchSplitsPattern = "kProblemBranchSplitsPattern"; |
| 385 // A branch targets an invalid code address (out of segment). | 483 // A branch targets an invalid code address (out of segment). |
| 386 const char * const kProblemBranchInvalidDest = "kProblemBranchInvalidDest"; | 484 const char * const kProblemBranchInvalidDest = "kProblemBranchInvalidDest"; |
| 387 // A store uses an unsafe (non-masked) base address. | 485 // A store uses an unsafe (non-masked) base address. |
| 388 const char * const kProblemUnsafeStore = "kProblemUnsafeStore"; | 486 const char * const kProblemUnsafeStore = "kProblemUnsafeStore"; |
| 389 // A branch uses an unsafe (non-masked) destination address. | 487 // A branch uses an unsafe (non-masked) destination address. |
| 390 const char * const kProblemUnsafeBranch = "kProblemUnsafeBranch"; | 488 const char * const kProblemUnsafeBranch = "kProblemUnsafeBranch"; |
| 391 // An instruction updates a data-address register (e.g. SP) without masking. | 489 // An instruction updates a data-address register (e.g. SP) without masking. |
| 392 const char * const kProblemUnsafeDataWrite = "kProblemUnsafeDataWrite"; | 490 const char * const kProblemUnsafeDataWrite = "kProblemUnsafeDataWrite"; |
| 393 // An instruction updates a read-only register (e.g. r9). | 491 // An instruction updates a read-only register (e.g. r9). |
| 394 const char * const kProblemReadOnlyRegister = "kProblemReadOnlyRegister"; | 492 const char * const kProblemReadOnlyRegister = "kProblemReadOnlyRegister"; |
| 395 // A pseudo-op pattern crosses a bundle boundary. | 493 // A pseudo-op pattern crosses a bundle boundary. |
| 396 const char * const kProblemPatternCrossesBundle = | 494 const char * const kProblemPatternCrossesBundle = |
| 397 "kProblemPatternCrossesBundle"; | 495 "kProblemPatternCrossesBundle"; |
| 398 // A linking branch instruction is not in the last bundle slot. | 496 // A linking branch instruction is not in the last bundle slot. |
| 399 const char * const kProblemMisalignedCall = "kProblemMisalignedCall"; | 497 const char * const kProblemMisalignedCall = "kProblemMisalignedCall"; |
| 400 | 498 |
| 401 } // namespace | 499 } // namespace |
| 402 | 500 |
| 403 #endif // NATIVE_CLIENT_SRC_TRUSTED_VALIDATOR_ARM_V2_VALIDATOR_H | 501 #endif // NATIVE_CLIENT_SRC_TRUSTED_VALIDATOR_ARM_V2_VALIDATOR_H |
| OLD | NEW |