Coverage for /Syzygy/pe/transforms/add_hot_patching_metadata_transform.cc

CoverageLines executed / instrumented / missingexe / inst / missLanguageGroup
100.0%48480.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/pe/transforms/add_hot_patching_metadata_transform.h"
  16    :  
  17    :  #include "syzygy/block_graph/hot_patching_metadata.h"
  18    :  #include "syzygy/block_graph/typed_block.h"
  19    :  #include "syzygy/common/defs.h"
  20    :  #include "syzygy/pe/pe_utils.h"
  21    :  
  22    :  namespace pe {
  23    :  namespace transforms {
  24    :  
  25    :  const char AddHotPatchingMetadataTransform::kTransformName[] =
  26    :      "AddHotPatchingMetadataTransform";
  27    :  
  28    :  AddHotPatchingMetadataTransform::AddHotPatchingMetadataTransform()
  29  E :      : blocks_prepared_(nullptr) {
  30  E :  }
  31    :  
  32    :  bool AddHotPatchingMetadataTransform::TransformBlockGraph(
  33    :      const TransformPolicyInterface* policy,
  34    :      BlockGraph* block_graph,
  35  E :      BlockGraph::Block* header_block) {
  36  E :    DCHECK_NE(static_cast<BlockVector*>(nullptr), blocks_prepared_);
  37    :  
  38    :    // Add the section that contains the hot patching metadata.
  39  E :    if (!blocks_prepared_->empty())
  40  E :      AddHotPatchingSection(block_graph);
  41    :  
  42  E :    return true;
  43  E :  }
  44    :  
  45    :  void AddHotPatchingMetadataTransform::AddHotPatchingSection(
  46  E :      BlockGraph* block_graph) {
  47  E :    DCHECK_NE(static_cast<BlockGraph*>(nullptr), block_graph);
  48  E :    DCHECK_NE(static_cast<BlockVector*>(nullptr), blocks_prepared_);
  49    :  
  50    :    using block_graph::TypedBlock;
  51    :    using block_graph::HotPatchingBlockMetadata;
  52    :    using block_graph::HotPatchingMetadataHeader;
  53    :  
  54    :    // Create a block for hot patching metadata.
  55    :    BlockGraph::Size hp_metadata_size = sizeof(HotPatchingMetadataHeader) +
  56  E :        sizeof(HotPatchingBlockMetadata) * blocks_prepared_->size();
  57    :    BlockGraph::Block* hp_metadata_block = block_graph->AddBlock(
  58    :        BlockGraph::DATA_BLOCK,
  59    :        hp_metadata_size,
  60  E :        common::kHotPatchingMetadataSectionName);
  61  E :    DCHECK_NE(static_cast<BlockGraph::Block*>(nullptr), hp_metadata_block);
  62  E :    hp_metadata_block->AllocateData(hp_metadata_size);
  63  E :    DCHECK(hp_metadata_block->owns_data());
  64    :  
  65    :    // Create hot patching metadata header.
  66  E :    TypedBlock<HotPatchingMetadataHeader> hp_header;
  67  E :    hp_header.Init(0, hp_metadata_block);
  68  E :    hp_header->version = block_graph::kHotPatchingMetadataVersion;
  69  E :    hp_header->number_of_blocks = blocks_prepared_->size();
  70    :  
  71    :    // Create hot patching block metadata.
  72  E :    size_t index = 0;
  73  E :    for (BlockGraph::Block* block : *blocks_prepared_) {
  74  E :      TypedBlock<HotPatchingBlockMetadata> hp_block_metadata;
  75    :      hp_block_metadata.Init(sizeof(HotPatchingMetadataHeader) +
  76  E :          sizeof(HotPatchingBlockMetadata) * index, hp_metadata_block);
  77    :      hp_block_metadata.SetReference(BlockGraph::RELATIVE_REF,
  78    :                                     hp_block_metadata->relative_address,
  79    :                                     block,
  80    :                                     0,
  81  E :                                     0);
  82  E :      hp_block_metadata->code_size = CalculateCodeSize(block);
  83  E :      hp_block_metadata->block_size = block->data_size();
  84    :  
  85  E :      ++index;
  86  E :    }
  87  E :    DCHECK_EQ(index, blocks_prepared_->size());
  88    :  
  89    :    // Create a section for hot patching metadata and put the block inside.
  90    :    BlockGraph::Section* hp_section =
  91    :        block_graph->AddSection(common::kHotPatchingMetadataSectionName,
  92  E :                                kReadOnlyDataCharacteristics);
  93  E :    DCHECK_NE(static_cast<BlockGraph::Section*>(nullptr), hp_section);
  94  E :    hp_metadata_block->set_section(hp_section->id());
  95  E :  }
  96    :  
  97    :  size_t AddHotPatchingMetadataTransform::CalculateCodeSize(
  98  E :      const BlockGraph::Block* block) {
  99    :    // If we will not encounter a data label, we assume that the whole block
 100    :    // contains code.
 101  E :    size_t code_size = block->data_size();
 102    :  
 103    :    // Iterate over labels to find a data label. We iterate backwards as data
 104    :    // labels are at the end and there are far less data labels than code labels.
 105  E :    for (auto it = block->labels().rbegin(); it != block->labels().rend(); ++it) {
 106  E :      const BlockGraph::Label& label = it->second;
 107    :  
 108    :      // We ignore the debug-end label, as it can come after block data.
 109  E :      if (label.has_attributes(BlockGraph::DEBUG_END_LABEL))
 110  E :        continue;
 111    :  
 112    :      // Anything that is not a data label means that there are no more data
 113    :      // labels.
 114  E :      if (!label.has_attributes(BlockGraph::DATA_LABEL))
 115  E :        break;
 116    :  
 117    :      // Update the code size with the information from the current data label.
 118    :      // Offsets are represented by signed integers, so we need a conversion.
 119  E :      DCHECK_GE(it->first, 0);
 120  E :      code_size = static_cast<size_t>(it->first);
 121    :  
 122    :      // Check if the label really points inside the block.
 123  E :      DCHECK_LE(code_size, block->data_size());
 124  E :    }
 125    :  
 126  E :    return code_size;
 127  E :  }
 128    :  
 129    :  }  // namespace transforms
 130    :  }  // namespace pe

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