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 : // A utility for controlling call-traces from the command-line.
16 : #include <iostream>
17 : #include "base/at_exit.h"
18 : #include "base/command_line.h"
19 : #include "base/logging.h"
20 : #include "syzygy/trace/etw_control/call_trace_control.h"
21 :
22 m : static const char kUsage[] =
23 m : "Usage: call_trace_control [command] [options]\n"
24 m : "Commands:\n"
25 m : " start: start the call-trace, creating the ETW logs.\n"
26 m : " query: query the call-trace status.\n"
27 m : " stop: stop the call-trace, flushing and closing the ETW logs.\n"
28 m : "\n"
29 m : "Options to 'start':\n"
30 m : " --append: Append to the ETW log files rather than overwriting them.\n"
31 m : " --call-trace-file: Path to call-trace ETW log file.\n"
32 m : " Defaults to 'call_trace.etl' in the current working directory.\n"
33 m : " --min-buffers: The minimum number of buffers to use for call-trace.\n"
34 m : " Augment this from the defaults if seeing lost events.\n"
35 m : " --kernel-file: Path to kernel ETW log file.\n"
36 m : " Defaults to 'kernel.etl' in the current working directory.\n"
37 m : " --kernel-flags: Flags to pass to kernel ETW logger (numeric).\n"
38 m : " Defaults to PROCESS|THREAD|IMAGE_LOAD|DISK_IO|DISK_FILE_IO|\n"
39 m : " MEMORY_PAGE_FAULTS|MEMORY_HARD_FAULTS|FILE_IO.\n";
40 :
41 m : int Usage() {
42 m : std::cout << kUsage;
43 m : return 1;
44 m : }
45 :
46 m : enum Command {
47 m : kStart,
48 m : kQuery,
49 m : kStop,
50 m : };
51 :
52 m : struct Options {
53 m : Command command;
54 m : };
55 :
56 m : bool ParseOptions(Options* options) {
57 m : DCHECK(options != NULL);
58 :
59 m : base::CommandLine* cmd_line = base::CommandLine::ForCurrentProcess();
60 :
61 m : if (cmd_line->HasSwitch("help") || cmd_line->HasSwitch("h")) {
62 m : Usage();
63 m : return false;
64 m : }
65 :
66 m : if (cmd_line->GetArgs().size() == 0) {
67 m : LOG(ERROR) << "Must specify a command.";
68 m : return false;
69 m : }
70 :
71 m : if (cmd_line->GetArgs().size() > 1) {
72 m : LOG(ERROR) << "Can only specify one command.";
73 m : return false;
74 m : }
75 :
76 m : if (cmd_line->GetArgs()[0] == L"start") {
77 m : options->command = kStart;
78 m : } else if (cmd_line->GetArgs()[0] == L"query") {
79 m : options->command = kQuery;
80 m : } else if (cmd_line->GetArgs()[0] == L"stop") {
81 m : options->command = kStop;
82 m : } else {
83 m : LOG(ERROR) << "Unknown command: " << cmd_line->GetArgs()[0] << ".";
84 m : return false;
85 m : }
86 :
87 m : return true;
88 m : }
89 :
90 m : int main(int argc, char** argv) {
91 m : base::AtExitManager at_exit;
92 m : base::CommandLine::Init(argc, argv);
93 :
94 m : logging::LoggingSettings settings;
95 m : settings.logging_dest = logging::LOG_TO_SYSTEM_DEBUG_LOG;
96 m : settings.lock_log = logging::DONT_LOCK_LOG_FILE;
97 m : settings.delete_old = logging::APPEND_TO_OLD_LOG_FILE;
98 m : if (!logging::InitLogging(settings))
99 m : return 1;
100 :
101 m : Options options;
102 m : if (!ParseOptions(&options))
103 m : return 1;
104 :
105 : // Call the command we care about.
106 m : bool success = false;
107 m : switch (options.command) {
108 m : case kStart: {
109 m : success = StartCallTraceImpl();
110 m : break;
111 m : }
112 :
113 m : case kQuery: {
114 m : success = QueryCallTraceImpl();
115 m : break;
116 m : }
117 :
118 m : case kStop: {
119 m : success = StopCallTraceImpl();
120 m : break;
121 m : }
122 :
123 m : default: {
124 m : NOTREACHED() << "Unexpected command.";
125 m : }
126 m : }
127 :
128 m : return success ? 0 : 1;
129 m : }
|