Coverage for /Syzygy/pe/pe_relinker.cc

CoverageLines executed / instrumented / missingexe / inst / missLanguageGroup
75.5%74980.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/pe/pe_relinker.h"
  16    :  
  17    :  #include "base/files/file_util.h"
  18    :  #include "syzygy/pdb/pdb_byte_stream.h"
  19    :  #include "syzygy/pdb/pdb_file.h"
  20    :  #include "syzygy/pdb/pdb_reader.h"
  21    :  #include "syzygy/pdb/pdb_util.h"
  22    :  #include "syzygy/pdb/pdb_writer.h"
  23    :  #include "syzygy/pe/decomposer.h"
  24    :  #include "syzygy/pe/metadata.h"
  25    :  #include "syzygy/pe/pdb_info.h"
  26    :  #include "syzygy/pe/pe_file_writer.h"
  27    :  #include "syzygy/pe/pe_relinker_util.h"
  28    :  #include "syzygy/pe/serialization.h"
  29    :  
  30    :  namespace pe {
  31    :  
  32    :  namespace {
  33    :  
  34    :  typedef block_graph::BlockGraphTransformInterface Transform;
  35    :  typedef block_graph::BlockGraphOrdererInterface Orderer;
  36    :  
  37    :  using block_graph::ApplyBlockGraphTransform;
  38    :  using block_graph::BlockGraph;
  39    :  using block_graph::OrderedBlockGraph;
  40    :  using core::RelativeAddress;
  41    :  using pdb::NameStreamMap;
  42    :  using pdb::PdbByteStream;
  43    :  using pdb::PdbFile;
  44    :  using pdb::PdbInfoHeader70;
  45    :  using pdb::PdbMutatorInterface;
  46    :  using pdb::PdbStream;
  47    :  using pdb::WritablePdbStream;
  48    :  
  49    :  // Decomposes the module enclosed by the given PE file.
  50    :  bool Decompose(const PEFile& pe_file,
  51    :                 const base::FilePath& pdb_path,
  52    :                 ImageLayout* image_layout,
  53  E :                 BlockGraph::Block** dos_header_block) {
  54  E :    DCHECK(image_layout != NULL);
  55  E :    DCHECK(dos_header_block != NULL);
  56    :  
  57  E :    LOG(INFO) << "Decomposing module: " << pe_file.path().value();
  58    :  
  59  E :    BlockGraph* block_graph = image_layout->blocks.graph();
  60  E :    ImageLayout orig_image_layout(block_graph);
  61    :  
  62    :    // Decompose the input image.
  63  E :    Decomposer decomposer(pe_file);
  64  E :    decomposer.set_pdb_path(pdb_path);
  65  E :    if (!decomposer.Decompose(&orig_image_layout)) {
  66  i :      LOG(ERROR) << "Unable to decompose module: " << pe_file.path().value();
  67  i :      return false;
  68    :    }
  69    :  
  70    :    // Make a copy of the image layout without padding. We don't want to carry
  71    :    // the padding through the toolchain.
  72  E :    LOG(INFO) << "Removing padding blocks.";
  73  E :    if (!pe::CopyImageLayoutWithoutPadding(orig_image_layout, image_layout)) {
  74  i :      LOG(ERROR) << "Failed to remove padding blocks.";
  75  i :      return false;
  76    :    }
  77    :  
  78    :    // Get the DOS header block.
  79    :    *dos_header_block =
  80    :        image_layout->blocks.GetBlockByAddress(
  81  E :            BlockGraph::RelativeAddress(0));
  82  E :    if (*dos_header_block == NULL) {
  83  i :      LOG(ERROR) << "Unable to find the DOS header block.";
  84  i :      return false;
  85    :    }
  86    :  
  87  E :    return true;
  88  E :  }
  89    :  
  90    :  // Writes the image.
  91    :  bool WriteImage(const ImageLayout& image_layout,
  92  E :                  const base::FilePath& output_path) {
  93  E :    PEFileWriter writer(image_layout);
  94    :  
  95  E :    LOG(INFO) << "Writing image: " << output_path.value();
  96  E :    if (!writer.WriteImage(output_path)) {
  97  i :      LOG(ERROR) << "Failed to write image \"" << output_path.value() << "\".";
  98  i :      return false;
  99    :    }
 100    :  
 101  E :    return true;
 102  E :  }
 103    :  
 104    :  }  // namespace
 105    :  
 106    :  PERelinker::PERelinker(const PETransformPolicy* pe_transform_policy)
 107    :      : PECoffRelinker(pe_transform_policy),
 108    :        pe_transform_policy_(pe_transform_policy),
 109    :        add_metadata_(true), augment_pdb_(true),
 110    :        compress_pdb_(false), strip_strings_(false),
 111  E :        padding_(0), code_alignment_(1), output_guid_(GUID_NULL) {
 112  E :    DCHECK(pe_transform_policy != NULL);
 113  E :  }
 114    :  
 115  E :  bool PERelinker::AppendPdbMutator(PdbMutatorInterface* pdb_mutator) {
 116  E :    DCHECK(pdb_mutator != NULL);
 117  E :    pdb_mutators_.push_back(pdb_mutator);
 118  E :    return true;
 119  E :  }
 120    :  
 121    :  bool PERelinker::AppendPdbMutators(
 122  E :      const std::vector<PdbMutatorInterface*>& pdb_mutators) {
 123    :    pdb_mutators_.insert(pdb_mutators_.end(),
 124    :                         pdb_mutators.begin(),
 125  E :                         pdb_mutators.end());
 126  E :    return true;
 127  E :  }
 128    :  
 129  E :  bool PERelinker::Init() {
 130  E :    DCHECK(!inited_);
 131    :  
 132    :    // Initialize the paths.
 133    :    if (!ValidateAndInferPaths(input_path_, output_path_, allow_overwrite_,
 134  E :                               &input_pdb_path_, &output_pdb_path_)) {
 135  E :      return false;
 136    :    }
 137    :  
 138  E :    LOG(INFO) << "Input module : " << input_path_.value();
 139  E :    LOG(INFO) << "Input PDB    : " << input_pdb_path_.value();
 140  E :    LOG(INFO) << "Output module: " << output_path_.value();
 141  E :    LOG(INFO) << "Output PDB   : " << output_pdb_path_.value();
 142    :  
 143    :    // Open the input PE file.
 144  E :    if (!input_pe_file_.Init(input_path_)) {
 145  i :      LOG(ERROR) << "Unable to load \"" << input_path_.value() << "\".";
 146  i :      return false;
 147    :    }
 148    :  
 149    :    // Generate a GUID for the relinked image's PDB file.
 150  E :    if (FAILED(::CoCreateGuid(&output_guid_))) {
 151  i :      LOG(ERROR) << "Failed to create new PDB GUID.";
 152  i :      return false;
 153    :    }
 154    :  
 155    :    // Decompose the image.
 156    :    if (!Decompose(input_pe_file_, input_pdb_path_, &input_image_layout_,
 157  E :                   &headers_block_)) {
 158  i :      return false;
 159    :    }
 160    :  
 161  E :    inited_ = true;
 162    :  
 163  E :    return true;
 164  E :  }
 165    :  
 166  E :  bool PERelinker::Relink() {
 167  E :    if (!inited_) {
 168  i :      LOG(ERROR) << "Init has not been successfully called.";
 169  i :      return false;
 170    :    }
 171    :  
 172    :    // Apply the user supplied transforms.
 173  E :    if (!ApplyUserTransforms())
 174  E :      return false;
 175    :  
 176    :    // Finalize the block-graph. This applies PE and Syzygy specific transforms.
 177    :    if (!FinalizeBlockGraph(input_path_, output_pdb_path_, output_guid_,
 178    :                            add_metadata_, pe_transform_policy_, &block_graph_,
 179  E :                            headers_block_)) {
 180  i :      return false;
 181    :    }
 182    :  
 183    :    // Apply the user supplied orderers.
 184  E :    OrderedBlockGraph ordered_block_graph(&block_graph_);
 185  E :    if (!ApplyUserOrderers(&ordered_block_graph))
 186  E :      return false;
 187    :  
 188    :    // Finalize the ordered block graph. This applies PE specific orderers.
 189  E :    if (!FinalizeOrderedBlockGraph(&ordered_block_graph, headers_block_))
 190  i :      return false;
 191    :  
 192    :    // Lay it out.
 193  E :    ImageLayout output_image_layout(&block_graph_);
 194    :    if (!BuildImageLayout(padding_, code_alignment_,
 195    :                          ordered_block_graph, headers_block_,
 196  E :                          &output_image_layout)) {
 197  i :      return false;
 198    :    }
 199    :  
 200    :    // Write the image.
 201  E :    if (!WriteImage(output_image_layout, output_path_))
 202  i :      return false;
 203    :  
 204    :    // From here on down we are processing the PDB file.
 205    :  
 206    :    // Read the PDB file.
 207  E :    LOG(INFO) << "Reading PDB file: " << input_pdb_path_.value();
 208  E :    pdb::PdbReader pdb_reader;
 209  E :    PdbFile pdb_file;
 210  E :    if (!pdb_reader.Read(input_pdb_path_, &pdb_file)) {
 211  i :      LOG(ERROR) << "Unable to read PDB file: " << input_pdb_path_.value();
 212  i :      return false;
 213    :    }
 214    :  
 215    :    // Apply any user specified mutators to the PDB file.
 216  E :    if (!pdb::ApplyPdbMutators(pdb_mutators_, &pdb_file))
 217  E :      return false;
 218    :  
 219    :    // Finalize the PDB file.
 220  E :    RelativeAddressRange input_range;
 221  E :    GetOmapRange(input_image_layout_.sections, &input_range);
 222    :    if (!FinalizePdbFile(input_path_, output_path_, input_range,
 223    :                         output_image_layout, output_guid_, augment_pdb_,
 224  E :                         strip_strings_, compress_pdb_, &pdb_file)) {
 225  i :      return false;
 226    :    }
 227    :  
 228    :    // Write the PDB file.
 229  E :    LOG(INFO) << "Writing the PDB.";
 230  E :    pdb::PdbWriter pdb_writer;
 231  E :    if (!pdb_writer.Write(output_pdb_path_, pdb_file)) {
 232  i :      LOG(ERROR) << "Failed to write PDB file \"" << output_pdb_path_.value()
 233    :                 << "\".";
 234  i :      return false;
 235    :    }
 236    :  
 237  E :    LOG(INFO) << "PE relinker finished.";
 238    :  
 239  E :    return true;
 240  E :  }
 241    :  
 242    :  }  // namespace pe

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