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

Generated by: LCOV version 1.7