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

Side by Side Diff: src/trusted/validator_mips/inst_classes.h

Issue 9979025: [MIPS] Adding validator for MIPS architecture. (Closed) Base URL: http://src.chromium.org/native_client/trunk/src/native_client/
Patch Set: Minor style changes. Created 8 years, 7 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
OLDNEW
(Empty)
1 /*
2 * Copyright 2012 The Native Client Authors. All rights reserved.
3 * Use of this source code is governed by a BSD-style license that can
4 * be found in the LICENSE file.
5 * Copyright 2012, Google Inc.
6 */
7
8 #ifndef NATIVE_CLIENT_SRC_TRUSTED_VALIDATOR_MIPS_INST_CLASSES_H
9 #define NATIVE_CLIENT_SRC_TRUSTED_VALIDATOR_MIPS_INST_CLASSES_H
10
11 #include <stdint.h>
12 #include "native_client/src/trusted/validator_mips/model.h"
13 #include "native_client/src/include/portability.h"
14
15
16 /*
17 * Models the "instruction classes" that the decoder produces.
18 */
19 namespace nacl_mips_dec {
20
21 /*
22 * Used to describe whether an instruction is safe, and if not, what the issue
23 * is. Only instructions that MAY_BE_SAFE should be allowed in untrusted code,
24 * and even those may be rejected by the validator.
Brad Chen 2012/05/04 22:49:50 Why the holes in the enumeration? Why not consecut
petarj 2012/05/08 14:54:19 We used the same values as ARM implementation does
Brad Chen 2012/05/29 16:20:39 What you will probably need to do is watch the sou
25 */
26 enum SafetyLevel {
27 // The initial value of uninitialized SafetyLevels -- treat as unsafe.
Brad Chen 2012/05/04 22:49:50 Please don't mix comment styles. For C stick with
petarj 2012/05/08 14:54:19 Copied as-is from validator_arm/inst_classes.h
28 UNKNOWN = 0,
29 // This instruction is forbidden by our SFI model.
30 FORBIDDEN = 4,
31 /*
32 * This instruction may be safe in untrusted code: in isolation it contains
33 * nothing scary, but the validator may overrule this during global analysis.
34 */
35 MAY_BE_SAFE = 6
36 };
37
38
39 // Function (op)codes.
40 uint32_t const kBitwiseLogicalAnd = 0x24; // b100100.
41
42
43 /*
44 * Decodes a class of instructions. Does spooky undefined things if handed
45 * instructions that don't belong to its class. Who defines which instructions
46 * these are? Why, the generated decoder, of course.
47 *
48 * This is an abstract base class intended to be overridden with the details of
49 * particular instruction-classes.
50 *
51 * ClassDecoders should be stateless, and should provide a no-arg constructor
52 * for use by the generated decoder.
53 */
54 class ClassDecoder {
55 public:
56 /*
57 * Checks how safe this instruction is, in isolation.
58 * This will detect any violation in the Mips spec -- undefined encodings,
59 * use of registers that are unpredictable -- and the most basic constraints
60 * in our SFI model. Because ClassDecoders are referentially-transparent and
61 * cannot touch global state, this will not check things that may vary with
62 * ABI version.
63 *
64 * The most positive result this can return is called MAY_BE_SAFE because it
65 * is necessary, but not sufficient: the validator has the final say.
66 */
67 virtual SafetyLevel safety(Instruction i) const = 0;
Brad Chen 2012/05/04 22:49:50 Mixed case for function/method names. Possible exc
petarj 2012/05/08 14:54:19 Copied as-is from validator_arm/inst_classes.h.
68
69 /*
70 * For instructions that perform 'masking', this function will return whether
71 * this is true or not for the given instruction.
72 *
73 * The result is useful only for Arithm3 'and' instruction.
74 */
75 virtual bool is_mask(Instruction i, nacl_mips_dec::Register dest,
Brad Chen 2012/05/04 22:49:50 Can functions like these could use more const qual
76 nacl_mips_dec::Register mask) const {
77 UNREFERENCED_PARAMETER(i);
78 UNREFERENCED_PARAMETER(dest);
79 UNREFERENCED_PARAMETER(mask);
80 return false;
81 }
82
83 /*
84 * The gpr register altered by the instruction.
85 */
86 virtual Register dest_gpr_reg(Instruction i) const {
87 UNREFERENCED_PARAMETER(i);
88 return kRegisterNone;
89 }
90
91 /*
92 * May be used for instr's with immediate operand; like addiu or jal.
93 */
94 virtual uint32_t get_imm(Instruction i) const {
95 UNREFERENCED_PARAMETER(i);
96 return -1;
97 }
98
99 /*
100 * For direct jumps (j, jal, branch instructions).
101 */
102 virtual bool is_direct_jump() const {
103 return false;
104 }
105
106 /*
107 * For jump and link (jal, jalr, bal).
108 */
109 virtual bool is_jal() const {
110 return false;
111 }
112
113 /*
114 * For jump register instructions (jr, jalr).
115 */
116 virtual bool is_jmp_reg() const {
117 return false;
118 }
119
120 /*
121 * For the instructions that are followed by a delay slot.
122 */
123 virtual bool has_delay_slot() const {
124 return is_direct_jump() || is_jmp_reg();
125 }
126
127 /*
128 * For load and store instructions.
129 */
130 virtual bool is_load_store() const {
131 return false;
132 }
133
134 /*
135 * For direct jumps, returning the destination address.
136 */
137 virtual uint32_t dest_addr(Instruction i, uint32_t addr) const {
138 UNREFERENCED_PARAMETER(i);
139 UNREFERENCED_PARAMETER(addr);
140 return 0;
141 }
142
143 /*
144 * Used by jump register instructions; returns the register that holds the
145 * address to jump to.
146 */
147 virtual Register target_reg(Instruction i) const {
148 UNREFERENCED_PARAMETER(i);
149 return kRegisterNone;
150 }
151
152 /*
153 * Base address register, for load and store instructions.
154 */
155 virtual Register base_address_register(Instruction i) const {
156 UNREFERENCED_PARAMETER(i);
157 return kRegisterNone;
158 }
159
160
161 protected:
162 ClassDecoder() {}
163 virtual ~ClassDecoder() {}
164 };
165
166 /*
167 * Current Mips NaCl halt (jr $zero).
168 */
169 class NaClHalt : public ClassDecoder {
170 public:
171 virtual ~NaClHalt() {}
172 virtual SafetyLevel safety(Instruction i) const {
173 UNREFERENCED_PARAMETER(i);
174 return MAY_BE_SAFE;
175 }
176 };
177
178 /*
179 * Represents an instruction that is forbidden under all circumstances, so we
180 * didn't bother decoding it further.
181 */
182 class Forbidden : public ClassDecoder {
183 public:
184 virtual ~Forbidden() {}
185 virtual SafetyLevel safety(Instruction i) const {
186 UNREFERENCED_PARAMETER(i);
187 return FORBIDDEN;
188 }
189 };
190
191 /*
192 * Instructions with 2 registers and an immediate value, where bits 20-16
193 * contain the destination gpr register.
194 */
195 class Arithm2 : public ClassDecoder {
196 public:
197 virtual ~Arithm2() {}
198 virtual Register dest_gpr_reg(Instruction i) const {
199 return i.reg(20, 16);
200 }
201 virtual SafetyLevel safety(Instruction i) const {
202 UNREFERENCED_PARAMETER(i);
203 return MAY_BE_SAFE;
204 }
205 };
206
207 /*
208 * Instruction with 3 registers, with bits 15-11 containing the destination gpr
209 * register.
210 */
211 class Arithm3 : public ClassDecoder {
212 public:
213 virtual ~Arithm3() {}
214 virtual Register dest_gpr_reg(Instruction i) const {
Brad Chen 2012/05/04 22:49:50 I would be grateful if you could think of a better
petarj 2012/05/08 14:54:19 We would gladly replace it with 'instr', sure, jus
215 return i.reg(15, 11);
216 }
217 virtual SafetyLevel safety(Instruction i) const {
218 UNREFERENCED_PARAMETER(i);
219 return MAY_BE_SAFE;
220 }
221 virtual bool is_mask(const Instruction instr,
222 const nacl_mips_dec::Register dest,
223 const nacl_mips_dec::Register mask) const {
224 return ((instr.bits(5, 0) == kBitwiseLogicalAnd)
225 && (instr.reg(15, 11) == dest)
226 && (instr.reg(25, 21) == dest)
227 && (instr.reg(20, 16) == mask));
228 }
229 };
230
231 /*
232 * Direct jump class, subclassed by Branch and JmpImm.
233 */
234 class DirectJump : public ClassDecoder {
235 public:
236 virtual ~DirectJump() {}
237 virtual SafetyLevel safety(Instruction i) const {
238 UNREFERENCED_PARAMETER(i);
239 return MAY_BE_SAFE;
240 }
241 virtual bool is_direct_jump() const {
242 return true;
243 }
244 };
245
246 /*
247 * Branch instructions.
248 */
249 class Branch : public DirectJump {
250 public:
251 virtual ~Branch() {}
252 virtual uint32_t get_imm(Instruction instr) const {
253 return instr.bits(15, 0);
254 }
255 virtual uint32_t dest_addr(Instruction instr, uint32_t addr) const {
256 return ((addr + kInstrSize) + ((int16_t)get_imm(instr) << 2));
257 }
258 };
259
260 /*
261 * Branch and link instructions (bal, bgezal, bltzal, bgezall, bltzall).
262 */
263 class BranchAndLink : public Branch {
264 public:
265 virtual ~BranchAndLink() {}
266 virtual bool is_jal() const {
267 return true;
268 }
269 };
270
271 /*
272 * Load and store instructions.
273 */
274 class AbstractLoadStore : public ClassDecoder {
275 public:
276 virtual bool is_load_store() const {
277 return true;
278 }
279 virtual ~AbstractLoadStore() {}
280 virtual SafetyLevel safety(Instruction i) const {
281 UNREFERENCED_PARAMETER(i);
282 return MAY_BE_SAFE;
283 }
284 virtual Register base_address_register(Instruction i) const {
285 return i.reg(25, 21);
286 }
287 };
288
289 /*
290 * Store instructions.
291 */
292 class Store : public AbstractLoadStore {
293 public:
294 virtual ~Store() {}
295 };
296
297 /*
298 * Load instructions, which alter the destination register.
299 */
300 class Load : public AbstractLoadStore {
301 public:
302 virtual ~Load() {}
303 virtual Register dest_gpr_reg(Instruction i) const {
304 return i.reg(20, 16);
305 }
306 };
307
308 /*
309 * Floating point load and store instructions.
310 */
311 class FPLoadStore : public AbstractLoadStore {
312 public:
313 virtual ~FPLoadStore() {}
314 };
315
316 /*
317 * Store Conditional class, containing the sc instruction,
318 * which might alter the contents of the register which is the 1st operand.
319 */
320 class StoreConditional : public Store {
321 public:
322 virtual ~StoreConditional() {}
323 virtual Register dest_gpr_reg(Instruction i) const {
324 return i.reg(20, 16);
325 }
326 };
327
328 /*
329 * Direct jumps - j, jal.
330 */
331 class JmpImm : public DirectJump {
332 public:
333 virtual ~JmpImm() {}
334 virtual uint32_t get_imm(Instruction instr) const {
335 return instr.bits(25, 0);
336 }
337 virtual uint32_t dest_addr(Instruction instr, uint32_t addr) const {
338 return ((addr + kInstrSize) & 0xf0000000) + (get_imm(instr) << 2);
339 }
340 };
341
342 /*
343 * Direct jump and link (jal).
344 */
345 class JalImm : public JmpImm {
346 public:
347 virtual ~JalImm() {}
348 virtual bool is_jal() const {
349 return true;
350 }
351 };
352
353 /*
354 * Jump register instructions - jr, jalr.
355 */
356 class JmpReg : public ClassDecoder {
357 public:
358 virtual ~JmpReg() {}
359 virtual SafetyLevel safety(Instruction i) const {
360 UNREFERENCED_PARAMETER(i);
361 return MAY_BE_SAFE;
362 }
363 virtual bool is_jmp_reg() const {
364 return true;
365 }
366 virtual Register target_reg(Instruction i) const {
367 return i.reg(25, 21);
368 }
369 };
370
371 /*
372 * Jump and link register - jalr.
373 */
374 class JalReg : public JmpReg {
375 public:
376 virtual ~JalReg() {}
377 virtual bool is_jal() const {
378 return true;
379 }
380 virtual Register dest_gpr_reg(Instruction i) const {
381 return i.reg(15, 11);
382 }
383 };
384
385 /*
386 * ext and ins instructions.
387 */
388 class ExtIns : public ClassDecoder {
389 public:
390 virtual ~ExtIns() {}
391 virtual Register dest_gpr_reg(Instruction i) const {
392 return i.reg(20, 16);
393 }
394 virtual SafetyLevel safety(Instruction i) const {
395 UNREFERENCED_PARAMETER(i);
396 return MAY_BE_SAFE;
397 }
398 };
399 /*
400 * The instructions that are safe under all circumstances.
401 */
402 class Safe : public ClassDecoder {
403 public:
404 virtual ~Safe() {}
405 virtual SafetyLevel safety(Instruction i) const {
406 UNREFERENCED_PARAMETER(i);
407 return MAY_BE_SAFE;
408 }
409 };
410
411 class Other : public ClassDecoder {
412 public:
413 virtual ~Other() {}
414 virtual SafetyLevel safety(Instruction i) const {
415 UNREFERENCED_PARAMETER(i);
416 return FORBIDDEN;
417 }
418 };
419
420 /*
421 * Unknown instructions, treated as forbidden.
422 */
423 class Unrecognized : public ClassDecoder {
424 public:
425 virtual ~Unrecognized() {}
426 virtual SafetyLevel safety(Instruction i) const {
427 UNREFERENCED_PARAMETER(i);
428 return FORBIDDEN;
429 }
430 };
431 } // namespace
432
433 #endif // NATIVE_CLIENT_SRC_TRUSTED_VALIDATOR_MIPS_INST_CLASSES_H
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698