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

CoverageLines executed / instrumented / missingexe / inst / missLanguageGroup
91.9%79860.C++source

Line-by-line coverage:

   1    :  // Copyright 2013 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/instrument/instrumenters/asan_instrumenter.h"
  16    :  
  17    :  #include <algorithm>
  18    :  
  19    :  #include "base/logging.h"
  20    :  #include "base/files/file_util.h"
  21    :  #include "syzygy/application/application.h"
  22    :  #include "syzygy/instrument/transforms/allocation_filter_transform.h"
  23    :  
  24    :  namespace {
  25    :    using instrument::transforms::AllocationFilterTransform;
  26    :  }
  27    :  
  28    :  namespace instrument {
  29    :  namespace instrumenters {
  30    :  
  31    :  AsanInstrumenter::AsanInstrumenter()
  32    :      : use_interceptors_(true),
  33    :        remove_redundant_checks_(true),
  34    :        use_liveness_analysis_(true),
  35    :        instrumentation_rate_(1.0),
  36    :        asan_rtl_options_(false),
  37  E :        hot_patching_(false) {
  38  E :  }
  39    :  
  40  E :  bool AsanInstrumenter::ImageFormatIsSupported(ImageFormat image_format) {
  41    :    if (image_format == BlockGraph::PE_IMAGE ||
  42  E :        image_format == BlockGraph::COFF_IMAGE) {
  43  E :      return true;
  44    :    }
  45  i :    return false;
  46  E :  }
  47    :  
  48  E :  bool AsanInstrumenter::InstrumentPrepare() {
  49  E :    return true;
  50  E :  }
  51    :  
  52  E :  bool AsanInstrumenter::InstrumentImpl() {
  53    :    // Parse the filter if one was provided.
  54  E :    scoped_ptr<pe::ImageFilter> filter;
  55  E :    if (!filter_path_.empty()) {
  56  E :      filter.reset(new pe::ImageFilter());
  57  E :      if (!filter->LoadFromJSON(filter_path_)) {
  58  i :        LOG(ERROR) << "Failed to parse filter file: " << filter_path_.value();
  59  i :        return false;
  60    :      }
  61    :  
  62    :      // Ensure it is for the input module.
  63  E :      if (!filter->IsForModule(input_image_path_)) {
  64  E :        LOG(ERROR) << "Filter does not match the input module.";
  65  E :        return false;
  66    :      }
  67    :    }
  68    :  
  69  E :    asan_transform_.reset(new instrument::transforms::AsanTransform());
  70  E :    asan_transform_->set_instrument_dll_name(agent_dll_);
  71  E :    asan_transform_->set_use_interceptors(use_interceptors_);
  72  E :    asan_transform_->set_use_liveness_analysis(use_liveness_analysis_);
  73  E :    asan_transform_->set_remove_redundant_checks(remove_redundant_checks_);
  74  E :    asan_transform_->set_instrumentation_rate(instrumentation_rate_);
  75  E :    asan_transform_->set_hot_patching(hot_patching_);
  76    :  
  77    :    // Set up the filter if one was provided.
  78  E :    if (filter.get()) {
  79  E :      filter_.reset(filter.release());
  80  E :      asan_transform_->set_filter(&filter_->filter);
  81    :    }
  82    :  
  83    :    // Set overwrite source range flag in the Asan transform. The Asan
  84    :    // transformation will overwrite the source range of created instructions to
  85    :    // the source range of corresponding instrumented instructions.
  86  E :    asan_transform_->set_debug_friendly(debug_friendly_);
  87    :  
  88    :    // If RTL options were provided then pass them to the transform.
  89  E :    if (asan_rtl_options_)
  90  E :      asan_transform_->set_asan_parameters(&asan_params_);
  91    :  
  92  E :    if (!relinker_->AppendTransform(asan_transform_.get()))
  93  i :      return false;
  94    :  
  95    :    // Append the AllocationFilter transform if necessary.
  96  E :    if (af_transform_.get() != nullptr) {
  97  i :      if (!relinker_->AppendTransform(af_transform_.get()))
  98  i :        return false;
  99    :    }
 100    :  
 101  E :    return true;
 102  E :  }
 103    :  
 104    :  bool AsanInstrumenter::DoCommandLineParse(
 105  E :      const base::CommandLine* command_line) {
 106  E :    if (!Super::DoCommandLineParse(command_line))
 107  i :      return false;
 108    :  
 109    :    // Parse the additional command line arguments.
 110  E :    filter_path_ = command_line->GetSwitchValuePath("filter");
 111  E :    use_liveness_analysis_ = !command_line->HasSwitch("no-liveness-analysis");
 112  E :    remove_redundant_checks_ = !command_line->HasSwitch("no-redundancy-analysis");
 113  E :    use_interceptors_ = !command_line->HasSwitch("no-interceptors");
 114  E :    hot_patching_ = command_line->HasSwitch("hot-patching");
 115    :  
 116    :    // Parse the instrumentation rate if one has been provided.
 117    :    static const char kInstrumentationRate[] = "instrumentation-rate";
 118  E :    if (command_line->HasSwitch(kInstrumentationRate)) {
 119  E :      std::string s = command_line->GetSwitchValueASCII(kInstrumentationRate);
 120  E :      double d = 0;
 121  E :      if (!base::StringToDouble(s, &d)) {
 122  E :        LOG(ERROR) << "Failed to parse floating point value: " << s;
 123  E :        return false;
 124    :      }
 125    :      // Cap the rate to the range of valid values [0, 1].
 126  E :      instrumentation_rate_ = std::max(0.0, std::min(1.0, d));
 127  E :    }
 128    :  
 129    :    // Parse Asan RTL options if present.
 130    :    static const char kAsanRtlOptions[] = "asan-rtl-options";
 131  E :    asan_rtl_options_ = command_line->HasSwitch(kAsanRtlOptions);
 132  E :    if (asan_rtl_options_) {
 133  E :      std::wstring options = command_line->GetSwitchValueNative(kAsanRtlOptions);
 134    :      // The Asan RTL options string might be encapsulated in quotes, remove them
 135    :      // if it's the case.
 136  E :      if (!options.empty() && options[0] == L'\"') {
 137  E :        CHECK_EQ(L'\"', options.back()) << "If the asan-rtl-options string "
 138    :            << "starts with a quote it should also end with one.";
 139  E :        options.erase(options.begin());
 140  E :        if (!options.empty())
 141  E :          options.pop_back();
 142    :      }
 143  E :      common::SetDefaultAsanParameters(&asan_params_);
 144  E :      if (!common::ParseAsanParameters(options, &asan_params_))
 145  E :        return false;
 146  E :    }
 147    :  
 148    :    // Parse the allocation-filter flag.
 149    :    static const char kAsanAllocationFilter[] = "allocation-filter-config-file";
 150    :    allocation_filter_config_file_path_ = command_line->GetSwitchValuePath(
 151  E :        kAsanAllocationFilter);
 152    :  
 153    :    // Setup the AllocationFilter transform if a configuration file was specified.
 154  E :    if (!allocation_filter_config_file_path_.empty()) {
 155  E :      std::string json_string;
 156  E :      AllocationFilterTransform::FunctionNameOffsetMap target_calls;
 157    :      if (!AllocationFilterTransform::ReadFromJSON(
 158  E :        allocation_filter_config_file_path_, &target_calls)) {
 159  E :        LOG(ERROR) << "Failed to parse allocation-filter configuration file: "
 160    :                   << allocation_filter_config_file_path_.value();
 161  E :        return false;
 162    :      }
 163    :  
 164  E :      if (!target_calls.empty()) {
 165    :        // Setup the allocation-filter transform.
 166  E :        af_transform_.reset(new AllocationFilterTransform(target_calls));
 167    :  
 168    :        // Set overwrite source range flag in the AllocationFilter transform.
 169    :        // It will overwrite the source range of created instructions to the
 170    :        // source range of corresponding instrumented instructions. The
 171    :        // AllocationFilter transform shares the Asan flag.
 172  E :        af_transform_->set_debug_friendly(debug_friendly_);
 173    :      }
 174  E :    }
 175    :  
 176    :    // Set default agent dll name if none provided. This has to be done here
 177    :    // because ParseCommandLine expects agent_dll_ to be filled.
 178  E :    if (agent_dll_.empty()) {
 179  E :      if (!hot_patching_) {
 180  E :        agent_dll_ = instrument::transforms::AsanTransform::kSyzyAsanDll;
 181  E :      } else {
 182  E :        agent_dll_ = instrument::transforms::AsanTransform::kSyzyAsanHpDll;
 183    :      }
 184    :    }
 185    :  
 186  E :    return true;
 187  E :  }
 188    :  
 189    :  }  // namespace instrumenters
 190    :  }  // namespace instrument

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