xref: /aosp_15_r20/system/extras/simpleperf/tracing.cpp (revision 288bf5226967eb3dac5cce6c939ccc2a7f2b4fe5)
1*288bf522SAndroid Build Coastguard Worker /*
2*288bf522SAndroid Build Coastguard Worker  * Copyright (C) 2016 The Android Open Source Project
3*288bf522SAndroid Build Coastguard Worker  *
4*288bf522SAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*288bf522SAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*288bf522SAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*288bf522SAndroid Build Coastguard Worker  *
8*288bf522SAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
9*288bf522SAndroid Build Coastguard Worker  *
10*288bf522SAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*288bf522SAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*288bf522SAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*288bf522SAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*288bf522SAndroid Build Coastguard Worker  * limitations under the License.
15*288bf522SAndroid Build Coastguard Worker  */
16*288bf522SAndroid Build Coastguard Worker 
17*288bf522SAndroid Build Coastguard Worker #include "tracing.h"
18*288bf522SAndroid Build Coastguard Worker 
19*288bf522SAndroid Build Coastguard Worker #include <stdlib.h>
20*288bf522SAndroid Build Coastguard Worker #include <string.h>
21*288bf522SAndroid Build Coastguard Worker 
22*288bf522SAndroid Build Coastguard Worker #include <map>
23*288bf522SAndroid Build Coastguard Worker #include <optional>
24*288bf522SAndroid Build Coastguard Worker #include <string>
25*288bf522SAndroid Build Coastguard Worker #include <vector>
26*288bf522SAndroid Build Coastguard Worker 
27*288bf522SAndroid Build Coastguard Worker #include <android-base/file.h>
28*288bf522SAndroid Build Coastguard Worker #include <android-base/logging.h>
29*288bf522SAndroid Build Coastguard Worker #include <android-base/parseint.h>
30*288bf522SAndroid Build Coastguard Worker #include <android-base/stringprintf.h>
31*288bf522SAndroid Build Coastguard Worker #include <android-base/strings.h>
32*288bf522SAndroid Build Coastguard Worker 
33*288bf522SAndroid Build Coastguard Worker #include "RegEx.h"
34*288bf522SAndroid Build Coastguard Worker #include "environment.h"
35*288bf522SAndroid Build Coastguard Worker #include "perf_event.h"
36*288bf522SAndroid Build Coastguard Worker #include "utils.h"
37*288bf522SAndroid Build Coastguard Worker 
38*288bf522SAndroid Build Coastguard Worker using android::base::Split;
39*288bf522SAndroid Build Coastguard Worker using android::base::StartsWith;
40*288bf522SAndroid Build Coastguard Worker 
41*288bf522SAndroid Build Coastguard Worker namespace simpleperf {
42*288bf522SAndroid Build Coastguard Worker 
43*288bf522SAndroid Build Coastguard Worker const char TRACING_INFO_MAGIC[10] = {23, 8, 68, 't', 'r', 'a', 'c', 'i', 'n', 'g'};
44*288bf522SAndroid Build Coastguard Worker 
45*288bf522SAndroid Build Coastguard Worker template <class T>
AppendData(std::vector<char> & data,const T & s)46*288bf522SAndroid Build Coastguard Worker void AppendData(std::vector<char>& data, const T& s) {
47*288bf522SAndroid Build Coastguard Worker   const char* p = reinterpret_cast<const char*>(&s);
48*288bf522SAndroid Build Coastguard Worker   data.insert(data.end(), p, p + sizeof(T));
49*288bf522SAndroid Build Coastguard Worker }
50*288bf522SAndroid Build Coastguard Worker 
AppendData(std::vector<char> & data,const char * s)51*288bf522SAndroid Build Coastguard Worker static void AppendData(std::vector<char>& data, const char* s) {
52*288bf522SAndroid Build Coastguard Worker   data.insert(data.end(), s, s + strlen(s) + 1);
53*288bf522SAndroid Build Coastguard Worker }
54*288bf522SAndroid Build Coastguard Worker 
55*288bf522SAndroid Build Coastguard Worker template <>
AppendData(std::vector<char> & data,const std::string & s)56*288bf522SAndroid Build Coastguard Worker void AppendData(std::vector<char>& data, const std::string& s) {
57*288bf522SAndroid Build Coastguard Worker   data.insert(data.end(), s.c_str(), s.c_str() + s.size() + 1);
58*288bf522SAndroid Build Coastguard Worker }
59*288bf522SAndroid Build Coastguard Worker 
AppendFile(std::vector<char> & data,const std::string & file,uint32_t file_size_bytes=8)60*288bf522SAndroid Build Coastguard Worker static void AppendFile(std::vector<char>& data, const std::string& file,
61*288bf522SAndroid Build Coastguard Worker                        uint32_t file_size_bytes = 8) {
62*288bf522SAndroid Build Coastguard Worker   if (file_size_bytes == 8) {
63*288bf522SAndroid Build Coastguard Worker     uint64_t file_size = file.size();
64*288bf522SAndroid Build Coastguard Worker     AppendData(data, file_size);
65*288bf522SAndroid Build Coastguard Worker   } else if (file_size_bytes == 4) {
66*288bf522SAndroid Build Coastguard Worker     uint32_t file_size = file.size();
67*288bf522SAndroid Build Coastguard Worker     AppendData(data, file_size);
68*288bf522SAndroid Build Coastguard Worker   }
69*288bf522SAndroid Build Coastguard Worker   data.insert(data.end(), file.begin(), file.end());
70*288bf522SAndroid Build Coastguard Worker }
71*288bf522SAndroid Build Coastguard Worker 
DetachFile(BinaryReader & reader,uint32_t file_size_bytes=8)72*288bf522SAndroid Build Coastguard Worker static std::string DetachFile(BinaryReader& reader, uint32_t file_size_bytes = 8) {
73*288bf522SAndroid Build Coastguard Worker   if (!reader.CheckLeftSize(file_size_bytes)) {
74*288bf522SAndroid Build Coastguard Worker     return "";
75*288bf522SAndroid Build Coastguard Worker   }
76*288bf522SAndroid Build Coastguard Worker   uint64_t file_size = ConvertBytesToValue(reader.head, file_size_bytes);
77*288bf522SAndroid Build Coastguard Worker   reader.head += file_size_bytes;
78*288bf522SAndroid Build Coastguard Worker   if (!reader.CheckLeftSize(file_size)) {
79*288bf522SAndroid Build Coastguard Worker     return "";
80*288bf522SAndroid Build Coastguard Worker   }
81*288bf522SAndroid Build Coastguard Worker   std::string result(reader.head, file_size);
82*288bf522SAndroid Build Coastguard Worker   reader.head += file_size;
83*288bf522SAndroid Build Coastguard Worker   return result;
84*288bf522SAndroid Build Coastguard Worker }
85*288bf522SAndroid Build Coastguard Worker 
ReadTraceFsFile(const std::string & path,std::string * content,bool report_error=true)86*288bf522SAndroid Build Coastguard Worker static bool ReadTraceFsFile(const std::string& path, std::string* content,
87*288bf522SAndroid Build Coastguard Worker                             bool report_error = true) {
88*288bf522SAndroid Build Coastguard Worker   const char* tracefs_dir = GetTraceFsDir();
89*288bf522SAndroid Build Coastguard Worker   if (tracefs_dir == nullptr) {
90*288bf522SAndroid Build Coastguard Worker     if (report_error) {
91*288bf522SAndroid Build Coastguard Worker       LOG(ERROR) << "tracefs doesn't exist";
92*288bf522SAndroid Build Coastguard Worker     }
93*288bf522SAndroid Build Coastguard Worker     return false;
94*288bf522SAndroid Build Coastguard Worker   }
95*288bf522SAndroid Build Coastguard Worker   std::string full_path = tracefs_dir + path;
96*288bf522SAndroid Build Coastguard Worker   if (!android::base::ReadFileToString(full_path, content)) {
97*288bf522SAndroid Build Coastguard Worker     if (report_error) {
98*288bf522SAndroid Build Coastguard Worker       PLOG(ERROR) << "failed to read " << full_path;
99*288bf522SAndroid Build Coastguard Worker     }
100*288bf522SAndroid Build Coastguard Worker     return false;
101*288bf522SAndroid Build Coastguard Worker   }
102*288bf522SAndroid Build Coastguard Worker   return true;
103*288bf522SAndroid Build Coastguard Worker }
104*288bf522SAndroid Build Coastguard Worker 
105*288bf522SAndroid Build Coastguard Worker struct TraceType {
106*288bf522SAndroid Build Coastguard Worker   std::string system;
107*288bf522SAndroid Build Coastguard Worker   std::string name;
108*288bf522SAndroid Build Coastguard Worker };
109*288bf522SAndroid Build Coastguard Worker 
110*288bf522SAndroid Build Coastguard Worker class TracingFile {
111*288bf522SAndroid Build Coastguard Worker  public:
112*288bf522SAndroid Build Coastguard Worker   TracingFile();
113*288bf522SAndroid Build Coastguard Worker   bool RecordHeaderFiles();
114*288bf522SAndroid Build Coastguard Worker   void RecordFtraceFiles(const std::vector<TraceType>& trace_types);
115*288bf522SAndroid Build Coastguard Worker   bool RecordEventFiles(const std::vector<TraceType>& trace_types);
116*288bf522SAndroid Build Coastguard Worker   bool RecordKallsymsFile();
117*288bf522SAndroid Build Coastguard Worker   bool RecordPrintkFormatsFile();
118*288bf522SAndroid Build Coastguard Worker   std::vector<char> BinaryFormat() const;
119*288bf522SAndroid Build Coastguard Worker   bool LoadFromBinary(const std::vector<char>& data);
120*288bf522SAndroid Build Coastguard Worker   void Dump(size_t indent) const;
121*288bf522SAndroid Build Coastguard Worker   std::vector<TracingFormat> LoadTracingFormatsFromEventFiles() const;
GetKallsymsFile() const122*288bf522SAndroid Build Coastguard Worker   const std::string& GetKallsymsFile() const { return kallsyms_file; }
GetPageSize() const123*288bf522SAndroid Build Coastguard Worker   uint32_t GetPageSize() const { return page_size; }
124*288bf522SAndroid Build Coastguard Worker 
125*288bf522SAndroid Build Coastguard Worker  private:
126*288bf522SAndroid Build Coastguard Worker   char magic[10];
127*288bf522SAndroid Build Coastguard Worker   std::string version;
128*288bf522SAndroid Build Coastguard Worker   char endian;
129*288bf522SAndroid Build Coastguard Worker   uint8_t size_of_long;
130*288bf522SAndroid Build Coastguard Worker   uint32_t page_size;
131*288bf522SAndroid Build Coastguard Worker   std::string header_page_file;
132*288bf522SAndroid Build Coastguard Worker   std::string header_event_file;
133*288bf522SAndroid Build Coastguard Worker 
134*288bf522SAndroid Build Coastguard Worker   std::vector<std::string> ftrace_format_files;
135*288bf522SAndroid Build Coastguard Worker   // pair of system, format_file_data.
136*288bf522SAndroid Build Coastguard Worker   std::vector<std::pair<std::string, std::string>> event_format_files;
137*288bf522SAndroid Build Coastguard Worker 
138*288bf522SAndroid Build Coastguard Worker   std::string kallsyms_file;
139*288bf522SAndroid Build Coastguard Worker   std::string printk_formats_file;
140*288bf522SAndroid Build Coastguard Worker };
141*288bf522SAndroid Build Coastguard Worker 
TracingFile()142*288bf522SAndroid Build Coastguard Worker TracingFile::TracingFile() {
143*288bf522SAndroid Build Coastguard Worker   memcpy(magic, TRACING_INFO_MAGIC, sizeof(TRACING_INFO_MAGIC));
144*288bf522SAndroid Build Coastguard Worker   version = "0.5";
145*288bf522SAndroid Build Coastguard Worker   endian = 0;
146*288bf522SAndroid Build Coastguard Worker   size_of_long = static_cast<int>(sizeof(long));  // NOLINT(google-runtime-int)
147*288bf522SAndroid Build Coastguard Worker   page_size = static_cast<uint32_t>(simpleperf::GetPageSize());
148*288bf522SAndroid Build Coastguard Worker }
149*288bf522SAndroid Build Coastguard Worker 
RecordHeaderFiles()150*288bf522SAndroid Build Coastguard Worker bool TracingFile::RecordHeaderFiles() {
151*288bf522SAndroid Build Coastguard Worker   return ReadTraceFsFile("/events/header_page", &header_page_file) &&
152*288bf522SAndroid Build Coastguard Worker          ReadTraceFsFile("/events/header_event", &header_event_file);
153*288bf522SAndroid Build Coastguard Worker }
154*288bf522SAndroid Build Coastguard Worker 
RecordFtraceFiles(const std::vector<TraceType> & trace_types)155*288bf522SAndroid Build Coastguard Worker void TracingFile::RecordFtraceFiles(const std::vector<TraceType>& trace_types) {
156*288bf522SAndroid Build Coastguard Worker   for (const auto& type : trace_types) {
157*288bf522SAndroid Build Coastguard Worker     std::string format_data;
158*288bf522SAndroid Build Coastguard Worker     if (ReadTraceFsFile("/events/ftrace/" + type.name + "/format", &format_data, false)) {
159*288bf522SAndroid Build Coastguard Worker       ftrace_format_files.emplace_back(std::move(format_data));
160*288bf522SAndroid Build Coastguard Worker     }
161*288bf522SAndroid Build Coastguard Worker   }
162*288bf522SAndroid Build Coastguard Worker }
163*288bf522SAndroid Build Coastguard Worker 
RecordEventFiles(const std::vector<TraceType> & trace_types)164*288bf522SAndroid Build Coastguard Worker bool TracingFile::RecordEventFiles(const std::vector<TraceType>& trace_types) {
165*288bf522SAndroid Build Coastguard Worker   for (const auto& type : trace_types) {
166*288bf522SAndroid Build Coastguard Worker     std::string format_data;
167*288bf522SAndroid Build Coastguard Worker     if (!ReadTraceFsFile("/events/" + type.system + "/" + type.name + "/format", &format_data)) {
168*288bf522SAndroid Build Coastguard Worker       return false;
169*288bf522SAndroid Build Coastguard Worker     }
170*288bf522SAndroid Build Coastguard Worker     event_format_files.emplace_back(type.system, std::move(format_data));
171*288bf522SAndroid Build Coastguard Worker   }
172*288bf522SAndroid Build Coastguard Worker   return true;
173*288bf522SAndroid Build Coastguard Worker }
174*288bf522SAndroid Build Coastguard Worker 
RecordPrintkFormatsFile()175*288bf522SAndroid Build Coastguard Worker bool TracingFile::RecordPrintkFormatsFile() {
176*288bf522SAndroid Build Coastguard Worker   return ReadTraceFsFile("/printk_formats", &printk_formats_file);
177*288bf522SAndroid Build Coastguard Worker }
178*288bf522SAndroid Build Coastguard Worker 
BinaryFormat() const179*288bf522SAndroid Build Coastguard Worker std::vector<char> TracingFile::BinaryFormat() const {
180*288bf522SAndroid Build Coastguard Worker   std::vector<char> ret;
181*288bf522SAndroid Build Coastguard Worker   ret.insert(ret.end(), magic, magic + sizeof(magic));
182*288bf522SAndroid Build Coastguard Worker   AppendData(ret, version);
183*288bf522SAndroid Build Coastguard Worker   ret.push_back(endian);
184*288bf522SAndroid Build Coastguard Worker   AppendData(ret, size_of_long);
185*288bf522SAndroid Build Coastguard Worker   AppendData(ret, page_size);
186*288bf522SAndroid Build Coastguard Worker   AppendData(ret, "header_page");
187*288bf522SAndroid Build Coastguard Worker   AppendFile(ret, header_page_file);
188*288bf522SAndroid Build Coastguard Worker   AppendData(ret, "header_event");
189*288bf522SAndroid Build Coastguard Worker   AppendFile(ret, header_event_file);
190*288bf522SAndroid Build Coastguard Worker   int count = static_cast<int>(ftrace_format_files.size());
191*288bf522SAndroid Build Coastguard Worker   AppendData(ret, count);
192*288bf522SAndroid Build Coastguard Worker   for (const auto& format : ftrace_format_files) {
193*288bf522SAndroid Build Coastguard Worker     AppendFile(ret, format);
194*288bf522SAndroid Build Coastguard Worker   }
195*288bf522SAndroid Build Coastguard Worker   count = static_cast<int>(event_format_files.size());
196*288bf522SAndroid Build Coastguard Worker   AppendData(ret, count);
197*288bf522SAndroid Build Coastguard Worker   for (const auto& pair : event_format_files) {
198*288bf522SAndroid Build Coastguard Worker     AppendData(ret, pair.first);
199*288bf522SAndroid Build Coastguard Worker     AppendData(ret, 1);
200*288bf522SAndroid Build Coastguard Worker     AppendFile(ret, pair.second);
201*288bf522SAndroid Build Coastguard Worker   }
202*288bf522SAndroid Build Coastguard Worker   AppendFile(ret, kallsyms_file, 4);
203*288bf522SAndroid Build Coastguard Worker   AppendFile(ret, printk_formats_file, 4);
204*288bf522SAndroid Build Coastguard Worker   return ret;
205*288bf522SAndroid Build Coastguard Worker }
206*288bf522SAndroid Build Coastguard Worker 
LoadFromBinary(const std::vector<char> & data)207*288bf522SAndroid Build Coastguard Worker bool TracingFile::LoadFromBinary(const std::vector<char>& data) {
208*288bf522SAndroid Build Coastguard Worker   BinaryReader reader(data.data(), data.size());
209*288bf522SAndroid Build Coastguard Worker   if (!reader.CheckLeftSize(sizeof(magic)) || memcmp(reader.head, magic, sizeof(magic)) != 0) {
210*288bf522SAndroid Build Coastguard Worker     return false;
211*288bf522SAndroid Build Coastguard Worker   }
212*288bf522SAndroid Build Coastguard Worker   reader.head += sizeof(magic);
213*288bf522SAndroid Build Coastguard Worker   version = reader.ReadString();
214*288bf522SAndroid Build Coastguard Worker   reader.Read(endian);
215*288bf522SAndroid Build Coastguard Worker   reader.Read(size_of_long);
216*288bf522SAndroid Build Coastguard Worker   reader.Read(page_size);
217*288bf522SAndroid Build Coastguard Worker   if (reader.ReadString() != "header_page") {
218*288bf522SAndroid Build Coastguard Worker     return false;
219*288bf522SAndroid Build Coastguard Worker   }
220*288bf522SAndroid Build Coastguard Worker   header_page_file = DetachFile(reader);
221*288bf522SAndroid Build Coastguard Worker   if (reader.ReadString() != "header_event") {
222*288bf522SAndroid Build Coastguard Worker     return false;
223*288bf522SAndroid Build Coastguard Worker   }
224*288bf522SAndroid Build Coastguard Worker   header_event_file = DetachFile(reader);
225*288bf522SAndroid Build Coastguard Worker   uint32_t count = 0;
226*288bf522SAndroid Build Coastguard Worker   reader.Read(count);
227*288bf522SAndroid Build Coastguard Worker   ftrace_format_files.clear();
228*288bf522SAndroid Build Coastguard Worker   while (count-- > 0 && !reader.error) {
229*288bf522SAndroid Build Coastguard Worker     ftrace_format_files.emplace_back(DetachFile(reader));
230*288bf522SAndroid Build Coastguard Worker   }
231*288bf522SAndroid Build Coastguard Worker   reader.Read(count);
232*288bf522SAndroid Build Coastguard Worker   event_format_files.clear();
233*288bf522SAndroid Build Coastguard Worker   while (count-- > 0 && !reader.error) {
234*288bf522SAndroid Build Coastguard Worker     std::string system = reader.ReadString();
235*288bf522SAndroid Build Coastguard Worker     uint32_t count_in_system = 0;
236*288bf522SAndroid Build Coastguard Worker     reader.Read(count_in_system);
237*288bf522SAndroid Build Coastguard Worker     while (count_in_system-- > 0 && !reader.error) {
238*288bf522SAndroid Build Coastguard Worker       std::string format = DetachFile(reader);
239*288bf522SAndroid Build Coastguard Worker       event_format_files.push_back(std::make_pair(system, std::move(format)));
240*288bf522SAndroid Build Coastguard Worker     }
241*288bf522SAndroid Build Coastguard Worker   }
242*288bf522SAndroid Build Coastguard Worker   kallsyms_file = DetachFile(reader, 4);
243*288bf522SAndroid Build Coastguard Worker   printk_formats_file = DetachFile(reader, 4);
244*288bf522SAndroid Build Coastguard Worker   return !reader.error && reader.head == reader.end;
245*288bf522SAndroid Build Coastguard Worker }
246*288bf522SAndroid Build Coastguard Worker 
Dump(size_t indent) const247*288bf522SAndroid Build Coastguard Worker void TracingFile::Dump(size_t indent) const {
248*288bf522SAndroid Build Coastguard Worker   PrintIndented(indent, "tracing data:\n");
249*288bf522SAndroid Build Coastguard Worker   PrintIndented(indent + 1, "magic: ");
250*288bf522SAndroid Build Coastguard Worker   for (size_t i = 0; i < 3u; ++i) {
251*288bf522SAndroid Build Coastguard Worker     printf("0x%x ", magic[i]);
252*288bf522SAndroid Build Coastguard Worker   }
253*288bf522SAndroid Build Coastguard Worker   for (size_t i = 3; i < sizeof(magic); ++i) {
254*288bf522SAndroid Build Coastguard Worker     printf("%c", magic[i]);
255*288bf522SAndroid Build Coastguard Worker   }
256*288bf522SAndroid Build Coastguard Worker   printf("\n");
257*288bf522SAndroid Build Coastguard Worker   PrintIndented(indent + 1, "version: %s\n", version.c_str());
258*288bf522SAndroid Build Coastguard Worker   PrintIndented(indent + 1, "endian: %d\n", endian);
259*288bf522SAndroid Build Coastguard Worker   PrintIndented(indent + 1, "header_page:\n%s\n\n", header_page_file.c_str());
260*288bf522SAndroid Build Coastguard Worker   PrintIndented(indent + 1, "header_event:\n%s\n\n", header_event_file.c_str());
261*288bf522SAndroid Build Coastguard Worker   for (size_t i = 0; i < ftrace_format_files.size(); ++i) {
262*288bf522SAndroid Build Coastguard Worker     PrintIndented(indent + 1, "ftrace format file %zu/%zu:\n%s\n\n", i + 1,
263*288bf522SAndroid Build Coastguard Worker                   ftrace_format_files.size(), ftrace_format_files[i].c_str());
264*288bf522SAndroid Build Coastguard Worker   }
265*288bf522SAndroid Build Coastguard Worker   for (size_t i = 0; i < event_format_files.size(); ++i) {
266*288bf522SAndroid Build Coastguard Worker     PrintIndented(indent + 1, "event format file %zu/%zu %s:\n%s\n\n", i + 1,
267*288bf522SAndroid Build Coastguard Worker                   event_format_files.size(), event_format_files[i].first.c_str(),
268*288bf522SAndroid Build Coastguard Worker                   event_format_files[i].second.c_str());
269*288bf522SAndroid Build Coastguard Worker   }
270*288bf522SAndroid Build Coastguard Worker   PrintIndented(indent + 1, "kallsyms:\n%s\n\n", kallsyms_file.c_str());
271*288bf522SAndroid Build Coastguard Worker   PrintIndented(indent + 1, "printk_formats:\n%s\n\n", printk_formats_file.c_str());
272*288bf522SAndroid Build Coastguard Worker }
273*288bf522SAndroid Build Coastguard Worker 
274*288bf522SAndroid Build Coastguard Worker enum class FormatParsingState {
275*288bf522SAndroid Build Coastguard Worker   READ_NAME,
276*288bf522SAndroid Build Coastguard Worker   READ_ID,
277*288bf522SAndroid Build Coastguard Worker   READ_FIELDS,
278*288bf522SAndroid Build Coastguard Worker   READ_PRINTFMT,
279*288bf522SAndroid Build Coastguard Worker };
280*288bf522SAndroid Build Coastguard Worker 
281*288bf522SAndroid Build Coastguard Worker // Parse lines like: field:char comm[16]; offset:8; size:16;  signed:1;
ParseTracingField(const std::string & s)282*288bf522SAndroid Build Coastguard Worker static std::optional<TracingField> ParseTracingField(const std::string& s) {
283*288bf522SAndroid Build Coastguard Worker   TracingField field;
284*288bf522SAndroid Build Coastguard Worker   std::string name;
285*288bf522SAndroid Build Coastguard Worker   std::string value;
286*288bf522SAndroid Build Coastguard Worker   auto re = RegEx::Create(R"((\w+):(.+?);)");
287*288bf522SAndroid Build Coastguard Worker 
288*288bf522SAndroid Build Coastguard Worker   std::unique_ptr<RegExMatch> match = re->SearchAll(s);
289*288bf522SAndroid Build Coastguard Worker   while (match->IsValid()) {
290*288bf522SAndroid Build Coastguard Worker     std::string name = match->GetField(1);
291*288bf522SAndroid Build Coastguard Worker     std::string value = match->GetField(2);
292*288bf522SAndroid Build Coastguard Worker     match->MoveToNextMatch();
293*288bf522SAndroid Build Coastguard Worker 
294*288bf522SAndroid Build Coastguard Worker     if (name == "field") {
295*288bf522SAndroid Build Coastguard Worker       std::string last_value_part = Split(value, " \t").back();
296*288bf522SAndroid Build Coastguard Worker 
297*288bf522SAndroid Build Coastguard Worker       if (StartsWith(value, "__data_loc char[]")) {
298*288bf522SAndroid Build Coastguard Worker         // Parse value like "__data_loc char[] name".
299*288bf522SAndroid Build Coastguard Worker         field.name = last_value_part;
300*288bf522SAndroid Build Coastguard Worker         field.elem_count = 1;
301*288bf522SAndroid Build Coastguard Worker         field.is_dynamic = true;
302*288bf522SAndroid Build Coastguard Worker       } else if (auto left_bracket_pos = last_value_part.find('[');
303*288bf522SAndroid Build Coastguard Worker                  left_bracket_pos != std::string::npos) {
304*288bf522SAndroid Build Coastguard Worker         // Parse value with brackets like "char comm[16]".
305*288bf522SAndroid Build Coastguard Worker         field.name = last_value_part.substr(0, left_bracket_pos);
306*288bf522SAndroid Build Coastguard Worker         field.elem_count = 1;
307*288bf522SAndroid Build Coastguard Worker         if (size_t right_bracket_pos = last_value_part.find(']', left_bracket_pos);
308*288bf522SAndroid Build Coastguard Worker             right_bracket_pos != std::string::npos) {
309*288bf522SAndroid Build Coastguard Worker           size_t len = right_bracket_pos - left_bracket_pos - 1;
310*288bf522SAndroid Build Coastguard Worker           size_t elem_count;
311*288bf522SAndroid Build Coastguard Worker           // Array size may not be a number, like field:u32 rates[IEEE80211_NUM_BANDS].
312*288bf522SAndroid Build Coastguard Worker           if (android::base::ParseUint(last_value_part.substr(left_bracket_pos + 1, len),
313*288bf522SAndroid Build Coastguard Worker                                        &elem_count) &&
314*288bf522SAndroid Build Coastguard Worker               elem_count > 0) {
315*288bf522SAndroid Build Coastguard Worker             field.elem_count = elem_count;
316*288bf522SAndroid Build Coastguard Worker           }
317*288bf522SAndroid Build Coastguard Worker         }
318*288bf522SAndroid Build Coastguard Worker       } else {
319*288bf522SAndroid Build Coastguard Worker         // Parse value like "int common_pid".
320*288bf522SAndroid Build Coastguard Worker         field.name = last_value_part;
321*288bf522SAndroid Build Coastguard Worker         field.elem_count = 1;
322*288bf522SAndroid Build Coastguard Worker       }
323*288bf522SAndroid Build Coastguard Worker     } else if (name == "offset") {
324*288bf522SAndroid Build Coastguard Worker       if (!android::base::ParseUint(value, &field.offset)) {
325*288bf522SAndroid Build Coastguard Worker         return std::nullopt;
326*288bf522SAndroid Build Coastguard Worker       }
327*288bf522SAndroid Build Coastguard Worker     } else if (name == "size") {
328*288bf522SAndroid Build Coastguard Worker       size_t size;
329*288bf522SAndroid Build Coastguard Worker       if (!android::base::ParseUint(value, &size) || size == 0 || size % field.elem_count != 0) {
330*288bf522SAndroid Build Coastguard Worker         return std::nullopt;
331*288bf522SAndroid Build Coastguard Worker       }
332*288bf522SAndroid Build Coastguard Worker       field.elem_size = size / field.elem_count;
333*288bf522SAndroid Build Coastguard Worker     } else if (name == "signed") {
334*288bf522SAndroid Build Coastguard Worker       int is_signed;
335*288bf522SAndroid Build Coastguard Worker       if (!android::base::ParseInt(value, &is_signed, 0, 1)) {
336*288bf522SAndroid Build Coastguard Worker         return std::nullopt;
337*288bf522SAndroid Build Coastguard Worker       }
338*288bf522SAndroid Build Coastguard Worker       field.is_signed = (is_signed == 1);
339*288bf522SAndroid Build Coastguard Worker     }
340*288bf522SAndroid Build Coastguard Worker   }
341*288bf522SAndroid Build Coastguard Worker   return field;
342*288bf522SAndroid Build Coastguard Worker }
343*288bf522SAndroid Build Coastguard Worker 
ParseTracingFormat(const std::string & data)344*288bf522SAndroid Build Coastguard Worker TracingFormat ParseTracingFormat(const std::string& data) {
345*288bf522SAndroid Build Coastguard Worker   TracingFormat format;
346*288bf522SAndroid Build Coastguard Worker   std::vector<std::string> strs = Split(data, "\n");
347*288bf522SAndroid Build Coastguard Worker   FormatParsingState state = FormatParsingState::READ_NAME;
348*288bf522SAndroid Build Coastguard Worker   for (const auto& s : strs) {
349*288bf522SAndroid Build Coastguard Worker     if (state == FormatParsingState::READ_NAME) {
350*288bf522SAndroid Build Coastguard Worker       if (size_t pos = s.find("name:"); pos != std::string::npos) {
351*288bf522SAndroid Build Coastguard Worker         format.name = android::base::Trim(s.substr(pos + strlen("name:")));
352*288bf522SAndroid Build Coastguard Worker         state = FormatParsingState::READ_ID;
353*288bf522SAndroid Build Coastguard Worker       }
354*288bf522SAndroid Build Coastguard Worker     } else if (state == FormatParsingState::READ_ID) {
355*288bf522SAndroid Build Coastguard Worker       if (size_t pos = s.find("ID:"); pos != std::string::npos) {
356*288bf522SAndroid Build Coastguard Worker         format.id = strtoull(s.substr(pos + strlen("ID:")).c_str(), nullptr, 10);
357*288bf522SAndroid Build Coastguard Worker         state = FormatParsingState::READ_FIELDS;
358*288bf522SAndroid Build Coastguard Worker       }
359*288bf522SAndroid Build Coastguard Worker     } else if (state == FormatParsingState::READ_FIELDS) {
360*288bf522SAndroid Build Coastguard Worker       if (size_t pos = s.find("field:"); pos != std::string::npos) {
361*288bf522SAndroid Build Coastguard Worker         // Ignore errors parsing a field. Because it's not critical.
362*288bf522SAndroid Build Coastguard Worker         if (std::optional<TracingField> field = ParseTracingField(s); field.has_value()) {
363*288bf522SAndroid Build Coastguard Worker           format.fields.emplace_back(field.value());
364*288bf522SAndroid Build Coastguard Worker         }
365*288bf522SAndroid Build Coastguard Worker       }
366*288bf522SAndroid Build Coastguard Worker     }
367*288bf522SAndroid Build Coastguard Worker   }
368*288bf522SAndroid Build Coastguard Worker   return format;
369*288bf522SAndroid Build Coastguard Worker }
370*288bf522SAndroid Build Coastguard Worker 
LoadTracingFormatsFromEventFiles() const371*288bf522SAndroid Build Coastguard Worker std::vector<TracingFormat> TracingFile::LoadTracingFormatsFromEventFiles() const {
372*288bf522SAndroid Build Coastguard Worker   std::vector<TracingFormat> formats;
373*288bf522SAndroid Build Coastguard Worker   for (const auto& pair : event_format_files) {
374*288bf522SAndroid Build Coastguard Worker     TracingFormat format = ParseTracingFormat(pair.second);
375*288bf522SAndroid Build Coastguard Worker     format.system_name = pair.first;
376*288bf522SAndroid Build Coastguard Worker     formats.push_back(format);
377*288bf522SAndroid Build Coastguard Worker   }
378*288bf522SAndroid Build Coastguard Worker   return formats;
379*288bf522SAndroid Build Coastguard Worker }
380*288bf522SAndroid Build Coastguard Worker 
Create(const std::vector<char> & data)381*288bf522SAndroid Build Coastguard Worker std::unique_ptr<Tracing> Tracing::Create(const std::vector<char>& data) {
382*288bf522SAndroid Build Coastguard Worker   std::unique_ptr<Tracing> tracing(new Tracing);
383*288bf522SAndroid Build Coastguard Worker   if (!tracing->tracing_file_->LoadFromBinary(data)) {
384*288bf522SAndroid Build Coastguard Worker     LOG(ERROR) << "Failed to load tracing data";
385*288bf522SAndroid Build Coastguard Worker     return nullptr;
386*288bf522SAndroid Build Coastguard Worker   }
387*288bf522SAndroid Build Coastguard Worker   return tracing;
388*288bf522SAndroid Build Coastguard Worker }
389*288bf522SAndroid Build Coastguard Worker 
Tracing()390*288bf522SAndroid Build Coastguard Worker Tracing::Tracing() : tracing_file_(new TracingFile) {}
391*288bf522SAndroid Build Coastguard Worker 
~Tracing()392*288bf522SAndroid Build Coastguard Worker Tracing::~Tracing() {}
393*288bf522SAndroid Build Coastguard Worker 
Dump(size_t indent)394*288bf522SAndroid Build Coastguard Worker void Tracing::Dump(size_t indent) {
395*288bf522SAndroid Build Coastguard Worker   tracing_file_->Dump(indent);
396*288bf522SAndroid Build Coastguard Worker }
397*288bf522SAndroid Build Coastguard Worker 
GetTracingFormatHavingId(uint64_t trace_event_id)398*288bf522SAndroid Build Coastguard Worker std::optional<TracingFormat> Tracing::GetTracingFormatHavingId(uint64_t trace_event_id) {
399*288bf522SAndroid Build Coastguard Worker   if (tracing_formats_.empty()) {
400*288bf522SAndroid Build Coastguard Worker     tracing_formats_ = tracing_file_->LoadTracingFormatsFromEventFiles();
401*288bf522SAndroid Build Coastguard Worker   }
402*288bf522SAndroid Build Coastguard Worker   for (const auto& format : tracing_formats_) {
403*288bf522SAndroid Build Coastguard Worker     if (format.id == trace_event_id) {
404*288bf522SAndroid Build Coastguard Worker       return format;
405*288bf522SAndroid Build Coastguard Worker     }
406*288bf522SAndroid Build Coastguard Worker   }
407*288bf522SAndroid Build Coastguard Worker   return std::nullopt;
408*288bf522SAndroid Build Coastguard Worker }
409*288bf522SAndroid Build Coastguard Worker 
GetTracingEventNameHavingId(uint64_t trace_event_id)410*288bf522SAndroid Build Coastguard Worker std::string Tracing::GetTracingEventNameHavingId(uint64_t trace_event_id) {
411*288bf522SAndroid Build Coastguard Worker   if (tracing_formats_.empty()) {
412*288bf522SAndroid Build Coastguard Worker     tracing_formats_ = tracing_file_->LoadTracingFormatsFromEventFiles();
413*288bf522SAndroid Build Coastguard Worker   }
414*288bf522SAndroid Build Coastguard Worker   for (const auto& format : tracing_formats_) {
415*288bf522SAndroid Build Coastguard Worker     if (format.id == trace_event_id) {
416*288bf522SAndroid Build Coastguard Worker       return android::base::StringPrintf("%s:%s", format.system_name.c_str(), format.name.c_str());
417*288bf522SAndroid Build Coastguard Worker     }
418*288bf522SAndroid Build Coastguard Worker   }
419*288bf522SAndroid Build Coastguard Worker   return "";
420*288bf522SAndroid Build Coastguard Worker }
421*288bf522SAndroid Build Coastguard Worker 
GetKallsyms() const422*288bf522SAndroid Build Coastguard Worker const std::string& Tracing::GetKallsyms() const {
423*288bf522SAndroid Build Coastguard Worker   return tracing_file_->GetKallsymsFile();
424*288bf522SAndroid Build Coastguard Worker }
425*288bf522SAndroid Build Coastguard Worker 
GetPageSize() const426*288bf522SAndroid Build Coastguard Worker uint32_t Tracing::GetPageSize() const {
427*288bf522SAndroid Build Coastguard Worker   return tracing_file_->GetPageSize();
428*288bf522SAndroid Build Coastguard Worker }
429*288bf522SAndroid Build Coastguard Worker 
GetTracingData(const std::vector<const EventType * > & event_types,std::vector<char> * data)430*288bf522SAndroid Build Coastguard Worker bool GetTracingData(const std::vector<const EventType*>& event_types, std::vector<char>* data) {
431*288bf522SAndroid Build Coastguard Worker   data->clear();
432*288bf522SAndroid Build Coastguard Worker   std::vector<TraceType> trace_types;
433*288bf522SAndroid Build Coastguard Worker   for (const auto& type : event_types) {
434*288bf522SAndroid Build Coastguard Worker     CHECK_EQ(static_cast<uint32_t>(PERF_TYPE_TRACEPOINT), type->type);
435*288bf522SAndroid Build Coastguard Worker     size_t pos = type->name.find(':');
436*288bf522SAndroid Build Coastguard Worker     TraceType trace_type;
437*288bf522SAndroid Build Coastguard Worker     trace_type.system = type->name.substr(0, pos);
438*288bf522SAndroid Build Coastguard Worker     trace_type.name = type->name.substr(pos + 1);
439*288bf522SAndroid Build Coastguard Worker     trace_types.push_back(trace_type);
440*288bf522SAndroid Build Coastguard Worker   }
441*288bf522SAndroid Build Coastguard Worker   TracingFile tracing_file;
442*288bf522SAndroid Build Coastguard Worker   if (!tracing_file.RecordHeaderFiles()) {
443*288bf522SAndroid Build Coastguard Worker     return false;
444*288bf522SAndroid Build Coastguard Worker   }
445*288bf522SAndroid Build Coastguard Worker   tracing_file.RecordFtraceFiles(trace_types);
446*288bf522SAndroid Build Coastguard Worker   if (!tracing_file.RecordEventFiles(trace_types)) {
447*288bf522SAndroid Build Coastguard Worker     return false;
448*288bf522SAndroid Build Coastguard Worker   }
449*288bf522SAndroid Build Coastguard Worker   // Don't record /proc/kallsyms here, as it will be contained in
450*288bf522SAndroid Build Coastguard Worker   // KernelSymbolRecord.
451*288bf522SAndroid Build Coastguard Worker   if (!tracing_file.RecordPrintkFormatsFile()) {
452*288bf522SAndroid Build Coastguard Worker     return false;
453*288bf522SAndroid Build Coastguard Worker   }
454*288bf522SAndroid Build Coastguard Worker   *data = tracing_file.BinaryFormat();
455*288bf522SAndroid Build Coastguard Worker   return true;
456*288bf522SAndroid Build Coastguard Worker }
457*288bf522SAndroid Build Coastguard Worker 
458*288bf522SAndroid Build Coastguard Worker namespace {
459*288bf522SAndroid Build Coastguard Worker 
460*288bf522SAndroid Build Coastguard Worker // Briefly check if the filter format is acceptable by the kernel, which is described in
461*288bf522SAndroid Build Coastguard Worker // Documentation/trace/events.rst in the kernel. Also adjust quotes in string operands.
462*288bf522SAndroid Build Coastguard Worker //
463*288bf522SAndroid Build Coastguard Worker // filter := predicate_expr [logical_operator predicate_expr]*
464*288bf522SAndroid Build Coastguard Worker // predicate_expr := predicate | '!' predicate_expr | '(' filter ')'
465*288bf522SAndroid Build Coastguard Worker // predicate := field_name relational_operator value
466*288bf522SAndroid Build Coastguard Worker //
467*288bf522SAndroid Build Coastguard Worker // logical_operator := '&&' | '||'
468*288bf522SAndroid Build Coastguard Worker // relational_operator := numeric_operator | string_operator
469*288bf522SAndroid Build Coastguard Worker // numeric_operator := '==' | '!=' | '<' | '<=' | '>' | '>=' | '&'
470*288bf522SAndroid Build Coastguard Worker // string_operator := '==' | '!=' | '~'
471*288bf522SAndroid Build Coastguard Worker // value := int or string
472*288bf522SAndroid Build Coastguard Worker struct FilterFormatAdjuster {
FilterFormatAdjustersimpleperf::__anona542376e0111::FilterFormatAdjuster473*288bf522SAndroid Build Coastguard Worker   FilterFormatAdjuster(bool use_quote) : use_quote(use_quote) {}
474*288bf522SAndroid Build Coastguard Worker 
MatchFiltersimpleperf::__anona542376e0111::FilterFormatAdjuster475*288bf522SAndroid Build Coastguard Worker   bool MatchFilter(const char*& p) {
476*288bf522SAndroid Build Coastguard Worker     bool ok = MatchPredicateExpr(p);
477*288bf522SAndroid Build Coastguard Worker     while (ok && *p != '\0') {
478*288bf522SAndroid Build Coastguard Worker       RemoveSpace(p);
479*288bf522SAndroid Build Coastguard Worker       if (strncmp(p, "||", 2) == 0 || strncmp(p, "&&", 2) == 0) {
480*288bf522SAndroid Build Coastguard Worker         CopyBytes(p, 2);
481*288bf522SAndroid Build Coastguard Worker         ok = MatchPredicateExpr(p);
482*288bf522SAndroid Build Coastguard Worker       } else {
483*288bf522SAndroid Build Coastguard Worker         break;
484*288bf522SAndroid Build Coastguard Worker       }
485*288bf522SAndroid Build Coastguard Worker     }
486*288bf522SAndroid Build Coastguard Worker     RemoveSpace(p);
487*288bf522SAndroid Build Coastguard Worker     return ok;
488*288bf522SAndroid Build Coastguard Worker   }
489*288bf522SAndroid Build Coastguard Worker 
RemoveSpacesimpleperf::__anona542376e0111::FilterFormatAdjuster490*288bf522SAndroid Build Coastguard Worker   void RemoveSpace(const char*& p) {
491*288bf522SAndroid Build Coastguard Worker     size_t i = 0;
492*288bf522SAndroid Build Coastguard Worker     while (isspace(p[i])) {
493*288bf522SAndroid Build Coastguard Worker       i++;
494*288bf522SAndroid Build Coastguard Worker     }
495*288bf522SAndroid Build Coastguard Worker     if (i > 0) {
496*288bf522SAndroid Build Coastguard Worker       CopyBytes(p, i);
497*288bf522SAndroid Build Coastguard Worker     }
498*288bf522SAndroid Build Coastguard Worker   }
499*288bf522SAndroid Build Coastguard Worker 
MatchPredicateExprsimpleperf::__anona542376e0111::FilterFormatAdjuster500*288bf522SAndroid Build Coastguard Worker   bool MatchPredicateExpr(const char*& p) {
501*288bf522SAndroid Build Coastguard Worker     RemoveSpace(p);
502*288bf522SAndroid Build Coastguard Worker     if (*p == '!') {
503*288bf522SAndroid Build Coastguard Worker       CopyBytes(p, 1);
504*288bf522SAndroid Build Coastguard Worker       return MatchPredicateExpr(p);
505*288bf522SAndroid Build Coastguard Worker     }
506*288bf522SAndroid Build Coastguard Worker     if (*p == '(') {
507*288bf522SAndroid Build Coastguard Worker       CopyBytes(p, 1);
508*288bf522SAndroid Build Coastguard Worker       bool ok = MatchFilter(p);
509*288bf522SAndroid Build Coastguard Worker       if (!ok) {
510*288bf522SAndroid Build Coastguard Worker         return false;
511*288bf522SAndroid Build Coastguard Worker       }
512*288bf522SAndroid Build Coastguard Worker       RemoveSpace(p);
513*288bf522SAndroid Build Coastguard Worker       if (*p != ')') {
514*288bf522SAndroid Build Coastguard Worker         return false;
515*288bf522SAndroid Build Coastguard Worker       }
516*288bf522SAndroid Build Coastguard Worker       CopyBytes(p, 1);
517*288bf522SAndroid Build Coastguard Worker       return true;
518*288bf522SAndroid Build Coastguard Worker     }
519*288bf522SAndroid Build Coastguard Worker     return MatchPredicate(p);
520*288bf522SAndroid Build Coastguard Worker   }
521*288bf522SAndroid Build Coastguard Worker 
MatchPredicatesimpleperf::__anona542376e0111::FilterFormatAdjuster522*288bf522SAndroid Build Coastguard Worker   bool MatchPredicate(const char*& p) {
523*288bf522SAndroid Build Coastguard Worker     return MatchFieldName(p) && MatchRelationalOperator(p) && MatchValue(p);
524*288bf522SAndroid Build Coastguard Worker   }
525*288bf522SAndroid Build Coastguard Worker 
MatchFieldNamesimpleperf::__anona542376e0111::FilterFormatAdjuster526*288bf522SAndroid Build Coastguard Worker   bool MatchFieldName(const char*& p) {
527*288bf522SAndroid Build Coastguard Worker     RemoveSpace(p);
528*288bf522SAndroid Build Coastguard Worker     std::string name;
529*288bf522SAndroid Build Coastguard Worker     for (size_t i = 0; isalnum(p[i]) || p[i] == '_'; i++) {
530*288bf522SAndroid Build Coastguard Worker       name.push_back(p[i]);
531*288bf522SAndroid Build Coastguard Worker     }
532*288bf522SAndroid Build Coastguard Worker     CopyBytes(p, name.size());
533*288bf522SAndroid Build Coastguard Worker     if (name.empty()) {
534*288bf522SAndroid Build Coastguard Worker       return false;
535*288bf522SAndroid Build Coastguard Worker     }
536*288bf522SAndroid Build Coastguard Worker     used_fields.emplace(std::move(name));
537*288bf522SAndroid Build Coastguard Worker     return true;
538*288bf522SAndroid Build Coastguard Worker   }
539*288bf522SAndroid Build Coastguard Worker 
MatchRelationalOperatorsimpleperf::__anona542376e0111::FilterFormatAdjuster540*288bf522SAndroid Build Coastguard Worker   bool MatchRelationalOperator(const char*& p) {
541*288bf522SAndroid Build Coastguard Worker     RemoveSpace(p);
542*288bf522SAndroid Build Coastguard Worker     // "==", "!=", "<", "<=", ">", ">=", "&", "~"
543*288bf522SAndroid Build Coastguard Worker     if (*p == '=' || *p == '!' || *p == '<' || *p == '>') {
544*288bf522SAndroid Build Coastguard Worker       if (p[1] == '=') {
545*288bf522SAndroid Build Coastguard Worker         CopyBytes(p, 2);
546*288bf522SAndroid Build Coastguard Worker         return true;
547*288bf522SAndroid Build Coastguard Worker       }
548*288bf522SAndroid Build Coastguard Worker     }
549*288bf522SAndroid Build Coastguard Worker     if (*p == '<' || *p == '>' || *p == '&' || *p == '~') {
550*288bf522SAndroid Build Coastguard Worker       CopyBytes(p, 1);
551*288bf522SAndroid Build Coastguard Worker       return true;
552*288bf522SAndroid Build Coastguard Worker     }
553*288bf522SAndroid Build Coastguard Worker     return false;
554*288bf522SAndroid Build Coastguard Worker   }
555*288bf522SAndroid Build Coastguard Worker 
MatchValuesimpleperf::__anona542376e0111::FilterFormatAdjuster556*288bf522SAndroid Build Coastguard Worker   bool MatchValue(const char*& p) {
557*288bf522SAndroid Build Coastguard Worker     RemoveSpace(p);
558*288bf522SAndroid Build Coastguard Worker     // Match a string with quotes.
559*288bf522SAndroid Build Coastguard Worker     if (*p == '\'' || *p == '"') {
560*288bf522SAndroid Build Coastguard Worker       char quote = *p;
561*288bf522SAndroid Build Coastguard Worker       size_t len = 1;
562*288bf522SAndroid Build Coastguard Worker       while (p[len] != quote && p[len] != '\0') {
563*288bf522SAndroid Build Coastguard Worker         len++;
564*288bf522SAndroid Build Coastguard Worker       }
565*288bf522SAndroid Build Coastguard Worker       if (p[len] != quote) {
566*288bf522SAndroid Build Coastguard Worker         return false;
567*288bf522SAndroid Build Coastguard Worker       }
568*288bf522SAndroid Build Coastguard Worker       len++;
569*288bf522SAndroid Build Coastguard Worker       if (use_quote) {
570*288bf522SAndroid Build Coastguard Worker         CopyBytes(p, len);
571*288bf522SAndroid Build Coastguard Worker       } else {
572*288bf522SAndroid Build Coastguard Worker         p++;
573*288bf522SAndroid Build Coastguard Worker         CopyBytes(p, len - 2);
574*288bf522SAndroid Build Coastguard Worker         p++;
575*288bf522SAndroid Build Coastguard Worker       }
576*288bf522SAndroid Build Coastguard Worker       return true;
577*288bf522SAndroid Build Coastguard Worker     }
578*288bf522SAndroid Build Coastguard Worker     // Match an int value.
579*288bf522SAndroid Build Coastguard Worker     char* end;
580*288bf522SAndroid Build Coastguard Worker     errno = 0;
581*288bf522SAndroid Build Coastguard Worker     if (*p == '-') {
582*288bf522SAndroid Build Coastguard Worker       strtoll(p, &end, 0);
583*288bf522SAndroid Build Coastguard Worker     } else {
584*288bf522SAndroid Build Coastguard Worker       strtoull(p, &end, 0);
585*288bf522SAndroid Build Coastguard Worker     }
586*288bf522SAndroid Build Coastguard Worker     if (errno == 0 && end != p) {
587*288bf522SAndroid Build Coastguard Worker       CopyBytes(p, end - p);
588*288bf522SAndroid Build Coastguard Worker       return true;
589*288bf522SAndroid Build Coastguard Worker     }
590*288bf522SAndroid Build Coastguard Worker     // Match a string without quotes, stopping at ), &&, || or space.
591*288bf522SAndroid Build Coastguard Worker     size_t len = 0;
592*288bf522SAndroid Build Coastguard Worker     while (p[len] != '\0' && strchr(")&| \t", p[len]) == nullptr) {
593*288bf522SAndroid Build Coastguard Worker       len++;
594*288bf522SAndroid Build Coastguard Worker     }
595*288bf522SAndroid Build Coastguard Worker     if (len == 0) {
596*288bf522SAndroid Build Coastguard Worker       return false;
597*288bf522SAndroid Build Coastguard Worker     }
598*288bf522SAndroid Build Coastguard Worker     if (use_quote) {
599*288bf522SAndroid Build Coastguard Worker       adjusted_filter += '"';
600*288bf522SAndroid Build Coastguard Worker     }
601*288bf522SAndroid Build Coastguard Worker     CopyBytes(p, len);
602*288bf522SAndroid Build Coastguard Worker     if (use_quote) {
603*288bf522SAndroid Build Coastguard Worker       adjusted_filter += '"';
604*288bf522SAndroid Build Coastguard Worker     }
605*288bf522SAndroid Build Coastguard Worker     return true;
606*288bf522SAndroid Build Coastguard Worker   }
607*288bf522SAndroid Build Coastguard Worker 
CopyBytessimpleperf::__anona542376e0111::FilterFormatAdjuster608*288bf522SAndroid Build Coastguard Worker   void CopyBytes(const char*& p, size_t len) {
609*288bf522SAndroid Build Coastguard Worker     adjusted_filter.append(p, len);
610*288bf522SAndroid Build Coastguard Worker     p += len;
611*288bf522SAndroid Build Coastguard Worker   }
612*288bf522SAndroid Build Coastguard Worker 
613*288bf522SAndroid Build Coastguard Worker   const bool use_quote;
614*288bf522SAndroid Build Coastguard Worker   std::string adjusted_filter;
615*288bf522SAndroid Build Coastguard Worker   FieldNameSet used_fields;
616*288bf522SAndroid Build Coastguard Worker };
617*288bf522SAndroid Build Coastguard Worker 
618*288bf522SAndroid Build Coastguard Worker }  // namespace
619*288bf522SAndroid Build Coastguard Worker 
AdjustTracepointFilter(const std::string & filter,bool use_quote,FieldNameSet * used_fields)620*288bf522SAndroid Build Coastguard Worker std::optional<std::string> AdjustTracepointFilter(const std::string& filter, bool use_quote,
621*288bf522SAndroid Build Coastguard Worker                                                   FieldNameSet* used_fields) {
622*288bf522SAndroid Build Coastguard Worker   FilterFormatAdjuster adjuster(use_quote);
623*288bf522SAndroid Build Coastguard Worker   const char* p = filter.c_str();
624*288bf522SAndroid Build Coastguard Worker   if (!adjuster.MatchFilter(p) || *p != '\0') {
625*288bf522SAndroid Build Coastguard Worker     LOG(ERROR) << "format error in filter \"" << filter << "\" starting from \"" << p << "\"";
626*288bf522SAndroid Build Coastguard Worker     return std::nullopt;
627*288bf522SAndroid Build Coastguard Worker   }
628*288bf522SAndroid Build Coastguard Worker   *used_fields = std::move(adjuster.used_fields);
629*288bf522SAndroid Build Coastguard Worker   return std::move(adjuster.adjusted_filter);
630*288bf522SAndroid Build Coastguard Worker }
631*288bf522SAndroid Build Coastguard Worker 
GetFieldNamesForTracepointEvent(const EventType & event)632*288bf522SAndroid Build Coastguard Worker std::optional<FieldNameSet> GetFieldNamesForTracepointEvent(const EventType& event) {
633*288bf522SAndroid Build Coastguard Worker   std::vector<std::string> strs = Split(event.name, ":");
634*288bf522SAndroid Build Coastguard Worker   if (strs.size() != 2) {
635*288bf522SAndroid Build Coastguard Worker     return {};
636*288bf522SAndroid Build Coastguard Worker   }
637*288bf522SAndroid Build Coastguard Worker   std::string data;
638*288bf522SAndroid Build Coastguard Worker   if (!ReadTraceFsFile("/events/" + strs[0] + "/" + strs[1] + "/format", &data, false)) {
639*288bf522SAndroid Build Coastguard Worker     return {};
640*288bf522SAndroid Build Coastguard Worker   }
641*288bf522SAndroid Build Coastguard Worker   TracingFormat format = ParseTracingFormat(data);
642*288bf522SAndroid Build Coastguard Worker   FieldNameSet names;
643*288bf522SAndroid Build Coastguard Worker   for (auto& field : format.fields) {
644*288bf522SAndroid Build Coastguard Worker     names.emplace(std::move(field.name));
645*288bf522SAndroid Build Coastguard Worker   }
646*288bf522SAndroid Build Coastguard Worker   return names;
647*288bf522SAndroid Build Coastguard Worker }
648*288bf522SAndroid Build Coastguard Worker 
649*288bf522SAndroid Build Coastguard Worker }  // namespace simpleperf
650