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

Unified 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, 8 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 side-by-side diff with in-line comments
Download patch
Index: src/trusted/validator_mips/inst_classes.h
diff --git a/src/trusted/validator_mips/inst_classes.h b/src/trusted/validator_mips/inst_classes.h
new file mode 100644
index 0000000000000000000000000000000000000000..27dd8cc971945b5fea8b688ba1c1c38c77b2ef76
--- /dev/null
+++ b/src/trusted/validator_mips/inst_classes.h
@@ -0,0 +1,433 @@
+/*
+ * Copyright 2012 The Native Client Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can
+ * be found in the LICENSE file.
+ * Copyright 2012, Google Inc.
+ */
+
+#ifndef NATIVE_CLIENT_SRC_TRUSTED_VALIDATOR_MIPS_INST_CLASSES_H
+#define NATIVE_CLIENT_SRC_TRUSTED_VALIDATOR_MIPS_INST_CLASSES_H
+
+#include <stdint.h>
+#include "native_client/src/trusted/validator_mips/model.h"
+#include "native_client/src/include/portability.h"
+
+
+/*
+ * Models the "instruction classes" that the decoder produces.
+ */
+namespace nacl_mips_dec {
+
+/*
+ * Used to describe whether an instruction is safe, and if not, what the issue
+ * is. Only instructions that MAY_BE_SAFE should be allowed in untrusted code,
+ * 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
+ */
+enum SafetyLevel {
+ // 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
+ UNKNOWN = 0,
+ // This instruction is forbidden by our SFI model.
+ FORBIDDEN = 4,
+ /*
+ * This instruction may be safe in untrusted code: in isolation it contains
+ * nothing scary, but the validator may overrule this during global analysis.
+ */
+ MAY_BE_SAFE = 6
+};
+
+
+// Function (op)codes.
+uint32_t const kBitwiseLogicalAnd = 0x24; // b100100.
+
+
+/*
+ * Decodes a class of instructions. Does spooky undefined things if handed
+ * instructions that don't belong to its class. Who defines which instructions
+ * these are? Why, the generated decoder, of course.
+ *
+ * This is an abstract base class intended to be overridden with the details of
+ * particular instruction-classes.
+ *
+ * ClassDecoders should be stateless, and should provide a no-arg constructor
+ * for use by the generated decoder.
+ */
+class ClassDecoder {
+ public:
+ /*
+ * Checks how safe this instruction is, in isolation.
+ * This will detect any violation in the Mips spec -- undefined encodings,
+ * use of registers that are unpredictable -- and the most basic constraints
+ * in our SFI model. Because ClassDecoders are referentially-transparent and
+ * cannot touch global state, this will not check things that may vary with
+ * ABI version.
+ *
+ * The most positive result this can return is called MAY_BE_SAFE because it
+ * is necessary, but not sufficient: the validator has the final say.
+ */
+ 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.
+
+ /*
+ * For instructions that perform 'masking', this function will return whether
+ * this is true or not for the given instruction.
+ *
+ * The result is useful only for Arithm3 'and' instruction.
+ */
+ 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
+ nacl_mips_dec::Register mask) const {
+ UNREFERENCED_PARAMETER(i);
+ UNREFERENCED_PARAMETER(dest);
+ UNREFERENCED_PARAMETER(mask);
+ return false;
+ }
+
+ /*
+ * The gpr register altered by the instruction.
+ */
+ virtual Register dest_gpr_reg(Instruction i) const {
+ UNREFERENCED_PARAMETER(i);
+ return kRegisterNone;
+ }
+
+ /*
+ * May be used for instr's with immediate operand; like addiu or jal.
+ */
+ virtual uint32_t get_imm(Instruction i) const {
+ UNREFERENCED_PARAMETER(i);
+ return -1;
+ }
+
+ /*
+ * For direct jumps (j, jal, branch instructions).
+ */
+ virtual bool is_direct_jump() const {
+ return false;
+ }
+
+ /*
+ * For jump and link (jal, jalr, bal).
+ */
+ virtual bool is_jal() const {
+ return false;
+ }
+
+ /*
+ * For jump register instructions (jr, jalr).
+ */
+ virtual bool is_jmp_reg() const {
+ return false;
+ }
+
+ /*
+ * For the instructions that are followed by a delay slot.
+ */
+ virtual bool has_delay_slot() const {
+ return is_direct_jump() || is_jmp_reg();
+ }
+
+ /*
+ * For load and store instructions.
+ */
+ virtual bool is_load_store() const {
+ return false;
+ }
+
+ /*
+ * For direct jumps, returning the destination address.
+ */
+ virtual uint32_t dest_addr(Instruction i, uint32_t addr) const {
+ UNREFERENCED_PARAMETER(i);
+ UNREFERENCED_PARAMETER(addr);
+ return 0;
+ }
+
+ /*
+ * Used by jump register instructions; returns the register that holds the
+ * address to jump to.
+ */
+ virtual Register target_reg(Instruction i) const {
+ UNREFERENCED_PARAMETER(i);
+ return kRegisterNone;
+ }
+
+ /*
+ * Base address register, for load and store instructions.
+ */
+ virtual Register base_address_register(Instruction i) const {
+ UNREFERENCED_PARAMETER(i);
+ return kRegisterNone;
+ }
+
+
+ protected:
+ ClassDecoder() {}
+ virtual ~ClassDecoder() {}
+};
+
+/*
+ * Current Mips NaCl halt (jr $zero).
+ */
+class NaClHalt : public ClassDecoder {
+ public:
+ virtual ~NaClHalt() {}
+ virtual SafetyLevel safety(Instruction i) const {
+ UNREFERENCED_PARAMETER(i);
+ return MAY_BE_SAFE;
+ }
+};
+
+/*
+ * Represents an instruction that is forbidden under all circumstances, so we
+ * didn't bother decoding it further.
+ */
+class Forbidden : public ClassDecoder {
+ public:
+ virtual ~Forbidden() {}
+ virtual SafetyLevel safety(Instruction i) const {
+ UNREFERENCED_PARAMETER(i);
+ return FORBIDDEN;
+ }
+};
+
+/*
+ * Instructions with 2 registers and an immediate value, where bits 20-16
+ * contain the destination gpr register.
+ */
+class Arithm2 : public ClassDecoder {
+ public:
+ virtual ~Arithm2() {}
+ virtual Register dest_gpr_reg(Instruction i) const {
+ return i.reg(20, 16);
+ }
+ virtual SafetyLevel safety(Instruction i) const {
+ UNREFERENCED_PARAMETER(i);
+ return MAY_BE_SAFE;
+ }
+};
+
+/*
+ * Instruction with 3 registers, with bits 15-11 containing the destination gpr
+ * register.
+ */
+class Arithm3 : public ClassDecoder {
+ public:
+ virtual ~Arithm3() {}
+ 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
+ return i.reg(15, 11);
+ }
+ virtual SafetyLevel safety(Instruction i) const {
+ UNREFERENCED_PARAMETER(i);
+ return MAY_BE_SAFE;
+ }
+ virtual bool is_mask(const Instruction instr,
+ const nacl_mips_dec::Register dest,
+ const nacl_mips_dec::Register mask) const {
+ return ((instr.bits(5, 0) == kBitwiseLogicalAnd)
+ && (instr.reg(15, 11) == dest)
+ && (instr.reg(25, 21) == dest)
+ && (instr.reg(20, 16) == mask));
+ }
+};
+
+/*
+ * Direct jump class, subclassed by Branch and JmpImm.
+ */
+class DirectJump : public ClassDecoder {
+ public:
+ virtual ~DirectJump() {}
+ virtual SafetyLevel safety(Instruction i) const {
+ UNREFERENCED_PARAMETER(i);
+ return MAY_BE_SAFE;
+ }
+ virtual bool is_direct_jump() const {
+ return true;
+ }
+};
+
+/*
+ * Branch instructions.
+ */
+class Branch : public DirectJump {
+ public:
+ virtual ~Branch() {}
+ virtual uint32_t get_imm(Instruction instr) const {
+ return instr.bits(15, 0);
+ }
+ virtual uint32_t dest_addr(Instruction instr, uint32_t addr) const {
+ return ((addr + kInstrSize) + ((int16_t)get_imm(instr) << 2));
+ }
+};
+
+/*
+ * Branch and link instructions (bal, bgezal, bltzal, bgezall, bltzall).
+ */
+class BranchAndLink : public Branch {
+ public:
+ virtual ~BranchAndLink() {}
+ virtual bool is_jal() const {
+ return true;
+ }
+};
+
+/*
+ * Load and store instructions.
+ */
+class AbstractLoadStore : public ClassDecoder {
+ public:
+ virtual bool is_load_store() const {
+ return true;
+ }
+ virtual ~AbstractLoadStore() {}
+ virtual SafetyLevel safety(Instruction i) const {
+ UNREFERENCED_PARAMETER(i);
+ return MAY_BE_SAFE;
+ }
+ virtual Register base_address_register(Instruction i) const {
+ return i.reg(25, 21);
+ }
+};
+
+/*
+ * Store instructions.
+ */
+class Store : public AbstractLoadStore {
+ public:
+ virtual ~Store() {}
+};
+
+/*
+ * Load instructions, which alter the destination register.
+ */
+class Load : public AbstractLoadStore {
+ public:
+ virtual ~Load() {}
+ virtual Register dest_gpr_reg(Instruction i) const {
+ return i.reg(20, 16);
+ }
+};
+
+/*
+ * Floating point load and store instructions.
+ */
+class FPLoadStore : public AbstractLoadStore {
+ public:
+ virtual ~FPLoadStore() {}
+};
+
+/*
+ * Store Conditional class, containing the sc instruction,
+ * which might alter the contents of the register which is the 1st operand.
+ */
+class StoreConditional : public Store {
+ public:
+ virtual ~StoreConditional() {}
+ virtual Register dest_gpr_reg(Instruction i) const {
+ return i.reg(20, 16);
+ }
+};
+
+/*
+ * Direct jumps - j, jal.
+ */
+class JmpImm : public DirectJump {
+ public:
+ virtual ~JmpImm() {}
+ virtual uint32_t get_imm(Instruction instr) const {
+ return instr.bits(25, 0);
+ }
+ virtual uint32_t dest_addr(Instruction instr, uint32_t addr) const {
+ return ((addr + kInstrSize) & 0xf0000000) + (get_imm(instr) << 2);
+ }
+};
+
+/*
+ * Direct jump and link (jal).
+ */
+class JalImm : public JmpImm {
+ public:
+ virtual ~JalImm() {}
+ virtual bool is_jal() const {
+ return true;
+ }
+};
+
+/*
+ * Jump register instructions - jr, jalr.
+ */
+class JmpReg : public ClassDecoder {
+ public:
+ virtual ~JmpReg() {}
+ virtual SafetyLevel safety(Instruction i) const {
+ UNREFERENCED_PARAMETER(i);
+ return MAY_BE_SAFE;
+ }
+ virtual bool is_jmp_reg() const {
+ return true;
+ }
+ virtual Register target_reg(Instruction i) const {
+ return i.reg(25, 21);
+ }
+};
+
+/*
+ * Jump and link register - jalr.
+ */
+class JalReg : public JmpReg {
+ public:
+ virtual ~JalReg() {}
+ virtual bool is_jal() const {
+ return true;
+ }
+ virtual Register dest_gpr_reg(Instruction i) const {
+ return i.reg(15, 11);
+ }
+};
+
+/*
+ * ext and ins instructions.
+ */
+class ExtIns : public ClassDecoder {
+ public:
+ virtual ~ExtIns() {}
+ virtual Register dest_gpr_reg(Instruction i) const {
+ return i.reg(20, 16);
+ }
+ virtual SafetyLevel safety(Instruction i) const {
+ UNREFERENCED_PARAMETER(i);
+ return MAY_BE_SAFE;
+ }
+};
+/*
+ * The instructions that are safe under all circumstances.
+ */
+class Safe : public ClassDecoder {
+ public:
+ virtual ~Safe() {}
+ virtual SafetyLevel safety(Instruction i) const {
+ UNREFERENCED_PARAMETER(i);
+ return MAY_BE_SAFE;
+ }
+};
+
+class Other : public ClassDecoder {
+ public:
+ virtual ~Other() {}
+ virtual SafetyLevel safety(Instruction i) const {
+ UNREFERENCED_PARAMETER(i);
+ return FORBIDDEN;
+ }
+};
+
+/*
+ * Unknown instructions, treated as forbidden.
+ */
+class Unrecognized : public ClassDecoder {
+ public:
+ virtual ~Unrecognized() {}
+ virtual SafetyLevel safety(Instruction i) const {
+ UNREFERENCED_PARAMETER(i);
+ return FORBIDDEN;
+ }
+};
+} // namespace
+
+#endif // NATIVE_CLIENT_SRC_TRUSTED_VALIDATOR_MIPS_INST_CLASSES_H

Powered by Google App Engine
This is Rietveld 408576698