Coverage for /Syzygy/instrument/transforms/filler_transform.cc

CoverageLines executed / instrumented / missingexe / inst / missLanguageGroup
93.2%82880.C++source

Line-by-line coverage:

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

Coverage information generated Thu Jan 14 17:40:38 2016.