Coverage for /Syzygy/instrument/instrumenters/archive_instrumenter.cc

CoverageLines executed / instrumented / missingexe / inst / missLanguageGroup
77.4%65840.C++source

Line-by-line coverage:

   1    :  // Copyright 2014 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    :  // Instrumentation adapter that adds archive support to any existing
  16    :  // instrumenter. Takes care of instantiating a new instance of the
  17    :  // underlying instrumenter for each file in the archive. When not processing
  18    :  // an archive simply passes through the original instrumenter.
  19    :  
  20    :  #include "syzygy/instrument/instrumenters/archive_instrumenter.h"
  21    :  
  22    :  #include "base/bind.h"
  23    :  #include "base/files/file_util.h"
  24    :  #include "syzygy/ar/ar_transform.h"
  25    :  #include "syzygy/core/file_util.h"
  26    :  
  27    :  namespace instrument {
  28    :  namespace instrumenters {
  29    :  
  30    :  namespace {
  31    :  
  32    :  const char kInputImage[] = "input-image";
  33    :  const char kOutputImage[] = "output-image";
  34    :  
  35    :  }  // namespace
  36    :  
  37    :  ArchiveInstrumenter::ArchiveInstrumenter()
  38    :      : factory_(NULL), overwrite_(false) {
  39    :  }
  40    :  
  41    :  ArchiveInstrumenter::ArchiveInstrumenter(InstrumenterFactoryFunction factory)
  42  E :      : factory_(factory), overwrite_(false) {
  43  E :    DCHECK_NE(reinterpret_cast<InstrumenterFactoryFunction>(NULL), factory);
  44  E :  }
  45    :  
  46    :  bool ArchiveInstrumenter::ParseCommandLine(
  47  E :      const base::CommandLine* command_line) {
  48  E :    DCHECK_NE(reinterpret_cast<base::CommandLine*>(NULL), command_line);
  49    :  
  50    :    // Create a copy of the command-line.
  51  E :    command_line_.reset(new base::CommandLine(*command_line));
  52    :  
  53    :    // Parse the few parameters that we care about.
  54  E :    input_image_ = command_line_->GetSwitchValuePath(kInputImage);
  55  E :    output_image_ = command_line_->GetSwitchValuePath(kOutputImage);
  56  E :    overwrite_ = command_line_->HasSwitch("overwrite");
  57    :  
  58  E :    return true;
  59  E :  }
  60    :  
  61  E :  bool ArchiveInstrumenter::Instrument() {
  62  E :    DCHECK_NE(reinterpret_cast<InstrumenterFactoryFunction>(NULL), factory_);
  63    :  
  64  E :    if (ProcessingArchive()) {
  65  E :      if (!InstrumentArchive())
  66  i :        return false;
  67  E :    } else {
  68  E :      if (!InstrumentPassthrough())
  69  i :        return false;
  70    :    }
  71    :  
  72  E :    return true;
  73  E :  }
  74    :  
  75  E :  bool ArchiveInstrumenter::ProcessingArchive() const {
  76  E :    if (input_image_.empty() || output_image_.empty())
  77  i :      return false;
  78    :  
  79  E :    if (!base::PathExists(input_image_))
  80  i :      return false;
  81    :  
  82  E :    core::FileType file_type = core::kUnknownFileType;
  83  E :    if (!core::GuessFileType(input_image_, &file_type))
  84  i :      return false;
  85    :  
  86  E :    if (file_type == core::kArchiveFileType)
  87  E :      return true;
  88    :  
  89  E :    return false;
  90  E :  }
  91    :  
  92  E :  bool ArchiveInstrumenter::InstrumentPassthrough() {
  93  E :    DCHECK_NE(reinterpret_cast<InstrumenterFactoryFunction>(NULL), factory_);
  94    :  
  95  E :    scoped_ptr<InstrumenterInterface> instrumenter(factory_());
  96    :    DCHECK_NE(reinterpret_cast<InstrumenterInterface*>(NULL),
  97  E :              instrumenter.get());
  98    :  
  99  E :    if (!instrumenter->ParseCommandLine(command_line_.get()))
 100  i :      return false;
 101    :  
 102  E :    if (!instrumenter->Instrument())
 103  i :      return false;
 104    :  
 105  E :    return true;
 106  E :  }
 107    :  
 108  E :  bool ArchiveInstrumenter::InstrumentArchive() {
 109    :    // Ensure we're not accidentally going to be overwriting the output.
 110  E :    if (!overwrite_ && base::PathExists(output_image_)) {
 111  i :      LOG(ERROR) << "Output path exists. Did you want to specify --overwrite?";
 112  i :      return false;
 113    :    }
 114    :  
 115  E :    LOG(INFO) << "Instrumenting archive: " << input_image_.value();
 116    :  
 117    :    // Configure and run an archive transform.
 118    :    ar::OnDiskArTransformAdapter::TransformFileOnDiskCallback callback =
 119  E :        base::Bind(&ArchiveInstrumenter::InstrumentFile, base::Unretained(this));
 120  E :    ar::OnDiskArTransformAdapter on_disk_adapter(callback);
 121  E :    ar::ArTransform ar_transform;
 122  E :    ar_transform.set_callback(on_disk_adapter.outer_callback());
 123  E :    ar_transform.set_input_archive(input_image_);
 124  E :    ar_transform.set_output_archive(output_image_);
 125  E :    if (!ar_transform.Transform())
 126  i :      return false;
 127    :  
 128  E :    return true;
 129  E :  }
 130    :  
 131    :  bool ArchiveInstrumenter::InstrumentFile(const base::FilePath& input_path,
 132    :                                           const base::FilePath& output_path,
 133    :                                           ar::ParsedArFileHeader* header,
 134  E :                                           bool* remove) {
 135  E :    DCHECK_NE(reinterpret_cast<InstrumenterFactoryFunction>(NULL), factory_);
 136  E :    DCHECK_NE(reinterpret_cast<ar::ParsedArFileHeader*>(NULL), header);
 137  E :    DCHECK_NE(reinterpret_cast<bool*>(NULL), remove);
 138    :  
 139    :    // We don't want to delete the file from the archive.
 140  E :    *remove = false;
 141    :  
 142    :    // Filter anything that isn't a known and recognized COFF file.
 143  E :    core::FileType file_type = core::kUnknownFileType;
 144  E :    if (!core::GuessFileType(input_path, &file_type)) {
 145  i :      LOG(ERROR) << "Unable to determine file type.";
 146  i :      return false;
 147    :    }
 148  E :    if (file_type != core::kCoffFileType) {
 149  i :      LOG(INFO) << "Not processing non-object file.";
 150  i :      if (!base::CopyFile(input_path, output_path)) {
 151  i :        LOG(ERROR) << "Unable to write output file: " << output_path.value();
 152  i :        return false;
 153    :      }
 154  i :      return true;
 155    :    }
 156    :  
 157    :    // Create the command-line for the child instrumenter.
 158  E :    base::CommandLine command_line(*command_line_.get());
 159  E :    command_line.AppendSwitchPath(kInputImage, input_path);
 160  E :    command_line.AppendSwitchPath(kOutputImage, output_path);
 161    :  
 162    :    // Create, initialize and run an instrumenter.
 163  E :    scoped_ptr<InstrumenterInterface> instrumenter(factory_());
 164    :    DCHECK_NE(reinterpret_cast<InstrumenterInterface*>(NULL),
 165  E :              instrumenter.get());
 166  E :    if (!instrumenter->ParseCommandLine(&command_line))
 167  i :      return false;
 168  E :    if (!instrumenter->Instrument())
 169  i :      return false;
 170    :  
 171  E :    return true;
 172  E :  }
 173    :  
 174    :  }  // namespace instrumenters
 175    :  }  // namespace instrument

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