LCOV - code coverage report
Current view: directory - src/trusted/validator_ragel - validator_internal.h (source / functions) Found Hit Coverage
Test: coverage.lcov Lines: 47 47 100.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                 : /*
       8                 :  * This file contains common parts of x86-32 and x86-64 internals (inline
       9                 :  * functions and defines).
      10                 :  */
      11                 : 
      12                 : #ifndef NATIVE_CLIENT_SRC_TRUSTED_VALIDATOR_RAGEL_VALIDATOR_INTERNAL_H_
      13                 : #define NATIVE_CLIENT_SRC_TRUSTED_VALIDATOR_RAGEL_VALIDATOR_INTERNAL_H_
      14                 : 
      15                 : #include "native_client/src/shared/platform/nacl_check.h"
      16                 : #include "native_client/src/shared/utils/types.h"
      17                 : #include "native_client/src/trusted/validator_ragel/decoding.h"
      18                 : #include "native_client/src/trusted/validator_ragel/validator.h"
      19                 : 
      20                 : /* Maximum set of R-DFA allowable CPUID features.  */
      21                 : extern const NaClCPUFeaturesX86 kValidatorCPUIDFeatures;
      22                 : 
      23                 : /* Macroses to support CPUID handling.  */
      24                 : 
      25                 : /*
      26                 :  * Main macro: FEATURE parameter here is one of the macroses below, e.g.
      27                 :  * SET_CPU_FEATURE(CPUFeature_AESAVX).
      28                 :  */
      29                 : #define SET_CPU_FEATURE(FEATURE) \
      30                 :   if (!(FEATURE(kValidatorCPUIDFeatures.data))) { \
      31                 :     instruction_info_collected |= UNRECOGNIZED_INSTRUCTION; \
      32                 :   } \
      33                 :   if (!(FEATURE(cpu_features->data))) { \
      34                 :     instruction_info_collected |= CPUID_UNSUPPORTED_INSTRUCTION; \
      35                 :   }
      36                 : /*
      37                 :  * Macroses to access induvidual elements of NaClCPUFeaturesX86 structure,
      38                 :  * e.g. CPUFeature_AESAVX(kValidatorCPUIDFeatures.data).
      39                 :  */
      40                 : #define CPUFeature_3DNOW(FEATURES)    FEATURES[NaClCPUFeatureX86_3DNOW]
      41                 : /*
      42                 :  * AMD documentation claims it's always available if CPUFeature_LM is present,
      43                 :  * But Intel documentation does not even mention it!
      44                 :  * Keep it as 3DNow! instruction.
      45                 :  */
      46                 : #define CPUFeature_3DPRFTCH(FEATURES) \
      47                 :   (CPUFeature_3DNOW(FEATURES) || CPUFeature_PRE(FEATURES))
      48                 : #define CPUFeature_AES(FEATURES)      FEATURES[NaClCPUFeatureX86_AES]
      49                 : #define CPUFeature_AESAVX(FEATURES) \
      50                 :   (CPUFeature_AES(FEATURES) && CPUFeature_AVX(FEATURES))
      51                 : #define CPUFeature_AVX(FEATURES)      FEATURES[NaClCPUFeatureX86_AVX]
      52                 : #define CPUFeature_BMI1(FEATURES)     FEATURES[NaClCPUFeatureX86_BMI1]
      53                 : #define CPUFeature_CLFLUSH(FEATURES)  FEATURES[NaClCPUFeatureX86_CLFLUSH]
      54                 : #define CPUFeature_CLMUL(FEATURES)    FEATURES[NaClCPUFeatureX86_CLMUL]
      55                 : #define CPUFeature_CLMULAVX(FEATURES) \
      56                 :   (CPUFeature_CLMUL(FEATURES) && CPUFeature_AVX(FEATURES))
      57                 : #define CPUFeature_CMOV(FEATURES)     FEATURES[NaClCPUFeatureX86_CMOV]
      58                 : #define CPUFeature_CMOVx87(FEATURES)  \
      59                 :   (CPUFeature_CMOV(FEATURES) && CPUFeature_x87(FEATURES))
      60                 : #define CPUFeature_CX16(FEATURES)     FEATURES[NaClCPUFeatureX86_CX16]
      61                 : #define CPUFeature_CX8(FEATURES)      FEATURES[NaClCPUFeatureX86_CX8]
      62                 : #define CPUFeature_E3DNOW(FEATURES)   FEATURES[NaClCPUFeatureX86_E3DNOW]
      63                 : #define CPUFeature_EMMX(FEATURES)     FEATURES[NaClCPUFeatureX86_EMMX]
      64                 : #define CPUFeature_EMMXSSE(FEATURES) \
      65                 :   (CPUFeature_EMMX(FEATURES) || CPUFeature_SSE(FEATURES))
      66                 : #define CPUFeature_F16C(FEATURES)     FEATURES[NaClCPUFeatureX86_F16C]
      67                 : #define CPUFeature_FMA(FEATURES)      FEATURES[NaClCPUFeatureX86_FMA]
      68                 : #define CPUFeature_FMA4(FEATURES)     FEATURES[NaClCPUFeatureX86_FMA4]
      69                 : #define CPUFeature_FXSR(FEATURES)     FEATURES[NaClCPUFeatureX86_FXSR]
      70                 : #define CPUFeature_LAHF(FEATURES)     FEATURES[NaClCPUFeatureX86_LAHF]
      71                 : #define CPUFeature_LM(FEATURES)       FEATURES[NaClCPUFeatureX86_LM]
      72                 : #define CPUFeature_LWP(FEATURES)      FEATURES[NaClCPUFeatureX86_LWP]
      73                 : /*
      74                 :  * We allow lzcnt unconditionally
      75                 :  * See http://code.google.com/p/nativeclient/issues/detail?id=2869
      76                 :  */
      77                 : #define CPUFeature_LZCNT(FEATURES)    TRUE
      78                 : #define CPUFeature_MMX(FEATURES)      FEATURES[NaClCPUFeatureX86_MMX]
      79                 : #define CPUFeature_MON(FEATURES)      FEATURES[NaClCPUFeatureX86_MON]
      80                 : #define CPUFeature_MOVBE(FEATURES)    FEATURES[NaClCPUFeatureX86_MOVBE]
      81                 : #define CPUFeature_OSXSAVE(FEATURES)  FEATURES[NaClCPUFeatureX86_OSXSAVE]
      82                 : #define CPUFeature_POPCNT(FEATURES)   FEATURES[NaClCPUFeatureX86_POPCNT]
      83                 : #define CPUFeature_PRE(FEATURES)      FEATURES[NaClCPUFeatureX86_PRE]
      84                 : #define CPUFeature_SSE(FEATURES)      FEATURES[NaClCPUFeatureX86_SSE]
      85                 : #define CPUFeature_SSE2(FEATURES)     FEATURES[NaClCPUFeatureX86_SSE2]
      86                 : #define CPUFeature_SSE3(FEATURES)     FEATURES[NaClCPUFeatureX86_SSE3]
      87                 : #define CPUFeature_SSE41(FEATURES)    FEATURES[NaClCPUFeatureX86_SSE41]
      88                 : #define CPUFeature_SSE42(FEATURES)    FEATURES[NaClCPUFeatureX86_SSE42]
      89                 : #define CPUFeature_SSE4A(FEATURES)    FEATURES[NaClCPUFeatureX86_SSE4A]
      90                 : #define CPUFeature_SSSE3(FEATURES)    FEATURES[NaClCPUFeatureX86_SSSE3]
      91                 : #define CPUFeature_TBM(FEATURES)      FEATURES[NaClCPUFeatureX86_TBM]
      92                 : #define CPUFeature_TSC(FEATURES)      FEATURES[NaClCPUFeatureX86_TSC]
      93                 : /*
      94                 :  * We allow tzcnt unconditionally
      95                 :  * See http://code.google.com/p/nativeclient/issues/detail?id=2869
      96                 :  */
      97                 : #define CPUFeature_TZCNT(FEATURES)    TRUE
      98                 : #define CPUFeature_x87(FEATURES)      FEATURES[NaClCPUFeatureX86_x87]
      99                 : #define CPUFeature_XOP(FEATURES)      FEATURES[NaClCPUFeatureX86_XOP]
     100                 : 
     101                 : /* Remember some information about instruction for further processing.  */
     102                 : #define GET_REX_PREFIX() rex_prefix
     103                 : #define SET_REX_PREFIX(PREFIX_BYTE) rex_prefix = (PREFIX_BYTE)
     104                 : #define GET_VEX_PREFIX2() vex_prefix2
     105                 : #define SET_VEX_PREFIX2(PREFIX_BYTE) vex_prefix2 = (PREFIX_BYTE)
     106                 : #define GET_VEX_PREFIX3() vex_prefix3
     107                 : #define SET_VEX_PREFIX3(PREFIX_BYTE) vex_prefix3 = (PREFIX_BYTE)
     108                 : #define SET_MODRM_BASE(REG_NUMBER) base = (REG_NUMBER)
     109                 : #define SET_MODRM_INDEX(REG_NUMBER) index = (REG_NUMBER)
     110                 : 
     111                 : /* Ignore this information for now.  */
     112                 : #define SET_DATA16_PREFIX(STATUS)
     113                 : #define SET_REPZ_PREFIX(STATUS)
     114                 : #define SET_REPNZ_PREFIX(STATUS)
     115                 : #define SET_MODRM_SCALE(VALUE)
     116                 : #define SET_DISPLACEMENT_POINTER(POINTER)
     117                 : #define SET_IMMEDIATE_POINTER(POINTER)
     118                 : #define SET_SECOND_IMMEDIATE_POINTER(POINTER)
     119                 : 
     120                 : /*
     121                 :  * Collect information about anyfields (offsets and immediates).
     122                 :  * Note: we use += below instead of |=. This means two immediate fields will
     123                 :  * be treated as one.  It's not important for safety.
     124                 :  */
     125                 : #define SET_DISPLACEMENT_FORMAT(FORMAT) SET_DISPLACEMENT_FORMAT_##FORMAT
     126                 : #define SET_DISPLACEMENT_FORMAT_DISPNONE
     127                 : #define SET_DISPLACEMENT_FORMAT_DISP8 \
     128                 :   (instruction_info_collected += DISPLACEMENT_8BIT)
     129                 : #define SET_DISPLACEMENT_FORMAT_DISP32 \
     130                 :   (instruction_info_collected += DISPLACEMENT_32BIT)
     131                 : #define SET_IMMEDIATE_FORMAT(FORMAT) SET_IMMEDIATE_FORMAT_##FORMAT
     132                 : /* imm2 field is a flag, not accumulator, like other immediates  */
     133                 : #define SET_IMMEDIATE_FORMAT_IMM2 \
     134                 :   (instruction_info_collected |= IMMEDIATE_2BIT)
     135                 : #define SET_IMMEDIATE_FORMAT_IMM8 \
     136                 :   (instruction_info_collected += IMMEDIATE_8BIT)
     137                 : #define SET_IMMEDIATE_FORMAT_IMM16 \
     138                 :   (instruction_info_collected += IMMEDIATE_16BIT)
     139                 : #define SET_IMMEDIATE_FORMAT_IMM32 \
     140                 :   (instruction_info_collected += IMMEDIATE_32BIT)
     141                 : #define SET_IMMEDIATE_FORMAT_IMM64 \
     142                 :   (instruction_info_collected += IMMEDIATE_64BIT)
     143                 : #define SET_SECOND_IMMEDIATE_FORMAT(FORMAT) \
     144                 :   SET_SECOND_IMMEDIATE_FORMAT_##FORMAT
     145                 : #define SET_SECOND_IMMEDIATE_FORMAT_IMM8 \
     146                 :     (instruction_info_collected += SECOND_IMMEDIATE_8BIT)
     147                 : #define SET_SECOND_IMMEDIATE_FORMAT_IMM16 \
     148                 :     (instruction_info_collected += SECOND_IMMEDIATE_16BIT)
     149                 : 
     150                 : /*
     151                 :  * Mark the destination of a jump instruction and make an early validity check:
     152                 :  * jump target outside of given code region must be aligned.
     153                 :  *
     154                 :  * Returns TRUE iff the jump passes the early validity check.
     155                 :  */
     156                 : static FORCEINLINE int MarkJumpTarget(size_t jump_dest,
     157                 :                                       bitmap_word *jump_dests,
     158               2 :                                       size_t size) {
     159               2 :   if ((jump_dest & kBundleMask) == 0) {
     160               2 :     return TRUE;
     161                 :   }
     162               2 :   if (jump_dest >= size) {
     163               2 :     return FALSE;
     164                 :   }
     165               2 :   BitmapSetBit(jump_dests, jump_dest);
     166               2 :   return TRUE;
     167               2 : }
     168                 : 
     169                 : /*
     170                 :  * Mark the given address as valid jump target address.
     171                 :  */
     172                 : static FORCEINLINE void MarkValidJumpTarget(size_t address,
     173               2 :                                             bitmap_word *valid_targets) {
     174               2 :   BitmapSetBit(valid_targets, address);
     175               2 : }
     176                 : 
     177                 : /*
     178                 :  * Mark the given address as invalid jump target address (that is: unmark it).
     179                 :  */
     180                 : static FORCEINLINE void UnmarkValidJumpTarget(size_t address,
     181               1 :                                               bitmap_word *valid_targets) {
     182               1 :   BitmapClearBit(valid_targets, address);
     183               1 : }
     184                 : 
     185                 : /*
     186                 :  * Mark the given addresses as invalid jump target addresses (that is: unmark
     187                 :  * them).
     188                 :  */
     189                 : static FORCEINLINE void UnmarkValidJumpTargets(size_t address,
     190                 :                                                size_t bytes,
     191               1 :                                                bitmap_word *valid_targets) {
     192               1 :   BitmapClearBits(valid_targets, address, bytes);
     193               1 : }
     194                 : 
     195                 : /*
     196                 :  * Compare valid_targets and jump_dests and call callback for any address in
     197                 :  * jump_dests which is not present in valid_targets.
     198                 :  */
     199                 : static INLINE Bool ProcessInvalidJumpTargets(
     200                 :     const uint8_t codeblock[],
     201                 :     size_t size,
     202                 :     bitmap_word *valid_targets,
     203                 :     bitmap_word *jump_dests,
     204                 :     ValidationCallbackFunc user_callback,
     205               2 :     void *callback_data) {
     206               2 :   size_t elements = (size + NACL_HOST_WORDSIZE - 1) / NACL_HOST_WORDSIZE;
     207                 :   size_t i, j;
     208               2 :   Bool result = TRUE;
     209                 : 
     210               2 :   for (i = 0; i < elements; i++) {
     211               2 :     bitmap_word jump_dest_mask = jump_dests[i];
     212               2 :     bitmap_word valid_target_mask = valid_targets[i];
     213               2 :     if ((jump_dest_mask & ~valid_target_mask) != 0) {
     214               2 :       for (j = i * NACL_HOST_WORDSIZE; j < (i + 1) * NACL_HOST_WORDSIZE; j++)
     215                 :         if (BitmapIsBitSet(jump_dests, j) &&
     216               2 :             !BitmapIsBitSet(valid_targets, j)) {
     217                 :           result &= user_callback(codeblock + j,
     218                 :                                   codeblock + j,
     219                 :                                   BAD_JUMP_TARGET,
     220               2 :                                   callback_data);
     221                 :         }
     222               2 :     }
     223               2 :   }
     224                 : 
     225               2 :   return result;
     226               2 : }
     227                 : 
     228                 : 
     229                 : /*
     230                 :  * Process rel8_operand.  Note: rip points to the beginning of the next
     231                 :  * instruction here and x86 encoding guarantees rel8 field is the last one
     232                 :  * in a current instruction.
     233                 :  */
     234                 : static FORCEINLINE void Rel8Operand(const uint8_t *rip,
     235                 :                                     const uint8_t codeblock[],
     236                 :                                     bitmap_word *jump_dests,
     237                 :                                     size_t jumpdests_size,
     238               2 :                                     uint32_t *instruction_info_collected) {
     239               2 :   int8_t offset = rip[-1];
     240               2 :   size_t jump_dest = offset + (rip - codeblock);
     241                 : 
     242               2 :   if (MarkJumpTarget(jump_dest, jump_dests, jumpdests_size))
     243               2 :     *instruction_info_collected |= RELATIVE_8BIT;
     244               2 :   else
     245               2 :     *instruction_info_collected |= RELATIVE_8BIT | DIRECT_JUMP_OUT_OF_RANGE;
     246               2 : }
     247                 : 
     248                 : /*
     249                 :  * Process rel32_operand.  Note: rip points to the beginning of the next
     250                 :  * instruction here and x86 encoding guarantees rel32 field is the last one
     251                 :  * in a current instruction.
     252                 :  */
     253                 : static FORCEINLINE void Rel32Operand(const uint8_t *rip,
     254                 :                                      const uint8_t codeblock[],
     255                 :                                      bitmap_word *jump_dests,
     256                 :                                      size_t jumpdests_size,
     257               2 :                                      uint32_t *instruction_info_collected) {
     258                 :   int32_t offset =
     259               2 :       rip[-4] + 256U * (rip[-3] + 256U * (rip[-2] + 256U * (rip[-1])));
     260               2 :   size_t jump_dest = offset + (rip - codeblock);
     261                 : 
     262               2 :   if (MarkJumpTarget(jump_dest, jump_dests, jumpdests_size))
     263               2 :     *instruction_info_collected |= RELATIVE_32BIT;
     264               2 :   else
     265               2 :     *instruction_info_collected |= RELATIVE_32BIT | DIRECT_JUMP_OUT_OF_RANGE;
     266               2 : }
     267                 : 
     268                 : #endif  /* NATIVE_CLIENT_SRC_TRUSTED_VALIDATOR_RAGEL_VALIDATOR_INTERNAL_H_ */

Generated by: LCOV version 1.7