main.cc revision 6e4e0383b0baf72512e5d44339c43808179808ca
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
17#include <sys/stat.h>
18#include <fstream>
19#include <memory>
20#include <regex>
21#include <set>
22#include <sstream>
23#include <string>
24
25#include "ftrace_proto_gen.h"
26#include "perfetto/ftrace_reader/format_parser.h"
27#include "perfetto/trace/ftrace/ftrace_event.pbzero.h"
28
29int main(int argc, const char** argv) {
30  if (argc != 4) {
31    fprintf(stderr, "Usage: ./%s whitelist_dir input_dir output_dir\n",
32            argv[0]);
33    return 1;
34  }
35
36  const char* whitelist_path = argv[1];
37  const char* input_dir = argv[2];
38  const char* output_dir = argv[3];
39
40  std::set<std::string> events = perfetto::GetWhitelistedEvents(whitelist_path);
41  std::vector<std::string> events_info;
42
43  // proto_field_id for each event is read from this file.
44  std::ifstream input("protos/perfetto/trace/ftrace/ftrace_event.proto",
45                      std::ios::in | std::ios::binary);
46  if (!input) {
47    fprintf(stderr, "Failed to open %s\n",
48            "protos/perfetto/trace/ftrace/ftrace_event.proto");
49    return 1;
50  }
51  std::ostringstream ftrace_stream;
52  ftrace_stream << input.rdbuf();
53
54  std::set<std::string> new_events;
55  for (auto event : events) {
56    std::string file_name =
57        event.substr(event.find('/') + 1, std::string::npos);
58    struct stat buf;
59    if (stat(("protos/perfetto/trace/ftrace/" + file_name + ".proto").c_str(),
60             &buf) == -1) {
61      new_events.insert(file_name);
62    }
63  }
64
65  if (!new_events.empty()) {
66    perfetto::PrintFtraceEventProtoAdditions(new_events);
67    perfetto::PrintTraceToTextMain(new_events);
68    perfetto::PrintTraceToTextUsingStatements(new_events);
69    perfetto::PrintTraceToTextFunctions(new_events);
70  }
71
72  for (auto event : events) {
73    std::string proto_file_name =
74        event.substr(event.find('/') + 1, std::string::npos) + ".proto";
75    std::string group = event.substr(0, event.find('/'));
76    std::string input_path = input_dir + event + std::string("/format");
77    std::string output_path = output_dir + std::string("/") + proto_file_name;
78
79    std::ifstream fin(input_path.c_str(), std::ios::in);
80    if (!fin) {
81      fprintf(stderr, "Failed to open %s\n", input_path.c_str());
82      return 1;
83    }
84    std::ostringstream stream;
85    stream << fin.rdbuf();
86    fin.close();
87    std::string contents = stream.str();
88
89    perfetto::FtraceEvent format;
90    if (!perfetto::ParseFtraceEvent(contents, &format)) {
91      fprintf(stderr, "Could not parse file %s.\n", input_path.c_str());
92      return 1;
93    }
94
95    perfetto::Proto proto;
96    if (!perfetto::GenerateProto(format, &proto)) {
97      fprintf(stderr, "Could not generate proto for file %s\n",
98              input_path.c_str());
99      return 1;
100    }
101
102    std::smatch match;
103    std::string ftrace =
104        ftrace_stream.str();  // regex_search requires a non-temporary string
105    std::regex event_regex(format.name + "\\s*=\\s*(\\d+)");
106    std::regex_search(ftrace, match, event_regex);
107    std::string proto_field_id = match[1].str().c_str();
108    if (proto_field_id == "") {
109      fprintf(stderr,
110              "Could not find proto_field_id for %s in ftrace_event.proto. "
111              "Please add it.\n",
112              format.name.c_str());
113      return 1;
114    }
115
116    events_info.push_back(
117        perfetto::SingleEventInfo(format, proto, group, proto_field_id));
118
119    std::ofstream fout(output_path.c_str(), std::ios::out);
120    if (!fout) {
121      fprintf(stderr, "Failed to open %s\n", output_path.c_str());
122      return 1;
123    }
124
125    fout << proto.ToString();
126    fout.close();
127  }
128
129  input.close();
130  perfetto::GenerateEventInfo(events_info);
131}
132