Coverage for /Syzygy/wsdump/wsdump_main.cc

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

Line-by-line coverage:

   1    :  // Copyright 2011 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 <iostream>
  16    :  #include <list>
  17    :  
  18    :  #include "base/at_exit.h"
  19    :  #include "base/command_line.h"
  20    :  #include "base/logging.h"
  21    :  #include "base/files/file_util.h"
  22    :  #include "base/process/process_iterator.h"
  23    :  #include "base/strings/utf_string_conversions.h"
  24    :  #include "pcrecpp.h"  // NOLINT
  25    :  #include "syzygy/core/json_file_writer.h"
  26    :  #include "syzygy/wsdump/process_working_set.h"
  27    :  
  28  m :  using wsdump::ProcessWorkingSet;
  29    :  
  30  m :  namespace {
  31    :  
  32  m :  class RegexpProcessFilter: public base::ProcessFilter {
  33  m :   public:
  34  m :    RegexpProcessFilter();
  35    :  
  36  m :    bool Initialize(const std::string& regexpr);
  37    :  
  38  m :    virtual bool Includes(const base::ProcessEntry& entry) const override;
  39    :  
  40  m :   private:
  41  m :    pcrecpp::RE expr_;
  42  m :  };
  43    :  
  44  m :  RegexpProcessFilter::RegexpProcessFilter() : expr_("") {
  45  m :  }
  46    :  
  47  m :  bool RegexpProcessFilter::Initialize(const std::string& regexpr) {
  48  m :    pcrecpp::RE_Options options;
  49  m :    options.set_utf8(true);
  50  m :    options.set_caseless(true);
  51  m :    pcrecpp::RE new_expr(regexpr, options);
  52    :  
  53  m :    if (!new_expr.error().empty()) {
  54  m :      LOG(ERROR) << "Failed to initialize regular expression, error: "
  55  m :                 << new_expr.error();
  56  m :      return false;
  57  m :    }
  58    :  
  59  m :    expr_ = new_expr;
  60  m :    DCHECK_EQ("", new_expr.error());
  61    :  
  62  m :    return true;
  63  m :  }
  64    :  
  65  m :  bool RegexpProcessFilter::Includes(const base::ProcessEntry& entry) const {
  66  m :    return expr_.PartialMatch(base::WideToUTF8(entry.exe_file()));
  67  m :  }
  68    :  
  69  m :  const char kUsage[] =
  70  m :  "Usage: wsdump [--process-name=<process_re>]\n"
  71  m :  "\n"
  72  m :  "    Captures and outputs working set statistics for all processes,\n"
  73  m :  "    or only for processess whose executable name matches <process_re>.\n"
  74  m :  "\n"
  75  m :  "    The output is JSON encoded array, where each element of the array\n"
  76  m :  "    is a dictionary describing a process. Each process has the following\n"
  77  m :  "    items:\n"
  78  m :  "      * exe_file - the process' executable file, e.g. \"chrome.exe\".\n"
  79  m :  "      * pid - the process ID.\n"
  80  m :  "      * parent_pid - the parent process ID.\n"
  81  m :  "      * modules - an array of dictionaries, one for each module in the\n"
  82  m :  "        process working set.\n"
  83  m :  "    Each module has the following keys:\n"
  84  m :  "      * module_name - the module file name, e.g. \"C:\\temp\\xyz.dll\"\n"
  85  m :  "      * pages - total number of pages from this module in the working set.\n"
  86  m :  "      * shareable_pages - shareable pages in the working set.\n"
  87  m :  "      * shared_pages - shared pages in the working set.\n"
  88  m :  "      * read_only_pages - read-only pages in the working set.\n"
  89  m :  "      * writable_pages - writable pages in the working set.\n"
  90  m :  "      * executable_pages - executable pages in the working set.\n"
  91  m :  "\n"
  92  m :  "Example Output:\n"
  93  m :  "[\n"
  94  m :  "  {\n"
  95  m :  "    \"exe_file\": \"devenv.exe\",\n"
  96  m :  "    \"pid\": 5772,\n"
  97  m :  "    \"parent_pid\": 3804,\n"
  98  m :  "    \"modules\": [\n"
  99  m :  "      {\n"
 100  m :  "        \"module_name\": \"Total\",\n"
 101  m :  "        \"pages\": 34145,\n"
 102  m :  "        \"shareable_pages\": 10515,\n"
 103  m :  "        \"shared_pages\": 4847,\n"
 104  m :  "        \"read_only_pages\": 1951,\n"
 105  m :  "        \"writable_pages\": 23235,\n"
 106  m :  "        \"executable_pages\": 8959\n"
 107  m :  "      },\n"
 108  m :  "      {\n"
 109  m :  " ... \n";
 110    :  
 111  m :  int Usage() {
 112  m :    std::cout << kUsage;
 113  m :    return 1;
 114  m :  }
 115    :  
 116  m :  struct ProcessInfo {
 117  m :    ProcessInfo() : pid(0), parent_pid(0) {
 118  m :    }
 119    :  
 120  m :    std::wstring exe_file;
 121  m :    base::ProcessId pid;
 122  m :    base::ProcessId parent_pid;
 123  m :    ProcessWorkingSet ws;
 124  m :  };
 125    :  
 126  m :  void OutputModule(const std::wstring& module_name,
 127  m :                    const ProcessWorkingSet::Stats& stats,
 128  m :                    core::JSONFileWriter* json) {
 129  m :    DCHECK(json != NULL);
 130    :  
 131  m :    json->OpenDict();
 132  m :    json->OutputKey("module_name");
 133  m :    json->OutputString(module_name);
 134  m :    json->OutputKey("pages");
 135  m :    json->OutputInteger(stats.pages);
 136  m :    json->OutputKey("shareable_pages");
 137  m :    json->OutputInteger(stats.shareable_pages);
 138  m :    json->OutputKey("shared_pages");
 139  m :    json->OutputInteger(stats.shared_pages);
 140  m :    json->OutputKey("read_only_pages");
 141  m :    json->OutputInteger(stats.read_only_pages);
 142  m :    json->OutputKey("writable_pages");
 143  m :    json->OutputInteger(stats.writable_pages);
 144  m :    json->OutputKey("executable_pages");
 145  m :    json->OutputInteger(stats.executable_pages);
 146  m :    json->CloseDict();
 147  m :  }
 148    :  
 149  m :  void OutputProcessInfo(const ProcessInfo& info,
 150  m :                         core::JSONFileWriter* json) {
 151  m :    DCHECK(json != NULL);
 152    :  
 153  m :    json->OpenDict();
 154  m :    json->OutputKey("exe_file");
 155  m :    json->OutputString(info.exe_file);
 156  m :    json->OutputKey("pid");
 157  m :    json->OutputInteger(info.pid);
 158  m :    json->OutputKey("parent_pid");
 159  m :    json->OutputInteger(info.parent_pid);
 160    :  
 161  m :    json->OutputKey("modules");
 162  m :    json->OpenList();
 163  m :    OutputModule(L"Total", info.ws.total_stats(), json);
 164    :  
 165  m :    ProcessWorkingSet::ModuleStatsVector::const_iterator it =
 166  m :        info.ws.module_stats().begin();
 167  m :    ProcessWorkingSet::ModuleStatsVector::const_iterator end =
 168  m :        info.ws.module_stats().end();
 169  m :    for (; it != end; ++it)
 170  m :      OutputModule(it->module_name, *it, json);
 171    :  
 172  m :    json->CloseList();
 173  m :    json->CloseDict();
 174  m :  }
 175    :  
 176  m :  }  // namespace
 177    :  
 178  m :  int main(int argc, char** argv) {
 179  m :    base::AtExitManager at_exit_manager;
 180  m :    base::CommandLine::Init(argc, argv);
 181    :  
 182  m :    logging::LoggingSettings settings;
 183  m :    settings.logging_dest = logging::LOG_TO_SYSTEM_DEBUG_LOG;
 184  m :    settings.lock_log = logging::DONT_LOCK_LOG_FILE;
 185  m :    settings.delete_old = logging::APPEND_TO_OLD_LOG_FILE;
 186  m :    if (!logging::InitLogging(settings))
 187  m :      return 1;
 188    :  
 189  m :    base::CommandLine* cmd_line = base::CommandLine::ForCurrentProcess();
 190  m :    DCHECK(cmd_line != NULL);
 191    :  
 192  m :    if (cmd_line->HasSwitch("help") || !cmd_line->GetArgs().empty()) {
 193  m :      return Usage();
 194  m :    }
 195    :  
 196    :    // If the process-name is empty or missing we match all processes.
 197  m :    std::string process_re = cmd_line->GetSwitchValueASCII("process-name");
 198  m :    RegexpProcessFilter filter;
 199  m :    if (!filter.Initialize(process_re)) {
 200  m :      LOG(ERROR) << "Incorrect process filter regular expression.";
 201  m :      return 1;
 202  m :    }
 203    :  
 204  m :    typedef std::list<ProcessInfo> WorkingSets;
 205  m :    WorkingSets working_sets;
 206    :  
 207  m :    const base::ProcessEntry* entry = NULL;
 208  m :    base::ProcessIterator process_iterator(&filter);
 209  m :    entry = process_iterator.NextProcessEntry();
 210  m :    while (entry) {
 211  m :      working_sets.push_back(ProcessInfo());
 212  m :      ProcessInfo& info = working_sets.back();
 213  m :      if (info.ws.Initialize(entry->pid())) {
 214  m :        info.exe_file = entry->exe_file();
 215  m :        info.pid = entry->pid();
 216  m :        info.parent_pid = entry->parent_pid();
 217  m :      } else {
 218  m :        LOG(ERROR) << "Unable to capture working set information for pid: "
 219  m :                   << entry->pid();
 220  m :        working_sets.pop_back();
 221  m :      }
 222  m :      entry = process_iterator.NextProcessEntry();
 223  m :    }
 224    :  
 225  m :    core::JSONFileWriter json(stdout, true);
 226  m :    json.OpenList();
 227  m :    WorkingSets::const_iterator it = working_sets.begin();
 228  m :    for (; it != working_sets.end(); ++it) {
 229  m :      WorkingSets::const_iterator next = it;
 230  m :      ++next;
 231  m :      OutputProcessInfo(*it, &json);
 232  m :    }
 233  m :    json.CloseList();
 234  m :    json.Flush();
 235    :  
 236  m :    return 0;
 237  m :  }

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