OLD | NEW |
1 /* | 1 /* |
2 * Copyright 2010 The Native Client Authors. All rights reserved. | 2 * Copyright 2010 The Native Client Authors. All rights reserved. |
3 * Use of this source code is governed by a BSD-style license that can | 3 * Use of this source code is governed by a BSD-style license that can |
4 * be found in the LICENSE file. | 4 * be found in the LICENSE file. |
5 */ | 5 */ |
6 | 6 |
7 /* | 7 /* |
8 * nccopycode.c | 8 * nccopycode.c |
9 * Copies two code streams in a thread-safe way | 9 * Copies two code streams in a thread-safe way |
10 * | 10 * |
11 */ | 11 */ |
12 | 12 |
13 #include "native_client/src/include/portability.h" | 13 #include "native_client/src/include/portability.h" |
14 | 14 |
15 #if NACL_WINDOWS == 1 | 15 #if NACL_WINDOWS == 1 |
16 #include <windows.h> | 16 #include <windows.h> |
17 #else | 17 #else |
18 #include <sys/mman.h> | 18 #include <sys/mman.h> |
19 #endif | 19 #endif |
20 | 20 |
21 #include <stdio.h> | 21 #include <stdio.h> |
22 #include <stdlib.h> | 22 #include <stdlib.h> |
23 #include <errno.h> | 23 #include <errno.h> |
24 #include <string.h> | 24 #include <string.h> |
25 #include <assert.h> | 25 #include <assert.h> |
| 26 #include "native_client/src/shared/platform/nacl_check.h" |
| 27 #if NACL_TARGET_SUBARCH == 32 |
26 #include "native_client/src/trusted/validator_x86/ncdecode.h" | 28 #include "native_client/src/trusted/validator_x86/ncdecode.h" |
27 #include "native_client/src/trusted/validator_x86/ncvalidate.h" | 29 #include "native_client/src/trusted/validator_x86/ncvalidate.h" |
28 #include "native_client/src/shared/platform/nacl_check.h" | 30 #elif NACL_TARGET_SUBARCH == 64 |
| 31 #include "native_client/src/trusted/validator_x86/nc_inst_iter.h" |
| 32 #include "native_client/src/trusted/validator_x86/nc_segment.h" |
| 33 #include "native_client/src/trusted/validator_x86/nc_inst_state_internal.h" |
| 34 #else |
| 35 #error "Unknown Platform" |
| 36 #endif |
29 | 37 |
30 /* x86 HALT opcode */ | 38 /* x86 HALT opcode */ |
31 static const uint8_t kNaClFullStop = 0xf4; | 39 static const uint8_t kNaClFullStop = 0xf4; |
32 | 40 |
33 /* | 41 /* |
34 * Max size of aligned writes we may issue to code without syncing. | 42 * Max size of aligned writes we may issue to code without syncing. |
35 * 8 is a safe value according to: | 43 * 8 is a safe value according to: |
36 * [1] Advance Micro Devices Inc. AMD64 Architecture Program- | 44 * [1] Advance Micro Devices Inc. AMD64 Architecture Program- |
37 * mers Manual Volume 1: Application Programming, 2009. | 45 * mers Manual Volume 1: Application Programming, 2009. |
38 * [2] Intel Inc. Intel 64 and IA-32 Architectures Software Developers | 46 * [2] Intel Inc. Intel 64 and IA-32 Architectures Software Developers |
(...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
151 prot = (prot == prot_a ? prot_b : prot_a); | 159 prot = (prot == prot_a ? prot_b : prot_a); |
152 rv = mprotect(g_squashybuffer, size, prot); | 160 rv = mprotect(g_squashybuffer, size, prot); |
153 CHECK(rv == 0); | 161 CHECK(rv == 0); |
154 #endif | 162 #endif |
155 } | 163 } |
156 | 164 |
157 /* | 165 /* |
158 * Copy a single instruction, avoiding the possibility of other threads | 166 * Copy a single instruction, avoiding the possibility of other threads |
159 * executing a partially changed instruction. | 167 * executing a partially changed instruction. |
160 */ | 168 */ |
161 void CopyInstruction(const struct NCDecoderState *mstate_old, | 169 void CopyInstructionInternal(uint8_t *dst, |
162 const struct NCDecoderState *mstate_new) { | 170 uint8_t *src, |
163 uint8_t* dst = mstate_old->inst.maddr; | 171 uint8_t sz) { |
164 uint8_t* src = mstate_new->inst.maddr; | |
165 int sz = mstate_old->inst.length; | |
166 intptr_t offset = 0; | 172 intptr_t offset = 0; |
167 CHECK(mstate_new->inst.length == mstate_old->inst.length); | 173 uint8_t *firstbyte_p = dst; |
168 | 174 |
169 while (sz > 0 && dst[0] == src[0]) { | 175 while (sz > 0 && dst[0] == src[0]) { |
170 /* scroll to first changed byte */ | 176 /* scroll to first changed byte */ |
171 dst++, src++, sz--; | 177 dst++, src++, sz--; |
172 } | 178 } |
173 | 179 |
174 if (sz == 0) { | 180 if (sz == 0) { |
175 /* instructions are identical, we are done */ | 181 /* instructions are identical, we are done */ |
176 return; | 182 return; |
177 } | 183 } |
(...skipping 11 matching lines...) Expand all Loading... |
189 memcpy(tmp, dst-offset, sizeof tmp); | 195 memcpy(tmp, dst-offset, sizeof tmp); |
190 memcpy(tmp+offset, src, sz); | 196 memcpy(tmp+offset, src, sz); |
191 onestore_memmove4(dst-offset, tmp); | 197 onestore_memmove4(dst-offset, tmp); |
192 } else if (IsTrustedWrite(dst, sz, 8, &offset)) { | 198 } else if (IsTrustedWrite(dst, sz, 8, &offset)) { |
193 uint8_t tmp[8]; | 199 uint8_t tmp[8]; |
194 memcpy(tmp, dst-offset, sizeof tmp); | 200 memcpy(tmp, dst-offset, sizeof tmp); |
195 memcpy(tmp+offset, src, sz); | 201 memcpy(tmp+offset, src, sz); |
196 onestore_memmove8(dst-offset, tmp); | 202 onestore_memmove8(dst-offset, tmp); |
197 } else { | 203 } else { |
198 /* the slow path, first flip first byte to halt*/ | 204 /* the slow path, first flip first byte to halt*/ |
199 uint8_t firstbyte = mstate_old->inst.maddr[0]; | 205 uint8_t firstbyte = firstbyte_p[0]; |
200 mstate_old->inst.maddr[0] = kNaClFullStop; | 206 firstbyte_p[0] = kNaClFullStop; |
201 | 207 |
202 SerializeAllProcessors(); | 208 SerializeAllProcessors(); |
203 | 209 |
204 /* copy the rest of instruction */ | 210 /* copy the rest of instruction */ |
205 if (dst == mstate_old->inst.maddr) { | 211 if (dst == firstbyte_p) { |
206 /* but not the first byte! */ | 212 /* but not the first byte! */ |
207 firstbyte = *src; | 213 firstbyte = *src; |
208 dst++, src++, sz--; | 214 dst++, src++, sz--; |
209 } | 215 } |
210 memcpy(dst, src, sz); | 216 memcpy(dst, src, sz); |
211 | 217 |
212 SerializeAllProcessors(); | 218 SerializeAllProcessors(); |
213 | 219 |
214 /* flip first byte back */ | 220 /* flip first byte back */ |
215 mstate_old->inst.maddr[0] = firstbyte; | 221 firstbyte_p[0] = firstbyte; |
216 } | 222 } |
217 } | 223 } |
218 | 224 |
| 225 #if NACL_TARGET_SUBARCH == 32 |
| 226 |
| 227 /* |
| 228 * Copy a single instruction, avoiding the possibility of other threads |
| 229 * executing a partially changed instruction. |
| 230 */ |
| 231 void CopyInstruction(const struct NCDecoderState *mstate_old, |
| 232 const struct NCDecoderState *mstate_new) { |
| 233 CHECK(mstate_new->inst.length == mstate_old->inst.length); |
| 234 |
| 235 CopyInstructionInternal(mstate_old->inst.maddr, |
| 236 mstate_new->inst.maddr, |
| 237 mstate_old->inst.length); |
| 238 } |
| 239 |
219 int NCCopyCode(uint8_t *dst, uint8_t *src, NaClPcAddress vbase, | 240 int NCCopyCode(uint8_t *dst, uint8_t *src, NaClPcAddress vbase, |
220 size_t sz, int bundle_size) { | 241 size_t sz, int bundle_size) { |
221 struct NCValidatorState *vstate; | 242 struct NCValidatorState *vstate; |
222 vstate = NCValidateInit(vbase, vbase+sz, bundle_size); | 243 vstate = NCValidateInit(vbase, vbase+sz, bundle_size); |
223 CHECK(NULL != vstate); | 244 CHECK(NULL != vstate); |
224 NCDecodeSegmentPair(dst, src, vbase, sz, vstate, CopyInstruction); | 245 NCDecodeSegmentPair(dst, src, vbase, sz, vstate, CopyInstruction); |
225 NCValidateFreeState(&vstate); | 246 NCValidateFreeState(&vstate); |
226 return 0; | 247 return 0; |
227 } | 248 } |
228 | 249 |
| 250 #elif NACL_TARGET_SUBARCH == 64 |
| 251 |
| 252 int NaClCopyCodeIter(uint8_t *dst, uint8_t *src, |
| 253 NaClPcAddress vbase, size_t size) { |
| 254 NaClSegment segment_old, segment_new; |
| 255 NaClInstIter *iter_old, *iter_new; |
| 256 NaClInstState *istate_old, *istate_new; |
| 257 |
| 258 NaClSegmentInitialize(dst, vbase, size, &segment_old); |
| 259 NaClSegmentInitialize(src, vbase, size, &segment_new); |
| 260 |
| 261 iter_old = NaClInstIterCreate(&segment_old); |
| 262 iter_new = NaClInstIterCreate(&segment_new); |
| 263 while (NaClInstIterHasNext(iter_old) && |
| 264 NaClInstIterHasNext(iter_new)) { |
| 265 istate_old = NaClInstIterGetState(iter_old); |
| 266 istate_new = NaClInstIterGetState(iter_new); |
| 267 if (istate_old->length != istate_new->length || |
| 268 istate_new->vpc != istate_old->vpc) { |
| 269 NaClLog(LOG_ERROR, |
| 270 "Segment replacement: copied instructions misaligned\n"); |
| 271 return 1; |
| 272 } |
| 273 CopyInstructionInternal(istate_old->mpc, |
| 274 istate_new->mpc, |
| 275 istate_old->length); |
| 276 NaClInstIterAdvance(iter_old); |
| 277 NaClInstIterAdvance(iter_new); |
| 278 } |
| 279 |
| 280 CHECK(!NaClInstIterHasNext(iter_old) && !NaClInstIterHasNext(iter_new)); |
| 281 |
| 282 NaClInstIterDestroy(iter_old); |
| 283 NaClInstIterDestroy(iter_new); |
| 284 return 0; |
| 285 } |
| 286 |
| 287 #else |
| 288 #error "Unknown Platform" |
| 289 #endif |
| 290 |
OLD | NEW |