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

Side by Side Diff: src/trusted/validator/x86/ncval_reg_sfi/nc_jumps.c

Issue 7980021: Speed up x86-64 validator by inlining heavily called routines. Speeds up (Closed) Base URL: svn://svn.chromium.org/native_client/trunk/src/native_client/
Patch Set: '' Created 9 years, 3 months 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 (c) 2011 The Native Client Authors. All rights reserved. 2 * Copyright (c) 2011 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 * nc_jumps.c - Validate where valid jumps can occur. 8 * nc_jumps.c - Validate where valid jumps can occur.
9 */ 9 */
10 10
11 #include <assert.h> 11 #include <assert.h>
12 #include <stdlib.h> 12 #include <stdlib.h>
13 13
14 #include "native_client/src/trusted/validator/x86/ncval_reg_sfi/nc_jumps.h" 14 #include "native_client/src/trusted/validator/x86/ncval_reg_sfi/nc_jumps.h"
15 15
16 #include "native_client/src/shared/platform/nacl_log.h" 16 #include "native_client/src/shared/platform/nacl_log.h"
17 #include "native_client/src/trusted/validator/x86/decoder/ncop_exps.h"
18 #include "native_client/src/trusted/validator/x86/decoder/nc_inst_iter.h"
19 #include "native_client/src/trusted/validator/x86/decoder/nc_inst_state_internal .h" 17 #include "native_client/src/trusted/validator/x86/decoder/nc_inst_state_internal .h"
20 #include "native_client/src/trusted/validator/x86/decoder/nc_inst_trans.h" 18 #include "native_client/src/trusted/validator/x86/decoder/nc_inst_trans.h"
21 #include "native_client/src/trusted/validator/x86/ncval_reg_sfi/address_sets.h" 19 #include "native_client/src/trusted/validator/x86/ncval_reg_sfi/address_sets.h"
22 #include "native_client/src/trusted/validator/x86/ncval_reg_sfi/ncvalidate_iter. h" 20 #include "native_client/src/trusted/validator/x86/ncval_reg_sfi/ncvalidate_iter. h"
23 #include "native_client/src/trusted/validator/x86/ncval_reg_sfi/ncvalidate_iter_ internal.h" 21 #include "native_client/src/trusted/validator/x86/ncval_reg_sfi/ncvalidate_iter_ internal.h"
24 22
25 /* To turn on debugging of instruction decoding, change value of 23 /* To turn on debugging of instruction decoding, change value of
26 * DEBUGGING to 1. 24 * DEBUGGING to 1.
27 */ 25 */
28 #define DEBUGGING 0 26 #define DEBUGGING 0
29 27
30 #include "native_client/src/shared/utils/debugging.h" 28 #include "native_client/src/shared/utils/debugging.h"
31 29
30 #include "native_client/src/trusted/validator/x86/decoder/ncop_exps_inl.c"
31 #include "native_client/src/trusted/validator/x86/decoder/nc_inst_iter_inl.c"
32 #include "native_client/src/trusted/validator/x86/ncval_reg_sfi/address_sets_inl .c"
33
32 Bool NACL_FLAGS_identity_mask = FALSE; 34 Bool NACL_FLAGS_identity_mask = FALSE;
33 35
34 static INLINE uint8_t NaClGetJumpMask(NaClValidatorState* state) { 36 static INLINE uint8_t NaClGetJumpMask(NaClValidatorState* state) {
35 return NACL_FLAGS_identity_mask 37 return NACL_FLAGS_identity_mask
36 ? (uint8_t) 0xFF 38 ? (uint8_t) 0xFF
37 : (uint8_t) (~state->alignment_mask); 39 : (uint8_t) (~state->alignment_mask);
38 } 40 }
39 41
40 /* Generates a jump validator. */ 42 /* Generates a jump validator. */
41 NaClJumpSets* NaClJumpValidatorCreate(NaClValidatorState* state) { 43 NaClJumpSets* NaClJumpValidatorCreate(NaClValidatorState* state) {
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
81 * Otherwise, only allow if 0 mod 32. 83 * Otherwise, only allow if 0 mod 32.
82 */ 84 */
83 DEBUG(NaClLog(LOG_INFO, "Add jump to jump sets: %" 85 DEBUG(NaClLog(LOG_INFO, "Add jump to jump sets: %"
84 NACL_PRIxNaClPcAddress" -> %"NACL_PRIxNaClPcAddress"\n", 86 NACL_PRIxNaClPcAddress" -> %"NACL_PRIxNaClPcAddress"\n",
85 from_address, to_address)); 87 from_address, to_address));
86 if (state->vbase <= to_address && to_address < state->vlimit) { 88 if (state->vbase <= to_address && to_address < state->vlimit) {
87 /* Remember address for checking later. */ 89 /* Remember address for checking later. */
88 DEBUG(NaClLog(LOG_INFO, "Add jump to target: %"NACL_PRIxNaClPcAddress 90 DEBUG(NaClLog(LOG_INFO, "Add jump to target: %"NACL_PRIxNaClPcAddress
89 " -> %"NACL_PRIxNaClPcAddress"\n", 91 " -> %"NACL_PRIxNaClPcAddress"\n",
90 from_address, to_address)); 92 from_address, to_address));
91 NaClAddressSetAdd(jump_sets->actual_targets, to_address, state); 93 NaClAddressSetAddInline(jump_sets->actual_targets, to_address, state);
92 } 94 }
93 /* The range check may not be strictly necessary given that we have 95 /* The range check may not be strictly necessary given that we have
94 * guard regions around the sandbox address space, but it shouldn't 96 * guard regions around the sandbox address space, but it shouldn't
95 * hurt to disallow branches that overflow or underflow the address 97 * hurt to disallow branches that overflow or underflow the address
96 * space. 98 * space.
97 */ 99 */
98 else if ((to_address & state->alignment_mask) == 0 && 100 else if ((to_address & state->alignment_mask) == 0 &&
99 (to_address & ~(NaClPcAddress) 0xffffffff) == 0) { 101 (to_address & ~(NaClPcAddress) 0xffffffff) == 0) {
100 /* Allow bundle-aligned jump. */ 102 /* Allow bundle-aligned jump. */
101 } 103 }
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after
195 NaClJumpSets* jump_sets) { 197 NaClJumpSets* jump_sets) {
196 uint8_t mask; 198 uint8_t mask;
197 NaClInstState* and_state; 199 NaClInstState* and_state;
198 NaClInstState* middle_state; 200 NaClInstState* middle_state;
199 const NaClInst* and_inst; 201 const NaClInst* and_inst;
200 const NaClInst* middle_inst; 202 const NaClInst* middle_inst;
201 int op_1, op_2; 203 int op_1, op_2;
202 NaClOpKind and_reg, and_64_reg, jump_reg, middle_reg; 204 NaClOpKind and_reg, and_64_reg, jump_reg, middle_reg;
203 NaClExpVector* nodes; 205 NaClExpVector* nodes;
204 NaClExp* node; 206 NaClExp* node;
205 jump_reg = NaClGetExpRegister(reg); 207 jump_reg = NaClGetExpRegisterInline(reg);
206 DEBUG(NaClLog(LOG_INFO, "checking indirect jump: "); 208 DEBUG(NaClLog(LOG_INFO, "checking indirect jump: ");
207 NaClInstStateInstPrint(NaClLogGetGio(), inst); 209 NaClInstStateInstPrint(NaClLogGetGio(), inst);
208 gprintf(NaClLogGetGio(), "jump_reg = %s\n", NaClOpKindName(jump_reg))); 210 gprintf(NaClLogGetGio(), "jump_reg = %s\n", NaClOpKindName(jump_reg)));
209 211
210 /* Do the following block exactly once. Use loop so that "break" can 212 /* Do the following block exactly once. Use loop so that "break" can
211 * be used for premature exit of block. 213 * be used for premature exit of block.
212 */ 214 */
213 do { 215 do {
214 /* Check and in 3 instruction sequence. */ 216 /* Check and in 3 instruction sequence. */
215 if (!NaClInstIterHasLookbackState(iter, 2)) break; 217 if (!NaClInstIterHasLookbackStateInline(iter, 2)) break;
216 and_state = NaClInstIterGetLookbackState(iter, 2); 218 and_state = NaClInstIterGetLookbackStateInline(iter, 2);
217 DEBUG(NaClLog(LOG_INFO, "and?: "); 219 DEBUG(NaClLog(LOG_INFO, "and?: ");
218 NaClInstStateInstPrint(NaClLogGetGio(), and_state)); 220 NaClInstStateInstPrint(NaClLogGetGio(), and_state));
219 and_inst = NaClInstStateInst(and_state); 221 and_inst = NaClInstStateInst(and_state);
220 if (((and_state->num_opcode_bytes == 0) || 222 if (((and_state->num_opcode_bytes == 0) ||
221 (0x83 != and_state->bytes.byte[and_state->num_prefix_bytes])) || 223 (0x83 != and_state->bytes.byte[and_state->num_prefix_bytes])) ||
222 InstAnd != and_inst->name) break; 224 InstAnd != and_inst->name) break;
223 DEBUG(NaClLog(LOG_INFO, "and instruction\n")); 225 DEBUG(NaClLog(LOG_INFO, "and instruction\n"));
224 226
225 /* Extract the values of the two operands for the and. */ 227 /* Extract the values of the two operands for the and. */
226 if (!NaClExtractBinaryOperandIndices(and_state, &op_1, &op_2)) break; 228 if (!NaClExtractBinaryOperandIndices(and_state, &op_1, &op_2)) break;
227 DEBUG(NaClLog(LOG_INFO, "binary and\n")); 229 DEBUG(NaClLog(LOG_INFO, "binary and\n"));
228 230
229 /* Extract the destination register of the and. */ 231 /* Extract the destination register of the and. */
230 nodes = NaClInstStateExpVector(and_state); 232 nodes = NaClInstStateExpVector(and_state);
231 node = &nodes->node[op_1]; 233 node = &nodes->node[op_1];
232 if (ExprRegister != node->kind) break; 234 if (ExprRegister != node->kind) break;
233 and_reg = NaClGetExpRegister(node); 235 and_reg = NaClGetExpRegisterInline(node);
234 DEBUG(NaClLog(LOG_INFO, "and_reg = %s\n", NaClOpKindName(and_reg))); 236 DEBUG(NaClLog(LOG_INFO, "and_reg = %s\n", NaClOpKindName(and_reg)));
235 and_64_reg = NaClGet64For32BitReg(and_reg); 237 and_64_reg = NaClGet64For32BitReg(and_reg);
236 DEBUG(NaClLog(LOG_INFO, "and_64_reg = %s\n", NaClOpKindName(and_64_reg))); 238 DEBUG(NaClLog(LOG_INFO, "and_64_reg = %s\n", NaClOpKindName(and_64_reg)));
237 if (RegUnknown == and_64_reg) break; 239 if (RegUnknown == and_64_reg) break;
238 DEBUG(NaClLog(LOG_INFO, "registers match!\n")); 240 DEBUG(NaClLog(LOG_INFO, "registers match!\n"));
239 241
240 /* Check that the mask is ok. */ 242 /* Check that the mask is ok. */
241 mask = NaClGetJumpMask(state); 243 mask = NaClGetJumpMask(state);
242 DEBUG(NaClLog(LOG_INFO, "mask = %"NACL_PRIx8"\n", mask)); 244 DEBUG(NaClLog(LOG_INFO, "mask = %"NACL_PRIx8"\n", mask));
243 assert(0 != mask); /* alignment must be either 16 or 32. */ 245 assert(0 != mask); /* alignment must be either 16 or 32. */
244 node = &nodes->node[op_2]; 246 node = &nodes->node[op_2];
245 if (ExprConstant != node->kind || mask != node->value) break; 247 if (ExprConstant != node->kind || mask != node->value) break;
246 DEBUG(NaClLog(LOG_INFO, "is mask constant\n")); 248 DEBUG(NaClLog(LOG_INFO, "is mask constant\n"));
247 249
248 /* Check middle (i.e. lea/add) instruction in 3 instruction sequence. */ 250 /* Check middle (i.e. lea/add) instruction in 3 instruction sequence. */
249 middle_state = NaClInstIterGetLookbackState(iter, 1); 251 middle_state = NaClInstIterGetLookbackStateInline(iter, 1);
250 DEBUG(NaClLog(LOG_INFO, "middle inst: "); 252 DEBUG(NaClLog(LOG_INFO, "middle inst: ");
251 NaClInstStateInstPrint(NaClLogGetGio(), middle_state)); 253 NaClInstStateInstPrint(NaClLogGetGio(), middle_state));
252 middle_inst = NaClInstStateInst(middle_state); 254 middle_inst = NaClInstStateInst(middle_state);
253 255
254 /* Extract the values of the two operands for the lea/add instruction. */ 256 /* Extract the values of the two operands for the lea/add instruction. */
255 if (!NaClExtractBinaryOperandIndices(middle_state, &op_1, &op_2)) break; 257 if (!NaClExtractBinaryOperandIndices(middle_state, &op_1, &op_2)) break;
256 DEBUG(NaClLog(LOG_INFO, "middle is binary, op_1 index = %d\n", op_1)); 258 DEBUG(NaClLog(LOG_INFO, "middle is binary, op_1 index = %d\n", op_1));
257 259
258 /* Extract the destination register of the lea/and, and verify that 260 /* Extract the destination register of the lea/and, and verify that
259 * it is a register. 261 * it is a register.
260 */ 262 */
261 nodes = NaClInstStateExpVector(middle_state); 263 nodes = NaClInstStateExpVector(middle_state);
262 node = &nodes->node[op_1]; 264 node = &nodes->node[op_1];
263 if (ExprRegister != node->kind) break; 265 if (ExprRegister != node->kind) break;
264 266
265 /* Compare the middle destination register to the jump register. */ 267 /* Compare the middle destination register to the jump register. */
266 middle_reg = NaClGetExpRegister(node); 268 middle_reg = NaClGetExpRegisterInline(node);
267 DEBUG(NaClLog(LOG_INFO, "middle reg = %s\n", NaClOpKindName(middle_reg))); 269 DEBUG(NaClLog(LOG_INFO, "middle reg = %s\n", NaClOpKindName(middle_reg)));
268 if (middle_reg != jump_reg) break; 270 if (middle_reg != jump_reg) break;
269 271
270 if (InstLea == middle_inst->name) { 272 if (InstLea == middle_inst->name) {
271 /* Check that we have [%RBASE + %REG64-A] as second argument to lea */ 273 /* Check that we have [%RBASE + %REG64-A] as second argument to lea */
272 node = &nodes->node[op_2]; 274 node = &nodes->node[op_2];
273 if (ExprMemOffset != node->kind || 275 if (ExprMemOffset != node->kind ||
274 !NaClMemOffsetMatchesBaseIndex(nodes, op_2, state->base_register, 276 !NaClMemOffsetMatchesBaseIndex(nodes, op_2, state->base_register,
275 and_64_reg)) { 277 and_64_reg)) {
276 break; 278 break;
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
329 NaClJumpSets* jump_sets 331 NaClJumpSets* jump_sets
330 ) { 332 ) {
331 uint8_t mask; 333 uint8_t mask;
332 NaClInstState* and_state; 334 NaClInstState* and_state;
333 const NaClInst* and_inst; 335 const NaClInst* and_inst;
334 int op_1, op_2; 336 int op_1, op_2;
335 NaClOpKind and_reg, jump_reg; 337 NaClOpKind and_reg, jump_reg;
336 NaClExpVector* nodes; 338 NaClExpVector* nodes;
337 NaClExp* node; 339 NaClExp* node;
338 assert(ExprRegister == reg->kind); 340 assert(ExprRegister == reg->kind);
339 jump_reg = NaClGetExpRegister(reg); 341 jump_reg = NaClGetExpRegisterInline(reg);
340 342
341 /* Do the following block exactly once. */ 343 /* Do the following block exactly once. */
342 do { 344 do {
343 /* Check that the jump is preceded with an AND. */ 345 /* Check that the jump is preceded with an AND. */
344 if (!NaClInstIterHasLookbackState(iter, 1)) break; 346 if (!NaClInstIterHasLookbackStateInline(iter, 1)) break;
345 and_state = NaClInstIterGetLookbackState(iter, 1); 347 and_state = NaClInstIterGetLookbackStateInline(iter, 1);
346 and_inst = NaClInstStateInst(and_state); 348 and_inst = NaClInstStateInst(and_state);
347 if (((and_state->num_opcode_bytes == 0) || 349 if (((and_state->num_opcode_bytes == 0) ||
348 (0x83 != and_state->bytes.byte[and_state->num_prefix_bytes])) || 350 (0x83 != and_state->bytes.byte[and_state->num_prefix_bytes])) ||
349 InstAnd != and_inst->name) break; 351 InstAnd != and_inst->name) break;
350 352
351 /* Extract the values of the two operands for the and. */ 353 /* Extract the values of the two operands for the and. */
352 if (!NaClExtractBinaryOperandIndices(and_state, &op_1, &op_2)) break; 354 if (!NaClExtractBinaryOperandIndices(and_state, &op_1, &op_2)) break;
353 355
354 356
355 /* Check that the register of the AND matches the jump. */ 357 /* Check that the register of the AND matches the jump. */
356 nodes = NaClInstStateExpVector(and_state); 358 nodes = NaClInstStateExpVector(and_state);
357 node = &nodes->node[op_1]; 359 node = &nodes->node[op_1];
358 if (ExprRegister != node->kind) break; 360 if (ExprRegister != node->kind) break;
359 and_reg = NaClGetExpRegister(node); 361 and_reg = NaClGetExpRegisterInline(node);
360 if (jump_reg != and_reg) break; 362 if (jump_reg != and_reg) break;
361 363
362 /* Check that the mask is ok. */ 364 /* Check that the mask is ok. */
363 mask = NaClGetJumpMask(state); 365 mask = NaClGetJumpMask(state);
364 assert(0 != mask); /* alignment must be either 16 or 32. */ 366 assert(0 != mask); /* alignment must be either 16 or 32. */
365 node = &nodes->node[op_2]; 367 node = &nodes->node[op_2];
366 if (ExprConstant != node->kind || mask != node->value) break; 368 if (ExprConstant != node->kind || mask != node->value) break;
367 369
368 /* If reached, indirect jump is properly masked. */ 370 /* If reached, indirect jump is properly masked. */
369 DEBUG(NaClLog(LOG_INFO, "Protect register jump indirect\n")); 371 DEBUG(NaClLog(LOG_INFO, "Protect register jump indirect\n"));
(...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after
477 NaClPcAddress pc, 479 NaClPcAddress pc,
478 NaClInstState* inst_state, 480 NaClInstState* inst_state,
479 NaClJumpSets* jump_sets) { 481 NaClJumpSets* jump_sets) {
480 if (pc < state->vbase || pc >= state->vlimit) { 482 if (pc < state->vbase || pc >= state->vlimit) {
481 NaClValidatorInstMessage(LOG_ERROR, state, inst_state, 483 NaClValidatorInstMessage(LOG_ERROR, state, inst_state,
482 "Instruction pc out of range\n"); 484 "Instruction pc out of range\n");
483 } else { 485 } else {
484 DEBUG(NaClLog(LOG_INFO, 486 DEBUG(NaClLog(LOG_INFO,
485 "Add possible jump address: %"NACL_PRIxNaClPcAddress"\n", 487 "Add possible jump address: %"NACL_PRIxNaClPcAddress"\n",
486 pc)); 488 pc));
487 NaClAddressSetAdd(jump_sets->possible_targets, pc, state); 489 NaClAddressSetAddInline(jump_sets->possible_targets, pc, state);
488 } 490 }
489 } 491 }
490 492
491 void NaClJumpValidatorRememberIpOnly(NaClValidatorState* state, 493 void NaClJumpValidatorRememberIpOnly(NaClValidatorState* state,
492 NaClInstIter* iter, 494 NaClInstIter* iter,
493 NaClJumpSets* jump_sets) { 495 NaClJumpSets* jump_sets) {
494 NaClInstState* inst_state = state->cur_inst_state; 496 NaClInstState* inst_state = state->cur_inst_state;
495 NaClPcAddress pc = NaClInstStateVpc(inst_state); 497 NaClPcAddress pc = NaClInstStateVpc(inst_state);
496 NaClRememberIp(state, pc, inst_state, jump_sets); 498 NaClRememberIp(state, pc, inst_state, jump_sets);
497 } 499 }
(...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after
628 */ 630 */
629 } else { 631 } else {
630 NaClJumpSets* jump_sets = 632 NaClJumpSets* jump_sets =
631 (NaClJumpSets*) 633 (NaClJumpSets*)
632 NaClGetValidatorLocalMemory((NaClValidator) NaClJumpValidator, 634 NaClGetValidatorLocalMemory((NaClValidator) NaClJumpValidator,
633 state); 635 state);
634 DEBUG(NaClLog(LOG_INFO, 636 DEBUG(NaClLog(LOG_INFO,
635 "Mark instruction as jump illegal: %"NACL_PRIxNaClPcAddress 637 "Mark instruction as jump illegal: %"NACL_PRIxNaClPcAddress
636 "\n", 638 "\n",
637 pc)); 639 pc));
638 NaClAddressSetAdd(jump_sets->removed_targets, pc, state); 640 NaClAddressSetAddInline(jump_sets->removed_targets, pc, state);
639 } 641 }
640 } 642 }
OLDNEW
« no previous file with comments | « src/trusted/validator/x86/ncval_reg_sfi/nc_cpu_checks.c ('k') | src/trusted/validator/x86/ncval_reg_sfi/nc_jumps_detailed.c » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698