Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(970)

Side by Side Diff: src/trusted/validator_arm/validator.h

Issue 7799013: Intial Thumb2 Sandbox (naclrev 6680) Base URL: svn://svn.chromium.org/native_client/trunk/src/native_client
Patch Set: fix thumb2 vs build_arm_thumb2 Created 9 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698