Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(496)

Side by Side Diff: src/trusted/validator_x86/nccopycode.c

Issue 5738003: Resurrect Petr's 64-bit dynamic code modification CL:... (Closed) Base URL: svn://svn.chromium.org/native_client/trunk/src/native_client/
Patch Set: fix first round of my own feedback Created 10 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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
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 is atomic */
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);
bsy 2010/12/15 04:06:50 does this get pseudo-atomic sequences as a single
elijahtaylor (use chromium) 2010/12/15 21:26:37 Comment added to clarify what we're doing. On 201
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");
bsy 2010/12/15 04:06:50 is this precondition violation that should never h
elijahtaylor (use chromium) 2010/12/15 21:26:37 Changed to LOG_FATAL and commented as this should
271 return 1;
272 }
273 CopyInstructionInternal(istate_old->mpc,
bsy 2010/12/15 04:06:50 add a comment here that replacing all affected ins
elijahtaylor (use chromium) 2010/12/15 21:26:37 Done. On 2010/12/15 04:06:50, bsy wrote:
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698