blob: 591e3d338b982c53b1aa99389f587aedc01ab170 [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>
20#include <memory>
Isabelle Taylor6498fcf2018-02-06 11:35:05 +000021#include <regex>
22#include <set>
Hector Dearmanbe61adf2017-10-18 15:58:46 +010023#include <sstream>
24#include <string>
25
Florian Mayer7c9e3b22018-04-26 11:55:15 +010026#include <google/protobuf/descriptor.h>
27#include <google/protobuf/descriptor.pb.h>
Primiano Tuccide82dae2018-06-04 16:17:49 +020028
Florian Mayer74b73a92018-03-09 17:37:13 +000029#include "perfetto/base/file_utils.h"
Primiano Tuccide82dae2018-06-04 16:17:49 +020030#include "perfetto/base/logging.h"
31#include "src/traced/probes/ftrace/format_parser.h"
Primiano Tucci3cbb10a2018-04-10 17:52:40 +010032#include "tools/ftrace_proto_gen/ftrace_proto_gen.h"
Hector Dearmanbe61adf2017-10-18 15:58:46 +010033
Florian Mayer4a6d8c82018-05-21 18:47:07 +010034std::unique_ptr<std::ostream> MakeOFStream(const std::string& filename);
35std::unique_ptr<std::ostream> MakeOFStream(const std::string& filename) {
36 return std::unique_ptr<std::ostream>(new std::ofstream(filename));
37}
38
39std::unique_ptr<std::ostream> MakeVerifyStream(const std::string& filename);
40std::unique_ptr<std::ostream> MakeVerifyStream(const std::string& filename) {
41 return std::unique_ptr<std::ostream>(new perfetto::VerifyStream(filename));
42}
43
Florian Mayer7c9e3b22018-04-26 11:55:15 +010044int main(int argc, char** argv) {
45 static struct option long_options[] = {
46 {"whitelist_path", required_argument, nullptr, 'w'},
47 {"output_dir", required_argument, nullptr, 'o'},
48 {"proto_descriptor", required_argument, nullptr, 'd'},
49 {"update_build_files", no_argument, nullptr, 'b'},
Florian Mayer4a6d8c82018-05-21 18:47:07 +010050 {"check_only", no_argument, nullptr, 'c'},
Florian Mayer7c9e3b22018-04-26 11:55:15 +010051 };
52
53 int option_index;
54 int c;
55
56 std::string whitelist_path;
57 std::string output_dir;
58 std::string proto_descriptor;
59 bool update_build_files = false;
60
Florian Mayer4a6d8c82018-05-21 18:47:07 +010061 std::unique_ptr<std::ostream> (*ostream_factory)(const std::string&) =
62 &MakeOFStream;
63
Florian Mayer7c9e3b22018-04-26 11:55:15 +010064 while ((c = getopt_long(argc, argv, "", long_options, &option_index)) != -1) {
65 switch (c) {
66 case 'w':
67 whitelist_path = optarg;
68 break;
69 case 'o':
70 output_dir = optarg;
71 break;
72 case 'd':
73 proto_descriptor = optarg;
74 break;
75 case 'b':
76 update_build_files = true;
77 break;
Florian Mayer4a6d8c82018-05-21 18:47:07 +010078 case 'c':
79 ostream_factory = &MakeVerifyStream;
Florian Mayer7c9e3b22018-04-26 11:55:15 +010080 }
81 }
82
83 PERFETTO_CHECK(!whitelist_path.empty());
84 PERFETTO_CHECK(!output_dir.empty());
85 PERFETTO_CHECK(!proto_descriptor.empty());
86
87 if (optind >= argc) {
88 fprintf(stderr,
89 "Usage: ./%s -w whitelist_dir -o output_dir -d proto_descriptor "
Florian Mayer4a6d8c82018-05-21 18:47:07 +010090 "[--check_only] input_dir...\n",
Isabelle Taylor6498fcf2018-02-06 11:35:05 +000091 argv[0]);
Hector Dearmanbe61adf2017-10-18 15:58:46 +010092 return 1;
93 }
94
Florian Mayer7c9e3b22018-04-26 11:55:15 +010095 std::vector<perfetto::FtraceEventName> whitelist =
96 perfetto::ReadWhitelist(whitelist_path);
Isabelle Taylor6498fcf2018-02-06 11:35:05 +000097 std::vector<std::string> events_info;
98
Florian Mayer7c9e3b22018-04-26 11:55:15 +010099 google::protobuf::DescriptorPool descriptor_pool;
100 descriptor_pool.AllowUnknownDependencies();
101 {
102 google::protobuf::FileDescriptorSet file_descriptor_set;
103 std::string descriptor_bytes;
104 if (!perfetto::base::ReadFile(proto_descriptor, &descriptor_bytes)) {
105 fprintf(stderr, "Failed to open %s\n", proto_descriptor.c_str());
106 return 1;
107 }
108 file_descriptor_set.ParseFromString(descriptor_bytes);
109
110 for (const auto& d : file_descriptor_set.file()) {
111 PERFETTO_CHECK(descriptor_pool.BuildFile(d));
112 }
113 }
114
Florian Mayer4a6d8c82018-05-21 18:47:07 +0100115 {
116 std::unique_ptr<std::ostream> out =
117 ostream_factory(output_dir + "/ftrace_event.proto");
118 perfetto::GenerateFtraceEventProto(whitelist, out.get());
Hector Dearmanbe61adf2017-10-18 15:58:46 +0100119 }
Hector Dearmanbe61adf2017-10-18 15:58:46 +0100120
Anna Zappone6e4e0382018-02-27 11:15:30 +0000121 std::set<std::string> new_events;
Florian Mayer7c9e3b22018-04-26 11:55:15 +0100122 for (const auto& event : whitelist) {
123 if (!event.valid())
124 continue;
Anna Zappone6e4e0382018-02-27 11:15:30 +0000125 struct stat buf;
Florian Mayer7c9e3b22018-04-26 11:55:15 +0100126 if (stat(
127 ("protos/perfetto/trace/ftrace/" + event.name() + ".proto").c_str(),
128 &buf) == -1) {
129 new_events.insert(event.name());
Anna Zappone6e4e0382018-02-27 11:15:30 +0000130 }
131 }
132
133 if (!new_events.empty()) {
Anna Zappone7c104622018-03-28 16:35:18 +0100134 perfetto::PrintEventFormatterMain(new_events);
135 perfetto::PrintEventFormatterUsingStatements(new_events);
136 perfetto::PrintEventFormatterFunctions(new_events);
137 printf(
138 "\nAdd output to ParseInode in "
139 "tools/ftrace_proto_gen/ftrace_inode_handler.cc\n");
Anna Zappone6e4e0382018-02-27 11:15:30 +0000140 }
141
Florian Mayer7c9e3b22018-04-26 11:55:15 +0100142 // The first id used for events in FtraceEvent proto is 3.
143 // Because we increment before the loop, this is 2.
144 uint32_t proto_field_id = 2;
145 for (auto event : whitelist) {
146 ++proto_field_id;
147 if (!event.valid())
148 continue;
149 std::string proto_file_name = event.name() + ".proto";
Isabelle Taylor6498fcf2018-02-06 11:35:05 +0000150 std::string output_path = output_dir + std::string("/") + proto_file_name;
151
Florian Mayer7c9e3b22018-04-26 11:55:15 +0100152 std::string proto_name =
153 perfetto::ToCamelCase(event.name()) + "FtraceEvent";
Isabelle Taylor6498fcf2018-02-06 11:35:05 +0000154 perfetto::Proto proto;
Florian Mayer7c9e3b22018-04-26 11:55:15 +0100155 proto.name = proto_name;
156 proto.event_name = event.name();
157 const google::protobuf::Descriptor* d =
158 descriptor_pool.FindMessageTypeByName("perfetto.protos." + proto_name);
159 if (d)
160 proto = perfetto::Proto(event.name(), *d);
161 else
162 PERFETTO_LOG("Did not find %s", proto_name.c_str());
163 for (int i = optind; i < argc; ++i) {
164 std::string input_dir = argv[i];
165 std::string input_path = input_dir + event.group() + "/" + event.name() +
166 std::string("/format");
Isabelle Taylor6498fcf2018-02-06 11:35:05 +0000167
Florian Mayer7c9e3b22018-04-26 11:55:15 +0100168 std::string contents;
169 if (!perfetto::base::ReadFile(input_path, &contents)) {
170 fprintf(stderr, "Failed to open %s\n", input_path.c_str());
171 continue;
172 }
173
174 perfetto::FtraceEvent format;
175 if (!perfetto::ParseFtraceEvent(contents, &format)) {
176 fprintf(stderr, "Could not parse file %s.\n", input_path.c_str());
177 return 1;
178 }
179
180 perfetto::Proto event_proto;
181 if (!perfetto::GenerateProto(format, &event_proto)) {
182 fprintf(stderr, "Could not generate proto for file %s\n",
183 input_path.c_str());
184 return 1;
185 }
186 proto.MergeFrom(event_proto);
Isabelle Taylor6498fcf2018-02-06 11:35:05 +0000187 }
188
Anna Zappone7c104622018-03-28 16:35:18 +0100189 if (!new_events.empty())
Florian Mayer7c9e3b22018-04-26 11:55:15 +0100190 PrintInodeHandlerMain(proto.name, proto);
Anna Zappone7c104622018-03-28 16:35:18 +0100191
Isabelle Taylor6498fcf2018-02-06 11:35:05 +0000192 events_info.push_back(
Florian Mayer7c9e3b22018-04-26 11:55:15 +0100193 perfetto::SingleEventInfo(proto, event.group(), proto_field_id));
Isabelle Taylor6498fcf2018-02-06 11:35:05 +0000194
Florian Mayer4a6d8c82018-05-21 18:47:07 +0100195 std::unique_ptr<std::ostream> fout = ostream_factory(output_path);
Isabelle Taylor6498fcf2018-02-06 11:35:05 +0000196 if (!fout) {
197 fprintf(stderr, "Failed to open %s\n", output_path.c_str());
198 return 1;
199 }
200
Florian Mayer4a6d8c82018-05-21 18:47:07 +0100201 *fout << proto.ToString();
202 PERFETTO_CHECK(!fout->fail());
Hector Dearmanbe61adf2017-10-18 15:58:46 +0100203 }
204
Florian Mayer4a6d8c82018-05-21 18:47:07 +0100205 {
206 std::unique_ptr<std::ostream> out =
Primiano Tuccide82dae2018-06-04 16:17:49 +0200207 ostream_factory("src/traced/probes/ftrace/event_info.cc");
Florian Mayer4a6d8c82018-05-21 18:47:07 +0100208 perfetto::GenerateEventInfo(events_info, out.get());
209 PERFETTO_CHECK(!out->fail());
210 }
Florian Mayer7c9e3b22018-04-26 11:55:15 +0100211
212 if (update_build_files) {
Florian Mayer4a6d8c82018-05-21 18:47:07 +0100213 std::unique_ptr<std::ostream> f =
214 ostream_factory(output_dir + "/all_protos.gni");
Florian Mayer7c9e3b22018-04-26 11:55:15 +0100215
Florian Mayer4a6d8c82018-05-21 18:47:07 +0100216 *f << R"(# Copyright (C) 2018 The Android Open Source Project
Florian Mayer7c9e3b22018-04-26 11:55:15 +0100217#
218# Licensed under the Apache License, Version 2.0 (the "License");
219# you may not use this file except in compliance with the License.
220# You may obtain a copy of the License at
221#
222# http://www.apache.org/licenses/LICENSE-2.0
223#
224# Unless required by applicable law or agreed to in writing, software
225# distributed under the License is distributed on an "AS IS" BASIS,
226# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
227# See the License for the specific language governing permissions and
228# limitations under the License.
229
230# Autogenerated by ftrace_proto_gen.
231
232ftrace_proto_names = [
233 "ftrace_event.proto",
234 "ftrace_event_bundle.proto",
Hector Dearman3afb1e02018-04-27 16:46:52 +0100235 "ftrace_stats.proto",
Florian Mayer7c9e3b22018-04-26 11:55:15 +0100236 "test_bundle_wrapper.proto",
237)";
238 for (const perfetto::FtraceEventName& event : whitelist) {
239 if (!event.valid())
240 continue;
Florian Mayer4a6d8c82018-05-21 18:47:07 +0100241 *f << " \"" << event.name() << ".proto\",\n";
Florian Mayer7c9e3b22018-04-26 11:55:15 +0100242 }
Florian Mayer4a6d8c82018-05-21 18:47:07 +0100243 *f << "]\n";
244 PERFETTO_CHECK(!f->fail());
Florian Mayer7c9e3b22018-04-26 11:55:15 +0100245 }
Hector Dearmanbe61adf2017-10-18 15:58:46 +0100246}