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 |