Coverage for /Syzygy/refinery/analyzers/run_analyzer_main.cc

CoverageLines executed / instrumented / missingexe / inst / missLanguageGroup
0.0%00173.C++source

Line-by-line coverage:

   1    :  // Copyright 2016 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    :  // Runs a particular analyzer over a minidump or set of minidumps.
  16    :  #include <windows.h>  // NOLINT
  17    :  #include <dbghelp.h>
  18    :  
  19    :  #include <vector>
  20    :  
  21    :  #include "base/at_exit.h"
  22    :  #include "base/command_line.h"
  23    :  #include "base/macros.h"
  24    :  #include "base/files/file_path.h"
  25    :  #include "base/strings/string16.h"
  26    :  #include "base/strings/string_split.h"
  27    :  #include "base/strings/stringprintf.h"
  28    :  #include "syzygy/application/application.h"
  29    :  #include "syzygy/minidump/minidump.h"
  30    :  #include "syzygy/refinery/analyzers/analysis_runner.h"
  31    :  #include "syzygy/refinery/analyzers/heap_analyzer.h"
  32    :  #include "syzygy/refinery/analyzers/memory_analyzer.h"
  33    :  #include "syzygy/refinery/analyzers/module_analyzer.h"
  34    :  #include "syzygy/refinery/analyzers/stack_analyzer.h"
  35    :  #include "syzygy/refinery/process_state/process_state.h"
  36    :  #include "syzygy/refinery/symbols/dia_symbol_provider.h"
  37    :  #include "syzygy/refinery/symbols/symbol_provider.h"
  38    :  
  39  m :  namespace {
  40    :  
  41  m :  class RunAnalyzerApplication : public application::AppImplBase {
  42  m :   public:
  43  m :    RunAnalyzerApplication();
  44    :  
  45  m :    bool ParseCommandLine(const base::CommandLine* command_line);
  46  m :    int Run();
  47    :  
  48  m :   private:
  49  m :    void PrintUsage(const base::FilePath& program,
  50  m :                    const base::StringPiece& message);
  51  m :    bool AddAnalyzers(
  52  m :        scoped_refptr<refinery::SymbolProvider> symbol_provider,
  53  m :        scoped_refptr<refinery::DiaSymbolProvider> dia_symbol_provider,
  54  m :        refinery::AnalysisRunner* runner);
  55  m :    bool Analyze(const minidump::Minidump& minidump,
  56  m :                 scoped_refptr<refinery::SymbolProvider> symbol_provider,
  57  m :                 scoped_refptr<refinery::DiaSymbolProvider> dia_symbol_provider,
  58  m :                 refinery::ProcessState* process_state);
  59    :  
  60  m :    std::vector<base::FilePath> mindump_paths_;
  61  m :    std::vector<std::string> analyzer_names_;
  62    :  
  63  m :    DISALLOW_COPY_AND_ASSIGN(RunAnalyzerApplication);
  64  m :  };
  65    :  
  66  m :  const char kUsageFormatStr[] =
  67  m :      "Usage: %ls [options] <dump files or patterns>\n"
  68  m :      "\n"
  69  m :      "  --analyzers=<comma-seperated list of analyzer names>\n"
  70  m :      "     Configures the set of analyzers to run on each of the dump\n"
  71  m :      "     files.\n";
  72    :  
  73  m :  const char kDefaultAnalyzers[] = "MemoryAnalyzer,ModuleAnalyser,HeapAnalyzer";
  74    :  
  75  m :  void RunAnalyzerApplication::PrintUsage(const base::FilePath& program,
  76  m :                                          const base::StringPiece& message) {
  77  m :    if (!message.empty()) {
  78  m :      ::fwrite(message.data(), 1, message.length(), out());
  79  m :      ::fprintf(out(), "\n\n");
  80  m :    }
  81    :  
  82  m :    ::fprintf(out(), kUsageFormatStr, program.BaseName().value().c_str());
  83  m :  }
  84    :  
  85  m :  RunAnalyzerApplication::RunAnalyzerApplication()
  86  m :      : AppImplBase("RunAnalyzerApplication") {
  87  m :  }
  88    :  
  89  m :  bool RunAnalyzerApplication::ParseCommandLine(
  90  m :      const base::CommandLine* cmd_line) {
  91  m :    if (cmd_line->HasSwitch("help")) {
  92  m :      PrintUsage(cmd_line->GetProgram(), "");
  93  m :      return false;
  94  m :    }
  95    :  
  96  m :    std::string analyzers = cmd_line->GetSwitchValueASCII("analyzers");
  97  m :    if (analyzers.empty())
  98  m :      analyzers = kDefaultAnalyzers;
  99    :  
 100  m :    analyzer_names_ = base::SplitString(analyzers, ",", base::TRIM_WHITESPACE,
 101  m :                                        base::SPLIT_WANT_NONEMPTY);
 102  m :    if (analyzer_names_.empty()) {
 103  m :      PrintUsage(cmd_line->GetProgram(),
 104  m :                 "Must provide a non-empty analyzer list.");
 105  m :      return false;
 106  m :    }
 107    :  
 108  m :    for (const auto& arg : cmd_line->GetArgs()) {
 109  m :      if (!AppendMatchingPaths(base::FilePath(arg), &mindump_paths_)) {
 110  m :        PrintUsage(
 111  m :            cmd_line->GetProgram(),
 112  m :            base::StringPrintf("Can't find file or pattern \"%s\"", arg.c_str()));
 113  m :        return false;
 114  m :      }
 115  m :    }
 116    :  
 117  m :    if (mindump_paths_.empty()) {
 118  m :      PrintUsage(cmd_line->GetProgram(),
 119  m :                 "You must provide at least one dump file.");
 120  m :      return false;
 121  m :    }
 122    :  
 123  m :    return true;
 124  m :  }
 125    :  
 126  m :  int RunAnalyzerApplication::Run() {
 127  m :    scoped_refptr<refinery::SymbolProvider> symbol_provider(
 128  m :        new refinery::SymbolProvider());
 129  m :    scoped_refptr<refinery::DiaSymbolProvider> dia_symbol_provider(
 130  m :        new refinery::DiaSymbolProvider());
 131    :  
 132  m :    for (const auto& minidump_path : mindump_paths_) {
 133  m :      ::fprintf(out(), "Processing \"%ls\"\n", minidump_path.value().c_str());
 134    :  
 135  m :      minidump::Minidump minidump;
 136  m :      if (!minidump.Open(minidump_path)) {
 137  m :        LOG(ERROR) << "Unable to open dump file.";
 138  m :        return 1;
 139  m :      }
 140    :  
 141  m :      refinery::ProcessState process_state;
 142  m :      if (!Analyze(minidump, symbol_provider, dia_symbol_provider,
 143  m :                   &process_state)) {
 144  m :        LOG(ERROR) << "Failure processing minidump " << minidump_path.value();
 145  m :      }
 146  m :    }
 147    :  
 148  m :    return 0;
 149  m :  }
 150    :  
 151  m :  bool RunAnalyzerApplication::AddAnalyzers(
 152  m :      scoped_refptr<refinery::SymbolProvider> symbol_provider,
 153  m :      scoped_refptr<refinery::DiaSymbolProvider> dia_symbol_provider,
 154  m :      refinery::AnalysisRunner* runner) {
 155  m :    scoped_ptr<refinery::Analyzer> analyzer;
 156    :    // TODO(siggi): Figure a better way to do this.
 157  m :    for (const auto& analyzer_name : analyzer_names_) {
 158  m :      if (analyzer_name == "MemoryAnalyzer") {
 159  m :        analyzer.reset(new refinery::MemoryAnalyzer());
 160  m :        runner->AddAnalyzer(analyzer.Pass());
 161  m :      } else if (analyzer_name == "ModuleAnalyzer") {
 162  m :        analyzer.reset(new refinery::ModuleAnalyzer());
 163  m :        runner->AddAnalyzer(analyzer.Pass());
 164  m :      } else if (analyzer_name == "HeapAnalyzer") {
 165  m :        analyzer.reset(new refinery::HeapAnalyzer(symbol_provider));
 166  m :        runner->AddAnalyzer(analyzer.Pass());
 167  m :      } else if (analyzer_name == "StackAnalyzer") {
 168  m :        analyzer.reset(new refinery::StackAnalyzer(dia_symbol_provider));
 169  m :        runner->AddAnalyzer(analyzer.Pass());
 170  m :      } else {
 171  m :        return false;
 172  m :      }
 173  m :    }
 174    :  
 175  m :    return true;
 176  m :  }
 177    :  
 178  m :  bool RunAnalyzerApplication::Analyze(
 179  m :      const minidump::Minidump& minidump,
 180  m :      scoped_refptr<refinery::SymbolProvider> symbol_provider,
 181  m :      scoped_refptr<refinery::DiaSymbolProvider> dia_symbol_provider,
 182  m :      refinery::ProcessState* process_state) {
 183  m :    DCHECK(symbol_provider);
 184  m :    DCHECK(dia_symbol_provider);
 185  m :    DCHECK(process_state);
 186    :  
 187  m :    minidump::Minidump::Stream sys_info_stream =
 188  m :        minidump.GetStream(SystemInfoStream);
 189    :  
 190  m :    MINIDUMP_SYSTEM_INFO system_info = {};
 191  m :    if (!sys_info_stream.ReadElement(&system_info)) {
 192  m :      LOG(ERROR) << "Unable to read system info stream.";
 193  m :      return false;
 194  m :    }
 195    :  
 196  m :    VLOG(1) << base::StringPrintf("Systeminformation");
 197  m :    VLOG(1) << base::StringPrintf("  ProcessorArchitecture 0x%04X",
 198  m :                                  system_info.ProcessorArchitecture);
 199  m :    VLOG(1) << base::StringPrintf("  ProcessorLevel 0x%04X",
 200  m :                                  system_info.ProcessorLevel);
 201  m :    VLOG(1) << base::StringPrintf("  ProcessorRevision 0x%04X",
 202  m :                                  system_info.ProcessorRevision);
 203  m :    VLOG(1) << base::StringPrintf("  NumberOfProcessors %d",
 204  m :                                  system_info.NumberOfProcessors);
 205  m :    VLOG(1) << base::StringPrintf("  ProductType %d", system_info.ProductType);
 206  m :    VLOG(1) << base::StringPrintf("  MajorVersion 0x%08X",
 207  m :                                  system_info.MajorVersion);
 208  m :    VLOG(1) << base::StringPrintf("  MinorVersion 0x%08X",
 209  m :                                  system_info.MinorVersion);
 210  m :    VLOG(1) << base::StringPrintf("  BuildNumber 0x%08X",
 211  m :                                  system_info.BuildNumber);
 212  m :    VLOG(1) << base::StringPrintf("  PlatformId 0x%08X", system_info.PlatformId);
 213  m :    VLOG(1) << base::StringPrintf("  CSDVersionRva 0x%08X",
 214  m :                                  system_info.CSDVersionRva);
 215  m :    VLOG(1) << base::StringPrintf("  SuiteMask 0x%04X", system_info.SuiteMask);
 216    :  
 217  m :    VLOG(1) << "  CPU information:";
 218  m :    VLOG(1) << base::StringPrintf("    VendorId 0x%08X:0x%08X:0x%08X",
 219  m :                                  system_info.Cpu.X86CpuInfo.VendorId[0],
 220  m :                                  system_info.Cpu.X86CpuInfo.VendorId[1],
 221  m :                                  system_info.Cpu.X86CpuInfo.VendorId[1]);
 222    :  
 223  m :    VLOG(1) << base::StringPrintf("    VersionInformation 0x%08X",
 224  m :                                  system_info.Cpu.X86CpuInfo.VersionInformation);
 225  m :    VLOG(1) << base::StringPrintf("    FeatureInformation 0x%08X",
 226  m :                                  system_info.Cpu.X86CpuInfo.FeatureInformation);
 227  m :    VLOG(1) << base::StringPrintf(
 228  m :        "    AMDExtendedCpuFeatures 0x%08X",
 229  m :        system_info.Cpu.X86CpuInfo.AMDExtendedCpuFeatures);
 230    :  
 231  m :    refinery::AnalysisRunner runner;
 232  m :    if (!AddAnalyzers(symbol_provider, dia_symbol_provider, &runner))
 233  m :      return false;
 234    :  
 235  m :    return runner.Analyze(minidump, process_state) ==
 236  m :           refinery::Analyzer::ANALYSIS_COMPLETE;
 237  m :  }
 238    :  
 239  m :  }  // namespace
 240    :  
 241  m :  int main(int argc, const char* const* argv) {
 242  m :    base::AtExitManager at_exit_manager;
 243  m :    base::CommandLine::Init(argc, argv);
 244  m :    return application::Application<RunAnalyzerApplication>().Run();
 245  m :  }

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