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