Hector Dearman | be61adf | 2017-10-18 15:58:46 +0100 | [diff] [blame] | 1 | /* |
| 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 Mayer | 7c9e3b2 | 2018-04-26 11:55:15 +0100 | [diff] [blame] | 17 | #include <getopt.h> |
Anna Zappone | 6e4e038 | 2018-02-27 11:15:30 +0000 | [diff] [blame] | 18 | #include <sys/stat.h> |
Hector Dearman | be61adf | 2017-10-18 15:58:46 +0100 | [diff] [blame] | 19 | #include <fstream> |
Hector Dearman | e0e5780 | 2018-11-21 16:09:56 +0000 | [diff] [blame] | 20 | #include <map> |
Hector Dearman | be61adf | 2017-10-18 15:58:46 +0100 | [diff] [blame] | 21 | #include <memory> |
Isabelle Taylor | 6498fcf | 2018-02-06 11:35:05 +0000 | [diff] [blame] | 22 | #include <regex> |
| 23 | #include <set> |
Hector Dearman | be61adf | 2017-10-18 15:58:46 +0100 | [diff] [blame] | 24 | #include <sstream> |
| 25 | #include <string> |
| 26 | |
Florian Mayer | 7c9e3b2 | 2018-04-26 11:55:15 +0100 | [diff] [blame] | 27 | #include <google/protobuf/descriptor.h> |
| 28 | #include <google/protobuf/descriptor.pb.h> |
Primiano Tucci | de82dae | 2018-06-04 16:17:49 +0200 | [diff] [blame] | 29 | |
Primiano Tucci | de82dae | 2018-06-04 16:17:49 +0200 | [diff] [blame] | 30 | #include "perfetto/base/logging.h" |
Primiano Tucci | 2c5488f | 2019-06-01 03:27:28 +0100 | [diff] [blame^] | 31 | #include "perfetto/ext/base/file_utils.h" |
Primiano Tucci | de82dae | 2018-06-04 16:17:49 +0200 | [diff] [blame] | 32 | #include "src/traced/probes/ftrace/format_parser.h" |
Isabelle Taylor | cfc8eba | 2018-12-16 21:02:56 +0000 | [diff] [blame] | 33 | #include "tools/ftrace_proto_gen/ftrace_descriptor_gen.h" |
Primiano Tucci | 3cbb10a | 2018-04-10 17:52:40 +0100 | [diff] [blame] | 34 | #include "tools/ftrace_proto_gen/ftrace_proto_gen.h" |
Hector Dearman | be61adf | 2017-10-18 15:58:46 +0100 | [diff] [blame] | 35 | |
Primiano Tucci | c4b9a57 | 2018-10-11 12:41:14 +0100 | [diff] [blame] | 36 | namespace { |
| 37 | inline std::unique_ptr<std::ostream> MakeOFStream(const std::string& filename) { |
Florian Mayer | 4a6d8c8 | 2018-05-21 18:47:07 +0100 | [diff] [blame] | 38 | return std::unique_ptr<std::ostream>(new std::ofstream(filename)); |
| 39 | } |
| 40 | |
Primiano Tucci | c4b9a57 | 2018-10-11 12:41:14 +0100 | [diff] [blame] | 41 | inline std::unique_ptr<std::ostream> MakeVerifyStream( |
| 42 | const std::string& filename) { |
Florian Mayer | 4a6d8c8 | 2018-05-21 18:47:07 +0100 | [diff] [blame] | 43 | return std::unique_ptr<std::ostream>(new perfetto::VerifyStream(filename)); |
| 44 | } |
Primiano Tucci | c4b9a57 | 2018-10-11 12:41:14 +0100 | [diff] [blame] | 45 | } // namespace |
Florian Mayer | 4a6d8c8 | 2018-05-21 18:47:07 +0100 | [diff] [blame] | 46 | |
Florian Mayer | 7c9e3b2 | 2018-04-26 11:55:15 +0100 | [diff] [blame] | 47 | int 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 Mayer | 4a6d8c8 | 2018-05-21 18:47:07 +0100 | [diff] [blame] | 53 | {"check_only", no_argument, nullptr, 'c'}, |
Florian Mayer | 7c9e3b2 | 2018-04-26 11:55:15 +0100 | [diff] [blame] | 54 | }; |
| 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 Mayer | 4a6d8c8 | 2018-05-21 18:47:07 +0100 | [diff] [blame] | 64 | std::unique_ptr<std::ostream> (*ostream_factory)(const std::string&) = |
| 65 | &MakeOFStream; |
| 66 | |
Florian Mayer | 7c9e3b2 | 2018-04-26 11:55:15 +0100 | [diff] [blame] | 67 | 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 Mayer | 4a6d8c8 | 2018-05-21 18:47:07 +0100 | [diff] [blame] | 81 | case 'c': |
| 82 | ostream_factory = &MakeVerifyStream; |
Florian Mayer | 7c9e3b2 | 2018-04-26 11:55:15 +0100 | [diff] [blame] | 83 | } |
| 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 Mayer | 4a6d8c8 | 2018-05-21 18:47:07 +0100 | [diff] [blame] | 93 | "[--check_only] input_dir...\n", |
Isabelle Taylor | 6498fcf | 2018-02-06 11:35:05 +0000 | [diff] [blame] | 94 | argv[0]); |
Hector Dearman | be61adf | 2017-10-18 15:58:46 +0100 | [diff] [blame] | 95 | return 1; |
| 96 | } |
| 97 | |
Florian Mayer | 7c9e3b2 | 2018-04-26 11:55:15 +0100 | [diff] [blame] | 98 | std::vector<perfetto::FtraceEventName> whitelist = |
| 99 | perfetto::ReadWhitelist(whitelist_path); |
Isabelle Taylor | 6498fcf | 2018-02-06 11:35:05 +0000 | [diff] [blame] | 100 | std::vector<std::string> events_info; |
| 101 | |
Florian Mayer | 7c9e3b2 | 2018-04-26 11:55:15 +0100 | [diff] [blame] | 102 | 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 Dearman | e0e5780 | 2018-11-21 16:09:56 +0000 | [diff] [blame] | 118 | std::set<std::string> groups; |
| 119 | std::multimap<std::string, const perfetto::FtraceEventName*> group_to_event; |
Anna Zappone | 6e4e038 | 2018-02-27 11:15:30 +0000 | [diff] [blame] | 120 | std::set<std::string> new_events; |
Florian Mayer | 7c9e3b2 | 2018-04-26 11:55:15 +0100 | [diff] [blame] | 121 | for (const auto& event : whitelist) { |
| 122 | if (!event.valid()) |
| 123 | continue; |
Hector Dearman | e0e5780 | 2018-11-21 16:09:56 +0000 | [diff] [blame] | 124 | groups.emplace(event.group()); |
| 125 | group_to_event.emplace(event.group(), &event); |
Anna Zappone | 6e4e038 | 2018-02-27 11:15:30 +0000 | [diff] [blame] | 126 | struct stat buf; |
Florian Mayer | 7c9e3b2 | 2018-04-26 11:55:15 +0100 | [diff] [blame] | 127 | if (stat( |
| 128 | ("protos/perfetto/trace/ftrace/" + event.name() + ".proto").c_str(), |
| 129 | &buf) == -1) { |
| 130 | new_events.insert(event.name()); |
Anna Zappone | 6e4e038 | 2018-02-27 11:15:30 +0000 | [diff] [blame] | 131 | } |
| 132 | } |
| 133 | |
Hector Dearman | e0e5780 | 2018-11-21 16:09:56 +0000 | [diff] [blame] | 134 | { |
| 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 Zappone | 6e4e038 | 2018-02-27 11:15:30 +0000 | [diff] [blame] | 140 | if (!new_events.empty()) { |
Anna Zappone | 7c10462 | 2018-03-28 16:35:18 +0100 | [diff] [blame] | 141 | 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 Zappone | 6e4e038 | 2018-02-27 11:15:30 +0000 | [diff] [blame] | 147 | } |
| 148 | |
Hector Dearman | e0e5780 | 2018-11-21 16:09:56 +0000 | [diff] [blame] | 149 | for (const std::string& group : groups) { |
| 150 | std::string proto_file_name = group + ".proto"; |
Isabelle Taylor | 6498fcf | 2018-02-06 11:35:05 +0000 | [diff] [blame] | 151 | std::string output_path = output_dir + std::string("/") + proto_file_name; |
Florian Mayer | 4a6d8c8 | 2018-05-21 18:47:07 +0100 | [diff] [blame] | 152 | std::unique_ptr<std::ostream> fout = ostream_factory(output_path); |
Isabelle Taylor | 6498fcf | 2018-02-06 11:35:05 +0000 | [diff] [blame] | 153 | if (!fout) { |
| 154 | fprintf(stderr, "Failed to open %s\n", output_path.c_str()); |
| 155 | return 1; |
| 156 | } |
Hector Dearman | e0e5780 | 2018-11-21 16:09:56 +0000 | [diff] [blame] | 157 | *fout << perfetto::ProtoHeader(); |
Isabelle Taylor | 6498fcf | 2018-02-06 11:35:05 +0000 | [diff] [blame] | 158 | |
Hector Dearman | e0e5780 | 2018-11-21 16:09:56 +0000 | [diff] [blame] | 159 | 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 Maganti | 3bd67ef | 2019-01-18 17:44:09 +0000 | [diff] [blame] | 208 | |
Hector Dearman | e0e5780 | 2018-11-21 16:09:56 +0000 | [diff] [blame] | 209 | // The first id used for events in FtraceEvent proto is 3. |
Lalit Maganti | 3bd67ef | 2019-01-18 17:44:09 +0000 | [diff] [blame] | 210 | 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 Dearman | e0e5780 | 2018-11-21 16:09:56 +0000 | [diff] [blame] | 217 | events_info.push_back( |
Lalit Maganti | 3bd67ef | 2019-01-18 17:44:09 +0000 | [diff] [blame] | 218 | perfetto::SingleEventInfo(proto, event.group(), proto_field)); |
Hector Dearman | e0e5780 | 2018-11-21 16:09:56 +0000 | [diff] [blame] | 219 | |
| 220 | *fout << proto.ToString(); |
| 221 | PERFETTO_CHECK(!fout->fail()); |
| 222 | } |
Hector Dearman | be61adf | 2017-10-18 15:58:46 +0100 | [diff] [blame] | 223 | } |
| 224 | |
Florian Mayer | 4a6d8c8 | 2018-05-21 18:47:07 +0100 | [diff] [blame] | 225 | { |
| 226 | std::unique_ptr<std::ostream> out = |
Isabelle Taylor | cfc8eba | 2018-12-16 21:02:56 +0000 | [diff] [blame] | 227 | 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 Tucci | de82dae | 2018-06-04 16:17:49 +0200 | [diff] [blame] | 234 | ostream_factory("src/traced/probes/ftrace/event_info.cc"); |
Florian Mayer | 4a6d8c8 | 2018-05-21 18:47:07 +0100 | [diff] [blame] | 235 | perfetto::GenerateEventInfo(events_info, out.get()); |
| 236 | PERFETTO_CHECK(!out->fail()); |
| 237 | } |
Florian Mayer | 7c9e3b2 | 2018-04-26 11:55:15 +0100 | [diff] [blame] | 238 | |
| 239 | if (update_build_files) { |
Florian Mayer | 4a6d8c8 | 2018-05-21 18:47:07 +0100 | [diff] [blame] | 240 | std::unique_ptr<std::ostream> f = |
| 241 | ostream_factory(output_dir + "/all_protos.gni"); |
Florian Mayer | 7c9e3b2 | 2018-04-26 11:55:15 +0100 | [diff] [blame] | 242 | |
Florian Mayer | 4a6d8c8 | 2018-05-21 18:47:07 +0100 | [diff] [blame] | 243 | *f << R"(# Copyright (C) 2018 The Android Open Source Project |
Florian Mayer | 7c9e3b2 | 2018-04-26 11:55:15 +0100 | [diff] [blame] | 244 | # |
| 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 | |
| 259 | ftrace_proto_names = [ |
| 260 | "ftrace_event.proto", |
| 261 | "ftrace_event_bundle.proto", |
Hector Dearman | 3afb1e0 | 2018-04-27 16:46:52 +0100 | [diff] [blame] | 262 | "ftrace_stats.proto", |
Florian Mayer | 7c9e3b2 | 2018-04-26 11:55:15 +0100 | [diff] [blame] | 263 | "test_bundle_wrapper.proto", |
Isabelle Taylor | 98e560d | 2018-11-22 11:59:12 +0000 | [diff] [blame] | 264 | "generic.proto", |
Florian Mayer | 7c9e3b2 | 2018-04-26 11:55:15 +0100 | [diff] [blame] | 265 | )"; |
Hector Dearman | e0e5780 | 2018-11-21 16:09:56 +0000 | [diff] [blame] | 266 | for (const std::string& group : groups) { |
| 267 | *f << " \"" << group << ".proto\",\n"; |
Florian Mayer | 7c9e3b2 | 2018-04-26 11:55:15 +0100 | [diff] [blame] | 268 | } |
Florian Mayer | 4a6d8c8 | 2018-05-21 18:47:07 +0100 | [diff] [blame] | 269 | *f << "]\n"; |
| 270 | PERFETTO_CHECK(!f->fail()); |
Florian Mayer | 7c9e3b2 | 2018-04-26 11:55:15 +0100 | [diff] [blame] | 271 | } |
Hector Dearman | be61adf | 2017-10-18 15:58:46 +0100 | [diff] [blame] | 272 | } |