• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2018 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 "src/trace_processor/trace_processor_impl.h"
18 
19 #include <algorithm>
20 #include <cinttypes>
21 #include <cstddef>
22 #include <cstdint>
23 #include <limits>
24 #include <memory>
25 #include <optional>
26 #include <string>
27 #include <unordered_map>
28 #include <utility>
29 #include <vector>
30 
31 #include "perfetto/base/build_config.h"
32 #include "perfetto/base/logging.h"
33 #include "perfetto/base/status.h"
34 #include "perfetto/base/thread_utils.h"
35 #include "perfetto/base/time.h"
36 #include "perfetto/ext/base/clock_snapshots.h"
37 #include "perfetto/ext/base/flat_hash_map.h"
38 #include "perfetto/ext/base/small_vector.h"
39 #include "perfetto/ext/base/status_or.h"
40 #include "perfetto/ext/base/string_splitter.h"
41 #include "perfetto/ext/base/string_utils.h"
42 #include "perfetto/protozero/scattered_heap_buffer.h"
43 #include "perfetto/public/compiler.h"
44 #include "perfetto/trace_processor/basic_types.h"
45 #include "perfetto/trace_processor/iterator.h"
46 #include "perfetto/trace_processor/trace_blob_view.h"
47 #include "perfetto/trace_processor/trace_processor.h"
48 #include "src/trace_processor/importers/android_bugreport/android_dumpstate_event_parser_impl.h"
49 #include "src/trace_processor/importers/android_bugreport/android_dumpstate_reader.h"
50 #include "src/trace_processor/importers/android_bugreport/android_log_event_parser_impl.h"
51 #include "src/trace_processor/importers/android_bugreport/android_log_reader.h"
52 #include "src/trace_processor/importers/archive/gzip_trace_parser.h"
53 #include "src/trace_processor/importers/archive/tar_trace_reader.h"
54 #include "src/trace_processor/importers/archive/zip_trace_reader.h"
55 #include "src/trace_processor/importers/art_method/art_method_parser_impl.h"
56 #include "src/trace_processor/importers/art_method/art_method_tokenizer.h"
57 #include "src/trace_processor/importers/common/clock_tracker.h"
58 #include "src/trace_processor/importers/common/trace_file_tracker.h"
59 #include "src/trace_processor/importers/common/trace_parser.h"
60 #include "src/trace_processor/importers/fuchsia/fuchsia_trace_parser.h"
61 #include "src/trace_processor/importers/fuchsia/fuchsia_trace_tokenizer.h"
62 #include "src/trace_processor/importers/gecko/gecko_trace_parser_impl.h"
63 #include "src/trace_processor/importers/gecko/gecko_trace_tokenizer.h"
64 #include "src/trace_processor/importers/json/json_trace_parser_impl.h"
65 #include "src/trace_processor/importers/json/json_trace_tokenizer.h"
66 #include "src/trace_processor/importers/json/json_utils.h"
67 #include "src/trace_processor/importers/ninja/ninja_log_parser.h"
68 #include "src/trace_processor/importers/perf/perf_data_tokenizer.h"
69 #include "src/trace_processor/importers/perf/perf_event.h"
70 #include "src/trace_processor/importers/perf/perf_tracker.h"
71 #include "src/trace_processor/importers/perf/record_parser.h"
72 #include "src/trace_processor/importers/perf/spe_record_parser.h"
73 #include "src/trace_processor/importers/perf_text/perf_text_trace_parser_impl.h"
74 #include "src/trace_processor/importers/perf_text/perf_text_trace_tokenizer.h"
75 #include "src/trace_processor/importers/proto/additional_modules.h"
76 #include "src/trace_processor/importers/systrace/systrace_trace_parser.h"
77 #include "src/trace_processor/iterator_impl.h"
78 #include "src/trace_processor/metrics/all_chrome_metrics.descriptor.h"
79 #include "src/trace_processor/metrics/all_webview_metrics.descriptor.h"
80 #include "src/trace_processor/metrics/metrics.descriptor.h"
81 #include "src/trace_processor/metrics/metrics.h"
82 #include "src/trace_processor/metrics/sql/amalgamated_sql_metrics.h"
83 #include "src/trace_processor/perfetto_sql/engine/perfetto_sql_engine.h"
84 #include "src/trace_processor/perfetto_sql/engine/table_pointer_module.h"
85 #include "src/trace_processor/perfetto_sql/generator/structured_query_generator.h"
86 #include "src/trace_processor/perfetto_sql/intrinsics/functions/base64.h"
87 #include "src/trace_processor/perfetto_sql/intrinsics/functions/clock_functions.h"
88 #include "src/trace_processor/perfetto_sql/intrinsics/functions/counter_intervals.h"
89 #include "src/trace_processor/perfetto_sql/intrinsics/functions/create_function.h"
90 #include "src/trace_processor/perfetto_sql/intrinsics/functions/create_view_function.h"
91 #include "src/trace_processor/perfetto_sql/intrinsics/functions/dominator_tree.h"
92 #include "src/trace_processor/perfetto_sql/intrinsics/functions/graph_scan.h"
93 #include "src/trace_processor/perfetto_sql/intrinsics/functions/graph_traversal.h"
94 #include "src/trace_processor/perfetto_sql/intrinsics/functions/import.h"
95 #include "src/trace_processor/perfetto_sql/intrinsics/functions/interval_intersect.h"
96 #include "src/trace_processor/perfetto_sql/intrinsics/functions/layout_functions.h"
97 #include "src/trace_processor/perfetto_sql/intrinsics/functions/math.h"
98 #include "src/trace_processor/perfetto_sql/intrinsics/functions/pprof_functions.h"
99 #include "src/trace_processor/perfetto_sql/intrinsics/functions/replace_numbers_function.h"
100 #include "src/trace_processor/perfetto_sql/intrinsics/functions/sqlite3_str_split.h"
101 #include "src/trace_processor/perfetto_sql/intrinsics/functions/stack_functions.h"
102 #include "src/trace_processor/perfetto_sql/intrinsics/functions/structural_tree_partition.h"
103 #include "src/trace_processor/perfetto_sql/intrinsics/functions/to_ftrace.h"
104 #include "src/trace_processor/perfetto_sql/intrinsics/functions/type_builders.h"
105 #include "src/trace_processor/perfetto_sql/intrinsics/functions/utils.h"
106 #include "src/trace_processor/perfetto_sql/intrinsics/functions/window_functions.h"
107 #include "src/trace_processor/perfetto_sql/intrinsics/operators/counter_mipmap_operator.h"
108 #include "src/trace_processor/perfetto_sql/intrinsics/operators/slice_mipmap_operator.h"
109 #include "src/trace_processor/perfetto_sql/intrinsics/operators/span_join_operator.h"
110 #include "src/trace_processor/perfetto_sql/intrinsics/operators/window_operator.h"
111 #include "src/trace_processor/perfetto_sql/intrinsics/table_functions/ancestor.h"
112 #include "src/trace_processor/perfetto_sql/intrinsics/table_functions/connected_flow.h"
113 #include "src/trace_processor/perfetto_sql/intrinsics/table_functions/descendant.h"
114 #include "src/trace_processor/perfetto_sql/intrinsics/table_functions/dfs_weight_bounded.h"
115 #include "src/trace_processor/perfetto_sql/intrinsics/table_functions/experimental_annotated_stack.h"
116 #include "src/trace_processor/perfetto_sql/intrinsics/table_functions/experimental_flamegraph.h"
117 #include "src/trace_processor/perfetto_sql/intrinsics/table_functions/experimental_flat_slice.h"
118 #include "src/trace_processor/perfetto_sql/intrinsics/table_functions/experimental_slice_layout.h"
119 #include "src/trace_processor/perfetto_sql/intrinsics/table_functions/table_info.h"
120 #include "src/trace_processor/perfetto_sql/intrinsics/table_functions/winscope_proto_to_args_with_defaults.h"
121 #include "src/trace_processor/perfetto_sql/stdlib/stdlib.h"
122 #include "src/trace_processor/sqlite/bindings/sqlite_aggregate_function.h"
123 #include "src/trace_processor/sqlite/bindings/sqlite_result.h"
124 #include "src/trace_processor/sqlite/sql_source.h"
125 #include "src/trace_processor/sqlite/sql_stats_table.h"
126 #include "src/trace_processor/sqlite/stats_table.h"
127 #include "src/trace_processor/storage/trace_storage.h"
128 #include "src/trace_processor/tp_metatrace.h"
129 #include "src/trace_processor/trace_processor_storage_impl.h"
130 #include "src/trace_processor/trace_reader_registry.h"
131 #include "src/trace_processor/trace_summary/summary.h"
132 #include "src/trace_processor/trace_summary/trace_summary.descriptor.h"
133 #include "src/trace_processor/types/trace_processor_context.h"
134 #include "src/trace_processor/util/descriptors.h"
135 #include "src/trace_processor/util/gzip_utils.h"
136 #include "src/trace_processor/util/protozero_to_json.h"
137 #include "src/trace_processor/util/protozero_to_text.h"
138 #include "src/trace_processor/util/regex.h"
139 #include "src/trace_processor/util/sql_modules.h"
140 #include "src/trace_processor/util/status_macros.h"
141 #include "src/trace_processor/util/trace_type.h"
142 
143 #include "protos/perfetto/trace/clock_snapshot.pbzero.h"
144 #include "protos/perfetto/trace/perfetto/perfetto_metatrace.pbzero.h"
145 #include "protos/perfetto/trace/trace.pbzero.h"
146 #include "protos/perfetto/trace/trace_packet.pbzero.h"
147 
148 #if PERFETTO_BUILDFLAG(PERFETTO_TP_INSTRUMENTS)
149 #include "src/trace_processor/importers/instruments/instruments_xml_tokenizer.h"
150 #include "src/trace_processor/importers/instruments/row_parser.h"
151 #endif
152 
153 #if PERFETTO_BUILDFLAG(PERFETTO_ENABLE_ETM_IMPORTER)
154 #include "src/trace_processor/importers/etm/etm_tracker.h"
155 #include "src/trace_processor/importers/etm/etm_v4_stream_demultiplexer.h"
156 #include "src/trace_processor/importers/etm/file_tracker.h"
157 #include "src/trace_processor/perfetto_sql/intrinsics/operators/etm_decode_trace_vtable.h"
158 #include "src/trace_processor/perfetto_sql/intrinsics/operators/etm_iterate_range_vtable.h"
159 #endif
160 
161 namespace perfetto::trace_processor {
162 namespace {
163 
164 template <typename SqlFunction, typename Ptr = typename SqlFunction::Context*>
RegisterFunction(PerfettoSqlEngine * engine,const char * name,int argc,Ptr context=nullptr,bool deterministic=true)165 void RegisterFunction(PerfettoSqlEngine* engine,
166                       const char* name,
167                       int argc,
168                       Ptr context = nullptr,
169                       bool deterministic = true) {
170   auto status = engine->RegisterStaticFunction<SqlFunction>(
171       name, argc, std::move(context), deterministic);
172   if (!status.ok())
173     PERFETTO_ELOG("%s", status.c_message());
174 }
175 
RegisterAllProtoBuilderFunctions(DescriptorPool * pool,std::unordered_map<std::string,std::string> * proto_fn_name_to_path,PerfettoSqlEngine * engine,TraceProcessor * tp)176 base::Status RegisterAllProtoBuilderFunctions(
177     DescriptorPool* pool,
178     std::unordered_map<std::string, std::string>* proto_fn_name_to_path,
179     PerfettoSqlEngine* engine,
180     TraceProcessor* tp) {
181   for (uint32_t i = 0; i < pool->descriptors().size(); ++i) {
182     // Convert the full name (e.g. .perfetto.protos.TraceMetrics.SubMetric)
183     // into a function name of the form (TraceMetrics_SubMetric).
184     const auto& desc = pool->descriptors()[i];
185     auto fn_name = desc.full_name().substr(desc.package_name().size() + 1);
186     std::replace(fn_name.begin(), fn_name.end(), '.', '_');
187     auto registered_fn = proto_fn_name_to_path->find(fn_name);
188     if (registered_fn != proto_fn_name_to_path->end() &&
189         registered_fn->second != desc.full_name()) {
190       return base::ErrStatus(
191           "Attempt to create new metric function '%s' for different descriptor "
192           "'%s' that conflicts with '%s'",
193           fn_name.c_str(), desc.full_name().c_str(),
194           registered_fn->second.c_str());
195     }
196     RegisterFunction<metrics::BuildProto>(
197         engine, fn_name.c_str(), -1,
198         std::make_unique<metrics::BuildProto::Context>(
199             metrics::BuildProto::Context{tp, pool, i}));
200     proto_fn_name_to_path->emplace(fn_name, desc.full_name());
201   }
202   return base::OkStatus();
203 }
204 
BuildBoundsTable(sqlite3 * db,std::pair<int64_t,int64_t> bounds)205 void BuildBoundsTable(sqlite3* db, std::pair<int64_t, int64_t> bounds) {
206   char* error = nullptr;
207   sqlite3_exec(db, "DELETE FROM _trace_bounds", nullptr, nullptr, &error);
208   if (error) {
209     PERFETTO_ELOG("Error deleting from bounds table: %s", error);
210     sqlite3_free(error);
211     return;
212   }
213 
214   base::StackString<1024> sql("INSERT INTO _trace_bounds VALUES(%" PRId64
215                               ", %" PRId64 ")",
216                               bounds.first, bounds.second);
217   sqlite3_exec(db, sql.c_str(), nullptr, nullptr, &error);
218   if (error) {
219     PERFETTO_ELOG("Error inserting bounds table: %s", error);
220     sqlite3_free(error);
221   }
222 }
223 
224 class ValueAtMaxTs : public SqliteAggregateFunction<ValueAtMaxTs> {
225  public:
226   static constexpr char kName[] = "VALUE_AT_MAX_TS";
227   static constexpr int kArgCount = 2;
228   struct Context {
229     bool initialized;
230     int value_type;
231 
232     int64_t max_ts;
233     int64_t int_value_at_max_ts;
234     double double_value_at_max_ts;
235   };
236 
Step(sqlite3_context * ctx,int,sqlite3_value ** argv)237   static void Step(sqlite3_context* ctx, int, sqlite3_value** argv) {
238     sqlite3_value* ts = argv[0];
239     sqlite3_value* value = argv[1];
240 
241     // Note that sqlite3_aggregate_context zeros the memory for us so all the
242     // variables of the struct should be zero.
243     auto* fn_ctx = reinterpret_cast<Context*>(
244         sqlite3_aggregate_context(ctx, sizeof(Context)));
245 
246     // For performance reasons, we only do the check for the type of ts and
247     // value on the first call of the function.
248     if (PERFETTO_UNLIKELY(!fn_ctx->initialized)) {
249       if (sqlite3_value_type(ts) != SQLITE_INTEGER) {
250         return sqlite::result::Error(
251             ctx, "VALUE_AT_MAX_TS: ts passed was not an integer");
252       }
253 
254       fn_ctx->value_type = sqlite3_value_type(value);
255       if (fn_ctx->value_type != SQLITE_INTEGER &&
256           fn_ctx->value_type != SQLITE_FLOAT) {
257         return sqlite::result::Error(
258             ctx, "VALUE_AT_MAX_TS: value passed was not an integer or float");
259       }
260 
261       fn_ctx->max_ts = std::numeric_limits<int64_t>::min();
262       fn_ctx->initialized = true;
263     }
264 
265     // On dcheck builds however, we check every passed ts and value.
266 #if PERFETTO_DCHECK_IS_ON()
267     if (sqlite3_value_type(ts) != SQLITE_INTEGER) {
268       return sqlite::result::Error(
269           ctx, "VALUE_AT_MAX_TS: ts passed was not an integer");
270     }
271     if (sqlite3_value_type(value) != fn_ctx->value_type) {
272       return sqlite::result::Error(
273           ctx, "VALUE_AT_MAX_TS: value type is inconsistent");
274     }
275 #endif
276 
277     int64_t ts_int = sqlite3_value_int64(ts);
278     if (PERFETTO_LIKELY(fn_ctx->max_ts <= ts_int)) {
279       fn_ctx->max_ts = ts_int;
280 
281       if (fn_ctx->value_type == SQLITE_INTEGER) {
282         fn_ctx->int_value_at_max_ts = sqlite3_value_int64(value);
283       } else {
284         fn_ctx->double_value_at_max_ts = sqlite3_value_double(value);
285       }
286     }
287   }
288 
Final(sqlite3_context * ctx)289   static void Final(sqlite3_context* ctx) {
290     auto* fn_ctx = static_cast<Context*>(sqlite3_aggregate_context(ctx, 0));
291     if (!fn_ctx) {
292       sqlite::result::Null(ctx);
293       return;
294     }
295     if (fn_ctx->value_type == SQLITE_INTEGER) {
296       sqlite::result::Long(ctx, fn_ctx->int_value_at_max_ts);
297     } else {
298       sqlite::result::Double(ctx, fn_ctx->double_value_at_max_ts);
299     }
300   }
301 };
302 
RegisterValueAtMaxTsFunction(PerfettoSqlEngine & engine)303 void RegisterValueAtMaxTsFunction(PerfettoSqlEngine& engine) {
304   base::Status status =
305       engine.RegisterSqliteAggregateFunction<ValueAtMaxTs>(nullptr);
306   if (!status.ok()) {
307     PERFETTO_ELOG("Error initializing VALUE_AT_MAX_TS");
308   }
309 }
310 
SanitizeMetricMountPaths(const std::vector<std::string> & mount_paths)311 std::vector<std::string> SanitizeMetricMountPaths(
312     const std::vector<std::string>& mount_paths) {
313   std::vector<std::string> sanitized;
314   for (const auto& path : mount_paths) {
315     if (path.empty())
316       continue;
317     sanitized.push_back(path);
318     if (path.back() != '/')
319       sanitized.back().append("/");
320   }
321   return sanitized;
322 }
323 
InsertIntoTraceMetricsTable(sqlite3 * db,const std::string & metric_name)324 void InsertIntoTraceMetricsTable(sqlite3* db, const std::string& metric_name) {
325   char* insert_sql = sqlite3_mprintf(
326       "INSERT INTO _trace_metrics(name) VALUES('%q')", metric_name.c_str());
327   char* insert_error = nullptr;
328   sqlite3_exec(db, insert_sql, nullptr, nullptr, &insert_error);
329   sqlite3_free(insert_sql);
330   if (insert_error) {
331     PERFETTO_ELOG("Error registering table: %s", insert_error);
332     sqlite3_free(insert_error);
333   }
334 }
335 
GetStdlibPackages()336 sql_modules::NameToPackage GetStdlibPackages() {
337   sql_modules::NameToPackage packages;
338   for (const auto& file_to_sql : stdlib::kFileToSql) {
339     std::string module_name = sql_modules::GetIncludeKey(file_to_sql.path);
340     std::string package_name = sql_modules::GetPackageName(module_name);
341     packages.Insert(package_name, {})
342         .first->push_back({module_name, file_to_sql.sql});
343   }
344   return packages;
345 }
346 
GetTraceTimestampBoundsNs(const TraceStorage & storage)347 std::pair<int64_t, int64_t> GetTraceTimestampBoundsNs(
348     const TraceStorage& storage) {
349   int64_t start_ns = std::numeric_limits<int64_t>::max();
350   int64_t end_ns = std::numeric_limits<int64_t>::min();
351   for (auto it = storage.ftrace_event_table().IterateRows(); it; ++it) {
352     start_ns = std::min(it.ts(), start_ns);
353     end_ns = std::max(it.ts(), end_ns);
354   }
355   for (auto it = storage.sched_slice_table().IterateRows(); it; ++it) {
356     start_ns = std::min(it.ts(), start_ns);
357     end_ns = std::max(it.ts() + it.dur(), end_ns);
358   }
359   for (auto it = storage.counter_table().IterateRows(); it; ++it) {
360     start_ns = std::min(it.ts(), start_ns);
361     end_ns = std::max(it.ts(), end_ns);
362   }
363   for (auto it = storage.slice_table().IterateRows(); it; ++it) {
364     start_ns = std::min(it.ts(), start_ns);
365     end_ns = std::max(it.ts() + it.dur(), end_ns);
366   }
367   for (auto it = storage.heap_profile_allocation_table().IterateRows(); it;
368        ++it) {
369     start_ns = std::min(it.ts(), start_ns);
370     end_ns = std::max(it.ts(), end_ns);
371   }
372   for (auto it = storage.thread_state_table().IterateRows(); it; ++it) {
373     start_ns = std::min(it.ts(), start_ns);
374     end_ns = std::max(it.ts() + it.dur(), end_ns);
375   }
376   for (auto it = storage.android_log_table().IterateRows(); it; ++it) {
377     start_ns = std::min(it.ts(), start_ns);
378     end_ns = std::max(it.ts(), end_ns);
379   }
380   for (auto it = storage.heap_graph_object_table().IterateRows(); it; ++it) {
381     start_ns = std::min(it.graph_sample_ts(), start_ns);
382     end_ns = std::max(it.graph_sample_ts(), end_ns);
383   }
384   for (auto it = storage.perf_sample_table().IterateRows(); it; ++it) {
385     start_ns = std::min(it.ts(), start_ns);
386     end_ns = std::max(it.ts(), end_ns);
387   }
388   for (auto it = storage.instruments_sample_table().IterateRows(); it; ++it) {
389     start_ns = std::min(it.ts(), start_ns);
390     end_ns = std::max(it.ts(), end_ns);
391   }
392   for (auto it = storage.cpu_profile_stack_sample_table().IterateRows(); it;
393        ++it) {
394     start_ns = std::min(it.ts(), start_ns);
395     end_ns = std::max(it.ts(), end_ns);
396   }
397   if (start_ns == std::numeric_limits<int64_t>::max()) {
398     return std::make_pair(0, 0);
399   }
400   if (start_ns == end_ns) {
401     end_ns += 1;
402   }
403   return std::make_pair(start_ns, end_ns);
404 }
405 
406 }  // namespace
407 
TraceProcessorImpl(const Config & cfg)408 TraceProcessorImpl::TraceProcessorImpl(const Config& cfg)
409     : TraceProcessorStorageImpl(cfg), config_(cfg) {
410   context_.reader_registry->RegisterTraceReader<AndroidDumpstateReader>(
411       kAndroidDumpstateTraceType);
412   context_.android_dumpstate_event_parser =
413       std::make_unique<AndroidDumpstateEventParserImpl>(&context_);
414 
415   context_.reader_registry->RegisterTraceReader<AndroidLogReader>(
416       kAndroidLogcatTraceType);
417   context_.android_log_event_parser =
418       std::make_unique<AndroidLogEventParserImpl>(&context_);
419 
420   context_.reader_registry->RegisterTraceReader<FuchsiaTraceTokenizer>(
421       kFuchsiaTraceType);
422   context_.fuchsia_record_parser =
423       std::make_unique<FuchsiaTraceParser>(&context_);
424 
425   context_.reader_registry->RegisterTraceReader<SystraceTraceParser>(
426       kSystraceTraceType);
427   context_.reader_registry->RegisterTraceReader<NinjaLogParser>(
428       kNinjaLogTraceType);
429 
430   context_.reader_registry
431       ->RegisterTraceReader<perf_importer::PerfDataTokenizer>(
432           kPerfDataTraceType);
433   context_.perf_record_parser =
434       std::make_unique<perf_importer::RecordParser>(&context_);
435   context_.spe_record_parser =
436       std::make_unique<perf_importer::SpeRecordParserImpl>(&context_);
437 
438 #if PERFETTO_BUILDFLAG(PERFETTO_TP_INSTRUMENTS)
439   context_.reader_registry
440       ->RegisterTraceReader<instruments_importer::InstrumentsXmlTokenizer>(
441           kInstrumentsXmlTraceType);
442   context_.instruments_row_parser =
443       std::make_unique<instruments_importer::RowParser>(&context_);
444 #endif
445 
446   if constexpr (util::IsGzipSupported()) {
447     context_.reader_registry->RegisterTraceReader<GzipTraceParser>(
448         kGzipTraceType);
449     context_.reader_registry->RegisterTraceReader<GzipTraceParser>(
450         kCtraceTraceType);
451     context_.reader_registry->RegisterTraceReader<ZipTraceReader>(kZipFile);
452   }
453 
454   if constexpr (json::IsJsonSupported()) {
455     context_.reader_registry->RegisterTraceReader<JsonTraceTokenizer>(
456         kJsonTraceType);
457     context_.json_trace_parser =
458         std::make_unique<JsonTraceParserImpl>(&context_);
459 
460     context_.reader_registry
461         ->RegisterTraceReader<gecko_importer::GeckoTraceTokenizer>(
462             kGeckoTraceType);
463     context_.gecko_trace_parser =
464         std::make_unique<gecko_importer::GeckoTraceParserImpl>(&context_);
465   }
466 
467   context_.reader_registry->RegisterTraceReader<art_method::ArtMethodTokenizer>(
468       kArtMethodTraceType);
469   context_.art_method_parser =
470       std::make_unique<art_method::ArtMethodParserImpl>(&context_);
471 
472   context_.reader_registry
473       ->RegisterTraceReader<perf_text_importer::PerfTextTraceTokenizer>(
474           kPerfTextTraceType);
475   context_.perf_text_parser =
476       std::make_unique<perf_text_importer::PerfTextTraceParserImpl>(&context_);
477 
478   context_.reader_registry->RegisterTraceReader<TarTraceReader>(kTarTraceType);
479 
480 #if PERFETTO_BUILDFLAG(PERFETTO_ENABLE_ETM_IMPORTER)
481   perf_importer::PerfTracker::GetOrCreate(&context_)->RegisterAuxTokenizer(
482       PERF_AUXTRACE_CS_ETM, etm::CreateEtmV4StreamDemultiplexer);
483 #endif
484 
485   const std::vector<std::string> sanitized_extension_paths =
486       SanitizeMetricMountPaths(config_.skip_builtin_metric_paths);
487   std::vector<std::string> skip_prefixes;
488   skip_prefixes.reserve(sanitized_extension_paths.size());
489   for (const auto& path : sanitized_extension_paths) {
490     skip_prefixes.push_back(kMetricProtoRoot + path);
491   }
492 
493   // Add metrics to descriptor pool
494   metrics_descriptor_pool_.AddFromFileDescriptorSet(
495       kMetricsDescriptor.data(), kMetricsDescriptor.size(), skip_prefixes);
496   metrics_descriptor_pool_.AddFromFileDescriptorSet(
497       kAllChromeMetricsDescriptor.data(), kAllChromeMetricsDescriptor.size(),
498       skip_prefixes);
499   metrics_descriptor_pool_.AddFromFileDescriptorSet(
500       kAllWebviewMetricsDescriptor.data(), kAllWebviewMetricsDescriptor.size(),
501       skip_prefixes);
502 
503   // Add the summary descriptor to the summary pool.
504   {
505     base::Status status = context_.descriptor_pool_->AddFromFileDescriptorSet(
506         kTraceSummaryDescriptor.data(), kTraceSummaryDescriptor.size());
507     PERFETTO_CHECK(status.ok());
508   }
509 
510   RegisterAdditionalModules(&context_);
511   InitPerfettoSqlEngine();
512 
513   sqlite_objects_post_prelude_ = engine_->SqliteRegisteredObjectCount();
514 
515   bool skip_all_sql = std::find(config_.skip_builtin_metric_paths.begin(),
516                                 config_.skip_builtin_metric_paths.end(),
517                                 "") != config_.skip_builtin_metric_paths.end();
518   if (!skip_all_sql) {
519     for (const auto& file_to_sql : sql_metrics::kFileToSql) {
520       if (base::StartsWithAny(file_to_sql.path, sanitized_extension_paths))
521         continue;
522       RegisterMetric(file_to_sql.path, file_to_sql.sql);
523     }
524   }
525 }
526 
527 TraceProcessorImpl::~TraceProcessorImpl() = default;
528 
529 // =================================================================
530 // |        TraceProcessorStorage implementation starts here       |
531 // =================================================================
532 
Parse(TraceBlobView blob)533 base::Status TraceProcessorImpl::Parse(TraceBlobView blob) {
534   bytes_parsed_ += blob.size();
535   return TraceProcessorStorageImpl::Parse(std::move(blob));
536 }
537 
Flush()538 void TraceProcessorImpl::Flush() {
539   TraceProcessorStorageImpl::Flush();
540   BuildBoundsTable(engine_->sqlite_engine()->db(),
541                    GetTraceTimestampBoundsNs(*context_.storage));
542 }
543 
NotifyEndOfFile()544 base::Status TraceProcessorImpl::NotifyEndOfFile() {
545   if (notify_eof_called_) {
546     const char kMessage[] =
547         "NotifyEndOfFile should only be called once. Try calling Flush instead "
548         "if trying to commit the contents of the trace to tables.";
549     PERFETTO_ELOG(kMessage);
550     return base::ErrStatus(kMessage);
551   }
552   notify_eof_called_ = true;
553 
554   if (current_trace_name_.empty())
555     current_trace_name_ = "Unnamed trace";
556 
557   // Last opportunity to flush all pending data.
558   Flush();
559 
560 #if PERFETTO_BUILDFLAG(PERFETTO_ENABLE_ETM_IMPORTER)
561   if (context_.etm_tracker) {
562     RETURN_IF_ERROR(etm::EtmTracker::GetOrCreate(&context_)->Finalize());
563   }
564 #endif
565 
566   RETURN_IF_ERROR(TraceProcessorStorageImpl::NotifyEndOfFile());
567   if (context_.perf_tracker) {
568     perf_importer::PerfTracker::GetOrCreate(&context_)->NotifyEndOfFile();
569   }
570   context_.storage->ShrinkToFitTables();
571 
572   // Rebuild the bounds table once everything has been completed: we do this
573   // so that if any data was added to tables in
574   // TraceProcessorStorageImpl::NotifyEndOfFile, this will be counted in
575   // trace bounds: this is important for parsers like ninja which wait until
576   // the end to flush all their data.
577   BuildBoundsTable(engine_->sqlite_engine()->db(),
578                    GetTraceTimestampBoundsNs(*context_.storage));
579 
580   TraceProcessorStorageImpl::DestroyContext();
581 
582   IncludeAfterEofPrelude();
583   sqlite_objects_post_prelude_ = engine_->SqliteRegisteredObjectCount();
584   return base::OkStatus();
585 }
586 
587 // =================================================================
588 // |        PerfettoSQL related functionality starts here          |
589 // =================================================================
590 
ExecuteQuery(const std::string & sql)591 Iterator TraceProcessorImpl::ExecuteQuery(const std::string& sql) {
592   PERFETTO_TP_TRACE(metatrace::Category::API_TIMELINE, "EXECUTE_QUERY",
593                     [&](metatrace::Record* r) { r->AddArg("query", sql); });
594 
595   uint32_t sql_stats_row =
596       context_.storage->mutable_sql_stats()->RecordQueryBegin(
597           sql, base::GetWallTimeNs().count());
598   std::string non_breaking_sql = base::ReplaceAll(sql, "\u00A0", " ");
599   base::StatusOr<PerfettoSqlEngine::ExecutionResult> result =
600       engine_->ExecuteUntilLastStatement(
601           SqlSource::FromExecuteQuery(std::move(non_breaking_sql)));
602   std::unique_ptr<IteratorImpl> impl(
603       new IteratorImpl(this, std::move(result), sql_stats_row));
604   return Iterator(std::move(impl));
605 }
606 
RegisterSqlPackage(SqlPackage sql_package)607 base::Status TraceProcessorImpl::RegisterSqlPackage(SqlPackage sql_package) {
608   sql_modules::RegisteredPackage new_package;
609   std::string name = sql_package.name;
610   if (engine_->FindPackage(name) && !sql_package.allow_override) {
611     return base::ErrStatus(
612         "Package '%s' is already registered. Choose a different name.\n"
613         "If you want to replace the existing package using trace processor "
614         "shell, you need to pass the --dev flag and use "
615         "--override-sql-module "
616         "to pass the module path.",
617         name.c_str());
618   }
619   for (auto const& module_name_and_sql : sql_package.modules) {
620     if (sql_modules::GetPackageName(module_name_and_sql.first) != name) {
621       return base::ErrStatus(
622           "Module name doesn't match the package name. First part of module "
623           "name should be package name. Import key: '%s', package name: '%s'.",
624           module_name_and_sql.first.c_str(), name.c_str());
625     }
626     new_package.modules.Insert(module_name_and_sql.first,
627                                {module_name_and_sql.second, false});
628   }
629   manually_registered_sql_packages_.push_back(SqlPackage(sql_package));
630   engine_->RegisterPackage(name, std::move(new_package));
631   return base::OkStatus();
632 }
633 
RegisterSqlModule(SqlModule module)634 base::Status TraceProcessorImpl::RegisterSqlModule(SqlModule module) {
635   SqlPackage package;
636   package.name = std::move(module.name);
637   package.modules = std::move(module.files);
638   package.allow_override = module.allow_module_override;
639   return RegisterSqlPackage(package);
640 }
641 
642 // =================================================================
643 // |  Trace-based metrics (v2) related functionality starts here   |
644 // =================================================================
645 
Summarize(const TraceSummaryComputationSpec & computation,const std::vector<TraceSummarySpecBytes> & specs,std::vector<uint8_t> * output,const TraceSummaryOutputSpec & output_spec)646 base::Status TraceProcessorImpl::Summarize(
647     const TraceSummaryComputationSpec& computation,
648     const std::vector<TraceSummarySpecBytes>& specs,
649     std::vector<uint8_t>* output,
650     const TraceSummaryOutputSpec& output_spec) {
651   return summary::Summarize(this, *context_.descriptor_pool_, computation,
652                             specs, output, output_spec);
653 }
654 
655 // =================================================================
656 // |        Metatracing related functionality starts here          |
657 // =================================================================
658 
EnableMetatrace(MetatraceConfig config)659 void TraceProcessorImpl::EnableMetatrace(MetatraceConfig config) {
660   metatrace::Enable(config);
661 }
662 
663 // =================================================================
664 // |                      Experimental                             |
665 // =================================================================
666 
AnalyzeStructuredQueries(const std::vector<StructuredQueryBytes> & sqs,std::vector<AnalyzedStructuredQuery> * output)667 base::Status TraceProcessorImpl::AnalyzeStructuredQueries(
668     const std::vector<StructuredQueryBytes>& sqs,
669     std::vector<AnalyzedStructuredQuery>* output) {
670   auto opt_idx = metrics_descriptor_pool_.FindDescriptorIdx(
671       ".perfetto.protos.TraceSummarySpec");
672   if (!opt_idx) {
673     metrics_descriptor_pool_.AddFromFileDescriptorSet(
674         kTraceSummaryDescriptor.data(), kTraceSummaryDescriptor.size());
675   }
676   perfetto_sql::generator::StructuredQueryGenerator sqg;
677   for (const auto& sq : sqs) {
678     AnalyzedStructuredQuery analyzed_sq;
679     ASSIGN_OR_RETURN(analyzed_sq.sql, sqg.Generate(sq.ptr, sq.size));
680     analyzed_sq.textproto =
681         perfetto::trace_processor::protozero_to_text::ProtozeroToText(
682             metrics_descriptor_pool_,
683             ".perfetto.protos.PerfettoSqlStructuredQuery",
684             protozero::ConstBytes{sq.ptr, sq.size},
685             perfetto::trace_processor::protozero_to_text::kIncludeNewLines);
686     analyzed_sq.modules = sqg.ComputeReferencedModules();
687     analyzed_sq.preambles = sqg.ComputePreambles();
688     sqg.AddQuery(sq.ptr, sq.size);
689     output->push_back(analyzed_sq);
690   }
691   return base::OkStatus();
692 }
693 
694 namespace {
695 
696 class StringInterner {
697  public:
StringInterner(protos::pbzero::PerfettoMetatrace & event,base::FlatHashMap<std::string,uint64_t> & interned_strings)698   StringInterner(protos::pbzero::PerfettoMetatrace& event,
699                  base::FlatHashMap<std::string, uint64_t>& interned_strings)
700       : event_(event), interned_strings_(interned_strings) {}
701 
~StringInterner()702   ~StringInterner() {
703     for (const auto& interned_string : new_interned_strings_) {
704       auto* interned_string_proto = event_.add_interned_strings();
705       interned_string_proto->set_iid(interned_string.first);
706       interned_string_proto->set_value(interned_string.second);
707     }
708   }
709 
InternString(const std::string & str)710   uint64_t InternString(const std::string& str) {
711     uint64_t new_iid = interned_strings_.size();
712     auto insert_result = interned_strings_.Insert(str, new_iid);
713     if (insert_result.second) {
714       new_interned_strings_.emplace_back(new_iid, str);
715     }
716     return *insert_result.first;
717   }
718 
719  private:
720   protos::pbzero::PerfettoMetatrace& event_;
721   base::FlatHashMap<std::string, uint64_t>& interned_strings_;
722 
723   base::SmallVector<std::pair<uint64_t, std::string>, 16> new_interned_strings_;
724 };
725 
726 }  // namespace
727 
DisableAndReadMetatrace(std::vector<uint8_t> * trace_proto)728 base::Status TraceProcessorImpl::DisableAndReadMetatrace(
729     std::vector<uint8_t>* trace_proto) {
730   protozero::HeapBuffered<protos::pbzero::Trace> trace;
731 
732   auto* clock_snapshot = trace->add_packet()->set_clock_snapshot();
733   for (const auto& [clock_id, ts] : base::CaptureClockSnapshots()) {
734     auto* clock = clock_snapshot->add_clocks();
735     clock->set_clock_id(clock_id);
736     clock->set_timestamp(ts);
737   }
738 
739   auto tid = static_cast<uint32_t>(base::GetThreadId());
740   base::FlatHashMap<std::string, uint64_t> interned_strings;
741   metatrace::DisableAndReadBuffer(
742       [&trace, &interned_strings, tid](metatrace::Record* record) {
743         auto* packet = trace->add_packet();
744         packet->set_timestamp(record->timestamp_ns);
745         auto* evt = packet->set_perfetto_metatrace();
746 
747         StringInterner interner(*evt, interned_strings);
748 
749         evt->set_event_name_iid(interner.InternString(record->event_name));
750         evt->set_event_duration_ns(record->duration_ns);
751         evt->set_thread_id(tid);
752 
753         if (record->args_buffer_size == 0)
754           return;
755 
756         base::StringSplitter s(
757             record->args_buffer, record->args_buffer_size, '\0',
758             base::StringSplitter::EmptyTokenMode::ALLOW_EMPTY_TOKENS);
759         for (; s.Next();) {
760           auto* arg_proto = evt->add_args();
761           arg_proto->set_key_iid(interner.InternString(s.cur_token()));
762 
763           bool has_next = s.Next();
764           PERFETTO_CHECK(has_next);
765           arg_proto->set_value_iid(interner.InternString(s.cur_token()));
766         }
767       });
768   *trace_proto = trace.SerializeAsArray();
769   return base::OkStatus();
770 }
771 
772 // =================================================================
773 // |              Advanced functionality starts here               |
774 // =================================================================
775 
GetCurrentTraceName()776 std::string TraceProcessorImpl::GetCurrentTraceName() {
777   if (current_trace_name_.empty())
778     return "";
779   auto size = " (" + std::to_string(bytes_parsed_ / 1024 / 1024) + " MB)";
780   return current_trace_name_ + size;
781 }
782 
SetCurrentTraceName(const std::string & name)783 void TraceProcessorImpl::SetCurrentTraceName(const std::string& name) {
784   current_trace_name_ = name;
785 }
786 
RegisterFileContent(const std::string & path,TraceBlobView content)787 base::Status TraceProcessorImpl::RegisterFileContent(
788     [[maybe_unused]] const std::string& path,
789     [[maybe_unused]] TraceBlobView content) {
790 #if PERFETTO_BUILDFLAG(PERFETTO_ENABLE_ETM_IMPORTER)
791   return etm::FileTracker::GetOrCreate(&context_)->AddFile(path,
792                                                            std::move(content));
793 #else
794   return base::OkStatus();
795 #endif
796 }
797 
InterruptQuery()798 void TraceProcessorImpl::InterruptQuery() {
799   if (!engine_->sqlite_engine()->db())
800     return;
801   query_interrupted_.store(true);
802   sqlite3_interrupt(engine_->sqlite_engine()->db());
803 }
804 
RestoreInitialTables()805 size_t TraceProcessorImpl::RestoreInitialTables() {
806   // We should always have at least as many objects now as we did in the
807   // constructor.
808   uint64_t registered_count_before = engine_->SqliteRegisteredObjectCount();
809   PERFETTO_CHECK(registered_count_before >= sqlite_objects_post_prelude_);
810 
811   InitPerfettoSqlEngine();
812 
813   // The registered count should now be the same as it was in the constructor.
814   uint64_t registered_count_after = engine_->SqliteRegisteredObjectCount();
815   PERFETTO_CHECK(registered_count_after == sqlite_objects_post_prelude_);
816   return static_cast<size_t>(registered_count_before - registered_count_after);
817 }
818 
819 // =================================================================
820 // |  Trace-based metrics (v1) related functionality starts here   |
821 // =================================================================
822 
RegisterMetric(const std::string & path,const std::string & sql)823 base::Status TraceProcessorImpl::RegisterMetric(const std::string& path,
824                                                 const std::string& sql) {
825   // Check if the metric with the given path already exists and if it does,
826   // just update the SQL associated with it.
827   auto it = std::find_if(
828       sql_metrics_.begin(), sql_metrics_.end(),
829       [&path](const metrics::SqlMetricFile& m) { return m.path == path; });
830   if (it != sql_metrics_.end()) {
831     it->sql = sql;
832     return base::OkStatus();
833   }
834 
835   auto sep_idx = path.rfind('/');
836   std::string basename =
837       sep_idx == std::string::npos ? path : path.substr(sep_idx + 1);
838 
839   auto sql_idx = basename.rfind(".sql");
840   if (sql_idx == std::string::npos) {
841     return base::ErrStatus("Unable to find .sql extension for metric");
842   }
843   auto no_ext_name = basename.substr(0, sql_idx);
844 
845   metrics::SqlMetricFile metric;
846   metric.path = path;
847   metric.sql = sql;
848 
849   if (IsRootMetricField(no_ext_name)) {
850     metric.proto_field_name = no_ext_name;
851     metric.output_table_name = no_ext_name + "_output";
852 
853     auto field_it_and_inserted =
854         proto_field_to_sql_metric_path_.emplace(*metric.proto_field_name, path);
855     if (!field_it_and_inserted.second) {
856       // We already had a metric with this field name in the map. However, if
857       // this was the case, we should have found the metric in
858       // |path_to_sql_metric_file_| above if we are simply overriding the
859       // metric. Return an error since this means we have two different SQL
860       // files which are trying to output the same metric.
861       const auto& prev_path = field_it_and_inserted.first->second;
862       PERFETTO_DCHECK(prev_path != path);
863       return base::ErrStatus(
864           "RegisterMetric Error: Metric paths %s (which is already "
865           "registered) "
866           "and %s are both trying to output the proto field %s",
867           prev_path.c_str(), path.c_str(), metric.proto_field_name->c_str());
868     }
869   }
870 
871   if (metric.proto_field_name) {
872     InsertIntoTraceMetricsTable(engine_->sqlite_engine()->db(),
873                                 *metric.proto_field_name);
874   }
875   sql_metrics_.emplace_back(metric);
876   return base::OkStatus();
877 }
878 
ExtendMetricsProto(const uint8_t * data,size_t size)879 base::Status TraceProcessorImpl::ExtendMetricsProto(const uint8_t* data,
880                                                     size_t size) {
881   return ExtendMetricsProto(data, size, /*skip_prefixes*/ {});
882 }
883 
ExtendMetricsProto(const uint8_t * data,size_t size,const std::vector<std::string> & skip_prefixes)884 base::Status TraceProcessorImpl::ExtendMetricsProto(
885     const uint8_t* data,
886     size_t size,
887     const std::vector<std::string>& skip_prefixes) {
888   RETURN_IF_ERROR(metrics_descriptor_pool_.AddFromFileDescriptorSet(
889       data, size, skip_prefixes));
890   RETURN_IF_ERROR(RegisterAllProtoBuilderFunctions(
891       &metrics_descriptor_pool_, &proto_fn_name_to_path_, engine_.get(), this));
892   return base::OkStatus();
893 }
894 
ComputeMetric(const std::vector<std::string> & metric_names,std::vector<uint8_t> * metrics_proto)895 base::Status TraceProcessorImpl::ComputeMetric(
896     const std::vector<std::string>& metric_names,
897     std::vector<uint8_t>* metrics_proto) {
898   auto opt_idx = metrics_descriptor_pool_.FindDescriptorIdx(
899       ".perfetto.protos.TraceMetrics");
900   if (!opt_idx.has_value())
901     return base::Status("Root metrics proto descriptor not found");
902 
903   const auto& root_descriptor =
904       metrics_descriptor_pool_.descriptors()[opt_idx.value()];
905   return metrics::ComputeMetrics(engine_.get(), metric_names, sql_metrics_,
906                                  metrics_descriptor_pool_, root_descriptor,
907                                  metrics_proto);
908 }
909 
ComputeMetricText(const std::vector<std::string> & metric_names,TraceProcessor::MetricResultFormat format,std::string * metrics_string)910 base::Status TraceProcessorImpl::ComputeMetricText(
911     const std::vector<std::string>& metric_names,
912     TraceProcessor::MetricResultFormat format,
913     std::string* metrics_string) {
914   std::vector<uint8_t> metrics_proto;
915   base::Status status = ComputeMetric(metric_names, &metrics_proto);
916   if (!status.ok())
917     return status;
918   switch (format) {
919     case TraceProcessor::MetricResultFormat::kProtoText:
920       *metrics_string = protozero_to_text::ProtozeroToText(
921           metrics_descriptor_pool_, ".perfetto.protos.TraceMetrics",
922           protozero::ConstBytes{metrics_proto.data(), metrics_proto.size()},
923           protozero_to_text::kIncludeNewLines);
924       break;
925     case TraceProcessor::MetricResultFormat::kJson:
926       *metrics_string = protozero_to_json::ProtozeroToJson(
927           metrics_descriptor_pool_, ".perfetto.protos.TraceMetrics",
928           protozero::ConstBytes{metrics_proto.data(), metrics_proto.size()},
929           protozero_to_json::kPretty | protozero_to_json::kInlineErrors |
930               protozero_to_json::kInlineAnnotations);
931       break;
932   }
933   return status;
934 }
935 
GetMetricDescriptors()936 std::vector<uint8_t> TraceProcessorImpl::GetMetricDescriptors() {
937   return metrics_descriptor_pool_.SerializeAsDescriptorSet();
938 }
939 
InitPerfettoSqlEngine()940 void TraceProcessorImpl::InitPerfettoSqlEngine() {
941   engine_ = std::make_unique<PerfettoSqlEngine>(
942       context_.storage->mutable_string_pool(), config_.enable_extra_checks);
943   sqlite3* db = engine_->sqlite_engine()->db();
944   sqlite3_str_split_init(db);
945 
946   // Register SQL functions only used in local development instances.
947   if (config_.enable_dev_features) {
948     RegisterFunction<WriteFile>(engine_.get(), "WRITE_FILE", 2);
949   }
950   RegisterFunction<Glob>(engine_.get(), "glob", 2);
951   RegisterFunction<Hash>(engine_.get(), "HASH", -1);
952   RegisterFunction<Base64Encode>(engine_.get(), "BASE64_ENCODE", 1);
953   RegisterFunction<Demangle>(engine_.get(), "DEMANGLE", 1);
954   RegisterFunction<SourceGeq>(engine_.get(), "SOURCE_GEQ", -1);
955   RegisterFunction<TablePtrBind>(engine_.get(), "__intrinsic_table_ptr_bind",
956                                  -1);
957   RegisterFunction<ExportJson>(engine_.get(), "EXPORT_JSON", 1,
958                                context_.storage.get(), false);
959   RegisterFunction<ExtractArg>(engine_.get(), "EXTRACT_ARG", 2,
960                                context_.storage.get());
961   RegisterFunction<AbsTimeStr>(engine_.get(), "ABS_TIME_STR", 1,
962                                context_.clock_converter.get());
963   RegisterFunction<Reverse>(engine_.get(), "REVERSE", 1);
964   RegisterFunction<ToMonotonic>(engine_.get(), "TO_MONOTONIC", 1,
965                                 context_.clock_converter.get());
966   RegisterFunction<ToRealtime>(engine_.get(), "TO_REALTIME", 1,
967                                context_.clock_converter.get());
968   RegisterFunction<ToTimecode>(engine_.get(), "TO_TIMECODE", 1);
969   RegisterFunction<CreateFunction>(engine_.get(), "CREATE_FUNCTION", 3,
970                                    engine_.get());
971   RegisterFunction<CreateViewFunction>(engine_.get(), "CREATE_VIEW_FUNCTION", 3,
972                                        engine_.get());
973   RegisterFunction<ExperimentalMemoize>(engine_.get(), "EXPERIMENTAL_MEMOIZE",
974                                         1, engine_.get());
975   RegisterFunction<Import>(
976       engine_.get(), "IMPORT", 1,
977       std::make_unique<Import::Context>(Import::Context{engine_.get()}));
978   RegisterFunction<ToFtrace>(
979       engine_.get(), "TO_FTRACE", 1,
980       std::make_unique<ToFtrace::Context>(ToFtrace::Context{
981           context_.storage.get(), SystraceSerializer(&context_)}));
982 
983   if constexpr (regex::IsRegexSupported()) {
984     RegisterFunction<Regex>(engine_.get(), "regexp", 2);
985   }
986   // Old style function registration.
987   // TODO(lalitm): migrate this over to using RegisterFunction once aggregate
988   // functions are supported.
989   RegisterValueAtMaxTsFunction(*engine_);
990   {
991     base::Status status = RegisterLastNonNullFunction(*engine_);
992     if (!status.ok())
993       PERFETTO_FATAL("%s", status.c_message());
994   }
995   {
996     base::Status status = RegisterStackFunctions(engine_.get(), &context_);
997     if (!status.ok())
998       PERFETTO_FATAL("%s", status.c_message());
999   }
1000   {
1001     base::Status status = RegisterStripHexFunction(engine_.get(), &context_);
1002     if (!status.ok())
1003       PERFETTO_FATAL("%s", status.c_message());
1004   }
1005   {
1006     base::Status status = PprofFunctions::Register(*engine_, &context_);
1007     if (!status.ok())
1008       PERFETTO_FATAL("%s", status.c_message());
1009   }
1010   {
1011     base::Status status = RegisterLayoutFunctions(*engine_);
1012     if (!status.ok())
1013       PERFETTO_FATAL("%s", status.c_message());
1014   }
1015   {
1016     base::Status status = RegisterMathFunctions(*engine_);
1017     if (!status.ok())
1018       PERFETTO_FATAL("%s", status.c_message());
1019   }
1020   {
1021     base::Status status = RegisterBase64Functions(*engine_);
1022     if (!status.ok())
1023       PERFETTO_FATAL("%s", status.c_message());
1024   }
1025   {
1026     base::Status status = RegisterTypeBuilderFunctions(*engine_);
1027     if (!status.ok())
1028       PERFETTO_FATAL("%s", status.c_message());
1029   }
1030   {
1031     base::Status status = RegisterGraphScanFunctions(
1032         *engine_, context_.storage->mutable_string_pool());
1033     if (!status.ok())
1034       PERFETTO_FATAL("%s", status.c_message());
1035   }
1036   {
1037     base::Status status = RegisterGraphTraversalFunctions(
1038         *engine_, *context_.storage->mutable_string_pool());
1039     if (!status.ok())
1040       PERFETTO_FATAL("%s", status.c_message());
1041   }
1042   {
1043     base::Status status = perfetto_sql::RegisterIntervalIntersectFunctions(
1044         *engine_, context_.storage->mutable_string_pool());
1045   }
1046   {
1047     base::Status status = perfetto_sql::RegisterCounterIntervalsFunctions(
1048         *engine_, context_.storage->mutable_string_pool());
1049   }
1050 
1051   TraceStorage* storage = context_.storage.get();
1052 
1053   // Operator tables.
1054   engine_->sqlite_engine()->RegisterVirtualTableModule<SpanJoinOperatorModule>(
1055       "span_join",
1056       std::make_unique<SpanJoinOperatorModule::Context>(engine_.get()));
1057   engine_->sqlite_engine()->RegisterVirtualTableModule<SpanJoinOperatorModule>(
1058       "span_left_join",
1059       std::make_unique<SpanJoinOperatorModule::Context>(engine_.get()));
1060   engine_->sqlite_engine()->RegisterVirtualTableModule<SpanJoinOperatorModule>(
1061       "span_outer_join",
1062       std::make_unique<SpanJoinOperatorModule::Context>(engine_.get()));
1063   engine_->sqlite_engine()->RegisterVirtualTableModule<WindowOperatorModule>(
1064       "window", std::make_unique<WindowOperatorModule::Context>());
1065   engine_->sqlite_engine()->RegisterVirtualTableModule<CounterMipmapOperator>(
1066       "__intrinsic_counter_mipmap",
1067       std::make_unique<CounterMipmapOperator::Context>(engine_.get()));
1068   engine_->sqlite_engine()->RegisterVirtualTableModule<SliceMipmapOperator>(
1069       "__intrinsic_slice_mipmap",
1070       std::make_unique<SliceMipmapOperator::Context>(engine_.get()));
1071 #if PERFETTO_BUILDFLAG(PERFETTO_ENABLE_ETM_IMPORTER)
1072   engine_->sqlite_engine()
1073       ->RegisterVirtualTableModule<etm::EtmDecodeTraceVtable>(
1074           "__intrinsic_etm_decode_trace", storage);
1075   engine_->sqlite_engine()
1076       ->RegisterVirtualTableModule<etm::EtmIterateRangeVtable>(
1077           "__intrinsic_etm_iterate_instruction_range", storage);
1078 #endif
1079 
1080   // Register stdlib packages.
1081   auto packages = GetStdlibPackages();
1082   for (auto package = packages.GetIterator(); package; ++package) {
1083     base::Status status =
1084         RegisterSqlPackage({/*name=*/package.key(), /*modules=*/package.value(),
1085                             /*allow_override=*/false});
1086     if (!status.ok())
1087       PERFETTO_ELOG("%s", status.c_message());
1088   }
1089 
1090   // Register metrics functions.
1091   {
1092     base::Status status =
1093         engine_->RegisterSqliteAggregateFunction<metrics::RepeatedField>(
1094             nullptr);
1095     if (!status.ok())
1096       PERFETTO_ELOG("%s", status.c_message());
1097   }
1098 
1099   RegisterFunction<metrics::NullIfEmpty>(engine_.get(), "NULL_IF_EMPTY", 1);
1100   RegisterFunction<metrics::UnwrapMetricProto>(engine_.get(),
1101                                                "UNWRAP_METRIC_PROTO", 2);
1102   RegisterFunction<metrics::RunMetric>(
1103       engine_.get(), "RUN_METRIC", -1,
1104       std::make_unique<metrics::RunMetric::Context>(
1105           metrics::RunMetric::Context{engine_.get(), &sql_metrics_}));
1106 
1107   // Legacy tables.
1108   engine_->sqlite_engine()->RegisterVirtualTableModule<SqlStatsModule>(
1109       "sqlstats", storage);
1110   engine_->sqlite_engine()->RegisterVirtualTableModule<StatsModule>("stats",
1111                                                                     storage);
1112   engine_->sqlite_engine()->RegisterVirtualTableModule<TablePointerModule>(
1113       "__intrinsic_table_ptr", nullptr);
1114 
1115   // New style db-backed tables.
1116   // Note: if adding a table here which might potentially contain many rows
1117   // (O(rows in sched/slice/counter)), then consider calling ShrinkToFit on
1118   // that table in TraceStorage::ShrinkToFitTables.
1119   RegisterStaticTable(storage->mutable_machine_table());
1120   RegisterStaticTable(storage->mutable_arg_table());
1121   RegisterStaticTable(storage->mutable_chrome_raw_table());
1122   RegisterStaticTable(storage->mutable_ftrace_event_table());
1123   RegisterStaticTable(storage->mutable_thread_table());
1124   RegisterStaticTable(storage->mutable_process_table());
1125   RegisterStaticTable(storage->mutable_filedescriptor_table());
1126   RegisterStaticTable(storage->mutable_trace_file_table());
1127 
1128   RegisterStaticTable(storage->mutable_slice_table());
1129   RegisterStaticTable(storage->mutable_flow_table());
1130   RegisterStaticTable(storage->mutable_sched_slice_table());
1131   RegisterStaticTable(storage->mutable_spurious_sched_wakeup_table());
1132   RegisterStaticTable(storage->mutable_thread_state_table());
1133 
1134   RegisterStaticTable(storage->mutable_track_table());
1135 
1136   RegisterStaticTable(storage->mutable_counter_table());
1137 
1138   RegisterStaticTable(storage->mutable_gpu_counter_group_table());
1139 
1140   RegisterStaticTable(storage->mutable_heap_graph_object_table());
1141   RegisterStaticTable(storage->mutable_heap_graph_reference_table());
1142   RegisterStaticTable(storage->mutable_heap_graph_class_table());
1143 
1144   RegisterStaticTable(storage->mutable_symbol_table());
1145   RegisterStaticTable(storage->mutable_heap_profile_allocation_table());
1146   RegisterStaticTable(storage->mutable_cpu_profile_stack_sample_table());
1147   RegisterStaticTable(storage->mutable_perf_session_table());
1148   RegisterStaticTable(storage->mutable_perf_sample_table());
1149   RegisterStaticTable(storage->mutable_instruments_sample_table());
1150   RegisterStaticTable(storage->mutable_stack_profile_callsite_table());
1151   RegisterStaticTable(storage->mutable_stack_profile_mapping_table());
1152   RegisterStaticTable(storage->mutable_stack_profile_frame_table());
1153   RegisterStaticTable(storage->mutable_package_list_table());
1154   RegisterStaticTable(storage->mutable_profiler_smaps_table());
1155 
1156   RegisterStaticTable(storage->mutable_android_log_table());
1157   RegisterStaticTable(storage->mutable_android_dumpstate_table());
1158   RegisterStaticTable(storage->mutable_android_game_intervenion_list_table());
1159   RegisterStaticTable(storage->mutable_android_key_events_table());
1160   RegisterStaticTable(storage->mutable_android_motion_events_table());
1161   RegisterStaticTable(storage->mutable_android_input_event_dispatch_table());
1162 
1163   RegisterStaticTable(storage->mutable_vulkan_memory_allocations_table());
1164 
1165   RegisterStaticTable(storage->mutable_android_network_packets_table());
1166 
1167   RegisterStaticTable(storage->mutable_v8_isolate_table());
1168   RegisterStaticTable(storage->mutable_v8_js_script_table());
1169   RegisterStaticTable(storage->mutable_v8_wasm_script_table());
1170   RegisterStaticTable(storage->mutable_v8_js_function_table());
1171   RegisterStaticTable(storage->mutable_v8_js_code_table());
1172   RegisterStaticTable(storage->mutable_v8_internal_code_table());
1173   RegisterStaticTable(storage->mutable_v8_wasm_code_table());
1174   RegisterStaticTable(storage->mutable_v8_regexp_code_table());
1175 
1176   RegisterStaticTable(storage->mutable_jit_code_table());
1177   RegisterStaticTable(storage->mutable_jit_frame_table());
1178 
1179   RegisterStaticTable(storage->mutable_etm_v4_configuration_table());
1180   RegisterStaticTable(storage->mutable_etm_v4_session_table());
1181   RegisterStaticTable(storage->mutable_etm_v4_trace_table());
1182   RegisterStaticTable(storage->mutable_elf_file_table());
1183   RegisterStaticTable(storage->mutable_file_table());
1184 
1185   RegisterStaticTable(storage->mutable_spe_record_table());
1186   RegisterStaticTable(storage->mutable_mmap_record_table());
1187 
1188   RegisterStaticTable(storage->mutable_inputmethod_clients_table());
1189   RegisterStaticTable(storage->mutable_inputmethod_manager_service_table());
1190   RegisterStaticTable(storage->mutable_inputmethod_service_table());
1191 
1192   RegisterStaticTable(storage->mutable_surfaceflinger_layers_snapshot_table());
1193   RegisterStaticTable(storage->mutable_surfaceflinger_layer_table());
1194   RegisterStaticTable(storage->mutable_surfaceflinger_transactions_table());
1195 
1196   RegisterStaticTable(storage->mutable_viewcapture_table());
1197   RegisterStaticTable(storage->mutable_viewcapture_view_table());
1198 
1199   RegisterStaticTable(storage->mutable_windowmanager_table());
1200 
1201   RegisterStaticTable(
1202       storage->mutable_window_manager_shell_transitions_table());
1203   RegisterStaticTable(
1204       storage->mutable_window_manager_shell_transition_handlers_table());
1205   RegisterStaticTable(
1206       storage->mutable_window_manager_shell_transition_protos_table());
1207 
1208   RegisterStaticTable(storage->mutable_protolog_table());
1209 
1210   RegisterStaticTable(storage->mutable_metadata_table());
1211   RegisterStaticTable(storage->mutable_cpu_table());
1212   RegisterStaticTable(storage->mutable_cpu_freq_table());
1213   RegisterStaticTable(storage->mutable_clock_snapshot_table());
1214 
1215   RegisterStaticTable(storage->mutable_memory_snapshot_table());
1216   RegisterStaticTable(storage->mutable_process_memory_snapshot_table());
1217   RegisterStaticTable(storage->mutable_memory_snapshot_node_table());
1218   RegisterStaticTable(storage->mutable_memory_snapshot_edge_table());
1219 
1220   RegisterStaticTable(storage->mutable_experimental_proto_path_table());
1221   RegisterStaticTable(storage->mutable_experimental_proto_content_table());
1222 
1223   RegisterStaticTable(
1224       storage->mutable_experimental_missing_chrome_processes_table());
1225 
1226   // Tables dynamically generated at query time.
1227   engine_->RegisterStaticTableFunction(
1228       std::make_unique<ExperimentalFlamegraph>(&context_));
1229   engine_->RegisterStaticTableFunction(
1230       std::make_unique<ExperimentalSliceLayout>(
1231           context_.storage->mutable_string_pool(), &storage->slice_table()));
1232   engine_->RegisterStaticTableFunction(std::make_unique<TableInfo>(
1233       context_.storage->mutable_string_pool(), engine_.get()));
1234   engine_->RegisterStaticTableFunction(std::make_unique<Ancestor>(
1235       Ancestor::Type::kSlice, context_.storage.get()));
1236   engine_->RegisterStaticTableFunction(std::make_unique<Ancestor>(
1237       Ancestor::Type::kStackProfileCallsite, context_.storage.get()));
1238   engine_->RegisterStaticTableFunction(std::make_unique<Ancestor>(
1239       Ancestor::Type::kSliceByStack, context_.storage.get()));
1240   engine_->RegisterStaticTableFunction(std::make_unique<Descendant>(
1241       Descendant::Type::kSlice, context_.storage.get()));
1242   engine_->RegisterStaticTableFunction(std::make_unique<Descendant>(
1243       Descendant::Type::kSliceByStack, context_.storage.get()));
1244   engine_->RegisterStaticTableFunction(std::make_unique<ConnectedFlow>(
1245       ConnectedFlow::Mode::kDirectlyConnectedFlow, context_.storage.get()));
1246   engine_->RegisterStaticTableFunction(std::make_unique<ConnectedFlow>(
1247       ConnectedFlow::Mode::kPrecedingFlow, context_.storage.get()));
1248   engine_->RegisterStaticTableFunction(std::make_unique<ConnectedFlow>(
1249       ConnectedFlow::Mode::kFollowingFlow, context_.storage.get()));
1250   engine_->RegisterStaticTableFunction(
1251       std::make_unique<ExperimentalAnnotatedStack>(&context_));
1252   engine_->RegisterStaticTableFunction(
1253       std::make_unique<ExperimentalFlatSlice>(&context_));
1254   engine_->RegisterStaticTableFunction(std::make_unique<DfsWeightBounded>(
1255       context_.storage->mutable_string_pool()));
1256   engine_->RegisterStaticTableFunction(
1257       std::make_unique<WinscopeProtoToArgsWithDefaults>(
1258           context_.storage->mutable_string_pool(), engine_.get(), &context_));
1259 
1260   // Value table aggregate functions.
1261   engine_->RegisterSqliteAggregateFunction<DominatorTree>(
1262       context_.storage->mutable_string_pool());
1263   engine_->RegisterSqliteAggregateFunction<StructuralTreePartition>(
1264       context_.storage->mutable_string_pool());
1265 
1266   // Metrics.
1267   {
1268     auto status = RegisterAllProtoBuilderFunctions(&metrics_descriptor_pool_,
1269                                                    &proto_fn_name_to_path_,
1270                                                    engine_.get(), this);
1271     if (!status.ok()) {
1272       PERFETTO_FATAL("%s", status.c_message());
1273     }
1274   }
1275 
1276   // Import prelude package.
1277   IncludeBeforeEofPrelude();
1278   if (notify_eof_called_) {
1279     IncludeAfterEofPrelude();
1280   }
1281 
1282   for (const auto& metric : sql_metrics_) {
1283     if (metric.proto_field_name) {
1284       InsertIntoTraceMetricsTable(db, *metric.proto_field_name);
1285     }
1286   }
1287 
1288   // Fill trace bounds table.
1289   BuildBoundsTable(db, GetTraceTimestampBoundsNs(*context_.storage));
1290 
1291   // Reregister manually added stdlib packages.
1292   for (const auto& package : manually_registered_sql_packages_) {
1293     RegisterSqlPackage(package);
1294   }
1295 }
1296 
IncludeBeforeEofPrelude()1297 void TraceProcessorImpl::IncludeBeforeEofPrelude() {
1298   auto result = engine_->Execute(SqlSource::FromTraceProcessorImplementation(
1299       "INCLUDE PERFETTO MODULE prelude.before_eof.*"));
1300   if (!result.status().ok()) {
1301     PERFETTO_FATAL("Failed to import prelude: %s", result.status().c_message());
1302   }
1303 }
1304 
IncludeAfterEofPrelude()1305 void TraceProcessorImpl::IncludeAfterEofPrelude() {
1306   auto result = engine_->Execute(SqlSource::FromTraceProcessorImplementation(
1307       "INCLUDE PERFETTO MODULE prelude.after_eof.*"));
1308   if (!result.status().ok()) {
1309     PERFETTO_FATAL("Failed to import prelude: %s", result.status().c_message());
1310   }
1311 }
1312 
IsRootMetricField(const std::string & metric_name)1313 bool TraceProcessorImpl::IsRootMetricField(const std::string& metric_name) {
1314   std::optional<uint32_t> desc_idx = metrics_descriptor_pool_.FindDescriptorIdx(
1315       ".perfetto.protos.TraceMetrics");
1316   if (!desc_idx.has_value())
1317     return false;
1318   const auto* field_idx =
1319       metrics_descriptor_pool_.descriptors()[*desc_idx].FindFieldByName(
1320           metric_name);
1321   return field_idx != nullptr;
1322 }
1323 
1324 }  // namespace perfetto::trace_processor
1325