Coverage for /Syzygy/pe/pe_relinker.cc

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

Coverage information generated Wed Dec 11 11:34:16 2013.