Coverage for /Syzygy/trace/parse/dump_trace_main.cc

CoverageLines executed / instrumented / missingexe / inst / missLanguageGroup
0.0%00300.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 <windows.h>  // NOLINT
  16    :  #include <stdio.h>
  17    :  #include <vector>
  18    :  
  19    :  #include "base/at_exit.h"
  20    :  #include "base/command_line.h"
  21    :  #include "base/file_path.h"
  22    :  #include "base/file_util.h"
  23    :  #include "base/logging.h"
  24    :  #include "base/threading/simple_thread.h"
  25    :  #include "base/win/event_trace_consumer.h"
  26    :  #include "base/win/event_trace_controller.h"
  27    :  #include "base/win/scoped_handle.h"
  28    :  #include "base/win/windows_version.h"
  29    :  #include "syzygy/trace/parse/parser.h"
  30    :  #include "syzygy/trace/service/service.h"
  31    :  
  32  m :  namespace {
  33    :  
  34  m :  using trace::parser::Parser;
  35  m :  using trace::parser::ParseEventHandler;
  36  m :  using trace::parser::ModuleInformation;
  37    :  
  38  m :  const char* GetIndexedDataTypeStr(uint8 data_type) {
  39  m :    const char* ret = NULL;
  40  m :    switch (data_type) {
  41  m :      case TraceIndexedFrequencyData::BASIC_BLOCK:
  42  m :        ret = "basic-block entry counts";
  43  m :        break;
  44  m :      case TraceIndexedFrequencyData::JUMP_TABLE:
  45  m :        ret = "jump-table case counts";
  46  m :        break;
  47  m :      default:
  48  m :        NOTREACHED();
  49  m :        break;
  50  m :    }
  51  m :    return ret;
  52  m :  }
  53    :  
  54  m :  class TraceFileDumper : public ParseEventHandler {
  55  m :   public:
  56  m :    explicit TraceFileDumper(FILE* file)
  57  m :        : file_(file ? file : stdout),
  58  m :          indentation_("") {
  59  m :    }
  60    :  
  61  m :    void PrintFunctionEvent(const char* event_type,
  62  m :                            base::Time time,
  63  m :                            DWORD process_id,
  64  m :                            DWORD thread_id,
  65  m :                            const TraceEnterExitEventData* data) {
  66  m :      DCHECK(event_type != NULL);
  67  m :      DCHECK(data != NULL);
  68  m :      DCHECK(data->function != NULL);
  69  m :      ::fprintf(file_,
  70  m :                "[%012lld] %s%s: process-id=%d; thread-id=%d; address=0x%08X\n",
  71  m :                time.ToInternalValue(),
  72  m :                indentation_,
  73  m :                event_type,
  74  m :                process_id,
  75  m :                thread_id,
  76  m :                data->function);
  77  m :    }
  78    :  
  79  m :    void PrintModuleEvent(const char* event_type,
  80  m :                          base::Time time,
  81  m :                          DWORD process_id,
  82  m :                          DWORD thread_id,
  83  m :                          const TraceModuleData* data) {
  84  m :      DCHECK(event_type != NULL);
  85  m :      DCHECK(data != NULL);
  86  m :      DCHECK(data->module_base_addr != NULL);
  87  m :      ::fprintf(file_,
  88  m :                "[%012lld] %s: process-id=%d; thread-id=%d;"
  89  m :                " module-name='%ls';"
  90  m :                " module-addr=0x%08X; module-size=%d\n",
  91  m :                time.ToInternalValue(),
  92  m :                event_type,
  93  m :                process_id,
  94  m :                thread_id,
  95  m :                data->module_name,
  96  m :                data->module_base_addr,
  97  m :                data->module_base_size);
  98  m :    }
  99    :  
 100  m :    void PrintOsVersionInfo(base::Time time,
 101  m :                            const OSVERSIONINFOEX& os_version_info) {
 102  m :      ::fprintf(file_,
 103  m :                "[%012lld] %sOsVersionInfo: platform_id=%d; product_type=%d; "
 104  m :                    "version=%d.%d; build=%d; service_pack=%d.%d\n",
 105  m :                time.ToInternalValue(),
 106  m :                indentation_,
 107  m :                os_version_info.dwPlatformId,
 108  m :                os_version_info.wProductType,
 109  m :                os_version_info.dwMajorVersion,
 110  m :                os_version_info.dwMinorVersion,
 111  m :                os_version_info.dwBuildNumber,
 112  m :                os_version_info.wServicePackMajor,
 113  m :                os_version_info.wServicePackMinor);
 114  m :    }
 115    :  
 116  m :    void PrintSystemInfo(base::Time time, const SYSTEM_INFO& system_info) {
 117  m :      ::fprintf(file_,
 118  m :                "[%012lld] %sSystemInfo: cpu_arch=%d; cpu_count=%d; "
 119  m :                    "cpu_level=%d; cpu_rev=%d\n",
 120  m :                time.ToInternalValue(),
 121  m :                indentation_,
 122  m :                system_info.wProcessorArchitecture,
 123  m :                system_info.dwNumberOfProcessors,
 124  m :                system_info.wProcessorLevel,
 125  m :                system_info.wProcessorRevision);
 126  m :    }
 127    :  
 128  m :    void PrintMemoryStatus(base::Time time, const MEMORYSTATUSEX& memory_status) {
 129  m :      ::fprintf(file_,
 130  m :                "[%012lld] %sMemoryStatus: load=%d; total_phys=%lld; "
 131  m :                    "avail_phys=%lld\n",
 132  m :                time.ToInternalValue(),
 133  m :                indentation_,
 134  m :                memory_status.dwMemoryLoad,
 135  m :                memory_status.ullTotalPhys,
 136  m :                memory_status.ullAvailPhys);
 137  m :    }
 138    :  
 139  m :    void PrintEnvironmentString(base::Time time,
 140  m :                                const std::wstring& key,
 141  m :                                const std::wstring& value) {
 142  m :      ::fprintf(file_,
 143  m :                "[%012lld] %sEnvironment: %ls=%ls\n",
 144  m :                time.ToInternalValue(),
 145  m :                indentation_,
 146  m :                key.c_str(),
 147  m :                value.c_str());
 148  m :    }
 149    :  
 150  m :    void PrintEnvironmentStrings(base::Time time,
 151  m :                                 const TraceEnvironmentStrings& env_strings) {
 152  m :      for (size_t i = 0; i < env_strings.size(); ++i)
 153  m :        PrintEnvironmentString(time, env_strings[i].first, env_strings[i].second);
 154  m :    }
 155    :  
 156  m :    virtual void OnProcessStarted(base::Time time,
 157  m :                                  DWORD process_id,
 158  m :                                  const TraceSystemInfo* data) {
 159  m :      ::fprintf(file_,
 160  m :                "[%012lld] OnProcessStarted: process-id=%d\n",
 161  m :                time.ToInternalValue(),
 162  m :                process_id);
 163    :  
 164  m :      if (data == NULL)
 165  m :        return;
 166    :  
 167  m :      indentation_ = "    ";
 168  m :      PrintOsVersionInfo(time, data->os_version_info);
 169  m :      PrintSystemInfo(time, data->system_info);
 170  m :      PrintMemoryStatus(time, data->memory_status);
 171  m :      PrintEnvironmentStrings(time, data->environment_strings);
 172  m :      indentation_ = "";
 173  m :    }
 174    :  
 175  m :    virtual void OnProcessEnded(base::Time time, DWORD process_id) {
 176  m :      ::fprintf(file_,
 177  m :                "[%012lld] OnProcessEnded: process-id=%d\n",
 178  m :                time.ToInternalValue(),
 179  m :                process_id);
 180  m :    }
 181    :  
 182  m :    virtual void OnFunctionEntry(base::Time time,
 183  m :                                 DWORD process_id,
 184  m :                                 DWORD thread_id,
 185  m :                                 const TraceEnterExitEventData* data) {
 186  m :      PrintFunctionEvent("OnFunctionEntry", time, process_id, thread_id, data);
 187  m :    }
 188    :  
 189  m :    virtual void OnFunctionExit(base::Time time,
 190  m :                                DWORD process_id,
 191  m :                                DWORD thread_id,
 192  m :                                const TraceEnterExitEventData* data) {
 193  m :      PrintFunctionEvent("OnFunctionEntry", time, process_id, thread_id, data);
 194  m :    }
 195    :  
 196  m :    virtual void OnBatchFunctionEntry(base::Time time,
 197  m :                                      DWORD process_id,
 198  m :                                      DWORD thread_id,
 199  m :                                      const TraceBatchEnterData* data) {
 200  m :      DCHECK(data != NULL);
 201  m :      DCHECK_EQ(thread_id, data->thread_id);
 202  m :      ::fprintf(file_,
 203  m :                "[%012lld] OnBatchFunctionEntry: " \
 204  m :                    "process-id=%d; thread-id=%d; num-calls=%d\n",
 205  m :                time.ToInternalValue(),
 206  m :                process_id,
 207  m :                thread_id,
 208  m :                data->num_calls);
 209    :  
 210    :      // Explode the batch event into individual function entry events.
 211  m :      TraceEnterExitEventData new_data = {};
 212  m :      indentation_ = "    ";
 213  m :      for (size_t i = 0; i < data->num_calls; ++i) {
 214  m :        new_data.function = data->calls[i].function;
 215  m :        OnFunctionEntry(time, process_id, thread_id, &new_data);
 216  m :      }
 217  m :      indentation_ = "";
 218  m :    }
 219    :  
 220  m :    virtual void OnProcessAttach(base::Time time,
 221  m :                                 DWORD process_id,
 222  m :                                 DWORD thread_id,
 223  m :                                 const TraceModuleData* data) {
 224  m :      PrintModuleEvent("OnProcessAttach", time, process_id, thread_id, data);
 225  m :    }
 226    :  
 227  m :    virtual void OnProcessDetach(base::Time time,
 228  m :                                 DWORD process_id,
 229  m :                                 DWORD thread_id,
 230  m :                                 const TraceModuleData* data) {
 231  m :      PrintModuleEvent("OnProcessDetach", time, process_id, thread_id, data);
 232  m :    }
 233    :  
 234  m :    virtual void OnThreadAttach(base::Time time,
 235  m :                                DWORD process_id,
 236  m :                                DWORD thread_id,
 237  m :                                const TraceModuleData* data) {
 238  m :      PrintModuleEvent("OnThreadAttach", time, process_id, thread_id, data);
 239  m :    }
 240    :  
 241  m :    virtual void OnThreadDetach(base::Time time,
 242  m :                                DWORD process_id,
 243  m :                                DWORD thread_id,
 244  m :                                const TraceModuleData* data) {
 245  m :      PrintModuleEvent("OnThreadDetach", time, process_id, thread_id, data);
 246  m :    }
 247    :  
 248  m :    virtual void OnInvocationBatch(base::Time time,
 249  m :                                   DWORD process_id,
 250  m :                                   DWORD thread_id,
 251  m :                                   size_t num_invocations,
 252  m :                                   const TraceBatchInvocationInfo* data) {
 253  m :      DCHECK(data != NULL);
 254  m :      ::fprintf(file_,
 255  m :                "OnInvocationBatch: process-id=%d; thread-id=%d;\n",
 256  m :                process_id,
 257  m :                thread_id);
 258  m :      for (size_t i = 0; i < num_invocations; ++i) {
 259  m :        ::fprintf(file_,
 260  m :                  "    caller=0x%08X; function=0x%08X; num-calls=%d;\n"
 261  m :                  "    cycles-min=%lld; cycles-max=%lld; cycles-sum=%lld\n",
 262  m :                  data->invocations[i].caller,
 263  m :                  data->invocations[i].function,
 264  m :                  data->invocations[i].num_calls,
 265  m :                  data->invocations[i].cycles_min,
 266  m :                  data->invocations[i].cycles_max,
 267  m :                  data->invocations[i].cycles_sum);
 268  m :      }
 269  m :    }
 270    :  
 271  m :    virtual void OnThreadName(base::Time time,
 272  m :                              DWORD process_id,
 273  m :                              DWORD thread_id,
 274  m :                              const base::StringPiece& thread_name) OVERRIDE {
 275  m :      ::fprintf(file_, "OnThreadName: process-id=%d; thread-id=%d;\n"
 276  m :                "    name=%s\n",
 277  m :                process_id, thread_id, thread_name.as_string().c_str());
 278  m :    }
 279    :  
 280  m :    virtual void OnIndexedFrequency(
 281  m :        base::Time time,
 282  m :        DWORD process_id,
 283  m :        DWORD thread_id,
 284  m :        const TraceIndexedFrequencyData* data) OVERRIDE {
 285  m :      DCHECK(data != NULL);
 286  m :      ::fprintf(file_,
 287  m :                "OnIndexedFrequency: process-id=%d; thread-id=%d;\n"
 288  m :                "    module-base-addr=0x%08X; module-base-size=%d\n"
 289  m :                "    module-checksum=0x%08X; module-time-date-stamp=0x%08X\n"
 290  m :                "    frequency-size=%d; data-type=%s; num-entries=%d\n",
 291  m :                process_id,
 292  m :                thread_id,
 293  m :                data->module_base_addr,
 294  m :                data->module_base_size,
 295  m :                data->module_checksum,
 296  m :                data->module_time_date_stamp,
 297  m :                data->frequency_size,
 298  m :                GetIndexedDataTypeStr(data->data_type),
 299  m :                data->num_entries);
 300  m :    }
 301    :  
 302  m :   private:
 303  m :    FILE* file_;
 304  m :    const char* indentation_;
 305    :  
 306  m :    DISALLOW_COPY_AND_ASSIGN(TraceFileDumper);
 307  m :  };
 308    :  
 309  m :  bool DumpTraceFiles(FILE* out_file, const std::vector<FilePath>& file_paths) {
 310  m :    Parser parser;
 311  m :    TraceFileDumper dumper(out_file);
 312  m :    if (!parser.Init(&dumper))
 313  m :      return false;
 314    :  
 315  m :    std::vector<FilePath>::const_iterator iter = file_paths.begin();
 316  m :    for (; iter != file_paths.end(); ++iter) {
 317  m :      if (!parser.OpenTraceFile(*iter))
 318  m :        return false;
 319  m :    }
 320    :  
 321  m :    return parser.Consume() && !parser.error_occurred();
 322  m :  }
 323    :  
 324  m :  }  // namespace
 325    :  
 326  m :  int main(int argc, const char** argv) {
 327  m :    base::AtExitManager at_exit_manager;
 328  m :    CommandLine::Init(argc, argv);
 329    :  
 330  m :    if (!logging::InitLogging(
 331  m :            L"",
 332  m :            logging::LOG_ONLY_TO_SYSTEM_DEBUG_LOG,
 333  m :            logging::DONT_LOCK_LOG_FILE,
 334  m :            logging::APPEND_TO_OLD_LOG_FILE,
 335  m :            logging::ENABLE_DCHECK_FOR_NON_OFFICIAL_RELEASE_BUILDS)) {
 336  m :      return 1;
 337  m :    }
 338    :  
 339  m :    CommandLine* cmd_line = CommandLine::ForCurrentProcess();
 340  m :    CHECK(cmd_line != NULL);
 341    :  
 342  m :    std::vector<FilePath> trace_file_paths;
 343  m :    for (size_t i = 0; i < cmd_line->GetArgs().size(); ++i)
 344  m :      trace_file_paths.push_back(FilePath(cmd_line->GetArgs()[i]));
 345    :  
 346  m :    if (trace_file_paths.empty()) {
 347  m :      LOG(ERROR) << "No trace file paths specified.";
 348    :  
 349  m :      ::fprintf(stderr,
 350  m :                "Usage: %ls [--out=OUTPUT] TRACE_FILE(s)...\n\n",
 351  m :                cmd_line->GetProgram().value().c_str());
 352  m :      return 1;
 353  m :    }
 354    :  
 355  m :    FilePath out_file_path(cmd_line->GetSwitchValuePath("out"));
 356  m :    file_util::ScopedFILE out_file;
 357  m :    if (!out_file_path.empty()) {
 358  m :      out_file.reset(file_util::OpenFile(out_file_path, "w"));
 359  m :      if (out_file.get() == NULL) {
 360  m :        LOG(ERROR) << "Failed to open output file: '" << out_file_path.value()
 361  m :                   << "'.";
 362  m :        return 1;
 363  m :      }
 364  m :    }
 365    :  
 366  m :    if (!DumpTraceFiles(out_file.get(), trace_file_paths)) {
 367  m :      LOG(ERROR) << "Failed to dump trace files.";
 368  m :      return 1;
 369  m :    }
 370    :  
 371  m :    return 0;
 372  m :  }

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