Coverage for /Syzygy/block_graph/transform.cc

CoverageLines executed / instrumented / missingexe / inst / missLanguageGroup
82.3%931130.C++source

Line-by-line coverage:

   1    :  // Copyright 2012 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/block_graph/transform.h"
  16    :  
  17    :  #include "syzygy/block_graph/basic_block_decomposer.h"
  18    :  #include "syzygy/block_graph/block_builder.h"
  19    :  #include "syzygy/block_graph/block_util.h"
  20    :  
  21    :  namespace block_graph {
  22    :  
  23    :  bool ApplyImageLayoutTransform(
  24    :      ImageLayoutTransformInterface* transform,
  25    :      const TransformPolicyInterface* policy,
  26    :      const pe::ImageLayout* image_layout,
  27  E :      const OrderedBlockGraph* ordered_block_graph) {
  28  E :    DCHECK(transform != NULL);
  29  E :    DCHECK(transform->name() != NULL);
  30  E :    DCHECK(policy != NULL);
  31  E :    DCHECK_GT(strlen(transform->name()), 0u);
  32  E :    DCHECK(image_layout != NULL);
  33  E :    DCHECK(ordered_block_graph != NULL);
  34    :  
  35    :    // Only the contents of block data can be changed in-place. References are
  36    :    // allowed to change. However one cannot add, delete or reorder blocks and/or
  37    :    // sections, nor can the size of blocks or sections be changed by adding or
  38    :    // deteling data bytes.
  39    :    // Get total number and the size of each block.
  40  E :    size_t no_blocks = image_layout->blocks.size();
  41  E :    std::vector<size_t> block_size;
  42  E :    auto block_it = image_layout->blocks.begin();
  43  E :    for (; block_it != image_layout->blocks.end(); ++block_it) {
  44  i :      block_size.push_back(block_it->first.size());
  45  i :    }
  46    :  
  47  E :    if (!transform->TransformImageLayout(policy, image_layout,
  48    :        ordered_block_graph)) {
  49  i :      LOG(ERROR) << "Layout transform \"" << transform->name() << "\" failed.";
  50  i :      return false;
  51    :    }
  52    :  
  53    :    // Ensure the number of blocks and the size of each block has not changed
  54  E :    if (no_blocks != image_layout->blocks.size()) {
  55  i :      LOG(ERROR) << "Layout transform \"" << transform->name() << "\" changed "
  56    :                 << "number of blocks.";
  57  i :      return false;
  58    :    }
  59  E :    block_it = image_layout->blocks.begin();
  60  E :    for (size_t i = 0; block_it != image_layout->blocks.end(); ++block_it, ++i) {
  61  i :      if (block_size[i] != block_it->first.size()) {
  62  i :        LOG(ERROR) << "Layout transform \"" << transform->name() << "\" changed "
  63    :                   << "size of blocks.";
  64  i :        return false;
  65    :      }
  66  i :    }
  67    :  
  68  E :    return true;
  69  E :  }
  70    :  
  71    :  bool ApplyImageLayoutTransforms(
  72    :      const std::vector<ImageLayoutTransformInterface*>& transforms,
  73    :      const TransformPolicyInterface* policy,
  74    :      const pe::ImageLayout* image_layout,
  75  E :      const OrderedBlockGraph* ordered_block_graph) {
  76  E :    DCHECK_NE(reinterpret_cast<TransformPolicyInterface*>(NULL), policy);
  77  E :    DCHECK_NE(reinterpret_cast<pe::ImageLayout*>(NULL), image_layout);
  78  E :    DCHECK_NE(reinterpret_cast<OrderedBlockGraph*>(NULL), ordered_block_graph);
  79    :  
  80    :    // Apply the transforms sequentially.
  81  E :    for (size_t i = 0; i < transforms.size(); ++i) {
  82  E :      if (!ApplyImageLayoutTransform(transforms[i],
  83    :          policy,
  84    :          image_layout,
  85    :          ordered_block_graph)) {
  86  i :        return false;
  87    :      }
  88  E :    }
  89    :  
  90  E :    return true;
  91  E :  }
  92    :  
  93    :  bool ApplyBlockGraphTransform(BlockGraphTransformInterface* transform,
  94    :                                const TransformPolicyInterface* policy,
  95    :                                BlockGraph* block_graph,
  96  E :                                BlockGraph::Block* header_block) {
  97  E :    DCHECK(transform != NULL);
  98  E :    DCHECK(transform->name() != NULL);
  99  E :    DCHECK(policy != NULL);
 100  E :    DCHECK_GT(strlen(transform->name()), 0u);
 101  E :    DCHECK(block_graph != NULL);
 102  E :    DCHECK(header_block != NULL);
 103    :  
 104    :    // Get the ID of the header block. As a sanity check we want to ensure
 105    :    // that it still exists after the transform.
 106  E :    BlockGraph::BlockId header_block_id = header_block->id();
 107    :  
 108  E :    if (!transform->TransformBlockGraph(policy, block_graph, header_block)) {
 109  E :      LOG(ERROR) << "Transform \"" << transform->name() << "\" failed.";
 110  E :      return false;
 111    :    }
 112    :  
 113    :    // Ensure that the header block still exists. If it was changed, it needs
 114    :    // to have been changed in place.
 115  E :    BlockGraph::Block* block = block_graph->GetBlockById(header_block_id);
 116  E :    if (block == NULL) {
 117  E :      LOG(ERROR) << "Header block not found after \"" << transform->name()
 118    :                 << "\" transform.";
 119  E :      return false;
 120    :    }
 121  E :    DCHECK_EQ(header_block, block);
 122    :  
 123  E :    return true;
 124  E :  }
 125    :  
 126    :  bool ApplyBlockGraphTransforms(
 127    :      const std::vector<BlockGraphTransformInterface*>& transforms,
 128    :      const TransformPolicyInterface* policy,
 129    :      BlockGraph* block_graph,
 130  E :      BlockGraph::Block* header_block) {
 131  E :    DCHECK_NE(reinterpret_cast<TransformPolicyInterface*>(NULL), policy);
 132  E :    DCHECK_NE(reinterpret_cast<BlockGraph*>(NULL), block_graph);
 133  E :    DCHECK_NE(reinterpret_cast<BlockGraph::Block*>(NULL), header_block);
 134    :  
 135    :    // Apply the transforms sequentially.
 136  E :    for (size_t i = 0; i < transforms.size(); ++i) {
 137  E :      if (!ApplyBlockGraphTransform(transforms[i],
 138    :                                    policy,
 139    :                                    block_graph,
 140    :                                    header_block)) {
 141  E :        return false;
 142    :      }
 143  E :    }
 144    :  
 145  E :    return true;
 146  E :  }
 147    :  
 148    :  bool ApplyBasicBlockSubGraphTransform(
 149    :      BasicBlockSubGraphTransformInterface* transform,
 150    :      const TransformPolicyInterface* policy,
 151    :      BlockGraph* block_graph,
 152    :      BlockGraph::Block* block,
 153  E :      BlockVector* new_blocks) {
 154  E :    DCHECK(transform != NULL);
 155  E :    DCHECK(policy != NULL);
 156  E :    DCHECK(block_graph != NULL);
 157  E :    DCHECK(block != NULL);
 158  E :    DCHECK_EQ(BlockGraph::CODE_BLOCK, block->type());
 159  E :    DCHECK(policy->BlockIsSafeToBasicBlockDecompose(block));
 160    :  
 161    :    // Decompose block to basic blocks.
 162  E :    BasicBlockSubGraph subgraph;
 163  E :    BasicBlockDecomposer bb_decomposer(block, &subgraph);
 164  E :    if (!bb_decomposer.Decompose()) {
 165    :      // If the failure is due to unsupported instructions then simply mark the
 166    :      // block as undecomposable so it won't be processed again.
 167  i :      if (bb_decomposer.contains_unsupported_instructions()) {
 168  i :        VLOG(1) << "Block contains unsupported instruction(s): "
 169    :                << BlockInfo(block);
 170  i :        block->set_attribute(BlockGraph::UNSUPPORTED_INSTRUCTIONS);
 171  i :        return true;
 172    :      }
 173    :  
 174  i :      return false;
 175    :    }
 176    :  
 177    :    // Call the transform.
 178  E :    if (!transform->TransformBasicBlockSubGraph(policy, block_graph, &subgraph))
 179  E :      return false;
 180    :  
 181    :    // Update the block-graph post transform.
 182  E :    BlockBuilder builder(block_graph);
 183  E :    if (!builder.Merge(&subgraph))
 184  i :      return false;
 185    :  
 186  E :    if (new_blocks != NULL) {
 187  E :      new_blocks->assign(builder.new_blocks().begin(),
 188    :                         builder.new_blocks().end());
 189    :    }
 190    :  
 191  E :    return true;
 192  E :  }
 193    :  
 194    :  bool ApplyBasicBlockSubGraphTransforms(
 195    :      const std::vector<BasicBlockSubGraphTransformInterface*>& transforms,
 196    :      const TransformPolicyInterface* policy,
 197    :      BlockGraph* block_graph,
 198    :      BlockGraph::Block* block,
 199  E :      BlockVector* new_blocks) {
 200  E :    DCHECK(policy != NULL);
 201  E :    DCHECK(block_graph != NULL);
 202  E :    DCHECK(block != NULL);
 203  E :    DCHECK_EQ(BlockGraph::CODE_BLOCK, block->type());
 204  E :    DCHECK(policy->BlockIsSafeToBasicBlockDecompose(block));
 205    :  
 206    :    // Decompose block to basic blocks.
 207  E :    BasicBlockSubGraph subgraph;
 208  E :    BasicBlockDecomposer bb_decomposer(block, &subgraph);
 209  E :    if (!bb_decomposer.Decompose())
 210  i :      return false;
 211    :  
 212    :    // Call the transforms.
 213    :    std::vector<BasicBlockSubGraphTransformInterface*>::const_iterator it =
 214  E :        transforms.begin();
 215  E :    for (; it != transforms.end(); ++it) {
 216  E :      BasicBlockSubGraphTransformInterface* transform = *it;
 217  E :      DCHECK(transform != NULL);
 218  E :      if (!transform->TransformBasicBlockSubGraph(policy, block_graph, &subgraph))
 219  i :        return false;
 220  E :    }
 221    :  
 222    :    // Update the block-graph post transform.
 223  E :    BlockBuilder builder(block_graph);
 224  E :    if (!builder.Merge(&subgraph))
 225  i :      return false;
 226    :  
 227  E :    if (new_blocks != NULL) {
 228  E :      new_blocks->assign(builder.new_blocks().begin(),
 229    :                         builder.new_blocks().end());
 230    :    }
 231    :  
 232  E :    return true;
 233  E :  }
 234    :  
 235    :  }  // namespace block_graph

Coverage information generated Fri Jul 29 11:00:21 2016.