Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 /* | 1 /* |
| 2 * Copyright (c) 2012 The Native Client Authors. All rights reserved. | 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 | 3 * Use of this source code is governed by a BSD-style license that can be |
| 4 * found in the LICENSE file. | 4 * found in the LICENSE file. |
| 5 */ | 5 */ |
| 6 | 6 |
| 7 /* | 7 /* |
| 8 * This file contains common parts of x86-32 and x86-64 internals (inline | 8 * This file contains common parts of x86-32 and x86-64 internals (inline |
| 9 * functions and defines). | 9 * functions and defines). |
| 10 */ | 10 */ |
| 11 | 11 |
| 12 #ifndef NATIVE_CLIENT_SRC_TRUSTED_VALIDATOR_RAGEL_VALIDATOR_INTERNAL_H_ | 12 #ifndef NATIVE_CLIENT_SRC_TRUSTED_VALIDATOR_RAGEL_VALIDATOR_INTERNAL_H_ |
| 13 #define NATIVE_CLIENT_SRC_TRUSTED_VALIDATOR_RAGEL_VALIDATOR_INTERNAL_H_ | 13 #define NATIVE_CLIENT_SRC_TRUSTED_VALIDATOR_RAGEL_VALIDATOR_INTERNAL_H_ |
| 14 | 14 |
| 15 #include "native_client/src/shared/platform/nacl_check.h" | 15 #include "native_client/src/shared/platform/nacl_check.h" |
| 16 #include "native_client/src/shared/utils/types.h" | 16 #include "native_client/src/shared/utils/types.h" |
| 17 #include "native_client/src/trusted/validator_ragel/unreviewed/decoding.h" | 17 #include "native_client/src/trusted/validator_ragel/decoding.h" |
| 18 #include "native_client/src/trusted/validator_ragel/unreviewed/validator.h" | 18 #include "native_client/src/trusted/validator_ragel/unreviewed/validator.h" |
| 19 | 19 |
| 20 /* Maximum set of R-DFA allowable CPUID features. */ | 20 /* Maximum set of R-DFA allowable CPUID features. */ |
| 21 extern const NaClCPUFeaturesX86 validator_cpuid_features; | 21 extern const NaClCPUFeaturesX86 kValidatorCPUIDFeatures; |
| 22 | 22 |
| 23 /* Macroses to suppport CPUID handling. */ | 23 /* Macroses to suppport CPUID handling. */ |
| 24 #define SET_CPU_FEATURE(F) \ | 24 #define SET_CPU_FEATURE(F) \ |
| 25 if (!(F##_Allowed)) { \ | 25 if (!(F##_Allowed)) { \ |
| 26 instruction_info_collected |= UNRECOGNIZED_INSTRUCTION; \ | 26 instruction_info_collected |= UNRECOGNIZED_INSTRUCTION; \ |
| 27 } \ | 27 } \ |
| 28 if (!(F)) { \ | 28 if (!(F)) { \ |
| 29 instruction_info_collected |= CPUID_UNSUPPORTED_INSTRUCTION; \ | 29 instruction_info_collected |= CPUID_UNSUPPORTED_INSTRUCTION; \ |
| 30 } | 30 } |
| 31 #define CPUFeature_3DNOW cpu_features->data[NaClCPUFeature_3DNOW] | 31 #define CPUFeature_3DNOW cpu_features->data[NaClCPUFeature_3DNOW] |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 78 #define CPUFeature_TSC cpu_features->data[NaClCPUFeature_TSC] | 78 #define CPUFeature_TSC cpu_features->data[NaClCPUFeature_TSC] |
| 79 /* | 79 /* |
| 80 * We allow tzcnt unconditionally | 80 * We allow tzcnt unconditionally |
| 81 * See http://code.google.com/p/nativeclient/issues/detail?id=2869 | 81 * See http://code.google.com/p/nativeclient/issues/detail?id=2869 |
| 82 */ | 82 */ |
| 83 #define CPUFeature_TZCNT TRUE | 83 #define CPUFeature_TZCNT TRUE |
| 84 #define CPUFeature_x87 cpu_features->data[NaClCPUFeature_x87] | 84 #define CPUFeature_x87 cpu_features->data[NaClCPUFeature_x87] |
| 85 #define CPUFeature_XOP cpu_features->data[NaClCPUFeature_XOP] | 85 #define CPUFeature_XOP cpu_features->data[NaClCPUFeature_XOP] |
| 86 | 86 |
| 87 #define CPUFeature_3DNOW_Allowed \ | 87 #define CPUFeature_3DNOW_Allowed \ |
| 88 validator_cpuid_features.data[NaClCPUFeature_3DNOW] | 88 kValidatorCPUIDFeatures.data[NaClCPUFeature_3DNOW] |
| 89 /* | 89 /* |
| 90 * AMD documentation claims it's always available if CPUFeature_LM is present, | 90 * AMD documentation claims it's always available if CPUFeature_LM is present, |
| 91 * But Intel documentation does not even mention it! | 91 * But Intel documentation does not even mention it! |
| 92 * Keep it as 3DNow! instruction. | 92 * Keep it as 3DNow! instruction. |
| 93 */ | 93 */ |
| 94 #define CPUFeature_3DPRFTCH_Allowed \ | 94 #define CPUFeature_3DPRFTCH_Allowed \ |
| 95 CPUFeature_3DNOW_Allowed || CPUFeature_PRE_Allowed | 95 CPUFeature_3DNOW_Allowed || CPUFeature_PRE_Allowed |
| 96 #define CPUFeature_AES_Allowed \ | 96 #define CPUFeature_AES_Allowed \ |
| 97 validator_cpuid_features.data[NaClCPUFeature_AES] | 97 kValidatorCPUIDFeatures.data[NaClCPUFeature_AES] |
| 98 #define CPUFeature_AESAVX_Allowed \ | 98 #define CPUFeature_AESAVX_Allowed \ |
| 99 CPUFeature_AES_Allowed && CPUFeature_AVX_Allowed | 99 CPUFeature_AES_Allowed && CPUFeature_AVX_Allowed |
| 100 #define CPUFeature_AVX_Allowed \ | 100 #define CPUFeature_AVX_Allowed \ |
| 101 validator_cpuid_features.data[NaClCPUFeature_AVX] | 101 kValidatorCPUIDFeatures.data[NaClCPUFeature_AVX] |
| 102 #define CPUFeature_BMI1_Allowed \ | 102 #define CPUFeature_BMI1_Allowed \ |
| 103 validator_cpuid_features.data[NaClCPUFeature_BMI1] | 103 kValidatorCPUIDFeatures.data[NaClCPUFeature_BMI1] |
| 104 #define CPUFeature_CLFLUSH_Allowed \ | 104 #define CPUFeature_CLFLUSH_Allowed \ |
| 105 validator_cpuid_features.data[NaClCPUFeature_CLFLUSH] | 105 kValidatorCPUIDFeatures.data[NaClCPUFeature_CLFLUSH] |
| 106 #define CPUFeature_CLMUL_Allowed \ | 106 #define CPUFeature_CLMUL_Allowed \ |
| 107 validator_cpuid_features.data[NaClCPUFeature_CLMUL] | 107 kValidatorCPUIDFeatures.data[NaClCPUFeature_CLMUL] |
| 108 #define CPUFeature_CLMULAVX_Allowed \ | 108 #define CPUFeature_CLMULAVX_Allowed \ |
| 109 CPUFeature_CLMUL_Allowed && CPUFeature_AVX_Allowed | 109 CPUFeature_CLMUL_Allowed && CPUFeature_AVX_Allowed |
| 110 #define CPUFeature_CMOV_Allowed \ | 110 #define CPUFeature_CMOV_Allowed \ |
| 111 validator_cpuid_features.data[NaClCPUFeature_CMOV] | 111 kValidatorCPUIDFeatures.data[NaClCPUFeature_CMOV] |
| 112 #define CPUFeature_CMOVx87_Allowed \ | 112 #define CPUFeature_CMOVx87_Allowed \ |
| 113 CPUFeature_CMOV_Allowed && CPUFeature_x87_Allowed | 113 CPUFeature_CMOV_Allowed && CPUFeature_x87_Allowed |
| 114 #define CPUFeature_CX16_Allowed \ | 114 #define CPUFeature_CX16_Allowed \ |
| 115 validator_cpuid_features.data[NaClCPUFeature_CX16] | 115 kValidatorCPUIDFeatures.data[NaClCPUFeature_CX16] |
| 116 #define CPUFeature_CX8_Allowed \ | 116 #define CPUFeature_CX8_Allowed \ |
| 117 validator_cpuid_features.data[NaClCPUFeature_CX8] | 117 kValidatorCPUIDFeatures.data[NaClCPUFeature_CX8] |
| 118 #define CPUFeature_E3DNOW_Allowed \ | 118 #define CPUFeature_E3DNOW_Allowed \ |
| 119 validator_cpuid_features.data[NaClCPUFeature_E3DNOW] | 119 kValidatorCPUIDFeatures.data[NaClCPUFeature_E3DNOW] |
| 120 #define CPUFeature_EMMX_Allowed \ | 120 #define CPUFeature_EMMX_Allowed \ |
| 121 validator_cpuid_features.data[NaClCPUFeature_EMMX] | 121 kValidatorCPUIDFeatures.data[NaClCPUFeature_EMMX] |
| 122 #define CPUFeature_EMMXSSE_Allowed \ | 122 #define CPUFeature_EMMXSSE_Allowed \ |
| 123 CPUFeature_EMMX_Allowed || CPUFeature_SSE_Allowed | 123 CPUFeature_EMMX_Allowed || CPUFeature_SSE_Allowed |
| 124 #define CPUFeature_F16C_Allowed \ | 124 #define CPUFeature_F16C_Allowed \ |
| 125 validator_cpuid_features.data[NaClCPUFeature_F16C] | 125 kValidatorCPUIDFeatures.data[NaClCPUFeature_F16C] |
| 126 #define CPUFeature_FMA_Allowed \ | 126 #define CPUFeature_FMA_Allowed \ |
| 127 validator_cpuid_features.data[NaClCPUFeature_FMA] | 127 kValidatorCPUIDFeatures.data[NaClCPUFeature_FMA] |
| 128 #define CPUFeature_FMA4_Allowed \ | 128 #define CPUFeature_FMA4_Allowed \ |
| 129 validator_cpuid_features.data[NaClCPUFeature_FMA4] | 129 kValidatorCPUIDFeatures.data[NaClCPUFeature_FMA4] |
| 130 #define CPUFeature_FXSR_Allowed \ | 130 #define CPUFeature_FXSR_Allowed \ |
| 131 validator_cpuid_features.data[NaClCPUFeature_FXSR] | 131 kValidatorCPUIDFeatures.data[NaClCPUFeature_FXSR] |
| 132 #define CPUFeature_LAHF_Allowed \ | 132 #define CPUFeature_LAHF_Allowed \ |
| 133 validator_cpuid_features.data[NaClCPUFeature_LAHF] | 133 kValidatorCPUIDFeatures.data[NaClCPUFeature_LAHF] |
| 134 #define CPUFeature_LM_Allowed \ | 134 #define CPUFeature_LM_Allowed \ |
| 135 validator_cpuid_features.data[NaClCPUFeature_LM] | 135 kValidatorCPUIDFeatures.data[NaClCPUFeature_LM] |
| 136 #define CPUFeature_LWP_Allowed \ | 136 #define CPUFeature_LWP_Allowed \ |
| 137 validator_cpuid_features.data[NaClCPUFeature_LWP] | 137 kValidatorCPUIDFeatures.data[NaClCPUFeature_LWP] |
| 138 /* | 138 /* |
| 139 * We allow lzcnt unconditionally | 139 * We allow lzcnt unconditionally |
| 140 * See http://code.google.com/p/nativeclient/issues/detail?id=2869 | 140 * See http://code.google.com/p/nativeclient/issues/detail?id=2869 |
| 141 */ | 141 */ |
| 142 #define CPUFeature_LZCNT_Allowed TRUE | 142 #define CPUFeature_LZCNT_Allowed TRUE |
| 143 #define CPUFeature_MMX_Allowed \ | 143 #define CPUFeature_MMX_Allowed \ |
| 144 validator_cpuid_features.data[NaClCPUFeature_MMX] | 144 kValidatorCPUIDFeatures.data[NaClCPUFeature_MMX] |
| 145 #define CPUFeature_MON_Allowed \ | 145 #define CPUFeature_MON_Allowed \ |
| 146 validator_cpuid_features.data[NaClCPUFeature_MON] | 146 kValidatorCPUIDFeatures.data[NaClCPUFeature_MON] |
| 147 #define CPUFeature_MOVBE_Allowed \ | 147 #define CPUFeature_MOVBE_Allowed \ |
| 148 validator_cpuid_features.data[NaClCPUFeature_MOVBE] | 148 kValidatorCPUIDFeatures.data[NaClCPUFeature_MOVBE] |
| 149 #define CPUFeature_OSXSAVE_Allowed \ | 149 #define CPUFeature_OSXSAVE_Allowed \ |
| 150 validator_cpuid_features.data[NaClCPUFeature_OSXSAVE] | 150 kValidatorCPUIDFeatures.data[NaClCPUFeature_OSXSAVE] |
| 151 #define CPUFeature_POPCNT_Allowed \ | 151 #define CPUFeature_POPCNT_Allowed \ |
| 152 validator_cpuid_features.data[NaClCPUFeature_POPCNT] | 152 kValidatorCPUIDFeatures.data[NaClCPUFeature_POPCNT] |
| 153 #define CPUFeature_PRE_Allowed \ | 153 #define CPUFeature_PRE_Allowed \ |
| 154 validator_cpuid_features.data[NaClCPUFeature_PRE] | 154 kValidatorCPUIDFeatures.data[NaClCPUFeature_PRE] |
| 155 #define CPUFeature_SSE_Allowed \ | 155 #define CPUFeature_SSE_Allowed \ |
| 156 validator_cpuid_features.data[NaClCPUFeature_SSE] | 156 kValidatorCPUIDFeatures.data[NaClCPUFeature_SSE] |
| 157 #define CPUFeature_SSE2_Allowed \ | 157 #define CPUFeature_SSE2_Allowed \ |
| 158 validator_cpuid_features.data[NaClCPUFeature_SSE2] | 158 kValidatorCPUIDFeatures.data[NaClCPUFeature_SSE2] |
| 159 #define CPUFeature_SSE3_Allowed \ | 159 #define CPUFeature_SSE3_Allowed \ |
| 160 validator_cpuid_features.data[NaClCPUFeature_SSE3] | 160 kValidatorCPUIDFeatures.data[NaClCPUFeature_SSE3] |
| 161 #define CPUFeature_SSE41_Allowed \ | 161 #define CPUFeature_SSE41_Allowed \ |
| 162 validator_cpuid_features.data[NaClCPUFeature_SSE41] | 162 kValidatorCPUIDFeatures.data[NaClCPUFeature_SSE41] |
| 163 #define CPUFeature_SSE42_Allowed \ | 163 #define CPUFeature_SSE42_Allowed \ |
| 164 validator_cpuid_features.data[NaClCPUFeature_SSE42] | 164 kValidatorCPUIDFeatures.data[NaClCPUFeature_SSE42] |
| 165 #define CPUFeature_SSE4A_Allowed \ | 165 #define CPUFeature_SSE4A_Allowed \ |
| 166 validator_cpuid_features.data[NaClCPUFeature_SSE4A] | 166 kValidatorCPUIDFeatures.data[NaClCPUFeature_SSE4A] |
| 167 #define CPUFeature_SSSE3_Allowed \ | 167 #define CPUFeature_SSSE3_Allowed \ |
| 168 validator_cpuid_features.data[NaClCPUFeature_SSSE3] | 168 kValidatorCPUIDFeatures.data[NaClCPUFeature_SSSE3] |
| 169 #define CPUFeature_TBM_Allowed \ | 169 #define CPUFeature_TBM_Allowed \ |
| 170 validator_cpuid_features.data[NaClCPUFeature_TBM] | 170 kValidatorCPUIDFeatures.data[NaClCPUFeature_TBM] |
| 171 #define CPUFeature_TSC_Allowed \ | 171 #define CPUFeature_TSC_Allowed \ |
| 172 validator_cpuid_features.data[NaClCPUFeature_TSC] | 172 kValidatorCPUIDFeatures.data[NaClCPUFeature_TSC] |
| 173 /* | 173 /* |
| 174 * We allow tzcnt unconditionally | 174 * We allow tzcnt unconditionally |
| 175 * See http://code.google.com/p/nativeclient/issues/detail?id=2869 | 175 * See http://code.google.com/p/nativeclient/issues/detail?id=2869 |
| 176 */ | 176 */ |
| 177 #define CPUFeature_TZCNT_Allowed TRUE | 177 #define CPUFeature_TZCNT_Allowed TRUE |
| 178 #define CPUFeature_x87_Allowed \ | 178 #define CPUFeature_x87_Allowed \ |
| 179 validator_cpuid_features.data[NaClCPUFeature_x87] | 179 kValidatorCPUIDFeatures.data[NaClCPUFeature_x87] |
| 180 #define CPUFeature_XOP_Allowed \ | 180 #define CPUFeature_XOP_Allowed \ |
| 181 validator_cpuid_features.data[NaClCPUFeature_XOP] | 181 kValidatorCPUIDFeatures.data[NaClCPUFeature_XOP] |
| 182 | 182 |
| 183 /* Remember some information about instruction for further processing. */ | 183 /* Remember some information about instruction for further processing. */ |
| 184 #define GET_REX_PREFIX() rex_prefix | 184 #define GET_REX_PREFIX() rex_prefix |
| 185 #define SET_REX_PREFIX(P) rex_prefix = (P) | 185 #define SET_REX_PREFIX(P) rex_prefix = (P) |
| 186 #define GET_VEX_PREFIX2() vex_prefix2 | 186 #define GET_VEX_PREFIX2() vex_prefix2 |
| 187 #define SET_VEX_PREFIX2(P) vex_prefix2 = (P) | 187 #define SET_VEX_PREFIX2(P) vex_prefix2 = (P) |
| 188 #define GET_VEX_PREFIX3() vex_prefix3 | 188 #define GET_VEX_PREFIX3() vex_prefix3 |
| 189 #define SET_VEX_PREFIX3(P) vex_prefix3 = (P) | 189 #define SET_VEX_PREFIX3(P) vex_prefix3 = (P) |
| 190 #define SET_MODRM_BASE(N) base = (N) | 190 #define SET_MODRM_BASE(N) base = (N) |
| 191 #define SET_MODRM_INDEX(N) index = (N) | 191 #define SET_MODRM_INDEX(N) index = (N) |
| (...skipping 14 matching lines...) Expand all Loading... | |
| 206 * 8bit operands must be distinguished from other types because the REX prefix | 206 * 8bit operands must be distinguished from other types because the REX prefix |
| 207 * regulates the choice between %ah and %spl, as well as %ch and %bpl. | 207 * regulates the choice between %ah and %spl, as well as %ch and %bpl. |
| 208 */ | 208 */ |
| 209 OperandSandbox8bit, | 209 OperandSandbox8bit, |
| 210 OperandSandboxRestricted, | 210 OperandSandboxRestricted, |
| 211 OperandSandboxUnrestricted | 211 OperandSandboxUnrestricted |
| 212 }; | 212 }; |
| 213 | 213 |
| 214 #define SET_OPERAND_NAME(N, S) operand_states |= ((S) << ((N) << 3)) | 214 #define SET_OPERAND_NAME(N, S) operand_states |= ((S) << ((N) << 3)) |
| 215 #define SET_OPERAND_TYPE(N, T) SET_OPERAND_TYPE_ ## T(N) | 215 #define SET_OPERAND_TYPE(N, T) SET_OPERAND_TYPE_ ## T(N) |
| 216 #define SET_OPERAND_TYPE_OPERAND_SIZE_8_BIT(N) \ | 216 #define SET_OPERAND_TYPE_OPERAND_TYPE_8_BIT(N) \ |
| 217 operand_states |= OperandSandbox8bit << (5 + ((N) << 3)) | 217 operand_states |= OperandSandbox8bit << (5 + ((N) << 3)) |
| 218 #define SET_OPERAND_TYPE_OPERAND_SIZE_16_BIT(N) \ | 218 #define SET_OPERAND_TYPE_OPERAND_TYPE_16_BIT(N) \ |
| 219 operand_states |= OperandSandboxUnrestricted << (5 + ((N) << 3)) | 219 operand_states |= OperandSandboxUnrestricted << (5 + ((N) << 3)) |
| 220 #define SET_OPERAND_TYPE_OPERAND_SIZE_32_BIT(N) \ | 220 #define SET_OPERAND_TYPE_OPERAND_TYPE_32_BIT(N) \ |
| 221 operand_states |= OperandSandboxRestricted << (5 + ((N) << 3)) | 221 operand_states |= OperandSandboxRestricted << (5 + ((N) << 3)) |
| 222 #define SET_OPERAND_TYPE_OPERAND_SIZE_64_BIT(N) \ | 222 #define SET_OPERAND_TYPE_OPERAND_TYPE_64_BIT(N) \ |
| 223 operand_states |= OperandSandboxUnrestricted << (5 + ((N) << 3)) | 223 operand_states |= OperandSandboxUnrestricted << (5 + ((N) << 3)) |
| 224 #define CHECK_OPERAND(N, S, T) \ | 224 #define CHECK_OPERAND(N, S, T) \ |
| 225 ((operand_states & (0xff << ((N) << 3))) == ((S | (T << 5)) << ((N) << 3))) | 225 ((operand_states & (0xff << ((N) << 3))) == ((S | (T << 5)) << ((N) << 3))) |
| 226 | 226 |
| 227 /* Ignore this information for now. */ | 227 /* Ignore this information for now. */ |
| 228 #define SET_DATA16_PREFIX(S) | 228 #define SET_DATA16_PREFIX(S) |
| 229 #define SET_LOCK_PREFIX(S) | 229 #define SET_LOCK_PREFIX(S) |
| 230 #define SET_REPZ_PREFIX(S) | 230 #define SET_REPZ_PREFIX(S) |
| 231 #define SET_REPNZ_PREFIX(S) | 231 #define SET_REPNZ_PREFIX(S) |
| 232 #define SET_BRANCH_TAKEN(S) | 232 #define SET_BRANCH_TAKEN(S) |
| (...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 297 (((((bitmap_word)1) << bits) - 1) << (index % NACL_HOST_WORDSIZE))) != 0; | 297 (((((bitmap_word)1) << bits) - 1) << (index % NACL_HOST_WORDSIZE))) != 0; |
| 298 } | 298 } |
| 299 | 299 |
| 300 /* All the bits must be in a single 32-bit bundle. */ | 300 /* All the bits must be in a single 32-bit bundle. */ |
| 301 static FORCEINLINE void BitmapSetBits(bitmap_word *bitmap, | 301 static FORCEINLINE void BitmapSetBits(bitmap_word *bitmap, |
| 302 size_t index, size_t bits) { | 302 size_t index, size_t bits) { |
| 303 bitmap[index / NACL_HOST_WORDSIZE] |= | 303 bitmap[index / NACL_HOST_WORDSIZE] |= |
| 304 ((((bitmap_word)1) << bits) - 1) << (index % NACL_HOST_WORDSIZE); | 304 ((((bitmap_word)1) << bits) - 1) << (index % NACL_HOST_WORDSIZE); |
| 305 } | 305 } |
| 306 | 306 |
| 307 /* Mark the destination of a jump instruction and make an early validity check: | 307 /* |
| 308 * Mark the destination of a jump instruction and make an early validity check: | |
| 308 * to jump outside given code region, the target address must be aligned. | 309 * to jump outside given code region, the target address must be aligned. |
| 309 * | 310 * |
| 310 * Returns TRUE iff the jump passes the early validity check. | 311 * Returns TRUE iff the jump passes the early validity check. |
| 311 */ | 312 */ |
| 312 static FORCEINLINE int MarkJumpTarget(size_t jump_dest, | 313 static FORCEINLINE int MarkJumpTarget(size_t jump_dest, |
| 313 bitmap_word *jump_dests, | 314 bitmap_word *jump_dests, |
| 314 size_t size) { | 315 size_t size) { |
| 315 if ((jump_dest & kBundleMask) == 0) { | 316 if ((jump_dest & kBundleMask) == 0) { |
| 316 return TRUE; | 317 return TRUE; |
| 317 } | 318 } |
| 318 if (jump_dest >= size) { | 319 if (jump_dest >= size) { |
| 319 return FALSE; | 320 return FALSE; |
| 320 } | 321 } |
| 321 BitmapSetBit(jump_dests, jump_dest); | 322 BitmapSetBit(jump_dests, jump_dest); |
| 322 return TRUE; | 323 return TRUE; |
| 323 } | 324 } |
| 324 | 325 |
| 326 /* | |
| 327 * Mark the gived address as valid jump target address. | |
|
Brad Chen
2012/10/05 16:47:21
"given"?
khim
2012/10/15 16:38:57
Done.
| |
| 328 */ | |
| 329 static FORCEINLINE void MakeJumpTargetValid(size_t address, | |
| 330 bitmap_word *valid_targets) { | |
| 331 BitmapSetBit(valid_targets, address); | |
| 332 } | |
| 333 | |
| 334 /* | |
| 335 * Mark the gived address as invalid jump target address. | |
|
Brad Chen
2012/10/05 16:47:21
"given"?
khim
2012/10/15 16:38:57
Done.
| |
| 336 */ | |
| 337 static FORCEINLINE void MakeInvalidJumpTarget(size_t address, | |
| 338 bitmap_word *valid_targets) { | |
| 339 BitmapClearBit(valid_targets, address); | |
| 340 } | |
| 325 | 341 |
| 326 static INLINE Bool ProcessInvalidJumpTargets( | 342 static INLINE Bool ProcessInvalidJumpTargets( |
| 327 const uint8_t *data, | 343 const uint8_t *data, |
| 328 size_t size, | 344 size_t size, |
| 329 bitmap_word *valid_targets, | 345 bitmap_word *valid_targets, |
| 330 bitmap_word *jump_dests, | 346 bitmap_word *jump_dests, |
| 331 validation_callback_func user_callback, | 347 ValidationCallbackFunc user_callback, |
| 332 void *callback_data) { | 348 void *callback_data) { |
| 333 size_t elements = (size + NACL_HOST_WORDSIZE - 1) / NACL_HOST_WORDSIZE; | 349 size_t elements = (size + NACL_HOST_WORDSIZE - 1) / NACL_HOST_WORDSIZE; |
| 334 size_t i, j; | 350 size_t i, j; |
| 335 Bool result = TRUE; | 351 Bool result = TRUE; |
| 336 | 352 |
| 337 for (i = 0; i < elements ; i++) { | 353 for (i = 0; i < elements ; i++) { |
| 338 bitmap_word jump_dest_mask = jump_dests[i]; | 354 bitmap_word jump_dest_mask = jump_dests[i]; |
| 339 bitmap_word valid_target_mask = valid_targets[i]; | 355 bitmap_word valid_target_mask = valid_targets[i]; |
| 340 if ((jump_dest_mask & ~valid_target_mask) != 0) { | 356 if ((jump_dest_mask & ~valid_target_mask) != 0) { |
| 341 for (j = i * NACL_HOST_WORDSIZE; j < (i + 1) * NACL_HOST_WORDSIZE; j++) | 357 for (j = i * NACL_HOST_WORDSIZE; j < (i + 1) * NACL_HOST_WORDSIZE; j++) |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 386 rip[-2] + 256U * ((uint32_t) rip[-1])))); | 402 rip[-2] + 256U * ((uint32_t) rip[-1])))); |
| 387 size_t jump_dest = offset + (rip - codeblock_start); | 403 size_t jump_dest = offset + (rip - codeblock_start); |
| 388 | 404 |
| 389 if (MarkJumpTarget(jump_dest, jump_dests, jumpdests_size)) | 405 if (MarkJumpTarget(jump_dest, jump_dests, jumpdests_size)) |
| 390 *instruction_info_collected |= RELATIVE_32BIT; | 406 *instruction_info_collected |= RELATIVE_32BIT; |
| 391 else | 407 else |
| 392 *instruction_info_collected |= RELATIVE_32BIT | DIRECT_JUMP_OUT_OF_RANGE; | 408 *instruction_info_collected |= RELATIVE_32BIT | DIRECT_JUMP_OUT_OF_RANGE; |
| 393 } | 409 } |
| 394 | 410 |
| 395 static INLINE void check_access(ptrdiff_t instruction_start, | 411 static INLINE void check_access(ptrdiff_t instruction_start, |
| 396 enum register_name base, | 412 enum OperandName base, |
| 397 enum register_name index, | 413 enum OperandName index, |
| 398 uint8_t restricted_register, | 414 uint8_t restricted_register, |
| 399 bitmap_word *valid_targets, | 415 bitmap_word *valid_targets, |
| 400 uint32_t *instruction_info_collected) { | 416 uint32_t *instruction_info_collected) { |
| 401 if ((base == REG_RIP) || (base == REG_R15) || | 417 if ((base == REG_RIP) || (base == REG_R15) || |
| 402 (base == REG_RSP) || (base == REG_RBP)) { | 418 (base == REG_RSP) || (base == REG_RBP)) { |
| 403 if ((index == NO_REG) || (index == REG_RIZ)) | 419 if ((index == NO_REG) || (index == REG_RIZ)) |
| 404 { /* do nothing. */ } | 420 { /* do nothing. */ } |
| 405 else if (index == restricted_register) | 421 else if (index == restricted_register) |
| 406 BitmapClearBit(valid_targets, instruction_start), | 422 BitmapClearBit(valid_targets, instruction_start), |
| 407 *instruction_info_collected |= RESTRICTED_REGISTER_USED; | 423 *instruction_info_collected |= RESTRICTED_REGISTER_USED; |
| 408 else | 424 else |
| 409 *instruction_info_collected |= UNRESTRICTED_INDEX_REGISTER; | 425 *instruction_info_collected |= UNRESTRICTED_INDEX_REGISTER; |
| 410 } else { | 426 } else { |
| 411 *instruction_info_collected |= FORBIDDEN_BASE_REGISTER; | 427 *instruction_info_collected |= FORBIDDEN_BASE_REGISTER; |
| 412 } | 428 } |
| 413 } | 429 } |
| 414 | 430 |
| 415 | 431 |
| 416 static INLINE void process_0_operands(enum register_name *restricted_register, | 432 static INLINE void process_0_operands(enum OperandName *restricted_register, |
| 417 uint32_t *instruction_info_collected) { | 433 uint32_t *instruction_info_collected) { |
| 418 /* Restricted %rsp or %rbp must be processed by appropriate nacl-special | 434 /* Restricted %rsp or %rbp must be processed by appropriate nacl-special |
| 419 * instruction, not with regular instruction. */ | 435 * instruction, not with regular instruction. */ |
| 420 if (*restricted_register == REG_RSP) { | 436 if (*restricted_register == REG_RSP) { |
| 421 *instruction_info_collected |= RESTRICTED_RSP_UNPROCESSED; | 437 *instruction_info_collected |= RESTRICTED_RSP_UNPROCESSED; |
| 422 } else if (*restricted_register == REG_RBP) { | 438 } else if (*restricted_register == REG_RBP) { |
| 423 *instruction_info_collected |= RESTRICTED_RBP_UNPROCESSED; | 439 *instruction_info_collected |= RESTRICTED_RBP_UNPROCESSED; |
| 424 } | 440 } |
| 425 *restricted_register = NO_REG; | 441 *restricted_register = NO_REG; |
| 426 } | 442 } |
| 427 | 443 |
| 428 static INLINE void process_1_operand(enum register_name *restricted_register, | 444 static INLINE void process_1_operand(enum OperandName *restricted_register, |
| 429 uint32_t *instruction_info_collected, | 445 uint32_t *instruction_info_collected, |
| 430 uint8_t rex_prefix, | 446 uint8_t rex_prefix, |
| 431 uint32_t operand_states) { | 447 uint32_t operand_states) { |
| 432 /* Restricted %rsp or %rbp must be processed by appropriate nacl-special | 448 /* Restricted %rsp or %rbp must be processed by appropriate nacl-special |
| 433 * instruction, not with regular instruction. */ | 449 * instruction, not with regular instruction. */ |
| 434 if (*restricted_register == REG_RSP) { | 450 if (*restricted_register == REG_RSP) { |
| 435 *instruction_info_collected |= RESTRICTED_RSP_UNPROCESSED; | 451 *instruction_info_collected |= RESTRICTED_RSP_UNPROCESSED; |
| 436 } else if (*restricted_register == REG_RBP) { | 452 } else if (*restricted_register == REG_RBP) { |
| 437 *instruction_info_collected |= RESTRICTED_RBP_UNPROCESSED; | 453 *instruction_info_collected |= RESTRICTED_RBP_UNPROCESSED; |
| 438 } | 454 } |
| 439 *restricted_register = NO_REG; | 455 *restricted_register = NO_REG; |
| 440 if (CHECK_OPERAND(0, REG_R15, OperandSandbox8bit) || | 456 if (CHECK_OPERAND(0, REG_R15, OperandSandbox8bit) || |
| 441 CHECK_OPERAND(0, REG_R15, OperandSandboxRestricted) || | 457 CHECK_OPERAND(0, REG_R15, OperandSandboxRestricted) || |
| 442 CHECK_OPERAND(0, REG_R15, OperandSandboxUnrestricted)) { | 458 CHECK_OPERAND(0, REG_R15, OperandSandboxUnrestricted)) { |
| 443 *instruction_info_collected |= R15_MODIFIED; | 459 *instruction_info_collected |= R15_MODIFIED; |
| 444 } else if ((CHECK_OPERAND(0, REG_RBP, OperandSandbox8bit) && rex_prefix) || | 460 } else if ((CHECK_OPERAND(0, REG_RBP, OperandSandbox8bit) && rex_prefix) || |
| 445 CHECK_OPERAND(0, REG_RBP, OperandSandboxRestricted) || | 461 CHECK_OPERAND(0, REG_RBP, OperandSandboxRestricted) || |
| 446 CHECK_OPERAND(0, REG_RBP, OperandSandboxUnrestricted)) { | 462 CHECK_OPERAND(0, REG_RBP, OperandSandboxUnrestricted)) { |
| 447 *instruction_info_collected |= BPL_MODIFIED; | 463 *instruction_info_collected |= BPL_MODIFIED; |
| 448 } else if ((CHECK_OPERAND(0, REG_RSP, OperandSandbox8bit) && rex_prefix) || | 464 } else if ((CHECK_OPERAND(0, REG_RSP, OperandSandbox8bit) && rex_prefix) || |
| 449 CHECK_OPERAND(0, REG_RSP, OperandSandboxRestricted) || | 465 CHECK_OPERAND(0, REG_RSP, OperandSandboxRestricted) || |
| 450 CHECK_OPERAND(0, REG_RSP, OperandSandboxUnrestricted)) { | 466 CHECK_OPERAND(0, REG_RSP, OperandSandboxUnrestricted)) { |
| 451 *instruction_info_collected |= SPL_MODIFIED; | 467 *instruction_info_collected |= SPL_MODIFIED; |
| 452 } | 468 } |
| 453 } | 469 } |
| 454 | 470 |
| 455 static INLINE void process_1_operand_zero_extends( | 471 static INLINE void process_1_operand_zero_extends( |
| 456 enum register_name *restricted_register, | 472 enum OperandName *restricted_register, |
| 457 uint32_t *instruction_info_collected, uint8_t rex_prefix, | 473 uint32_t *instruction_info_collected, uint8_t rex_prefix, |
| 458 uint32_t operand_states) { | 474 uint32_t operand_states) { |
| 459 /* Restricted %rsp or %rbp must be processed by appropriate nacl-special | 475 /* Restricted %rsp or %rbp must be processed by appropriate nacl-special |
| 460 * instruction, not with regular instruction. */ | 476 * instruction, not with regular instruction. */ |
| 461 if (*restricted_register == REG_RSP) { | 477 if (*restricted_register == REG_RSP) { |
| 462 *instruction_info_collected |= RESTRICTED_RSP_UNPROCESSED; | 478 *instruction_info_collected |= RESTRICTED_RSP_UNPROCESSED; |
| 463 } else if (*restricted_register == REG_RBP) { | 479 } else if (*restricted_register == REG_RBP) { |
| 464 *instruction_info_collected |= RESTRICTED_RBP_UNPROCESSED; | 480 *instruction_info_collected |= RESTRICTED_RBP_UNPROCESSED; |
| 465 } | 481 } |
| 466 *restricted_register = NO_REG; | 482 *restricted_register = NO_REG; |
| 467 if (CHECK_OPERAND(0, REG_R15, OperandSandbox8bit) || | 483 if (CHECK_OPERAND(0, REG_R15, OperandSandbox8bit) || |
| 468 CHECK_OPERAND(0, REG_R15, OperandSandboxRestricted) || | 484 CHECK_OPERAND(0, REG_R15, OperandSandboxRestricted) || |
| 469 CHECK_OPERAND(0, REG_R15, OperandSandboxUnrestricted)) { | 485 CHECK_OPERAND(0, REG_R15, OperandSandboxUnrestricted)) { |
| 470 *instruction_info_collected |= R15_MODIFIED; | 486 *instruction_info_collected |= R15_MODIFIED; |
| 471 } else if ((CHECK_OPERAND(0, REG_RBP, OperandSandbox8bit) && rex_prefix) || | 487 } else if ((CHECK_OPERAND(0, REG_RBP, OperandSandbox8bit) && rex_prefix) || |
| 472 CHECK_OPERAND(0, REG_RBP, OperandSandboxUnrestricted)) { | 488 CHECK_OPERAND(0, REG_RBP, OperandSandboxUnrestricted)) { |
| 473 *instruction_info_collected |= BPL_MODIFIED; | 489 *instruction_info_collected |= BPL_MODIFIED; |
| 474 } else if ((CHECK_OPERAND(0, REG_RSP, OperandSandbox8bit) && rex_prefix) || | 490 } else if ((CHECK_OPERAND(0, REG_RSP, OperandSandbox8bit) && rex_prefix) || |
| 475 CHECK_OPERAND(0, REG_RSP, OperandSandboxUnrestricted)) { | 491 CHECK_OPERAND(0, REG_RSP, OperandSandboxUnrestricted)) { |
| 476 *instruction_info_collected |= SPL_MODIFIED; | 492 *instruction_info_collected |= SPL_MODIFIED; |
| 477 /* Take 2 bits of operand type from operand_states as *restricted_register, | 493 /* Take 2 bits of operand type from operand_states as *restricted_register, |
| 478 * make sure operand_states denotes a register (4th bit == 0). */ | 494 * make sure operand_states denotes a register (4th bit == 0). */ |
| 479 } else if ((operand_states & 0x70) == (OperandSandboxRestricted << 5)) { | 495 } else if ((operand_states & 0x70) == (OperandSandboxRestricted << 5)) { |
| 480 *restricted_register = operand_states & 0x0f; | 496 *restricted_register = operand_states & 0x0f; |
| 481 } | 497 } |
| 482 } | 498 } |
| 483 | 499 |
| 484 static INLINE void process_2_operands(enum register_name *restricted_register, | 500 static INLINE void process_2_operands(enum OperandName *restricted_register, |
| 485 uint32_t *instruction_info_collected, | 501 uint32_t *instruction_info_collected, |
| 486 uint8_t rex_prefix, | 502 uint8_t rex_prefix, |
| 487 uint32_t operand_states) { | 503 uint32_t operand_states) { |
| 488 /* Restricted %rsp or %rbp must be processed by appropriate nacl-special | 504 /* Restricted %rsp or %rbp must be processed by appropriate nacl-special |
| 489 * instruction, not with regular instruction. */ | 505 * instruction, not with regular instruction. */ |
| 490 if (*restricted_register == REG_RSP) { | 506 if (*restricted_register == REG_RSP) { |
| 491 *instruction_info_collected |= RESTRICTED_RSP_UNPROCESSED; | 507 *instruction_info_collected |= RESTRICTED_RSP_UNPROCESSED; |
| 492 } else if (*restricted_register == REG_RBP) { | 508 } else if (*restricted_register == REG_RBP) { |
| 493 *instruction_info_collected |= RESTRICTED_RBP_UNPROCESSED; | 509 *instruction_info_collected |= RESTRICTED_RBP_UNPROCESSED; |
| 494 } | 510 } |
| (...skipping 15 matching lines...) Expand all Loading... | |
| 510 } else if ((CHECK_OPERAND(0, REG_RSP, OperandSandbox8bit) && rex_prefix) || | 526 } else if ((CHECK_OPERAND(0, REG_RSP, OperandSandbox8bit) && rex_prefix) || |
| 511 CHECK_OPERAND(0, REG_RSP, OperandSandboxRestricted) || | 527 CHECK_OPERAND(0, REG_RSP, OperandSandboxRestricted) || |
| 512 CHECK_OPERAND(0, REG_RSP, OperandSandboxUnrestricted) || | 528 CHECK_OPERAND(0, REG_RSP, OperandSandboxUnrestricted) || |
| 513 (CHECK_OPERAND(1, REG_RSP, OperandSandbox8bit) && rex_prefix) || | 529 (CHECK_OPERAND(1, REG_RSP, OperandSandbox8bit) && rex_prefix) || |
| 514 CHECK_OPERAND(1, REG_RSP, OperandSandboxRestricted) || | 530 CHECK_OPERAND(1, REG_RSP, OperandSandboxRestricted) || |
| 515 CHECK_OPERAND(1, REG_RSP, OperandSandboxUnrestricted)) { | 531 CHECK_OPERAND(1, REG_RSP, OperandSandboxUnrestricted)) { |
| 516 *instruction_info_collected |= SPL_MODIFIED; | 532 *instruction_info_collected |= SPL_MODIFIED; |
| 517 } | 533 } |
| 518 } | 534 } |
| 519 | 535 |
| 520 static INLINE void process_2_operands_zero_extends( | 536 static INLINE void process_2_operands_zero_extends( |
|
Brad Chen
2012/10/05 16:47:21
All these non-standard procedure names need to be
khim
2012/10/15 16:38:57
Done.
| |
| 521 enum register_name *restricted_register, | 537 enum OperandName *restricted_register, |
| 522 uint32_t *instruction_info_collected, | 538 uint32_t *instruction_info_collected, |
| 523 uint8_t rex_prefix, uint32_t operand_states) { | 539 uint8_t rex_prefix, uint32_t operand_states) { |
| 524 /* Restricted %rsp or %rbp must be processed by appropriate nacl-special | 540 /* Restricted %rsp or %rbp must be processed by appropriate nacl-special |
| 525 * instruction, not with regular instruction. */ | 541 * instruction, not with regular instruction. */ |
| 526 if (*restricted_register == REG_RSP) { | 542 if (*restricted_register == REG_RSP) { |
| 527 *instruction_info_collected |= RESTRICTED_RSP_UNPROCESSED; | 543 *instruction_info_collected |= RESTRICTED_RSP_UNPROCESSED; |
| 528 } else if (*restricted_register == REG_RBP) { | 544 } else if (*restricted_register == REG_RBP) { |
| 529 *instruction_info_collected |= RESTRICTED_RBP_UNPROCESSED; | 545 *instruction_info_collected |= RESTRICTED_RBP_UNPROCESSED; |
| 530 } | 546 } |
| 531 *restricted_register = NO_REG; | 547 *restricted_register = NO_REG; |
| (...skipping 23 matching lines...) Expand all Loading... | |
| 555 } else if (CHECK_OPERAND(1, REG_RBP, OperandSandboxRestricted)) { | 571 } else if (CHECK_OPERAND(1, REG_RBP, OperandSandboxRestricted)) { |
| 556 *instruction_info_collected |= RESTRICTED_RBP_UNPROCESSED; | 572 *instruction_info_collected |= RESTRICTED_RBP_UNPROCESSED; |
| 557 } | 573 } |
| 558 /* Take 2 bits of operand type from operand_states as *restricted_register, | 574 /* Take 2 bits of operand type from operand_states as *restricted_register, |
| 559 * make sure operand_states denotes a register (12th bit == 0). */ | 575 * make sure operand_states denotes a register (12th bit == 0). */ |
| 560 } else if ((operand_states & 0x7000) == (OperandSandboxRestricted << 13)) { | 576 } else if ((operand_states & 0x7000) == (OperandSandboxRestricted << 13)) { |
| 561 *restricted_register = (operand_states & 0x0f00) >> 8; | 577 *restricted_register = (operand_states & 0x0f00) >> 8; |
| 562 } | 578 } |
| 563 } | 579 } |
| 564 | 580 |
| 581 /* | |
| 582 * This action redefines the range of the superinstruction to include the | |
| 583 * preceding sandboxing sequence then invalidates jump targets on the | |
| 584 * interior of the superinstructions and finally clears “the restricted | |
| 585 * register” variable. | |
| 586 */ | |
| 587 static INLINE void ProcessNaclCallOrNaclJmp( | |
|
Brad Chen
2012/10/05 16:47:21
This is a big improvement. Now it's much easier to
khim
2012/10/15 16:38:57
Done.
| |
| 588 uint32_t *instruction_info_collected, const uint8_t **instruction_start, | |
| 589 const uint8_t *current_position, const uint8_t *data, | |
| 590 bitmap_word *valid_targets, Bool and_have_rex, Bool add_stores_to_reg) { | |
| 591 /* Expand the range. Only expand by 6 bytes: this covers “add” (second | |
| 592 * instruction) and “and” WITHOUT it's REX prefix. | |
| 593 */ | |
| 594 *instruction_start -= 6; | |
| 595 /* Compare registers used by “and”, “add”, and “call” or “jmp”. */ | |
| 596 if (RMFromModRM((*instruction_start)[1]) != | |
| 597 (add_stores_to_reg ? RegFromModRM((*instruction_start)[5]) : | |
| 598 RMFromModRM((*instruction_start)[5])) || | |
| 599 RMFromModRM((*instruction_start)[1]) != RMFromModRM(current_position[0])) | |
| 600 *instruction_info_collected |= UNRECOGNIZED_INSTRUCTION; | |
| 601 /* Make start of the second and third instruction not valid targets. */ | |
| 602 MakeInvalidJumpTarget((*instruction_start - data) + 3, valid_targets); | |
| 603 MakeInvalidJumpTarget((*instruction_start - data) + 6, valid_targets); | |
| 604 /* Expand the range again. This time to cover REX prefix (if any). */ | |
| 605 if (and_have_rex) --*instruction_start; | |
| 606 } | |
| 607 | |
| 608 /* | |
| 609 * This action redefines the range of the superinstruction to include the | |
| 610 * preceding sandboxing sequence then invalidates jump targets on the interior | |
| 611 * of the superinstruction. | |
| 612 */ | |
| 613 static INLINE void SandboxRsiOrRdiMakeInteriorInvalidJumpTargets( | |
| 614 const uint8_t **instruction_start, const uint8_t *data, | |
| 615 bitmap_word *valid_targets, Bool mov_have_rex) { | |
| 616 /* Expand the range. Only expand by 6 bytes: this covers “lea” (second | |
| 617 * instruction) and “mov” WITHOUT it's REX prefix. | |
| 618 */ | |
| 619 *instruction_start -= 6; | |
| 620 MakeInvalidJumpTarget((*instruction_start - data) + 2, valid_targets); | |
| 621 MakeInvalidJumpTarget((*instruction_start - data) + 6, valid_targets); | |
| 622 /* Expand the range again. This time to cover REX prefix (if any). */ | |
| 623 if (mov_have_rex) --*instruction_start; | |
| 624 } | |
| 625 | |
| 565 #endif /* NATIVE_CLIENT_SRC_TRUSTED_VALIDATOR_RAGEL_VALIDATOR_INTERNAL_H_ */ | 626 #endif /* NATIVE_CLIENT_SRC_TRUSTED_VALIDATOR_RAGEL_VALIDATOR_INTERNAL_H_ */ |
| OLD | NEW |