Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 1 // Copyright 2015 Google Inc. All Rights Reserved. | |
| 2 // | |
| 3 // Licensed under the Apache License, Version 2.0 (the "License"); | |
| 4 // you may not use this file except in compliance with the License. | |
| 5 // You may obtain a copy of the License at | |
| 6 // | |
| 7 // http://www.apache.org/licenses/LICENSE-2.0 | |
| 8 // | |
| 9 // Unless required by applicable law or agreed to in writing, software | |
| 10 // distributed under the License is distributed on an "AS IS" BASIS, | |
| 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
| 12 // See the License for the specific language governing permissions and | |
| 13 // limitations under the License. | |
| 14 | |
| 15 #include "syzygy/instrument/transforms/filler_transform.h" | |
| 16 | |
| 17 #include "base/logging.h" | |
| 18 #include "syzygy/assm/assembler_base.h" | |
| 19 #include "syzygy/block_graph/basic_block_assembler.h" | |
| 20 #include "syzygy/block_graph/basic_block_subgraph.h" | |
| 21 #include "syzygy/block_graph/block_util.h" | |
| 22 #include "syzygy/block_graph/transform_policy.h" | |
| 23 | |
| 24 namespace instrument { | |
| 25 namespace transforms { | |
| 26 | |
| 27 const char FillerBasicBlockTransform::kTransformName[] = | |
| 28 "FillerBasicBlockTransform"; | |
| 29 | |
| 30 const char FillerTransform::kTransformName[] = "FillerTransform"; | |
| 31 | |
| 32 // static | |
| 33 void FillerBasicBlockTransform::InjectNop( | |
| 34 const NopSpec& nop_spec, | |
| 35 bool debug_friendly, | |
| 36 BasicBlock::Instructions* instructions) { | |
| 37 BasicBlock::Instructions::iterator inst_it = instructions->begin(); | |
| 38 NopSpec::const_iterator nop_it = nop_spec.begin(); | |
| 39 size_t write_index = 0LL; | |
| 40 while (inst_it != instructions->end() && nop_it != nop_spec.end()) { | |
| 41 if (nop_it->first == write_index) { | |
| 42 block_graph::BasicBlockAssembler assm(inst_it, instructions); | |
| 43 // If specified, set source range for successive NOPs to to be that of the | |
| 44 // current instruction (which follows the NOPs). Caveat: This breaks the | |
| 45 // 1:1 OMAP mapping and may confuse some debuggers. | |
| 46 if (debug_friendly) { | |
| 47 assm.set_source_range(inst_it->source_range()); | |
| 48 auto source_range = inst_it->source_range(); | |
|
chrisha
2015/06/10 18:07:27
What is this needed for?
huangs
2015/06/11 14:54:15
Removed.
| |
| 49 } | |
| 50 // Add all NOPs with consecutive instruction indexes. | |
| 51 while (nop_it != nop_spec.end() && nop_it->first == write_index) { | |
| 52 assm.nop(nop_it->second); | |
| 53 ++nop_it; | |
| 54 ++write_index; | |
| 55 } | |
| 56 } | |
| 57 ++inst_it; | |
| 58 ++write_index; | |
| 59 } | |
| 60 } | |
| 61 | |
| 62 bool FillerBasicBlockTransform::TransformBasicBlockSubGraph( | |
| 63 const TransformPolicyInterface* policy, | |
| 64 BlockGraph* block_graph, | |
| 65 BasicBlockSubGraph* basic_block_subgraph) { | |
| 66 DCHECK(nullptr != policy); | |
| 67 DCHECK(nullptr != block_graph); | |
| 68 DCHECK(nullptr != basic_block_subgraph); | |
| 69 | |
| 70 // Locations for code injection. | |
| 71 NopSpec nop_spec = {{1, NOP1}}; | |
|
chrisha
2015/06/10 18:07:27
Is this going to be sufficient? Do we maybe want t
huangs
2015/06/11 14:54:15
We want to start small; will do randomness later.
| |
| 72 | |
| 73 fprintf(stderr, "TransformBasicBlockSubGraph: %s\n", | |
| 74 debug_friendly_ ? "true" : "false"); | |
|
chrisha
2015/06/10 18:07:27
Debugging code?
huangs
2015/06/11 14:54:15
Removed.
| |
| 75 | |
| 76 // Visit each basic code block and inject NOPs. | |
| 77 BasicBlockSubGraph::BBCollection& basic_blocks = | |
| 78 basic_block_subgraph->basic_blocks(); | |
| 79 for (auto bb = basic_blocks.begin(); bb != basic_blocks.end(); ++bb) { | |
| 80 BasicCodeBlock* bc_block = BasicCodeBlock::Cast(*bb); | |
| 81 if (bc_block != nullptr) | |
| 82 InjectNop(nop_spec, debug_friendly_, &bc_block->instructions()); | |
| 83 } | |
| 84 return true; | |
| 85 } | |
| 86 | |
| 87 FillerTransform::FillerTransform(const std::vector<std::string>& target_list) | |
| 88 : debug_friendly_(false), | |
| 89 num_blocks_(0), | |
| 90 num_code_blocks_(0), | |
| 91 num_targets_updated_(0) { | |
| 92 // Targets are not found yet, so initialize value to false. | |
| 93 for (const std::string& target : target_list) | |
| 94 target_names_[target] = false; | |
| 95 } | |
| 96 | |
| 97 bool FillerTransform::ShouldProcessBlock(Block* block) const { | |
| 98 return target_names_.find(block->name()) != target_names_.end(); | |
| 99 } | |
| 100 | |
| 101 void FillerTransform::CheckAllTargetFound() const { | |
| 102 bool has_missing = false; | |
| 103 for (auto it = target_names_.begin(); it != target_names_.end(); ++it) { | |
| 104 if (it->second) | |
| 105 continue; | |
| 106 if (!has_missing) { | |
| 107 LOG(WARNING) << "There are missing target(s):"; | |
| 108 has_missing = true; | |
| 109 } | |
| 110 LOG(WARNING) << " " << it->first; | |
| 111 } | |
| 112 } | |
| 113 | |
| 114 bool FillerTransform::PreBlockGraphIteration( | |
| 115 const TransformPolicyInterface* policy, | |
| 116 BlockGraph* block_graph, | |
| 117 Block* header_block) { | |
| 118 return true; | |
| 119 } | |
| 120 | |
| 121 bool FillerTransform::OnBlock(const TransformPolicyInterface* policy, | |
| 122 BlockGraph* block_graph, | |
| 123 Block* block) { | |
| 124 DCHECK(nullptr != policy); | |
| 125 DCHECK(nullptr != block_graph); | |
| 126 DCHECK(nullptr != block); | |
| 127 | |
| 128 ++num_blocks_; | |
| 129 if (block->type() != BlockGraph::CODE_BLOCK) | |
| 130 return true; | |
| 131 | |
| 132 ++num_code_blocks_; | |
| 133 if (!ShouldProcessBlock(block)) | |
| 134 return true; | |
| 135 | |
| 136 // Mark target as found. | |
| 137 std::string name(block->name()); | |
| 138 auto target_it = target_names_.find(block->name()); | |
| 139 if (target_it != target_names_.end()) | |
| 140 target_it->second = true; | |
| 141 | |
| 142 // Skip blocks that aren't eligible for basic-block decomposition. | |
| 143 if (!policy->BlockIsSafeToBasicBlockDecompose(block)) | |
| 144 return true; | |
| 145 | |
| 146 ++num_targets_updated_; | |
| 147 // Apply the basic block transform. | |
| 148 FillerBasicBlockTransform basic_block_transform; | |
| 149 basic_block_transform.set_debug_friendly(debug_friendly()); | |
| 150 return ApplyBasicBlockSubGraphTransform( | |
| 151 &basic_block_transform, policy, block_graph, block, NULL); | |
| 152 } | |
| 153 | |
| 154 bool FillerTransform::PostBlockGraphIteration( | |
| 155 const TransformPolicyInterface* policy, | |
| 156 BlockGraph* block_graph, | |
| 157 Block* header_block) { | |
| 158 LOG(INFO) << "Found " << num_blocks_ << " block(s)."; | |
| 159 LOG(INFO) << "Found " << num_code_blocks_ << " code block(s)."; | |
| 160 LOG(INFO) << "Updated " << num_targets_updated_ << " blocks(s)."; | |
| 161 CheckAllTargetFound(); | |
| 162 return true; | |
| 163 } | |
| 164 | |
| 165 } // namespace transforms | |
| 166 } // namespace instrument | |
| OLD | NEW |