Coverage for /Syzygy/grinder/grinders/coverage_grinder.cc

CoverageLines executed / instrumented / missingexe / inst / missLanguageGroup
73.9%65880.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/grinder/grinders/coverage_grinder.h"
  16    :  
  17    :  #include "base/files/file_path.h"
  18    :  #include "base/strings/string_util.h"
  19    :  #include "syzygy/common/indexed_frequency_data.h"
  20    :  #include "syzygy/grinder/cache_grind_writer.h"
  21    :  #include "syzygy/grinder/lcov_writer.h"
  22    :  #include "syzygy/pdb/pdb_reader.h"
  23    :  #include "syzygy/pdb/pdb_util.h"
  24    :  #include "syzygy/pe/find.h"
  25    :  
  26    :  namespace grinder {
  27    :  namespace grinders {
  28    :  
  29    :  namespace {
  30    :  
  31    :  using basic_block_util::ModuleInformation;
  32    :  using basic_block_util::RelativeAddressRange;
  33    :  using basic_block_util::GetFrequency;
  34    :  using basic_block_util::LoadPdbInfo;
  35    :  using basic_block_util::IsValidFrequencySize;
  36    :  using basic_block_util::PdbInfo;
  37    :  using basic_block_util::PdbInfoMap;
  38    :  using trace::parser::AbsoluteAddress64;
  39    :  
  40    :  }  // namespace
  41    :  
  42    :  CoverageGrinder::CoverageGrinder()
  43    :      : parser_(NULL),
  44    :        event_handler_errored_(false),
  45  E :        output_format_(kLcovFormat) {
  46  E :  }
  47    :  
  48  E :  CoverageGrinder::~CoverageGrinder() {
  49  E :  }
  50    :  
  51  E :  bool CoverageGrinder::ParseCommandLine(const base::CommandLine* command_line) {
  52  E :    DCHECK(command_line != NULL);
  53    :  
  54    :    // If the switch isn't present we have nothing to do!
  55  E :    const char kOutputFormat[] = "output-format";
  56  E :    if (!command_line->HasSwitch(kOutputFormat))
  57  E :      return true;
  58    :  
  59  E :    std::string format = command_line->GetSwitchValueASCII(kOutputFormat);
  60  E :    if (base::LowerCaseEqualsASCII(format, "lcov")) {
  61  E :      output_format_ = kLcovFormat;
  62  E :    } else if (base::LowerCaseEqualsASCII(format, "cachegrind")) {
  63  E :      output_format_ = kCacheGrindFormat;
  64  E :    } else {
  65  E :      LOG(ERROR) << "Unknown output format: " << format << ".";
  66  E :      return false;
  67    :    }
  68  E :    return true;
  69  E :  }
  70    :  
  71  E :  void CoverageGrinder::SetParser(Parser* parser) {
  72  E :    DCHECK(parser != NULL);
  73  E :    parser_ = parser;
  74  E :  }
  75    :  
  76  E :  bool CoverageGrinder::Grind() {
  77  E :    if (event_handler_errored_) {
  78  i :      LOG(WARNING) << "Failed to handle all basic block frequency data events, "
  79    :                   << "coverage results will be partial.";
  80    :    }
  81    :  
  82  E :    if (pdb_info_cache_.empty()) {
  83  E :      LOG(ERROR) << "No coverage data was encountered.";
  84  E :      return false;
  85    :    }
  86    :  
  87  E :    PdbInfoMap::const_iterator it = pdb_info_cache_.begin();
  88  E :    for (; it != pdb_info_cache_.end(); ++it) {
  89  E :      if (!coverage_data_.Add(it->second.line_info)) {
  90  i :        LOG(ERROR) << "Failed to aggregate line information from PDB: "
  91    :                   << it->first.path;
  92  i :        return false;
  93    :      }
  94  E :    }
  95  E :    DCHECK(!coverage_data_.source_file_coverage_data_map().empty());
  96    :  
  97  E :    return true;
  98  E :  }
  99    :  
 100  E :  bool CoverageGrinder::OutputData(FILE* file) {
 101  E :    DCHECK(file != NULL);
 102  E :    DCHECK(!coverage_data_.source_file_coverage_data_map().empty());
 103    :  
 104    :    // These functions log verbosely for us.
 105  E :    switch (output_format_) {
 106    :      case kLcovFormat: {
 107  E :        if (!WriteLcovCoverageFile(coverage_data_, file))
 108  i :          return false;
 109  E :        break;
 110    :      }
 111    :  
 112    :      case kCacheGrindFormat: {
 113  E :        if (!WriteCacheGrindCoverageFile(coverage_data_, file))
 114  i :          return false;
 115  E :        break;
 116    :      }
 117    :  
 118  i :      default: NOTREACHED() << "Unknown OutputFormat.";
 119    :    }
 120    :  
 121  E :    return true;
 122  E :  }
 123    :  
 124    :  void CoverageGrinder::OnIndexedFrequency(
 125    :      base::Time time,
 126    :      DWORD process_id,
 127    :      DWORD thread_id,
 128  E :      const TraceIndexedFrequencyData* data) {
 129  E :    DCHECK(data != NULL);
 130  E :    DCHECK(parser_ != NULL);
 131    :  
 132    :    if (data->data_type != common::IndexedFrequencyData::COVERAGE &&
 133  E :        data->data_type != common::IndexedFrequencyData::BASIC_BLOCK_ENTRY) {
 134  i :      return;
 135    :    }
 136    :  
 137  E :    if (data->num_entries == 0) {
 138  i :      LOG(INFO) << "Skipping empty basic block frequency data.";
 139  i :      return;
 140    :    }
 141    :  
 142  E :    if (!IsValidFrequencySize(data->frequency_size)) {
 143  i :      LOG(ERROR) << "Basic block frequency data has invalid frequency_size ("
 144    :                 << data->frequency_size << ").";
 145  i :      event_handler_errored_ = true;
 146  i :      return;
 147    :    }
 148    :  
 149    :    // Get the module information for which this BB frequency data belongs.
 150    :    const ModuleInformation* module_info = parser_->GetModuleInformation(
 151  E :        process_id, AbsoluteAddress64(data->module_base_addr));
 152  E :    if (module_info == NULL) {
 153  i :      LOG(ERROR) << "Failed to find module information for basic block frequency"
 154    :                 << " data.";
 155  i :      event_handler_errored_ = true;
 156  i :      return;
 157    :    }
 158    :  
 159    :    // TODO(chrisha): Validate that the PE file itself is instrumented as
 160    :    //     expected? This isn't strictly necessary but would add another level of
 161    :    //     safety checking.
 162    :  
 163    :    // Get the PDB info. This loads the line information and the basic-block
 164    :    // ranges if not already done, otherwise it returns the cached version.
 165  E :    PdbInfo* pdb_info = NULL;
 166  E :    if (!LoadPdbInfo(&pdb_info_cache_, *module_info, &pdb_info)) {
 167  i :      event_handler_errored_ = true;
 168  i :      return;
 169    :    }
 170    :  
 171  E :    DCHECK(pdb_info != NULL);
 172    :  
 173    :    // Sanity check the contents.
 174  E :    if (data->num_entries != pdb_info->bb_ranges.size()) {
 175  i :      LOG(ERROR) << "Mismatch between trace data BB count and PDB BB count.";
 176  i :      event_handler_errored_ = true;
 177  i :      return;
 178    :    }
 179    :  
 180    :    // Run over the BB frequency data and mark non-zero frequency BBs as having
 181    :    // been visited.
 182  E :    for (size_t bb_index = 0; bb_index < data->num_entries; ++bb_index) {
 183  E :      uint32 bb_freq = GetFrequency(data, bb_index, 0);
 184    :  
 185  E :      if (bb_freq == 0)
 186  E :        continue;
 187    :  
 188    :      // Mark this basic-block as visited.
 189  E :      const RelativeAddressRange& bb_range = pdb_info->bb_ranges[bb_index];
 190    :      if (!pdb_info->line_info.Visit(bb_range.start(),
 191    :                                     bb_range.size(),
 192  E :                                     bb_freq)) {
 193  i :        LOG(ERROR) << "Failed to visit BB at " << bb_range << ".";
 194  i :        event_handler_errored_ = true;
 195  i :        return;
 196    :      }
 197  E :    }
 198  E :  }
 199    :  
 200    :  }  // namespace grinders
 201    :  }  // namespace grinder

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