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

Side by Side Diff: sandbox/linux/seccomp-bpf/codegen.cc

Issue 286063007: Simplify PointerCompare a little (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 6 years, 7 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
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include <stdio.h> 5 #include <stdio.h>
6 6
7 #include "base/logging.h" 7 #include "base/logging.h"
8 #include "sandbox/linux/seccomp-bpf/codegen.h" 8 #include "sandbox/linux/seccomp-bpf/codegen.h"
9 9
10 namespace { 10 namespace {
(...skipping 425 matching lines...) Expand 10 before | Expand all | Expand 10 after
436 // Basic blocks should never be empty. 436 // Basic blocks should never be empty.
437 CHECK(!insns1.empty()); 437 CHECK(!insns1.empty());
438 CHECK(!insns2.empty()); 438 CHECK(!insns2.empty());
439 439
440 Instructions::const_iterator iter1 = insns1.begin(); 440 Instructions::const_iterator iter1 = insns1.begin();
441 Instructions::const_iterator iter2 = insns2.begin(); 441 Instructions::const_iterator iter2 = insns2.begin();
442 for (;; ++iter1, ++iter2) { 442 for (;; ++iter1, ++iter2) {
443 // If we have reached the end of the sequence of instructions in one or 443 // If we have reached the end of the sequence of instructions in one or
444 // both basic blocks, we know the relative ordering between the two blocks 444 // both basic blocks, we know the relative ordering between the two blocks
445 // and can return. 445 // and can return.
446 if (iter1 == insns1.end()) { 446 if (iter1 == insns1.end() || iter2 == insns2.end()) {
447 if (iter2 == insns2.end()) { 447 if (iter1 != insns1.end()) {
448 // If the two blocks are the same length (and have elementwise-equal 448 return 1;
449 // code and k fields, which is the only way we can reach this point),
450 // and the last instruction isn't a JMP or a RET, then we must compare
451 // their successors.
452 Instruction* const insns1_last = insns1.back();
453 Instruction* const insns2_last = insns2.back();
454 if (BPF_CLASS(insns1_last->code) != BPF_JMP &&
455 BPF_CLASS(insns1_last->code) != BPF_RET) {
456 // Non jumping instructions will always have a valid next instruction.
457 CHECK(insns1_last->next);
458 CHECK(insns2_last->next);
459 return PointerCompare(blocks.find(insns1_last->next)->second,
460 blocks.find(insns2_last->next)->second,
461 blocks);
462 } else {
463 return 0;
464 }
465 } 449 }
466 return -1; 450 if (iter2 != insns2.end()) {
467 } else if (iter2 == insns2.end()) { 451 return -1;
468 return 1; 452 }
453
454 // If the two blocks are the same length (and have elementwise-equal code
455 // and k fields) and their last instructions are neither a JMP nor a RET
456 // (which is the only way we can reach this point), then we must compare
457 // their successors.
458 Instruction* const insns1_last = insns1.back();
459 Instruction* const insns2_last = insns2.back();
460 CHECK(BPF_CLASS(insns1_last->code) != BPF_JMP &&
461 BPF_CLASS(insns1_last->code) != BPF_RET);
462
463 // Non jumping instructions will always have a valid next instruction.
464 CHECK(insns1_last->next);
465 CHECK(insns2_last->next);
466 return PointerCompare(blocks.find(insns1_last->next)->second,
467 blocks.find(insns2_last->next)->second,
468 blocks);
469 } 469 }
470 470
471 // Compare the individual fields for both instructions. 471 // Compare the individual fields for both instructions.
472 const Instruction& insn1 = **iter1; 472 const Instruction& insn1 = **iter1;
473 const Instruction& insn2 = **iter2; 473 const Instruction& insn2 = **iter2;
474 if (insn1.code == insn2.code) { 474 if (insn1.code != insn2.code) {
475 if (insn1.k == insn2.k) {
476 // Only conditional jump instructions use the jt_ptr and jf_ptr
477 // fields.
478 if (BPF_CLASS(insn1.code) == BPF_JMP) {
479 if (BPF_OP(insn1.code) != BPF_JA) {
480 // Recursively compare the "true" and "false" branches.
481 // A well-formed BPF program can't have any cycles, so we know
482 // that our recursive algorithm will ultimately terminate.
483 // In the unlikely event that the programmer made a mistake and
484 // went out of the way to give us a cyclic program, we will crash
485 // with a stack overflow. We are OK with that.
486 int c = PointerCompare(blocks.find(insn1.jt_ptr)->second,
487 blocks.find(insn2.jt_ptr)->second,
488 blocks);
489 if (c == 0) {
490 c = PointerCompare(blocks.find(insn1.jf_ptr)->second,
491 blocks.find(insn2.jf_ptr)->second,
492 blocks);
493 if (c == 0) {
494 continue;
495 } else {
496 return c;
497 }
498 } else {
499 return c;
500 }
501 } else {
502 int c = PointerCompare(blocks.find(insn1.jt_ptr)->second,
503 blocks.find(insn2.jt_ptr)->second,
504 blocks);
505 if (c == 0) {
506 continue;
507 } else {
508 return c;
509 }
510 }
511 } else {
512 continue;
513 }
514 } else {
515 return insn1.k - insn2.k;
516 }
517 } else {
518 return insn1.code - insn2.code; 475 return insn1.code - insn2.code;
519 } 476 }
477 if (insn1.k != insn2.k) {
478 return insn1.k - insn2.k;
479 }
480
481 // Sanity check: If we're looking at a JMP or RET instruction, by definition
482 // it should be the last instruction of the basic block.
483 if (BPF_CLASS(insn1.code) == BPF_JMP || BPF_CLASS(insn1.code) == BPF_RET) {
484 CHECK_EQ(insns1.back(), &insn1);
485 CHECK_EQ(insns2.back(), &insn2);
486 }
487
488 // RET instructions terminate execution, and only JMP instructions use the
489 // jt_ptr and jf_ptr fields. Anything else can continue to the next
490 // instruction in the basic block.
491 if (BPF_CLASS(insn1.code) == BPF_RET) {
492 return 0;
493 } else if (BPF_CLASS(insn1.code) != BPF_JMP) {
494 continue;
495 }
496
497 // Recursively compare the "true" and "false" branches.
498 // A well-formed BPF program can't have any cycles, so we know
499 // that our recursive algorithm will ultimately terminate.
500 // In the unlikely event that the programmer made a mistake and
501 // went out of the way to give us a cyclic program, we will crash
502 // with a stack overflow. We are OK with that.
503 if (BPF_OP(insn1.code) != BPF_JA) {
504 int c = PointerCompare(blocks.find(insn1.jf_ptr)->second,
505 blocks.find(insn2.jf_ptr)->second,
506 blocks);
507 if (c != 0) {
508 return c;
509 }
510 }
511 return PointerCompare(blocks.find(insn1.jt_ptr)->second,
512 blocks.find(insn2.jt_ptr)->second,
513 blocks);
520 } 514 }
521 } 515 }
522 516
523 void CodeGen::MergeTails(TargetsToBlocks* blocks) { 517 void CodeGen::MergeTails(TargetsToBlocks* blocks) {
524 // We enter all of our basic blocks into a set using the BasicBlock::Less() 518 // We enter all of our basic blocks into a set using the BasicBlock::Less()
525 // comparator. This naturally results in blocks with identical tails of 519 // comparator. This naturally results in blocks with identical tails of
526 // instructions to map to the same entry in the set. Whenever we discover 520 // instructions to map to the same entry in the set. Whenever we discover
527 // that a particular chain of instructions is already in the set, we merge 521 // that a particular chain of instructions is already in the set, we merge
528 // the basic blocks and update the pointer in the "blocks" map. 522 // the basic blocks and update the pointer in the "blocks" map.
529 // Returns the number of unique basic blocks. 523 // Returns the number of unique basic blocks.
(...skipping 235 matching lines...) Expand 10 before | Expand all | Expand 10 after
765 CutGraphIntoBasicBlocks(instructions, branch_targets, &all_blocks); 759 CutGraphIntoBasicBlocks(instructions, branch_targets, &all_blocks);
766 MergeTails(&all_blocks); 760 MergeTails(&all_blocks);
767 BasicBlocks basic_blocks; 761 BasicBlocks basic_blocks;
768 TopoSortBasicBlocks(first_block, all_blocks, &basic_blocks); 762 TopoSortBasicBlocks(first_block, all_blocks, &basic_blocks);
769 ComputeRelativeJumps(&basic_blocks, all_blocks); 763 ComputeRelativeJumps(&basic_blocks, all_blocks);
770 ConcatenateBasicBlocks(basic_blocks, program); 764 ConcatenateBasicBlocks(basic_blocks, program);
771 return; 765 return;
772 } 766 }
773 767
774 } // namespace sandbox 768 } // namespace sandbox
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698