Coverage for /Syzygy/grinder/basic_block_entry_count_grinder.cc

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

Coverage information generated Thu Mar 14 11:53:36 2013.