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

Unified Diff: src/trusted/validator_arm/inst_classes.h

Issue 7799013: Intial Thumb2 Sandbox (naclrev 6680) Base URL: svn://svn.chromium.org/native_client/trunk/src/native_client
Patch Set: asdsa 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 side-by-side diff with in-line comments
Download patch
Index: src/trusted/validator_arm/inst_classes.h
diff --git a/src/trusted/validator_arm/inst_classes.h b/src/trusted/validator_arm/inst_classes.h
index ade271e30e3be387e161da49efd90bbe41b7de29..a15f3f9356cce8d29ca5d0c138126801761e081a 100644
--- a/src/trusted/validator_arm/inst_classes.h
+++ b/src/trusted/validator_arm/inst_classes.h
@@ -10,6 +10,9 @@
#include <stdint.h>
#include "native_client/src/trusted/validator_arm/model.h"
#include "native_client/src/include/portability.h"
+// TODO(mrm) Remove this with debugging lines
+#include <stdio.h>
+#include <assert.h>
/*
* Models the "instruction classes" that the decoder produces.
@@ -17,6 +20,53 @@
namespace nacl_arm_dec {
/*
+ * Describes whether an operation is safe to have during an IT.
+ */
+enum ITSafety {
+// Safe to use in an IT block
+ALWAYS,
+// Unsafe to use in an IT block
+NEVER,
+// Can only go at the end of an IT block
+END
+};
+
+/*
+ * Describes what mode an instruction governed under an IT is in.
+ * THEN means condition must match, ELSE means condition must not match,
+ * NONE means this is the end of IT control flow.
+ */
+enum ITMode {
+// No condition. There should be no Thens or Elses after this
+NONE = 0,
+// Matches condition
+THEN = 1,
+// Does not match condition
+ELSE = 2
+};
+
+/*
+ * Used to store the full it conditional. This should fit in a byte, and so is
+ * used instead of an array. It is a bitpacked size 4 array of 2 bit values.
+ */
+typedef uint32_t ITCond;
+inline ITMode it_select(uint32_t index, ITCond cond) {
+ assert(index < 4);
+ return (ITMode)((cond >> (2 * index)) & 0x3);
+}
+
+/*
+ * In an if-then block, the instruction sequence can be predicated
+ * COND or !COND (undef if COND==ALWAYS)
+ * !COND is expressed same as COND but with the LSB inverted
+ * See pages A8-8 and A8-104 for the exact encoding
+ */
+inline ITCond it_set(uint32_t index, ITMode mode, ITCond cond) {
+ assert(index < 4);
+ return (mode << (2 * index)) | (cond & (~(0x3 << (2 * index))));
+}
+
+/*
* 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.
@@ -176,6 +226,18 @@ class ClassDecoder {
}
/*
+ * Checks that an instruction sets a certain pattern of bits in all its
+ * (non-flag) result registers. The mask should include 1s in the positions
+ * that should be set. Unlike clears_bits, which may clear a superset of these
+ * bits, sets_bits must set PRECISELY the bits in mask.
+ */
+ virtual bool sets_bits(Instruction i, uint32_t mask) const {
+ UNREFERENCED_PARAMETER(i);
+ UNREFERENCED_PARAMETER(mask);
+ return false;
+ }
+
+ /*
* Checks that an instruction clears a certain pattern of bits in all its
* (non-flag) result registers. The mask should include 1s in the positions
* that should be cleared.
@@ -202,12 +264,52 @@ class ClassDecoder {
return false;
}
+ /*
+ * Generates the appropriate it condition set for this instruction.
+ * All entries after a NONE is hit should be zero.
+ * Default return is that no IT is in effect.
+ * There are exactly 4 entries, encoded as a bitpacked 2-bit element array.
+ */
+ virtual ITCond it_sequence(Instruction i) const {
+ UNREFERENCED_PARAMETER(i);
+ return 0;
+ }
+
+ /*
+ * Determines under what conditions an instruction is safe to have in an IT
+ * block for CPU sanity. Usually, most instructions are.
+ */
+ virtual ITSafety it_safe(Instruction i) const {
+ UNREFERENCED_PARAMETER(i);
+ return ALWAYS;
+ }
+
+ /*
+ * Calculate the condition code. This used to be done by Instruction,
+ * but Thumb has some special cases, so we hook here for potential override.
+ */
+ virtual Instruction::Condition condition(Instruction i) const {
+ return i.condition();
+ }
+
protected:
ClassDecoder() {}
virtual ~ClassDecoder() {}
};
/*
+ * Base class for thumb decoders, has different default behavior for conditions
+ */
+class ClassDecoderT : public ClassDecoder {
+ public:
+ virtual ~ClassDecoderT() {}
+ virtual Instruction::Condition condition(Instruction i) const {
+ UNREFERENCED_PARAMETER(i);
+ return Instruction::UNCONDITIONAL;
+ }
+};
+
+/*
* Represents an instruction that is forbidden under all circumstances, so we
* didn't bother decoding it further.
*/
@@ -336,6 +438,14 @@ class Breakpoint : public Roadblock {
virtual bool is_literal_pool_head(Instruction i) const;
};
+class ThumbBreakpoint : public Breakpoint {
+ public:
+ virtual ~ThumbBreakpoint() {}
+
+ virtual bool is_literal_pool_head(Instruction i) const;
+};
+
+
/*
* Models the most common class of data processing instructions. We use this
* for any operation that
@@ -768,6 +878,505 @@ class Branch : public ClassDecoder {
virtual int32_t branch_target_offset(Instruction i) const;
};
+/* Thumb Classes */
+
+class Def3 : public ClassDecoderT {
+ public:
+ virtual ~Def3() {}
+
+ virtual SafetyLevel safety(Instruction i) const;
+ virtual RegisterList defs(Instruction i) const;
+};
+
+class Def8_10 : public ClassDecoderT {
+ public:
+ virtual ~Def8_10() {}
+
+ virtual SafetyLevel safety(Instruction i) const;
+ virtual RegisterList defs(Instruction i) const;
+};
+
+class MemOpThumb : public ClassDecoderT {
+ public:
+ virtual ~MemOpThumb() {}
+
+ virtual SafetyLevel safety(Instruction i) const;
+ virtual RegisterList defs(Instruction i) const {
+ UNREFERENCED_PARAMETER(i);
+ return kRegisterNone;
+ }
+
+ virtual Register base_address_register(Instruction i) const;
+};
+
+class MemOpThumbLoad : public MemOpThumb {
+ public:
+ virtual ~MemOpThumbLoad() {}
+
+ virtual RegisterList defs(Instruction i) const;
+};
+
+class MemOpThumbStore : public MemOpThumb {
+ public:
+ virtual ~MemOpThumbStore() {}
+
+ virtual bool writes_memory(Instruction i) const {
+ UNREFERENCED_PARAMETER(i);
+ return true;
+ }
+};
+
+class SPMod : public ClassDecoderT {
+ public:
+ virtual ~SPMod() {}
+ virtual SafetyLevel safety(Instruction i) const {
+ UNREFERENCED_PARAMETER(i);
+ return MAY_BE_SAFE;
+ }
+ virtual RegisterList defs(Instruction i) const {
+ UNREFERENCED_PARAMETER(i);
+ return kRegisterStack;
+ }
+};
+
+// mrm BiC3, OrMask3, Mask3 are dummies atm, and could be replaced by
+// Def3, its only potential purpose is to allow registerwise
+// bitmasking, which is not a current feature.
+class BiC3 : public Def3 {
+ public:
+ virtual ~BiC3() {}
+};
+
+class Mask3 : public Def3 {
+ public:
+ virtual ~Mask3() {}
+};
+
+class OrMask3 : public Def3 {
+ public:
+ virtual ~OrMask3() {}
+};
+
+class Cmp : public ClassDecoderT {
+ public :
+ virtual ~Cmp() {}
+ virtual SafetyLevel safety(Instruction i) const {
+ UNREFERENCED_PARAMETER(i);
+ return MAY_BE_SAFE;
+ }
+ virtual RegisterList defs(Instruction i) const {
+ UNREFERENCED_PARAMETER(i);
+ return kRegisterNone;
+ }
+ // mrm may want logic for cmp sandboxing, but not atm
+ // This would be a superclass for that, not the target class
+};
+
+class CmpBrZ : public ClassDecoderT {
+ public:
+ virtual ~CmpBrZ() {}
+ virtual SafetyLevel safety(Instruction i) const {
+ UNREFERENCED_PARAMETER(i);
+ return MAY_BE_SAFE;
+ }
+ virtual RegisterList defs(Instruction i) const {
+ UNREFERENCED_PARAMETER(i);
+ return kRegisterPc;
+ }
+ virtual bool is_relative_branch(Instruction i) const {
+ UNREFERENCED_PARAMETER(i);
+ return true;
+ }
+ virtual ITSafety it_safe(Instruction i) const {
+ UNREFERENCED_PARAMETER(i);
+ return NEVER;
+ }
+ virtual int32_t branch_target_offset(Instruction i) const;
+};
+
+class PushMult : public ClassDecoderT {
+ public:
+ virtual ~PushMult() {}
+ virtual SafetyLevel safety(Instruction i) const {
+ UNREFERENCED_PARAMETER(i);
+ return MAY_BE_SAFE;
+ }
+ virtual RegisterList defs(Instruction i) const {
+ UNREFERENCED_PARAMETER(i);
+ return kRegisterStack;
+ }
+ virtual Register base_address_register(Instruction i) const {
+ UNREFERENCED_PARAMETER(i);
+ return kRegisterStack;
+ }
+ virtual RegisterList immediate_addressing_defs(Instruction i) const {
+ return base_address_register(i);
+ }
+ virtual bool writes_memory(Instruction i) const {
+ UNREFERENCED_PARAMETER(i);
+ return true;
+ }
+};
+
+class PopMult : public PushMult {
+ public:
+ virtual ~PopMult() {}
+ virtual RegisterList defs(Instruction i) const;
+};
+
+class BranchT : public ClassDecoder {
+ public:
+ virtual ~BranchT() {}
+ virtual SafetyLevel safety(Instruction i) const {
+ UNREFERENCED_PARAMETER(i);
+ return MAY_BE_SAFE;
+ }
+ virtual RegisterList defs(Instruction i) const {
+ UNREFERENCED_PARAMETER(i);
+ return kRegisterPc;
+ }
+ virtual bool is_relative_branch(Instruction i) const {
+ UNREFERENCED_PARAMETER(i);
+ return true;
+ }
+ virtual ITSafety it_safe(Instruction i) const {
+ UNREFERENCED_PARAMETER(i);
+ return END;
+ }
+};
+
+class BranchTCond : public BranchT {
+ public:
+ virtual ~BranchTCond() {}
+ virtual SafetyLevel safety(Instruction i) const;
+ virtual ITSafety it_safe(Instruction i) const {
+ UNREFERENCED_PARAMETER(i);
+ return NEVER;
+ }
+};
+
+class BranchT1 : public BranchTCond {
+ virtual int32_t branch_target_offset(Instruction i) const;
+ virtual Instruction::Condition condition(Instruction i) const;
+};
+
+class BranchT2 : public BranchT {
+ public:
+ virtual ~BranchT2() {}
+ virtual int32_t branch_target_offset(Instruction i) const;
+};
+
+class BranchT3 : public BranchTCond {
+ public:
+ virtual ~BranchT3() {}
+ virtual int32_t branch_target_offset(Instruction i) const;
+ virtual Instruction::Condition condition(Instruction i) const;
+};
+
+class BranchT4 : public BranchT {
+ public:
+ virtual ~BranchT4() {}
+ virtual int32_t branch_target_offset(Instruction i) const;
+};
+
+class STMT1 : public ClassDecoderT {
+ public:
+ virtual ~STMT1() {}
+ virtual SafetyLevel safety(Instruction i) const {
+ UNREFERENCED_PARAMETER(i);
+ return MAY_BE_SAFE;
+ }
+ virtual RegisterList immediate_addressing_defs(Instruction i) const;
+ virtual RegisterList defs(Instruction i) const;
+ virtual Register base_address_register(Instruction i) const;
+ virtual bool writes_memory(Instruction i) const {
+ UNREFERENCED_PARAMETER(i);
+ return true;
+ }
+};
+
+class LDMT1 : public STMT1 {
+ public:
+ virtual ~LDMT1() {}
+ virtual RegisterList defs(Instruction i) const;
+ virtual bool writes_memory(Instruction i) const {
+ UNREFERENCED_PARAMETER(i);
+ return false;
+ }
+};
+
+class LDRLitT1 : public ClassDecoderT {
+ public:
+ virtual ~LDRLitT1() {}
+ virtual SafetyLevel safety(Instruction i) const {
+ UNREFERENCED_PARAMETER(i);
+ return MAY_BE_SAFE;
+ }
+ virtual RegisterList defs(Instruction i) const;
+};
+
+class ADRT1 : public ClassDecoderT {
+ public:
+ virtual ~ADRT1() {}
+ virtual SafetyLevel safety(Instruction i) const {
+ UNREFERENCED_PARAMETER(i);
+ return MAY_BE_SAFE;
+ }
+ virtual RegisterList defs(Instruction i) const;
+};
+
+class MemOpSPThumbStore : public ClassDecoderT {
+ public:
+ virtual ~MemOpSPThumbStore() {}
+ virtual SafetyLevel safety(Instruction i) const {
+ UNREFERENCED_PARAMETER(i);
+ return MAY_BE_SAFE;
+ }
+ virtual bool writes_memory(Instruction i) const {
+ UNREFERENCED_PARAMETER(i);
+ return true;
+ }
+ virtual RegisterList defs(Instruction i) const {
+ UNREFERENCED_PARAMETER(i);
+ return kRegisterNone;
+ }
+ virtual Register base_address_register(Instruction i) const {
+ UNREFERENCED_PARAMETER(i);
+ return kRegisterStack;
+ }
+};
+
+class MemOpSPThumbLoad : public ClassDecoderT {
+ public:
+ virtual ~MemOpSPThumbLoad() {}
+ virtual SafetyLevel safety(Instruction i) const {
+ UNREFERENCED_PARAMETER(i);
+ return MAY_BE_SAFE;
+ }
+ virtual RegisterList defs(Instruction i) const;
+ virtual Register base_address_register(Instruction i) const {
+ UNREFERENCED_PARAMETER(i);
+ return kRegisterStack;
+ }
+};
+
+class DPMImm : public ClassDecoderT {
+ public:
+ virtual ~DPMImm() {}
+ virtual SafetyLevel safety(Instruction i) const {
+ UNREFERENCED_PARAMETER(i);
+ return MAY_BE_SAFE;
+ }
+ virtual RegisterList defs(Instruction i) const;
+};
+
+class BicModImmT : public DPMImm {
+ public:
+ virtual ~BicModImmT() {}
+ virtual bool clears_bits(Instruction i, uint32_t mask) const;
+};
+
+class OrrModImmT : public DPMImm {
+ public:
+ virtual ~OrrModImmT() {}
+ virtual bool sets_bits(Instruction i, uint32_t mask) const;
+};
+
+class MovT : public Def3 {
+ public:
+ virtual ~MovT() {}
+ virtual RegisterList defs(Instruction i) const;
+};
+
+class BXT : public ClassDecoderT {
+ public:
+ virtual ~BXT() {}
+ virtual SafetyLevel safety(Instruction i) const {
+ UNREFERENCED_PARAMETER(i);
+ return MAY_BE_SAFE;
+ }
+ virtual RegisterList defs(Instruction i) const {
+ UNREFERENCED_PARAMETER(i);
+ return kRegisterPc;
+ }
+ Register branch_target_register(Instruction i) const;
+ virtual ITSafety it_safe(Instruction i) const {
+ UNREFERENCED_PARAMETER(i);
+ return END;
+ }
+};
+
+class BLXT : public BXT {
+ public:
+ virtual ~BLXT() {}
+ virtual RegisterList defs(Instruction i) const {
+ UNREFERENCED_PARAMETER(i);
+ return kRegisterPc + kRegisterLink;
+ }
+};
+
+class BLT : public ClassDecoderT {
+ public:
+ virtual ~BLT() {}
+ virtual SafetyLevel safety(Instruction i) const {
+ UNREFERENCED_PARAMETER(i);
+ return MAY_BE_SAFE;
+ }
+ virtual RegisterList defs(Instruction i) const {
+ UNREFERENCED_PARAMETER(i);
+ return kRegisterPc + kRegisterLink;
+ }
+ virtual bool is_relative_branch(Instruction i) const {
+ UNREFERENCED_PARAMETER(i);
+ return true;
+ }
+ virtual int32_t branch_target_offset(Instruction i) const;
+ virtual ITSafety it_safe(Instruction i) const {
+ UNREFERENCED_PARAMETER(i);
+ return END;
+ }
+};
+
+class IT : public ClassDecoderT {
+ public:
+ virtual ~IT() {}
+ virtual SafetyLevel safety(Instruction i) const {
+ UNREFERENCED_PARAMETER(i);
+ return MAY_BE_SAFE;
+ }
+ virtual ITSafety it_safe(Instruction i) const {
+ UNREFERENCED_PARAMETER(i);
+ return NEVER;
+ }
+ virtual RegisterList defs(Instruction i) const {
+ UNREFERENCED_PARAMETER(i);
+ return kRegisterNone;
+ }
+ virtual Instruction::Condition condition(Instruction i) const;
+ virtual ITCond it_sequence(Instruction i) const;
+};
+
+class STMTD : public ClassDecoderT {
+ public:
+ virtual ~STMTD() {}
+ virtual SafetyLevel safety(Instruction i) const {
+ UNREFERENCED_PARAMETER(i);
+ return MAY_BE_SAFE;
+ }
+ virtual RegisterList defs(Instruction i) const;
+ virtual bool writes_memory(Instruction i) const {
+ UNREFERENCED_PARAMETER(i);
+ return true;
+ }
+ virtual Register base_address_register(Instruction i) const;
+ virtual RegisterList immediate_addressing_defs(Instruction i) const;
+};
+
+class LDMTD : public STMTD {
+ public:
+ virtual ~LDMTD() {}
+ virtual RegisterList defs(Instruction i) const;
+ virtual bool writes_memory(Instruction i) const {
+ UNREFERENCED_PARAMETER(i);
+ return false;
+ }
+};
+
+class StrS : public STMTD {
+ public:
+ virtual ~StrS() {}
+ virtual Register base_address_register(Instruction i) const;
+ virtual RegisterList defs(Instruction i) const;
+};
+
+class LDRImmT3 : public ClassDecoderT {
+ public:
+ virtual ~LDRImmT3() {}
+ virtual SafetyLevel safety(Instruction i) const {
+ UNREFERENCED_PARAMETER(i);
+ return MAY_BE_SAFE;
+ }
+ virtual RegisterList defs(Instruction i) const {
+ UNREFERENCED_PARAMETER(i);
+ return kRegisterNone;
+ }
+ virtual Register base_address_register(Instruction i) const;
+};
+
+class LDRImmT4 : public LDRImmT3 {
+ public:
+ virtual ~LDRImmT4() {}
+ virtual RegisterList immediate_addressing_defs(Instruction i) const;
+ virtual RegisterList defs(Instruction i) const;
+};
+
+class Def31_18 : public Def3 {
+ public:
+ virtual ~Def31_18() {}
+ virtual RegisterList defs(Instruction i) const;
+};
+
+class StrEx : public Def3 {
+ public:
+ virtual ~StrEx() {}
+ virtual RegisterList defs(Instruction i) const;
+ virtual RegisterList immediate_addressing_defs(Instruction i) const;
+ virtual bool writes_memory(Instruction i) const {
+ UNREFERENCED_PARAMETER(i);
+ return true;
+ }
+ virtual Register base_address_register(Instruction i) const;
+};
+
+class LdrEx : public StrEx {
+ public:
+ virtual ~LdrEx() {}
+ virtual RegisterList defs(Instruction i) const;
+ virtual bool writes_memory(Instruction i) const {
+ UNREFERENCED_PARAMETER(i);
+ return false;
+ }
+};
+
+class StrD : public StrEx {
+ public:
+ virtual ~StrD() {}
+ virtual RegisterList defs(Instruction i) const;
+};
+
+class LdrD : public LdrEx {
+ public:
+ virtual ~LdrD() {}
+ virtual RegisterList defs(Instruction i) const;
+};
+
+class StrExD : public StrEx {
+ public:
+ virtual ~StrExD() {}
+ virtual RegisterList immediate_addressing_defs(Instruction i) const {
+ UNREFERENCED_PARAMETER(i);
+ return kRegisterNone; // Writeback not available
+ }
+};
+
+class LdrExD : public LdrD {
+ public:
+ virtual ~LdrExD() {}
+ virtual RegisterList immediate_addressing_defs(Instruction i) const {
+ UNREFERENCED_PARAMETER(i);
+ return kRegisterNone; // Writeback not available
+ }
+};
+
+class Def27_24 : public Def3 {
+ public:
+ virtual ~Def27_24() {}
+ virtual RegisterList defs(Instruction i) const;
+};
+
+/* Unimplemented Thumb instructions go here */
+#define THUMB_TODO(x) class x : public Forbidden {};
+THUMB_TODO(Unimplemented)
} // namespace
#endif // NATIVE_CLIENT_SRC_TRUSTED_VALIDATOR_ARM_V2_INST_CLASSES_H

Powered by Google App Engine
This is Rietveld 408576698