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 /* Implement the Validator API for the x86-32 architecture. */ | 7 /* Implement the Validator API for the x86-32 architecture. */ |
8 #include <assert.h> | 8 #include <assert.h> |
9 #include <errno.h> | 9 #include <errno.h> |
10 #include <stddef.h> | 10 #include <stddef.h> |
(...skipping 16 matching lines...) Expand all Loading... |
27 | 27 |
28 #define NACL_HALT_OPCODE 0xf4 | 28 #define NACL_HALT_OPCODE 0xf4 |
29 | 29 |
30 static Bool ProcessError(const uint8_t *begin, const uint8_t *end, | 30 static Bool ProcessError(const uint8_t *begin, const uint8_t *end, |
31 uint32_t info, void *callback_data) { | 31 uint32_t info, void *callback_data) { |
32 UNREFERENCED_PARAMETER(begin); | 32 UNREFERENCED_PARAMETER(begin); |
33 UNREFERENCED_PARAMETER(end); | 33 UNREFERENCED_PARAMETER(end); |
34 UNREFERENCED_PARAMETER(info); | 34 UNREFERENCED_PARAMETER(info); |
35 | 35 |
36 /* Instruction is unsupported by CPU, but otherwise valid. */ | 36 /* Instruction is unsupported by CPU, but otherwise valid. */ |
37 if ((info & VALIDATION_ERRORS) == CPUID_UNSUPPORTED_INSTRUCTION) { | 37 if ((info & VALIDATION_ERRORS_MASK) == CPUID_UNSUPPORTED_INSTRUCTION) { |
38 *((enum NaClValidationStatus*)callback_data) = | 38 *((enum NaClValidationStatus*)callback_data) = |
39 NaClValidationFailedCpuNotSupported; | 39 NaClValidationFailedCpuNotSupported; |
40 } | 40 } |
41 return FALSE; | 41 return FALSE; |
42 } | 42 } |
43 | 43 |
44 static Bool StubOutCPUUnsupportedInstruction(const uint8_t *begin, | 44 static Bool StubOutCPUUnsupportedInstruction(const uint8_t *begin, |
45 const uint8_t *end, uint32_t info, void *callback_data) { | 45 const uint8_t *end, uint32_t info, void *callback_data) { |
46 UNREFERENCED_PARAMETER(callback_data); | 46 UNREFERENCED_PARAMETER(callback_data); |
47 | 47 |
48 /* Stubout unsupported by CPU, but otherwise valid instructions. */ | 48 /* Stubout unsupported by CPU, but otherwise valid instructions. */ |
49 if ((info & VALIDATION_ERRORS) == CPUID_UNSUPPORTED_INSTRUCTION) { | 49 if ((info & VALIDATION_ERRORS_MASK) == CPUID_UNSUPPORTED_INSTRUCTION) { |
50 memset((uint8_t *)begin, NACL_HALT_OPCODE, end - begin + 1); | 50 memset((uint8_t *)begin, NACL_HALT_OPCODE, end - begin + 1); |
51 return TRUE; | 51 return TRUE; |
52 } else { | 52 } else { |
53 return FALSE; | 53 return FALSE; |
54 } | 54 } |
55 } | 55 } |
56 | 56 |
57 NaClValidationStatus ApplyDfaValidator_x86_32( | 57 NaClValidationStatus ApplyDfaValidator_x86_32( |
58 uintptr_t guest_addr, | 58 uintptr_t guest_addr, |
59 uint8_t *data, | 59 uint8_t *data, |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
103 | 103 |
104 static Bool ProcessCodeCopyInstruction(const uint8_t *begin_new, | 104 static Bool ProcessCodeCopyInstruction(const uint8_t *begin_new, |
105 const uint8_t *end_new, uint32_t info, void *callback_data) { | 105 const uint8_t *end_new, uint32_t info, void *callback_data) { |
106 struct CodeCopyCallbackData *data = callback_data; | 106 struct CodeCopyCallbackData *data = callback_data; |
107 | 107 |
108 /* Sanity check: instruction must be shorter then 15 bytes. */ | 108 /* Sanity check: instruction must be shorter then 15 bytes. */ |
109 CHECK(end_new - begin_new < MAX_INSTRUCTION_LENGTH); | 109 CHECK(end_new - begin_new < MAX_INSTRUCTION_LENGTH); |
110 | 110 |
111 return data->copy_func( | 111 return data->copy_func( |
112 (uint8_t *)begin_new + data->delta, | 112 (uint8_t *)begin_new + data->delta, |
113 (info & VALIDATION_ERRORS) == CPUID_UNSUPPORTED_INSTRUCTION ? | 113 (info & VALIDATION_ERRORS_MASK) == CPUID_UNSUPPORTED_INSTRUCTION ? |
114 (uint8_t *)kStubOutMem : | 114 (uint8_t *)kStubOutMem : |
115 (uint8_t *)begin_new, | 115 (uint8_t *)begin_new, |
116 (uint8_t)(end_new - begin_new + 1)); | 116 (uint8_t)(end_new - begin_new + 1)); |
117 } | 117 } |
118 | 118 |
119 static NaClValidationStatus ValidatorCopy_x86_32( | 119 static NaClValidationStatus ValidatorCopy_x86_32( |
120 uintptr_t guest_addr, | 120 uintptr_t guest_addr, |
121 uint8_t *data_old, | 121 uint8_t *data_old, |
122 uint8_t *data_new, | 122 uint8_t *data_new, |
123 size_t size, | 123 size_t size, |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
156 }; | 156 }; |
157 | 157 |
158 static Bool ProcessOriginalCodeInstruction(const uint8_t *begin_old, | 158 static Bool ProcessOriginalCodeInstruction(const uint8_t *begin_old, |
159 const uint8_t *end_old, uint32_t info, void *callback_data) { | 159 const uint8_t *end_old, uint32_t info, void *callback_data) { |
160 struct CodeReplacementCallbackData *data = callback_data; | 160 struct CodeReplacementCallbackData *data = callback_data; |
161 | 161 |
162 /* Sanity check: instruction must be shorter then 15 bytes. */ | 162 /* Sanity check: instruction must be shorter then 15 bytes. */ |
163 CHECK(end_old - begin_old < MAX_INSTRUCTION_LENGTH); | 163 CHECK(end_old - begin_old < MAX_INSTRUCTION_LENGTH); |
164 | 164 |
165 /* Sanity check: old code must be valid... except for jumps. */ | 165 /* Sanity check: old code must be valid... except for jumps. */ |
166 CHECK(!(info & (VALIDATION_ERRORS & ~DIRECT_JUMP_OUT_OF_RANGE))); | 166 CHECK(!(info & (VALIDATION_ERRORS_MASK & ~DIRECT_JUMP_OUT_OF_RANGE))); |
167 | 167 |
168 /* Don't mask the end of bundle: may lead to overflow */ | 168 /* Don't mask the end of bundle: may lead to overflow */ |
169 if (end_old - data->data_old == kBundleMask) | 169 if (end_old - data->data_old == kBundleMask) |
170 return TRUE; | 170 return TRUE; |
171 | 171 |
172 BitmapSetBit(&data->instruction_boundaries_old, | 172 BitmapSetBit(&data->instruction_boundaries_old, |
173 (end_old + 1) - data->data_old); | 173 (end_old + 1) - data->data_old); |
174 return TRUE; | 174 return TRUE; |
175 } | 175 } |
176 | 176 |
177 static Bool ProcessCodeReplacementInstruction(const uint8_t *begin_new, | 177 static Bool ProcessCodeReplacementInstruction(const uint8_t *begin_new, |
178 const uint8_t *end_new, uint32_t info, void *callback_data) { | 178 const uint8_t *end_new, uint32_t info, void *callback_data) { |
179 struct CodeReplacementCallbackData *data = callback_data; | 179 struct CodeReplacementCallbackData *data = callback_data; |
180 size_t instruction_length = end_new - begin_new + 1; | 180 size_t instruction_length = end_new - begin_new + 1; |
181 const uint8_t *begin_old = begin_new + data->delta; | 181 const uint8_t *begin_old = begin_new + data->delta; |
182 | 182 |
183 /* Sanity check: instruction must be shorter then 15 bytes. */ | 183 /* Sanity check: instruction must be shorter then 15 bytes. */ |
184 CHECK(instruction_length <= MAX_INSTRUCTION_LENGTH); | 184 CHECK(instruction_length <= MAX_INSTRUCTION_LENGTH); |
185 | 185 |
186 /* Unsupported instruction must have been replaced with HLTs. */ | 186 /* Unsupported instruction must have been replaced with HLTs. */ |
187 if ((info & VALIDATION_ERRORS) == CPUID_UNSUPPORTED_INSTRUCTION) { | 187 if ((info & VALIDATION_ERRORS_MASK) == CPUID_UNSUPPORTED_INSTRUCTION) { |
188 if (memcmp(kStubOutMem, begin_old, instruction_length) == 0) { | 188 if (memcmp(kStubOutMem, begin_old, instruction_length) == 0) { |
189 BitmapSetBits(&(data->instruction_boundaries_new), | 189 BitmapSetBits(&(data->instruction_boundaries_new), |
190 (begin_new - data->data_new) & kBundleMask, | 190 (begin_new - data->data_new) & kBundleMask, |
191 instruction_length); | 191 instruction_length); |
192 } else { | 192 } else { |
193 return FALSE; | 193 return FALSE; |
194 } | 194 } |
195 /* If we have jump which jumps out of it's range... */ | 195 /* If we have jump which jumps out of it's range... */ |
196 } else if (info & DIRECT_JUMP_OUT_OF_RANGE) { | 196 } else if (info & DIRECT_JUMP_OUT_OF_RANGE) { |
197 /* then everything is fine if it's the only error and jump is unchanged! */ | 197 /* then everything is fine if it's the only error and jump is unchanged! */ |
198 if ((info & (VALIDATION_ERRORS & ~DIRECT_JUMP_OUT_OF_RANGE)) || | 198 if ((info & (VALIDATION_ERRORS_MASK & ~DIRECT_JUMP_OUT_OF_RANGE)) || |
199 memcmp(begin_new, begin_old, instruction_length) != 0) | 199 memcmp(begin_new, begin_old, instruction_length) != 0) |
200 return FALSE; | 200 return FALSE; |
201 /* If instruction is not accepted then we have nothing to do here. */ | 201 /* If instruction is not accepted then we have nothing to do here. */ |
202 } else if (info & (VALIDATION_ERRORS | BAD_JUMP_TARGET)) { | 202 } else if (info & (VALIDATION_ERRORS_MASK | BAD_JUMP_TARGET)) { |
203 return FALSE; | 203 return FALSE; |
204 /* Instruction is untouched: we are done. */ | 204 /* Instruction is untouched: we are done. */ |
205 } if (memcmp(begin_new, begin_old, instruction_length) == 0) { | 205 } if (memcmp(begin_new, begin_old, instruction_length) == 0) { |
206 /* do nothing */ | 206 /* do nothing */ |
207 /* Special instruction must be untouched! */ | 207 /* Special instruction must be untouched! */ |
208 } else if (info & SPECIAL_INSTRUCTION) { | 208 } else if (info & SPECIAL_INSTRUCTION) { |
209 return FALSE; | 209 return FALSE; |
210 } | 210 } |
211 /* If we in the middle of a bundle then collect bondaries. */ | 211 /* If we in the middle of a bundle then collect bondaries. */ |
212 if (((end_new - data->data_new) & kBundleMask) != kBundleMask) { | 212 if (((end_new - data->data_new) & kBundleMask) != kBundleMask) { |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
265 | 265 |
266 static const struct NaClValidatorInterface validator = { | 266 static const struct NaClValidatorInterface validator = { |
267 ApplyDfaValidator_x86_32, | 267 ApplyDfaValidator_x86_32, |
268 ValidatorCopy_x86_32, | 268 ValidatorCopy_x86_32, |
269 ValidatorCodeReplacement_x86_32, | 269 ValidatorCodeReplacement_x86_32, |
270 }; | 270 }; |
271 | 271 |
272 const struct NaClValidatorInterface *NaClDfaValidatorCreate_x86_32() { | 272 const struct NaClValidatorInterface *NaClDfaValidatorCreate_x86_32() { |
273 return &validator; | 273 return &validator; |
274 } | 274 } |
OLD | NEW |