Chromium Code Reviews| 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 } |
| 178 | 184 |
| 179 while (sz > 0 && dst[sz-1] == src[sz-1]) { | 185 while (sz > 0 && dst[sz-1] == src[sz-1]) { |
| 180 /* trim identical bytes at end */ | 186 /* trim identical bytes at end */ |
| 181 sz--; | 187 sz--; |
| 182 } | 188 } |
| 183 | 189 |
| 184 if (sz == 1) { | 190 if (sz == 1) { |
| 185 /* we assume a 1-byte change it atomic */ | 191 /* we assume a 1-byte change it atomic */ |
|
elijahtaylor (use chromium)
2010/12/10 20:01:40
s/it/is/
Karl
2010/12/10 21:18:15
Yes this should be changed as you suggest.
| |
| 186 *dst = *src; | 192 *dst = *src; |
| 187 } else if (IsTrustedWrite(dst, sz, 4, &offset)) { | 193 } else if (IsTrustedWrite(dst, sz, 4, &offset)) { |
| 188 uint8_t tmp[4]; | 194 uint8_t tmp[4]; |
| 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 |