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 |