blob: 082acf535cb9f3581beeae87706124692d5fb936 [file] [log] [blame]
Hector Dearmanbe61adf2017-10-18 15:58:46 +01001/*
2 * Copyright (C) 2017 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Florian Mayer7c9e3b22018-04-26 11:55:15 +010017#include <getopt.h>
Anna Zappone6e4e0382018-02-27 11:15:30 +000018#include <sys/stat.h>
Hector Dearmanbe61adf2017-10-18 15:58:46 +010019#include <fstream>
Hector Dearmane0e57802018-11-21 16:09:56 +000020#include <map>
Hector Dearmanbe61adf2017-10-18 15:58:46 +010021#include <memory>
Isabelle Taylor6498fcf2018-02-06 11:35:05 +000022#include <regex>
23#include <set>
Hector Dearmanbe61adf2017-10-18 15:58:46 +010024#include <sstream>
25#include <string>
26
Florian Mayer7c9e3b22018-04-26 11:55:15 +010027#include <google/protobuf/descriptor.h>
28#include <google/protobuf/descriptor.pb.h>
Primiano Tuccide82dae2018-06-04 16:17:49 +020029
Primiano Tuccide82dae2018-06-04 16:17:49 +020030#include "perfetto/base/logging.h"
Primiano Tucci2c5488f2019-06-01 03:27:28 +010031#include "perfetto/ext/base/file_utils.h"
Primiano Tuccide82dae2018-06-04 16:17:49 +020032#include "src/traced/probes/ftrace/format_parser.h"
Isabelle Taylorcfc8eba2018-12-16 21:02:56 +000033#include "tools/ftrace_proto_gen/ftrace_descriptor_gen.h"
Primiano Tucci3cbb10a2018-04-10 17:52:40 +010034#include "tools/ftrace_proto_gen/ftrace_proto_gen.h"
Hector Dearmanbe61adf2017-10-18 15:58:46 +010035
Primiano Tuccic4b9a572018-10-11 12:41:14 +010036namespace {
37inline std::unique_ptr<std::ostream> MakeOFStream(const std::string& filename) {
Florian Mayer4a6d8c82018-05-21 18:47:07 +010038 return std::unique_ptr<std::ostream>(new std::ofstream(filename));
39}
40
Primiano Tuccic4b9a572018-10-11 12:41:14 +010041inline std::unique_ptr<std::ostream> MakeVerifyStream(
42 const std::string& filename) {
Florian Mayer4a6d8c82018-05-21 18:47:07 +010043 return std::unique_ptr<std::ostream>(new perfetto::VerifyStream(filename));
44}
Primiano Tuccic4b9a572018-10-11 12:41:14 +010045} // namespace
Florian Mayer4a6d8c82018-05-21 18:47:07 +010046
Florian Mayer7c9e3b22018-04-26 11:55:15 +010047int main(int argc, char** argv) {
48 static struct option long_options[] = {
49 {"whitelist_path", required_argument, nullptr, 'w'},
50 {"output_dir", required_argument, nullptr, 'o'},
51 {"proto_descriptor", required_argument, nullptr, 'd'},
52 {"update_build_files", no_argument, nullptr, 'b'},
Florian Mayer4a6d8c82018-05-21 18:47:07 +010053 {"check_only", no_argument, nullptr, 'c'},
Florian Mayer7c9e3b22018-04-26 11:55:15 +010054 };
55
56 int option_index;
57 int c;
58
59 std::string whitelist_path;
60 std::string output_dir;
61 std::string proto_descriptor;
62 bool update_build_files = false;
63
Florian Mayer4a6d8c82018-05-21 18:47:07 +010064 std::unique_ptr<std::ostream> (*ostream_factory)(const std::string&) =
65 &MakeOFStream;
66
Florian Mayer7c9e3b22018-04-26 11:55:15 +010067 while ((c = getopt_long(argc, argv, "", long_options, &option_index)) != -1) {
68 switch (c) {
69 case 'w':
70 whitelist_path = optarg;
71 break;
72 case 'o':
73 output_dir = optarg;
74 break;
75 case 'd':
76 proto_descriptor = optarg;
77 break;
78 case 'b':
79 update_build_files = true;
80 break;
Florian Mayer4a6d8c82018-05-21 18:47:07 +010081 case 'c':
82 ostream_factory = &MakeVerifyStream;
Florian Mayer7c9e3b22018-04-26 11:55:15 +010083 }
84 }
85
86 PERFETTO_CHECK(!whitelist_path.empty());
87 PERFETTO_CHECK(!output_dir.empty());
88 PERFETTO_CHECK(!proto_descriptor.empty());
89
90 if (optind >= argc) {
91 fprintf(stderr,
92 "Usage: ./%s -w whitelist_dir -o output_dir -d proto_descriptor "
Florian Mayer4a6d8c82018-05-21 18:47:07 +010093 "[--check_only] input_dir...\n",
Isabelle Taylor6498fcf2018-02-06 11:35:05 +000094 argv[0]);
Hector Dearmanbe61adf2017-10-18 15:58:46 +010095 return 1;
96 }
97
Florian Mayer7c9e3b22018-04-26 11:55:15 +010098 std::vector<perfetto::FtraceEventName> whitelist =
99 perfetto::ReadWhitelist(whitelist_path);
Isabelle Taylor6498fcf2018-02-06 11:35:05 +0000100 std::vector<std::string> events_info;
101
Florian Mayer7c9e3b22018-04-26 11:55:15 +0100102 google::protobuf::DescriptorPool descriptor_pool;
103 descriptor_pool.AllowUnknownDependencies();
104 {
105 google::protobuf::FileDescriptorSet file_descriptor_set;
106 std::string descriptor_bytes;
107 if (!perfetto::base::ReadFile(proto_descriptor, &descriptor_bytes)) {
108 fprintf(stderr, "Failed to open %s\n", proto_descriptor.c_str());
109 return 1;
110 }
111 file_descriptor_set.ParseFromString(descriptor_bytes);
112
113 for (const auto& d : file_descriptor_set.file()) {
114 PERFETTO_CHECK(descriptor_pool.BuildFile(d));
115 }
116 }
117
Hector Dearmane0e57802018-11-21 16:09:56 +0000118 std::set<std::string> groups;
119 std::multimap<std::string, const perfetto::FtraceEventName*> group_to_event;
Anna Zappone6e4e0382018-02-27 11:15:30 +0000120 std::set<std::string> new_events;
Florian Mayer7c9e3b22018-04-26 11:55:15 +0100121 for (const auto& event : whitelist) {
122 if (!event.valid())
123 continue;
Hector Dearmane0e57802018-11-21 16:09:56 +0000124 groups.emplace(event.group());
125 group_to_event.emplace(event.group(), &event);
Anna Zappone6e4e0382018-02-27 11:15:30 +0000126 struct stat buf;
Florian Mayer7c9e3b22018-04-26 11:55:15 +0100127 if (stat(
128 ("protos/perfetto/trace/ftrace/" + event.name() + ".proto").c_str(),
129 &buf) == -1) {
130 new_events.insert(event.name());
Anna Zappone6e4e0382018-02-27 11:15:30 +0000131 }
132 }
133
Hector Dearmane0e57802018-11-21 16:09:56 +0000134 {
135 std::unique_ptr<std::ostream> out =
136 ostream_factory(output_dir + "/ftrace_event.proto");
137 perfetto::GenerateFtraceEventProto(whitelist, groups, out.get());
138 }
139
Anna Zappone6e4e0382018-02-27 11:15:30 +0000140 if (!new_events.empty()) {
Anna Zappone7c104622018-03-28 16:35:18 +0100141 perfetto::PrintEventFormatterMain(new_events);
142 perfetto::PrintEventFormatterUsingStatements(new_events);
143 perfetto::PrintEventFormatterFunctions(new_events);
144 printf(
145 "\nAdd output to ParseInode in "
146 "tools/ftrace_proto_gen/ftrace_inode_handler.cc\n");
Anna Zappone6e4e0382018-02-27 11:15:30 +0000147 }
148
Hector Dearmane0e57802018-11-21 16:09:56 +0000149 for (const std::string& group : groups) {
150 std::string proto_file_name = group + ".proto";
Isabelle Taylor6498fcf2018-02-06 11:35:05 +0000151 std::string output_path = output_dir + std::string("/") + proto_file_name;
Florian Mayer4a6d8c82018-05-21 18:47:07 +0100152 std::unique_ptr<std::ostream> fout = ostream_factory(output_path);
Isabelle Taylor6498fcf2018-02-06 11:35:05 +0000153 if (!fout) {
154 fprintf(stderr, "Failed to open %s\n", output_path.c_str());
155 return 1;
156 }
Hector Dearmane0e57802018-11-21 16:09:56 +0000157 *fout << perfetto::ProtoHeader();
Isabelle Taylor6498fcf2018-02-06 11:35:05 +0000158
Hector Dearmane0e57802018-11-21 16:09:56 +0000159 auto range = group_to_event.equal_range(group);
160 for (auto it = range.first; it != range.second; ++it) {
161 const auto& event = *it->second;
162 if (!event.valid())
163 continue;
164
165 std::string proto_name =
166 perfetto::ToCamelCase(event.name()) + "FtraceEvent";
167 perfetto::Proto proto;
168 proto.name = proto_name;
169 proto.event_name = event.name();
170 const google::protobuf::Descriptor* d =
171 descriptor_pool.FindMessageTypeByName("perfetto.protos." +
172 proto_name);
173 if (d)
174 proto = perfetto::Proto(event.name(), *d);
175 else
176 PERFETTO_LOG("Did not find %s", proto_name.c_str());
177 for (int i = optind; i < argc; ++i) {
178 std::string input_dir = argv[i];
179 std::string input_path = input_dir + event.group() + "/" +
180 event.name() + std::string("/format");
181
182 std::string contents;
183 if (!perfetto::base::ReadFile(input_path, &contents)) {
184 continue;
185 }
186
187 perfetto::FtraceEvent format;
188 if (!perfetto::ParseFtraceEvent(contents, &format)) {
189 fprintf(stderr, "Could not parse file %s.\n", input_path.c_str());
190 return 1;
191 }
192
193 perfetto::Proto event_proto;
194 if (!perfetto::GenerateProto(format, &event_proto)) {
195 fprintf(stderr, "Could not generate proto for file %s\n",
196 input_path.c_str());
197 return 1;
198 }
199 proto.MergeFrom(event_proto);
200 }
201
202 if (!new_events.empty())
203 PrintInodeHandlerMain(proto.name, proto);
204
205 uint32_t i = 0;
206 for (; it->second != &whitelist[i]; i++)
207 ;
Lalit Maganti3bd67ef2019-01-18 17:44:09 +0000208
Hector Dearmane0e57802018-11-21 16:09:56 +0000209 // The first id used for events in FtraceEvent proto is 3.
Lalit Maganti3bd67ef2019-01-18 17:44:09 +0000210 uint32_t proto_field = i + 3;
211
212 // The generic event has field id 327 so any event with a id higher
213 // than that has to be incremented by 1.
214 if (proto_field >= 327)
215 proto_field++;
216
Hector Dearmane0e57802018-11-21 16:09:56 +0000217 events_info.push_back(
Lalit Maganti3bd67ef2019-01-18 17:44:09 +0000218 perfetto::SingleEventInfo(proto, event.group(), proto_field));
Hector Dearmane0e57802018-11-21 16:09:56 +0000219
220 *fout << proto.ToString();
221 PERFETTO_CHECK(!fout->fail());
222 }
Hector Dearmanbe61adf2017-10-18 15:58:46 +0100223 }
224
Florian Mayer4a6d8c82018-05-21 18:47:07 +0100225 {
226 std::unique_ptr<std::ostream> out =
Isabelle Taylorcfc8eba2018-12-16 21:02:56 +0000227 ostream_factory("src/trace_processor/ftrace_descriptors.cc");
228 perfetto::GenerateFtraceDescriptors(descriptor_pool, out.get());
229 PERFETTO_CHECK(!out->fail());
230 }
231
232 {
233 std::unique_ptr<std::ostream> out =
Primiano Tuccide82dae2018-06-04 16:17:49 +0200234 ostream_factory("src/traced/probes/ftrace/event_info.cc");
Florian Mayer4a6d8c82018-05-21 18:47:07 +0100235 perfetto::GenerateEventInfo(events_info, out.get());
236 PERFETTO_CHECK(!out->fail());
237 }
Florian Mayer7c9e3b22018-04-26 11:55:15 +0100238
239 if (update_build_files) {
Florian Mayer4a6d8c82018-05-21 18:47:07 +0100240 std::unique_ptr<std::ostream> f =
241 ostream_factory(output_dir + "/all_protos.gni");
Florian Mayer7c9e3b22018-04-26 11:55:15 +0100242
Florian Mayer4a6d8c82018-05-21 18:47:07 +0100243 *f << R"(# Copyright (C) 2018 The Android Open Source Project
Florian Mayer7c9e3b22018-04-26 11:55:15 +0100244#
245# Licensed under the Apache License, Version 2.0 (the "License");
246# you may not use this file except in compliance with the License.
247# You may obtain a copy of the License at
248#
249# http://www.apache.org/licenses/LICENSE-2.0
250#
251# Unless required by applicable law or agreed to in writing, software
252# distributed under the License is distributed on an "AS IS" BASIS,
253# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
254# See the License for the specific language governing permissions and
255# limitations under the License.
256
257# Autogenerated by ftrace_proto_gen.
258
259ftrace_proto_names = [
260 "ftrace_event.proto",
261 "ftrace_event_bundle.proto",
Hector Dearman3afb1e02018-04-27 16:46:52 +0100262 "ftrace_stats.proto",
Florian Mayer7c9e3b22018-04-26 11:55:15 +0100263 "test_bundle_wrapper.proto",
Isabelle Taylor98e560d2018-11-22 11:59:12 +0000264 "generic.proto",
Florian Mayer7c9e3b22018-04-26 11:55:15 +0100265)";
Hector Dearmane0e57802018-11-21 16:09:56 +0000266 for (const std::string& group : groups) {
267 *f << " \"" << group << ".proto\",\n";
Florian Mayer7c9e3b22018-04-26 11:55:15 +0100268 }
Florian Mayer4a6d8c82018-05-21 18:47:07 +0100269 *f << "]\n";
270 PERFETTO_CHECK(!f->fail());
Florian Mayer7c9e3b22018-04-26 11:55:15 +0100271 }
Hector Dearmanbe61adf2017-10-18 15:58:46 +0100272}