LCOV - code coverage report
Current view: directory - src/trusted/validator_arm - model.h (source / functions) Found Hit Coverage
Test: coverage.lcov Lines: 95 0 0.0 %
Date: 2014-09-25 Functions: 0 0 -

       1                 : /*
       2                 :  * Copyright (c) 2012 The Native Client Authors. All rights reserved.
       3                 :  * Use of this source code is governed by a BSD-style license that can be
       4                 :  * found in the LICENSE file.
       5                 :  */
       6                 : 
       7                 : #ifndef NATIVE_CLIENT_SRC_TRUSTED_VALIDATOR_ARM_V2_MODEL_H
       8                 : #define NATIVE_CLIENT_SRC_TRUSTED_VALIDATOR_ARM_V2_MODEL_H
       9                 : 
      10                 : /*
      11                 :  * Models instructions and decode results.
      12                 :  *
      13                 :  * Implementation Note:
      14                 :  * All the classes in this file are designed to be fully inlined as 32-bit
      15                 :  * (POD) integers.  The goal: to provide a nice, fluent interface for
      16                 :  * describing instruction bit operations, with zero runtime cost.  Compare:
      17                 :  *
      18                 :  *   return (1 << ((insn >> 12) & 0xF)) | (1 << ((insn >> 19) & 0xF));
      19                 :  *
      20                 :  *   return insn.reg(15,12) + insn.reg(19,16);
      21                 :  *
      22                 :  * Both lines compile to the same machine code, but the second one is easier
      23                 :  * to read, and eliminates a common error (using X in place of 1 << X).
      24                 :  *
      25                 :  * To this end, keep the following in mind:
      26                 :  *  - Avoid virtual methods.
      27                 :  *  - Mark all methods as inline.  Small method bodies may be included here,
      28                 :  *    but anything nontrivial should go in model-inl.h.
      29                 :  *  - Do not declare destructors.  A destructor causes an object to be passed
      30                 :  *    on the stack, even when passed by value.  (This may be a GCC bug.)
      31                 :  *    Adding a destructor to Instruction slowed the decoder down by 10% on
      32                 :  *    gcc 4.3.3.
      33                 :  */
      34                 : 
      35                 : #include <cstddef>
      36                 : #include <string>
      37                 : #include "native_client/src/include/arm_sandbox.h"
      38                 : #include "native_client/src/include/portability.h"
      39                 : #include "native_client/src/include/portability_bits.h"
      40                 : 
      41                 : namespace nacl_arm_dec {
      42                 : 
      43                 : class RegisterList;
      44                 : 
      45                 : // Defines the architecture version of the ARM processor. Currently assumes
      46                 : // always 7.
      47                 : // TODO(karl): Generalize this to handle multiple versions, once we know how
      48                 : //             to do this.
      49               0 : inline uint32_t ArchVersion() {
      50               0 :   return 7;
      51               0 : }
      52                 : 
      53                 : // Returns FALSE if all of the 32 registers D0-D31 can be accessed, and TRUE if
      54                 : // only the 16 registers D0-D15 can be accessed.
      55               0 : inline bool VFPSmallRegisterBank() {
      56                 :   // Note: The minimum supported platform, which is checked in (see
      57                 :   // native_client/src/trusted/platform_qualify/arch/arm/nacl_arm_qualify.h)
      58                 :   // allows access to all 32 registers D0-D31.
      59               0 :   return false;
      60               0 : }
      61                 : 
      62                 : // A (POD) value class that names a single register.  We could use a typedef
      63                 : // for this, but it introduces some ambiguity problems because of the
      64                 : // implicit conversion to/from int.
      65                 : //
      66                 : // The 32-bit ARM v7 ARM and Thumb instruction sets have:
      67                 : //   - 15 32-bit GPRs, with:
      68                 : //       - R13/R14/R15 serving as SP/LR/PC.
      69                 : //       - R8-R15 being inaccessible in most 16-bit Thumb instructions.
      70                 : //   - FPRs, with:
      71                 : //       - 16 128-bit quadword registers, denoted Q0-Q15.
      72                 : //       - 32 64-bit doubleword registers, denoted D0-D31.
      73                 : //       - 32 32-bit single word registers, denoted S0-S31.
      74                 : //       - Note that the above holds true for only some ARM processors:
      75                 : //         different VFP implementations might have only D0-D15 with S0-S31,
      76                 : //         and Advanced SIMD support is required for the quadword registers.
      77                 : //       - The above FPRs are overlaid and accessing S/D/Q registers
      78                 : //         interchangeably is sometimes expected by the ARM ISA.
      79                 : //         Specifically S0-S3 correspond to D0-D1 as well as Q0,
      80                 : //         S4-S7 to D2-D3 and Q1, and so on.
      81                 : //         D16-D31 and Q8-Q15 do not correspond to any single word register.
      82                 : //
      83                 : // TODO(jfb) detail aarch64 when we support ARM v8.
      84                 : class Register {
      85                 :  public:
      86                 :   typedef uint8_t Number;
      87                 :   // RegisterMask wide enough for aarch32, including "special" registers.
      88                 :   // TODO(jfb) Update for aarch64.
      89                 :   typedef uint32_t Mask;
      90                 :     // aarch32 only has 16 GPRs, we steal other registers for flags and such.
      91                 :   // TODO(jfb) Update for aarch64.
      92                 :   static const Mask kGprMask = 0xFFFF;
      93                 : 
      94                 :   Register() : number_(kNone) {}
      95               0 :   explicit Register(Number number) : number_(number) {}
      96               0 :   Register(const Register& r) : number_(r.number_) {}
      97                 : 
      98                 :   // Produces the bitmask used to represent this register, in both RegisterList
      99                 :   // and ARM's LDM instruction.
     100               0 :   Mask BitMask() const {
     101               0 :     return (number_ == kNone) ? 0 : (1u << number_);
     102               0 :   }
     103                 : 
     104               0 :   Number number() const { return number_; }
     105               0 :   bool Equals(const Register& r) const { return number_ == r.number_; }
     106                 : 
     107                 :   Register& Copy(const Register& r) {
     108                 :     number_ = r.number_;
     109                 :     return *this;
     110                 :   }
     111                 : 
     112                 :   const char* ToString() const;
     113                 : 
     114                 :   // TODO(jfb) Need different numbers for aarch64.
     115                 :   static const Number kTp = 9;   // Thread local pointer.
     116                 :   static const Number kSp = 13;  // Stack pointer.
     117                 :   static const Number kLr = 14;  // Link register.
     118                 :   static const Number kPc = 15;  // Program counter.
     119                 :   static const Number kNumberGPRs = 16;  // Number of General purpose registers.
     120                 :   static const Number kConditions = 16;
     121                 :   static const Number kNone = 32;  // Out of GPR and FPR range.
     122                 : 
     123                 :   // A special value used to indicate that a register field is not used.
     124                 :   // This is specially chosen to ensure that bitmask() == 0, so it can be added
     125                 :   // to any RegisterList with no effect.
     126               0 :   static Register None() { return Register(kNone); }
     127                 : 
     128                 :   // The conditions (i.e. APSR N, Z, C, and V) are collectively modeled as
     129                 :   // a single register, out of the usual ARM GPR range.
     130                 :   // These bits of the APSR register are separately tracked, so we can
     131                 :   // test when any of the 4 bits (and hence conditional execution) is
     132                 :   // affected. If you need to track other bits in the APSR, add them as
     133                 :   // a separate register.
     134               0 :   static Register Conditions() { return Register(kConditions); }
     135                 : 
     136                 :   // Registers with special meaning in our model:
     137               0 :   static Register Tp() { return Register(kTp); }
     138               0 :   static Register Sp() { return Register(kSp); }
     139               0 :   static Register Lr() { return Register(kLr); }
     140               0 :   static Register Pc() { return Register(kPc); }
     141                 : 
     142                 :  private:
     143                 :   Number number_;
     144                 :   Register& operator=(const Register& r);  // Disallow assignment.
     145                 : };
     146                 : 
     147                 : 
     148                 : // A collection of Registers.  Used to describe the side effects of operations.
     149                 : //
     150                 : // Note that this is technically a set, not a list -- but RegisterSet is a
     151                 : // well-known term that means something else.
     152                 : class RegisterList {
     153                 :  public:
     154                 :   // Defines an empty register list.
     155               0 :   RegisterList() : bits_(0) {}
     156                 : 
     157                 :   // Produces a RegisterList that contains the registers specified in the
     158                 :   // given bitmask.  To indicate rN, the bitmask must include (1 << N).
     159               0 :   explicit RegisterList(Register::Mask bitmask) : bits_(bitmask) {}
     160                 : 
     161               0 :   RegisterList(const RegisterList& other) : bits_(other.bits_) {}
     162                 : 
     163                 :   // Produces a RegisterList containing a single register.
     164               0 :   explicit RegisterList(const Register& r) : bits_(r.BitMask()) {}
     165                 : 
     166                 :   // Checks whether this list contains the given register.
     167               0 :   bool Contains(const Register& r) const {
     168               0 :     return bits_ & r.BitMask();
     169               0 :   }
     170                 : 
     171                 :   // Checks whether this list contains all the registers in the operand.
     172               0 :   bool ContainsAll(const RegisterList& other) const {
     173               0 :     return (bits_ & other.bits_) == other.bits_;
     174               0 :   }
     175                 : 
     176                 :   // Checks whether this list contains any of the registers in the operand.
     177               0 :   bool ContainsAny(const RegisterList& other) const {
     178               0 :     return bits_ & other.bits_;
     179               0 :   }
     180                 : 
     181                 :   // Returns true if the two register lists are identical.
     182                 :   bool Equals(const RegisterList& other) const {
     183                 :     return bits_ == other.bits_;
     184                 :   }
     185                 : 
     186                 :   // Adds a register to the register list.
     187               0 :   RegisterList& Add(const Register& r) {
     188               0 :     bits_ |= r.BitMask();
     189               0 :     return *this;
     190               0 :   }
     191                 : 
     192                 :   // Removes a register from the register list.
     193                 :   RegisterList& Remove(const Register& r) {
     194                 :     bits_ &= ~r.BitMask();
     195                 :     return *this;
     196                 :   }
     197                 : 
     198                 :   // Unions this given register list into this.
     199               0 :   RegisterList& Union(const RegisterList& other) {
     200               0 :     bits_ |= other.bits_;
     201               0 :     return *this;
     202               0 :   }
     203                 : 
     204                 :   // Intersects the given register list into this.
     205               0 :   RegisterList& Intersect(const RegisterList& other) {
     206               0 :     bits_ &= other.bits_;
     207               0 :     return *this;
     208               0 :   }
     209                 : 
     210                 :   // Copies the other register list into this.
     211               0 :   RegisterList& Copy(const RegisterList& other) {
     212               0 :     bits_ = other.bits_;
     213               0 :     return *this;
     214               0 :   }
     215                 : 
     216                 :   // Returns the bits defined in the register list.
     217                 :   Register::Mask bits() const {
     218                 :     return bits_;
     219                 :   }
     220                 : 
     221                 :   // Number of ARM GPRs in the list.
     222               0 :   uint32_t numGPRs() const {
     223               0 :     uint16_t gprs = bits_ & Register::kGprMask;
     224               0 :     return nacl::PopCount(gprs);
     225               0 :   }
     226                 : 
     227                 :   // Returns the smallest GPR register in the list.
     228                 :   Register::Number SmallestGPR() const;
     229                 : 
     230                 :   // A list containing every possible register, even some we don't define.
     231                 :   // Used exclusively as a bogus scary return value for forbidden instructions.
     232               0 :   static RegisterList Everything() { return RegisterList(-1); }
     233                 : 
     234                 :   // A special register list to communicate registers that can't be changed
     235                 :   // when doing dynamic code replacement.
     236               0 :   static RegisterList DynCodeReplaceFrozenRegs() {
     237                 :     return RegisterList((1 << Register::kPc) |
     238                 :                         (1 << Register::kLr) |
     239                 :                         (1 << Register::kSp) |
     240               0 :                         (1 << Register::kTp));
     241               0 :   }
     242                 : 
     243                 :  private:
     244                 :   Register::Mask bits_;
     245                 :   RegisterList& operator=(const RegisterList& r);  // Disallow assignment.
     246                 : };
     247                 : 
     248                 : 
     249                 : // The number of bits in an ARM instruction.
     250                 : static const int kArm32InstSize = 32;
     251                 : 
     252                 : // Special ARM instructions for sandboxing.
     253                 : static const uint32_t kLiteralPoolHead = NACL_INSTR_ARM_LITERAL_POOL_HEAD;
     254                 : static const uint32_t kBreakpoint = NACL_INSTR_ARM_BREAKPOINT;
     255                 : static const uint32_t kHaltFill = NACL_INSTR_ARM_HALT_FILL;
     256                 : static const uint32_t kAbortNow = NACL_INSTR_ARM_ABORT_NOW;
     257                 : static const uint32_t kFailValidation = NACL_INSTR_ARM_FAIL_VALIDATION;
     258                 : 
     259                 : // Not-so-special instructions.
     260                 : static const uint32_t kNop = NACL_INSTR_ARM_NOP;
     261                 : 
     262                 : // Models a 32-bit ARM instruction.
     263                 : //
     264                 : // This class is designed for efficiency:
     265                 : //  - Its public methods for bitfield extraction are short and inline.
     266                 : //  - It has no vtable, so on 32-bit platforms it's exactly the size of the
     267                 : //    instruction it models.
     268                 : class Instruction {
     269                 :  public:
     270                 :   Instruction() : bits_(0) {}
     271                 : 
     272               0 :   Instruction(const Instruction& inst) : bits_(inst.bits_) {}
     273                 : 
     274                 :   // Creates an a 32-bit ARM instruction.
     275               0 :   explicit Instruction(uint32_t bits)  : bits_(bits) {}
     276                 : 
     277                 :   // Returns the entire sequence of bits defined by an instruction.
     278               0 :   uint32_t Bits() const {
     279               0 :     return bits_;
     280               0 :   }
     281                 : 
     282                 :   // Mask for the lowest bits.
     283               0 :   static uint32_t LowestBitsMask(int bit_count) {
     284               0 :     return (~(uint32_t)0) >> (32 - bit_count);
     285               0 :   }
     286                 : 
     287                 :   // Extracts a range of contiguous bits, right-justifies it, and returns it.
     288                 :   // Note that the range follows hardware convention, with the high bit first.
     289               0 :   uint32_t Bits(int hi, int lo) const {
     290                 :     // When both arguments are constant (the usual case), this can be inlined
     291                 :     // as
     292                 :     //    ubfx r0, r0, #hi, #(hi+1-lo)
     293                 :     //
     294                 :     // Curiously, even at aggressive optimization levels, GCC 4.3.2 generates a
     295                 :     // less-efficient sequence of ands, bics, and shifts.
     296                 :     //
     297                 :     // TODO(jfb) Validate and fix this: this function is called very often and
     298                 :     //           could speed up validation quite a bit.
     299               0 :     uint32_t right_justified = bits_ >> lo;
     300               0 :     int bit_count = hi - lo + 1;
     301               0 :     return right_justified & LowestBitsMask(bit_count);
     302               0 :   }
     303                 : 
     304                 :   // Changes the range of contiguous bits, with the given value.
     305                 :   // Note: Assumes the value fits, if not, it is truncated.
     306               0 :   void SetBits(int hi, int lo, uint32_t value) {
     307                 :     // TODO(jfb) Same as the above function, this should generate a BFI
     308                 :     //           when hi and lo are compile-time constants.
     309                 :     //
     310                 :     // Compute bit mask for range of bits.
     311               0 :     int bit_count = hi - lo + 1;
     312               0 :     uint32_t clear_mask = LowestBitsMask(bit_count);
     313                 :     // Remove from the value any bits out of range, then shift to location
     314                 :     // to add.
     315               0 :     value = (value & clear_mask) << lo;
     316                 :     // Shift mask to corresponding position and replace bits with value.
     317               0 :     clear_mask = ~(clear_mask << lo);
     318               0 :     bits_ = (bits_ & clear_mask) | value;
     319               0 :   }
     320                 : 
     321                 :   // A convenience method for converting bits to a register.
     322                 :   const Register Reg(int hi, int lo) const {
     323                 :     return Register(Bits(hi, lo));
     324                 :   }
     325                 : 
     326                 :   // Extracts a single bit (0 - 31).
     327                 :   bool Bit(int index) const {
     328                 :     return (bits_ >> index) & 1;
     329                 :   }
     330                 : 
     331                 :   // Sets the specified bit to the specified value for an ARM instruction.
     332                 :   void SetBit(int index, bool value) {
     333                 :     uint32_t mask = (1 << index);
     334                 :     if (value) {
     335                 :       // Set to 1
     336                 :       bits_ |= mask;
     337                 :     } else {
     338                 :       // Set to 0
     339                 :       bits_ &= ~mask;
     340                 :     }
     341                 :   }
     342                 : 
     343                 :   // Possible values for the condition field, from the ARM ARM section A8.3.
     344                 :   // Conditional execution is determined by the APSR's condition flags: NZCV.
     345                 :   enum Condition {
     346                 :     EQ = 0x0,  // Equal                         |  Z == 1
     347                 :     NE = 0x1,  // Not equal                     |  Z == 0
     348                 :     CS = 0x2,  // Carry set                     |  C == 1
     349                 :     CC = 0x3,  // Carry clear                   |  C == 0
     350                 :     MI = 0x4,  // Minus, negative               |  N == 1
     351                 :     PL = 0x5,  // Plus, positive or zero        |  N == 0
     352                 :     VS = 0x6,  // Overflow                      |  V == 1
     353                 :     VC = 0x7,  // No overflow                   |  V == 0
     354                 :     HI = 0x8,  // Unsigned higher               |  C == 1 && Z == 0
     355                 :     LS = 0x9,  // Unsigned lower or same        |  C == 0 || Z == 1
     356                 :     GE = 0xA,  // Signed greater than or equal  |  N == V
     357                 :     LT = 0xB,  // Signed less than              |  N != V
     358                 :     GT = 0xC,  // Signed greater than           |  Z == 0 && N == V
     359                 :     LE = 0xD,  // Signed less than or equal     |  Z == 1 || N != V
     360                 :     AL = 0xE,  // Always (unconditional)        |  Any
     361                 :     UNCONDITIONAL = 0xF,  // Equivalent to AL -- converted in our API
     362                 :     // Aliases:
     363                 :     HS = CS,  // Unsigned higher or same
     364                 :     LO = CC   // Unsigned lower
     365                 :   };
     366                 : 
     367                 :   // Defines the size of enumerated type Condition, minus
     368                 :   // UNCONDITIONAL (assuming one uses GetCondition() to get the
     369                 :   // condition of an instruction).
     370                 :   static const size_t kConditionSize = 15;
     371                 : 
     372                 :   static const char* ToString(Condition cond);
     373                 : 
     374                 :   static Condition Next(Condition cond) {
     375                 :     return static_cast<Condition>(static_cast<int>(cond) + 1);
     376                 :   }
     377                 : 
     378                 :   // Extracts the condition field.  UNCONDITIONAL is converted to AL -- in the
     379                 :   // event that you need to distinguish, (1) make sure that's really true and
     380                 :   // then (2) explicitly extract bits(31,28).
     381               0 :   Condition GetCondition() const {
     382               0 :     Instruction::Condition cc = Instruction::Condition(Bits(31, 28));
     383               0 :     if (cc == Instruction::UNCONDITIONAL) {
     384               0 :       return Instruction::AL;
     385                 :     }
     386               0 :     return cc;
     387               0 :   }
     388                 : 
     389                 :   // Returns true if this and the given instruction are equal.
     390               0 :   bool Equals(const Instruction& inst) const {
     391               0 :     return bits_ == inst.bits_;
     392               0 :   }
     393                 : 
     394                 :   // Copies insn into this.
     395               0 :   Instruction& Copy(const Instruction& insn) {
     396               0 :     bits_ = insn.bits_;
     397               0 :     return *this;
     398               0 :   }
     399                 : 
     400                 :  private:
     401                 :   uint32_t bits_;
     402                 :   Instruction& operator=(const Instruction& insn);  // Disallow assignment.
     403                 : };
     404                 : 
     405                 : // Checks if instruction is a valid constant pool head.
     406               0 : inline bool IsBreakPointAndConstantPoolHead(Instruction i) {
     407                 :   return ((i.Bits(31, 0) == kLiteralPoolHead) ||
     408               0 :           (i.Bits(31, 0) == kBreakpoint));
     409               0 : }
     410                 : 
     411                 : // Same as above, but with integer contents of instruction as argument.
     412               0 : inline bool IsBreakPointAndConstantPoolHead(uint32_t i) {
     413               0 :   return IsBreakPointAndConstantPoolHead(Instruction(i));
     414               0 : }
     415                 : 
     416                 : }  // namespace nacl_arm_dec
     417                 : 
     418                 : #endif  // NATIVE_CLIENT_SRC_TRUSTED_VALIDATOR_ARM_V2_MODEL_H

Generated by: LCOV version 1.7