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

CoverageLines executed / instrumented / missingexe / inst / missLanguageGroup
71.4%65910.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/basic_block_entry_count_grinder.h"
  16    :  
  17    :  #include <limits>
  18    :  
  19    :  #include "base/files/file_path.h"
  20    :  #include "base/json/json_reader.h"
  21    :  #include "syzygy/common/indexed_frequency_data.h"
  22    :  #include "syzygy/common/syzygy_version.h"
  23    :  #include "syzygy/core/json_file_writer.h"
  24    :  #include "syzygy/pdb/pdb_reader.h"
  25    :  #include "syzygy/pdb/pdb_util.h"
  26    :  #include "syzygy/pe/find.h"
  27    :  #include "syzygy/pe/metadata.h"
  28    :  #include "syzygy/pe/pe_file.h"
  29    :  
  30    :  namespace grinder {
  31    :  namespace grinders {
  32    :  
  33    :  BasicBlockEntryCountGrinder::BasicBlockEntryCountGrinder()
  34    :      : parser_(NULL),
  35  E :        event_handler_errored_(false) {
  36  E :  }
  37    :  
  38    :  bool BasicBlockEntryCountGrinder::ParseCommandLine(
  39  E :      const CommandLine* command_line) {
  40  E :    serializer_.set_pretty_print(command_line->HasSwitch("pretty-print"));
  41  E :    return true;
  42  E :  }
  43    :  
  44  E :  void BasicBlockEntryCountGrinder::SetParser(Parser* parser) {
  45  E :    DCHECK(parser != NULL);
  46  E :    parser_ = parser;
  47  E :  }
  48    :  
  49  E :  bool BasicBlockEntryCountGrinder::Grind() {
  50  E :    if (entry_count_map_.empty()) {
  51  E :      LOG(ERROR) << "No basic-block frequency data was encountered.";
  52  E :      return false;
  53    :    }
  54    :  
  55  E :    return true;
  56  E :  }
  57    :  
  58  E :  bool BasicBlockEntryCountGrinder::OutputData(FILE* file) {
  59  E :    DCHECK(file != NULL);
  60    :  
  61  E :    if (!serializer_.SaveAsJson(entry_count_map_, file))
  62  i :      return false;
  63    :  
  64  E :    return true;
  65  E :  }
  66    :  
  67    :  void BasicBlockEntryCountGrinder::OnIndexedFrequency(
  68    :      base::Time time,
  69    :      DWORD process_id,
  70    :      DWORD thread_id,
  71  E :      const TraceIndexedFrequencyData* data) {
  72  E :    DCHECK(data != NULL);
  73  E :    DCHECK(parser_ != NULL);
  74    :  
  75    :    if (data->data_type != common::IndexedFrequencyData::BASIC_BLOCK_ENTRY &&
  76  E :        data->data_type != common::IndexedFrequencyData::COVERAGE )
  77  i :      return;
  78    :  
  79  E :    if (data->num_entries == 0) {
  80  i :      LOG(INFO) << "Skipping empty basic block frequency data.";
  81  i :      return;
  82    :    }
  83    :  
  84  E :    if (!basic_block_util::IsValidFrequencySize(data->frequency_size)) {
  85  i :       LOG(ERROR) << "Basic block frequency data has invalid frequency_size ("
  86    :                  << data->frequency_size << ").";
  87  i :       event_handler_errored_ = true;
  88  i :       return;
  89    :    }
  90    :  
  91    :    using trace::parser::AbsoluteAddress64;
  92    :  
  93    :    // Get the module information for which this BB frequency data belongs.
  94    :    const ModuleInformation* module_info = parser_->GetModuleInformation(
  95  E :        process_id, AbsoluteAddress64(data->module_base_addr));
  96  E :    if (module_info == NULL) {
  97  i :      LOG(ERROR) << "Failed to find module information.";
  98  i :      event_handler_errored_ = true;
  99  i :      return;
 100    :    }
 101    :  
 102    :    const InstrumentedModuleInformation* instrumented_module =
 103  E :        FindOrCreateInstrumentedModule(module_info);
 104  E :    if (instrumented_module == NULL) {
 105  i :      LOG(ERROR) << "Failed to find instrumented module "
 106    :                 << module_info->image_file_name;
 107  i :      event_handler_errored_ = true;
 108  i :      return;
 109    :    }
 110    :  
 111  E :    if (data->num_entries != instrumented_module->block_ranges.size()) {
 112  i :      LOG(ERROR) << "Unexpected data size for instrumented module "
 113    :                 << module_info->image_file_name;
 114  i :      event_handler_errored_ = true;
 115  i :      return;
 116    :    }
 117    :  
 118  E :    UpdateBasicBlockEntryCount(*instrumented_module, data);
 119  E :  }
 120    :  
 121    :  void BasicBlockEntryCountGrinder::UpdateBasicBlockEntryCount(
 122    :      const InstrumentedModuleInformation& instrumented_module,
 123  E :      const TraceIndexedFrequencyData* data) {
 124    :    using basic_block_util::BasicBlockOffset;
 125    :    using basic_block_util::EntryCountType;
 126    :    using basic_block_util::EntryCountMap;
 127    :    using basic_block_util::GetFrequency;
 128    :  
 129  E :    DCHECK(data != NULL);
 130  E :    DCHECK_NE(0U, data->num_entries);
 131    :  
 132    :    DCHECK(data->data_type == common::IndexedFrequencyData::BASIC_BLOCK_ENTRY ||
 133  E :           data->data_type == common::IndexedFrequencyData::COVERAGE);
 134    :  
 135    :    EntryCountMap& bb_entries =
 136  E :        entry_count_map_[instrumented_module.original_module];
 137    :  
 138    :    // Run over the BB frequency data and increment bb_entries for each basic
 139    :    // block using saturation arithmetic.
 140    :  
 141  E :    for (size_t bb_id = 0; bb_id < data->num_entries; ++bb_id) {
 142  E :      EntryCountType amount = GetFrequency(data, bb_id);
 143  E :      if (amount != 0) {
 144    :        BasicBlockOffset offs =
 145  E :            instrumented_module.block_ranges[bb_id].start().value();
 146    :  
 147  E :        EntryCountType& value = bb_entries[offs];
 148  E :        if (amount < 0) {
 149    :          // We need to detect uint32 to int32 overflow because JSON file output
 150    :          // int32 and basic block agent use an uint32 counter.
 151  i :          value = std::numeric_limits<EntryCountType>::max();
 152  i :        } else {
 153    :          value += std::min(
 154  E :              amount, std::numeric_limits<EntryCountType>::max() - value);
 155    :        }
 156    :      }
 157  E :    }
 158  E :  }
 159    :  
 160    :  const BasicBlockEntryCountGrinder::InstrumentedModuleInformation*
 161    :  BasicBlockEntryCountGrinder::FindOrCreateInstrumentedModule(
 162  E :      const ModuleInformation* module_info) {
 163    :    // See if we already encountered this instrumented module.
 164  E :    InstrumentedModuleMap::iterator it(instrumented_modules_.find(*module_info));
 165  E :    if (it != instrumented_modules_.end())
 166  i :      return &it->second;
 167    :  
 168    :    // Get the original file's metadata.
 169  E :    base::FilePath module_path(module_info->image_file_name);
 170  E :    pe::PEFile instrumented_module;
 171  E :    if (!instrumented_module.Init(module_path)) {
 172  i :      LOG(ERROR) << "Unable to locate instrumented module: "
 173    :                 << module_path.value();
 174  i :      return NULL;
 175    :    }
 176    :  
 177  E :    pe::Metadata metadata;
 178  E :    if (!metadata.LoadFromPE(instrumented_module)) {
 179  i :      LOG(ERROR) << "Unable to load metadata from module: "
 180    :                 << module_path.value();
 181  i :      return NULL;
 182    :    }
 183    :  
 184    :    // Find the PDB file for the module.
 185  E :    base::FilePath pdb_path;
 186  E :    if (!pe::FindPdbForModule(module_path, &pdb_path) || pdb_path.empty()) {
 187  i :      LOG(ERROR) << "Failed to find PDB for module: " << module_path.value();
 188  i :      return NULL;
 189    :    }
 190    :  
 191  E :    RelativeAddressRangeVector block_ranges;
 192    :    // This logs verbosely for us.
 193  E :    if (!basic_block_util::LoadBasicBlockRanges(pdb_path, &block_ranges)) {
 194  i :      return NULL;
 195    :    }
 196    :  
 197    :    // We've located all the information we need, create and
 198    :    // initialize the record.
 199  E :    InstrumentedModuleInformation& info = instrumented_modules_[*module_info];
 200    :    basic_block_util::InitModuleInfo(metadata.module_signature(),
 201  E :                                     &info.original_module);
 202    :  
 203  E :    info.block_ranges.swap(block_ranges);
 204    :  
 205  E :    return &info;
 206  E :  }
 207    :  
 208    :  }  // namespace grinders
 209    :  }  // namespace grinder

Coverage information generated Thu Jul 04 09:34:53 2013.