1 // Copyright 2015 The Chromium OS Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 #include "perf_option_parser.h"
5
6 #include <algorithm>
7 #include <map>
8
9 #include "compat/string.h"
10
11 namespace quipper {
12
13 namespace {
14
15 enum class OptionType {
16 Boolean, // has no value
17 Value, // Uses another argument.
18 };
19
GetPerfRecordOptions()20 const std::map<string, OptionType>& GetPerfRecordOptions() {
21 static const auto* kPerfRecordOptions = new std::map<string, OptionType>{
22 {"-e", OptionType::Value},
23 {"--event", OptionType::Value},
24 {"--filter", OptionType::Value},
25 {"-p", OptionType::Value},
26 {"--pid", OptionType::Value},
27 {"-t", OptionType::Value},
28 {"--tid", OptionType::Value},
29 {"-r", OptionType::Value},
30 {"--realtime", OptionType::Value},
31 /* Banned: {"--no-buffering", OptionType::Boolean}, */
32 {"-R", OptionType::Boolean},
33 {"--raw-samples", OptionType::Boolean},
34 {"-a", OptionType::Boolean},
35 {"--all-cpus", OptionType::Boolean},
36 {"-C", OptionType::Value},
37 {"--cpu", OptionType::Value},
38 {"-c", OptionType::Value},
39 {"--count", OptionType::Value},
40 /* Banned: {"-o", OptionType::Value},
41 * {"--output", OptionType::Value}, */
42 {"-i", OptionType::Boolean},
43 {"--no-inherit", OptionType::Boolean},
44 {"-F", OptionType::Value},
45 {"--freq", OptionType::Value},
46 /* Banned: {"-m", OptionType::Value},
47 * {"--mmap-pages", OptionType::Value}, */
48 {"--group", OptionType::Boolean}, /* new? */
49 {"-g", OptionType::Boolean}, /* NB: in stat, this is short for --group */
50 {"--call-graph", OptionType::Value},
51 /* Banned: {"-v", OptionType::Boolean},
52 * {"--verbose", OptionType::Boolean}, */
53 /* Banned: {"-q", OptionType::Boolean},
54 * {"--quiet", OptionType::Boolean}, */
55 {"-s", OptionType::Boolean},
56 {"--stat", OptionType::Boolean},
57 {"-d", OptionType::Boolean},
58 {"--data", OptionType::Boolean},
59 {"-T", OptionType::Boolean},
60 {"--timestamp", OptionType::Boolean},
61 {"-P", OptionType::Boolean}, /* new? */
62 {"--period", OptionType::Boolean}, /* new? */
63 {"-n", OptionType::Boolean},
64 {"--no-samples", OptionType::Boolean},
65 {"-N", OptionType::Boolean},
66 {"--no-buildid-cache", OptionType::Boolean},
67 {"-B", OptionType::Boolean}, /* new? */
68 {"--no-buildid", OptionType::Boolean}, /* new? */
69 {"-G", OptionType::Value},
70 {"--cgroup", OptionType::Value},
71 /* Changed between v3.13 to v3.14 from:
72 {"-D", OptionType::Boolean},
73 {"--no-delay", OptionType::Boolean},
74 * to:
75 {"-D", OptionType::Value},
76 {"--delay", OptionType::Value},
77 * ... So just ban it until the new option is universal on ChromeOS perf.
78 */
79 {"-u", OptionType::Value},
80 {"--uid", OptionType::Value},
81 {"-b", OptionType::Boolean},
82 {"--branch-any", OptionType::Boolean},
83 {"-j", OptionType::Value},
84 {"--branch-filter", OptionType::Value},
85 {"-W", OptionType::Boolean},
86 {"--weight", OptionType::Boolean},
87 {"--transaction", OptionType::Boolean},
88 /* Banned: {"--per-thread", OptionType::Boolean},
89 * Only briefly present in v3.12-v3.13, but also banned:
90 * {"--force-per-cpu", OptionType::Boolean}, */
91 /* Banned: {"-I", OptionType::Boolean}, // may reveal PII
92 {"--intr-regs", OptionType::Boolean}, */
93 {"--running-time", OptionType::Boolean},
94 {"-k", OptionType::Value},
95 {"--clockid", OptionType::Value},
96 {"-S", OptionType::Value},
97 {"--snapshot", OptionType::Value},
98
99 {"--pfm-events", OptionType::Value},
100 };
101 return *kPerfRecordOptions;
102 }
103
GetPerfStatOptions()104 const std::map<string, OptionType>& GetPerfStatOptions() {
105 static const auto* kPerfStatOptions = new std::map<string, OptionType>{
106 {"-T", OptionType::Boolean},
107 {"--transaction", OptionType::Boolean},
108 {"-e", OptionType::Value},
109 {"--event", OptionType::Value},
110 {"--filter", OptionType::Value},
111 {"-i", OptionType::Boolean},
112 {"--no-inherit", OptionType::Boolean},
113 {"-p", OptionType::Value},
114 {"--pid", OptionType::Value},
115 {"-t", OptionType::Value},
116 {"--tid", OptionType::Value},
117 {"-a", OptionType::Boolean},
118 {"--all-cpus", OptionType::Boolean},
119 {"-g", OptionType::Boolean},
120 {"--group", OptionType::Boolean},
121 {"-c", OptionType::Boolean},
122 {"--scale", OptionType::Boolean},
123 /* Banned: {"-v", OptionType::Boolean},
124 * {"--verbose", OptionType::Boolean}, */
125 /* Banned: {"-r", OptionType::Value},
126 * {"--repeat", OptionType::Value}, */
127 /* Banned: {"-n", OptionType::Boolean},
128 * {"--null", OptionType::Boolean}, */
129 /* Banned: {"-d", OptionType::Boolean},
130 * {"--detailed", OptionType::Boolean}, */
131 /* Banned: {"-S", OptionType::Boolean},
132 * {"--sync", OptionType::Boolean}, */
133 /* Banned: {"-B", OptionType::Boolean},
134 * {"--big-num", OptionType::Boolean}, */
135 {"-C", OptionType::Value},
136 {"--cpu", OptionType::Value},
137 {"-A", OptionType::Boolean},
138 {"--no-aggr", OptionType::Boolean},
139 /* Banned: {"-x", OptionType::Value},
140 * {"--field-separator", OptionType::Value}, */
141 {"-G", OptionType::Value},
142 {"--cgroup", OptionType::Value},
143 /* Banned: {"-o", OptionType::Value},
144 * {"--output", OptionType::Value}, */
145 /* Banned: {"--append", OptionType::Value}, */
146 /* Banned: {"--log-fd", OptionType::Value}, */
147 /* Banned: {"--pre", OptionType::Value}, */
148 /* Banned: {"--post", OptionType::Value}, */
149 /* Banned: {"-I", OptionType::Value},
150 * {"--interval-print", OptionType::Value}, */
151 {"--per-socket", OptionType::Boolean},
152 {"--per-core", OptionType::Boolean},
153 {"-D", OptionType::Value},
154 {"--delay", OptionType::Value},
155 };
156 return *kPerfStatOptions;
157 }
158
GetPerfMemOptions()159 const std::map<string, OptionType>& GetPerfMemOptions() {
160 static const auto* kPerfMemOptions = new std::map<string, OptionType>{
161 {"-t", OptionType::Value}, {"--type", OptionType::Value},
162 {"-D", OptionType::Boolean}, {"--dump-raw-samples", OptionType::Boolean},
163 {"-x", OptionType::Value}, {"--field-separator", OptionType::Value},
164 {"-C", OptionType::Value}, {"--cpu-list", OptionType::Value},
165 };
166 return *kPerfMemOptions;
167 }
168
ValidatePerfCommandLineOptions(std::vector<string>::const_iterator begin_arg,std::vector<string>::const_iterator end_arg,const std::map<string,OptionType> & options)169 bool ValidatePerfCommandLineOptions(
170 std::vector<string>::const_iterator begin_arg,
171 std::vector<string>::const_iterator end_arg,
172 const std::map<string, OptionType>& options) {
173 for (auto args_iter = begin_arg; args_iter != end_arg; ++args_iter) {
174 const auto& it = options.find(*args_iter);
175 if (it == options.end()) {
176 return false;
177 }
178 if (it->second == OptionType::Value) {
179 ++args_iter;
180 if (args_iter == end_arg) {
181 return false; // missing value
182 }
183 }
184 }
185 return true;
186 }
187
188 } // namespace
189
ValidatePerfCommandLine(const std::vector<string> & args)190 bool ValidatePerfCommandLine(const std::vector<string>& args) {
191 if (args.size() < 2) {
192 return false;
193 }
194 if (args[0] != "perf") {
195 return false;
196 }
197 if (args[1] == "record") {
198 return ValidatePerfCommandLineOptions(args.begin() + 2, args.end(),
199 GetPerfRecordOptions());
200 }
201 if (args[1] == "mem") {
202 auto record_arg_iter = std::find(args.begin(), args.end(), "record");
203 if (record_arg_iter == args.end()) return false;
204
205 return ValidatePerfCommandLineOptions(args.begin() + 2, record_arg_iter,
206 GetPerfMemOptions()) &&
207 ValidatePerfCommandLineOptions(record_arg_iter + 1, args.end(),
208 GetPerfRecordOptions());
209 }
210 if (args[1] == "stat") {
211 return ValidatePerfCommandLineOptions(args.begin() + 2, args.end(),
212 GetPerfStatOptions());
213 }
214 return false;
215 }
216
217 } // namespace quipper
218