| 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 // Add all NOPs with consecutive instruction indexes. |
| 49 while (nop_it != nop_spec.end() && nop_it->first == write_index) { |
| 50 assm.nop(nop_it->second); |
| 51 ++nop_it; |
| 52 ++write_index; |
| 53 } |
| 54 } |
| 55 ++inst_it; |
| 56 ++write_index; |
| 57 } |
| 58 } |
| 59 |
| 60 bool FillerBasicBlockTransform::TransformBasicBlockSubGraph( |
| 61 const TransformPolicyInterface* policy, |
| 62 BlockGraph* block_graph, |
| 63 BasicBlockSubGraph* basic_block_subgraph) { |
| 64 DCHECK(nullptr != policy); |
| 65 DCHECK(nullptr != block_graph); |
| 66 DCHECK(nullptr != basic_block_subgraph); |
| 67 |
| 68 // Locations for code injection. |
| 69 NopSpec nop_spec = {{1, NOP1}}; |
| 70 |
| 71 // Visit each basic code block and inject NOPs. |
| 72 BasicBlockSubGraph::BBCollection& basic_blocks = |
| 73 basic_block_subgraph->basic_blocks(); |
| 74 for (auto bb = basic_blocks.begin(); bb != basic_blocks.end(); ++bb) { |
| 75 BasicCodeBlock* bc_block = BasicCodeBlock::Cast(*bb); |
| 76 if (bc_block != nullptr) |
| 77 InjectNop(nop_spec, debug_friendly_, &bc_block->instructions()); |
| 78 } |
| 79 return true; |
| 80 } |
| 81 |
| 82 FillerTransform::FillerTransform(const std::vector<std::string>& target_list) |
| 83 : debug_friendly_(false), |
| 84 num_blocks_(0), |
| 85 num_code_blocks_(0), |
| 86 num_targets_updated_(0) { |
| 87 // Targets are not found yet, so initialize value to false. |
| 88 for (const std::string& target : target_list) |
| 89 target_names_[target] = false; |
| 90 } |
| 91 |
| 92 bool FillerTransform::ShouldProcessBlock(Block* block) const { |
| 93 return target_names_.find(block->name()) != target_names_.end(); |
| 94 } |
| 95 |
| 96 void FillerTransform::CheckAllTargetsFound() const { |
| 97 bool has_missing = false; |
| 98 for (auto it = target_names_.begin(); it != target_names_.end(); ++it) { |
| 99 if (it->second) |
| 100 continue; |
| 101 if (!has_missing) { |
| 102 LOG(WARNING) << "There are missing target(s):"; |
| 103 has_missing = true; |
| 104 } |
| 105 LOG(WARNING) << " " << it->first; |
| 106 } |
| 107 } |
| 108 |
| 109 bool FillerTransform::PreBlockGraphIteration( |
| 110 const TransformPolicyInterface* policy, |
| 111 BlockGraph* block_graph, |
| 112 Block* header_block) { |
| 113 return true; |
| 114 } |
| 115 |
| 116 bool FillerTransform::OnBlock(const TransformPolicyInterface* policy, |
| 117 BlockGraph* block_graph, |
| 118 Block* block) { |
| 119 DCHECK(nullptr != policy); |
| 120 DCHECK(nullptr != block_graph); |
| 121 DCHECK(nullptr != block); |
| 122 |
| 123 ++num_blocks_; |
| 124 if (block->type() != BlockGraph::CODE_BLOCK) |
| 125 return true; |
| 126 |
| 127 ++num_code_blocks_; |
| 128 if (!ShouldProcessBlock(block)) |
| 129 return true; |
| 130 |
| 131 // Mark target as found. |
| 132 std::string name(block->name()); |
| 133 auto target_it = target_names_.find(block->name()); |
| 134 if (target_it != target_names_.end()) |
| 135 target_it->second = true; |
| 136 |
| 137 // Skip blocks that aren't eligible for basic-block decomposition. |
| 138 if (!policy->BlockIsSafeToBasicBlockDecompose(block)) |
| 139 return true; |
| 140 |
| 141 ++num_targets_updated_; |
| 142 // Apply the basic block transform. |
| 143 FillerBasicBlockTransform basic_block_transform; |
| 144 basic_block_transform.set_debug_friendly(debug_friendly()); |
| 145 return ApplyBasicBlockSubGraphTransform( |
| 146 &basic_block_transform, policy, block_graph, block, NULL); |
| 147 } |
| 148 |
| 149 bool FillerTransform::PostBlockGraphIteration( |
| 150 const TransformPolicyInterface* policy, |
| 151 BlockGraph* block_graph, |
| 152 Block* header_block) { |
| 153 LOG(INFO) << "Found " << num_blocks_ << " block(s)."; |
| 154 LOG(INFO) << "Found " << num_code_blocks_ << " code block(s)."; |
| 155 LOG(INFO) << "Updated " << num_targets_updated_ << " blocks(s)."; |
| 156 CheckAllTargetsFound(); |
| 157 return true; |
| 158 } |
| 159 |
| 160 } // namespace transforms |
| 161 } // namespace instrument |
| OLD | NEW |