Merge "ui: simplify "io.ufs.command.tags" track grouping" into main
diff --git a/Android.bp b/Android.bp
index 2f1dc27..dd2c861 100644
--- a/Android.bp
+++ b/Android.bp
@@ -569,12 +569,6 @@
         ":perfetto_src_ipc_host",
         ":perfetto_src_kallsyms_kallsyms",
         ":perfetto_src_kernel_utils_syscall_table",
-        ":perfetto_src_perfetto_cmd_bugreport_path",
-        ":perfetto_src_perfetto_cmd_pbtxt_to_pb",
-        ":perfetto_src_perfetto_cmd_perfetto_cmd",
-        ":perfetto_src_perfetto_cmd_protos_cpp_gen",
-        ":perfetto_src_perfetto_cmd_trigger_perfetto_cmd",
-        ":perfetto_src_perfetto_cmd_trigger_producer",
         ":perfetto_src_protozero_filtering_bytecode_common",
         ":perfetto_src_protozero_filtering_bytecode_parser",
         ":perfetto_src_protozero_filtering_message_filter",
@@ -605,7 +599,6 @@
         ":perfetto_src_tracing_common",
         ":perfetto_src_tracing_core_core",
         ":perfetto_src_tracing_ipc_common",
-        ":perfetto_src_tracing_ipc_consumer_consumer",
         ":perfetto_src_tracing_ipc_default_socket",
         ":perfetto_src_tracing_ipc_producer_producer",
         ":perfetto_src_tracing_ipc_service_service",
@@ -671,8 +664,6 @@
         "perfetto_protos_perfetto_trace_translation_zero_gen_headers",
         "perfetto_protos_third_party_statsd_config_zero_gen_headers",
         "perfetto_src_base_version_gen_h",
-        "perfetto_src_perfetto_cmd_gen_cc_config_descriptor",
-        "perfetto_src_perfetto_cmd_protos_cpp_gen_headers",
     ],
     defaults: [
         "perfetto_defaults",
@@ -1137,12 +1128,151 @@
 cc_binary {
     name: "perfetto",
     srcs: [
+        ":perfetto_base_default_platform",
+        ":perfetto_include_perfetto_base_base",
+        ":perfetto_include_perfetto_ext_base_base",
+        ":perfetto_include_perfetto_ext_base_version",
+        ":perfetto_include_perfetto_ext_ipc_ipc",
         ":perfetto_include_perfetto_ext_traced_traced",
+        ":perfetto_include_perfetto_ext_tracing_core_core",
+        ":perfetto_include_perfetto_ext_tracing_ipc_ipc",
+        ":perfetto_include_perfetto_protozero_protozero",
+        ":perfetto_include_perfetto_public_abi_base",
+        ":perfetto_include_perfetto_public_base",
+        ":perfetto_include_perfetto_public_protozero",
+        ":perfetto_include_perfetto_tracing_core_core",
+        ":perfetto_include_perfetto_tracing_core_forward_decls",
+        ":perfetto_include_perfetto_tracing_tracing",
+        ":perfetto_protos_perfetto_common_cpp_gen",
+        ":perfetto_protos_perfetto_common_zero_gen",
+        ":perfetto_protos_perfetto_config_android_cpp_gen",
+        ":perfetto_protos_perfetto_config_android_zero_gen",
+        ":perfetto_protos_perfetto_config_cpp_gen",
+        ":perfetto_protos_perfetto_config_ftrace_cpp_gen",
+        ":perfetto_protos_perfetto_config_ftrace_zero_gen",
+        ":perfetto_protos_perfetto_config_gpu_cpp_gen",
+        ":perfetto_protos_perfetto_config_gpu_zero_gen",
+        ":perfetto_protos_perfetto_config_inode_file_cpp_gen",
+        ":perfetto_protos_perfetto_config_inode_file_zero_gen",
+        ":perfetto_protos_perfetto_config_interceptors_cpp_gen",
+        ":perfetto_protos_perfetto_config_interceptors_zero_gen",
+        ":perfetto_protos_perfetto_config_power_cpp_gen",
+        ":perfetto_protos_perfetto_config_power_zero_gen",
+        ":perfetto_protos_perfetto_config_process_stats_cpp_gen",
+        ":perfetto_protos_perfetto_config_process_stats_zero_gen",
+        ":perfetto_protos_perfetto_config_profiling_cpp_gen",
+        ":perfetto_protos_perfetto_config_profiling_zero_gen",
+        ":perfetto_protos_perfetto_config_statsd_cpp_gen",
+        ":perfetto_protos_perfetto_config_statsd_zero_gen",
+        ":perfetto_protos_perfetto_config_sys_stats_cpp_gen",
+        ":perfetto_protos_perfetto_config_sys_stats_zero_gen",
+        ":perfetto_protos_perfetto_config_system_info_cpp_gen",
+        ":perfetto_protos_perfetto_config_system_info_zero_gen",
+        ":perfetto_protos_perfetto_config_track_event_cpp_gen",
+        ":perfetto_protos_perfetto_config_track_event_zero_gen",
+        ":perfetto_protos_perfetto_config_zero_gen",
+        ":perfetto_protos_perfetto_ipc_cpp_gen",
+        ":perfetto_protos_perfetto_ipc_ipc_gen",
+        ":perfetto_protos_perfetto_ipc_wire_protocol_cpp_gen",
+        ":perfetto_protos_perfetto_trace_android_zero_gen",
+        ":perfetto_protos_perfetto_trace_chrome_zero_gen",
+        ":perfetto_protos_perfetto_trace_etw_zero_gen",
+        ":perfetto_protos_perfetto_trace_filesystem_zero_gen",
+        ":perfetto_protos_perfetto_trace_ftrace_zero_gen",
+        ":perfetto_protos_perfetto_trace_gpu_zero_gen",
+        ":perfetto_protos_perfetto_trace_interned_data_zero_gen",
+        ":perfetto_protos_perfetto_trace_minimal_zero_gen",
+        ":perfetto_protos_perfetto_trace_non_minimal_zero_gen",
+        ":perfetto_protos_perfetto_trace_perfetto_zero_gen",
+        ":perfetto_protos_perfetto_trace_power_zero_gen",
+        ":perfetto_protos_perfetto_trace_profiling_zero_gen",
+        ":perfetto_protos_perfetto_trace_ps_zero_gen",
+        ":perfetto_protos_perfetto_trace_statsd_zero_gen",
+        ":perfetto_protos_perfetto_trace_sys_stats_zero_gen",
+        ":perfetto_protos_perfetto_trace_system_info_zero_gen",
+        ":perfetto_protos_perfetto_trace_track_event_cpp_gen",
+        ":perfetto_protos_perfetto_trace_track_event_zero_gen",
+        ":perfetto_protos_perfetto_trace_translation_zero_gen",
+        ":perfetto_src_android_internal_headers",
+        ":perfetto_src_android_internal_lazy_library_loader",
+        ":perfetto_src_android_stats_android_stats",
+        ":perfetto_src_android_stats_perfetto_atoms",
+        ":perfetto_src_base_base",
+        ":perfetto_src_base_unix_socket",
+        ":perfetto_src_base_version",
+        ":perfetto_src_ipc_client",
+        ":perfetto_src_ipc_common",
+        ":perfetto_src_perfetto_cmd_bugreport_path",
+        ":perfetto_src_perfetto_cmd_pbtxt_to_pb",
+        ":perfetto_src_perfetto_cmd_perfetto_cmd",
+        ":perfetto_src_perfetto_cmd_protos_cpp_gen",
+        ":perfetto_src_perfetto_cmd_trigger_producer",
+        ":perfetto_src_protozero_protozero",
+        ":perfetto_src_tracing_common",
+        ":perfetto_src_tracing_core_core",
+        ":perfetto_src_tracing_ipc_common",
+        ":perfetto_src_tracing_ipc_consumer_consumer",
+        ":perfetto_src_tracing_ipc_default_socket",
+        ":perfetto_src_tracing_ipc_producer_producer",
         "src/perfetto_cmd/main.cc",
     ],
     shared_libs: [
         "liblog",
-        "libperfetto",
+    ],
+    generated_headers: [
+        "perfetto_protos_perfetto_common_cpp_gen_headers",
+        "perfetto_protos_perfetto_common_zero_gen_headers",
+        "perfetto_protos_perfetto_config_android_cpp_gen_headers",
+        "perfetto_protos_perfetto_config_android_zero_gen_headers",
+        "perfetto_protos_perfetto_config_cpp_gen_headers",
+        "perfetto_protos_perfetto_config_ftrace_cpp_gen_headers",
+        "perfetto_protos_perfetto_config_ftrace_zero_gen_headers",
+        "perfetto_protos_perfetto_config_gpu_cpp_gen_headers",
+        "perfetto_protos_perfetto_config_gpu_zero_gen_headers",
+        "perfetto_protos_perfetto_config_inode_file_cpp_gen_headers",
+        "perfetto_protos_perfetto_config_inode_file_zero_gen_headers",
+        "perfetto_protos_perfetto_config_interceptors_cpp_gen_headers",
+        "perfetto_protos_perfetto_config_interceptors_zero_gen_headers",
+        "perfetto_protos_perfetto_config_power_cpp_gen_headers",
+        "perfetto_protos_perfetto_config_power_zero_gen_headers",
+        "perfetto_protos_perfetto_config_process_stats_cpp_gen_headers",
+        "perfetto_protos_perfetto_config_process_stats_zero_gen_headers",
+        "perfetto_protos_perfetto_config_profiling_cpp_gen_headers",
+        "perfetto_protos_perfetto_config_profiling_zero_gen_headers",
+        "perfetto_protos_perfetto_config_statsd_cpp_gen_headers",
+        "perfetto_protos_perfetto_config_statsd_zero_gen_headers",
+        "perfetto_protos_perfetto_config_sys_stats_cpp_gen_headers",
+        "perfetto_protos_perfetto_config_sys_stats_zero_gen_headers",
+        "perfetto_protos_perfetto_config_system_info_cpp_gen_headers",
+        "perfetto_protos_perfetto_config_system_info_zero_gen_headers",
+        "perfetto_protos_perfetto_config_track_event_cpp_gen_headers",
+        "perfetto_protos_perfetto_config_track_event_zero_gen_headers",
+        "perfetto_protos_perfetto_config_zero_gen_headers",
+        "perfetto_protos_perfetto_ipc_cpp_gen_headers",
+        "perfetto_protos_perfetto_ipc_ipc_gen_headers",
+        "perfetto_protos_perfetto_ipc_wire_protocol_cpp_gen_headers",
+        "perfetto_protos_perfetto_trace_android_zero_gen_headers",
+        "perfetto_protos_perfetto_trace_chrome_zero_gen_headers",
+        "perfetto_protos_perfetto_trace_etw_zero_gen_headers",
+        "perfetto_protos_perfetto_trace_filesystem_zero_gen_headers",
+        "perfetto_protos_perfetto_trace_ftrace_zero_gen_headers",
+        "perfetto_protos_perfetto_trace_gpu_zero_gen_headers",
+        "perfetto_protos_perfetto_trace_interned_data_zero_gen_headers",
+        "perfetto_protos_perfetto_trace_minimal_zero_gen_headers",
+        "perfetto_protos_perfetto_trace_non_minimal_zero_gen_headers",
+        "perfetto_protos_perfetto_trace_perfetto_zero_gen_headers",
+        "perfetto_protos_perfetto_trace_power_zero_gen_headers",
+        "perfetto_protos_perfetto_trace_profiling_zero_gen_headers",
+        "perfetto_protos_perfetto_trace_ps_zero_gen_headers",
+        "perfetto_protos_perfetto_trace_statsd_zero_gen_headers",
+        "perfetto_protos_perfetto_trace_sys_stats_zero_gen_headers",
+        "perfetto_protos_perfetto_trace_system_info_zero_gen_headers",
+        "perfetto_protos_perfetto_trace_track_event_cpp_gen_headers",
+        "perfetto_protos_perfetto_trace_track_event_zero_gen_headers",
+        "perfetto_protos_perfetto_trace_translation_zero_gen_headers",
+        "perfetto_src_base_version_gen_h",
+        "perfetto_src_perfetto_cmd_gen_cc_config_descriptor",
+        "perfetto_src_perfetto_cmd_protos_cpp_gen_headers",
     ],
     defaults: [
         "perfetto_defaults",
@@ -1868,6 +1998,11 @@
     name: "perfetto_include_perfetto_ext_tracing_core_core",
 }
 
+// GN: //include/perfetto/ext/tracing/core:test_support
+filegroup {
+    name: "perfetto_include_perfetto_ext_tracing_core_test_support",
+}
+
 // GN: //include/perfetto/ext/tracing/ipc:ipc
 filegroup {
     name: "perfetto_include_perfetto_ext_tracing_ipc_ipc",
@@ -1964,6 +2099,7 @@
         ":perfetto_include_perfetto_ext_traced_sys_stats_counters",
         ":perfetto_include_perfetto_ext_traced_traced",
         ":perfetto_include_perfetto_ext_tracing_core_core",
+        ":perfetto_include_perfetto_ext_tracing_core_test_support",
         ":perfetto_include_perfetto_ext_tracing_ipc_ipc",
         ":perfetto_include_perfetto_protozero_protozero",
         ":perfetto_include_perfetto_public_abi_base",
@@ -9918,6 +10054,14 @@
     ],
 }
 
+// GN: //src/kernel_utils:unittests
+filegroup {
+    name: "perfetto_src_kernel_utils_unittests",
+    srcs: [
+        "src/kernel_utils/syscall_table_unittest.cc",
+    ],
+}
+
 // GN: //src/perfetto_cmd:bugreport_path
 filegroup {
     name: "perfetto_src_perfetto_cmd_bugreport_path",
@@ -10714,7 +10858,6 @@
     srcs: [
         "src/trace_processor/containers/bit_vector_unittest.cc",
         "src/trace_processor/containers/null_term_string_view_unittest.cc",
-        "src/trace_processor/containers/nullable_vector_unittest.cc",
         "src/trace_processor/containers/row_map_unittest.cc",
         "src/trace_processor/containers/string_pool_unittest.cc",
     ],
@@ -11226,6 +11369,8 @@
 filegroup {
     name: "perfetto_src_trace_processor_importers_proto_winscope_full",
     srcs: [
+        "src/trace_processor/importers/proto/winscope/protolog_messages_tracker.cc",
+        "src/trace_processor/importers/proto/winscope/protolog_parser.cc",
         "src/trace_processor/importers/proto/winscope/shell_transitions_parser.cc",
         "src/trace_processor/importers/proto/winscope/shell_transitions_tracker.cc",
         "src/trace_processor/importers/proto/winscope/surfaceflinger_layers_parser.cc",
@@ -11649,6 +11794,7 @@
         "src/trace_processor/perfetto_sql/intrinsics/table_functions/ancestor.cc",
         "src/trace_processor/perfetto_sql/intrinsics/table_functions/connected_flow.cc",
         "src/trace_processor/perfetto_sql/intrinsics/table_functions/descendant.cc",
+        "src/trace_processor/perfetto_sql/intrinsics/table_functions/dfs.cc",
         "src/trace_processor/perfetto_sql/intrinsics/table_functions/dominator_tree.cc",
         "src/trace_processor/perfetto_sql/intrinsics/table_functions/experimental_annotated_stack.cc",
         "src/trace_processor/perfetto_sql/intrinsics/table_functions/experimental_counter_dur.cc",
@@ -11735,9 +11881,11 @@
     name: "perfetto_src_trace_processor_perfetto_sql_stdlib_stdlib",
     srcs: [
         "src/trace_processor/perfetto_sql/stdlib/android/anrs.sql",
+        "src/trace_processor/perfetto_sql/stdlib/android/app_process_starts.sql",
         "src/trace_processor/perfetto_sql/stdlib/android/battery.sql",
         "src/trace_processor/perfetto_sql/stdlib/android/battery_stats.sql",
         "src/trace_processor/perfetto_sql/stdlib/android/binder.sql",
+        "src/trace_processor/perfetto_sql/stdlib/android/broadcasts.sql",
         "src/trace_processor/perfetto_sql/stdlib/android/dvfs.sql",
         "src/trace_processor/perfetto_sql/stdlib/android/io.sql",
         "src/trace_processor/perfetto_sql/stdlib/android/monitor_contention.sql",
@@ -11745,11 +11893,11 @@
         "src/trace_processor/perfetto_sql/stdlib/android/process_metadata.sql",
         "src/trace_processor/perfetto_sql/stdlib/android/screenshots.sql",
         "src/trace_processor/perfetto_sql/stdlib/android/slices.sql",
-        "src/trace_processor/perfetto_sql/stdlib/android/startup/internal_startup_events.sql",
-        "src/trace_processor/perfetto_sql/stdlib/android/startup/internal_startups_maxsdk28.sql",
-        "src/trace_processor/perfetto_sql/stdlib/android/startup/internal_startups_minsdk29.sql",
-        "src/trace_processor/perfetto_sql/stdlib/android/startup/internal_startups_minsdk33.sql",
+        "src/trace_processor/perfetto_sql/stdlib/android/startup/startup_events.sql",
         "src/trace_processor/perfetto_sql/stdlib/android/startup/startups.sql",
+        "src/trace_processor/perfetto_sql/stdlib/android/startup/startups_maxsdk28.sql",
+        "src/trace_processor/perfetto_sql/stdlib/android/startup/startups_minsdk29.sql",
+        "src/trace_processor/perfetto_sql/stdlib/android/startup/startups_minsdk33.sql",
         "src/trace_processor/perfetto_sql/stdlib/android/statsd.sql",
         "src/trace_processor/perfetto_sql/stdlib/android/thread.sql",
         "src/trace_processor/perfetto_sql/stdlib/chrome/**/*.sql",
@@ -11761,18 +11909,17 @@
         "src/trace_processor/perfetto_sql/stdlib/common/slices.sql",
         "src/trace_processor/perfetto_sql/stdlib/common/thread_states.sql",
         "src/trace_processor/perfetto_sql/stdlib/common/timestamps.sql",
-        "src/trace_processor/perfetto_sql/stdlib/experimental/android_broadcast.sql",
-        "src/trace_processor/perfetto_sql/stdlib/experimental/flat_slices.sql",
-        "src/trace_processor/perfetto_sql/stdlib/experimental/proto_path.sql",
-        "src/trace_processor/perfetto_sql/stdlib/experimental/slices.sql",
-        "src/trace_processor/perfetto_sql/stdlib/experimental/thread_executing_span.sql",
-        "src/trace_processor/perfetto_sql/stdlib/experimental/thread_state_flattened.sql",
         "src/trace_processor/perfetto_sql/stdlib/graphs/dominator_tree.sql",
+        "src/trace_processor/perfetto_sql/stdlib/graphs/search.sql",
         "src/trace_processor/perfetto_sql/stdlib/intervals/overlap.sql",
         "src/trace_processor/perfetto_sql/stdlib/linux/cpu_idle.sql",
         "src/trace_processor/perfetto_sql/stdlib/pkvm/hypervisor.sql",
         "src/trace_processor/perfetto_sql/stdlib/prelude/slices.sql",
+        "src/trace_processor/perfetto_sql/stdlib/sched/thread_executing_span.sql",
         "src/trace_processor/perfetto_sql/stdlib/sched/thread_level_parallelism.sql",
+        "src/trace_processor/perfetto_sql/stdlib/sched/thread_state_flattened.sql",
+        "src/trace_processor/perfetto_sql/stdlib/slices/flat_slices.sql",
+        "src/trace_processor/perfetto_sql/stdlib/slices/slices.sql",
     ],
     cmd: "$(location tools/gen_amalgamated_sql.py) --namespace=stdlib --cpp-out=$(out) $(in)",
     out: [
@@ -13494,6 +13641,7 @@
         ":perfetto_src_kallsyms_kallsyms",
         ":perfetto_src_kallsyms_unittests",
         ":perfetto_src_kernel_utils_syscall_table",
+        ":perfetto_src_kernel_utils_unittests",
         ":perfetto_src_perfetto_cmd_bugreport_path",
         ":perfetto_src_perfetto_cmd_pbtxt_to_pb",
         ":perfetto_src_perfetto_cmd_perfetto_cmd",
@@ -14871,12 +15019,147 @@
 cc_binary {
     name: "trigger_perfetto",
     srcs: [
+        ":perfetto_base_default_platform",
+        ":perfetto_include_perfetto_base_base",
+        ":perfetto_include_perfetto_ext_base_base",
+        ":perfetto_include_perfetto_ext_base_version",
+        ":perfetto_include_perfetto_ext_ipc_ipc",
         ":perfetto_include_perfetto_ext_traced_traced",
+        ":perfetto_include_perfetto_ext_tracing_core_core",
+        ":perfetto_include_perfetto_ext_tracing_ipc_ipc",
+        ":perfetto_include_perfetto_protozero_protozero",
+        ":perfetto_include_perfetto_public_abi_base",
+        ":perfetto_include_perfetto_public_base",
+        ":perfetto_include_perfetto_public_protozero",
+        ":perfetto_include_perfetto_tracing_core_core",
+        ":perfetto_include_perfetto_tracing_core_forward_decls",
+        ":perfetto_include_perfetto_tracing_tracing",
+        ":perfetto_protos_perfetto_common_cpp_gen",
+        ":perfetto_protos_perfetto_common_zero_gen",
+        ":perfetto_protos_perfetto_config_android_cpp_gen",
+        ":perfetto_protos_perfetto_config_android_zero_gen",
+        ":perfetto_protos_perfetto_config_cpp_gen",
+        ":perfetto_protos_perfetto_config_ftrace_cpp_gen",
+        ":perfetto_protos_perfetto_config_ftrace_zero_gen",
+        ":perfetto_protos_perfetto_config_gpu_cpp_gen",
+        ":perfetto_protos_perfetto_config_gpu_zero_gen",
+        ":perfetto_protos_perfetto_config_inode_file_cpp_gen",
+        ":perfetto_protos_perfetto_config_inode_file_zero_gen",
+        ":perfetto_protos_perfetto_config_interceptors_cpp_gen",
+        ":perfetto_protos_perfetto_config_interceptors_zero_gen",
+        ":perfetto_protos_perfetto_config_power_cpp_gen",
+        ":perfetto_protos_perfetto_config_power_zero_gen",
+        ":perfetto_protos_perfetto_config_process_stats_cpp_gen",
+        ":perfetto_protos_perfetto_config_process_stats_zero_gen",
+        ":perfetto_protos_perfetto_config_profiling_cpp_gen",
+        ":perfetto_protos_perfetto_config_profiling_zero_gen",
+        ":perfetto_protos_perfetto_config_statsd_cpp_gen",
+        ":perfetto_protos_perfetto_config_statsd_zero_gen",
+        ":perfetto_protos_perfetto_config_sys_stats_cpp_gen",
+        ":perfetto_protos_perfetto_config_sys_stats_zero_gen",
+        ":perfetto_protos_perfetto_config_system_info_cpp_gen",
+        ":perfetto_protos_perfetto_config_system_info_zero_gen",
+        ":perfetto_protos_perfetto_config_track_event_cpp_gen",
+        ":perfetto_protos_perfetto_config_track_event_zero_gen",
+        ":perfetto_protos_perfetto_config_zero_gen",
+        ":perfetto_protos_perfetto_ipc_cpp_gen",
+        ":perfetto_protos_perfetto_ipc_ipc_gen",
+        ":perfetto_protos_perfetto_ipc_wire_protocol_cpp_gen",
+        ":perfetto_protos_perfetto_trace_android_zero_gen",
+        ":perfetto_protos_perfetto_trace_chrome_zero_gen",
+        ":perfetto_protos_perfetto_trace_etw_zero_gen",
+        ":perfetto_protos_perfetto_trace_filesystem_zero_gen",
+        ":perfetto_protos_perfetto_trace_ftrace_zero_gen",
+        ":perfetto_protos_perfetto_trace_gpu_zero_gen",
+        ":perfetto_protos_perfetto_trace_interned_data_zero_gen",
+        ":perfetto_protos_perfetto_trace_minimal_zero_gen",
+        ":perfetto_protos_perfetto_trace_non_minimal_zero_gen",
+        ":perfetto_protos_perfetto_trace_perfetto_zero_gen",
+        ":perfetto_protos_perfetto_trace_power_zero_gen",
+        ":perfetto_protos_perfetto_trace_profiling_zero_gen",
+        ":perfetto_protos_perfetto_trace_ps_zero_gen",
+        ":perfetto_protos_perfetto_trace_statsd_zero_gen",
+        ":perfetto_protos_perfetto_trace_sys_stats_zero_gen",
+        ":perfetto_protos_perfetto_trace_system_info_zero_gen",
+        ":perfetto_protos_perfetto_trace_track_event_cpp_gen",
+        ":perfetto_protos_perfetto_trace_track_event_zero_gen",
+        ":perfetto_protos_perfetto_trace_translation_zero_gen",
+        ":perfetto_src_android_internal_headers",
+        ":perfetto_src_android_internal_lazy_library_loader",
+        ":perfetto_src_android_stats_android_stats",
+        ":perfetto_src_android_stats_perfetto_atoms",
+        ":perfetto_src_base_base",
+        ":perfetto_src_base_unix_socket",
+        ":perfetto_src_base_version",
+        ":perfetto_src_ipc_client",
+        ":perfetto_src_ipc_common",
+        ":perfetto_src_perfetto_cmd_protos_cpp_gen",
+        ":perfetto_src_perfetto_cmd_trigger_perfetto_cmd",
+        ":perfetto_src_perfetto_cmd_trigger_producer",
+        ":perfetto_src_protozero_protozero",
+        ":perfetto_src_tracing_common",
+        ":perfetto_src_tracing_core_core",
+        ":perfetto_src_tracing_ipc_common",
+        ":perfetto_src_tracing_ipc_default_socket",
+        ":perfetto_src_tracing_ipc_producer_producer",
         "src/perfetto_cmd/trigger_perfetto_main.cc",
     ],
     shared_libs: [
         "liblog",
-        "libperfetto",
+    ],
+    generated_headers: [
+        "perfetto_protos_perfetto_common_cpp_gen_headers",
+        "perfetto_protos_perfetto_common_zero_gen_headers",
+        "perfetto_protos_perfetto_config_android_cpp_gen_headers",
+        "perfetto_protos_perfetto_config_android_zero_gen_headers",
+        "perfetto_protos_perfetto_config_cpp_gen_headers",
+        "perfetto_protos_perfetto_config_ftrace_cpp_gen_headers",
+        "perfetto_protos_perfetto_config_ftrace_zero_gen_headers",
+        "perfetto_protos_perfetto_config_gpu_cpp_gen_headers",
+        "perfetto_protos_perfetto_config_gpu_zero_gen_headers",
+        "perfetto_protos_perfetto_config_inode_file_cpp_gen_headers",
+        "perfetto_protos_perfetto_config_inode_file_zero_gen_headers",
+        "perfetto_protos_perfetto_config_interceptors_cpp_gen_headers",
+        "perfetto_protos_perfetto_config_interceptors_zero_gen_headers",
+        "perfetto_protos_perfetto_config_power_cpp_gen_headers",
+        "perfetto_protos_perfetto_config_power_zero_gen_headers",
+        "perfetto_protos_perfetto_config_process_stats_cpp_gen_headers",
+        "perfetto_protos_perfetto_config_process_stats_zero_gen_headers",
+        "perfetto_protos_perfetto_config_profiling_cpp_gen_headers",
+        "perfetto_protos_perfetto_config_profiling_zero_gen_headers",
+        "perfetto_protos_perfetto_config_statsd_cpp_gen_headers",
+        "perfetto_protos_perfetto_config_statsd_zero_gen_headers",
+        "perfetto_protos_perfetto_config_sys_stats_cpp_gen_headers",
+        "perfetto_protos_perfetto_config_sys_stats_zero_gen_headers",
+        "perfetto_protos_perfetto_config_system_info_cpp_gen_headers",
+        "perfetto_protos_perfetto_config_system_info_zero_gen_headers",
+        "perfetto_protos_perfetto_config_track_event_cpp_gen_headers",
+        "perfetto_protos_perfetto_config_track_event_zero_gen_headers",
+        "perfetto_protos_perfetto_config_zero_gen_headers",
+        "perfetto_protos_perfetto_ipc_cpp_gen_headers",
+        "perfetto_protos_perfetto_ipc_ipc_gen_headers",
+        "perfetto_protos_perfetto_ipc_wire_protocol_cpp_gen_headers",
+        "perfetto_protos_perfetto_trace_android_zero_gen_headers",
+        "perfetto_protos_perfetto_trace_chrome_zero_gen_headers",
+        "perfetto_protos_perfetto_trace_etw_zero_gen_headers",
+        "perfetto_protos_perfetto_trace_filesystem_zero_gen_headers",
+        "perfetto_protos_perfetto_trace_ftrace_zero_gen_headers",
+        "perfetto_protos_perfetto_trace_gpu_zero_gen_headers",
+        "perfetto_protos_perfetto_trace_interned_data_zero_gen_headers",
+        "perfetto_protos_perfetto_trace_minimal_zero_gen_headers",
+        "perfetto_protos_perfetto_trace_non_minimal_zero_gen_headers",
+        "perfetto_protos_perfetto_trace_perfetto_zero_gen_headers",
+        "perfetto_protos_perfetto_trace_power_zero_gen_headers",
+        "perfetto_protos_perfetto_trace_profiling_zero_gen_headers",
+        "perfetto_protos_perfetto_trace_ps_zero_gen_headers",
+        "perfetto_protos_perfetto_trace_statsd_zero_gen_headers",
+        "perfetto_protos_perfetto_trace_sys_stats_zero_gen_headers",
+        "perfetto_protos_perfetto_trace_system_info_zero_gen_headers",
+        "perfetto_protos_perfetto_trace_track_event_cpp_gen_headers",
+        "perfetto_protos_perfetto_trace_track_event_zero_gen_headers",
+        "perfetto_protos_perfetto_trace_translation_zero_gen_headers",
+        "perfetto_src_base_version_gen_h",
+        "perfetto_src_perfetto_cmd_protos_cpp_gen_headers",
     ],
     defaults: [
         "perfetto_defaults",
diff --git a/BUILD b/BUILD
index e38a6df..f8f66a2 100644
--- a/BUILD
+++ b/BUILD
@@ -432,11 +432,6 @@
         ":src_android_stats_perfetto_atoms",
         ":src_kallsyms_kallsyms",
         ":src_kernel_utils_syscall_table",
-        ":src_perfetto_cmd_bugreport_path",
-        ":src_perfetto_cmd_pbtxt_to_pb",
-        ":src_perfetto_cmd_perfetto_cmd",
-        ":src_perfetto_cmd_trigger_perfetto_cmd",
-        ":src_perfetto_cmd_trigger_producer",
         ":src_protozero_filtering_bytecode_common",
         ":src_protozero_filtering_bytecode_parser",
         ":src_protozero_filtering_message_filter",
@@ -466,7 +461,6 @@
         ":src_tracing_common",
         ":src_tracing_core_core",
         ":src_tracing_ipc_common",
-        ":src_tracing_ipc_consumer_consumer",
         ":src_tracing_ipc_default_socket",
         ":src_tracing_ipc_producer_producer",
         ":src_tracing_ipc_service_service",
@@ -545,8 +539,6 @@
         ":protozero",
         ":src_base_base",
         ":src_base_version",
-        ":src_perfetto_cmd_gen_cc_config_descriptor",
-        ":src_perfetto_cmd_protos_cpp",
     ] + PERFETTO_CONFIG.deps.zlib,
     linkstatic = True,
 )
@@ -1099,11 +1091,7 @@
     srcs = [
         "src/kernel_utils/syscall_table.cc",
         "src/kernel_utils/syscall_table.h",
-        "src/kernel_utils/syscalls_aarch32.h",
-        "src/kernel_utils/syscalls_aarch64.h",
-        "src/kernel_utils/syscalls_armeabi.h",
-        "src/kernel_utils/syscalls_x86.h",
-        "src/kernel_utils/syscalls_x86_64.h",
+        "src/kernel_utils/syscall_table_generated.h",
     ],
 )
 
@@ -1150,14 +1138,6 @@
     ],
 )
 
-# GN target: //src/perfetto_cmd:trigger_perfetto_cmd
-perfetto_filegroup(
-    name = "src_perfetto_cmd_trigger_perfetto_cmd",
-    srcs = [
-        "src/perfetto_cmd/trigger_perfetto.cc",
-    ],
-)
-
 # GN target: //src/perfetto_cmd:trigger_producer
 perfetto_filegroup(
     name = "src_perfetto_cmd_trigger_producer",
@@ -1291,7 +1271,6 @@
         "src/trace_processor/containers/bit_vector.h",
         "src/trace_processor/containers/bit_vector_iterators.h",
         "src/trace_processor/containers/null_term_string_view.h",
-        "src/trace_processor/containers/nullable_vector.h",
         "src/trace_processor/containers/row_map.h",
         "src/trace_processor/containers/row_map_algorithms.h",
         "src/trace_processor/containers/string_pool.h",
@@ -1586,6 +1565,10 @@
 perfetto_filegroup(
     name = "src_trace_processor_importers_proto_winscope_full",
     srcs = [
+        "src/trace_processor/importers/proto/winscope/protolog_messages_tracker.cc",
+        "src/trace_processor/importers/proto/winscope/protolog_messages_tracker.h",
+        "src/trace_processor/importers/proto/winscope/protolog_parser.cc",
+        "src/trace_processor/importers/proto/winscope/protolog_parser.h",
         "src/trace_processor/importers/proto/winscope/shell_transitions_parser.cc",
         "src/trace_processor/importers/proto/winscope/shell_transitions_parser.h",
         "src/trace_processor/importers/proto/winscope/shell_transitions_tracker.cc",
@@ -2187,6 +2170,8 @@
         "src/trace_processor/perfetto_sql/intrinsics/table_functions/connected_flow.h",
         "src/trace_processor/perfetto_sql/intrinsics/table_functions/descendant.cc",
         "src/trace_processor/perfetto_sql/intrinsics/table_functions/descendant.h",
+        "src/trace_processor/perfetto_sql/intrinsics/table_functions/dfs.cc",
+        "src/trace_processor/perfetto_sql/intrinsics/table_functions/dfs.h",
         "src/trace_processor/perfetto_sql/intrinsics/table_functions/dominator_tree.cc",
         "src/trace_processor/perfetto_sql/intrinsics/table_functions/dominator_tree.h",
         "src/trace_processor/perfetto_sql/intrinsics/table_functions/experimental_annotated_stack.cc",
@@ -2247,11 +2232,11 @@
 perfetto_filegroup(
     name = "src_trace_processor_perfetto_sql_stdlib_android_startup_startup",
     srcs = [
-        "src/trace_processor/perfetto_sql/stdlib/android/startup/internal_startup_events.sql",
-        "src/trace_processor/perfetto_sql/stdlib/android/startup/internal_startups_maxsdk28.sql",
-        "src/trace_processor/perfetto_sql/stdlib/android/startup/internal_startups_minsdk29.sql",
-        "src/trace_processor/perfetto_sql/stdlib/android/startup/internal_startups_minsdk33.sql",
+        "src/trace_processor/perfetto_sql/stdlib/android/startup/startup_events.sql",
         "src/trace_processor/perfetto_sql/stdlib/android/startup/startups.sql",
+        "src/trace_processor/perfetto_sql/stdlib/android/startup/startups_maxsdk28.sql",
+        "src/trace_processor/perfetto_sql/stdlib/android/startup/startups_minsdk29.sql",
+        "src/trace_processor/perfetto_sql/stdlib/android/startup/startups_minsdk33.sql",
     ],
 )
 
@@ -2260,9 +2245,11 @@
     name = "src_trace_processor_perfetto_sql_stdlib_android_android",
     srcs = [
         "src/trace_processor/perfetto_sql/stdlib/android/anrs.sql",
+        "src/trace_processor/perfetto_sql/stdlib/android/app_process_starts.sql",
         "src/trace_processor/perfetto_sql/stdlib/android/battery.sql",
         "src/trace_processor/perfetto_sql/stdlib/android/battery_stats.sql",
         "src/trace_processor/perfetto_sql/stdlib/android/binder.sql",
+        "src/trace_processor/perfetto_sql/stdlib/android/broadcasts.sql",
         "src/trace_processor/perfetto_sql/stdlib/android/dvfs.sql",
         "src/trace_processor/perfetto_sql/stdlib/android/io.sql",
         "src/trace_processor/perfetto_sql/stdlib/android/monitor_contention.sql",
@@ -2296,24 +2283,12 @@
     ],
 )
 
-# GN target: //src/trace_processor/perfetto_sql/stdlib/experimental:experimental
-perfetto_filegroup(
-    name = "src_trace_processor_perfetto_sql_stdlib_experimental_experimental",
-    srcs = [
-        "src/trace_processor/perfetto_sql/stdlib/experimental/android_broadcast.sql",
-        "src/trace_processor/perfetto_sql/stdlib/experimental/flat_slices.sql",
-        "src/trace_processor/perfetto_sql/stdlib/experimental/proto_path.sql",
-        "src/trace_processor/perfetto_sql/stdlib/experimental/slices.sql",
-        "src/trace_processor/perfetto_sql/stdlib/experimental/thread_executing_span.sql",
-        "src/trace_processor/perfetto_sql/stdlib/experimental/thread_state_flattened.sql",
-    ],
-)
-
 # GN target: //src/trace_processor/perfetto_sql/stdlib/graphs:graphs
 perfetto_filegroup(
     name = "src_trace_processor_perfetto_sql_stdlib_graphs_graphs",
     srcs = [
         "src/trace_processor/perfetto_sql/stdlib/graphs/dominator_tree.sql",
+        "src/trace_processor/perfetto_sql/stdlib/graphs/search.sql",
     ],
 )
 
@@ -2353,7 +2328,18 @@
 perfetto_filegroup(
     name = "src_trace_processor_perfetto_sql_stdlib_sched_sched",
     srcs = [
+        "src/trace_processor/perfetto_sql/stdlib/sched/thread_executing_span.sql",
         "src/trace_processor/perfetto_sql/stdlib/sched/thread_level_parallelism.sql",
+        "src/trace_processor/perfetto_sql/stdlib/sched/thread_state_flattened.sql",
+    ],
+)
+
+# GN target: //src/trace_processor/perfetto_sql/stdlib/slices:slices
+perfetto_filegroup(
+    name = "src_trace_processor_perfetto_sql_stdlib_slices_slices",
+    srcs = [
+        "src/trace_processor/perfetto_sql/stdlib/slices/flat_slices.sql",
+        "src/trace_processor/perfetto_sql/stdlib/slices/slices.sql",
     ],
 )
 
@@ -2365,13 +2351,13 @@
         ":src_trace_processor_perfetto_sql_stdlib_android_startup_startup",
         ":src_trace_processor_perfetto_sql_stdlib_chrome_chrome_sql",
         ":src_trace_processor_perfetto_sql_stdlib_common_common",
-        ":src_trace_processor_perfetto_sql_stdlib_experimental_experimental",
         ":src_trace_processor_perfetto_sql_stdlib_graphs_graphs",
         ":src_trace_processor_perfetto_sql_stdlib_intervals_intervals",
         ":src_trace_processor_perfetto_sql_stdlib_linux_linux",
         ":src_trace_processor_perfetto_sql_stdlib_pkvm_pkvm",
         ":src_trace_processor_perfetto_sql_stdlib_prelude_prelude",
         ":src_trace_processor_perfetto_sql_stdlib_sched_sched",
+        ":src_trace_processor_perfetto_sql_stdlib_slices_slices",
     ],
     outs = [
         "src/trace_processor/perfetto_sql/stdlib/stdlib.h",
@@ -5200,14 +5186,92 @@
 perfetto_cc_binary(
     name = "perfetto",
     srcs = [
+        ":include_perfetto_base_base",
+        ":include_perfetto_ext_base_base",
+        ":include_perfetto_ext_ipc_ipc",
         ":include_perfetto_ext_traced_traced",
+        ":include_perfetto_ext_tracing_core_core",
+        ":include_perfetto_ext_tracing_ipc_ipc",
+        ":include_perfetto_protozero_protozero",
+        ":include_perfetto_public_abi_base",
+        ":include_perfetto_public_base",
+        ":include_perfetto_public_protozero",
+        ":include_perfetto_tracing_core_core",
+        ":include_perfetto_tracing_core_forward_decls",
+        ":include_perfetto_tracing_tracing",
+        ":src_android_stats_android_stats",
+        ":src_android_stats_perfetto_atoms",
+        ":src_perfetto_cmd_bugreport_path",
+        ":src_perfetto_cmd_pbtxt_to_pb",
+        ":src_perfetto_cmd_perfetto_cmd",
+        ":src_perfetto_cmd_trigger_producer",
+        ":src_tracing_common",
+        ":src_tracing_core_core",
+        ":src_tracing_ipc_common",
+        ":src_tracing_ipc_consumer_consumer",
+        ":src_tracing_ipc_default_socket",
+        ":src_tracing_ipc_producer_producer",
         "src/perfetto_cmd/main.cc",
     ],
     visibility = [
         "//visibility:public",
     ],
     deps = [
-        ":libperfetto",
+        ":perfetto_ipc",
+        ":protos_perfetto_common_cpp",
+        ":protos_perfetto_common_zero",
+        ":protos_perfetto_config_android_cpp",
+        ":protos_perfetto_config_android_zero",
+        ":protos_perfetto_config_cpp",
+        ":protos_perfetto_config_ftrace_cpp",
+        ":protos_perfetto_config_ftrace_zero",
+        ":protos_perfetto_config_gpu_cpp",
+        ":protos_perfetto_config_gpu_zero",
+        ":protos_perfetto_config_inode_file_cpp",
+        ":protos_perfetto_config_inode_file_zero",
+        ":protos_perfetto_config_interceptors_cpp",
+        ":protos_perfetto_config_interceptors_zero",
+        ":protos_perfetto_config_power_cpp",
+        ":protos_perfetto_config_power_zero",
+        ":protos_perfetto_config_process_stats_cpp",
+        ":protos_perfetto_config_process_stats_zero",
+        ":protos_perfetto_config_profiling_cpp",
+        ":protos_perfetto_config_profiling_zero",
+        ":protos_perfetto_config_statsd_cpp",
+        ":protos_perfetto_config_statsd_zero",
+        ":protos_perfetto_config_sys_stats_cpp",
+        ":protos_perfetto_config_sys_stats_zero",
+        ":protos_perfetto_config_system_info_cpp",
+        ":protos_perfetto_config_system_info_zero",
+        ":protos_perfetto_config_track_event_cpp",
+        ":protos_perfetto_config_track_event_zero",
+        ":protos_perfetto_config_zero",
+        ":protos_perfetto_ipc_cpp",
+        ":protos_perfetto_ipc_ipc",
+        ":protos_perfetto_trace_android_zero",
+        ":protos_perfetto_trace_chrome_zero",
+        ":protos_perfetto_trace_etw_zero",
+        ":protos_perfetto_trace_filesystem_zero",
+        ":protos_perfetto_trace_ftrace_zero",
+        ":protos_perfetto_trace_gpu_zero",
+        ":protos_perfetto_trace_interned_data_zero",
+        ":protos_perfetto_trace_minimal_zero",
+        ":protos_perfetto_trace_non_minimal_zero",
+        ":protos_perfetto_trace_perfetto_zero",
+        ":protos_perfetto_trace_power_zero",
+        ":protos_perfetto_trace_profiling_zero",
+        ":protos_perfetto_trace_ps_zero",
+        ":protos_perfetto_trace_statsd_zero",
+        ":protos_perfetto_trace_sys_stats_zero",
+        ":protos_perfetto_trace_system_info_zero",
+        ":protos_perfetto_trace_track_event_cpp",
+        ":protos_perfetto_trace_track_event_zero",
+        ":protos_perfetto_trace_translation_zero",
+        ":protozero",
+        ":src_base_base",
+        ":src_base_version",
+        ":src_perfetto_cmd_gen_cc_config_descriptor",
+        ":src_perfetto_cmd_protos_cpp",
     ],
 )
 
diff --git a/BUILD.gn b/BUILD.gn
index d52ed7d..a80de8d 100644
--- a/BUILD.gn
+++ b/BUILD.gn
@@ -246,8 +246,6 @@
     deps = [
       "gn:default_deps",
       "src/traced/service",
-      "src/perfetto_cmd",
-      "src/perfetto_cmd:trigger_perfetto_cmd",
     ]
     if (enable_perfetto_traced_probes) {
       deps += [ "src/traced/probes" ]
diff --git a/docs/analysis/perfetto-sql-syntax.md b/docs/analysis/perfetto-sql-syntax.md
index 3170ec8..cb9418a 100644
--- a/docs/analysis/perfetto-sql-syntax.md
+++ b/docs/analysis/perfetto-sql-syntax.md
@@ -125,13 +125,89 @@
 SELECT 1 as x, 'test' as y
 ```
 
-## CREATE PERFETTO VIEW
+## Creating views with a schema
 
 Views can be created via `CREATE PERFETTO VIEW`, taking an optional schema.
 With the exception of the schema, they behave exactly the same as regular
 SQLite views.
 
+NOTE: the use of `CREATE PERFETTO VIEW` instead of `CREATE VIEW` is required in
+the standard library where each column must be documented.
+
 ```sql
 CREATE PERFETTO VIEW foo(x INT, y STRING) AS
 SELECT 1 as x, 'test' as y
+```
+
+## Defining macros
+`CREATE PEFETTO MACRO` allows macros to be defined in SQL. The design of macros
+is inspired by the macros in Rust.
+
+The following are recommended uses of macros:
+- Passing tables as arguments to a "function-like" snippet of SQL.
+
+Macros are powerful but also dangerous if used incorrectly, making debugging
+extremely difficult. For this reason, it's recommended that they are used
+sparingly when they are needed and only for the recommended uses described
+above. If only passing around scalar SQL values, use functions as discussed
+above.
+
+NOTE: Macros are expanded with a pre-processing step *before* any execution
+happens. Expansion is a purely syntatic operation involves replacing the macro
+invocation with the SQL tokens in the macro definition.
+
+As macros are syntactic, the types of arguments and return types in macros are
+different to the types used in functions and correspond to parts of the SQL
+parse tree. The following are the supported types:
+
+| Type name         | Description                                       |
+| ---------         | -----------                                       |
+| `Expr`            | Corresponds to any SQL scalar expression.         |
+| `TableOrSubquery` | Corresponds to either an SQL table or a subquery  |
+| `ColumnName`      | Corresponds to a column name of a table           |
+
+Example:
+```sql
+-- Create a macro taking no arguments. Note how the returned SQL fragment needs
+-- to be wrapped in brackets to make it a valid SQL expression.
+--
+-- Note: this is a strongly discouraged use of macros as a simple SQL
+-- function would also work here.
+CREATE PERFETTO MACRO constant_macro() RETURNS Expr AS (SELECT 1);
+
+-- Using the above macro. Macros are invoked by suffixing their names with !.
+-- This is similar to how macros are invoked in Rust.
+SELECT constant_macro!();
+
+-- This causes the following SQL to be actually executed:
+-- SELECT (SELECT 1);
+
+-- A variant of the above. Again, strongly discouraged.
+CREATE PERFETTO MACRO constant_macro_no_bracket() RETURNS Expr AS 2;
+
+-- Using the above macro.
+SELECT constant_macro_no_bracket!();
+
+-- This causes the following SQL to be actually executed:
+-- SELECT 2;
+
+-- Creating a macro taking a single scalar argument and returning a scalar.
+-- Note: again this is a strongly discouraged use of macros as functions can
+-- also do this.
+CREATE PERFETTO MACRO single_arg_macro(x Expr) RETURNS Expr AS (SELECT $x);
+SELECT constant_macro!() + single_arg_macro!(100);
+
+-- Creating a macro taking both a table and a scalar expression as an argument
+-- and returning a table. Note again how the returned SQL statement is wrapped
+-- in brackets to make it a subquery. This allows it to be used anywhere a
+-- table or subquery is allowed.
+--
+-- Note: if tables are reused multiple times, it's recommended that they be
+-- "cached" with a common-table expression (CTE) for performance reasons.
+CREATE PERFETTO MACRO multi_arg_macro(x TableOrSubquery, y Expr)
+RETURNS TableOrSubquery AS
+(
+  SELECT input_tab.input_col + $y
+  FROM $x AS input_tab;
+)
 ```
\ No newline at end of file
diff --git a/gn/perfetto.gni b/gn/perfetto.gni
index 7816d73..8cd9b08 100644
--- a/gn/perfetto.gni
+++ b/gn/perfetto.gni
@@ -208,7 +208,7 @@
   # are monolithic and don't use a common shared library. This is mainly to
   # avoid LD_LIBRARY_PATH dances when testing locally.
   # On Windows we default to monolithic executables, because pairing
-  # dllexport/import adds extra complexity for little benefit. The only reason
+  # dllexport/import adds extra complexity for little benefit. Te only reason
   # for monolithic_binaries=false is saving binary size, which matters mainly on
   # Android. See also comments on PERFETTO_EXPORT_ENTRYPOINT in compiler.h.
   monolithic_binaries = !perfetto_build_with_android && (is_win || is_mac)
diff --git a/gn/perfetto_unittests.gni b/gn/perfetto_unittests.gni
index a8f16a5..2769a63 100644
--- a/gn/perfetto_unittests.gni
+++ b/gn/perfetto_unittests.gni
@@ -48,6 +48,7 @@
   perfetto_unittests_targets += [
     "src/perfetto_cmd:unittests",
     "src/traced/service:unittests",
+    "src/kernel_utils:unittests",
   ]
   if (enable_perfetto_traced_probes) {
     perfetto_unittests_targets += [
diff --git a/include/perfetto/ext/tracing/core/BUILD.gn b/include/perfetto/ext/tracing/core/BUILD.gn
index e21c4fb..601e0ce 100644
--- a/include/perfetto/ext/tracing/core/BUILD.gn
+++ b/include/perfetto/ext/tracing/core/BUILD.gn
@@ -35,3 +35,7 @@
     "tracing_service.h",
   ]
 }
+
+source_set("test_support") {
+  sources = [ "null_consumer_endpoint_for_testing.h" ]
+}
diff --git a/include/perfetto/ext/tracing/core/null_consumer_endpoint_for_testing.h b/include/perfetto/ext/tracing/core/null_consumer_endpoint_for_testing.h
new file mode 100644
index 0000000..2e85c92
--- /dev/null
+++ b/include/perfetto/ext/tracing/core/null_consumer_endpoint_for_testing.h
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef INCLUDE_PERFETTO_EXT_TRACING_CORE_NULL_CONSUMER_ENDPOINT_FOR_TESTING_H_
+#define INCLUDE_PERFETTO_EXT_TRACING_CORE_NULL_CONSUMER_ENDPOINT_FOR_TESTING_H_
+
+#include "perfetto/ext/tracing/core/tracing_service.h"
+
+namespace perfetto {
+
+// An empty implemetation of ConsumerEndpoint. This is used only to handle
+// code in other repos like arctraceservice/PerfettoClient_test.cpp which
+// ended up depending on internal perfetto interfaces against our plans.
+// This allows to make changes to the ConsumerEndpoint without requiring 3way
+// patches when touching methods that are not overridden by other projects.
+class NullConsumerEndpointForTesting : public ConsumerEndpoint {
+ public:
+  ~NullConsumerEndpointForTesting() override {}
+
+  void EnableTracing(const TraceConfig&, base::ScopedFile) override {}
+  void ChangeTraceConfig(const perfetto::TraceConfig&) override {}
+  void StartTracing() override {}
+  void DisableTracing() override {}
+  void CloneSession(TracingSessionID, CloneSessionArgs) override {}
+  void Flush(uint32_t, FlushCallback, FlushFlags) override {}
+  void ReadBuffers() override {}
+  void FreeBuffers() override {}
+  void Detach(const std::string&) override {}
+  void Attach(const std::string&) override {}
+  void GetTraceStats() override {}
+  void ObserveEvents(uint32_t) override {}
+  void QueryServiceState(ConsumerEndpoint::QueryServiceStateArgs,
+                         ConsumerEndpoint::QueryServiceStateCallback) override {
+  }
+  void QueryCapabilities(ConsumerEndpoint::QueryCapabilitiesCallback) override {
+  }
+  void SaveTraceForBugreport(
+      ConsumerEndpoint::SaveTraceForBugreportCallback) override {}
+};
+
+}  // namespace perfetto
+
+#endif  // INCLUDE_PERFETTO_EXT_TRACING_CORE_NULL_CONSUMER_ENDPOINT_FOR_TESTING_H_
diff --git a/infra/perfetto.dev/src/gen_stdlib_docs_md.py b/infra/perfetto.dev/src/gen_stdlib_docs_md.py
index b0ed5c7..47007a7 100644
--- a/infra/perfetto.dev/src/gen_stdlib_docs_md.py
+++ b/infra/perfetto.dev/src/gen_stdlib_docs_md.py
@@ -23,6 +23,11 @@
 from typing import Any, List, Dict
 
 
+# Escapes special characters in a markdown table.
+def escape_in_table(desc: str):
+  return desc.replace('|', '\\|')
+
+
 # Responsible for module level markdown generation.
 class ModuleMd:
 
@@ -39,6 +44,8 @@
     self.summary_view_funs = '\n'.join(file.summary_view_funs
                                        for file in self.files_md
                                        if file.summary_view_funs)
+    self.summary_macros = '\n'.join(
+        file.summary_macros for file in self.files_md if file.summary_macros)
 
   def print_description(self):
     if not self.files_md:
@@ -63,10 +70,15 @@
       if table_funs:
         long_s.append('#### Table Functions')
         long_s.append(table_funs)
+      macros = '\n'.join(
+          macro for file in self.files_md for macro in file.macros)
+      if macros:
+        long_s.append('#### Macros')
+        long_s.append(macros)
       return '\n'.join(long_s)
 
     for file in self.files_md:
-      if not file.objs and not file.funs and not file.view_funs:
+      if not any((file.objs, file.funs, file.view_funs, file.macros)):
         continue
 
       long_s.append(f'### {file.import_key}')
@@ -79,6 +91,9 @@
       if file.view_funs:
         long_s.append('#### Table Functions')
         long_s.append('\n'.join(file.view_funs))
+      if file.macros:
+        long_s.append('#### Macros')
+        long_s.append('\n'.join(file.macros))
 
     return '\n'.join(long_s)
 
@@ -89,8 +104,8 @@
   def __init__(self, module_name, file_dict):
     self.import_key = file_dict['import_key']
     import_key_name = self.import_key if module_name != 'prelude' else 'N/A'
-    self.objs, self.funs, self.view_funs = [], [], []
-    summary_objs_list, summary_funs_list, summary_view_funs_list = [], [], []
+    self.objs, self.funs, self.view_funs, self.macros = [], [], [], []
+    summary_objs_list, summary_funs_list, summary_view_funs_list, summary_macros_list = [], [], [], []
 
     # Add imports if in file.
     for data in file_dict['imports']:
@@ -98,19 +113,19 @@
       anchor = f'''obj/{module_name}/{data['name']}'''
 
       # Add summary of imported view/table
-      desc = data['desc'].split('.')[0]
       summary_objs_list.append(f'''[{data['name']}](#{anchor})|'''
                                f'''{import_key_name}|'''
-                               f'''{desc}''')
+                               f'''{escape_in_table(data['summary_desc'])}''')
 
       self.objs.append(f'''\n\n<a name="{anchor}"></a>'''
                        f'''**{data['name']}**, {data['type']}\n\n'''
-                       f'''{data['desc']}\n''')
+                       f'''{escape_in_table(data['desc'])}\n''')
 
       self.objs.append(
           'Column | Type | Description\n------ | --- | -----------')
       for name, info in data['cols'].items():
-        self.objs.append(f'{name} | {info["type"]} | {info["desc"]}')
+        self.objs.append(
+            f'{name} | {info["type"]} | {escape_in_table(info["desc"])}')
 
       self.objs.append('\n\n')
 
@@ -123,10 +138,10 @@
       summary_funs_list.append(f'''[{data['name']}](#{anchor})|'''
                                f'''{import_key_name}|'''
                                f'''{data['return_type']}|'''
-                               f'''{data['desc'].split('.')[0]}''')
+                               f'''{escape_in_table(data['summary_desc'])}''')
       self.funs.append(
           f'''\n\n<a name="{anchor}"></a>'''
-          f'''**{data['name']}**\n'''
+          f'''**{data['name']}**\n\n'''
           f'''{data['desc']}\n\n'''
           f'''Returns: {data['return_type']}, {data['return_desc']}\n\n''')
       if data['args']:
@@ -134,7 +149,8 @@
                          '-------- | ---- | -----------')
         for name, arg_dict in data['args'].items():
           self.funs.append(
-              f'''{name} | {arg_dict['type']} | {arg_dict['desc']}''')
+              f'''{name} | {arg_dict['type']} | {escape_in_table(arg_dict['desc'])}'''
+          )
 
         self.funs.append('\n\n')
 
@@ -143,9 +159,10 @@
       # Anchor
       anchor = rf'''view_fun/{module_name}/{data['name']}'''
       # Add summary of imported view function
-      summary_view_funs_list.append(f'''[{data['name']}](#{anchor})|'''
-                                    f'''{import_key_name}|'''
-                                    f'''{data['desc'].split('.')[0]}''')
+      summary_view_funs_list.append(
+          f'''[{data['name']}](#{anchor})|'''
+          f'''{import_key_name}|'''
+          f'''{escape_in_table(data['summary_desc'])}''')
 
       self.view_funs.append(f'''\n\n<a name="{anchor}"></a>'''
                             f'''**{data['name']}**\n'''
@@ -155,7 +172,8 @@
                               '-------- | ---- | -----------')
         for name, arg_dict in data['args'].items():
           self.view_funs.append(
-              f'''{name} | {arg_dict['type']} | {arg_dict['desc']}''')
+              f'''{name} | {arg_dict['type']} | {escape_in_table(arg_dict['desc'])}'''
+          )
         self.view_funs.append('\n')
       self.view_funs.append('Column | Type | Description\n'
                             '------ | -- | -----------')
@@ -164,9 +182,34 @@
 
       self.view_funs.append('\n\n')
 
+    # Add macros if in file
+    for data in file_dict['macros']:
+      # Anchor
+      anchor = rf'''macro/{module_name}/{data['name']}'''
+      # Add summary of imported view function
+      summary_macros_list.append(f'''[{data['name']}](#{anchor})|'''
+                                 f'''{import_key_name}|'''
+                                 f'''{escape_in_table(data['summary_desc'])}''')
+
+      self.macros.append(
+          f'''\n\n<a name="{anchor}"></a>'''
+          f'''**{data['name']}**\n'''
+          f'''{data['desc']}\n\n'''
+          f'''Returns: {data['return_type']}, {data['return_desc']}\n\n''')
+      if data['args']:
+        self.macros.append('Argument | Type | Description\n'
+                           '-------- | ---- | -----------')
+        for name, arg_dict in data['args'].items():
+          self.macros.append(
+              f'''{name} | {arg_dict['type']} | {escape_in_table(arg_dict['desc'])}'''
+          )
+        self.macros.append('\n')
+      self.macros.append('\n\n')
+
     self.summary_objs = '\n'.join(summary_objs_list)
     self.summary_funs = '\n'.join(summary_funs_list)
     self.summary_view_funs = '\n'.join(summary_view_funs_list)
+    self.summary_macros = '\n'.join(summary_macros_list)
 
 
 def main():
@@ -178,7 +221,7 @@
   with open(args.input) as f:
     modules_json_dict = json.load(f)
 
-  modules_dict = {}
+  modules_dict: Dict[str, ModuleMd] = {}
 
   for module_name, module_files in modules_json_dict.items():
     modules_dict[module_name] = ModuleMd(module_name, module_files)
@@ -257,6 +300,15 @@
         for name, module in modules_dict.items()
         if (module.summary_view_funs and name != 'experimental')
     ]
+    summary_macros = [prelude_module.summary_macros
+                     ] if prelude_module.summary_macros else []
+    summary_macros += [common_module.summary_macros
+                      ] if common_module.summary_macros else []
+    summary_macros += [
+        module.summary_macros
+        for name, module in modules_dict.items()
+        if (module.summary_macros and name != 'experimental')
+    ]
 
     if summary_objs:
       f.write('### Views/tables\n\n'
@@ -279,6 +331,13 @@
       f.write('\n'.join(summary_view_funs))
       f.write('\n')
 
+    if summary_macros:
+      f.write('### Macros\n\n'
+              'Name | Import |  Description\n'
+              '---- | ------ |  -----------\n')
+      f.write('\n'.join(summary_macros))
+      f.write('\n')
+
     f.write('\n\n')
     f.write(prelude_module.print_description())
     f.write('\n')
diff --git a/protos/perfetto/metrics/android/ad_services_metric.proto b/protos/perfetto/metrics/android/ad_services_metric.proto
index 1a3ed93..a14ed4f 100644
--- a/protos/perfetto/metrics/android/ad_services_metric.proto
+++ b/protos/perfetto/metrics/android/ad_services_metric.proto
@@ -23,7 +23,7 @@
   optional double common_service_initialization_latency = 1;
   optional double common_service_permission_check_latency = 2;
   optional double common_service_ux_engine_flow_latency = 3;
-  optional double main_actitivity_creation_latency = 4;
+  optional double main_activity_creation_latency = 4;
   optional double consent_manager_initialization_latency = 5;
   optional double consent_manager_read_latency = 6;
   optional double consent_manager_write_latency = 7;
@@ -39,9 +39,18 @@
   optional double latency = 1;
 }
 
-// Next: 4
+// Next: 5
+message OnDevicePersonalizationMetric {
+  optional double managing_service_initialization_latency = 1;
+  optional double service_delegate_execute_flow_latency = 2;
+  optional double service_delegate_request_surface_package_latency = 3;
+  optional double service_delegate_register_web_trigger_latency = 4;
+}
+
+// Next: 5
 message AdServicesMetric {
   repeated AdServicesUiMetric ui_metric = 1;
   repeated AdServicesAdIdMetric ad_id_metric = 2;
   repeated AdServicesAppSetIdMetric app_set_id_metric = 3;
+  repeated OnDevicePersonalizationMetric odp_metric = 4;
 }
\ No newline at end of file
diff --git a/protos/perfetto/metrics/perfetto_merged_metrics.proto b/protos/perfetto/metrics/perfetto_merged_metrics.proto
index 94d79ac..904258a 100644
--- a/protos/perfetto/metrics/perfetto_merged_metrics.proto
+++ b/protos/perfetto/metrics/perfetto_merged_metrics.proto
@@ -20,7 +20,7 @@
   optional double common_service_initialization_latency = 1;
   optional double common_service_permission_check_latency = 2;
   optional double common_service_ux_engine_flow_latency = 3;
-  optional double main_actitivity_creation_latency = 4;
+  optional double main_activity_creation_latency = 4;
   optional double consent_manager_initialization_latency = 5;
   optional double consent_manager_read_latency = 6;
   optional double consent_manager_write_latency = 7;
@@ -36,11 +36,20 @@
   optional double latency = 1;
 }
 
-// Next: 4
+// Next: 5
+message OnDevicePersonalizationMetric {
+  optional double managing_service_initialization_latency = 1;
+  optional double service_delegate_execute_flow_latency = 2;
+  optional double service_delegate_request_surface_package_latency = 3;
+  optional double service_delegate_register_web_trigger_latency = 4;
+}
+
+// Next: 5
 message AdServicesMetric {
   repeated AdServicesUiMetric ui_metric = 1;
   repeated AdServicesAdIdMetric ad_id_metric = 2;
   repeated AdServicesAppSetIdMetric app_set_id_metric = 3;
+  repeated OnDevicePersonalizationMetric odp_metric = 4;
 }
 // End of protos/perfetto/metrics/android/ad_services_metric.proto
 
diff --git a/protos/perfetto/trace_processor/trace_processor.proto b/protos/perfetto/trace_processor/trace_processor.proto
index 48959ad..c96caa0 100644
--- a/protos/perfetto/trace_processor/trace_processor.proto
+++ b/protos/perfetto/trace_processor/trace_processor.proto
@@ -47,7 +47,8 @@
   // 8. Add 'json' option to ComputeMetricArgs
   // 9. Add get_thread_state_summary_for_interval.
   // 10. Add 'slice_is_ancestor' to stdlib.
-  TRACE_PROCESSOR_CURRENT_API_VERSION = 10;
+  // 11. Removal of experimental module from stdlib.
+  TRACE_PROCESSOR_CURRENT_API_VERSION = 11;
 }
 
 // At lowest level, the wire-format of the RPC procol is a linear sequence of
diff --git a/python/generators/sql_processing/docs_extractor.py b/python/generators/sql_processing/docs_extractor.py
index c42774e..99571f0 100644
--- a/python/generators/sql_processing/docs_extractor.py
+++ b/python/generators/sql_processing/docs_extractor.py
@@ -56,6 +56,7 @@
     extracted += self._extract_for_kind(ObjKind.table_view)
     extracted += self._extract_for_kind(ObjKind.function)
     extracted += self._extract_for_kind(ObjKind.table_function)
+    extracted += self._extract_for_kind(ObjKind.macro)
     return extracted
 
   def _extract_for_kind(self, kind: ObjKind) -> List[Extract]:
@@ -75,18 +76,15 @@
       assert line.startswith('--')
 
       # Remove the comment.
-      stripped = line.lstrip('--').lstrip()
-
-      # Ignore lines which only contain '--'.
-      if not stripped:
-        continue
+      comment_stripped = line.lstrip('--')
+      stripped = comment_stripped.lstrip()
 
       # Check if the line is an annotation.
       if not stripped.startswith('@'):
         # We are not in annotation: if we haven't seen an annotation yet, we
         # must be still be parsing the description. Just add to that
         if not extract.annotations:
-          extract.description += stripped + " "
+          extract.description += comment_stripped + "\n"
           continue
 
         # Otherwise, add to the latest annotation.
diff --git a/python/generators/sql_processing/docs_parse.py b/python/generators/sql_processing/docs_parse.py
index 564679a..31cea3c 100644
--- a/python/generators/sql_processing/docs_parse.py
+++ b/python/generators/sql_processing/docs_parse.py
@@ -22,13 +22,11 @@
 from python.generators.sql_processing.docs_extractor import DocsExtractor
 from python.generators.sql_processing.utils import ALLOWED_PREFIXES, ANY_PATTERN, ARG_DEFINITION_PATTERN, ObjKind
 from python.generators.sql_processing.utils import ARG_ANNOTATION_PATTERN
-from python.generators.sql_processing.utils import NAME_AND_TYPE_PATTERN
-from python.generators.sql_processing.utils import FUNCTION_RETURN_PATTERN
 from python.generators.sql_processing.utils import COLUMN_ANNOTATION_PATTERN
 
 
 def is_internal(name: str) -> bool:
-  return re.match(r'^internal_.*', name, re.IGNORECASE) is not None
+  return re.match(r'^_.*', name, re.IGNORECASE) is not None
 
 
 def is_snake_case(s: str) -> bool:
@@ -94,7 +92,7 @@
 
   def _parse_desc_not_empty(self, desc: str):
     if not desc:
-      self._error('Description of the table/view/function is missing')
+      self._error('Description of the table/view/function/macro is missing')
     return desc.strip()
 
   def _validate_only_contains_annotations(self,
@@ -194,7 +192,7 @@
                     '({ARG_DEFINITION_PATTERN})')
         return result
       groups = m.groups()
-      comment = None if groups[0] is None else parse_comment(groups[0])
+      comment = '' if groups[0] is None else parse_comment(groups[0])
       name = groups[-3]
       type = groups[-2]
       result[name] = Arg(type, comment)
@@ -235,7 +233,9 @@
 
     if or_replace is not None:
       self._error(
-          f'{type} "{self.name}": CREATE OR REPLACE is not allowed in stdlib')
+          f'{type} "{self.name}": CREATE OR REPLACE is not allowed in stdlib '
+          f'as standard library modules can only included once. Please just '
+          f'use CREATE instead.')
     if is_internal(self.name):
       return None
 
@@ -281,7 +281,9 @@
 
     if or_replace is not None:
       self._error(
-          f'Function "{self.name}": CREATE OR REPLACE is not allowed in stdlib')
+          f'Function "{self.name}": CREATE OR REPLACE is not allowed in stdlib '
+          f'as standard library modules can only included once. Please just '
+          f'use CREATE instead.')
 
     # Ignore internal functions.
     if is_internal(self.name):
@@ -330,7 +332,9 @@
 
     if or_replace is not None:
       self._error(
-          f'Function "{self.name}": CREATE OR REPLACE is not allowed in stdlib')
+          f'Function "{self.name}": CREATE OR REPLACE is not allowed in stdlib '
+          f'as standard library modules can only included once. Please just '
+          f'use CREATE instead.')
 
     # Ignore internal functions.
     if is_internal(self.name):
@@ -352,17 +356,72 @@
     )
 
 
+class Macro:
+  name: str
+  desc: str
+  return_desc: str
+  return_type: str
+  args: Dict[str, Arg]
+
+  def __init__(self, name: str, desc: str, return_desc: str, return_type: str,
+               args: Dict[str, Arg]):
+    self.name = name
+    self.desc = desc
+    self.return_desc = return_desc
+    self.return_type = return_type
+    self.args = args
+
+
+class MacroDocParser(AbstractDocParser):
+  """Parses documentation for macro statements."""
+
+  def __init__(self, path: str, module: str):
+    super().__init__(path, module)
+
+  def parse(self, doc: DocsExtractor.Extract) -> Optional[Macro]:
+    or_replace, self.name, args, return_desc, return_type = doc.obj_match
+
+    if or_replace is not None:
+      self._error(
+          f'Function "{self.name}": CREATE OR REPLACE is not allowed in stdlib '
+          f'as standard library modules can only included once. Please just '
+          f'use CREATE instead.')
+
+    # Ignore internal macros.
+    if is_internal(self.name):
+      return None
+
+    self._validate_only_contains_annotations(doc.annotations, set())
+    name = self._parse_name()
+
+    if not is_snake_case(name):
+      self._error(f'Macro name "{name}" is not snake_case'
+                  f' (should be "{name.casefold()}")')
+
+    return Macro(
+        name=name,
+        desc=self._parse_desc_not_empty(doc.description),
+        return_desc=parse_comment(return_desc),
+        return_type=return_type,
+        args=self._parse_args(doc.annotations, args),
+    )
+
+
 class ParsedFile:
   errors: List[str] = []
   table_views: List[TableOrView] = []
   functions: List[Function] = []
   table_functions: List[TableFunction] = []
+  macros: List[Macro] = []
 
-  def __init__(self, errors, table_views, functions, table_functions):
+  def __init__(self, errors: List[str], table_views: List[TableOrView],
+               functions: List[Function], table_functions: List[TableFunction],
+               macros: List[Macro]):
     self.errors = errors
     self.table_views = table_views
     self.functions = functions
     self.table_functions = table_functions
+    self.macros = macros
 
 
 # Reads the provided SQL and, if possible, generates a dictionary with data
@@ -378,13 +437,14 @@
   extractor = DocsExtractor(path, module_name, sql)
   docs = extractor.extract()
   if extractor.errors:
-    return ParsedFile(extractor.errors, [], [], [])
+    return ParsedFile(extractor.errors, [], [], [], [])
 
   # Parse the extracted docs.
   errors = []
   table_views = []
   functions = []
   table_functions = []
+  macros = []
   for doc in docs:
     if doc.obj_kind == ObjKind.table_view:
       parser = TableViewDocParser(path, module_name)
@@ -404,5 +464,11 @@
       if res:
         table_functions.append(res)
       errors += parser.errors
+    if doc.obj_kind == ObjKind.macro:
+      parser = MacroDocParser(path, module_name)
+      res = parser.parse(doc)
+      if res:
+        macros.append(res)
+      errors += parser.errors
 
-  return ParsedFile(errors, table_views, functions, table_functions)
+  return ParsedFile(errors, table_views, functions, table_functions, macros)
diff --git a/python/generators/sql_processing/utils.py b/python/generators/sql_processing/utils.py
index c7133b3..b665008 100644
--- a/python/generators/sql_processing/utils.py
+++ b/python/generators/sql_processing/utils.py
@@ -20,7 +20,7 @@
 NAME = r'[a-zA-Z_\d\{\}]+'
 ANY_WORDS = r'[^\s].*'
 ANY_NON_QUOTE = r'[^\']*.*'
-TYPE = r'[A-Z]+'
+TYPE = r'[a-zA-Z]+'
 SQL = r'[\s\S]*?'
 WS = r'\s*'
 COMMENT = r' --[^\n]*\n'
@@ -78,7 +78,7 @@
     fr" \( ({ARGS}) \) "
     # Type: word after RETURNS.
     fr"({COMMENTS})"
-    fr" RETURNS")
+    fr" RETURNS ({TYPE})")
 
 COLUMN_ANNOTATION_PATTERN = update_pattern(fr'^ ({NAME}) ({ANY_WORDS})')
 
@@ -97,16 +97,19 @@
   table_view = 'table_view'
   function = 'function'
   table_function = 'table_function'
+  macro = 'macro'
 
 
 PATTERN_BY_KIND = {
     ObjKind.table_view: CREATE_TABLE_VIEW_PATTERN,
     ObjKind.function: CREATE_FUNCTION_PATTERN,
     ObjKind.table_function: CREATE_TABLE_FUNCTION_PATTERN,
+    ObjKind.macro: CREATE_MACRO_PATTERN
 }
 
 ALLOWED_PREFIXES = {
     'chrome/util': 'cr',
+    'graphs': 'graph',
 }
 
 # Given a regex pattern and a string to match against, returns all the
diff --git a/python/generators/trace_processor_table/serialize.py b/python/generators/trace_processor_table/serialize.py
index cecaf4d..b607bdc 100644
--- a/python/generators/trace_processor_table/serialize.py
+++ b/python/generators/trace_processor_table/serialize.py
@@ -606,6 +606,7 @@
 #ifndef {ifdef_guard}
 #define {ifdef_guard}
 
+#include "src/trace_processor/db/typed_column.h"
 #include "src/trace_processor/tables/macros_internal.h"
 
 {include_paths_str}
diff --git a/python/perfetto/trace_processor/metrics.descriptor b/python/perfetto/trace_processor/metrics.descriptor
index bef8394..0851fc0 100644
--- a/python/perfetto/trace_processor/metrics.descriptor
+++ b/python/perfetto/trace_processor/metrics.descriptor
Binary files differ
diff --git a/python/perfetto/trace_processor/trace_processor.descriptor b/python/perfetto/trace_processor/trace_processor.descriptor
index ecb561d..261ab0b 100644
--- a/python/perfetto/trace_processor/trace_processor.descriptor
+++ b/python/perfetto/trace_processor/trace_processor.descriptor
Binary files differ
diff --git a/python/test/stdlib_unittest.py b/python/test/stdlib_unittest.py
index f7963fb..6002e83 100644
--- a/python/test/stdlib_unittest.py
+++ b/python/test/stdlib_unittest.py
@@ -39,7 +39,7 @@
 
     table = res.table_views[0]
     self.assertEqual(table.name, 'foo_table')
-    self.assertEqual(table.desc, 'First line. Second line.')
+    self.assertEqual(table.desc, 'First line.\n Second line.')
     self.assertEqual(table.type, 'TABLE')
     self.assertEqual(
         table.cols, {
@@ -64,7 +64,7 @@
 
     fn = res.functions[0]
     self.assertEqual(fn.name, 'foo_fn')
-    self.assertEqual(fn.desc, 'First line. Second line.')
+    self.assertEqual(fn.desc, 'First line.\n Second line.')
     self.assertEqual(
         fn.args, {
             'utid': Arg('INT', 'Utid of thread.'),
@@ -292,7 +292,7 @@
     self.assertListEqual(res.errors, [])
 
     fn = res.functions[0]
-    self.assertEqual(fn.desc, 'This is a very long description.')
+    self.assertEqual(fn.desc, 'This\n is\n\n a\n      very\n\n long\n\n description.')
 
   def test_multiline_arg_desc(self):
     res = parse_file(
@@ -317,7 +317,7 @@
     self.assertEqual(
         fn.args, {
             'utid':
-                Arg('INT', 'Uint spread across lines.'),
+                Arg('INT', 'Uint spread  across lines.'),
             'name':
                 Arg(
                     'STRING', 'String name which spans across multiple lines '
@@ -551,3 +551,56 @@
     })
     self.assertEqual(fn.return_type, 'BOOL')
     self.assertEqual(fn.return_desc, 'Exists.')
+
+  def test_macro(self):
+    res = parse_file(
+        'foo/bar.sql', f'''
+-- Macro
+CREATE OR REPLACE PERFETTO FUNCTION foo_fn()
+-- Exists.
+RETURNS BOOL
+AS
+SELECT 1;
+    '''.strip())
+    # Expecting an error: CREATE OR REPLACE is not allowed in stdlib.
+    self.assertEqual(len(res.errors), 1)
+
+  def test_create_or_replace_macro_smoke(self):
+    res = parse_file(
+        'foo/bar.sql', f'''
+-- Macro
+CREATE PERFETTO MACRO foo_macro(
+  -- x Arg.
+  x TableOrSubquery
+)
+-- Exists.
+RETURNS TableOrSubquery
+AS
+SELECT 1;
+    '''.strip())
+
+    macro = res.macros[0]
+    self.assertEqual(macro.name, 'foo_macro')
+    self.assertEqual(macro.desc, 'Macro')
+    self.assertEqual(macro.args, {
+        'x': Arg('TableOrSubquery', 'x Arg.'),
+    })
+    self.assertEqual(macro.return_type, 'TableOrSubquery')
+    self.assertEqual(macro.return_desc, 'Exists.')
+
+
+  def test_create_or_replace_macro_banned(self):
+    res = parse_file(
+        'foo/bar.sql', f'''
+-- Macro
+CREATE OR REPLACE PERFETTO MACRO foo_macro(
+  -- x Arg.
+  x TableOrSubquery
+)
+-- Exists.
+RETURNS TableOrSubquery
+AS
+SELECT 1;
+    '''.strip())
+    # Expecting an error: CREATE OR REPLACE is not allowed in stdlib.
+    self.assertEqual(len(res.errors), 1)
diff --git a/src/base/test/status_matchers.h b/src/base/test/status_matchers.h
index e16214b..a6cddc2 100644
--- a/src/base/test/status_matchers.h
+++ b/src/base/test/status_matchers.h
@@ -36,13 +36,22 @@
   return !arg.ok();
 }
 
-// Macros for testing the results of functions that return absl::Status or
-// absl::StatusOr<T> (for any type T).
+// Macros for testing the results of functions that return base::Status or
+// base::StatusOr<T> (for any type T).
 #define EXPECT_OK(expression) \
   EXPECT_THAT(expression, ::perfetto::base::gtest_matchers::IsOk())
 #define ASSERT_OK(expression) \
   ASSERT_THAT(expression, ::perfetto::base::gtest_matchers::IsOk())
 
+// Macros for testing the results of function returning base::StatusOr<T>.
+#define PERFETTO_TEST_STATUS_MATCHER_CONCAT(x, y) x##y
+#define ASSERT_OK_AND_ASSIGN(lhs, rhs)                                    \
+  PERFETTO_TEST_STATUS_MATCHER_CONCAT(auto status_or, __LINE__) = rhs;    \
+  ASSERT_OK(                                                              \
+      PERFETTO_TEST_STATUS_MATCHER_CONCAT(status_or, __LINE__).status()); \
+  lhs = std::move(                                                        \
+      PERFETTO_TEST_STATUS_MATCHER_CONCAT(status_or, __LINE__).value())
+
 }  // namespace gtest_matchers
 
 // Add a |PrintTo| function to allow easily determining what the cause of the
diff --git a/src/kernel_utils/BUILD.gn b/src/kernel_utils/BUILD.gn
index 9f136ac..9771580 100644
--- a/src/kernel_utils/BUILD.gn
+++ b/src/kernel_utils/BUILD.gn
@@ -12,6 +12,8 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+import("../../gn/test.gni")
+
 source_set("syscall_table") {
   deps = [
     "../../gn:default_deps",
@@ -20,10 +22,17 @@
   sources = [
     "syscall_table.cc",
     "syscall_table.h",
-    "syscalls_aarch32.h",
-    "syscalls_aarch64.h",
-    "syscalls_armeabi.h",
-    "syscalls_x86.h",
-    "syscalls_x86_64.h",
+    "syscall_table_generated.h",
   ]
 }
+
+perfetto_unittest_source_set("unittests") {
+  testonly = true
+  deps = [
+    ":syscall_table",
+    "../../gn:default_deps",
+    "../../gn:gtest_and_gmock",
+    "../base",
+  ]
+  sources = [ "syscall_table_unittest.cc" ]
+}
diff --git a/src/kernel_utils/syscall_table.cc b/src/kernel_utils/syscall_table.cc
index d5a6e23..eae0c4e 100644
--- a/src/kernel_utils/syscall_table.cc
+++ b/src/kernel_utils/syscall_table.cc
@@ -22,70 +22,51 @@
 #include <sys/utsname.h>
 #endif
 
-#include "src/kernel_utils/syscalls_aarch32.h"
-#include "src/kernel_utils/syscalls_aarch64.h"
-#include "src/kernel_utils/syscalls_armeabi.h"
-#include "src/kernel_utils/syscalls_x86.h"
-#include "src/kernel_utils/syscalls_x86_64.h"
+#include "src/kernel_utils/syscall_table_generated.h"
 
 namespace perfetto {
 
-template <typename T>
-constexpr size_t GetSyscalls(const T&) {
-  static_assert(std::extent<T>::value <= kMaxSyscalls,
-                "kMaxSyscalls too small");
-  return std::extent<T>::value;
-}
-
 SyscallTable::SyscallTable(Architecture arch) {
-  static const char* kSyscalls_Unknown[] = {nullptr};
-
   switch (arch) {
-    case kArmEabi:
-      syscall_count_ = GetSyscalls(kSyscalls_ArmEabi);
-      syscall_table_ = &kSyscalls_ArmEabi[0];
+    case Architecture::kArmEabi:
+      *this = SyscallTable::Load<SyscallTable_armeabi>();
       break;
-    case kAarch32:
-      syscall_count_ = GetSyscalls(kSyscalls_Aarch32);
-      syscall_table_ = &kSyscalls_Aarch32[0];
+    case Architecture::kAarch32:
+      *this = SyscallTable::Load<SyscallTable_aarch32>();
       break;
-    case kAarch64:
-      syscall_count_ = GetSyscalls(kSyscalls_Aarch64);
-      syscall_table_ = &kSyscalls_Aarch64[0];
+    case Architecture::kAarch64:
+      *this = SyscallTable::Load<SyscallTable_aarch64>();
       break;
-    case kX86_64:
-      syscall_count_ = GetSyscalls(kSyscalls_x86_64);
-      syscall_table_ = &kSyscalls_x86_64[0];
+    case Architecture::kX86_64:
+      *this = SyscallTable::Load<SyscallTable_x86_64>();
       break;
-    case kX86:
-      syscall_count_ = GetSyscalls(kSyscalls_x86);
-      syscall_table_ = &kSyscalls_x86[0];
+    case Architecture::kX86:
+      *this = SyscallTable::Load<SyscallTable_x86>();
       break;
-    case kUnknown:
-      syscall_count_ = 0;
-      syscall_table_ = &kSyscalls_Unknown[0];
+    case Architecture::kUnknown:
+      // The default field initializers take care of the null initialization.
       break;
   }
 }
 
 Architecture SyscallTable::ArchFromString(base::StringView machine) {
   if (machine == "aarch64") {
-    return kAarch64;
+    return Architecture::kAarch64;
   } else if (machine == "armv8l") {
-    return kArmEabi;
+    return Architecture::kArmEabi;
   } else if (machine == "armv7l") {
-    return kAarch32;
+    return Architecture::kAarch32;
   } else if (machine == "x86_64") {
-    return kX86_64;
+    return Architecture::kX86_64;
   } else if (machine == "i686") {
-    return kX86;
+    return Architecture::kX86;
   } else {
-    return kUnknown;
+    return Architecture::kUnknown;
   }
 }
 
 SyscallTable SyscallTable::FromCurrentArch() {
-  Architecture arch = kUnknown;
+  Architecture arch = Architecture::kUnknown;
 
 #if PERFETTO_BUILDFLAG(PERFETTO_OS_LINUX) || \
     PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID)
@@ -100,7 +81,7 @@
 
 std::optional<size_t> SyscallTable::GetByName(const std::string& name) const {
   for (size_t i = 0; i < syscall_count_; i++) {
-    if (name == syscall_table_[i]) {
+    if (name == &syscall_names_[syscall_offsets_[i]]) {
       return i;
     }
   }
@@ -109,7 +90,7 @@
 
 const char* SyscallTable::GetById(size_t id) const {
   if (id < syscall_count_) {
-    return syscall_table_[id];
+    return &syscall_names_[syscall_offsets_[id]];
   }
   return nullptr;
 }
diff --git a/src/kernel_utils/syscall_table.h b/src/kernel_utils/syscall_table.h
index c2ec4a5..339f15e 100644
--- a/src/kernel_utils/syscall_table.h
+++ b/src/kernel_utils/syscall_table.h
@@ -22,12 +22,13 @@
 #include <string>
 
 #include "perfetto/ext/base/string_view.h"
+#include "perfetto/ext/base/utils.h"
 
 namespace perfetto {
 
 static constexpr size_t kMaxSyscalls = 550;
 
-enum Architecture {
+enum class Architecture {
   kUnknown = 0,
   kArmEabi,  // 32-bit kernel running a 32-bit process (most old devices).
   kAarch32,  // 64-bit kernel running a 32-bit process (should be rare).
@@ -38,11 +39,17 @@
 
 class SyscallTable {
  public:
-  explicit SyscallTable(Architecture arch);
+  using OffT = uint16_t;
+  // Exposed for testing.
+  template <typename Table>
+  static SyscallTable Load() {
+    static_assert(base::ArraySize(Table::offsets) <= kMaxSyscalls,
+                  "kMaxSyscalls too small");
+    return SyscallTable(Table::names, Table::offsets,
+                        base::ArraySize(Table::offsets));
+  }
 
-  // Use for testing.
-  SyscallTable(const char* const* table, size_t count)
-      : syscall_count_(count), syscall_table_(table) {}
+  explicit SyscallTable(Architecture arch);
 
   // Return the architecture enum for the given uname machine string.
   static Architecture ArchFromString(base::StringView machine);
@@ -60,8 +67,12 @@
   const char* GetById(size_t id) const;
 
  private:
-  size_t syscall_count_;
-  const char* const* syscall_table_;
+  SyscallTable(const char* names, const OffT* off, size_t count)
+      : syscall_names_(names), syscall_offsets_(off), syscall_count_(count) {}
+
+  const char* syscall_names_ = "";
+  const OffT* syscall_offsets_ = {};
+  size_t syscall_count_ = 0;
 };
 }  // namespace perfetto
 
diff --git a/src/kernel_utils/syscall_table_generated.h b/src/kernel_utils/syscall_table_generated.h
new file mode 100644
index 0000000..cd53332
--- /dev/null
+++ b/src/kernel_utils/syscall_table_generated.h
@@ -0,0 +1,2484 @@
+// DO NOT EDIT. Auto-generated by tools/extract_linux_syscall_tables
+#ifndef SRC_KERNEL_UTILS_SYSCALL_TABLE_GENERATED_H_
+#define SRC_KERNEL_UTILS_SYSCALL_TABLE_GENERATED_H_
+
+#include <stdint.h>
+
+namespace perfetto {
+
+constexpr char kAllSyscalllNames[] =
+    "\0"
+    "sys__llseek\0"
+    "sys__newselect\0"
+    "sys__sysctl\0"
+    "sys_accept\0"
+    "sys_accept4\0"
+    "sys_access\0"
+    "sys_acct\0"
+    "sys_add_key\0"
+    "sys_adjtimex\0"
+    "sys_afs_syscall\0"
+    "sys_alarm\0"
+    "sys_arch_prctl\0"
+    "sys_arch_specific_syscall\0"
+    "sys_arm_fadvise64_64\0"
+    "sys_arm_sync_file_range\0"
+    "sys_bdflush\0"
+    "sys_bind\0"
+    "sys_bpf\0"
+    "sys_break\0"
+    "sys_brk\0"
+    "sys_capget\0"
+    "sys_capset\0"
+    "sys_chdir\0"
+    "sys_chmod\0"
+    "sys_chown\0"
+    "sys_chown32\0"
+    "sys_chroot\0"
+    "sys_clock_adjtime\0"
+    "sys_clock_getres\0"
+    "sys_clock_gettime\0"
+    "sys_clock_nanosleep\0"
+    "sys_clock_settime\0"
+    "sys_clone\0"
+    "sys_close\0"
+    "sys_connect\0"
+    "sys_copy_file_range\0"
+    "sys_creat\0"
+    "sys_create_module\0"
+    "sys_delete_module\0"
+    "sys_dup\0"
+    "sys_dup2\0"
+    "sys_dup3\0"
+    "sys_epoll_create\0"
+    "sys_epoll_create1\0"
+    "sys_epoll_ctl\0"
+    "sys_epoll_ctl_old\0"
+    "sys_epoll_pwait\0"
+    "sys_epoll_wait\0"
+    "sys_epoll_wait_old\0"
+    "sys_eventfd\0"
+    "sys_eventfd2\0"
+    "sys_execve\0"
+    "sys_execveat\0"
+    "sys_exit\0"
+    "sys_exit_group\0"
+    "sys_faccessat\0"
+    "sys_fadvise64\0"
+    "sys_fadvise64_64\0"
+    "sys_fallocate\0"
+    "sys_fanotify_init\0"
+    "sys_fanotify_mark\0"
+    "sys_fchdir\0"
+    "sys_fchmod\0"
+    "sys_fchmodat\0"
+    "sys_fchown\0"
+    "sys_fchown32\0"
+    "sys_fchownat\0"
+    "sys_fcntl\0"
+    "sys_fcntl64\0"
+    "sys_fdatasync\0"
+    "sys_fgetxattr\0"
+    "sys_finit_module\0"
+    "sys_flistxattr\0"
+    "sys_flock\0"
+    "sys_fork\0"
+    "sys_fremovexattr\0"
+    "sys_fsetxattr\0"
+    "sys_fstat\0"
+    "sys_fstat64\0"
+    "sys_fstatat\0"
+    "sys_fstatat64\0"
+    "sys_fstatfs\0"
+    "sys_fstatfs64\0"
+    "sys_fsync\0"
+    "sys_ftime\0"
+    "sys_ftruncate\0"
+    "sys_ftruncate64\0"
+    "sys_futex\0"
+    "sys_futimesat\0"
+    "sys_get_kernel_syms\0"
+    "sys_get_mempolicy\0"
+    "sys_get_robust_list\0"
+    "sys_get_thread_area\0"
+    "sys_getcpu\0"
+    "sys_getcwd\0"
+    "sys_getdents\0"
+    "sys_getdents64\0"
+    "sys_getegid\0"
+    "sys_getegid32\0"
+    "sys_geteuid\0"
+    "sys_geteuid32\0"
+    "sys_getgid\0"
+    "sys_getgid32\0"
+    "sys_getgroups\0"
+    "sys_getgroups32\0"
+    "sys_getitimer\0"
+    "sys_getpeername\0"
+    "sys_getpgid\0"
+    "sys_getpgrp\0"
+    "sys_getpid\0"
+    "sys_getpmsg\0"
+    "sys_getppid\0"
+    "sys_getpriority\0"
+    "sys_getrandom\0"
+    "sys_getresgid\0"
+    "sys_getresgid32\0"
+    "sys_getresuid\0"
+    "sys_getresuid32\0"
+    "sys_getrlimit\0"
+    "sys_getrusage\0"
+    "sys_getsid\0"
+    "sys_getsockname\0"
+    "sys_getsockopt\0"
+    "sys_gettid\0"
+    "sys_gettimeofday\0"
+    "sys_getuid\0"
+    "sys_getuid32\0"
+    "sys_getxattr\0"
+    "sys_gtty\0"
+    "sys_idle\0"
+    "sys_init_module\0"
+    "sys_inotify_add_watch\0"
+    "sys_inotify_init\0"
+    "sys_inotify_init1\0"
+    "sys_inotify_rm_watch\0"
+    "sys_io_cancel\0"
+    "sys_io_destroy\0"
+    "sys_io_getevents\0"
+    "sys_io_pgetevents\0"
+    "sys_io_setup\0"
+    "sys_io_submit\0"
+    "sys_ioctl\0"
+    "sys_ioperm\0"
+    "sys_iopl\0"
+    "sys_ioprio_get\0"
+    "sys_ioprio_set\0"
+    "sys_ipc\0"
+    "sys_kcmp\0"
+    "sys_kexec_file_load\0"
+    "sys_kexec_load\0"
+    "sys_keyctl\0"
+    "sys_kill\0"
+    "sys_lchown\0"
+    "sys_lchown32\0"
+    "sys_lgetxattr\0"
+    "sys_link\0"
+    "sys_linkat\0"
+    "sys_listen\0"
+    "sys_listxattr\0"
+    "sys_llistxattr\0"
+    "sys_lock\0"
+    "sys_lookup_dcookie\0"
+    "sys_lremovexattr\0"
+    "sys_lseek\0"
+    "sys_lsetxattr\0"
+    "sys_lstat\0"
+    "sys_lstat64\0"
+    "sys_madvise\0"
+    "sys_mbind\0"
+    "sys_membarrier\0"
+    "sys_memfd_create\0"
+    "sys_migrate_pages\0"
+    "sys_mincore\0"
+    "sys_mkdir\0"
+    "sys_mkdirat\0"
+    "sys_mknod\0"
+    "sys_mknodat\0"
+    "sys_mlock\0"
+    "sys_mlock2\0"
+    "sys_mlockall\0"
+    "sys_mmap\0"
+    "sys_mmap2\0"
+    "sys_modify_ldt\0"
+    "sys_mount\0"
+    "sys_move_pages\0"
+    "sys_mprotect\0"
+    "sys_mpx\0"
+    "sys_mq_getsetattr\0"
+    "sys_mq_notify\0"
+    "sys_mq_open\0"
+    "sys_mq_timedreceive\0"
+    "sys_mq_timedsend\0"
+    "sys_mq_unlink\0"
+    "sys_mremap\0"
+    "sys_msgctl\0"
+    "sys_msgget\0"
+    "sys_msgrcv\0"
+    "sys_msgsnd\0"
+    "sys_msync\0"
+    "sys_munlock\0"
+    "sys_munlockall\0"
+    "sys_munmap\0"
+    "sys_name_to_handle_at\0"
+    "sys_nanosleep\0"
+    "sys_newfstatat\0"
+    "sys_nfsservctl\0"
+    "sys_nice\0"
+    "sys_oldfstat\0"
+    "sys_oldlstat\0"
+    "sys_oldolduname\0"
+    "sys_oldstat\0"
+    "sys_olduname\0"
+    "sys_open\0"
+    "sys_open_by_handle_at\0"
+    "sys_openat\0"
+    "sys_pause\0"
+    "sys_pciconfig_iobase\0"
+    "sys_pciconfig_read\0"
+    "sys_pciconfig_write\0"
+    "sys_perf_event_open\0"
+    "sys_personality\0"
+    "sys_pipe\0"
+    "sys_pipe2\0"
+    "sys_pivot_root\0"
+    "sys_pkey_alloc\0"
+    "sys_pkey_free\0"
+    "sys_pkey_mprotect\0"
+    "sys_poll\0"
+    "sys_ppoll\0"
+    "sys_prctl\0"
+    "sys_pread64\0"
+    "sys_preadv\0"
+    "sys_preadv2\0"
+    "sys_prlimit64\0"
+    "sys_process_vm_readv\0"
+    "sys_process_vm_writev\0"
+    "sys_prof\0"
+    "sys_profil\0"
+    "sys_pselect6\0"
+    "sys_ptrace\0"
+    "sys_putpmsg\0"
+    "sys_pwrite64\0"
+    "sys_pwritev\0"
+    "sys_pwritev2\0"
+    "sys_query_module\0"
+    "sys_quotactl\0"
+    "sys_read\0"
+    "sys_readahead\0"
+    "sys_readdir\0"
+    "sys_readlink\0"
+    "sys_readlinkat\0"
+    "sys_readv\0"
+    "sys_reboot\0"
+    "sys_recv\0"
+    "sys_recvfrom\0"
+    "sys_recvmmsg\0"
+    "sys_recvmsg\0"
+    "sys_remap_file_pages\0"
+    "sys_removexattr\0"
+    "sys_rename\0"
+    "sys_renameat\0"
+    "sys_renameat2\0"
+    "sys_request_key\0"
+    "sys_restart_syscall\0"
+    "sys_rmdir\0"
+    "sys_rseq\0"
+    "sys_rt_sigaction\0"
+    "sys_rt_sigpending\0"
+    "sys_rt_sigprocmask\0"
+    "sys_rt_sigqueueinfo\0"
+    "sys_rt_sigreturn\0"
+    "sys_rt_sigsuspend\0"
+    "sys_rt_sigtimedwait\0"
+    "sys_rt_tgsigqueueinfo\0"
+    "sys_sched_get_priority_max\0"
+    "sys_sched_get_priority_min\0"
+    "sys_sched_getaffinity\0"
+    "sys_sched_getattr\0"
+    "sys_sched_getparam\0"
+    "sys_sched_getscheduler\0"
+    "sys_sched_rr_get_interval\0"
+    "sys_sched_setaffinity\0"
+    "sys_sched_setattr\0"
+    "sys_sched_setparam\0"
+    "sys_sched_setscheduler\0"
+    "sys_sched_yield\0"
+    "sys_seccomp\0"
+    "sys_security\0"
+    "sys_select\0"
+    "sys_semctl\0"
+    "sys_semget\0"
+    "sys_semop\0"
+    "sys_semtimedop\0"
+    "sys_send\0"
+    "sys_sendfile\0"
+    "sys_sendfile64\0"
+    "sys_sendmmsg\0"
+    "sys_sendmsg\0"
+    "sys_sendto\0"
+    "sys_set_mempolicy\0"
+    "sys_set_robust_list\0"
+    "sys_set_thread_area\0"
+    "sys_set_tid_address\0"
+    "sys_setdomainname\0"
+    "sys_setfsgid\0"
+    "sys_setfsgid32\0"
+    "sys_setfsuid\0"
+    "sys_setfsuid32\0"
+    "sys_setgid\0"
+    "sys_setgid32\0"
+    "sys_setgroups\0"
+    "sys_setgroups32\0"
+    "sys_sethostname\0"
+    "sys_setitimer\0"
+    "sys_setns\0"
+    "sys_setpgid\0"
+    "sys_setpriority\0"
+    "sys_setregid\0"
+    "sys_setregid32\0"
+    "sys_setresgid\0"
+    "sys_setresgid32\0"
+    "sys_setresuid\0"
+    "sys_setresuid32\0"
+    "sys_setreuid\0"
+    "sys_setreuid32\0"
+    "sys_setrlimit\0"
+    "sys_setsid\0"
+    "sys_setsockopt\0"
+    "sys_settimeofday\0"
+    "sys_setuid\0"
+    "sys_setuid32\0"
+    "sys_setxattr\0"
+    "sys_sgetmask\0"
+    "sys_shmat\0"
+    "sys_shmctl\0"
+    "sys_shmdt\0"
+    "sys_shmget\0"
+    "sys_shutdown\0"
+    "sys_sigaction\0"
+    "sys_sigaltstack\0"
+    "sys_signal\0"
+    "sys_signalfd\0"
+    "sys_signalfd4\0"
+    "sys_sigpending\0"
+    "sys_sigprocmask\0"
+    "sys_sigreturn\0"
+    "sys_sigsuspend\0"
+    "sys_socket\0"
+    "sys_socketcall\0"
+    "sys_socketpair\0"
+    "sys_splice\0"
+    "sys_ssetmask\0"
+    "sys_stat\0"
+    "sys_stat64\0"
+    "sys_statfs\0"
+    "sys_statfs64\0"
+    "sys_statx\0"
+    "sys_stime\0"
+    "sys_stty\0"
+    "sys_swapoff\0"
+    "sys_swapon\0"
+    "sys_symlink\0"
+    "sys_symlinkat\0"
+    "sys_sync\0"
+    "sys_sync_file_range\0"
+    "sys_sync_file_range2\0"
+    "sys_syncfs\0"
+    "sys_syscall\0"
+    "sys_sysfs\0"
+    "sys_sysinfo\0"
+    "sys_syslog\0"
+    "sys_tee\0"
+    "sys_tgkill\0"
+    "sys_time\0"
+    "sys_timer_create\0"
+    "sys_timer_delete\0"
+    "sys_timer_getoverrun\0"
+    "sys_timer_gettime\0"
+    "sys_timer_settime\0"
+    "sys_timerfd_create\0"
+    "sys_timerfd_gettime\0"
+    "sys_timerfd_settime\0"
+    "sys_times\0"
+    "sys_tkill\0"
+    "sys_truncate\0"
+    "sys_truncate64\0"
+    "sys_tuxcall\0"
+    "sys_ugetrlimit\0"
+    "sys_ulimit\0"
+    "sys_umask\0"
+    "sys_umount\0"
+    "sys_umount2\0"
+    "sys_uname\0"
+    "sys_unlink\0"
+    "sys_unlinkat\0"
+    "sys_unshare\0"
+    "sys_uselib\0"
+    "sys_userfaultfd\0"
+    "sys_ustat\0"
+    "sys_utime\0"
+    "sys_utimensat\0"
+    "sys_utimes\0"
+    "sys_vfork\0"
+    "sys_vhangup\0"
+    "sys_vm86\0"
+    "sys_vm86old\0"
+    "sys_vmsplice\0"
+    "sys_vserver\0"
+    "sys_wait4\0"
+    "sys_waitid\0"
+    "sys_waitpid\0"
+    "sys_write\0"
+    "sys_writev\0";
+
+struct SyscallTable_aarch32 {
+  static constexpr const char* names = kAllSyscalllNames;
+  static constexpr SyscallTable::OffT offsets[]{
+      3544,  // 0: sys_restart_syscall
+      723,   // 1: sys_exit
+      1006,  // 2: sys_fork
+      3322,  // 3: sys_read
+      5639,  // 4: sys_write
+      2848,  // 5: sys_open
+      443,   // 6: sys_close
+      0,     // 7:
+      485,   // 8: sys_creat
+      2115,  // 9: sys_link
+      5430,  // 10: sys_unlink
+      699,   // 11: sys_execve
+      289,   // 12: sys_chdir
+      0,     // 13:
+      2372,  // 14: sys_mknod
+      299,   // 15: sys_chmod
+      2077,  // 16: sys_lchown
+      0,     // 17:
+      0,     // 18:
+      2220,  // 19: sys_lseek
+      1482,  // 20: sys_getpid
+      2462,  // 21: sys_mount
+      0,     // 22:
+      4597,  // 23: sys_setuid
+      1705,  // 24: sys_getuid
+      0,     // 25:
+      3231,  // 26: sys_ptrace
+      0,     // 27:
+      0,     // 28:
+      2890,  // 29: sys_pause
+      0,     // 30:
+      0,     // 31:
+      0,     // 32:
+      63,    // 33: sys_access
+      2772,  // 34: sys_nice
+      0,     // 35:
+      5017,  // 36: sys_sync
+      2068,  // 37: sys_kill
+      3490,  // 38: sys_rename
+      2350,  // 39: sys_mkdir
+      3564,  // 40: sys_rmdir
+      531,   // 41: sys_dup
+      2996,  // 42: sys_pipe
+      5301,  // 43: sys_times
+      0,     // 44:
+      259,   // 45: sys_brk
+      4302,  // 46: sys_setgid
+      1374,  // 47: sys_getgid
+      0,     // 48:
+      1348,  // 49: sys_geteuid
+      1322,  // 50: sys_getegid
+      74,    // 51: sys_acct
+      5408,  // 52: sys_umount2
+      0,     // 53:
+      1945,  // 54: sys_ioctl
+      914,   // 55: sys_fcntl
+      0,     // 56:
+      4396,  // 57: sys_setpgid
+      0,     // 58:
+      0,     // 59:
+      5387,  // 60: sys_umask
+      331,   // 61: sys_chroot
+      5493,  // 62: sys_ustat
+      539,   // 63: sys_dup2
+      1505,  // 64: sys_getppid
+      1470,  // 65: sys_getpgrp
+      4554,  // 66: sys_setsid
+      4702,  // 67: sys_sigaction
+      0,     // 68:
+      0,     // 69:
+      4512,  // 70: sys_setreuid
+      4424,  // 71: sys_setregid
+      4815,  // 72: sys_sigsuspend
+      4770,  // 73: sys_sigpending
+      4356,  // 74: sys_sethostname
+      4540,  // 75: sys_setrlimit
+      0,     // 76:
+      1621,  // 77: sys_getrusage
+      1688,  // 78: sys_gettimeofday
+      4580,  // 79: sys_settimeofday
+      1398,  // 80: sys_getgroups
+      4326,  // 81: sys_setgroups
+      0,     // 82:
+      4991,  // 83: sys_symlink
+      0,     // 84:
+      3357,  // 85: sys_readlink
+      5466,  // 86: sys_uselib
+      4980,  // 87: sys_swapon
+      3395,  // 88: sys_reboot
+      0,     // 89:
+      0,     // 90:
+      2695,  // 91: sys_munmap
+      5321,  // 92: sys_truncate
+      1140,  // 93: sys_ftruncate
+      853,   // 94: sys_fchmod
+      877,   // 95: sys_fchown
+      1517,  // 96: sys_getpriority
+      4408,  // 97: sys_setpriority
+      0,     // 98:
+      4915,  // 99: sys_statfs
+      1094,  // 100: sys_fstatfs
+      0,     // 101:
+      0,     // 102:
+      5112,  // 103: sys_syslog
+      4372,  // 104: sys_setitimer
+      1428,  // 105: sys_getitimer
+      4895,  // 106: sys_stat
+      2244,  // 107: sys_lstat
+      1046,  // 108: sys_fstat
+      0,     // 109:
+      0,     // 110:
+      5548,  // 111: sys_vhangup
+      0,     // 112:
+      0,     // 113:
+      5606,  // 114: sys_wait4
+      4968,  // 115: sys_swapoff
+      5100,  // 116: sys_sysinfo
+      0,     // 117:
+      1120,  // 118: sys_fsync
+      4801,  // 119: sys_sigreturn
+      433,   // 120: sys_clone
+      4228,  // 121: sys_setdomainname
+      5420,  // 122: sys_uname
+      0,     // 123:
+      95,    // 124: sys_adjtimex
+      2487,  // 125: sys_mprotect
+      4785,  // 126: sys_sigprocmask
+      0,     // 127:
+      1760,  // 128: sys_init_module
+      513,   // 129: sys_delete_module
+      0,     // 130:
+      3309,  // 131: sys_quotactl
+      1458,  // 132: sys_getpgid
+      842,   // 133: sys_fchdir
+      220,   // 134: sys_bdflush
+      5090,  // 135: sys_sysfs
+      2980,  // 136: sys_personality
+      0,     // 137:
+      4274,  // 138: sys_setfsuid
+      4246,  // 139: sys_setfsgid
+      1,     // 140: sys__llseek
+      1294,  // 141: sys_getdents
+      13,    // 142: sys__newselect
+      996,   // 143: sys_flock
+      2658,  // 144: sys_msync
+      3385,  // 145: sys_readv
+      5649,  // 146: sys_writev
+      1635,  // 147: sys_getsid
+      936,   // 148: sys_fdatasync
+      28,    // 149: sys__sysctl
+      2394,  // 150: sys_mlock
+      2668,  // 151: sys_munlock
+      2415,  // 152: sys_mlockall
+      2680,  // 153: sys_munlockall
+      3936,  // 154: sys_sched_setparam
+      3828,  // 155: sys_sched_getparam
+      3955,  // 156: sys_sched_setscheduler
+      3847,  // 157: sys_sched_getscheduler
+      3978,  // 158: sys_sched_yield
+      3734,  // 159: sys_sched_get_priority_max
+      3761,  // 160: sys_sched_get_priority_min
+      3870,  // 161: sys_sched_rr_get_interval
+      2728,  // 162: sys_nanosleep
+      2603,  // 163: sys_mremap
+      4482,  // 164: sys_setresuid
+      1577,  // 165: sys_getresuid
+      0,     // 166:
+      0,     // 167:
+      3077,  // 168: sys_poll
+      2757,  // 169: sys_nfsservctl
+      4452,  // 170: sys_setresgid
+      1547,  // 171: sys_getresgid
+      3096,  // 172: sys_prctl
+      3657,  // 173: sys_rt_sigreturn
+      3583,  // 174: sys_rt_sigaction
+      3618,  // 175: sys_rt_sigprocmask
+      3600,  // 176: sys_rt_sigpending
+      3692,  // 177: sys_rt_sigtimedwait
+      3637,  // 178: sys_rt_sigqueueinfo
+      3674,  // 179: sys_rt_sigsuspend
+      3106,  // 180: sys_pread64
+      3254,  // 181: sys_pwrite64
+      309,   // 182: sys_chown
+      1283,  // 183: sys_getcwd
+      267,   // 184: sys_capget
+      278,   // 185: sys_capset
+      4716,  // 186: sys_sigaltstack
+      4086,  // 187: sys_sendfile
+      0,     // 188:
+      0,     // 189:
+      5538,  // 190: sys_vfork
+      0,     // 191:
+      2437,  // 192: sys_mmap2
+      5334,  // 193: sys_truncate64
+      1154,  // 194: sys_ftruncate64
+      4904,  // 195: sys_stat64
+      2254,  // 196: sys_lstat64
+      1056,  // 197: sys_fstat64
+      2088,  // 198: sys_lchown32
+      1716,  // 199: sys_getuid32
+      1385,  // 200: sys_getgid32
+      1360,  // 201: sys_geteuid32
+      1334,  // 202: sys_getegid32
+      4525,  // 203: sys_setreuid32
+      4437,  // 204: sys_setregid32
+      1412,  // 205: sys_getgroups32
+      4340,  // 206: sys_setgroups32
+      888,   // 207: sys_fchown32
+      4496,  // 208: sys_setresuid32
+      1591,  // 209: sys_getresuid32
+      4466,  // 210: sys_setresgid32
+      1561,  // 211: sys_getresgid32
+      319,   // 212: sys_chown32
+      4608,  // 213: sys_setuid32
+      4313,  // 214: sys_setgid32
+      4287,  // 215: sys_setfsuid32
+      4259,  // 216: sys_setfsgid32
+      1307,  // 217: sys_getdents64
+      3015,  // 218: sys_pivot_root
+      2338,  // 219: sys_mincore
+      2266,  // 220: sys_madvise
+      924,   // 221: sys_fcntl64
+      0,     // 222:
+      0,     // 223:
+      1677,  // 224: sys_gettid
+      3331,  // 225: sys_readahead
+      4621,  // 226: sys_setxattr
+      2230,  // 227: sys_lsetxattr
+      1032,  // 228: sys_fsetxattr
+      1729,  // 229: sys_getxattr
+      2101,  // 230: sys_lgetxattr
+      950,   // 231: sys_fgetxattr
+      2146,  // 232: sys_listxattr
+      2160,  // 233: sys_llistxattr
+      981,   // 234: sys_flistxattr
+      3474,  // 235: sys_removexattr
+      2203,  // 236: sys_lremovexattr
+      1015,  // 237: sys_fremovexattr
+      5311,  // 238: sys_tkill
+      4099,  // 239: sys_sendfile64
+      1170,  // 240: sys_futex
+      3896,  // 241: sys_sched_setaffinity
+      3788,  // 242: sys_sched_getaffinity
+      1918,  // 243: sys_io_setup
+      1868,  // 244: sys_io_destroy
+      1883,  // 245: sys_io_getevents
+      1931,  // 246: sys_io_submit
+      1854,  // 247: sys_io_cancel
+      732,   // 248: sys_exit_group
+      2184,  // 249: sys_lookup_dcookie
+      557,   // 250: sys_epoll_create
+      592,   // 251: sys_epoll_ctl
+      640,   // 252: sys_epoll_wait
+      3453,  // 253: sys_remap_file_pages
+      0,     // 254:
+      0,     // 255:
+      4208,  // 256: sys_set_tid_address
+      5151,  // 257: sys_timer_create
+      5224,  // 258: sys_timer_settime
+      5206,  // 259: sys_timer_gettime
+      5185,  // 260: sys_timer_getoverrun
+      5168,  // 261: sys_timer_delete
+      415,   // 262: sys_clock_settime
+      377,   // 263: sys_clock_gettime
+      360,   // 264: sys_clock_getres
+      395,   // 265: sys_clock_nanosleep
+      4926,  // 266: sys_statfs64
+      1106,  // 267: sys_fstatfs64
+      5131,  // 268: sys_tgkill
+      5527,  // 269: sys_utimes
+      175,   // 270: sys_arm_fadvise64_64
+      2900,  // 271: sys_pciconfig_iobase
+      2921,  // 272: sys_pciconfig_read
+      2940,  // 273: sys_pciconfig_write
+      2540,  // 274: sys_mq_open
+      2589,  // 275: sys_mq_unlink
+      2572,  // 276: sys_mq_timedsend
+      2552,  // 277: sys_mq_timedreceive
+      2526,  // 278: sys_mq_notify
+      2508,  // 279: sys_mq_getsetattr
+      5616,  // 280: sys_waitid
+      4830,  // 281: sys_socket
+      232,   // 282: sys_bind
+      453,   // 283: sys_connect
+      2135,  // 284: sys_listen
+      40,    // 285: sys_accept
+      1646,  // 286: sys_getsockname
+      1442,  // 287: sys_getpeername
+      4856,  // 288: sys_socketpair
+      4077,  // 289: sys_send
+      4139,  // 290: sys_sendto
+      3406,  // 291: sys_recv
+      3415,  // 292: sys_recvfrom
+      4689,  // 293: sys_shutdown
+      4565,  // 294: sys_setsockopt
+      1662,  // 295: sys_getsockopt
+      4127,  // 296: sys_sendmsg
+      3441,  // 297: sys_recvmsg
+      4052,  // 298: sys_semop
+      4041,  // 299: sys_semget
+      4030,  // 300: sys_semctl
+      2647,  // 301: sys_msgsnd
+      2636,  // 302: sys_msgrcv
+      2625,  // 303: sys_msgget
+      2614,  // 304: sys_msgctl
+      4647,  // 305: sys_shmat
+      4668,  // 306: sys_shmdt
+      4678,  // 307: sys_shmget
+      4657,  // 308: sys_shmctl
+      83,    // 309: sys_add_key
+      3528,  // 310: sys_request_key
+      2057,  // 311: sys_keyctl
+      4062,  // 312: sys_semtimedop
+      5594,  // 313: sys_vserver
+      1990,  // 314: sys_ioprio_set
+      1975,  // 315: sys_ioprio_get
+      1798,  // 316: sys_inotify_init
+      1776,  // 317: sys_inotify_add_watch
+      1833,  // 318: sys_inotify_rm_watch
+      2278,  // 319: sys_mbind
+      1214,  // 320: sys_get_mempolicy
+      4150,  // 321: sys_set_mempolicy
+      2879,  // 322: sys_openat
+      2360,  // 323: sys_mkdirat
+      2382,  // 324: sys_mknodat
+      901,   // 325: sys_fchownat
+      1180,  // 326: sys_futimesat
+      1080,  // 327: sys_fstatat64
+      5441,  // 328: sys_unlinkat
+      3501,  // 329: sys_renameat
+      2124,  // 330: sys_linkat
+      5003,  // 331: sys_symlinkat
+      3370,  // 332: sys_readlinkat
+      864,   // 333: sys_fchmodat
+      747,   // 334: sys_faccessat
+      3218,  // 335: sys_pselect6
+      3086,  // 336: sys_ppoll
+      5454,  // 337: sys_unshare
+      4168,  // 338: sys_set_robust_list
+      1232,  // 339: sys_get_robust_list
+      4871,  // 340: sys_splice
+      5046,  // 341: sys_sync_file_range2
+      5123,  // 342: sys_tee
+      5581,  // 343: sys_vmsplice
+      2472,  // 344: sys_move_pages
+      1272,  // 345: sys_getcpu
+      624,   // 346: sys_epoll_pwait
+      2042,  // 347: sys_kexec_load
+      5513,  // 348: sys_utimensat
+      4743,  // 349: sys_signalfd
+      5242,  // 350: sys_timerfd_create
+      674,   // 351: sys_eventfd
+      792,   // 352: sys_fallocate
+      5281,  // 353: sys_timerfd_settime
+      5261,  // 354: sys_timerfd_gettime
+      4756,  // 355: sys_signalfd4
+      686,   // 356: sys_eventfd2
+      574,   // 357: sys_epoll_create1
+      548,   // 358: sys_dup3
+      3005,  // 359: sys_pipe2
+      1815,  // 360: sys_inotify_init1
+      3118,  // 361: sys_preadv
+      3267,  // 362: sys_pwritev
+      3712,  // 363: sys_rt_tgsigqueueinfo
+      2960,  // 364: sys_perf_event_open
+      3428,  // 365: sys_recvmmsg
+      51,    // 366: sys_accept4
+      806,   // 367: sys_fanotify_init
+      824,   // 368: sys_fanotify_mark
+      3141,  // 369: sys_prlimit64
+      2706,  // 370: sys_name_to_handle_at
+      2857,  // 371: sys_open_by_handle_at
+      342,   // 372: sys_clock_adjtime
+      5067,  // 373: sys_syncfs
+      4114,  // 374: sys_sendmmsg
+      4386,  // 375: sys_setns
+      3155,  // 376: sys_process_vm_readv
+      3176,  // 377: sys_process_vm_writev
+      2013,  // 378: sys_kcmp
+      964,   // 379: sys_finit_module
+      3918,  // 380: sys_sched_setattr
+      3810,  // 381: sys_sched_getattr
+      3514,  // 382: sys_renameat2
+      3994,  // 383: sys_seccomp
+      1533,  // 384: sys_getrandom
+      2303,  // 385: sys_memfd_create
+      241,   // 386: sys_bpf
+      710,   // 387: sys_execveat
+      5477,  // 388: sys_userfaultfd
+      2288,  // 389: sys_membarrier
+      2404,  // 390: sys_mlock2
+      465,   // 391: sys_copy_file_range
+      3129,  // 392: sys_preadv2
+      3279,  // 393: sys_pwritev2
+      3059,  // 394: sys_pkey_mprotect
+      3030,  // 395: sys_pkey_alloc
+      3045,  // 396: sys_pkey_free
+      4939,  // 397: sys_statx
+      3574,  // 398: sys_rseq
+  };
+};
+
+struct SyscallTable_aarch64 {
+  static constexpr const char* names = kAllSyscalllNames;
+  static constexpr SyscallTable::OffT offsets[]{
+      1918,  // 0: sys_io_setup
+      1868,  // 1: sys_io_destroy
+      1931,  // 2: sys_io_submit
+      1854,  // 3: sys_io_cancel
+      1883,  // 4: sys_io_getevents
+      4621,  // 5: sys_setxattr
+      2230,  // 6: sys_lsetxattr
+      1032,  // 7: sys_fsetxattr
+      1729,  // 8: sys_getxattr
+      2101,  // 9: sys_lgetxattr
+      950,   // 10: sys_fgetxattr
+      2146,  // 11: sys_listxattr
+      2160,  // 12: sys_llistxattr
+      981,   // 13: sys_flistxattr
+      3474,  // 14: sys_removexattr
+      2203,  // 15: sys_lremovexattr
+      1015,  // 16: sys_fremovexattr
+      1283,  // 17: sys_getcwd
+      2184,  // 18: sys_lookup_dcookie
+      686,   // 19: sys_eventfd2
+      574,   // 20: sys_epoll_create1
+      592,   // 21: sys_epoll_ctl
+      624,   // 22: sys_epoll_pwait
+      531,   // 23: sys_dup
+      548,   // 24: sys_dup3
+      914,   // 25: sys_fcntl
+      1815,  // 26: sys_inotify_init1
+      1776,  // 27: sys_inotify_add_watch
+      1833,  // 28: sys_inotify_rm_watch
+      1945,  // 29: sys_ioctl
+      1990,  // 30: sys_ioprio_set
+      1975,  // 31: sys_ioprio_get
+      996,   // 32: sys_flock
+      2382,  // 33: sys_mknodat
+      2360,  // 34: sys_mkdirat
+      5441,  // 35: sys_unlinkat
+      5003,  // 36: sys_symlinkat
+      2124,  // 37: sys_linkat
+      3501,  // 38: sys_renameat
+      5408,  // 39: sys_umount2
+      2462,  // 40: sys_mount
+      3015,  // 41: sys_pivot_root
+      2757,  // 42: sys_nfsservctl
+      4915,  // 43: sys_statfs
+      1094,  // 44: sys_fstatfs
+      5321,  // 45: sys_truncate
+      1140,  // 46: sys_ftruncate
+      792,   // 47: sys_fallocate
+      747,   // 48: sys_faccessat
+      289,   // 49: sys_chdir
+      842,   // 50: sys_fchdir
+      331,   // 51: sys_chroot
+      853,   // 52: sys_fchmod
+      864,   // 53: sys_fchmodat
+      901,   // 54: sys_fchownat
+      877,   // 55: sys_fchown
+      2879,  // 56: sys_openat
+      443,   // 57: sys_close
+      5548,  // 58: sys_vhangup
+      3005,  // 59: sys_pipe2
+      3309,  // 60: sys_quotactl
+      1307,  // 61: sys_getdents64
+      2220,  // 62: sys_lseek
+      3322,  // 63: sys_read
+      5639,  // 64: sys_write
+      3385,  // 65: sys_readv
+      5649,  // 66: sys_writev
+      3106,  // 67: sys_pread64
+      3254,  // 68: sys_pwrite64
+      3118,  // 69: sys_preadv
+      3267,  // 70: sys_pwritev
+      4086,  // 71: sys_sendfile
+      3218,  // 72: sys_pselect6
+      3086,  // 73: sys_ppoll
+      4756,  // 74: sys_signalfd4
+      5581,  // 75: sys_vmsplice
+      4871,  // 76: sys_splice
+      5123,  // 77: sys_tee
+      3370,  // 78: sys_readlinkat
+      1068,  // 79: sys_fstatat
+      1046,  // 80: sys_fstat
+      5017,  // 81: sys_sync
+      1120,  // 82: sys_fsync
+      936,   // 83: sys_fdatasync
+      5026,  // 84: sys_sync_file_range
+      5242,  // 85: sys_timerfd_create
+      5281,  // 86: sys_timerfd_settime
+      5261,  // 87: sys_timerfd_gettime
+      5513,  // 88: sys_utimensat
+      74,    // 89: sys_acct
+      267,   // 90: sys_capget
+      278,   // 91: sys_capset
+      2980,  // 92: sys_personality
+      723,   // 93: sys_exit
+      732,   // 94: sys_exit_group
+      5616,  // 95: sys_waitid
+      4208,  // 96: sys_set_tid_address
+      5454,  // 97: sys_unshare
+      1170,  // 98: sys_futex
+      4168,  // 99: sys_set_robust_list
+      1232,  // 100: sys_get_robust_list
+      2728,  // 101: sys_nanosleep
+      1428,  // 102: sys_getitimer
+      4372,  // 103: sys_setitimer
+      2042,  // 104: sys_kexec_load
+      1760,  // 105: sys_init_module
+      513,   // 106: sys_delete_module
+      5151,  // 107: sys_timer_create
+      5206,  // 108: sys_timer_gettime
+      5185,  // 109: sys_timer_getoverrun
+      5224,  // 110: sys_timer_settime
+      5168,  // 111: sys_timer_delete
+      415,   // 112: sys_clock_settime
+      377,   // 113: sys_clock_gettime
+      360,   // 114: sys_clock_getres
+      395,   // 115: sys_clock_nanosleep
+      5112,  // 116: sys_syslog
+      3231,  // 117: sys_ptrace
+      3936,  // 118: sys_sched_setparam
+      3955,  // 119: sys_sched_setscheduler
+      3847,  // 120: sys_sched_getscheduler
+      3828,  // 121: sys_sched_getparam
+      3896,  // 122: sys_sched_setaffinity
+      3788,  // 123: sys_sched_getaffinity
+      3978,  // 124: sys_sched_yield
+      3734,  // 125: sys_sched_get_priority_max
+      3761,  // 126: sys_sched_get_priority_min
+      3870,  // 127: sys_sched_rr_get_interval
+      3544,  // 128: sys_restart_syscall
+      2068,  // 129: sys_kill
+      5311,  // 130: sys_tkill
+      5131,  // 131: sys_tgkill
+      4716,  // 132: sys_sigaltstack
+      3674,  // 133: sys_rt_sigsuspend
+      3583,  // 134: sys_rt_sigaction
+      3618,  // 135: sys_rt_sigprocmask
+      3600,  // 136: sys_rt_sigpending
+      3692,  // 137: sys_rt_sigtimedwait
+      3637,  // 138: sys_rt_sigqueueinfo
+      3657,  // 139: sys_rt_sigreturn
+      4408,  // 140: sys_setpriority
+      1517,  // 141: sys_getpriority
+      3395,  // 142: sys_reboot
+      4424,  // 143: sys_setregid
+      4302,  // 144: sys_setgid
+      4512,  // 145: sys_setreuid
+      4597,  // 146: sys_setuid
+      4482,  // 147: sys_setresuid
+      1577,  // 148: sys_getresuid
+      4452,  // 149: sys_setresgid
+      1547,  // 150: sys_getresgid
+      4274,  // 151: sys_setfsuid
+      4246,  // 152: sys_setfsgid
+      5301,  // 153: sys_times
+      4396,  // 154: sys_setpgid
+      1458,  // 155: sys_getpgid
+      1635,  // 156: sys_getsid
+      4554,  // 157: sys_setsid
+      1398,  // 158: sys_getgroups
+      4326,  // 159: sys_setgroups
+      5420,  // 160: sys_uname
+      4356,  // 161: sys_sethostname
+      4228,  // 162: sys_setdomainname
+      1607,  // 163: sys_getrlimit
+      4540,  // 164: sys_setrlimit
+      1621,  // 165: sys_getrusage
+      5387,  // 166: sys_umask
+      3096,  // 167: sys_prctl
+      1272,  // 168: sys_getcpu
+      1688,  // 169: sys_gettimeofday
+      4580,  // 170: sys_settimeofday
+      95,    // 171: sys_adjtimex
+      1482,  // 172: sys_getpid
+      1505,  // 173: sys_getppid
+      1705,  // 174: sys_getuid
+      1348,  // 175: sys_geteuid
+      1374,  // 176: sys_getgid
+      1322,  // 177: sys_getegid
+      1677,  // 178: sys_gettid
+      5100,  // 179: sys_sysinfo
+      2540,  // 180: sys_mq_open
+      2589,  // 181: sys_mq_unlink
+      2572,  // 182: sys_mq_timedsend
+      2552,  // 183: sys_mq_timedreceive
+      2526,  // 184: sys_mq_notify
+      2508,  // 185: sys_mq_getsetattr
+      2625,  // 186: sys_msgget
+      2614,  // 187: sys_msgctl
+      2636,  // 188: sys_msgrcv
+      2647,  // 189: sys_msgsnd
+      4041,  // 190: sys_semget
+      4030,  // 191: sys_semctl
+      4062,  // 192: sys_semtimedop
+      4052,  // 193: sys_semop
+      4678,  // 194: sys_shmget
+      4657,  // 195: sys_shmctl
+      4647,  // 196: sys_shmat
+      4668,  // 197: sys_shmdt
+      4830,  // 198: sys_socket
+      4856,  // 199: sys_socketpair
+      232,   // 200: sys_bind
+      2135,  // 201: sys_listen
+      40,    // 202: sys_accept
+      453,   // 203: sys_connect
+      1646,  // 204: sys_getsockname
+      1442,  // 205: sys_getpeername
+      4139,  // 206: sys_sendto
+      3415,  // 207: sys_recvfrom
+      4565,  // 208: sys_setsockopt
+      1662,  // 209: sys_getsockopt
+      4689,  // 210: sys_shutdown
+      4127,  // 211: sys_sendmsg
+      3441,  // 212: sys_recvmsg
+      3331,  // 213: sys_readahead
+      259,   // 214: sys_brk
+      2695,  // 215: sys_munmap
+      2603,  // 216: sys_mremap
+      83,    // 217: sys_add_key
+      3528,  // 218: sys_request_key
+      2057,  // 219: sys_keyctl
+      433,   // 220: sys_clone
+      699,   // 221: sys_execve
+      2428,  // 222: sys_mmap
+      761,   // 223: sys_fadvise64
+      4980,  // 224: sys_swapon
+      4968,  // 225: sys_swapoff
+      2487,  // 226: sys_mprotect
+      2658,  // 227: sys_msync
+      2394,  // 228: sys_mlock
+      2668,  // 229: sys_munlock
+      2415,  // 230: sys_mlockall
+      2680,  // 231: sys_munlockall
+      2338,  // 232: sys_mincore
+      2266,  // 233: sys_madvise
+      3453,  // 234: sys_remap_file_pages
+      2278,  // 235: sys_mbind
+      1214,  // 236: sys_get_mempolicy
+      4150,  // 237: sys_set_mempolicy
+      2320,  // 238: sys_migrate_pages
+      2472,  // 239: sys_move_pages
+      3712,  // 240: sys_rt_tgsigqueueinfo
+      2960,  // 241: sys_perf_event_open
+      51,    // 242: sys_accept4
+      3428,  // 243: sys_recvmmsg
+      149,   // 244: sys_arch_specific_syscall
+      0,     // 245:
+      0,     // 246:
+      0,     // 247:
+      0,     // 248:
+      0,     // 249:
+      0,     // 250:
+      0,     // 251:
+      0,     // 252:
+      0,     // 253:
+      0,     // 254:
+      0,     // 255:
+      0,     // 256:
+      0,     // 257:
+      0,     // 258:
+      0,     // 259:
+      5606,  // 260: sys_wait4
+      3141,  // 261: sys_prlimit64
+      806,   // 262: sys_fanotify_init
+      824,   // 263: sys_fanotify_mark
+      2706,  // 264: sys_name_to_handle_at
+      2857,  // 265: sys_open_by_handle_at
+      342,   // 266: sys_clock_adjtime
+      5067,  // 267: sys_syncfs
+      4386,  // 268: sys_setns
+      4114,  // 269: sys_sendmmsg
+      3155,  // 270: sys_process_vm_readv
+      3176,  // 271: sys_process_vm_writev
+      2013,  // 272: sys_kcmp
+      964,   // 273: sys_finit_module
+      3918,  // 274: sys_sched_setattr
+      3810,  // 275: sys_sched_getattr
+      3514,  // 276: sys_renameat2
+      3994,  // 277: sys_seccomp
+      1533,  // 278: sys_getrandom
+      2303,  // 279: sys_memfd_create
+      241,   // 280: sys_bpf
+      710,   // 281: sys_execveat
+      5477,  // 282: sys_userfaultfd
+      2288,  // 283: sys_membarrier
+      2404,  // 284: sys_mlock2
+      465,   // 285: sys_copy_file_range
+      3129,  // 286: sys_preadv2
+      3279,  // 287: sys_pwritev2
+      3059,  // 288: sys_pkey_mprotect
+      3030,  // 289: sys_pkey_alloc
+      3045,  // 290: sys_pkey_free
+      4939,  // 291: sys_statx
+      1900,  // 292: sys_io_pgetevents
+      3574,  // 293: sys_rseq
+  };
+};
+
+struct SyscallTable_armeabi {
+  static constexpr const char* names = kAllSyscalllNames;
+  static constexpr SyscallTable::OffT offsets[]{
+      3544,  // 0: sys_restart_syscall
+      723,   // 1: sys_exit
+      1006,  // 2: sys_fork
+      3322,  // 3: sys_read
+      5639,  // 4: sys_write
+      2848,  // 5: sys_open
+      443,   // 6: sys_close
+      0,     // 7:
+      485,   // 8: sys_creat
+      2115,  // 9: sys_link
+      5430,  // 10: sys_unlink
+      699,   // 11: sys_execve
+      289,   // 12: sys_chdir
+      5142,  // 13: sys_time
+      2372,  // 14: sys_mknod
+      299,   // 15: sys_chmod
+      2077,  // 16: sys_lchown
+      0,     // 17:
+      0,     // 18:
+      2220,  // 19: sys_lseek
+      1482,  // 20: sys_getpid
+      2462,  // 21: sys_mount
+      5397,  // 22: sys_umount
+      4597,  // 23: sys_setuid
+      1705,  // 24: sys_getuid
+      4949,  // 25: sys_stime
+      3231,  // 26: sys_ptrace
+      124,   // 27: sys_alarm
+      0,     // 28:
+      2890,  // 29: sys_pause
+      5503,  // 30: sys_utime
+      0,     // 31:
+      0,     // 32:
+      63,    // 33: sys_access
+      2772,  // 34: sys_nice
+      0,     // 35:
+      5017,  // 36: sys_sync
+      2068,  // 37: sys_kill
+      3490,  // 38: sys_rename
+      2350,  // 39: sys_mkdir
+      3564,  // 40: sys_rmdir
+      531,   // 41: sys_dup
+      2996,  // 42: sys_pipe
+      5301,  // 43: sys_times
+      0,     // 44:
+      259,   // 45: sys_brk
+      4302,  // 46: sys_setgid
+      1374,  // 47: sys_getgid
+      0,     // 48:
+      1348,  // 49: sys_geteuid
+      1322,  // 50: sys_getegid
+      74,    // 51: sys_acct
+      5408,  // 52: sys_umount2
+      0,     // 53:
+      1945,  // 54: sys_ioctl
+      914,   // 55: sys_fcntl
+      0,     // 56:
+      4396,  // 57: sys_setpgid
+      0,     // 58:
+      0,     // 59:
+      5387,  // 60: sys_umask
+      331,   // 61: sys_chroot
+      5493,  // 62: sys_ustat
+      539,   // 63: sys_dup2
+      1505,  // 64: sys_getppid
+      1470,  // 65: sys_getpgrp
+      4554,  // 66: sys_setsid
+      4702,  // 67: sys_sigaction
+      0,     // 68:
+      0,     // 69:
+      4512,  // 70: sys_setreuid
+      4424,  // 71: sys_setregid
+      4815,  // 72: sys_sigsuspend
+      4770,  // 73: sys_sigpending
+      4356,  // 74: sys_sethostname
+      4540,  // 75: sys_setrlimit
+      1607,  // 76: sys_getrlimit
+      1621,  // 77: sys_getrusage
+      1688,  // 78: sys_gettimeofday
+      4580,  // 79: sys_settimeofday
+      1398,  // 80: sys_getgroups
+      4326,  // 81: sys_setgroups
+      4019,  // 82: sys_select
+      4991,  // 83: sys_symlink
+      0,     // 84:
+      3357,  // 85: sys_readlink
+      5466,  // 86: sys_uselib
+      4980,  // 87: sys_swapon
+      3395,  // 88: sys_reboot
+      3345,  // 89: sys_readdir
+      2428,  // 90: sys_mmap
+      2695,  // 91: sys_munmap
+      5321,  // 92: sys_truncate
+      1140,  // 93: sys_ftruncate
+      853,   // 94: sys_fchmod
+      877,   // 95: sys_fchown
+      1517,  // 96: sys_getpriority
+      4408,  // 97: sys_setpriority
+      0,     // 98:
+      4915,  // 99: sys_statfs
+      1094,  // 100: sys_fstatfs
+      0,     // 101:
+      4841,  // 102: sys_socketcall
+      5112,  // 103: sys_syslog
+      4372,  // 104: sys_setitimer
+      1428,  // 105: sys_getitimer
+      4895,  // 106: sys_stat
+      2244,  // 107: sys_lstat
+      1046,  // 108: sys_fstat
+      0,     // 109:
+      0,     // 110:
+      5548,  // 111: sys_vhangup
+      0,     // 112:
+      5078,  // 113: sys_syscall
+      5606,  // 114: sys_wait4
+      4968,  // 115: sys_swapoff
+      5100,  // 116: sys_sysinfo
+      2005,  // 117: sys_ipc
+      1120,  // 118: sys_fsync
+      4801,  // 119: sys_sigreturn
+      433,   // 120: sys_clone
+      4228,  // 121: sys_setdomainname
+      5420,  // 122: sys_uname
+      0,     // 123:
+      95,    // 124: sys_adjtimex
+      2487,  // 125: sys_mprotect
+      4785,  // 126: sys_sigprocmask
+      0,     // 127:
+      1760,  // 128: sys_init_module
+      513,   // 129: sys_delete_module
+      0,     // 130:
+      3309,  // 131: sys_quotactl
+      1458,  // 132: sys_getpgid
+      842,   // 133: sys_fchdir
+      220,   // 134: sys_bdflush
+      5090,  // 135: sys_sysfs
+      2980,  // 136: sys_personality
+      0,     // 137:
+      4274,  // 138: sys_setfsuid
+      4246,  // 139: sys_setfsgid
+      1,     // 140: sys__llseek
+      1294,  // 141: sys_getdents
+      13,    // 142: sys__newselect
+      996,   // 143: sys_flock
+      2658,  // 144: sys_msync
+      3385,  // 145: sys_readv
+      5649,  // 146: sys_writev
+      1635,  // 147: sys_getsid
+      936,   // 148: sys_fdatasync
+      28,    // 149: sys__sysctl
+      2394,  // 150: sys_mlock
+      2668,  // 151: sys_munlock
+      2415,  // 152: sys_mlockall
+      2680,  // 153: sys_munlockall
+      3936,  // 154: sys_sched_setparam
+      3828,  // 155: sys_sched_getparam
+      3955,  // 156: sys_sched_setscheduler
+      3847,  // 157: sys_sched_getscheduler
+      3978,  // 158: sys_sched_yield
+      3734,  // 159: sys_sched_get_priority_max
+      3761,  // 160: sys_sched_get_priority_min
+      3870,  // 161: sys_sched_rr_get_interval
+      2728,  // 162: sys_nanosleep
+      2603,  // 163: sys_mremap
+      4482,  // 164: sys_setresuid
+      1577,  // 165: sys_getresuid
+      0,     // 166:
+      0,     // 167:
+      3077,  // 168: sys_poll
+      2757,  // 169: sys_nfsservctl
+      4452,  // 170: sys_setresgid
+      1547,  // 171: sys_getresgid
+      3096,  // 172: sys_prctl
+      3657,  // 173: sys_rt_sigreturn
+      3583,  // 174: sys_rt_sigaction
+      3618,  // 175: sys_rt_sigprocmask
+      3600,  // 176: sys_rt_sigpending
+      3692,  // 177: sys_rt_sigtimedwait
+      3637,  // 178: sys_rt_sigqueueinfo
+      3674,  // 179: sys_rt_sigsuspend
+      3106,  // 180: sys_pread64
+      3254,  // 181: sys_pwrite64
+      309,   // 182: sys_chown
+      1283,  // 183: sys_getcwd
+      267,   // 184: sys_capget
+      278,   // 185: sys_capset
+      4716,  // 186: sys_sigaltstack
+      4086,  // 187: sys_sendfile
+      0,     // 188:
+      0,     // 189:
+      5538,  // 190: sys_vfork
+      5361,  // 191: sys_ugetrlimit
+      2437,  // 192: sys_mmap2
+      5334,  // 193: sys_truncate64
+      1154,  // 194: sys_ftruncate64
+      4904,  // 195: sys_stat64
+      2254,  // 196: sys_lstat64
+      1056,  // 197: sys_fstat64
+      2088,  // 198: sys_lchown32
+      1716,  // 199: sys_getuid32
+      1385,  // 200: sys_getgid32
+      1360,  // 201: sys_geteuid32
+      1334,  // 202: sys_getegid32
+      4525,  // 203: sys_setreuid32
+      4437,  // 204: sys_setregid32
+      1412,  // 205: sys_getgroups32
+      4340,  // 206: sys_setgroups32
+      888,   // 207: sys_fchown32
+      4496,  // 208: sys_setresuid32
+      1591,  // 209: sys_getresuid32
+      4466,  // 210: sys_setresgid32
+      1561,  // 211: sys_getresgid32
+      319,   // 212: sys_chown32
+      4608,  // 213: sys_setuid32
+      4313,  // 214: sys_setgid32
+      4287,  // 215: sys_setfsuid32
+      4259,  // 216: sys_setfsgid32
+      1307,  // 217: sys_getdents64
+      3015,  // 218: sys_pivot_root
+      2338,  // 219: sys_mincore
+      2266,  // 220: sys_madvise
+      924,   // 221: sys_fcntl64
+      0,     // 222:
+      0,     // 223:
+      1677,  // 224: sys_gettid
+      3331,  // 225: sys_readahead
+      4621,  // 226: sys_setxattr
+      2230,  // 227: sys_lsetxattr
+      1032,  // 228: sys_fsetxattr
+      1729,  // 229: sys_getxattr
+      2101,  // 230: sys_lgetxattr
+      950,   // 231: sys_fgetxattr
+      2146,  // 232: sys_listxattr
+      2160,  // 233: sys_llistxattr
+      981,   // 234: sys_flistxattr
+      3474,  // 235: sys_removexattr
+      2203,  // 236: sys_lremovexattr
+      1015,  // 237: sys_fremovexattr
+      5311,  // 238: sys_tkill
+      4099,  // 239: sys_sendfile64
+      1170,  // 240: sys_futex
+      3896,  // 241: sys_sched_setaffinity
+      3788,  // 242: sys_sched_getaffinity
+      1918,  // 243: sys_io_setup
+      1868,  // 244: sys_io_destroy
+      1883,  // 245: sys_io_getevents
+      1931,  // 246: sys_io_submit
+      1854,  // 247: sys_io_cancel
+      732,   // 248: sys_exit_group
+      2184,  // 249: sys_lookup_dcookie
+      557,   // 250: sys_epoll_create
+      592,   // 251: sys_epoll_ctl
+      640,   // 252: sys_epoll_wait
+      3453,  // 253: sys_remap_file_pages
+      0,     // 254:
+      0,     // 255:
+      4208,  // 256: sys_set_tid_address
+      5151,  // 257: sys_timer_create
+      5224,  // 258: sys_timer_settime
+      5206,  // 259: sys_timer_gettime
+      5185,  // 260: sys_timer_getoverrun
+      5168,  // 261: sys_timer_delete
+      415,   // 262: sys_clock_settime
+      377,   // 263: sys_clock_gettime
+      360,   // 264: sys_clock_getres
+      395,   // 265: sys_clock_nanosleep
+      4926,  // 266: sys_statfs64
+      1106,  // 267: sys_fstatfs64
+      5131,  // 268: sys_tgkill
+      5527,  // 269: sys_utimes
+      175,   // 270: sys_arm_fadvise64_64
+      2900,  // 271: sys_pciconfig_iobase
+      2921,  // 272: sys_pciconfig_read
+      2940,  // 273: sys_pciconfig_write
+      2540,  // 274: sys_mq_open
+      2589,  // 275: sys_mq_unlink
+      2572,  // 276: sys_mq_timedsend
+      2552,  // 277: sys_mq_timedreceive
+      2526,  // 278: sys_mq_notify
+      2508,  // 279: sys_mq_getsetattr
+      5616,  // 280: sys_waitid
+      4830,  // 281: sys_socket
+      232,   // 282: sys_bind
+      453,   // 283: sys_connect
+      2135,  // 284: sys_listen
+      40,    // 285: sys_accept
+      1646,  // 286: sys_getsockname
+      1442,  // 287: sys_getpeername
+      4856,  // 288: sys_socketpair
+      4077,  // 289: sys_send
+      4139,  // 290: sys_sendto
+      3406,  // 291: sys_recv
+      3415,  // 292: sys_recvfrom
+      4689,  // 293: sys_shutdown
+      4565,  // 294: sys_setsockopt
+      1662,  // 295: sys_getsockopt
+      4127,  // 296: sys_sendmsg
+      3441,  // 297: sys_recvmsg
+      4052,  // 298: sys_semop
+      4041,  // 299: sys_semget
+      4030,  // 300: sys_semctl
+      2647,  // 301: sys_msgsnd
+      2636,  // 302: sys_msgrcv
+      2625,  // 303: sys_msgget
+      2614,  // 304: sys_msgctl
+      4647,  // 305: sys_shmat
+      4668,  // 306: sys_shmdt
+      4678,  // 307: sys_shmget
+      4657,  // 308: sys_shmctl
+      83,    // 309: sys_add_key
+      3528,  // 310: sys_request_key
+      2057,  // 311: sys_keyctl
+      4062,  // 312: sys_semtimedop
+      5594,  // 313: sys_vserver
+      1990,  // 314: sys_ioprio_set
+      1975,  // 315: sys_ioprio_get
+      1798,  // 316: sys_inotify_init
+      1776,  // 317: sys_inotify_add_watch
+      1833,  // 318: sys_inotify_rm_watch
+      2278,  // 319: sys_mbind
+      1214,  // 320: sys_get_mempolicy
+      4150,  // 321: sys_set_mempolicy
+      2879,  // 322: sys_openat
+      2360,  // 323: sys_mkdirat
+      2382,  // 324: sys_mknodat
+      901,   // 325: sys_fchownat
+      1180,  // 326: sys_futimesat
+      1080,  // 327: sys_fstatat64
+      5441,  // 328: sys_unlinkat
+      3501,  // 329: sys_renameat
+      2124,  // 330: sys_linkat
+      5003,  // 331: sys_symlinkat
+      3370,  // 332: sys_readlinkat
+      864,   // 333: sys_fchmodat
+      747,   // 334: sys_faccessat
+      3218,  // 335: sys_pselect6
+      3086,  // 336: sys_ppoll
+      5454,  // 337: sys_unshare
+      4168,  // 338: sys_set_robust_list
+      1232,  // 339: sys_get_robust_list
+      4871,  // 340: sys_splice
+      196,   // 341: sys_arm_sync_file_range
+      5123,  // 342: sys_tee
+      5581,  // 343: sys_vmsplice
+      2472,  // 344: sys_move_pages
+      1272,  // 345: sys_getcpu
+      624,   // 346: sys_epoll_pwait
+      2042,  // 347: sys_kexec_load
+      5513,  // 348: sys_utimensat
+      4743,  // 349: sys_signalfd
+      5242,  // 350: sys_timerfd_create
+      674,   // 351: sys_eventfd
+      792,   // 352: sys_fallocate
+      5281,  // 353: sys_timerfd_settime
+      5261,  // 354: sys_timerfd_gettime
+      4756,  // 355: sys_signalfd4
+      686,   // 356: sys_eventfd2
+      574,   // 357: sys_epoll_create1
+      548,   // 358: sys_dup3
+      3005,  // 359: sys_pipe2
+      1815,  // 360: sys_inotify_init1
+      3118,  // 361: sys_preadv
+      3267,  // 362: sys_pwritev
+      3712,  // 363: sys_rt_tgsigqueueinfo
+      2960,  // 364: sys_perf_event_open
+      3428,  // 365: sys_recvmmsg
+      51,    // 366: sys_accept4
+      806,   // 367: sys_fanotify_init
+      824,   // 368: sys_fanotify_mark
+      3141,  // 369: sys_prlimit64
+      2706,  // 370: sys_name_to_handle_at
+      2857,  // 371: sys_open_by_handle_at
+      342,   // 372: sys_clock_adjtime
+      5067,  // 373: sys_syncfs
+      4114,  // 374: sys_sendmmsg
+      4386,  // 375: sys_setns
+      3155,  // 376: sys_process_vm_readv
+      3176,  // 377: sys_process_vm_writev
+      2013,  // 378: sys_kcmp
+      964,   // 379: sys_finit_module
+      3918,  // 380: sys_sched_setattr
+      3810,  // 381: sys_sched_getattr
+      3514,  // 382: sys_renameat2
+      3994,  // 383: sys_seccomp
+      1533,  // 384: sys_getrandom
+      2303,  // 385: sys_memfd_create
+      241,   // 386: sys_bpf
+      710,   // 387: sys_execveat
+      5477,  // 388: sys_userfaultfd
+      2288,  // 389: sys_membarrier
+      2404,  // 390: sys_mlock2
+      465,   // 391: sys_copy_file_range
+      3129,  // 392: sys_preadv2
+      3279,  // 393: sys_pwritev2
+      3059,  // 394: sys_pkey_mprotect
+      3030,  // 395: sys_pkey_alloc
+      3045,  // 396: sys_pkey_free
+      4939,  // 397: sys_statx
+      3574,  // 398: sys_rseq
+      1900,  // 399: sys_io_pgetevents
+  };
+};
+
+struct SyscallTable_x86 {
+  static constexpr const char* names = kAllSyscalllNames;
+  static constexpr SyscallTable::OffT offsets[]{
+      3544,  // 0: sys_restart_syscall
+      723,   // 1: sys_exit
+      1006,  // 2: sys_fork
+      3322,  // 3: sys_read
+      5639,  // 4: sys_write
+      2848,  // 5: sys_open
+      443,   // 6: sys_close
+      5627,  // 7: sys_waitpid
+      485,   // 8: sys_creat
+      2115,  // 9: sys_link
+      5430,  // 10: sys_unlink
+      699,   // 11: sys_execve
+      289,   // 12: sys_chdir
+      5142,  // 13: sys_time
+      2372,  // 14: sys_mknod
+      299,   // 15: sys_chmod
+      2077,  // 16: sys_lchown
+      249,   // 17: sys_break
+      2823,  // 18: sys_oldstat
+      2220,  // 19: sys_lseek
+      1482,  // 20: sys_getpid
+      2462,  // 21: sys_mount
+      5397,  // 22: sys_umount
+      4597,  // 23: sys_setuid
+      1705,  // 24: sys_getuid
+      4949,  // 25: sys_stime
+      3231,  // 26: sys_ptrace
+      124,   // 27: sys_alarm
+      2781,  // 28: sys_oldfstat
+      2890,  // 29: sys_pause
+      5503,  // 30: sys_utime
+      4959,  // 31: sys_stty
+      1742,  // 32: sys_gtty
+      63,    // 33: sys_access
+      2772,  // 34: sys_nice
+      1130,  // 35: sys_ftime
+      5017,  // 36: sys_sync
+      2068,  // 37: sys_kill
+      3490,  // 38: sys_rename
+      2350,  // 39: sys_mkdir
+      3564,  // 40: sys_rmdir
+      531,   // 41: sys_dup
+      2996,  // 42: sys_pipe
+      5301,  // 43: sys_times
+      3198,  // 44: sys_prof
+      259,   // 45: sys_brk
+      4302,  // 46: sys_setgid
+      1374,  // 47: sys_getgid
+      4732,  // 48: sys_signal
+      1348,  // 49: sys_geteuid
+      1322,  // 50: sys_getegid
+      74,    // 51: sys_acct
+      5408,  // 52: sys_umount2
+      2175,  // 53: sys_lock
+      1945,  // 54: sys_ioctl
+      914,   // 55: sys_fcntl
+      2500,  // 56: sys_mpx
+      4396,  // 57: sys_setpgid
+      5376,  // 58: sys_ulimit
+      2807,  // 59: sys_oldolduname
+      5387,  // 60: sys_umask
+      331,   // 61: sys_chroot
+      5493,  // 62: sys_ustat
+      539,   // 63: sys_dup2
+      1505,  // 64: sys_getppid
+      1470,  // 65: sys_getpgrp
+      4554,  // 66: sys_setsid
+      4702,  // 67: sys_sigaction
+      4634,  // 68: sys_sgetmask
+      4882,  // 69: sys_ssetmask
+      4512,  // 70: sys_setreuid
+      4424,  // 71: sys_setregid
+      4815,  // 72: sys_sigsuspend
+      4770,  // 73: sys_sigpending
+      4356,  // 74: sys_sethostname
+      4540,  // 75: sys_setrlimit
+      1607,  // 76: sys_getrlimit
+      1621,  // 77: sys_getrusage
+      1688,  // 78: sys_gettimeofday
+      4580,  // 79: sys_settimeofday
+      1398,  // 80: sys_getgroups
+      4326,  // 81: sys_setgroups
+      4019,  // 82: sys_select
+      4991,  // 83: sys_symlink
+      2794,  // 84: sys_oldlstat
+      3357,  // 85: sys_readlink
+      5466,  // 86: sys_uselib
+      4980,  // 87: sys_swapon
+      3395,  // 88: sys_reboot
+      3345,  // 89: sys_readdir
+      2428,  // 90: sys_mmap
+      2695,  // 91: sys_munmap
+      5321,  // 92: sys_truncate
+      1140,  // 93: sys_ftruncate
+      853,   // 94: sys_fchmod
+      877,   // 95: sys_fchown
+      1517,  // 96: sys_getpriority
+      4408,  // 97: sys_setpriority
+      3207,  // 98: sys_profil
+      4915,  // 99: sys_statfs
+      1094,  // 100: sys_fstatfs
+      1955,  // 101: sys_ioperm
+      4841,  // 102: sys_socketcall
+      5112,  // 103: sys_syslog
+      4372,  // 104: sys_setitimer
+      1428,  // 105: sys_getitimer
+      4895,  // 106: sys_stat
+      2244,  // 107: sys_lstat
+      1046,  // 108: sys_fstat
+      2835,  // 109: sys_olduname
+      1966,  // 110: sys_iopl
+      5548,  // 111: sys_vhangup
+      1751,  // 112: sys_idle
+      5569,  // 113: sys_vm86old
+      5606,  // 114: sys_wait4
+      4968,  // 115: sys_swapoff
+      5100,  // 116: sys_sysinfo
+      2005,  // 117: sys_ipc
+      1120,  // 118: sys_fsync
+      4801,  // 119: sys_sigreturn
+      433,   // 120: sys_clone
+      4228,  // 121: sys_setdomainname
+      5420,  // 122: sys_uname
+      2447,  // 123: sys_modify_ldt
+      95,    // 124: sys_adjtimex
+      2487,  // 125: sys_mprotect
+      4785,  // 126: sys_sigprocmask
+      495,   // 127: sys_create_module
+      1760,  // 128: sys_init_module
+      513,   // 129: sys_delete_module
+      1194,  // 130: sys_get_kernel_syms
+      3309,  // 131: sys_quotactl
+      1458,  // 132: sys_getpgid
+      842,   // 133: sys_fchdir
+      220,   // 134: sys_bdflush
+      5090,  // 135: sys_sysfs
+      2980,  // 136: sys_personality
+      108,   // 137: sys_afs_syscall
+      4274,  // 138: sys_setfsuid
+      4246,  // 139: sys_setfsgid
+      1,     // 140: sys__llseek
+      1294,  // 141: sys_getdents
+      13,    // 142: sys__newselect
+      996,   // 143: sys_flock
+      2658,  // 144: sys_msync
+      3385,  // 145: sys_readv
+      5649,  // 146: sys_writev
+      1635,  // 147: sys_getsid
+      936,   // 148: sys_fdatasync
+      28,    // 149: sys__sysctl
+      2394,  // 150: sys_mlock
+      2668,  // 151: sys_munlock
+      2415,  // 152: sys_mlockall
+      2680,  // 153: sys_munlockall
+      3936,  // 154: sys_sched_setparam
+      3828,  // 155: sys_sched_getparam
+      3955,  // 156: sys_sched_setscheduler
+      3847,  // 157: sys_sched_getscheduler
+      3978,  // 158: sys_sched_yield
+      3734,  // 159: sys_sched_get_priority_max
+      3761,  // 160: sys_sched_get_priority_min
+      3870,  // 161: sys_sched_rr_get_interval
+      2728,  // 162: sys_nanosleep
+      2603,  // 163: sys_mremap
+      4482,  // 164: sys_setresuid
+      1577,  // 165: sys_getresuid
+      5560,  // 166: sys_vm86
+      3292,  // 167: sys_query_module
+      3077,  // 168: sys_poll
+      2757,  // 169: sys_nfsservctl
+      4452,  // 170: sys_setresgid
+      1547,  // 171: sys_getresgid
+      3096,  // 172: sys_prctl
+      3657,  // 173: sys_rt_sigreturn
+      3583,  // 174: sys_rt_sigaction
+      3618,  // 175: sys_rt_sigprocmask
+      3600,  // 176: sys_rt_sigpending
+      3692,  // 177: sys_rt_sigtimedwait
+      3637,  // 178: sys_rt_sigqueueinfo
+      3674,  // 179: sys_rt_sigsuspend
+      3106,  // 180: sys_pread64
+      3254,  // 181: sys_pwrite64
+      309,   // 182: sys_chown
+      1283,  // 183: sys_getcwd
+      267,   // 184: sys_capget
+      278,   // 185: sys_capset
+      4716,  // 186: sys_sigaltstack
+      4086,  // 187: sys_sendfile
+      1493,  // 188: sys_getpmsg
+      3242,  // 189: sys_putpmsg
+      5538,  // 190: sys_vfork
+      5361,  // 191: sys_ugetrlimit
+      2437,  // 192: sys_mmap2
+      5334,  // 193: sys_truncate64
+      1154,  // 194: sys_ftruncate64
+      4904,  // 195: sys_stat64
+      2254,  // 196: sys_lstat64
+      1056,  // 197: sys_fstat64
+      2088,  // 198: sys_lchown32
+      1716,  // 199: sys_getuid32
+      1385,  // 200: sys_getgid32
+      1360,  // 201: sys_geteuid32
+      1334,  // 202: sys_getegid32
+      4525,  // 203: sys_setreuid32
+      4437,  // 204: sys_setregid32
+      1412,  // 205: sys_getgroups32
+      4340,  // 206: sys_setgroups32
+      888,   // 207: sys_fchown32
+      4496,  // 208: sys_setresuid32
+      1591,  // 209: sys_getresuid32
+      4466,  // 210: sys_setresgid32
+      1561,  // 211: sys_getresgid32
+      319,   // 212: sys_chown32
+      4608,  // 213: sys_setuid32
+      4313,  // 214: sys_setgid32
+      4287,  // 215: sys_setfsuid32
+      4259,  // 216: sys_setfsgid32
+      3015,  // 217: sys_pivot_root
+      2338,  // 218: sys_mincore
+      2266,  // 219: sys_madvise
+      1307,  // 220: sys_getdents64
+      924,   // 221: sys_fcntl64
+      0,     // 222:
+      0,     // 223:
+      1677,  // 224: sys_gettid
+      3331,  // 225: sys_readahead
+      4621,  // 226: sys_setxattr
+      2230,  // 227: sys_lsetxattr
+      1032,  // 228: sys_fsetxattr
+      1729,  // 229: sys_getxattr
+      2101,  // 230: sys_lgetxattr
+      950,   // 231: sys_fgetxattr
+      2146,  // 232: sys_listxattr
+      2160,  // 233: sys_llistxattr
+      981,   // 234: sys_flistxattr
+      3474,  // 235: sys_removexattr
+      2203,  // 236: sys_lremovexattr
+      1015,  // 237: sys_fremovexattr
+      5311,  // 238: sys_tkill
+      4099,  // 239: sys_sendfile64
+      1170,  // 240: sys_futex
+      3896,  // 241: sys_sched_setaffinity
+      3788,  // 242: sys_sched_getaffinity
+      4188,  // 243: sys_set_thread_area
+      1252,  // 244: sys_get_thread_area
+      1918,  // 245: sys_io_setup
+      1868,  // 246: sys_io_destroy
+      1883,  // 247: sys_io_getevents
+      1931,  // 248: sys_io_submit
+      1854,  // 249: sys_io_cancel
+      761,   // 250: sys_fadvise64
+      0,     // 251:
+      732,   // 252: sys_exit_group
+      2184,  // 253: sys_lookup_dcookie
+      557,   // 254: sys_epoll_create
+      592,   // 255: sys_epoll_ctl
+      640,   // 256: sys_epoll_wait
+      3453,  // 257: sys_remap_file_pages
+      4208,  // 258: sys_set_tid_address
+      5151,  // 259: sys_timer_create
+      5224,  // 260: sys_timer_settime
+      5206,  // 261: sys_timer_gettime
+      5185,  // 262: sys_timer_getoverrun
+      5168,  // 263: sys_timer_delete
+      415,   // 264: sys_clock_settime
+      377,   // 265: sys_clock_gettime
+      360,   // 266: sys_clock_getres
+      395,   // 267: sys_clock_nanosleep
+      4926,  // 268: sys_statfs64
+      1106,  // 269: sys_fstatfs64
+      5131,  // 270: sys_tgkill
+      5527,  // 271: sys_utimes
+      775,   // 272: sys_fadvise64_64
+      5594,  // 273: sys_vserver
+      2278,  // 274: sys_mbind
+      1214,  // 275: sys_get_mempolicy
+      4150,  // 276: sys_set_mempolicy
+      2540,  // 277: sys_mq_open
+      2589,  // 278: sys_mq_unlink
+      2572,  // 279: sys_mq_timedsend
+      2552,  // 280: sys_mq_timedreceive
+      2526,  // 281: sys_mq_notify
+      2508,  // 282: sys_mq_getsetattr
+      2042,  // 283: sys_kexec_load
+      5616,  // 284: sys_waitid
+      0,     // 285:
+      83,    // 286: sys_add_key
+      3528,  // 287: sys_request_key
+      2057,  // 288: sys_keyctl
+      1990,  // 289: sys_ioprio_set
+      1975,  // 290: sys_ioprio_get
+      1798,  // 291: sys_inotify_init
+      1776,  // 292: sys_inotify_add_watch
+      1833,  // 293: sys_inotify_rm_watch
+      2320,  // 294: sys_migrate_pages
+      2879,  // 295: sys_openat
+      2360,  // 296: sys_mkdirat
+      2382,  // 297: sys_mknodat
+      901,   // 298: sys_fchownat
+      1180,  // 299: sys_futimesat
+      1080,  // 300: sys_fstatat64
+      5441,  // 301: sys_unlinkat
+      3501,  // 302: sys_renameat
+      2124,  // 303: sys_linkat
+      5003,  // 304: sys_symlinkat
+      3370,  // 305: sys_readlinkat
+      864,   // 306: sys_fchmodat
+      747,   // 307: sys_faccessat
+      3218,  // 308: sys_pselect6
+      3086,  // 309: sys_ppoll
+      5454,  // 310: sys_unshare
+      4168,  // 311: sys_set_robust_list
+      1232,  // 312: sys_get_robust_list
+      4871,  // 313: sys_splice
+      5026,  // 314: sys_sync_file_range
+      5123,  // 315: sys_tee
+      5581,  // 316: sys_vmsplice
+      2472,  // 317: sys_move_pages
+      1272,  // 318: sys_getcpu
+      624,   // 319: sys_epoll_pwait
+      5513,  // 320: sys_utimensat
+      4743,  // 321: sys_signalfd
+      5242,  // 322: sys_timerfd_create
+      674,   // 323: sys_eventfd
+      792,   // 324: sys_fallocate
+      5281,  // 325: sys_timerfd_settime
+      5261,  // 326: sys_timerfd_gettime
+      4756,  // 327: sys_signalfd4
+      686,   // 328: sys_eventfd2
+      574,   // 329: sys_epoll_create1
+      548,   // 330: sys_dup3
+      3005,  // 331: sys_pipe2
+      1815,  // 332: sys_inotify_init1
+      3118,  // 333: sys_preadv
+      3267,  // 334: sys_pwritev
+      3712,  // 335: sys_rt_tgsigqueueinfo
+      2960,  // 336: sys_perf_event_open
+      3428,  // 337: sys_recvmmsg
+      806,   // 338: sys_fanotify_init
+      824,   // 339: sys_fanotify_mark
+      3141,  // 340: sys_prlimit64
+      2706,  // 341: sys_name_to_handle_at
+      2857,  // 342: sys_open_by_handle_at
+      342,   // 343: sys_clock_adjtime
+      5067,  // 344: sys_syncfs
+      4114,  // 345: sys_sendmmsg
+      4386,  // 346: sys_setns
+      3155,  // 347: sys_process_vm_readv
+      3176,  // 348: sys_process_vm_writev
+      2013,  // 349: sys_kcmp
+      964,   // 350: sys_finit_module
+      3918,  // 351: sys_sched_setattr
+      3810,  // 352: sys_sched_getattr
+      3514,  // 353: sys_renameat2
+      3994,  // 354: sys_seccomp
+      1533,  // 355: sys_getrandom
+      2303,  // 356: sys_memfd_create
+      241,   // 357: sys_bpf
+      710,   // 358: sys_execveat
+      4830,  // 359: sys_socket
+      4856,  // 360: sys_socketpair
+      232,   // 361: sys_bind
+      453,   // 362: sys_connect
+      2135,  // 363: sys_listen
+      51,    // 364: sys_accept4
+      1662,  // 365: sys_getsockopt
+      4565,  // 366: sys_setsockopt
+      1646,  // 367: sys_getsockname
+      1442,  // 368: sys_getpeername
+      4139,  // 369: sys_sendto
+      4127,  // 370: sys_sendmsg
+      3415,  // 371: sys_recvfrom
+      3441,  // 372: sys_recvmsg
+      4689,  // 373: sys_shutdown
+      5477,  // 374: sys_userfaultfd
+      2288,  // 375: sys_membarrier
+      2404,  // 376: sys_mlock2
+      465,   // 377: sys_copy_file_range
+      3129,  // 378: sys_preadv2
+      3279,  // 379: sys_pwritev2
+      3059,  // 380: sys_pkey_mprotect
+      3030,  // 381: sys_pkey_alloc
+      3045,  // 382: sys_pkey_free
+      4939,  // 383: sys_statx
+      134,   // 384: sys_arch_prctl
+      1900,  // 385: sys_io_pgetevents
+      3574,  // 386: sys_rseq
+  };
+};
+
+struct SyscallTable_x86_64 {
+  static constexpr const char* names = kAllSyscalllNames;
+  static constexpr SyscallTable::OffT offsets[]{
+      3322,  // 0: sys_read
+      5639,  // 1: sys_write
+      2848,  // 2: sys_open
+      443,   // 3: sys_close
+      4895,  // 4: sys_stat
+      1046,  // 5: sys_fstat
+      2244,  // 6: sys_lstat
+      3077,  // 7: sys_poll
+      2220,  // 8: sys_lseek
+      2428,  // 9: sys_mmap
+      2487,  // 10: sys_mprotect
+      2695,  // 11: sys_munmap
+      259,   // 12: sys_brk
+      3583,  // 13: sys_rt_sigaction
+      3618,  // 14: sys_rt_sigprocmask
+      3657,  // 15: sys_rt_sigreturn
+      1945,  // 16: sys_ioctl
+      3106,  // 17: sys_pread64
+      3254,  // 18: sys_pwrite64
+      3385,  // 19: sys_readv
+      5649,  // 20: sys_writev
+      63,    // 21: sys_access
+      2996,  // 22: sys_pipe
+      4019,  // 23: sys_select
+      3978,  // 24: sys_sched_yield
+      2603,  // 25: sys_mremap
+      2658,  // 26: sys_msync
+      2338,  // 27: sys_mincore
+      2266,  // 28: sys_madvise
+      4678,  // 29: sys_shmget
+      4647,  // 30: sys_shmat
+      4657,  // 31: sys_shmctl
+      531,   // 32: sys_dup
+      539,   // 33: sys_dup2
+      2890,  // 34: sys_pause
+      2728,  // 35: sys_nanosleep
+      1428,  // 36: sys_getitimer
+      124,   // 37: sys_alarm
+      4372,  // 38: sys_setitimer
+      1482,  // 39: sys_getpid
+      4086,  // 40: sys_sendfile
+      4830,  // 41: sys_socket
+      453,   // 42: sys_connect
+      40,    // 43: sys_accept
+      4139,  // 44: sys_sendto
+      3415,  // 45: sys_recvfrom
+      4127,  // 46: sys_sendmsg
+      3441,  // 47: sys_recvmsg
+      4689,  // 48: sys_shutdown
+      232,   // 49: sys_bind
+      2135,  // 50: sys_listen
+      1646,  // 51: sys_getsockname
+      1442,  // 52: sys_getpeername
+      4856,  // 53: sys_socketpair
+      4565,  // 54: sys_setsockopt
+      1662,  // 55: sys_getsockopt
+      433,   // 56: sys_clone
+      1006,  // 57: sys_fork
+      5538,  // 58: sys_vfork
+      699,   // 59: sys_execve
+      723,   // 60: sys_exit
+      5606,  // 61: sys_wait4
+      2068,  // 62: sys_kill
+      5420,  // 63: sys_uname
+      4041,  // 64: sys_semget
+      4052,  // 65: sys_semop
+      4030,  // 66: sys_semctl
+      4668,  // 67: sys_shmdt
+      2625,  // 68: sys_msgget
+      2647,  // 69: sys_msgsnd
+      2636,  // 70: sys_msgrcv
+      2614,  // 71: sys_msgctl
+      914,   // 72: sys_fcntl
+      996,   // 73: sys_flock
+      1120,  // 74: sys_fsync
+      936,   // 75: sys_fdatasync
+      5321,  // 76: sys_truncate
+      1140,  // 77: sys_ftruncate
+      1294,  // 78: sys_getdents
+      1283,  // 79: sys_getcwd
+      289,   // 80: sys_chdir
+      842,   // 81: sys_fchdir
+      3490,  // 82: sys_rename
+      2350,  // 83: sys_mkdir
+      3564,  // 84: sys_rmdir
+      485,   // 85: sys_creat
+      2115,  // 86: sys_link
+      5430,  // 87: sys_unlink
+      4991,  // 88: sys_symlink
+      3357,  // 89: sys_readlink
+      299,   // 90: sys_chmod
+      853,   // 91: sys_fchmod
+      309,   // 92: sys_chown
+      877,   // 93: sys_fchown
+      2077,  // 94: sys_lchown
+      5387,  // 95: sys_umask
+      1688,  // 96: sys_gettimeofday
+      1607,  // 97: sys_getrlimit
+      1621,  // 98: sys_getrusage
+      5100,  // 99: sys_sysinfo
+      5301,  // 100: sys_times
+      3231,  // 101: sys_ptrace
+      1705,  // 102: sys_getuid
+      5112,  // 103: sys_syslog
+      1374,  // 104: sys_getgid
+      4597,  // 105: sys_setuid
+      4302,  // 106: sys_setgid
+      1348,  // 107: sys_geteuid
+      1322,  // 108: sys_getegid
+      4396,  // 109: sys_setpgid
+      1505,  // 110: sys_getppid
+      1470,  // 111: sys_getpgrp
+      4554,  // 112: sys_setsid
+      4512,  // 113: sys_setreuid
+      4424,  // 114: sys_setregid
+      1398,  // 115: sys_getgroups
+      4326,  // 116: sys_setgroups
+      4482,  // 117: sys_setresuid
+      1577,  // 118: sys_getresuid
+      4452,  // 119: sys_setresgid
+      1547,  // 120: sys_getresgid
+      1458,  // 121: sys_getpgid
+      4274,  // 122: sys_setfsuid
+      4246,  // 123: sys_setfsgid
+      1635,  // 124: sys_getsid
+      267,   // 125: sys_capget
+      278,   // 126: sys_capset
+      3600,  // 127: sys_rt_sigpending
+      3692,  // 128: sys_rt_sigtimedwait
+      3637,  // 129: sys_rt_sigqueueinfo
+      3674,  // 130: sys_rt_sigsuspend
+      4716,  // 131: sys_sigaltstack
+      5503,  // 132: sys_utime
+      2372,  // 133: sys_mknod
+      5466,  // 134: sys_uselib
+      2980,  // 135: sys_personality
+      5493,  // 136: sys_ustat
+      4915,  // 137: sys_statfs
+      1094,  // 138: sys_fstatfs
+      5090,  // 139: sys_sysfs
+      1517,  // 140: sys_getpriority
+      4408,  // 141: sys_setpriority
+      3936,  // 142: sys_sched_setparam
+      3828,  // 143: sys_sched_getparam
+      3955,  // 144: sys_sched_setscheduler
+      3847,  // 145: sys_sched_getscheduler
+      3734,  // 146: sys_sched_get_priority_max
+      3761,  // 147: sys_sched_get_priority_min
+      3870,  // 148: sys_sched_rr_get_interval
+      2394,  // 149: sys_mlock
+      2668,  // 150: sys_munlock
+      2415,  // 151: sys_mlockall
+      2680,  // 152: sys_munlockall
+      5548,  // 153: sys_vhangup
+      2447,  // 154: sys_modify_ldt
+      3015,  // 155: sys_pivot_root
+      28,    // 156: sys__sysctl
+      3096,  // 157: sys_prctl
+      134,   // 158: sys_arch_prctl
+      95,    // 159: sys_adjtimex
+      4540,  // 160: sys_setrlimit
+      331,   // 161: sys_chroot
+      5017,  // 162: sys_sync
+      74,    // 163: sys_acct
+      4580,  // 164: sys_settimeofday
+      2462,  // 165: sys_mount
+      5408,  // 166: sys_umount2
+      4980,  // 167: sys_swapon
+      4968,  // 168: sys_swapoff
+      3395,  // 169: sys_reboot
+      4356,  // 170: sys_sethostname
+      4228,  // 171: sys_setdomainname
+      1966,  // 172: sys_iopl
+      1955,  // 173: sys_ioperm
+      495,   // 174: sys_create_module
+      1760,  // 175: sys_init_module
+      513,   // 176: sys_delete_module
+      1194,  // 177: sys_get_kernel_syms
+      3292,  // 178: sys_query_module
+      3309,  // 179: sys_quotactl
+      2757,  // 180: sys_nfsservctl
+      1493,  // 181: sys_getpmsg
+      3242,  // 182: sys_putpmsg
+      108,   // 183: sys_afs_syscall
+      5349,  // 184: sys_tuxcall
+      4006,  // 185: sys_security
+      1677,  // 186: sys_gettid
+      3331,  // 187: sys_readahead
+      4621,  // 188: sys_setxattr
+      2230,  // 189: sys_lsetxattr
+      1032,  // 190: sys_fsetxattr
+      1729,  // 191: sys_getxattr
+      2101,  // 192: sys_lgetxattr
+      950,   // 193: sys_fgetxattr
+      2146,  // 194: sys_listxattr
+      2160,  // 195: sys_llistxattr
+      981,   // 196: sys_flistxattr
+      3474,  // 197: sys_removexattr
+      2203,  // 198: sys_lremovexattr
+      1015,  // 199: sys_fremovexattr
+      5311,  // 200: sys_tkill
+      5142,  // 201: sys_time
+      1170,  // 202: sys_futex
+      3896,  // 203: sys_sched_setaffinity
+      3788,  // 204: sys_sched_getaffinity
+      4188,  // 205: sys_set_thread_area
+      1918,  // 206: sys_io_setup
+      1868,  // 207: sys_io_destroy
+      1883,  // 208: sys_io_getevents
+      1931,  // 209: sys_io_submit
+      1854,  // 210: sys_io_cancel
+      1252,  // 211: sys_get_thread_area
+      2184,  // 212: sys_lookup_dcookie
+      557,   // 213: sys_epoll_create
+      606,   // 214: sys_epoll_ctl_old
+      655,   // 215: sys_epoll_wait_old
+      3453,  // 216: sys_remap_file_pages
+      1307,  // 217: sys_getdents64
+      4208,  // 218: sys_set_tid_address
+      3544,  // 219: sys_restart_syscall
+      4062,  // 220: sys_semtimedop
+      761,   // 221: sys_fadvise64
+      5151,  // 222: sys_timer_create
+      5224,  // 223: sys_timer_settime
+      5206,  // 224: sys_timer_gettime
+      5185,  // 225: sys_timer_getoverrun
+      5168,  // 226: sys_timer_delete
+      415,   // 227: sys_clock_settime
+      377,   // 228: sys_clock_gettime
+      360,   // 229: sys_clock_getres
+      395,   // 230: sys_clock_nanosleep
+      732,   // 231: sys_exit_group
+      640,   // 232: sys_epoll_wait
+      592,   // 233: sys_epoll_ctl
+      5131,  // 234: sys_tgkill
+      5527,  // 235: sys_utimes
+      5594,  // 236: sys_vserver
+      2278,  // 237: sys_mbind
+      4150,  // 238: sys_set_mempolicy
+      1214,  // 239: sys_get_mempolicy
+      2540,  // 240: sys_mq_open
+      2589,  // 241: sys_mq_unlink
+      2572,  // 242: sys_mq_timedsend
+      2552,  // 243: sys_mq_timedreceive
+      2526,  // 244: sys_mq_notify
+      2508,  // 245: sys_mq_getsetattr
+      2042,  // 246: sys_kexec_load
+      5616,  // 247: sys_waitid
+      83,    // 248: sys_add_key
+      3528,  // 249: sys_request_key
+      2057,  // 250: sys_keyctl
+      1990,  // 251: sys_ioprio_set
+      1975,  // 252: sys_ioprio_get
+      1798,  // 253: sys_inotify_init
+      1776,  // 254: sys_inotify_add_watch
+      1833,  // 255: sys_inotify_rm_watch
+      2320,  // 256: sys_migrate_pages
+      2879,  // 257: sys_openat
+      2360,  // 258: sys_mkdirat
+      2382,  // 259: sys_mknodat
+      901,   // 260: sys_fchownat
+      1180,  // 261: sys_futimesat
+      2742,  // 262: sys_newfstatat
+      5441,  // 263: sys_unlinkat
+      3501,  // 264: sys_renameat
+      2124,  // 265: sys_linkat
+      5003,  // 266: sys_symlinkat
+      3370,  // 267: sys_readlinkat
+      864,   // 268: sys_fchmodat
+      747,   // 269: sys_faccessat
+      3218,  // 270: sys_pselect6
+      3086,  // 271: sys_ppoll
+      5454,  // 272: sys_unshare
+      4168,  // 273: sys_set_robust_list
+      1232,  // 274: sys_get_robust_list
+      4871,  // 275: sys_splice
+      5123,  // 276: sys_tee
+      5026,  // 277: sys_sync_file_range
+      5581,  // 278: sys_vmsplice
+      2472,  // 279: sys_move_pages
+      5513,  // 280: sys_utimensat
+      624,   // 281: sys_epoll_pwait
+      4743,  // 282: sys_signalfd
+      5242,  // 283: sys_timerfd_create
+      674,   // 284: sys_eventfd
+      792,   // 285: sys_fallocate
+      5281,  // 286: sys_timerfd_settime
+      5261,  // 287: sys_timerfd_gettime
+      51,    // 288: sys_accept4
+      4756,  // 289: sys_signalfd4
+      686,   // 290: sys_eventfd2
+      574,   // 291: sys_epoll_create1
+      548,   // 292: sys_dup3
+      3005,  // 293: sys_pipe2
+      1815,  // 294: sys_inotify_init1
+      3118,  // 295: sys_preadv
+      3267,  // 296: sys_pwritev
+      3712,  // 297: sys_rt_tgsigqueueinfo
+      2960,  // 298: sys_perf_event_open
+      3428,  // 299: sys_recvmmsg
+      806,   // 300: sys_fanotify_init
+      824,   // 301: sys_fanotify_mark
+      3141,  // 302: sys_prlimit64
+      2706,  // 303: sys_name_to_handle_at
+      2857,  // 304: sys_open_by_handle_at
+      342,   // 305: sys_clock_adjtime
+      5067,  // 306: sys_syncfs
+      4114,  // 307: sys_sendmmsg
+      4386,  // 308: sys_setns
+      1272,  // 309: sys_getcpu
+      3155,  // 310: sys_process_vm_readv
+      3176,  // 311: sys_process_vm_writev
+      2013,  // 312: sys_kcmp
+      964,   // 313: sys_finit_module
+      3918,  // 314: sys_sched_setattr
+      3810,  // 315: sys_sched_getattr
+      3514,  // 316: sys_renameat2
+      3994,  // 317: sys_seccomp
+      1533,  // 318: sys_getrandom
+      2303,  // 319: sys_memfd_create
+      2022,  // 320: sys_kexec_file_load
+      241,   // 321: sys_bpf
+      710,   // 322: sys_execveat
+      5477,  // 323: sys_userfaultfd
+      2288,  // 324: sys_membarrier
+      2404,  // 325: sys_mlock2
+      465,   // 326: sys_copy_file_range
+      3129,  // 327: sys_preadv2
+      3279,  // 328: sys_pwritev2
+      3059,  // 329: sys_pkey_mprotect
+      3030,  // 330: sys_pkey_alloc
+      3045,  // 331: sys_pkey_free
+      4939,  // 332: sys_statx
+      1900,  // 333: sys_io_pgetevents
+      3574,  // 334: sys_rseq
+      0,     // 335:
+      0,     // 336:
+      0,     // 337:
+      0,     // 338:
+      0,     // 339:
+      0,     // 340:
+      0,     // 341:
+      0,     // 342:
+      0,     // 343:
+      0,     // 344:
+      0,     // 345:
+      0,     // 346:
+      0,     // 347:
+      0,     // 348:
+      0,     // 349:
+      0,     // 350:
+      0,     // 351:
+      0,     // 352:
+      0,     // 353:
+      0,     // 354:
+      0,     // 355:
+      0,     // 356:
+      0,     // 357:
+      0,     // 358:
+      0,     // 359:
+      0,     // 360:
+      0,     // 361:
+      0,     // 362:
+      0,     // 363:
+      0,     // 364:
+      0,     // 365:
+      0,     // 366:
+      0,     // 367:
+      0,     // 368:
+      0,     // 369:
+      0,     // 370:
+      0,     // 371:
+      0,     // 372:
+      0,     // 373:
+      0,     // 374:
+      0,     // 375:
+      0,     // 376:
+      0,     // 377:
+      0,     // 378:
+      0,     // 379:
+      0,     // 380:
+      0,     // 381:
+      0,     // 382:
+      0,     // 383:
+      0,     // 384:
+      0,     // 385:
+      0,     // 386:
+      0,     // 387:
+      0,     // 388:
+      0,     // 389:
+      0,     // 390:
+      0,     // 391:
+      0,     // 392:
+      0,     // 393:
+      0,     // 394:
+      0,     // 395:
+      0,     // 396:
+      0,     // 397:
+      0,     // 398:
+      0,     // 399:
+      0,     // 400:
+      0,     // 401:
+      0,     // 402:
+      0,     // 403:
+      0,     // 404:
+      0,     // 405:
+      0,     // 406:
+      0,     // 407:
+      0,     // 408:
+      0,     // 409:
+      0,     // 410:
+      0,     // 411:
+      0,     // 412:
+      0,     // 413:
+      0,     // 414:
+      0,     // 415:
+      0,     // 416:
+      0,     // 417:
+      0,     // 418:
+      0,     // 419:
+      0,     // 420:
+      0,     // 421:
+      0,     // 422:
+      0,     // 423:
+      0,     // 424:
+      0,     // 425:
+      0,     // 426:
+      0,     // 427:
+      0,     // 428:
+      0,     // 429:
+      0,     // 430:
+      0,     // 431:
+      0,     // 432:
+      0,     // 433:
+      0,     // 434:
+      0,     // 435:
+      0,     // 436:
+      0,     // 437:
+      0,     // 438:
+      0,     // 439:
+      0,     // 440:
+      0,     // 441:
+      0,     // 442:
+      0,     // 443:
+      0,     // 444:
+      0,     // 445:
+      0,     // 446:
+      0,     // 447:
+      0,     // 448:
+      0,     // 449:
+      0,     // 450:
+      0,     // 451:
+      0,     // 452:
+      0,     // 453:
+      0,     // 454:
+      0,     // 455:
+      0,     // 456:
+      0,     // 457:
+      0,     // 458:
+      0,     // 459:
+      0,     // 460:
+      0,     // 461:
+      0,     // 462:
+      0,     // 463:
+      0,     // 464:
+      0,     // 465:
+      0,     // 466:
+      0,     // 467:
+      0,     // 468:
+      0,     // 469:
+      0,     // 470:
+      0,     // 471:
+      0,     // 472:
+      0,     // 473:
+      0,     // 474:
+      0,     // 475:
+      0,     // 476:
+      0,     // 477:
+      0,     // 478:
+      0,     // 479:
+      0,     // 480:
+      0,     // 481:
+      0,     // 482:
+      0,     // 483:
+      0,     // 484:
+      0,     // 485:
+      0,     // 486:
+      0,     // 487:
+      0,     // 488:
+      0,     // 489:
+      0,     // 490:
+      0,     // 491:
+      0,     // 492:
+      0,     // 493:
+      0,     // 494:
+      0,     // 495:
+      0,     // 496:
+      0,     // 497:
+      0,     // 498:
+      0,     // 499:
+      0,     // 500:
+      0,     // 501:
+      0,     // 502:
+      0,     // 503:
+      0,     // 504:
+      0,     // 505:
+      0,     // 506:
+      0,     // 507:
+      0,     // 508:
+      0,     // 509:
+      0,     // 510:
+      0,     // 511:
+      3583,  // 512: sys_rt_sigaction
+      3657,  // 513: sys_rt_sigreturn
+      1945,  // 514: sys_ioctl
+      3385,  // 515: sys_readv
+      5649,  // 516: sys_writev
+      3415,  // 517: sys_recvfrom
+      4127,  // 518: sys_sendmsg
+      3441,  // 519: sys_recvmsg
+      699,   // 520: sys_execve
+      3231,  // 521: sys_ptrace
+      3600,  // 522: sys_rt_sigpending
+      3692,  // 523: sys_rt_sigtimedwait
+      3637,  // 524: sys_rt_sigqueueinfo
+      4716,  // 525: sys_sigaltstack
+      5151,  // 526: sys_timer_create
+      2526,  // 527: sys_mq_notify
+      2042,  // 528: sys_kexec_load
+      5616,  // 529: sys_waitid
+      4168,  // 530: sys_set_robust_list
+      1232,  // 531: sys_get_robust_list
+      5581,  // 532: sys_vmsplice
+      2472,  // 533: sys_move_pages
+      3118,  // 534: sys_preadv
+      3267,  // 535: sys_pwritev
+      3712,  // 536: sys_rt_tgsigqueueinfo
+      3428,  // 537: sys_recvmmsg
+      4114,  // 538: sys_sendmmsg
+      3155,  // 539: sys_process_vm_readv
+      3176,  // 540: sys_process_vm_writev
+      4565,  // 541: sys_setsockopt
+      1662,  // 542: sys_getsockopt
+      1918,  // 543: sys_io_setup
+      1931,  // 544: sys_io_submit
+      710,   // 545: sys_execveat
+      3129,  // 546: sys_preadv2
+      3279,  // 547: sys_pwritev2
+  };
+};
+
+}  // namespace perfetto
+#endif  // SRC_KERNEL_UTILS_SYSCALL_TABLE_GENERATED_H_
diff --git a/src/kernel_utils/syscall_table_unittest.cc b/src/kernel_utils/syscall_table_unittest.cc
new file mode 100644
index 0000000..30390f3
--- /dev/null
+++ b/src/kernel_utils/syscall_table_unittest.cc
@@ -0,0 +1,109 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "src/kernel_utils/syscall_table.h"
+
+#include "test/gtest_and_gmock.h"
+
+namespace perfetto {
+namespace {
+
+TEST(SyscallTableTest, Aarch64) {
+  SyscallTable t(Architecture::kAarch64);
+  EXPECT_STREQ(t.GetById(0), "sys_io_setup");
+  EXPECT_EQ(t.GetByName("sys_io_setup"), 0u);
+
+  EXPECT_STREQ(t.GetById(1), "sys_io_destroy");
+  EXPECT_EQ(t.GetByName("sys_io_destroy"), 1u);
+
+  EXPECT_STREQ(t.GetById(220), "sys_clone");
+  EXPECT_EQ(t.GetByName("sys_clone"), 220u);
+
+  EXPECT_STREQ(t.GetById(293), "sys_rseq");
+  EXPECT_EQ(t.GetByName("sys_rseq"), 293u);
+
+  EXPECT_STREQ(t.GetById(294), nullptr);
+  EXPECT_STREQ(t.GetById(kMaxSyscalls), nullptr);
+
+  EXPECT_EQ(t.GetByName("sys_non_existent"), std::nullopt);
+}
+
+TEST(SyscallTableTest, ArmEabi) {
+  SyscallTable t(Architecture::kArmEabi);
+  EXPECT_STREQ(t.GetById(0), "sys_restart_syscall");
+  EXPECT_EQ(t.GetByName("sys_restart_syscall"), 0u);
+
+  EXPECT_STREQ(t.GetById(1), "sys_exit");
+  EXPECT_EQ(t.GetByName("sys_exit"), 1u);
+
+  EXPECT_STREQ(t.GetById(190), "sys_vfork");
+  EXPECT_EQ(t.GetByName("sys_vfork"), 190u);
+
+  EXPECT_STREQ(t.GetById(399), "sys_io_pgetevents");
+  EXPECT_EQ(t.GetByName("sys_io_pgetevents"), 399u);
+
+  EXPECT_STREQ(t.GetById(400), nullptr);
+  EXPECT_STREQ(t.GetById(kMaxSyscalls), nullptr);
+
+  EXPECT_EQ(t.GetByName("sys_non_existent"), std::nullopt);
+}
+
+TEST(SyscallTableTest, X86_64) {
+  SyscallTable t(Architecture::kX86_64);
+  EXPECT_STREQ(t.GetById(0), "sys_read");
+  EXPECT_EQ(t.GetByName("sys_read"), 0u);
+
+  EXPECT_STREQ(t.GetById(1), "sys_write");
+  EXPECT_EQ(t.GetByName("sys_write"), 1u);
+
+  EXPECT_STREQ(t.GetById(58), "sys_vfork");
+  EXPECT_EQ(t.GetByName("sys_vfork"), 58u);
+
+  // sys_pwritev2 shows up in two slots, 328 and 547 (which is really
+  // compat_sys_pwritev64v2). Ensure we can lookup both.
+  EXPECT_STREQ(t.GetById(547), "sys_pwritev2");
+  EXPECT_STREQ(t.GetById(328), "sys_pwritev2");
+  EXPECT_EQ(t.GetByName("sys_pwritev2"), 328u);
+
+  EXPECT_STREQ(t.GetById(335), "");
+  EXPECT_STREQ(t.GetById(511), "");
+
+  EXPECT_STREQ(t.GetById(548), nullptr);
+  EXPECT_STREQ(t.GetById(kMaxSyscalls), nullptr);
+  EXPECT_EQ(t.GetByName("sys_non_existent"), std::nullopt);
+}
+
+TEST(SyscallTableTest, X86) {
+  SyscallTable t(Architecture::kX86);
+  EXPECT_STREQ(t.GetById(0), "sys_restart_syscall");
+  EXPECT_EQ(t.GetByName("sys_restart_syscall"), 0u);
+
+  EXPECT_STREQ(t.GetById(1), "sys_exit");
+  EXPECT_EQ(t.GetByName("sys_exit"), 1u);
+
+  EXPECT_STREQ(t.GetById(190), "sys_vfork");
+  EXPECT_EQ(t.GetByName("sys_vfork"), 190u);
+
+  EXPECT_STREQ(t.GetById(386), "sys_rseq");
+  EXPECT_EQ(t.GetByName("sys_rseq"), 386);
+
+  EXPECT_STREQ(t.GetById(387), nullptr);
+  EXPECT_STREQ(t.GetById(kMaxSyscalls), nullptr);
+  EXPECT_EQ(t.GetByName("sys_non_existent"), std::nullopt);
+}
+
+}  // namespace
+}  // namespace perfetto
diff --git a/src/kernel_utils/syscalls_aarch32.h b/src/kernel_utils/syscalls_aarch32.h
deleted file mode 100644
index e1bb6b3..0000000
--- a/src/kernel_utils/syscalls_aarch32.h
+++ /dev/null
@@ -1,427 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef SRC_KERNEL_UTILS_SYSCALLS_AARCH32_H_
-#define SRC_KERNEL_UTILS_SYSCALLS_AARCH32_H_
-
-namespace perfetto {
-
-// See tools/extract_linux_syscall_tables .
-constexpr const char* kSyscalls_Aarch32[] = {
-    "sys_restart_syscall",         // 0
-    "sys_exit",                    // 1
-    "sys_fork",                    // 2
-    "sys_read",                    // 3
-    "sys_write",                   // 4
-    "sys_open",                    // 5
-    "sys_close",                   // 6
-    "",                            // 7
-    "sys_creat",                   // 8
-    "sys_link",                    // 9
-    "sys_unlink",                  // 10
-    "sys_execve",                  // 11
-    "sys_chdir",                   // 12
-    "",                            // 13
-    "sys_mknod",                   // 14
-    "sys_chmod",                   // 15
-    "sys_lchown",                  // 16
-    "",                            // 17
-    "",                            // 18
-    "sys_lseek",                   // 19
-    "sys_getpid",                  // 20
-    "sys_mount",                   // 21
-    "",                            // 22
-    "sys_setuid",                  // 23
-    "sys_getuid",                  // 24
-    "",                            // 25
-    "sys_ptrace",                  // 26
-    "",                            // 27
-    "",                            // 28
-    "sys_pause",                   // 29
-    "",                            // 30
-    "",                            // 31
-    "",                            // 32
-    "sys_access",                  // 33
-    "sys_nice",                    // 34
-    "",                            // 35
-    "sys_sync",                    // 36
-    "sys_kill",                    // 37
-    "sys_rename",                  // 38
-    "sys_mkdir",                   // 39
-    "sys_rmdir",                   // 40
-    "sys_dup",                     // 41
-    "sys_pipe",                    // 42
-    "sys_times",                   // 43
-    "",                            // 44
-    "sys_brk",                     // 45
-    "sys_setgid",                  // 46
-    "sys_getgid",                  // 47
-    "",                            // 48
-    "sys_geteuid",                 // 49
-    "sys_getegid",                 // 50
-    "sys_acct",                    // 51
-    "sys_umount2",                 // 52
-    "",                            // 53
-    "sys_ioctl",                   // 54
-    "sys_fcntl",                   // 55
-    "",                            // 56
-    "sys_setpgid",                 // 57
-    "",                            // 58
-    "",                            // 59
-    "sys_umask",                   // 60
-    "sys_chroot",                  // 61
-    "sys_ustat",                   // 62
-    "sys_dup2",                    // 63
-    "sys_getppid",                 // 64
-    "sys_getpgrp",                 // 65
-    "sys_setsid",                  // 66
-    "sys_sigaction",               // 67
-    "",                            // 68
-    "",                            // 69
-    "sys_setreuid",                // 70
-    "sys_setregid",                // 71
-    "sys_sigsuspend",              // 72
-    "sys_sigpending",              // 73
-    "sys_sethostname",             // 74
-    "sys_setrlimit",               // 75
-    "",                            // 76
-    "sys_getrusage",               // 77
-    "sys_gettimeofday",            // 78
-    "sys_settimeofday",            // 79
-    "sys_getgroups",               // 80
-    "sys_setgroups",               // 81
-    "",                            // 82
-    "sys_symlink",                 // 83
-    "",                            // 84
-    "sys_readlink",                // 85
-    "sys_uselib",                  // 86
-    "sys_swapon",                  // 87
-    "sys_reboot",                  // 88
-    "",                            // 89
-    "",                            // 90
-    "sys_munmap",                  // 91
-    "sys_truncate",                // 92
-    "sys_ftruncate",               // 93
-    "sys_fchmod",                  // 94
-    "sys_fchown",                  // 95
-    "sys_getpriority",             // 96
-    "sys_setpriority",             // 97
-    "",                            // 98
-    "sys_statfs",                  // 99
-    "sys_fstatfs",                 // 100
-    "",                            // 101
-    "",                            // 102
-    "sys_syslog",                  // 103
-    "sys_setitimer",               // 104
-    "sys_getitimer",               // 105
-    "sys_stat",                    // 106
-    "sys_lstat",                   // 107
-    "sys_fstat",                   // 108
-    "",                            // 109
-    "",                            // 110
-    "sys_vhangup",                 // 111
-    "",                            // 112
-    "",                            // 113
-    "sys_wait4",                   // 114
-    "sys_swapoff",                 // 115
-    "sys_sysinfo",                 // 116
-    "",                            // 117
-    "sys_fsync",                   // 118
-    "sys_sigreturn",               // 119
-    "sys_clone",                   // 120
-    "sys_setdomainname",           // 121
-    "sys_uname",                   // 122
-    "",                            // 123
-    "sys_adjtimex",                // 124
-    "sys_mprotect",                // 125
-    "sys_sigprocmask",             // 126
-    "",                            // 127
-    "sys_init_module",             // 128
-    "sys_delete_module",           // 129
-    "",                            // 130
-    "sys_quotactl",                // 131
-    "sys_getpgid",                 // 132
-    "sys_fchdir",                  // 133
-    "sys_bdflush",                 // 134
-    "sys_sysfs",                   // 135
-    "sys_personality",             // 136
-    "",                            // 137
-    "sys_setfsuid",                // 138
-    "sys_setfsgid",                // 139
-    "sys__llseek",                 // 140
-    "sys_getdents",                // 141
-    "sys__newselect",              // 142
-    "sys_flock",                   // 143
-    "sys_msync",                   // 144
-    "sys_readv",                   // 145
-    "sys_writev",                  // 146
-    "sys_getsid",                  // 147
-    "sys_fdatasync",               // 148
-    "sys__sysctl",                 // 149
-    "sys_mlock",                   // 150
-    "sys_munlock",                 // 151
-    "sys_mlockall",                // 152
-    "sys_munlockall",              // 153
-    "sys_sched_setparam",          // 154
-    "sys_sched_getparam",          // 155
-    "sys_sched_setscheduler",      // 156
-    "sys_sched_getscheduler",      // 157
-    "sys_sched_yield",             // 158
-    "sys_sched_get_priority_max",  // 159
-    "sys_sched_get_priority_min",  // 160
-    "sys_sched_rr_get_interval",   // 161
-    "sys_nanosleep",               // 162
-    "sys_mremap",                  // 163
-    "sys_setresuid",               // 164
-    "sys_getresuid",               // 165
-    "",                            // 166
-    "",                            // 167
-    "sys_poll",                    // 168
-    "sys_nfsservctl",              // 169
-    "sys_setresgid",               // 170
-    "sys_getresgid",               // 171
-    "sys_prctl",                   // 172
-    "sys_rt_sigreturn",            // 173
-    "sys_rt_sigaction",            // 174
-    "sys_rt_sigprocmask",          // 175
-    "sys_rt_sigpending",           // 176
-    "sys_rt_sigtimedwait",         // 177
-    "sys_rt_sigqueueinfo",         // 178
-    "sys_rt_sigsuspend",           // 179
-    "sys_pread64",                 // 180
-    "sys_pwrite64",                // 181
-    "sys_chown",                   // 182
-    "sys_getcwd",                  // 183
-    "sys_capget",                  // 184
-    "sys_capset",                  // 185
-    "sys_sigaltstack",             // 186
-    "sys_sendfile",                // 187
-    "",                            // 188
-    "",                            // 189
-    "sys_vfork",                   // 190
-    "",                            // 191
-    "sys_mmap2",                   // 192
-    "sys_truncate64",              // 193
-    "sys_ftruncate64",             // 194
-    "sys_stat64",                  // 195
-    "sys_lstat64",                 // 196
-    "sys_fstat64",                 // 197
-    "sys_lchown32",                // 198
-    "sys_getuid32",                // 199
-    "sys_getgid32",                // 200
-    "sys_geteuid32",               // 201
-    "sys_getegid32",               // 202
-    "sys_setreuid32",              // 203
-    "sys_setregid32",              // 204
-    "sys_getgroups32",             // 205
-    "sys_setgroups32",             // 206
-    "sys_fchown32",                // 207
-    "sys_setresuid32",             // 208
-    "sys_getresuid32",             // 209
-    "sys_setresgid32",             // 210
-    "sys_getresgid32",             // 211
-    "sys_chown32",                 // 212
-    "sys_setuid32",                // 213
-    "sys_setgid32",                // 214
-    "sys_setfsuid32",              // 215
-    "sys_setfsgid32",              // 216
-    "sys_getdents64",              // 217
-    "sys_pivot_root",              // 218
-    "sys_mincore",                 // 219
-    "sys_madvise",                 // 220
-    "sys_fcntl64",                 // 221
-    "",                            // 222
-    "",                            // 223
-    "sys_gettid",                  // 224
-    "sys_readahead",               // 225
-    "sys_setxattr",                // 226
-    "sys_lsetxattr",               // 227
-    "sys_fsetxattr",               // 228
-    "sys_getxattr",                // 229
-    "sys_lgetxattr",               // 230
-    "sys_fgetxattr",               // 231
-    "sys_listxattr",               // 232
-    "sys_llistxattr",              // 233
-    "sys_flistxattr",              // 234
-    "sys_removexattr",             // 235
-    "sys_lremovexattr",            // 236
-    "sys_fremovexattr",            // 237
-    "sys_tkill",                   // 238
-    "sys_sendfile64",              // 239
-    "sys_futex",                   // 240
-    "sys_sched_setaffinity",       // 241
-    "sys_sched_getaffinity",       // 242
-    "sys_io_setup",                // 243
-    "sys_io_destroy",              // 244
-    "sys_io_getevents",            // 245
-    "sys_io_submit",               // 246
-    "sys_io_cancel",               // 247
-    "sys_exit_group",              // 248
-    "sys_lookup_dcookie",          // 249
-    "sys_epoll_create",            // 250
-    "sys_epoll_ctl",               // 251
-    "sys_epoll_wait",              // 252
-    "sys_remap_file_pages",        // 253
-    "",                            // 254
-    "",                            // 255
-    "sys_set_tid_address",         // 256
-    "sys_timer_create",            // 257
-    "sys_timer_settime",           // 258
-    "sys_timer_gettime",           // 259
-    "sys_timer_getoverrun",        // 260
-    "sys_timer_delete",            // 261
-    "sys_clock_settime",           // 262
-    "sys_clock_gettime",           // 263
-    "sys_clock_getres",            // 264
-    "sys_clock_nanosleep",         // 265
-    "sys_statfs64",                // 266
-    "sys_fstatfs64",               // 267
-    "sys_tgkill",                  // 268
-    "sys_utimes",                  // 269
-    "sys_arm_fadvise64_64",        // 270
-    "sys_pciconfig_iobase",        // 271
-    "sys_pciconfig_read",          // 272
-    "sys_pciconfig_write",         // 273
-    "sys_mq_open",                 // 274
-    "sys_mq_unlink",               // 275
-    "sys_mq_timedsend",            // 276
-    "sys_mq_timedreceive",         // 277
-    "sys_mq_notify",               // 278
-    "sys_mq_getsetattr",           // 279
-    "sys_waitid",                  // 280
-    "sys_socket",                  // 281
-    "sys_bind",                    // 282
-    "sys_connect",                 // 283
-    "sys_listen",                  // 284
-    "sys_accept",                  // 285
-    "sys_getsockname",             // 286
-    "sys_getpeername",             // 287
-    "sys_socketpair",              // 288
-    "sys_send",                    // 289
-    "sys_sendto",                  // 290
-    "sys_recv",                    // 291
-    "sys_recvfrom",                // 292
-    "sys_shutdown",                // 293
-    "sys_setsockopt",              // 294
-    "sys_getsockopt",              // 295
-    "sys_sendmsg",                 // 296
-    "sys_recvmsg",                 // 297
-    "sys_semop",                   // 298
-    "sys_semget",                  // 299
-    "sys_semctl",                  // 300
-    "sys_msgsnd",                  // 301
-    "sys_msgrcv",                  // 302
-    "sys_msgget",                  // 303
-    "sys_msgctl",                  // 304
-    "sys_shmat",                   // 305
-    "sys_shmdt",                   // 306
-    "sys_shmget",                  // 307
-    "sys_shmctl",                  // 308
-    "sys_add_key",                 // 309
-    "sys_request_key",             // 310
-    "sys_keyctl",                  // 311
-    "sys_semtimedop",              // 312
-    "sys_vserver",                 // 313
-    "sys_ioprio_set",              // 314
-    "sys_ioprio_get",              // 315
-    "sys_inotify_init",            // 316
-    "sys_inotify_add_watch",       // 317
-    "sys_inotify_rm_watch",        // 318
-    "sys_mbind",                   // 319
-    "sys_get_mempolicy",           // 320
-    "sys_set_mempolicy",           // 321
-    "sys_openat",                  // 322
-    "sys_mkdirat",                 // 323
-    "sys_mknodat",                 // 324
-    "sys_fchownat",                // 325
-    "sys_futimesat",               // 326
-    "sys_fstatat64",               // 327
-    "sys_unlinkat",                // 328
-    "sys_renameat",                // 329
-    "sys_linkat",                  // 330
-    "sys_symlinkat",               // 331
-    "sys_readlinkat",              // 332
-    "sys_fchmodat",                // 333
-    "sys_faccessat",               // 334
-    "sys_pselect6",                // 335
-    "sys_ppoll",                   // 336
-    "sys_unshare",                 // 337
-    "sys_set_robust_list",         // 338
-    "sys_get_robust_list",         // 339
-    "sys_splice",                  // 340
-    "sys_sync_file_range2",        // 341
-    "sys_tee",                     // 342
-    "sys_vmsplice",                // 343
-    "sys_move_pages",              // 344
-    "sys_getcpu",                  // 345
-    "sys_epoll_pwait",             // 346
-    "sys_kexec_load",              // 347
-    "sys_utimensat",               // 348
-    "sys_signalfd",                // 349
-    "sys_timerfd_create",          // 350
-    "sys_eventfd",                 // 351
-    "sys_fallocate",               // 352
-    "sys_timerfd_settime",         // 353
-    "sys_timerfd_gettime",         // 354
-    "sys_signalfd4",               // 355
-    "sys_eventfd2",                // 356
-    "sys_epoll_create1",           // 357
-    "sys_dup3",                    // 358
-    "sys_pipe2",                   // 359
-    "sys_inotify_init1",           // 360
-    "sys_preadv",                  // 361
-    "sys_pwritev",                 // 362
-    "sys_rt_tgsigqueueinfo",       // 363
-    "sys_perf_event_open",         // 364
-    "sys_recvmmsg",                // 365
-    "sys_accept4",                 // 366
-    "sys_fanotify_init",           // 367
-    "sys_fanotify_mark",           // 368
-    "sys_prlimit64",               // 369
-    "sys_name_to_handle_at",       // 370
-    "sys_open_by_handle_at",       // 371
-    "sys_clock_adjtime",           // 372
-    "sys_syncfs",                  // 373
-    "sys_sendmmsg",                // 374
-    "sys_setns",                   // 375
-    "sys_process_vm_readv",        // 376
-    "sys_process_vm_writev",       // 377
-    "sys_kcmp",                    // 378
-    "sys_finit_module",            // 379
-    "sys_sched_setattr",           // 380
-    "sys_sched_getattr",           // 381
-    "sys_renameat2",               // 382
-    "sys_seccomp",                 // 383
-    "sys_getrandom",               // 384
-    "sys_memfd_create",            // 385
-    "sys_bpf",                     // 386
-    "sys_execveat",                // 387
-    "sys_userfaultfd",             // 388
-    "sys_membarrier",              // 389
-    "sys_mlock2",                  // 390
-    "sys_copy_file_range",         // 391
-    "sys_preadv2",                 // 392
-    "sys_pwritev2",                // 393
-    "sys_pkey_mprotect",           // 394
-    "sys_pkey_alloc",              // 395
-    "sys_pkey_free",               // 396
-    "sys_statx",                   // 397
-    "sys_rseq",                    // 398
-};
-
-}  // namespace perfetto
-
-#endif  // SRC_KERNEL_UTILS_SYSCALLS_AARCH32_H_
diff --git a/src/kernel_utils/syscalls_aarch64.h b/src/kernel_utils/syscalls_aarch64.h
deleted file mode 100644
index 8a95e89..0000000
--- a/src/kernel_utils/syscalls_aarch64.h
+++ /dev/null
@@ -1,322 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef SRC_KERNEL_UTILS_SYSCALLS_AARCH64_H_
-#define SRC_KERNEL_UTILS_SYSCALLS_AARCH64_H_
-
-namespace perfetto {
-
-// See tools/extract_linux_syscall_tables .
-constexpr const char* kSyscalls_Aarch64[] = {
-    "sys_io_setup",                // 0
-    "sys_io_destroy",              // 1
-    "sys_io_submit",               // 2
-    "sys_io_cancel",               // 3
-    "sys_io_getevents",            // 4
-    "sys_setxattr",                // 5
-    "sys_lsetxattr",               // 6
-    "sys_fsetxattr",               // 7
-    "sys_getxattr",                // 8
-    "sys_lgetxattr",               // 9
-    "sys_fgetxattr",               // 10
-    "sys_listxattr",               // 11
-    "sys_llistxattr",              // 12
-    "sys_flistxattr",              // 13
-    "sys_removexattr",             // 14
-    "sys_lremovexattr",            // 15
-    "sys_fremovexattr",            // 16
-    "sys_getcwd",                  // 17
-    "sys_lookup_dcookie",          // 18
-    "sys_eventfd2",                // 19
-    "sys_epoll_create1",           // 20
-    "sys_epoll_ctl",               // 21
-    "sys_epoll_pwait",             // 22
-    "sys_dup",                     // 23
-    "sys_dup3",                    // 24
-    "sys_fcntl",                   // 25
-    "sys_inotify_init1",           // 26
-    "sys_inotify_add_watch",       // 27
-    "sys_inotify_rm_watch",        // 28
-    "sys_ioctl",                   // 29
-    "sys_ioprio_set",              // 30
-    "sys_ioprio_get",              // 31
-    "sys_flock",                   // 32
-    "sys_mknodat",                 // 33
-    "sys_mkdirat",                 // 34
-    "sys_unlinkat",                // 35
-    "sys_symlinkat",               // 36
-    "sys_linkat",                  // 37
-    "sys_renameat",                // 38
-    "sys_umount2",                 // 39
-    "sys_mount",                   // 40
-    "sys_pivot_root",              // 41
-    "sys_nfsservctl",              // 42
-    "sys_statfs",                  // 43
-    "sys_fstatfs",                 // 44
-    "sys_truncate",                // 45
-    "sys_ftruncate",               // 46
-    "sys_fallocate",               // 47
-    "sys_faccessat",               // 48
-    "sys_chdir",                   // 49
-    "sys_fchdir",                  // 50
-    "sys_chroot",                  // 51
-    "sys_fchmod",                  // 52
-    "sys_fchmodat",                // 53
-    "sys_fchownat",                // 54
-    "sys_fchown",                  // 55
-    "sys_openat",                  // 56
-    "sys_close",                   // 57
-    "sys_vhangup",                 // 58
-    "sys_pipe2",                   // 59
-    "sys_quotactl",                // 60
-    "sys_getdents64",              // 61
-    "sys_lseek",                   // 62
-    "sys_read",                    // 63
-    "sys_write",                   // 64
-    "sys_readv",                   // 65
-    "sys_writev",                  // 66
-    "sys_pread64",                 // 67
-    "sys_pwrite64",                // 68
-    "sys_preadv",                  // 69
-    "sys_pwritev",                 // 70
-    "sys_sendfile",                // 71
-    "sys_pselect6",                // 72
-    "sys_ppoll",                   // 73
-    "sys_signalfd4",               // 74
-    "sys_vmsplice",                // 75
-    "sys_splice",                  // 76
-    "sys_tee",                     // 77
-    "sys_readlinkat",              // 78
-    "sys_fstatat",                 // 79
-    "sys_fstat",                   // 80
-    "sys_sync",                    // 81
-    "sys_fsync",                   // 82
-    "sys_fdatasync",               // 83
-    "sys_sync_file_range",         // 84
-    "sys_timerfd_create",          // 85
-    "sys_timerfd_settime",         // 86
-    "sys_timerfd_gettime",         // 87
-    "sys_utimensat",               // 88
-    "sys_acct",                    // 89
-    "sys_capget",                  // 90
-    "sys_capset",                  // 91
-    "sys_personality",             // 92
-    "sys_exit",                    // 93
-    "sys_exit_group",              // 94
-    "sys_waitid",                  // 95
-    "sys_set_tid_address",         // 96
-    "sys_unshare",                 // 97
-    "sys_futex",                   // 98
-    "sys_set_robust_list",         // 99
-    "sys_get_robust_list",         // 100
-    "sys_nanosleep",               // 101
-    "sys_getitimer",               // 102
-    "sys_setitimer",               // 103
-    "sys_kexec_load",              // 104
-    "sys_init_module",             // 105
-    "sys_delete_module",           // 106
-    "sys_timer_create",            // 107
-    "sys_timer_gettime",           // 108
-    "sys_timer_getoverrun",        // 109
-    "sys_timer_settime",           // 110
-    "sys_timer_delete",            // 111
-    "sys_clock_settime",           // 112
-    "sys_clock_gettime",           // 113
-    "sys_clock_getres",            // 114
-    "sys_clock_nanosleep",         // 115
-    "sys_syslog",                  // 116
-    "sys_ptrace",                  // 117
-    "sys_sched_setparam",          // 118
-    "sys_sched_setscheduler",      // 119
-    "sys_sched_getscheduler",      // 120
-    "sys_sched_getparam",          // 121
-    "sys_sched_setaffinity",       // 122
-    "sys_sched_getaffinity",       // 123
-    "sys_sched_yield",             // 124
-    "sys_sched_get_priority_max",  // 125
-    "sys_sched_get_priority_min",  // 126
-    "sys_sched_rr_get_interval",   // 127
-    "sys_restart_syscall",         // 128
-    "sys_kill",                    // 129
-    "sys_tkill",                   // 130
-    "sys_tgkill",                  // 131
-    "sys_sigaltstack",             // 132
-    "sys_rt_sigsuspend",           // 133
-    "sys_rt_sigaction",            // 134
-    "sys_rt_sigprocmask",          // 135
-    "sys_rt_sigpending",           // 136
-    "sys_rt_sigtimedwait",         // 137
-    "sys_rt_sigqueueinfo",         // 138
-    "sys_rt_sigreturn",            // 139
-    "sys_setpriority",             // 140
-    "sys_getpriority",             // 141
-    "sys_reboot",                  // 142
-    "sys_setregid",                // 143
-    "sys_setgid",                  // 144
-    "sys_setreuid",                // 145
-    "sys_setuid",                  // 146
-    "sys_setresuid",               // 147
-    "sys_getresuid",               // 148
-    "sys_setresgid",               // 149
-    "sys_getresgid",               // 150
-    "sys_setfsuid",                // 151
-    "sys_setfsgid",                // 152
-    "sys_times",                   // 153
-    "sys_setpgid",                 // 154
-    "sys_getpgid",                 // 155
-    "sys_getsid",                  // 156
-    "sys_setsid",                  // 157
-    "sys_getgroups",               // 158
-    "sys_setgroups",               // 159
-    "sys_uname",                   // 160
-    "sys_sethostname",             // 161
-    "sys_setdomainname",           // 162
-    "sys_getrlimit",               // 163
-    "sys_setrlimit",               // 164
-    "sys_getrusage",               // 165
-    "sys_umask",                   // 166
-    "sys_prctl",                   // 167
-    "sys_getcpu",                  // 168
-    "sys_gettimeofday",            // 169
-    "sys_settimeofday",            // 170
-    "sys_adjtimex",                // 171
-    "sys_getpid",                  // 172
-    "sys_getppid",                 // 173
-    "sys_getuid",                  // 174
-    "sys_geteuid",                 // 175
-    "sys_getgid",                  // 176
-    "sys_getegid",                 // 177
-    "sys_gettid",                  // 178
-    "sys_sysinfo",                 // 179
-    "sys_mq_open",                 // 180
-    "sys_mq_unlink",               // 181
-    "sys_mq_timedsend",            // 182
-    "sys_mq_timedreceive",         // 183
-    "sys_mq_notify",               // 184
-    "sys_mq_getsetattr",           // 185
-    "sys_msgget",                  // 186
-    "sys_msgctl",                  // 187
-    "sys_msgrcv",                  // 188
-    "sys_msgsnd",                  // 189
-    "sys_semget",                  // 190
-    "sys_semctl",                  // 191
-    "sys_semtimedop",              // 192
-    "sys_semop",                   // 193
-    "sys_shmget",                  // 194
-    "sys_shmctl",                  // 195
-    "sys_shmat",                   // 196
-    "sys_shmdt",                   // 197
-    "sys_socket",                  // 198
-    "sys_socketpair",              // 199
-    "sys_bind",                    // 200
-    "sys_listen",                  // 201
-    "sys_accept",                  // 202
-    "sys_connect",                 // 203
-    "sys_getsockname",             // 204
-    "sys_getpeername",             // 205
-    "sys_sendto",                  // 206
-    "sys_recvfrom",                // 207
-    "sys_setsockopt",              // 208
-    "sys_getsockopt",              // 209
-    "sys_shutdown",                // 210
-    "sys_sendmsg",                 // 211
-    "sys_recvmsg",                 // 212
-    "sys_readahead",               // 213
-    "sys_brk",                     // 214
-    "sys_munmap",                  // 215
-    "sys_mremap",                  // 216
-    "sys_add_key",                 // 217
-    "sys_request_key",             // 218
-    "sys_keyctl",                  // 219
-    "sys_clone",                   // 220
-    "sys_execve",                  // 221
-    "sys_mmap",                    // 222
-    "sys_fadvise64",               // 223
-    "sys_swapon",                  // 224
-    "sys_swapoff",                 // 225
-    "sys_mprotect",                // 226
-    "sys_msync",                   // 227
-    "sys_mlock",                   // 228
-    "sys_munlock",                 // 229
-    "sys_mlockall",                // 230
-    "sys_munlockall",              // 231
-    "sys_mincore",                 // 232
-    "sys_madvise",                 // 233
-    "sys_remap_file_pages",        // 234
-    "sys_mbind",                   // 235
-    "sys_get_mempolicy",           // 236
-    "sys_set_mempolicy",           // 237
-    "sys_migrate_pages",           // 238
-    "sys_move_pages",              // 239
-    "sys_rt_tgsigqueueinfo",       // 240
-    "sys_perf_event_open",         // 241
-    "sys_accept4",                 // 242
-    "sys_recvmmsg",                // 243
-    "sys_arch_specific_syscall",   // 244
-    "",                            // 245
-    "",                            // 246
-    "",                            // 247
-    "",                            // 248
-    "",                            // 249
-    "",                            // 250
-    "",                            // 251
-    "",                            // 252
-    "",                            // 253
-    "",                            // 254
-    "",                            // 255
-    "",                            // 256
-    "",                            // 257
-    "",                            // 258
-    "",                            // 259
-    "sys_wait4",                   // 260
-    "sys_prlimit64",               // 261
-    "sys_fanotify_init",           // 262
-    "sys_fanotify_mark",           // 263
-    "sys_name_to_handle_at",       // 264
-    "sys_open_by_handle_at",       // 265
-    "sys_clock_adjtime",           // 266
-    "sys_syncfs",                  // 267
-    "sys_setns",                   // 268
-    "sys_sendmmsg",                // 269
-    "sys_process_vm_readv",        // 270
-    "sys_process_vm_writev",       // 271
-    "sys_kcmp",                    // 272
-    "sys_finit_module",            // 273
-    "sys_sched_setattr",           // 274
-    "sys_sched_getattr",           // 275
-    "sys_renameat2",               // 276
-    "sys_seccomp",                 // 277
-    "sys_getrandom",               // 278
-    "sys_memfd_create",            // 279
-    "sys_bpf",                     // 280
-    "sys_execveat",                // 281
-    "sys_userfaultfd",             // 282
-    "sys_membarrier",              // 283
-    "sys_mlock2",                  // 284
-    "sys_copy_file_range",         // 285
-    "sys_preadv2",                 // 286
-    "sys_pwritev2",                // 287
-    "sys_pkey_mprotect",           // 288
-    "sys_pkey_alloc",              // 289
-    "sys_pkey_free",               // 290
-    "sys_statx",                   // 291
-    "sys_io_pgetevents",           // 292
-    "sys_rseq",                    // 293
-};
-
-}  // namespace perfetto
-
-#endif  // SRC_KERNEL_UTILS_SYSCALLS_AARCH64_H_
diff --git a/src/kernel_utils/syscalls_armeabi.h b/src/kernel_utils/syscalls_armeabi.h
deleted file mode 100644
index 22b3e8c..0000000
--- a/src/kernel_utils/syscalls_armeabi.h
+++ /dev/null
@@ -1,428 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef SRC_KERNEL_UTILS_SYSCALLS_ARMEABI_H_
-#define SRC_KERNEL_UTILS_SYSCALLS_ARMEABI_H_
-
-namespace perfetto {
-
-// See tools/extract_linux_syscall_tables .
-constexpr const char* kSyscalls_ArmEabi[] = {
-    "sys_restart_syscall",         // 0
-    "sys_exit",                    // 1
-    "sys_fork",                    // 2
-    "sys_read",                    // 3
-    "sys_write",                   // 4
-    "sys_open",                    // 5
-    "sys_close",                   // 6
-    "",                            // 7
-    "sys_creat",                   // 8
-    "sys_link",                    // 9
-    "sys_unlink",                  // 10
-    "sys_execve",                  // 11
-    "sys_chdir",                   // 12
-    "sys_time",                    // 13
-    "sys_mknod",                   // 14
-    "sys_chmod",                   // 15
-    "sys_lchown",                  // 16
-    "",                            // 17
-    "",                            // 18
-    "sys_lseek",                   // 19
-    "sys_getpid",                  // 20
-    "sys_mount",                   // 21
-    "sys_umount",                  // 22
-    "sys_setuid",                  // 23
-    "sys_getuid",                  // 24
-    "sys_stime",                   // 25
-    "sys_ptrace",                  // 26
-    "sys_alarm",                   // 27
-    "",                            // 28
-    "sys_pause",                   // 29
-    "sys_utime",                   // 30
-    "",                            // 31
-    "",                            // 32
-    "sys_access",                  // 33
-    "sys_nice",                    // 34
-    "",                            // 35
-    "sys_sync",                    // 36
-    "sys_kill",                    // 37
-    "sys_rename",                  // 38
-    "sys_mkdir",                   // 39
-    "sys_rmdir",                   // 40
-    "sys_dup",                     // 41
-    "sys_pipe",                    // 42
-    "sys_times",                   // 43
-    "",                            // 44
-    "sys_brk",                     // 45
-    "sys_setgid",                  // 46
-    "sys_getgid",                  // 47
-    "",                            // 48
-    "sys_geteuid",                 // 49
-    "sys_getegid",                 // 50
-    "sys_acct",                    // 51
-    "sys_umount2",                 // 52
-    "",                            // 53
-    "sys_ioctl",                   // 54
-    "sys_fcntl",                   // 55
-    "",                            // 56
-    "sys_setpgid",                 // 57
-    "",                            // 58
-    "",                            // 59
-    "sys_umask",                   // 60
-    "sys_chroot",                  // 61
-    "sys_ustat",                   // 62
-    "sys_dup2",                    // 63
-    "sys_getppid",                 // 64
-    "sys_getpgrp",                 // 65
-    "sys_setsid",                  // 66
-    "sys_sigaction",               // 67
-    "",                            // 68
-    "",                            // 69
-    "sys_setreuid",                // 70
-    "sys_setregid",                // 71
-    "sys_sigsuspend",              // 72
-    "sys_sigpending",              // 73
-    "sys_sethostname",             // 74
-    "sys_setrlimit",               // 75
-    "sys_getrlimit",               // 76
-    "sys_getrusage",               // 77
-    "sys_gettimeofday",            // 78
-    "sys_settimeofday",            // 79
-    "sys_getgroups",               // 80
-    "sys_setgroups",               // 81
-    "sys_select",                  // 82
-    "sys_symlink",                 // 83
-    "",                            // 84
-    "sys_readlink",                // 85
-    "sys_uselib",                  // 86
-    "sys_swapon",                  // 87
-    "sys_reboot",                  // 88
-    "sys_readdir",                 // 89
-    "sys_mmap",                    // 90
-    "sys_munmap",                  // 91
-    "sys_truncate",                // 92
-    "sys_ftruncate",               // 93
-    "sys_fchmod",                  // 94
-    "sys_fchown",                  // 95
-    "sys_getpriority",             // 96
-    "sys_setpriority",             // 97
-    "",                            // 98
-    "sys_statfs",                  // 99
-    "sys_fstatfs",                 // 100
-    "",                            // 101
-    "sys_socketcall",              // 102
-    "sys_syslog",                  // 103
-    "sys_setitimer",               // 104
-    "sys_getitimer",               // 105
-    "sys_stat",                    // 106
-    "sys_lstat",                   // 107
-    "sys_fstat",                   // 108
-    "",                            // 109
-    "",                            // 110
-    "sys_vhangup",                 // 111
-    "",                            // 112
-    "sys_syscall",                 // 113
-    "sys_wait4",                   // 114
-    "sys_swapoff",                 // 115
-    "sys_sysinfo",                 // 116
-    "sys_ipc",                     // 117
-    "sys_fsync",                   // 118
-    "sys_sigreturn",               // 119
-    "sys_clone",                   // 120
-    "sys_setdomainname",           // 121
-    "sys_uname",                   // 122
-    "",                            // 123
-    "sys_adjtimex",                // 124
-    "sys_mprotect",                // 125
-    "sys_sigprocmask",             // 126
-    "",                            // 127
-    "sys_init_module",             // 128
-    "sys_delete_module",           // 129
-    "",                            // 130
-    "sys_quotactl",                // 131
-    "sys_getpgid",                 // 132
-    "sys_fchdir",                  // 133
-    "sys_bdflush",                 // 134
-    "sys_sysfs",                   // 135
-    "sys_personality",             // 136
-    "",                            // 137
-    "sys_setfsuid",                // 138
-    "sys_setfsgid",                // 139
-    "sys__llseek",                 // 140
-    "sys_getdents",                // 141
-    "sys__newselect",              // 142
-    "sys_flock",                   // 143
-    "sys_msync",                   // 144
-    "sys_readv",                   // 145
-    "sys_writev",                  // 146
-    "sys_getsid",                  // 147
-    "sys_fdatasync",               // 148
-    "sys__sysctl",                 // 149
-    "sys_mlock",                   // 150
-    "sys_munlock",                 // 151
-    "sys_mlockall",                // 152
-    "sys_munlockall",              // 153
-    "sys_sched_setparam",          // 154
-    "sys_sched_getparam",          // 155
-    "sys_sched_setscheduler",      // 156
-    "sys_sched_getscheduler",      // 157
-    "sys_sched_yield",             // 158
-    "sys_sched_get_priority_max",  // 159
-    "sys_sched_get_priority_min",  // 160
-    "sys_sched_rr_get_interval",   // 161
-    "sys_nanosleep",               // 162
-    "sys_mremap",                  // 163
-    "sys_setresuid",               // 164
-    "sys_getresuid",               // 165
-    "",                            // 166
-    "",                            // 167
-    "sys_poll",                    // 168
-    "sys_nfsservctl",              // 169
-    "sys_setresgid",               // 170
-    "sys_getresgid",               // 171
-    "sys_prctl",                   // 172
-    "sys_rt_sigreturn",            // 173
-    "sys_rt_sigaction",            // 174
-    "sys_rt_sigprocmask",          // 175
-    "sys_rt_sigpending",           // 176
-    "sys_rt_sigtimedwait",         // 177
-    "sys_rt_sigqueueinfo",         // 178
-    "sys_rt_sigsuspend",           // 179
-    "sys_pread64",                 // 180
-    "sys_pwrite64",                // 181
-    "sys_chown",                   // 182
-    "sys_getcwd",                  // 183
-    "sys_capget",                  // 184
-    "sys_capset",                  // 185
-    "sys_sigaltstack",             // 186
-    "sys_sendfile",                // 187
-    "",                            // 188
-    "",                            // 189
-    "sys_vfork",                   // 190
-    "sys_ugetrlimit",              // 191
-    "sys_mmap2",                   // 192
-    "sys_truncate64",              // 193
-    "sys_ftruncate64",             // 194
-    "sys_stat64",                  // 195
-    "sys_lstat64",                 // 196
-    "sys_fstat64",                 // 197
-    "sys_lchown32",                // 198
-    "sys_getuid32",                // 199
-    "sys_getgid32",                // 200
-    "sys_geteuid32",               // 201
-    "sys_getegid32",               // 202
-    "sys_setreuid32",              // 203
-    "sys_setregid32",              // 204
-    "sys_getgroups32",             // 205
-    "sys_setgroups32",             // 206
-    "sys_fchown32",                // 207
-    "sys_setresuid32",             // 208
-    "sys_getresuid32",             // 209
-    "sys_setresgid32",             // 210
-    "sys_getresgid32",             // 211
-    "sys_chown32",                 // 212
-    "sys_setuid32",                // 213
-    "sys_setgid32",                // 214
-    "sys_setfsuid32",              // 215
-    "sys_setfsgid32",              // 216
-    "sys_getdents64",              // 217
-    "sys_pivot_root",              // 218
-    "sys_mincore",                 // 219
-    "sys_madvise",                 // 220
-    "sys_fcntl64",                 // 221
-    "",                            // 222
-    "",                            // 223
-    "sys_gettid",                  // 224
-    "sys_readahead",               // 225
-    "sys_setxattr",                // 226
-    "sys_lsetxattr",               // 227
-    "sys_fsetxattr",               // 228
-    "sys_getxattr",                // 229
-    "sys_lgetxattr",               // 230
-    "sys_fgetxattr",               // 231
-    "sys_listxattr",               // 232
-    "sys_llistxattr",              // 233
-    "sys_flistxattr",              // 234
-    "sys_removexattr",             // 235
-    "sys_lremovexattr",            // 236
-    "sys_fremovexattr",            // 237
-    "sys_tkill",                   // 238
-    "sys_sendfile64",              // 239
-    "sys_futex",                   // 240
-    "sys_sched_setaffinity",       // 241
-    "sys_sched_getaffinity",       // 242
-    "sys_io_setup",                // 243
-    "sys_io_destroy",              // 244
-    "sys_io_getevents",            // 245
-    "sys_io_submit",               // 246
-    "sys_io_cancel",               // 247
-    "sys_exit_group",              // 248
-    "sys_lookup_dcookie",          // 249
-    "sys_epoll_create",            // 250
-    "sys_epoll_ctl",               // 251
-    "sys_epoll_wait",              // 252
-    "sys_remap_file_pages",        // 253
-    "",                            // 254
-    "",                            // 255
-    "sys_set_tid_address",         // 256
-    "sys_timer_create",            // 257
-    "sys_timer_settime",           // 258
-    "sys_timer_gettime",           // 259
-    "sys_timer_getoverrun",        // 260
-    "sys_timer_delete",            // 261
-    "sys_clock_settime",           // 262
-    "sys_clock_gettime",           // 263
-    "sys_clock_getres",            // 264
-    "sys_clock_nanosleep",         // 265
-    "sys_statfs64",                // 266
-    "sys_fstatfs64",               // 267
-    "sys_tgkill",                  // 268
-    "sys_utimes",                  // 269
-    "sys_arm_fadvise64_64",        // 270
-    "sys_pciconfig_iobase",        // 271
-    "sys_pciconfig_read",          // 272
-    "sys_pciconfig_write",         // 273
-    "sys_mq_open",                 // 274
-    "sys_mq_unlink",               // 275
-    "sys_mq_timedsend",            // 276
-    "sys_mq_timedreceive",         // 277
-    "sys_mq_notify",               // 278
-    "sys_mq_getsetattr",           // 279
-    "sys_waitid",                  // 280
-    "sys_socket",                  // 281
-    "sys_bind",                    // 282
-    "sys_connect",                 // 283
-    "sys_listen",                  // 284
-    "sys_accept",                  // 285
-    "sys_getsockname",             // 286
-    "sys_getpeername",             // 287
-    "sys_socketpair",              // 288
-    "sys_send",                    // 289
-    "sys_sendto",                  // 290
-    "sys_recv",                    // 291
-    "sys_recvfrom",                // 292
-    "sys_shutdown",                // 293
-    "sys_setsockopt",              // 294
-    "sys_getsockopt",              // 295
-    "sys_sendmsg",                 // 296
-    "sys_recvmsg",                 // 297
-    "sys_semop",                   // 298
-    "sys_semget",                  // 299
-    "sys_semctl",                  // 300
-    "sys_msgsnd",                  // 301
-    "sys_msgrcv",                  // 302
-    "sys_msgget",                  // 303
-    "sys_msgctl",                  // 304
-    "sys_shmat",                   // 305
-    "sys_shmdt",                   // 306
-    "sys_shmget",                  // 307
-    "sys_shmctl",                  // 308
-    "sys_add_key",                 // 309
-    "sys_request_key",             // 310
-    "sys_keyctl",                  // 311
-    "sys_semtimedop",              // 312
-    "sys_vserver",                 // 313
-    "sys_ioprio_set",              // 314
-    "sys_ioprio_get",              // 315
-    "sys_inotify_init",            // 316
-    "sys_inotify_add_watch",       // 317
-    "sys_inotify_rm_watch",        // 318
-    "sys_mbind",                   // 319
-    "sys_get_mempolicy",           // 320
-    "sys_set_mempolicy",           // 321
-    "sys_openat",                  // 322
-    "sys_mkdirat",                 // 323
-    "sys_mknodat",                 // 324
-    "sys_fchownat",                // 325
-    "sys_futimesat",               // 326
-    "sys_fstatat64",               // 327
-    "sys_unlinkat",                // 328
-    "sys_renameat",                // 329
-    "sys_linkat",                  // 330
-    "sys_symlinkat",               // 331
-    "sys_readlinkat",              // 332
-    "sys_fchmodat",                // 333
-    "sys_faccessat",               // 334
-    "sys_pselect6",                // 335
-    "sys_ppoll",                   // 336
-    "sys_unshare",                 // 337
-    "sys_set_robust_list",         // 338
-    "sys_get_robust_list",         // 339
-    "sys_splice",                  // 340
-    "sys_arm_sync_file_range",     // 341
-    "sys_tee",                     // 342
-    "sys_vmsplice",                // 343
-    "sys_move_pages",              // 344
-    "sys_getcpu",                  // 345
-    "sys_epoll_pwait",             // 346
-    "sys_kexec_load",              // 347
-    "sys_utimensat",               // 348
-    "sys_signalfd",                // 349
-    "sys_timerfd_create",          // 350
-    "sys_eventfd",                 // 351
-    "sys_fallocate",               // 352
-    "sys_timerfd_settime",         // 353
-    "sys_timerfd_gettime",         // 354
-    "sys_signalfd4",               // 355
-    "sys_eventfd2",                // 356
-    "sys_epoll_create1",           // 357
-    "sys_dup3",                    // 358
-    "sys_pipe2",                   // 359
-    "sys_inotify_init1",           // 360
-    "sys_preadv",                  // 361
-    "sys_pwritev",                 // 362
-    "sys_rt_tgsigqueueinfo",       // 363
-    "sys_perf_event_open",         // 364
-    "sys_recvmmsg",                // 365
-    "sys_accept4",                 // 366
-    "sys_fanotify_init",           // 367
-    "sys_fanotify_mark",           // 368
-    "sys_prlimit64",               // 369
-    "sys_name_to_handle_at",       // 370
-    "sys_open_by_handle_at",       // 371
-    "sys_clock_adjtime",           // 372
-    "sys_syncfs",                  // 373
-    "sys_sendmmsg",                // 374
-    "sys_setns",                   // 375
-    "sys_process_vm_readv",        // 376
-    "sys_process_vm_writev",       // 377
-    "sys_kcmp",                    // 378
-    "sys_finit_module",            // 379
-    "sys_sched_setattr",           // 380
-    "sys_sched_getattr",           // 381
-    "sys_renameat2",               // 382
-    "sys_seccomp",                 // 383
-    "sys_getrandom",               // 384
-    "sys_memfd_create",            // 385
-    "sys_bpf",                     // 386
-    "sys_execveat",                // 387
-    "sys_userfaultfd",             // 388
-    "sys_membarrier",              // 389
-    "sys_mlock2",                  // 390
-    "sys_copy_file_range",         // 391
-    "sys_preadv2",                 // 392
-    "sys_pwritev2",                // 393
-    "sys_pkey_mprotect",           // 394
-    "sys_pkey_alloc",              // 395
-    "sys_pkey_free",               // 396
-    "sys_statx",                   // 397
-    "sys_rseq",                    // 398
-    "sys_io_pgetevents",           // 399
-};
-
-}  // namespace perfetto
-
-#endif  // SRC_KERNEL_UTILS_SYSCALLS_ARMEABI_H_
diff --git a/src/kernel_utils/syscalls_x86.h b/src/kernel_utils/syscalls_x86.h
deleted file mode 100644
index b89a5da..0000000
--- a/src/kernel_utils/syscalls_x86.h
+++ /dev/null
@@ -1,415 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef SRC_KERNEL_UTILS_SYSCALLS_X86_H_
-#define SRC_KERNEL_UTILS_SYSCALLS_X86_H_
-
-namespace perfetto {
-
-// See tools/extract_linux_syscall_tables .
-constexpr const char* kSyscalls_x86[] = {
-    "sys_restart_syscall",         // 0
-    "sys_exit",                    // 1
-    "sys_fork",                    // 2
-    "sys_read",                    // 3
-    "sys_write",                   // 4
-    "sys_open",                    // 5
-    "sys_close",                   // 6
-    "sys_waitpid",                 // 7
-    "sys_creat",                   // 8
-    "sys_link",                    // 9
-    "sys_unlink",                  // 10
-    "sys_execve",                  // 11
-    "sys_chdir",                   // 12
-    "sys_time",                    // 13
-    "sys_mknod",                   // 14
-    "sys_chmod",                   // 15
-    "sys_lchown",                  // 16
-    "sys_break",                   // 17
-    "sys_oldstat",                 // 18
-    "sys_lseek",                   // 19
-    "sys_getpid",                  // 20
-    "sys_mount",                   // 21
-    "sys_umount",                  // 22
-    "sys_setuid",                  // 23
-    "sys_getuid",                  // 24
-    "sys_stime",                   // 25
-    "sys_ptrace",                  // 26
-    "sys_alarm",                   // 27
-    "sys_oldfstat",                // 28
-    "sys_pause",                   // 29
-    "sys_utime",                   // 30
-    "sys_stty",                    // 31
-    "sys_gtty",                    // 32
-    "sys_access",                  // 33
-    "sys_nice",                    // 34
-    "sys_ftime",                   // 35
-    "sys_sync",                    // 36
-    "sys_kill",                    // 37
-    "sys_rename",                  // 38
-    "sys_mkdir",                   // 39
-    "sys_rmdir",                   // 40
-    "sys_dup",                     // 41
-    "sys_pipe",                    // 42
-    "sys_times",                   // 43
-    "sys_prof",                    // 44
-    "sys_brk",                     // 45
-    "sys_setgid",                  // 46
-    "sys_getgid",                  // 47
-    "sys_signal",                  // 48
-    "sys_geteuid",                 // 49
-    "sys_getegid",                 // 50
-    "sys_acct",                    // 51
-    "sys_umount2",                 // 52
-    "sys_lock",                    // 53
-    "sys_ioctl",                   // 54
-    "sys_fcntl",                   // 55
-    "sys_mpx",                     // 56
-    "sys_setpgid",                 // 57
-    "sys_ulimit",                  // 58
-    "sys_oldolduname",             // 59
-    "sys_umask",                   // 60
-    "sys_chroot",                  // 61
-    "sys_ustat",                   // 62
-    "sys_dup2",                    // 63
-    "sys_getppid",                 // 64
-    "sys_getpgrp",                 // 65
-    "sys_setsid",                  // 66
-    "sys_sigaction",               // 67
-    "sys_sgetmask",                // 68
-    "sys_ssetmask",                // 69
-    "sys_setreuid",                // 70
-    "sys_setregid",                // 71
-    "sys_sigsuspend",              // 72
-    "sys_sigpending",              // 73
-    "sys_sethostname",             // 74
-    "sys_setrlimit",               // 75
-    "sys_getrlimit",               // 76
-    "sys_getrusage",               // 77
-    "sys_gettimeofday",            // 78
-    "sys_settimeofday",            // 79
-    "sys_getgroups",               // 80
-    "sys_setgroups",               // 81
-    "sys_select",                  // 82
-    "sys_symlink",                 // 83
-    "sys_oldlstat",                // 84
-    "sys_readlink",                // 85
-    "sys_uselib",                  // 86
-    "sys_swapon",                  // 87
-    "sys_reboot",                  // 88
-    "sys_readdir",                 // 89
-    "sys_mmap",                    // 90
-    "sys_munmap",                  // 91
-    "sys_truncate",                // 92
-    "sys_ftruncate",               // 93
-    "sys_fchmod",                  // 94
-    "sys_fchown",                  // 95
-    "sys_getpriority",             // 96
-    "sys_setpriority",             // 97
-    "sys_profil",                  // 98
-    "sys_statfs",                  // 99
-    "sys_fstatfs",                 // 100
-    "sys_ioperm",                  // 101
-    "sys_socketcall",              // 102
-    "sys_syslog",                  // 103
-    "sys_setitimer",               // 104
-    "sys_getitimer",               // 105
-    "sys_stat",                    // 106
-    "sys_lstat",                   // 107
-    "sys_fstat",                   // 108
-    "sys_olduname",                // 109
-    "sys_iopl",                    // 110
-    "sys_vhangup",                 // 111
-    "sys_idle",                    // 112
-    "sys_vm86old",                 // 113
-    "sys_wait4",                   // 114
-    "sys_swapoff",                 // 115
-    "sys_sysinfo",                 // 116
-    "sys_ipc",                     // 117
-    "sys_fsync",                   // 118
-    "sys_sigreturn",               // 119
-    "sys_clone",                   // 120
-    "sys_setdomainname",           // 121
-    "sys_uname",                   // 122
-    "sys_modify_ldt",              // 123
-    "sys_adjtimex",                // 124
-    "sys_mprotect",                // 125
-    "sys_sigprocmask",             // 126
-    "sys_create_module",           // 127
-    "sys_init_module",             // 128
-    "sys_delete_module",           // 129
-    "sys_get_kernel_syms",         // 130
-    "sys_quotactl",                // 131
-    "sys_getpgid",                 // 132
-    "sys_fchdir",                  // 133
-    "sys_bdflush",                 // 134
-    "sys_sysfs",                   // 135
-    "sys_personality",             // 136
-    "sys_afs_syscall",             // 137
-    "sys_setfsuid",                // 138
-    "sys_setfsgid",                // 139
-    "sys__llseek",                 // 140
-    "sys_getdents",                // 141
-    "sys__newselect",              // 142
-    "sys_flock",                   // 143
-    "sys_msync",                   // 144
-    "sys_readv",                   // 145
-    "sys_writev",                  // 146
-    "sys_getsid",                  // 147
-    "sys_fdatasync",               // 148
-    "sys__sysctl",                 // 149
-    "sys_mlock",                   // 150
-    "sys_munlock",                 // 151
-    "sys_mlockall",                // 152
-    "sys_munlockall",              // 153
-    "sys_sched_setparam",          // 154
-    "sys_sched_getparam",          // 155
-    "sys_sched_setscheduler",      // 156
-    "sys_sched_getscheduler",      // 157
-    "sys_sched_yield",             // 158
-    "sys_sched_get_priority_max",  // 159
-    "sys_sched_get_priority_min",  // 160
-    "sys_sched_rr_get_interval",   // 161
-    "sys_nanosleep",               // 162
-    "sys_mremap",                  // 163
-    "sys_setresuid",               // 164
-    "sys_getresuid",               // 165
-    "sys_vm86",                    // 166
-    "sys_query_module",            // 167
-    "sys_poll",                    // 168
-    "sys_nfsservctl",              // 169
-    "sys_setresgid",               // 170
-    "sys_getresgid",               // 171
-    "sys_prctl",                   // 172
-    "sys_rt_sigreturn",            // 173
-    "sys_rt_sigaction",            // 174
-    "sys_rt_sigprocmask",          // 175
-    "sys_rt_sigpending",           // 176
-    "sys_rt_sigtimedwait",         // 177
-    "sys_rt_sigqueueinfo",         // 178
-    "sys_rt_sigsuspend",           // 179
-    "sys_pread64",                 // 180
-    "sys_pwrite64",                // 181
-    "sys_chown",                   // 182
-    "sys_getcwd",                  // 183
-    "sys_capget",                  // 184
-    "sys_capset",                  // 185
-    "sys_sigaltstack",             // 186
-    "sys_sendfile",                // 187
-    "sys_getpmsg",                 // 188
-    "sys_putpmsg",                 // 189
-    "sys_vfork",                   // 190
-    "sys_ugetrlimit",              // 191
-    "sys_mmap2",                   // 192
-    "sys_truncate64",              // 193
-    "sys_ftruncate64",             // 194
-    "sys_stat64",                  // 195
-    "sys_lstat64",                 // 196
-    "sys_fstat64",                 // 197
-    "sys_lchown32",                // 198
-    "sys_getuid32",                // 199
-    "sys_getgid32",                // 200
-    "sys_geteuid32",               // 201
-    "sys_getegid32",               // 202
-    "sys_setreuid32",              // 203
-    "sys_setregid32",              // 204
-    "sys_getgroups32",             // 205
-    "sys_setgroups32",             // 206
-    "sys_fchown32",                // 207
-    "sys_setresuid32",             // 208
-    "sys_getresuid32",             // 209
-    "sys_setresgid32",             // 210
-    "sys_getresgid32",             // 211
-    "sys_chown32",                 // 212
-    "sys_setuid32",                // 213
-    "sys_setgid32",                // 214
-    "sys_setfsuid32",              // 215
-    "sys_setfsgid32",              // 216
-    "sys_pivot_root",              // 217
-    "sys_mincore",                 // 218
-    "sys_madvise",                 // 219
-    "sys_getdents64",              // 220
-    "sys_fcntl64",                 // 221
-    "",                            // 222
-    "",                            // 223
-    "sys_gettid",                  // 224
-    "sys_readahead",               // 225
-    "sys_setxattr",                // 226
-    "sys_lsetxattr",               // 227
-    "sys_fsetxattr",               // 228
-    "sys_getxattr",                // 229
-    "sys_lgetxattr",               // 230
-    "sys_fgetxattr",               // 231
-    "sys_listxattr",               // 232
-    "sys_llistxattr",              // 233
-    "sys_flistxattr",              // 234
-    "sys_removexattr",             // 235
-    "sys_lremovexattr",            // 236
-    "sys_fremovexattr",            // 237
-    "sys_tkill",                   // 238
-    "sys_sendfile64",              // 239
-    "sys_futex",                   // 240
-    "sys_sched_setaffinity",       // 241
-    "sys_sched_getaffinity",       // 242
-    "sys_set_thread_area",         // 243
-    "sys_get_thread_area",         // 244
-    "sys_io_setup",                // 245
-    "sys_io_destroy",              // 246
-    "sys_io_getevents",            // 247
-    "sys_io_submit",               // 248
-    "sys_io_cancel",               // 249
-    "sys_fadvise64",               // 250
-    "",                            // 251
-    "sys_exit_group",              // 252
-    "sys_lookup_dcookie",          // 253
-    "sys_epoll_create",            // 254
-    "sys_epoll_ctl",               // 255
-    "sys_epoll_wait",              // 256
-    "sys_remap_file_pages",        // 257
-    "sys_set_tid_address",         // 258
-    "sys_timer_create",            // 259
-    "sys_timer_settime",           // 260
-    "sys_timer_gettime",           // 261
-    "sys_timer_getoverrun",        // 262
-    "sys_timer_delete",            // 263
-    "sys_clock_settime",           // 264
-    "sys_clock_gettime",           // 265
-    "sys_clock_getres",            // 266
-    "sys_clock_nanosleep",         // 267
-    "sys_statfs64",                // 268
-    "sys_fstatfs64",               // 269
-    "sys_tgkill",                  // 270
-    "sys_utimes",                  // 271
-    "sys_fadvise64_64",            // 272
-    "sys_vserver",                 // 273
-    "sys_mbind",                   // 274
-    "sys_get_mempolicy",           // 275
-    "sys_set_mempolicy",           // 276
-    "sys_mq_open",                 // 277
-    "sys_mq_unlink",               // 278
-    "sys_mq_timedsend",            // 279
-    "sys_mq_timedreceive",         // 280
-    "sys_mq_notify",               // 281
-    "sys_mq_getsetattr",           // 282
-    "sys_kexec_load",              // 283
-    "sys_waitid",                  // 284
-    "",                            // 285
-    "sys_add_key",                 // 286
-    "sys_request_key",             // 287
-    "sys_keyctl",                  // 288
-    "sys_ioprio_set",              // 289
-    "sys_ioprio_get",              // 290
-    "sys_inotify_init",            // 291
-    "sys_inotify_add_watch",       // 292
-    "sys_inotify_rm_watch",        // 293
-    "sys_migrate_pages",           // 294
-    "sys_openat",                  // 295
-    "sys_mkdirat",                 // 296
-    "sys_mknodat",                 // 297
-    "sys_fchownat",                // 298
-    "sys_futimesat",               // 299
-    "sys_fstatat64",               // 300
-    "sys_unlinkat",                // 301
-    "sys_renameat",                // 302
-    "sys_linkat",                  // 303
-    "sys_symlinkat",               // 304
-    "sys_readlinkat",              // 305
-    "sys_fchmodat",                // 306
-    "sys_faccessat",               // 307
-    "sys_pselect6",                // 308
-    "sys_ppoll",                   // 309
-    "sys_unshare",                 // 310
-    "sys_set_robust_list",         // 311
-    "sys_get_robust_list",         // 312
-    "sys_splice",                  // 313
-    "sys_sync_file_range",         // 314
-    "sys_tee",                     // 315
-    "sys_vmsplice",                // 316
-    "sys_move_pages",              // 317
-    "sys_getcpu",                  // 318
-    "sys_epoll_pwait",             // 319
-    "sys_utimensat",               // 320
-    "sys_signalfd",                // 321
-    "sys_timerfd_create",          // 322
-    "sys_eventfd",                 // 323
-    "sys_fallocate",               // 324
-    "sys_timerfd_settime",         // 325
-    "sys_timerfd_gettime",         // 326
-    "sys_signalfd4",               // 327
-    "sys_eventfd2",                // 328
-    "sys_epoll_create1",           // 329
-    "sys_dup3",                    // 330
-    "sys_pipe2",                   // 331
-    "sys_inotify_init1",           // 332
-    "sys_preadv",                  // 333
-    "sys_pwritev",                 // 334
-    "sys_rt_tgsigqueueinfo",       // 335
-    "sys_perf_event_open",         // 336
-    "sys_recvmmsg",                // 337
-    "sys_fanotify_init",           // 338
-    "sys_fanotify_mark",           // 339
-    "sys_prlimit64",               // 340
-    "sys_name_to_handle_at",       // 341
-    "sys_open_by_handle_at",       // 342
-    "sys_clock_adjtime",           // 343
-    "sys_syncfs",                  // 344
-    "sys_sendmmsg",                // 345
-    "sys_setns",                   // 346
-    "sys_process_vm_readv",        // 347
-    "sys_process_vm_writev",       // 348
-    "sys_kcmp",                    // 349
-    "sys_finit_module",            // 350
-    "sys_sched_setattr",           // 351
-    "sys_sched_getattr",           // 352
-    "sys_renameat2",               // 353
-    "sys_seccomp",                 // 354
-    "sys_getrandom",               // 355
-    "sys_memfd_create",            // 356
-    "sys_bpf",                     // 357
-    "sys_execveat",                // 358
-    "sys_socket",                  // 359
-    "sys_socketpair",              // 360
-    "sys_bind",                    // 361
-    "sys_connect",                 // 362
-    "sys_listen",                  // 363
-    "sys_accept4",                 // 364
-    "sys_getsockopt",              // 365
-    "sys_setsockopt",              // 366
-    "sys_getsockname",             // 367
-    "sys_getpeername",             // 368
-    "sys_sendto",                  // 369
-    "sys_sendmsg",                 // 370
-    "sys_recvfrom",                // 371
-    "sys_recvmsg",                 // 372
-    "sys_shutdown",                // 373
-    "sys_userfaultfd",             // 374
-    "sys_membarrier",              // 375
-    "sys_mlock2",                  // 376
-    "sys_copy_file_range",         // 377
-    "sys_preadv2",                 // 378
-    "sys_pwritev2",                // 379
-    "sys_pkey_mprotect",           // 380
-    "sys_pkey_alloc",              // 381
-    "sys_pkey_free",               // 382
-    "sys_statx",                   // 383
-    "sys_arch_prctl",              // 384
-    "sys_io_pgetevents",           // 385
-    "sys_rseq",                    // 386
-};
-
-}  // namespace perfetto
-
-#endif  // SRC_KERNEL_UTILS_SYSCALLS_X86_H_
diff --git a/src/kernel_utils/syscalls_x86_64.h b/src/kernel_utils/syscalls_x86_64.h
deleted file mode 100644
index 19fd5dc..0000000
--- a/src/kernel_utils/syscalls_x86_64.h
+++ /dev/null
@@ -1,576 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef SRC_KERNEL_UTILS_SYSCALLS_X86_64_H_
-#define SRC_KERNEL_UTILS_SYSCALLS_X86_64_H_
-
-namespace perfetto {
-
-// See tools/extract_linux_syscall_tables .
-constexpr const char* kSyscalls_x86_64[] = {
-    "sys_read",                    // 0
-    "sys_write",                   // 1
-    "sys_open",                    // 2
-    "sys_close",                   // 3
-    "sys_stat",                    // 4
-    "sys_fstat",                   // 5
-    "sys_lstat",                   // 6
-    "sys_poll",                    // 7
-    "sys_lseek",                   // 8
-    "sys_mmap",                    // 9
-    "sys_mprotect",                // 10
-    "sys_munmap",                  // 11
-    "sys_brk",                     // 12
-    "sys_rt_sigaction",            // 13
-    "sys_rt_sigprocmask",          // 14
-    "sys_rt_sigreturn",            // 15
-    "sys_ioctl",                   // 16
-    "sys_pread64",                 // 17
-    "sys_pwrite64",                // 18
-    "sys_readv",                   // 19
-    "sys_writev",                  // 20
-    "sys_access",                  // 21
-    "sys_pipe",                    // 22
-    "sys_select",                  // 23
-    "sys_sched_yield",             // 24
-    "sys_mremap",                  // 25
-    "sys_msync",                   // 26
-    "sys_mincore",                 // 27
-    "sys_madvise",                 // 28
-    "sys_shmget",                  // 29
-    "sys_shmat",                   // 30
-    "sys_shmctl",                  // 31
-    "sys_dup",                     // 32
-    "sys_dup2",                    // 33
-    "sys_pause",                   // 34
-    "sys_nanosleep",               // 35
-    "sys_getitimer",               // 36
-    "sys_alarm",                   // 37
-    "sys_setitimer",               // 38
-    "sys_getpid",                  // 39
-    "sys_sendfile",                // 40
-    "sys_socket",                  // 41
-    "sys_connect",                 // 42
-    "sys_accept",                  // 43
-    "sys_sendto",                  // 44
-    "sys_recvfrom",                // 45
-    "sys_sendmsg",                 // 46
-    "sys_recvmsg",                 // 47
-    "sys_shutdown",                // 48
-    "sys_bind",                    // 49
-    "sys_listen",                  // 50
-    "sys_getsockname",             // 51
-    "sys_getpeername",             // 52
-    "sys_socketpair",              // 53
-    "sys_setsockopt",              // 54
-    "sys_getsockopt",              // 55
-    "sys_clone",                   // 56
-    "sys_fork",                    // 57
-    "sys_vfork",                   // 58
-    "sys_execve",                  // 59
-    "sys_exit",                    // 60
-    "sys_wait4",                   // 61
-    "sys_kill",                    // 62
-    "sys_uname",                   // 63
-    "sys_semget",                  // 64
-    "sys_semop",                   // 65
-    "sys_semctl",                  // 66
-    "sys_shmdt",                   // 67
-    "sys_msgget",                  // 68
-    "sys_msgsnd",                  // 69
-    "sys_msgrcv",                  // 70
-    "sys_msgctl",                  // 71
-    "sys_fcntl",                   // 72
-    "sys_flock",                   // 73
-    "sys_fsync",                   // 74
-    "sys_fdatasync",               // 75
-    "sys_truncate",                // 76
-    "sys_ftruncate",               // 77
-    "sys_getdents",                // 78
-    "sys_getcwd",                  // 79
-    "sys_chdir",                   // 80
-    "sys_fchdir",                  // 81
-    "sys_rename",                  // 82
-    "sys_mkdir",                   // 83
-    "sys_rmdir",                   // 84
-    "sys_creat",                   // 85
-    "sys_link",                    // 86
-    "sys_unlink",                  // 87
-    "sys_symlink",                 // 88
-    "sys_readlink",                // 89
-    "sys_chmod",                   // 90
-    "sys_fchmod",                  // 91
-    "sys_chown",                   // 92
-    "sys_fchown",                  // 93
-    "sys_lchown",                  // 94
-    "sys_umask",                   // 95
-    "sys_gettimeofday",            // 96
-    "sys_getrlimit",               // 97
-    "sys_getrusage",               // 98
-    "sys_sysinfo",                 // 99
-    "sys_times",                   // 100
-    "sys_ptrace",                  // 101
-    "sys_getuid",                  // 102
-    "sys_syslog",                  // 103
-    "sys_getgid",                  // 104
-    "sys_setuid",                  // 105
-    "sys_setgid",                  // 106
-    "sys_geteuid",                 // 107
-    "sys_getegid",                 // 108
-    "sys_setpgid",                 // 109
-    "sys_getppid",                 // 110
-    "sys_getpgrp",                 // 111
-    "sys_setsid",                  // 112
-    "sys_setreuid",                // 113
-    "sys_setregid",                // 114
-    "sys_getgroups",               // 115
-    "sys_setgroups",               // 116
-    "sys_setresuid",               // 117
-    "sys_getresuid",               // 118
-    "sys_setresgid",               // 119
-    "sys_getresgid",               // 120
-    "sys_getpgid",                 // 121
-    "sys_setfsuid",                // 122
-    "sys_setfsgid",                // 123
-    "sys_getsid",                  // 124
-    "sys_capget",                  // 125
-    "sys_capset",                  // 126
-    "sys_rt_sigpending",           // 127
-    "sys_rt_sigtimedwait",         // 128
-    "sys_rt_sigqueueinfo",         // 129
-    "sys_rt_sigsuspend",           // 130
-    "sys_sigaltstack",             // 131
-    "sys_utime",                   // 132
-    "sys_mknod",                   // 133
-    "sys_uselib",                  // 134
-    "sys_personality",             // 135
-    "sys_ustat",                   // 136
-    "sys_statfs",                  // 137
-    "sys_fstatfs",                 // 138
-    "sys_sysfs",                   // 139
-    "sys_getpriority",             // 140
-    "sys_setpriority",             // 141
-    "sys_sched_setparam",          // 142
-    "sys_sched_getparam",          // 143
-    "sys_sched_setscheduler",      // 144
-    "sys_sched_getscheduler",      // 145
-    "sys_sched_get_priority_max",  // 146
-    "sys_sched_get_priority_min",  // 147
-    "sys_sched_rr_get_interval",   // 148
-    "sys_mlock",                   // 149
-    "sys_munlock",                 // 150
-    "sys_mlockall",                // 151
-    "sys_munlockall",              // 152
-    "sys_vhangup",                 // 153
-    "sys_modify_ldt",              // 154
-    "sys_pivot_root",              // 155
-    "sys__sysctl",                 // 156
-    "sys_prctl",                   // 157
-    "sys_arch_prctl",              // 158
-    "sys_adjtimex",                // 159
-    "sys_setrlimit",               // 160
-    "sys_chroot",                  // 161
-    "sys_sync",                    // 162
-    "sys_acct",                    // 163
-    "sys_settimeofday",            // 164
-    "sys_mount",                   // 165
-    "sys_umount2",                 // 166
-    "sys_swapon",                  // 167
-    "sys_swapoff",                 // 168
-    "sys_reboot",                  // 169
-    "sys_sethostname",             // 170
-    "sys_setdomainname",           // 171
-    "sys_iopl",                    // 172
-    "sys_ioperm",                  // 173
-    "sys_create_module",           // 174
-    "sys_init_module",             // 175
-    "sys_delete_module",           // 176
-    "sys_get_kernel_syms",         // 177
-    "sys_query_module",            // 178
-    "sys_quotactl",                // 179
-    "sys_nfsservctl",              // 180
-    "sys_getpmsg",                 // 181
-    "sys_putpmsg",                 // 182
-    "sys_afs_syscall",             // 183
-    "sys_tuxcall",                 // 184
-    "sys_security",                // 185
-    "sys_gettid",                  // 186
-    "sys_readahead",               // 187
-    "sys_setxattr",                // 188
-    "sys_lsetxattr",               // 189
-    "sys_fsetxattr",               // 190
-    "sys_getxattr",                // 191
-    "sys_lgetxattr",               // 192
-    "sys_fgetxattr",               // 193
-    "sys_listxattr",               // 194
-    "sys_llistxattr",              // 195
-    "sys_flistxattr",              // 196
-    "sys_removexattr",             // 197
-    "sys_lremovexattr",            // 198
-    "sys_fremovexattr",            // 199
-    "sys_tkill",                   // 200
-    "sys_time",                    // 201
-    "sys_futex",                   // 202
-    "sys_sched_setaffinity",       // 203
-    "sys_sched_getaffinity",       // 204
-    "sys_set_thread_area",         // 205
-    "sys_io_setup",                // 206
-    "sys_io_destroy",              // 207
-    "sys_io_getevents",            // 208
-    "sys_io_submit",               // 209
-    "sys_io_cancel",               // 210
-    "sys_get_thread_area",         // 211
-    "sys_lookup_dcookie",          // 212
-    "sys_epoll_create",            // 213
-    "sys_epoll_ctl_old",           // 214
-    "sys_epoll_wait_old",          // 215
-    "sys_remap_file_pages",        // 216
-    "sys_getdents64",              // 217
-    "sys_set_tid_address",         // 218
-    "sys_restart_syscall",         // 219
-    "sys_semtimedop",              // 220
-    "sys_fadvise64",               // 221
-    "sys_timer_create",            // 222
-    "sys_timer_settime",           // 223
-    "sys_timer_gettime",           // 224
-    "sys_timer_getoverrun",        // 225
-    "sys_timer_delete",            // 226
-    "sys_clock_settime",           // 227
-    "sys_clock_gettime",           // 228
-    "sys_clock_getres",            // 229
-    "sys_clock_nanosleep",         // 230
-    "sys_exit_group",              // 231
-    "sys_epoll_wait",              // 232
-    "sys_epoll_ctl",               // 233
-    "sys_tgkill",                  // 234
-    "sys_utimes",                  // 235
-    "sys_vserver",                 // 236
-    "sys_mbind",                   // 237
-    "sys_set_mempolicy",           // 238
-    "sys_get_mempolicy",           // 239
-    "sys_mq_open",                 // 240
-    "sys_mq_unlink",               // 241
-    "sys_mq_timedsend",            // 242
-    "sys_mq_timedreceive",         // 243
-    "sys_mq_notify",               // 244
-    "sys_mq_getsetattr",           // 245
-    "sys_kexec_load",              // 246
-    "sys_waitid",                  // 247
-    "sys_add_key",                 // 248
-    "sys_request_key",             // 249
-    "sys_keyctl",                  // 250
-    "sys_ioprio_set",              // 251
-    "sys_ioprio_get",              // 252
-    "sys_inotify_init",            // 253
-    "sys_inotify_add_watch",       // 254
-    "sys_inotify_rm_watch",        // 255
-    "sys_migrate_pages",           // 256
-    "sys_openat",                  // 257
-    "sys_mkdirat",                 // 258
-    "sys_mknodat",                 // 259
-    "sys_fchownat",                // 260
-    "sys_futimesat",               // 261
-    "sys_newfstatat",              // 262
-    "sys_unlinkat",                // 263
-    "sys_renameat",                // 264
-    "sys_linkat",                  // 265
-    "sys_symlinkat",               // 266
-    "sys_readlinkat",              // 267
-    "sys_fchmodat",                // 268
-    "sys_faccessat",               // 269
-    "sys_pselect6",                // 270
-    "sys_ppoll",                   // 271
-    "sys_unshare",                 // 272
-    "sys_set_robust_list",         // 273
-    "sys_get_robust_list",         // 274
-    "sys_splice",                  // 275
-    "sys_tee",                     // 276
-    "sys_sync_file_range",         // 277
-    "sys_vmsplice",                // 278
-    "sys_move_pages",              // 279
-    "sys_utimensat",               // 280
-    "sys_epoll_pwait",             // 281
-    "sys_signalfd",                // 282
-    "sys_timerfd_create",          // 283
-    "sys_eventfd",                 // 284
-    "sys_fallocate",               // 285
-    "sys_timerfd_settime",         // 286
-    "sys_timerfd_gettime",         // 287
-    "sys_accept4",                 // 288
-    "sys_signalfd4",               // 289
-    "sys_eventfd2",                // 290
-    "sys_epoll_create1",           // 291
-    "sys_dup3",                    // 292
-    "sys_pipe2",                   // 293
-    "sys_inotify_init1",           // 294
-    "sys_preadv",                  // 295
-    "sys_pwritev",                 // 296
-    "sys_rt_tgsigqueueinfo",       // 297
-    "sys_perf_event_open",         // 298
-    "sys_recvmmsg",                // 299
-    "sys_fanotify_init",           // 300
-    "sys_fanotify_mark",           // 301
-    "sys_prlimit64",               // 302
-    "sys_name_to_handle_at",       // 303
-    "sys_open_by_handle_at",       // 304
-    "sys_clock_adjtime",           // 305
-    "sys_syncfs",                  // 306
-    "sys_sendmmsg",                // 307
-    "sys_setns",                   // 308
-    "sys_getcpu",                  // 309
-    "sys_process_vm_readv",        // 310
-    "sys_process_vm_writev",       // 311
-    "sys_kcmp",                    // 312
-    "sys_finit_module",            // 313
-    "sys_sched_setattr",           // 314
-    "sys_sched_getattr",           // 315
-    "sys_renameat2",               // 316
-    "sys_seccomp",                 // 317
-    "sys_getrandom",               // 318
-    "sys_memfd_create",            // 319
-    "sys_kexec_file_load",         // 320
-    "sys_bpf",                     // 321
-    "sys_execveat",                // 322
-    "sys_userfaultfd",             // 323
-    "sys_membarrier",              // 324
-    "sys_mlock2",                  // 325
-    "sys_copy_file_range",         // 326
-    "sys_preadv2",                 // 327
-    "sys_pwritev2",                // 328
-    "sys_pkey_mprotect",           // 329
-    "sys_pkey_alloc",              // 330
-    "sys_pkey_free",               // 331
-    "sys_statx",                   // 332
-    "sys_io_pgetevents",           // 333
-    "sys_rseq",                    // 334
-    "",                            // 335
-    "",                            // 336
-    "",                            // 337
-    "",                            // 338
-    "",                            // 339
-    "",                            // 340
-    "",                            // 341
-    "",                            // 342
-    "",                            // 343
-    "",                            // 344
-    "",                            // 345
-    "",                            // 346
-    "",                            // 347
-    "",                            // 348
-    "",                            // 349
-    "",                            // 350
-    "",                            // 351
-    "",                            // 352
-    "",                            // 353
-    "",                            // 354
-    "",                            // 355
-    "",                            // 356
-    "",                            // 357
-    "",                            // 358
-    "",                            // 359
-    "",                            // 360
-    "",                            // 361
-    "",                            // 362
-    "",                            // 363
-    "",                            // 364
-    "",                            // 365
-    "",                            // 366
-    "",                            // 367
-    "",                            // 368
-    "",                            // 369
-    "",                            // 370
-    "",                            // 371
-    "",                            // 372
-    "",                            // 373
-    "",                            // 374
-    "",                            // 375
-    "",                            // 376
-    "",                            // 377
-    "",                            // 378
-    "",                            // 379
-    "",                            // 380
-    "",                            // 381
-    "",                            // 382
-    "",                            // 383
-    "",                            // 384
-    "",                            // 385
-    "",                            // 386
-    "",                            // 387
-    "",                            // 388
-    "",                            // 389
-    "",                            // 390
-    "",                            // 391
-    "",                            // 392
-    "",                            // 393
-    "",                            // 394
-    "",                            // 395
-    "",                            // 396
-    "",                            // 397
-    "",                            // 398
-    "",                            // 399
-    "",                            // 400
-    "",                            // 401
-    "",                            // 402
-    "",                            // 403
-    "",                            // 404
-    "",                            // 405
-    "",                            // 406
-    "",                            // 407
-    "",                            // 408
-    "",                            // 409
-    "",                            // 410
-    "",                            // 411
-    "",                            // 412
-    "",                            // 413
-    "",                            // 414
-    "",                            // 415
-    "",                            // 416
-    "",                            // 417
-    "",                            // 418
-    "",                            // 419
-    "",                            // 420
-    "",                            // 421
-    "",                            // 422
-    "",                            // 423
-    "",                            // 424
-    "",                            // 425
-    "",                            // 426
-    "",                            // 427
-    "",                            // 428
-    "",                            // 429
-    "",                            // 430
-    "",                            // 431
-    "",                            // 432
-    "",                            // 433
-    "",                            // 434
-    "",                            // 435
-    "",                            // 436
-    "",                            // 437
-    "",                            // 438
-    "",                            // 439
-    "",                            // 440
-    "",                            // 441
-    "",                            // 442
-    "",                            // 443
-    "",                            // 444
-    "",                            // 445
-    "",                            // 446
-    "",                            // 447
-    "",                            // 448
-    "",                            // 449
-    "",                            // 450
-    "",                            // 451
-    "",                            // 452
-    "",                            // 453
-    "",                            // 454
-    "",                            // 455
-    "",                            // 456
-    "",                            // 457
-    "",                            // 458
-    "",                            // 459
-    "",                            // 460
-    "",                            // 461
-    "",                            // 462
-    "",                            // 463
-    "",                            // 464
-    "",                            // 465
-    "",                            // 466
-    "",                            // 467
-    "",                            // 468
-    "",                            // 469
-    "",                            // 470
-    "",                            // 471
-    "",                            // 472
-    "",                            // 473
-    "",                            // 474
-    "",                            // 475
-    "",                            // 476
-    "",                            // 477
-    "",                            // 478
-    "",                            // 479
-    "",                            // 480
-    "",                            // 481
-    "",                            // 482
-    "",                            // 483
-    "",                            // 484
-    "",                            // 485
-    "",                            // 486
-    "",                            // 487
-    "",                            // 488
-    "",                            // 489
-    "",                            // 490
-    "",                            // 491
-    "",                            // 492
-    "",                            // 493
-    "",                            // 494
-    "",                            // 495
-    "",                            // 496
-    "",                            // 497
-    "",                            // 498
-    "",                            // 499
-    "",                            // 500
-    "",                            // 501
-    "",                            // 502
-    "",                            // 503
-    "",                            // 504
-    "",                            // 505
-    "",                            // 506
-    "",                            // 507
-    "",                            // 508
-    "",                            // 509
-    "",                            // 510
-    "",                            // 511
-    "sys_rt_sigaction",            // 512
-    "sys_rt_sigreturn",            // 513
-    "sys_ioctl",                   // 514
-    "sys_readv",                   // 515
-    "sys_writev",                  // 516
-    "sys_recvfrom",                // 517
-    "sys_sendmsg",                 // 518
-    "sys_recvmsg",                 // 519
-    "sys_execve",                  // 520
-    "sys_ptrace",                  // 521
-    "sys_rt_sigpending",           // 522
-    "sys_rt_sigtimedwait",         // 523
-    "sys_rt_sigqueueinfo",         // 524
-    "sys_sigaltstack",             // 525
-    "sys_timer_create",            // 526
-    "sys_mq_notify",               // 527
-    "sys_kexec_load",              // 528
-    "sys_waitid",                  // 529
-    "sys_set_robust_list",         // 530
-    "sys_get_robust_list",         // 531
-    "sys_vmsplice",                // 532
-    "sys_move_pages",              // 533
-    "sys_preadv",                  // 534
-    "sys_pwritev",                 // 535
-    "sys_rt_tgsigqueueinfo",       // 536
-    "sys_recvmmsg",                // 537
-    "sys_sendmmsg",                // 538
-    "sys_process_vm_readv",        // 539
-    "sys_process_vm_writev",       // 540
-    "sys_setsockopt",              // 541
-    "sys_getsockopt",              // 542
-    "sys_io_setup",                // 543
-    "sys_io_submit",               // 544
-    "sys_execveat",                // 545
-    "sys_preadv2",                 // 546
-    "sys_pwritev2",                // 547
-};
-
-}  // namespace perfetto
-
-#endif  // SRC_KERNEL_UTILS_SYSCALLS_X86_64_H_
diff --git a/src/perfetto_cmd/BUILD.gn b/src/perfetto_cmd/BUILD.gn
index fbb06c2..3f90a57 100644
--- a/src/perfetto_cmd/BUILD.gn
+++ b/src/perfetto_cmd/BUILD.gn
@@ -21,9 +21,8 @@
 # tracing, acting as a Consumer.
 executable("perfetto") {
   deps = [
-    "../../:libperfetto",
+    ":perfetto_cmd",
     "../../gn:default_deps",
-    "../../include/perfetto/ext/traced",
   ]
   sources = [ "main.cc" ]
 }
@@ -36,9 +35,8 @@
 # due to selinux rules.
 executable("trigger_perfetto") {
   deps = [
-    "../../:libperfetto",
+    ":trigger_perfetto_cmd",
     "../../gn:default_deps",
-    "../../include/perfetto/ext/traced",
   ]
   sources = [ "trigger_perfetto_main.cc" ]
 }
diff --git a/src/perfetto_cmd/perfetto_cmd.cc b/src/perfetto_cmd/perfetto_cmd.cc
index 01ef3d2..ac864e5 100644
--- a/src/perfetto_cmd/perfetto_cmd.cc
+++ b/src/perfetto_cmd/perfetto_cmd.cc
@@ -144,8 +144,7 @@
 }
 
 bool IsUserBuild() {
-#if PERFETTO_BUILDFLAG(PERFETTO_ANDROID_BUILD) && \
-    PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID)
+#if PERFETTO_BUILDFLAG(PERFETTO_ANDROID_BUILD)
   std::string build_type = base::GetAndroidProp("ro.build.type");
   if (build_type.empty()) {
     PERFETTO_ELOG("Unable to read ro.build.type: assuming user build");
@@ -154,8 +153,7 @@
   return build_type == "user";
 #else
   return false;
-#endif  // PERFETTO_BUILDFLAG(PERFETTO_ANDROID_BUILD) &&
-        // PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID)
+#endif  // PERFETTO_BUILDFLAG(PERFETTO_ANDROID_BUILD)
 }
 
 std::optional<PerfettoStatsdAtom> ConvertRateLimiterResponseToAtom(
diff --git a/src/perfetto_cmd/perfetto_cmd_android.cc b/src/perfetto_cmd/perfetto_cmd_android.cc
index 7957a3a..b03493f 100644
--- a/src/perfetto_cmd/perfetto_cmd_android.cc
+++ b/src/perfetto_cmd/perfetto_cmd_android.cc
@@ -14,11 +14,6 @@
  * limitations under the License.
  */
 
-
-#include "perfetto/base/build_config.h"
-
-#if PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID)
-
 #include "src/perfetto_cmd/perfetto_cmd.h"
 
 #include <sys/sendfile.h>
@@ -192,5 +187,3 @@
 }
 
 }  // namespace perfetto
-
-#endif  // PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID)
diff --git a/src/trace_processor/containers/BUILD.gn b/src/trace_processor/containers/BUILD.gn
index 4c4cb8d..08cddfc 100644
--- a/src/trace_processor/containers/BUILD.gn
+++ b/src/trace_processor/containers/BUILD.gn
@@ -24,7 +24,6 @@
     "bit_vector.h",
     "bit_vector_iterators.h",
     "null_term_string_view.h",
-    "nullable_vector.h",
     "row_map.h",
     "row_map_algorithms.h",
     "string_pool.h",
@@ -48,7 +47,6 @@
   sources = [
     "bit_vector_unittest.cc",
     "null_term_string_view_unittest.cc",
-    "nullable_vector_unittest.cc",
     "row_map_unittest.cc",
     "string_pool_unittest.cc",
   ]
@@ -71,7 +69,6 @@
     ]
     sources = [
       "bit_vector_benchmark.cc",
-      "nullable_vector_benchmark.cc",
       "row_map_algorithms_benchmark.cc",
       "row_map_benchmark.cc",
     ]
diff --git a/src/trace_processor/containers/bit_vector.h b/src/trace_processor/containers/bit_vector.h
index 243651c..541bed2 100644
--- a/src/trace_processor/containers/bit_vector.h
+++ b/src/trace_processor/containers/bit_vector.h
@@ -98,7 +98,7 @@
         return BitVector();
 
       std::vector<uint32_t> counts(BlockCount(size_));
-      PERFETTO_CHECK(skipped_blocks_ < counts.size());
+      PERFETTO_CHECK(skipped_blocks_ <= counts.size());
       for (uint32_t i = skipped_blocks_ + 1; i < counts.size(); ++i) {
         counts[i] = counts[i - 1] +
                     ConstBlock(&words_[Block::kWords * (i - 1)]).CountSetBits();
diff --git a/src/trace_processor/containers/bit_vector_unittest.cc b/src/trace_processor/containers/bit_vector_unittest.cc
index ad282dc..47a8aff 100644
--- a/src/trace_processor/containers/bit_vector_unittest.cc
+++ b/src/trace_processor/containers/bit_vector_unittest.cc
@@ -545,6 +545,14 @@
   ASSERT_TRUE(bv.IsSet(127));
 }
 
+TEST(BitVectorUnittest, BuilderSkipAll) {
+  BitVector::Builder builder(128, 128);
+  BitVector bv = std::move(builder).Build();
+
+  ASSERT_EQ(bv.size(), 128u);
+  ASSERT_EQ(bv.CountSetBits(), 0u);
+}
+
 TEST(BitVectorUnittest, BuilderBitsInCompleteWordsUntilFull) {
   BitVector::Builder builder(128 + 1);
 
diff --git a/src/trace_processor/containers/nullable_vector.h b/src/trace_processor/containers/nullable_vector.h
deleted file mode 100644
index dd9d929..0000000
--- a/src/trace_processor/containers/nullable_vector.h
+++ /dev/null
@@ -1,150 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef SRC_TRACE_PROCESSOR_CONTAINERS_NULLABLE_VECTOR_H_
-#define SRC_TRACE_PROCESSOR_CONTAINERS_NULLABLE_VECTOR_H_
-
-#include <stdint.h>
-
-#include <deque>
-#include <optional>
-
-#include "perfetto/base/logging.h"
-#include "src/trace_processor/containers/row_map.h"
-
-namespace perfetto {
-namespace trace_processor {
-
-// A data structure which compactly stores a list of possibly nullable data.
-//
-// Internally, this class is implemented using a combination of a std::deque
-// with a BitVector used to store whether each index is null or not.
-// By default, for each null value, it only uses a single bit inside the
-// BitVector at a slight cost (searching the BitVector to find the index into
-// the std::deque) when looking up the data.
-template <typename T>
-class NullableVector {
- private:
-  enum class Mode {
-    // Sparse mode is the default mode and ensures that nulls are stored using
-    // only
-    // a single bit (at the cost of making setting null entries to non-null
-    // O(n)).
-    kSparse,
-
-    // Dense mode forces the reservation of space for null entries which
-    // increases
-    // memory usage but allows for O(1) set operations.
-    kDense,
-  };
-
- public:
-  // Creates an empty NullableVector.
-  NullableVector() : NullableVector<T>(Mode::kSparse) {}
-
-  NullableVector(const NullableVector&) = delete;
-  NullableVector& operator=(const NullableVector&) = delete;
-
-  NullableVector(NullableVector&&) = default;
-  NullableVector& operator=(NullableVector&&) noexcept = default;
-
-  // Creates a sparse nullable vector
-  static NullableVector<T> Sparse() { return NullableVector<T>(Mode::kSparse); }
-
-  // Creates a dense nullable vector
-  static NullableVector<T> Dense() { return NullableVector<T>(Mode::kDense); }
-
-  // Returns the optional value at |idx| or std::nullopt if the value is null.
-  std::optional<T> Get(uint32_t idx) const {
-    bool contains = valid_.IsSet(idx);
-    if (mode_ == Mode::kDense)
-      return contains ? std::make_optional(data_[idx]) : std::nullopt;
-
-    return contains ? std::make_optional(data_[valid_.CountSetBits(idx)])
-                    : std::nullopt;
-  }
-
-  // Adds the given value to the NullableVector.
-  void Append(T val) {
-    data_.emplace_back(val);
-    valid_.AppendTrue();
-  }
-
-  // Adds the given optional value to the NullableVector.
-  void Append(std::optional<T> val) {
-    if (val) {
-      Append(*val);
-    } else {
-      AppendNull();
-    }
-  }
-
-  // Sets the value at |idx| to the given |val|.
-  void Set(uint32_t idx, T val) {
-    if (mode_ == Mode::kDense) {
-      valid_.Set(idx);
-      data_[idx] = val;
-    } else {
-      // Generally, we will be setting a null row to non-null so optimize for
-      // that path.
-      uint32_t row = valid_.CountSetBits(idx);
-      bool was_set = valid_.Set(idx);
-      if (PERFETTO_UNLIKELY(was_set)) {
-        data_[row] = val;
-      } else {
-        data_.insert(data_.begin() + static_cast<ptrdiff_t>(row), val);
-      }
-    }
-  }
-
-  // Requests the removal of unused capacity.
-  // Matches the semantics of std::vector::shrink_to_fit.
-  void ShrinkToFit() {
-    data_.shrink_to_fit();
-    valid_.ShrinkToFit();
-  }
-
-  // Returns the size of the NullableVector; this includes any null values.
-  uint32_t size() const { return valid_.size(); }
-
-  // Returns whether data in this NullableVector is stored densely.
-  bool IsDense() const { return mode_ == Mode::kDense; }
-
-  const std::vector<T>& non_null_vector() const& { return data_; }
-  const BitVector& non_null_bit_vector() const { return valid_; }
-
-  std::vector<T> non_null_vector() && { return std::move(data_); }
-
- private:
-  explicit NullableVector(Mode mode) : mode_(mode) {}
-
-  void AppendNull() {
-    if (mode_ == Mode::kDense) {
-      data_.emplace_back();
-    }
-    valid_.AppendFalse();
-  }
-
-  Mode mode_ = Mode::kSparse;
-
-  std::vector<T> data_;
-  BitVector valid_;
-};
-
-}  // namespace trace_processor
-}  // namespace perfetto
-
-#endif  // SRC_TRACE_PROCESSOR_CONTAINERS_NULLABLE_VECTOR_H_
diff --git a/src/trace_processor/containers/nullable_vector_benchmark.cc b/src/trace_processor/containers/nullable_vector_benchmark.cc
deleted file mode 100644
index d5f1a39..0000000
--- a/src/trace_processor/containers/nullable_vector_benchmark.cc
+++ /dev/null
@@ -1,66 +0,0 @@
-// Copyright (C) 2019 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-#include <random>
-
-#include <benchmark/benchmark.h>
-
-#include "src/trace_processor/containers/nullable_vector.h"
-
-namespace {
-
-static constexpr uint32_t kPoolSize = 100000;
-static constexpr uint32_t kSize = 123456;
-
-}  // namespace
-
-static void BM_NullableVectorAppendNonNull(benchmark::State& state) {
-  std::vector<uint8_t> data_pool(kPoolSize);
-
-  static constexpr uint32_t kRandomSeed = 42;
-  std::minstd_rand0 rnd_engine(kRandomSeed);
-  for (uint32_t i = 0; i < kPoolSize; ++i) {
-    data_pool[i] = rnd_engine() % std::numeric_limits<uint8_t>::max();
-  }
-
-  perfetto::trace_processor::NullableVector<uint8_t> sv;
-  uint32_t pool_idx = 0;
-  for (auto _ : state) {
-    sv.Append(data_pool[pool_idx]);
-    pool_idx = (pool_idx + 1) % kPoolSize;
-    benchmark::ClobberMemory();
-  }
-}
-BENCHMARK(BM_NullableVectorAppendNonNull);
-
-static void BM_NullableVectorGetNonNull(benchmark::State& state) {
-  std::vector<uint32_t> idx_pool(kPoolSize);
-
-  perfetto::trace_processor::NullableVector<uint8_t> sv;
-  static constexpr uint32_t kRandomSeed = 42;
-  std::minstd_rand0 rnd_engine(kRandomSeed);
-  for (uint32_t i = 0; i < kSize; ++i) {
-    sv.Append(rnd_engine() % std::numeric_limits<uint8_t>::max());
-  }
-  for (uint32_t i = 0; i < kPoolSize; ++i) {
-    idx_pool[i] = rnd_engine() % kSize;
-  }
-
-  uint32_t pool_idx = 0;
-  for (auto _ : state) {
-    benchmark::DoNotOptimize(sv.Get(idx_pool[pool_idx]));
-    pool_idx = (pool_idx + 1) % kPoolSize;
-  }
-}
-BENCHMARK(BM_NullableVectorGetNonNull);
diff --git a/src/trace_processor/containers/nullable_vector_unittest.cc b/src/trace_processor/containers/nullable_vector_unittest.cc
deleted file mode 100644
index c256ec4..0000000
--- a/src/trace_processor/containers/nullable_vector_unittest.cc
+++ /dev/null
@@ -1,96 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "src/trace_processor/containers/nullable_vector.h"
-
-#include "test/gtest_and_gmock.h"
-
-namespace perfetto {
-namespace trace_processor {
-namespace {
-
-TEST(NullableVector, Append) {
-  NullableVector<int64_t> sv;
-  sv.Append(10);
-  sv.Append(20);
-  sv.Append(std::nullopt);
-  sv.Append(40);
-
-  ASSERT_FALSE(sv.IsDense());
-  ASSERT_EQ(sv.size(), 4u);
-  ASSERT_EQ(sv.Get(0), std::optional<int64_t>(10));
-  ASSERT_EQ(sv.Get(1), std::optional<int64_t>(20));
-  ASSERT_EQ(sv.Get(2), std::nullopt);
-  ASSERT_EQ(sv.Get(3), std::optional<int64_t>(40));
-}
-
-TEST(NullableVector, Set) {
-  NullableVector<int64_t> sv;
-  sv.Append(10);
-  sv.Append(20);
-  sv.Append(std::nullopt);
-  sv.Append(std::nullopt);
-  sv.Append(40);
-
-  sv.Set(0, 15);
-  sv.Set(3, 30);
-
-  ASSERT_EQ(*sv.Get(0), 15);
-  ASSERT_EQ(*sv.Get(1), 20);
-  ASSERT_EQ(sv.Get(2), std::nullopt);
-  ASSERT_EQ(*sv.Get(3), 30);
-  ASSERT_EQ(*sv.Get(4), 40);
-}
-
-TEST(NullableVector, SetNonNull) {
-  NullableVector<int64_t> sv;
-  sv.Append(1);
-  sv.Append(2);
-  sv.Append(3);
-  sv.Append(4);
-
-  sv.Set(1, 22);
-
-  ASSERT_EQ(sv.Get(0), std::optional<int64_t>(1));
-  ASSERT_EQ(sv.Get(1), std::optional<int64_t>(22));
-  ASSERT_EQ(sv.Get(2), std::optional<int64_t>(3));
-  ASSERT_EQ(sv.Get(3), std::optional<int64_t>(4));
-}
-
-TEST(NullableVector, Dense) {
-  auto sv = NullableVector<int64_t>::Dense();
-
-  sv.Append(0);
-  sv.Append(std::nullopt);
-  sv.Append(2);
-  sv.Append(3);
-  sv.Append(std::nullopt);
-
-  ASSERT_TRUE(sv.IsDense());
-  ASSERT_EQ(sv.Get(0), 0);
-  ASSERT_EQ(sv.Get(1), std::nullopt);
-  ASSERT_EQ(sv.Get(2), 2);
-  ASSERT_EQ(sv.Get(3), 3);
-  ASSERT_EQ(sv.Get(4), std::nullopt);
-
-  sv.Set(1, 1);
-  ASSERT_EQ(sv.Get(1), 1);
-  ASSERT_EQ(sv.Get(2), 2);
-}
-
-}  // namespace
-}  // namespace trace_processor
-}  // namespace perfetto
diff --git a/src/trace_processor/db/BUILD.gn b/src/trace_processor/db/BUILD.gn
index aca3a21..d870996 100644
--- a/src/trace_processor/db/BUILD.gn
+++ b/src/trace_processor/db/BUILD.gn
@@ -68,6 +68,8 @@
     "../../../gn:gtest_and_gmock",
     "../../../include/perfetto/trace_processor:basic_types",
     "../../base",
+    "../../base:test_support",
+    "../containers",
     "../tables",
     "column",
     "column:fake_storage",
diff --git a/src/trace_processor/db/column_storage.h b/src/trace_processor/db/column_storage.h
index fa40745..294c1cf 100644
--- a/src/trace_processor/db/column_storage.h
+++ b/src/trace_processor/db/column_storage.h
@@ -17,11 +17,16 @@
 #ifndef SRC_TRACE_PROCESSOR_DB_COLUMN_STORAGE_H_
 #define SRC_TRACE_PROCESSOR_DB_COLUMN_STORAGE_H_
 
-#include "src/trace_processor/containers/bit_vector.h"
-#include "src/trace_processor/containers/nullable_vector.h"
+#include <cstddef>
+#include <cstdint>
+#include <optional>
+#include <vector>
 
-namespace perfetto {
-namespace trace_processor {
+#include "perfetto/base/logging.h"
+#include "perfetto/public/compiler.h"
+#include "src/trace_processor/containers/bit_vector.h"
+
+namespace perfetto::trace_processor {
 
 // Base class for allowing type erasure when defining plug-in implementations
 // of backing storage for columns.
@@ -96,46 +101,94 @@
   ColumnStorage(ColumnStorage&&) = default;
   ColumnStorage& operator=(ColumnStorage&&) noexcept = default;
 
-  std::optional<T> Get(uint32_t idx) const { return nv_.Get(idx); }
-  void Append(T val) { nv_.Append(val); }
-  void Append(std::optional<T> val) { nv_.Append(std::move(val)); }
-  void Set(uint32_t idx, T val) { nv_.Set(idx, val); }
-  bool IsDense() const { return nv_.IsDense(); }
-  void ShrinkToFit() { nv_.ShrinkToFit(); }
+  std::optional<T> Get(uint32_t idx) const {
+    bool contains = valid_.IsSet(idx);
+    if (mode_ == Mode::kDense) {
+      return contains ? std::make_optional(data_[idx]) : std::nullopt;
+    }
+    return contains ? std::make_optional(data_[valid_.CountSetBits(idx)])
+                    : std::nullopt;
+  }
+  void Append(T val) {
+    data_.emplace_back(val);
+    valid_.AppendTrue();
+  }
+  void Append(std::optional<T> val) {
+    if (val) {
+      Append(*val);
+    } else {
+      AppendNull();
+    }
+  }
+  void Set(uint32_t idx, T val) {
+    if (mode_ == Mode::kDense) {
+      valid_.Set(idx);
+      data_[idx] = val;
+    } else {
+      // Generally, we will be setting a null row to non-null so optimize for
+      // that path.
+      uint32_t row = valid_.CountSetBits(idx);
+      bool was_set = valid_.Set(idx);
+      if (PERFETTO_UNLIKELY(was_set)) {
+        data_[row] = val;
+      } else {
+        data_.insert(data_.begin() + static_cast<ptrdiff_t>(row), val);
+      }
+    }
+  }
+  bool IsDense() const { return mode_ == Mode::kDense; }
+  void ShrinkToFit() {
+    data_.shrink_to_fit();
+    valid_.ShrinkToFit();
+  }
   // For dense columns the size of the vector is equal to size of the bit
   // vector. For sparse it's equal to count set bits of the bit vector.
-  const std::vector<T>& non_null_vector() const& {
-    return nv_.non_null_vector();
-  }
-  const BitVector& non_null_bit_vector() const {
-    return nv_.non_null_bit_vector();
-  }
+  const std::vector<T>& non_null_vector() const& { return data_; }
+  const BitVector& non_null_bit_vector() const { return valid_; }
 
-  const void* data() const final { return nv_.non_null_vector().data(); }
-  const BitVector* bv() const final { return &nv_.non_null_bit_vector(); }
-  uint32_t size() const final { return nv_.size(); }
+  const void* data() const final { return non_null_vector().data(); }
+  const BitVector* bv() const final { return &non_null_bit_vector(); }
+  uint32_t size() const final { return valid_.size(); }
   uint32_t non_null_size() const final {
-    return static_cast<uint32_t>(nv_.non_null_vector().size());
+    return static_cast<uint32_t>(non_null_vector().size());
   }
 
   template <bool IsDense>
   static ColumnStorage<std::optional<T>> Create() {
-    return IsDense
-               ? ColumnStorage<std::optional<T>>(NullableVector<T>::Dense())
-               : ColumnStorage<std::optional<T>>(NullableVector<T>::Sparse());
+    return IsDense ? ColumnStorage<std::optional<T>>(Mode::kDense)
+                   : ColumnStorage<std::optional<T>>(Mode::kSparse);
   }
 
-  std::vector<T> non_null_vector() && {
-    return std::move(nv_).non_null_vector();
-  }
+  std::vector<T> non_null_vector() && { return std::move(data_); }
 
  private:
-  explicit ColumnStorage(NullableVector<T> nv) : nv_(std::move(nv)) {}
+  enum class Mode {
+    // Sparse mode is the default mode and ensures that nulls are stored using
+    // only
+    // a single bit (at the cost of making setting null entries to non-null
+    // O(n)).
+    kSparse,
 
-  NullableVector<T> nv_;
+    // Dense mode forces the reservation of space for null entries which
+    // increases
+    // memory usage but allows for O(1) set operations.
+    kDense,
+  };
+
+  explicit ColumnStorage(Mode mode) : mode_(mode) {}
+
+  void AppendNull() {
+    if (mode_ == Mode::kDense) {
+      data_.emplace_back();
+    }
+    valid_.AppendFalse();
+  }
+
+  Mode mode_ = Mode::kSparse;
+  std::vector<T> data_;
+  BitVector valid_;
 };
 
-}  // namespace trace_processor
-}  // namespace perfetto
+}  // namespace perfetto::trace_processor
 
 #endif  // SRC_TRACE_PROCESSOR_DB_COLUMN_STORAGE_H_
diff --git a/src/trace_processor/db/query_executor_benchmark.cc b/src/trace_processor/db/query_executor_benchmark.cc
index 38feabd..f8a7684 100644
--- a/src/trace_processor/db/query_executor_benchmark.cc
+++ b/src/trace_processor/db/query_executor_benchmark.cc
@@ -351,6 +351,14 @@
 
 BENCHMARK(BM_QESliceTableTsAndTrackId)->ArgsProduct({{DB::V1, DB::V2}});
 
+static void BM_QEFilterOneElement(benchmark::State& state) {
+  SliceTableForBenchmark table(state);
+  BenchmarkSliceTable(state, table,
+                      {table.table_.id().eq(10), table.table_.dur().eq(100)});
+}
+
+BENCHMARK(BM_QEFilterOneElement)->ArgsProduct({{DB::V1, DB::V2}});
+
 static void BM_QEFilterWithArrangement(benchmark::State& state) {
   Table::kUseFilterV2 = state.range(0) == 1;
 
diff --git a/src/trace_processor/db/runtime_table.cc b/src/trace_processor/db/runtime_table.cc
index 6f3cd54..6ccc942 100644
--- a/src/trace_processor/db/runtime_table.cc
+++ b/src/trace_processor/db/runtime_table.cc
@@ -17,15 +17,22 @@
 #include "src/trace_processor/db/runtime_table.h"
 
 #include <algorithm>
+#include <cinttypes>
 #include <cstdint>
+#include <memory>
 #include <optional>
+#include <string>
+#include <utility>
+#include <variant>
+#include <vector>
 
 #include "perfetto/base/logging.h"
 #include "perfetto/base/status.h"
+#include "perfetto/ext/base/status_or.h"
+#include "src/trace_processor/containers/string_pool.h"
 #include "src/trace_processor/db/column.h"
 
-namespace perfetto {
-namespace trace_processor {
+namespace perfetto::trace_processor {
 namespace {
 
 template <typename T, typename U>
@@ -49,15 +56,17 @@
 
 }  // namespace
 
-RuntimeTable::RuntimeTable(StringPool* pool, std::vector<std::string> col_names)
-    : Table(pool), col_names_(col_names), storage_(col_names_.size()) {
-  for (uint32_t i = 0; i < col_names.size(); i++)
-    storage_[i] = std::make_unique<VariantStorage>();
-}
-
 RuntimeTable::~RuntimeTable() = default;
 
-base::Status RuntimeTable::AddNull(uint32_t idx) {
+RuntimeTable::Builder::Builder(StringPool* pool,
+                               std::vector<std::string> col_names)
+    : string_pool_(pool), col_names_(std::move(col_names)) {
+  for (uint32_t i = 0; i < col_names_.size(); i++) {
+    storage_.emplace_back(std::make_unique<VariantStorage>());
+  }
+}
+
+base::Status RuntimeTable::Builder::AddNull(uint32_t idx) {
   auto* col = storage_[idx].get();
   PERFETTO_DCHECK(IsStorageNotIntNorDouble(*col));
   if (auto* leading_nulls = std::get_if<uint32_t>(col)) {
@@ -74,7 +83,7 @@
   return base::OkStatus();
 }
 
-base::Status RuntimeTable::AddInteger(uint32_t idx, int64_t res) {
+base::Status RuntimeTable::Builder::AddInteger(uint32_t idx, int64_t res) {
   auto* col = storage_[idx].get();
   PERFETTO_DCHECK(IsStorageNotIntNorDouble(*col));
   if (auto* leading_nulls_ptr = std::get_if<uint32_t>(col)) {
@@ -98,7 +107,7 @@
   return base::OkStatus();
 }
 
-base::Status RuntimeTable::AddFloat(uint32_t idx, double res) {
+base::Status RuntimeTable::Builder::AddFloat(uint32_t idx, double res) {
   auto* col = storage_[idx].get();
   PERFETTO_DCHECK(IsStorageNotIntNorDouble(*col));
   if (auto* leading_nulls_ptr = std::get_if<uint32_t>(col)) {
@@ -130,7 +139,7 @@
   return base::OkStatus();
 }
 
-base::Status RuntimeTable::AddText(uint32_t idx, const char* ptr) {
+base::Status RuntimeTable::Builder::AddText(uint32_t idx, const char* ptr) {
   auto* col = storage_[idx].get();
   PERFETTO_DCHECK(IsStorageNotIntNorDouble(*col));
   if (auto* leading_nulls_ptr = std::get_if<uint32_t>(col)) {
@@ -145,10 +154,16 @@
   return base::OkStatus();
 }
 
-base::Status RuntimeTable::AddColumnsAndOverlays(uint32_t rows) {
-  overlays_.push_back(ColumnStorageOverlay(rows));
-  for (uint32_t i = 0; i < col_names_.size(); ++i) {
-    auto* col = storage_[i].get();
+base::StatusOr<std::unique_ptr<RuntimeTable>> RuntimeTable::Builder::Build(
+    uint32_t rows) && {
+  auto table = std::make_unique<RuntimeTable>();
+  table->row_count_ = rows;
+  table->string_pool_ = string_pool_;
+  table->overlays_.emplace_back(rows);
+  table->storage_ = std::move(storage_);
+  table->col_names_ = std::move(col_names_);
+  for (uint32_t i = 0; i < table->col_names_.size(); ++i) {
+    auto* col = table->storage_[i].get();
     PERFETTO_DCHECK(IsStorageNotIntNorDouble(*col));
     if (auto* leading_nulls = std::get_if<uint32_t>(col)) {
       PERFETTO_CHECK(*leading_nulls == rows);
@@ -165,19 +180,18 @@
         uint32_t flags = is_sorted ? ColumnLegacy::Flag::kNonNull |
                                          ColumnLegacy::Flag::kSorted
                                    : ColumnLegacy::Flag::kNonNull;
-        columns_.push_back(ColumnLegacy(col_names_[i].c_str(), non_null_ints,
-                                        flags, this, i, 0));
+        table->columns_.emplace_back(table->col_names_[i].c_str(),
+                                     non_null_ints, flags, table.get(), i, 0);
       } else {
-        columns_.push_back(ColumnLegacy(col_names_[i].c_str(), ints,
-                                        ColumnLegacy::Flag::kNoFlag, this, i,
-                                        0));
+        table->columns_.emplace_back(table->col_names_[i].c_str(), ints,
+                                     ColumnLegacy::Flag::kNoFlag, table.get(),
+                                     i, 0);
       }
-
     } else if (auto* strings = std::get_if<StringStorage>(col)) {
       PERFETTO_CHECK(strings->size() == rows);
-      columns_.push_back(ColumnLegacy(col_names_[i].c_str(), strings,
-                                      ColumnLegacy::Flag::kNonNull, this, i,
-                                      0));
+      table->columns_.emplace_back(table->col_names_[i].c_str(), strings,
+                                   ColumnLegacy::Flag::kNonNull, table.get(), i,
+                                   0);
     } else if (auto* doubles = std::get_if<NullDoubleStorage>(col)) {
       PERFETTO_CHECK(doubles->size() == rows);
       // Check if the column is nullable.
@@ -190,24 +204,29 @@
         uint32_t flags = is_sorted ? ColumnLegacy::Flag::kNonNull |
                                          ColumnLegacy::Flag::kSorted
                                    : ColumnLegacy::Flag::kNonNull;
-
-        columns_.push_back(ColumnLegacy(col_names_[i].c_str(), non_null_doubles,
-                                        flags, this, i, 0));
+        table->columns_.emplace_back(table->col_names_[i].c_str(),
+                                     non_null_doubles, flags, table.get(), i,
+                                     0);
       } else {
-        columns_.push_back(ColumnLegacy(col_names_[i].c_str(), doubles,
-                                        ColumnLegacy::Flag::kNoFlag, this, i,
-                                        0));
+        table->columns_.emplace_back(table->col_names_[i].c_str(), doubles,
+                                     ColumnLegacy::Flag::kNoFlag, table.get(),
+                                     i, 0);
       }
     } else {
       PERFETTO_FATAL("Unexpected column type");
     }
   }
-  columns_.push_back(ColumnLegacy::IdColumn(
-      this, static_cast<uint32_t>(col_names_.size()), 0, "_auto_id",
+  table->columns_.push_back(ColumnLegacy::IdColumn(
+      table.get(), static_cast<uint32_t>(table->columns_.size()), 0, "_auto_id",
       ColumnLegacy::kIdFlags | ColumnLegacy::Flag::kHidden));
-  row_count_ = rows;
-  return base::OkStatus();
+
+  table->schema_.columns.reserve(table->columns_.size());
+  for (const auto& col : table->columns_) {
+    table->schema_.columns.emplace_back(
+        Schema::Column{col.name(), col.type(), col.IsId(), col.IsSorted(),
+                       col.IsHidden(), col.IsSetId()});
+  }
+  return {std::move(table)};
 }
 
-}  // namespace trace_processor
-}  // namespace perfetto
+}  // namespace perfetto::trace_processor
diff --git a/src/trace_processor/db/runtime_table.h b/src/trace_processor/db/runtime_table.h
index 21c9540..f61b0dd 100644
--- a/src/trace_processor/db/runtime_table.h
+++ b/src/trace_processor/db/runtime_table.h
@@ -17,19 +17,20 @@
 #ifndef SRC_TRACE_PROCESSOR_DB_RUNTIME_TABLE_H_
 #define SRC_TRACE_PROCESSOR_DB_RUNTIME_TABLE_H_
 
-#include <stdint.h>
-
-#include <limits>
+#include <cstdint>
 #include <memory>
-#include <numeric>
 #include <optional>
 #include <string>
+#include <variant>
 #include <vector>
 
+#include "perfetto/base/status.h"
+#include "perfetto/ext/base/status_or.h"
+#include "src/trace_processor/containers/string_pool.h"
+#include "src/trace_processor/db/column_storage.h"
 #include "src/trace_processor/db/table.h"
 
-namespace perfetto {
-namespace trace_processor {
+namespace perfetto::trace_processor {
 
 // Represents a table of data with named, strongly typed columns. Only used
 // where the schema of the table is decided at runtime.
@@ -46,26 +47,33 @@
                                       StringStorage,
                                       DoubleStorage,
                                       NullDoubleStorage>;
+  class Builder {
+   public:
+    Builder(StringPool* pool, std::vector<std::string> col_names);
 
-  RuntimeTable(StringPool* pool, std::vector<std::string> col_names);
+    base::Status AddNull(uint32_t idx);
+    base::Status AddInteger(uint32_t idx, int64_t res);
+    base::Status AddFloat(uint32_t idx, double res);
+    base::Status AddText(uint32_t idx, const char* ptr);
+
+    base::StatusOr<std::unique_ptr<RuntimeTable>> Build(uint32_t rows) &&;
+
+   private:
+    StringPool* string_pool_ = nullptr;
+    std::vector<std::string> col_names_;
+    std::vector<std::unique_ptr<VariantStorage>> storage_;
+  };
+
   ~RuntimeTable() override;
 
-  base::Status AddNull(uint32_t idx);
-
-  base::Status AddInteger(uint32_t idx, int64_t res);
-
-  base::Status AddFloat(uint32_t idx, double res);
-
-  base::Status AddText(uint32_t idx, const char* ptr);
-
-  base::Status AddColumnsAndOverlays(uint32_t rows);
+  const Table::Schema& schema() const { return schema_; }
 
  private:
   std::vector<std::string> col_names_;
   std::vector<std::unique_ptr<VariantStorage>> storage_;
+  Table::Schema schema_;
 };
 
-}  // namespace trace_processor
-}  // namespace perfetto
+}  // namespace perfetto::trace_processor
 
 #endif  // SRC_TRACE_PROCESSOR_DB_RUNTIME_TABLE_H_
diff --git a/src/trace_processor/db/runtime_table_unittest.cc b/src/trace_processor/db/runtime_table_unittest.cc
index 85ca8ec..d5629ca 100644
--- a/src/trace_processor/db/runtime_table_unittest.cc
+++ b/src/trace_processor/db/runtime_table_unittest.cc
@@ -16,45 +16,51 @@
 
 #include "src/trace_processor/db/runtime_table.h"
 
+#include <string>
+#include <utility>
+#include <vector>
+
+#include "src/base/test/status_matchers.h"
+#include "src/trace_processor/containers/string_pool.h"
 #include "test/gtest_and_gmock.h"
 
-namespace perfetto {
-namespace trace_processor {
+namespace perfetto::trace_processor {
 namespace {
+using base::gtest_matchers::IsOk;
+using testing::Not;
 
 class RuntimeTableTest : public ::testing::Test {
  protected:
   StringPool pool_;
   std::vector<std::string> names_{{"foo"}};
-  RuntimeTable table_{&pool_, names_};
+  RuntimeTable::Builder builder_{&pool_, names_};
 };
 
 TEST_F(RuntimeTableTest, DoubleThenIntValid) {
-  ASSERT_TRUE(table_.AddFloat(0, 1024.3).ok());
-  ASSERT_TRUE(table_.AddInteger(0, 1ll << 53).ok());
-  ASSERT_TRUE(table_.AddColumnsAndOverlays(2).ok());
+  ASSERT_OK(builder_.AddFloat(0, 1024.3));
+  ASSERT_OK(builder_.AddInteger(0, 1ll << 53));
+  ASSERT_OK_AND_ASSIGN(auto table, std::move(builder_).Build(2));
 
-  const auto& col = table_.columns()[0];
+  const auto& col = table->columns()[0];
   ASSERT_EQ(col.Get(0).AsDouble(), 1024.3);
   ASSERT_EQ(col.Get(1).AsDouble(), static_cast<double>(1ll << 53));
 }
 
 TEST_F(RuntimeTableTest, DoubleThenIntInvalid) {
-  ASSERT_TRUE(table_.AddFloat(0, 1024.0).ok());
-  ASSERT_FALSE(table_.AddInteger(0, (1ll << 53) + 1).ok());
-  ASSERT_FALSE(table_.AddInteger(0, -(1ll << 53) - 1).ok());
+  ASSERT_OK(builder_.AddFloat(0, 1024.0));
+  ASSERT_THAT(builder_.AddInteger(0, (1ll << 53) + 1), Not(IsOk()));
+  ASSERT_THAT(builder_.AddInteger(0, -(1ll << 53) - 1), Not(IsOk()));
 }
 
 TEST_F(RuntimeTableTest, IntThenDouble) {
-  ASSERT_TRUE(table_.AddInteger(0, 1024).ok());
-  ASSERT_TRUE(table_.AddFloat(0, 1.3).ok());
-  ASSERT_TRUE(table_.AddColumnsAndOverlays(2).ok());
+  ASSERT_TRUE(builder_.AddInteger(0, 1024).ok());
+  ASSERT_TRUE(builder_.AddFloat(0, 1.3).ok());
+  ASSERT_OK_AND_ASSIGN(auto table, std::move(builder_).Build(2));
 
-  const auto& col = table_.columns()[0];
+  const auto& col = table->columns()[0];
   ASSERT_EQ(col.Get(0).AsDouble(), 1024.0);
   ASSERT_EQ(col.Get(1).AsDouble(), 1.3);
 }
 
 }  // namespace
-}  // namespace trace_processor
-}  // namespace perfetto
+}  // namespace perfetto::trace_processor
diff --git a/src/trace_processor/db/table.h b/src/trace_processor/db/table.h
index 2f0c91c..1d0abdb 100644
--- a/src/trace_processor/db/table.h
+++ b/src/trace_processor/db/table.h
@@ -19,11 +19,14 @@
 
 #include <stdint.h>
 
+#include <algorithm>
+#include <iterator>
 #include <limits>
 #include <memory>
 #include <numeric>
 #include <optional>
 #include <string>
+#include <string_view>
 #include <vector>
 
 #include "perfetto/base/logging.h"
@@ -163,23 +166,13 @@
   // Returns the column at index |idx| in the Table.
   const ColumnLegacy& GetColumn(uint32_t idx) const { return columns_[idx]; }
 
-  // Returns the column index with the given name or std::nullopt otherwise.
-  std::optional<uint32_t> GetColumnIndexByName(const char* name) const {
-    auto it = std::find_if(columns_.begin(), columns_.end(),
-                           [name](const ColumnLegacy& col) {
-                             return strcmp(col.name(), name) == 0;
-                           });
-    if (it == columns_.end())
-      return std::nullopt;
-    return static_cast<uint32_t>(std::distance(columns_.begin(), it));
-  }
-
   // Returns the column with the given name or nullptr otherwise.
   const ColumnLegacy* GetColumnByName(const char* name) const {
-    std::optional<uint32_t> opt_idx = GetColumnIndexByName(name);
-    if (!opt_idx)
-      return nullptr;
-    return &columns_[*opt_idx];
+    auto it = std::find_if(columns_.begin(), columns_.end(),
+                           [name](const ColumnLegacy& col) {
+                             return std::string_view(col.name()) == name;
+                           });
+    return it == columns_.end() ? nullptr : &*it;
   }
 
   template <typename T>
@@ -187,39 +180,14 @@
     return *TypedColumn<T>::FromColumn(GetColumnByName(name));
   }
 
-  template <typename T>
-  const IdColumn<T>& GetIdColumnByName(const char* name) const {
-    return *IdColumn<T>::FromColumn(GetColumnByName(name));
-  }
-
-  // Returns the number of columns in the Table.
-  uint32_t GetColumnCount() const {
-    return static_cast<uint32_t>(columns_.size());
-  }
-
   // Returns an iterator into the Table.
   Iterator IterateRows() const { return Iterator(this); }
 
   // Creates a copy of this table.
   Table Copy() const;
 
-  // Computes the schema of this table and returns it.
-  Schema ComputeSchema() const {
-    Schema schema;
-    schema.columns.reserve(columns_.size());
-    for (const auto& col : columns_) {
-      schema.columns.emplace_back(
-          Schema::Column{col.name(), col.type(), col.IsId(), col.IsSorted(),
-                         col.IsHidden(), col.IsSetId()});
-    }
-    return schema;
-  }
-
   uint32_t row_count() const { return row_count_; }
   StringPool* string_pool() const { return string_pool_; }
-  const std::vector<ColumnStorageOverlay>& overlays() const {
-    return overlays_;
-  }
   const std::vector<ColumnLegacy>& columns() const { return columns_; }
 
  protected:
@@ -232,6 +200,9 @@
     }
     return rm;
   }
+  const std::vector<ColumnStorageOverlay>& overlays() const {
+    return overlays_;
+  }
 
   std::vector<ColumnStorageOverlay> overlays_;
   std::vector<ColumnLegacy> columns_;
diff --git a/src/trace_processor/importers/common/BUILD.gn b/src/trace_processor/importers/common/BUILD.gn
index 5fc2a1d..d465379 100644
--- a/src/trace_processor/importers/common/BUILD.gn
+++ b/src/trace_processor/importers/common/BUILD.gn
@@ -64,6 +64,7 @@
     "../../../../protos/perfetto/trace:zero",
     "../../../../protos/perfetto/trace/profiling:zero",
     "../../../base",
+    "../../db",
     "../../storage",
     "../../types",
     "../fuchsia:fuchsia_record",
diff --git a/src/trace_processor/importers/common/args_tracker.cc b/src/trace_processor/importers/common/args_tracker.cc
index 1ead9d3..36b50b1 100644
--- a/src/trace_processor/importers/common/args_tracker.cc
+++ b/src/trace_processor/importers/common/args_tracker.cc
@@ -17,11 +17,15 @@
 #include "src/trace_processor/importers/common/args_tracker.h"
 
 #include <algorithm>
+#include <cstdint>
 
+#include "src/trace_processor/db/column.h"
 #include "src/trace_processor/importers/common/args_translation_table.h"
+#include "src/trace_processor/storage/trace_storage.h"
+#include "src/trace_processor/types/trace_processor_context.h"
+#include "src/trace_processor/types/variadic.h"
 
-namespace perfetto {
-namespace trace_processor {
+namespace perfetto::trace_processor {
 
 ArgsTracker::ArgsTracker(TraceProcessorContext* context) : context_(context) {}
 
@@ -121,5 +125,4 @@
 
 ArgsTracker::BoundInserter::~BoundInserter() = default;
 
-}  // namespace trace_processor
-}  // namespace perfetto
+}  // namespace perfetto::trace_processor
diff --git a/src/trace_processor/importers/proto/metadata_minimal_module.cc b/src/trace_processor/importers/proto/metadata_minimal_module.cc
index 099cdac..df4dd3f 100644
--- a/src/trace_processor/importers/proto/metadata_minimal_module.cc
+++ b/src/trace_processor/importers/proto/metadata_minimal_module.cc
@@ -17,6 +17,7 @@
 #include "src/trace_processor/importers/proto/metadata_minimal_module.h"
 
 #include "perfetto/ext/base/base64.h"
+#include "perfetto/ext/base/string_utils.h"
 #include "src/trace_processor/importers/common/metadata_tracker.h"
 #include "src/trace_processor/types/trace_processor_context.h"
 
@@ -106,6 +107,15 @@
   TraceStorage* storage = context_->storage.get();
   MetadataTracker* metadata = context_->metadata_tracker.get();
 
+  // TODO(b/322298334): There is no easy way to associate ChromeMetadataPacket
+  // with ChromeMetadata for the same instance, so we have opted for letters to
+  // differentiate Chrome instances for ChromeMetadataPacket. When a unifying
+  // Chrome instance ID is in place, update this code to use the same counter
+  // as ChromeMetadata values.
+  base::StackString<6> metadata_prefix(
+      "cr-%c-", static_cast<char>('a' + (chrome_metadata_count_ % 26)));
+  chrome_metadata_count_++;
+
   // Typed chrome metadata proto. The untyped metadata is parsed below in
   // ParseChromeEvents().
   protos::pbzero::ChromeMetadataPacket::Decoder packet_decoder(blob.data,
@@ -113,14 +123,48 @@
 
   if (packet_decoder.has_chrome_version_code()) {
     metadata->SetDynamicMetadata(
-        storage->InternString("cr-playstore_version_code"),
+        storage->InternString(base::StringView(metadata_prefix.ToStdString() +
+                                               "playstore_version_code")),
         Variadic::Integer(packet_decoder.chrome_version_code()));
   }
   if (packet_decoder.has_enabled_categories()) {
     auto categories_id =
         storage->InternString(packet_decoder.enabled_categories());
-    metadata->SetDynamicMetadata(storage->InternString("cr-enabled_categories"),
-                                 Variadic::String(categories_id));
+    metadata->SetDynamicMetadata(
+        storage->InternString(base::StringView(metadata_prefix.ToStdString() +
+                                               "enabled_categories")),
+        Variadic::String(categories_id));
+  }
+
+  if (packet_decoder.has_field_trial_hashes()) {
+    std::string field_trials;
+
+    // Add  a line break after every 2 field trial hashes to better utilize the
+    // UI space.
+    int line_size = 0;
+    for (auto it = packet_decoder.field_trial_hashes(); it; ++it) {
+      if (line_size == 2) {
+        field_trials.append("\n");
+        line_size = 1;
+      } else {
+        line_size++;
+      }
+
+      perfetto::protos::pbzero::ChromeMetadataPacket::FinchHash::Decoder
+          field_trial(*it);
+
+      base::StackString<45> field_trial_string(
+          "{ name: %u, group: %u } ", field_trial.name(), field_trial.group());
+
+      field_trials.append(field_trial_string.ToStdString());
+    }
+
+    StringId field_trials_string =
+        context_->storage->InternString(base::StringView(field_trials));
+    metadata->SetDynamicMetadata(
+        storage->InternString(base::StringView(metadata_prefix.ToStdString() +
+                                               "field_trial_hashes")),
+        Variadic::String(field_trials_string));
   }
 
   if (packet_decoder.has_background_tracing_metadata()) {
diff --git a/src/trace_processor/importers/proto/metadata_minimal_module.h b/src/trace_processor/importers/proto/metadata_minimal_module.h
index b12eed9..3ffdf62 100644
--- a/src/trace_processor/importers/proto/metadata_minimal_module.h
+++ b/src/trace_processor/importers/proto/metadata_minimal_module.h
@@ -44,6 +44,8 @@
   void ParseChromeMetadataPacket(ConstBytes);
 
   TraceProcessorContext* context_;
+
+  uint32_t chrome_metadata_count_ = 0;
 };
 
 }  // namespace trace_processor
diff --git a/src/trace_processor/importers/proto/proto_trace_parser.cc b/src/trace_processor/importers/proto/proto_trace_parser.cc
index b18bdea..b23a513 100644
--- a/src/trace_processor/importers/proto/proto_trace_parser.cc
+++ b/src/trace_processor/importers/proto/proto_trace_parser.cc
@@ -172,6 +172,26 @@
                     static_cast<int64_t>(evt.flushes_succeeded()));
   storage->SetStats(stats::traced_flushes_failed,
                     static_cast<int64_t>(evt.flushes_failed()));
+
+  if (evt.has_filter_stats()) {
+    protos::pbzero::TraceStats::FilterStats::Decoder fstat(evt.filter_stats());
+    storage->SetStats(stats::filter_errors,
+                      static_cast<int64_t>(fstat.errors()));
+    storage->SetStats(stats::filter_input_bytes,
+                      static_cast<int64_t>(fstat.input_bytes()));
+    storage->SetStats(stats::filter_input_packets,
+                      static_cast<int64_t>(fstat.input_packets()));
+    storage->SetStats(stats::filter_output_bytes,
+                      static_cast<int64_t>(fstat.output_bytes()));
+    storage->SetStats(stats::filter_time_taken_ns,
+                      static_cast<int64_t>(fstat.time_taken_ns()));
+    for (auto [i, it] = std::tuple{0, fstat.bytes_discarded_per_buffer()}; it;
+         ++it, ++i) {
+      storage->SetIndexedStats(stats::traced_buf_bytes_filtered_out, i,
+                               static_cast<int64_t>(*it));
+    }
+  }
+
   switch (evt.final_flush_outcome()) {
     case protos::pbzero::TraceStats::FINAL_FLUSH_SUCCEEDED:
       storage->IncrementStats(stats::traced_final_flush_succeeded, 1);
diff --git a/src/trace_processor/importers/proto/system_probes_parser.cc b/src/trace_processor/importers/proto/system_probes_parser.cc
index 97fecb8..bd1f8c4 100644
--- a/src/trace_processor/importers/proto/system_probes_parser.cc
+++ b/src/trace_processor/importers/proto/system_probes_parser.cc
@@ -608,7 +608,7 @@
     base::StringView machine = utsname.machine();
     SyscallTracker* syscall_tracker = SyscallTracker::GetOrCreate(context_);
     Architecture arch = SyscallTable::ArchFromString(machine);
-    if (arch != kUnknown) {
+    if (arch != Architecture::kUnknown) {
       syscall_tracker->SetArchitecture(arch);
     } else {
       PERFETTO_ELOG("Unknown architecture %s. Syscall traces will not work.",
diff --git a/src/trace_processor/importers/proto/winscope/BUILD.gn b/src/trace_processor/importers/proto/winscope/BUILD.gn
index 7b04e85..47e5cb4 100644
--- a/src/trace_processor/importers/proto/winscope/BUILD.gn
+++ b/src/trace_processor/importers/proto/winscope/BUILD.gn
@@ -16,6 +16,10 @@
 
 source_set("full") {
   sources = [
+    "protolog_messages_tracker.cc",
+    "protolog_messages_tracker.h",
+    "protolog_parser.cc",
+    "protolog_parser.h",
     "shell_transitions_parser.cc",
     "shell_transitions_parser.h",
     "shell_transitions_tracker.cc",
@@ -35,11 +39,15 @@
     "../../../../../gn:default_deps",
     "../../../../../protos/perfetto/trace:zero",
     "../../../../../protos/perfetto/trace/android:zero",
+    "../../../../../protos/perfetto/trace/interned_data:zero",
+    "../../../../../protos/perfetto/trace/profiling:zero",
     "../../../storage",
     "../../../tables",
     "../../../types",
     "../../common",
     "../../common:parser_types",
+    "../../proto:minimal",
+    "../../proto:packet_sequence_state_generation_hdr",
   ]
 }
 
diff --git a/src/trace_processor/importers/proto/winscope/protolog_messages_tracker.cc b/src/trace_processor/importers/proto/winscope/protolog_messages_tracker.cc
new file mode 100644
index 0000000..caf481d
--- /dev/null
+++ b/src/trace_processor/importers/proto/winscope/protolog_messages_tracker.cc
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "protolog_messages_tracker.h"
+#include "perfetto/ext/base/crash_keys.h"
+#include "src/trace_processor/importers/common/process_tracker.h"
+#include "src/trace_processor/storage/metadata.h"
+#include "src/trace_processor/types/trace_processor_context.h"
+
+namespace perfetto {
+namespace trace_processor {
+ProtoLogMessagesTracker::ProtoLogMessagesTracker() {}
+
+ProtoLogMessagesTracker::~ProtoLogMessagesTracker() = default;
+
+void ProtoLogMessagesTracker::TrackMessage(
+    TrackedProtoLogMessage tracked_protolog_message) {
+  tracked_protolog_messages
+      .Insert(tracked_protolog_message.message_id,
+              std::vector<TrackedProtoLogMessage>())
+      .first->emplace_back(tracked_protolog_message);
+}
+
+const std::optional<
+    std::vector<ProtoLogMessagesTracker::TrackedProtoLogMessage>*>
+ProtoLogMessagesTracker::GetTrackedMessagesByMessageId(uint64_t message_id) {
+  auto tracked_messages = tracked_protolog_messages.Find(message_id);
+
+  if (tracked_messages == nullptr) {
+    // No tracked messages found for this id
+    return std::nullopt;
+  }
+
+  return tracked_messages;
+}
+
+}  // namespace trace_processor
+}  // namespace perfetto
diff --git a/src/trace_processor/importers/proto/winscope/protolog_messages_tracker.h b/src/trace_processor/importers/proto/winscope/protolog_messages_tracker.h
new file mode 100644
index 0000000..e61c5f5
--- /dev/null
+++ b/src/trace_processor/importers/proto/winscope/protolog_messages_tracker.h
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef SRC_TRACE_PROCESSOR_IMPORTERS_PROTO_WINSCOPE_PROTOLOG_MESSAGES_TRACKER_H_
+#define SRC_TRACE_PROCESSOR_IMPORTERS_PROTO_WINSCOPE_PROTOLOG_MESSAGES_TRACKER_H_
+
+#include "perfetto/trace_processor/basic_types.h"
+#include "src/trace_processor/storage/trace_storage.h"
+#include "src/trace_processor/types/trace_processor_context.h"
+
+namespace perfetto {
+namespace trace_processor {
+
+class ProtoLogMessagesTracker : public Destructible {
+ public:
+  explicit ProtoLogMessagesTracker();
+  virtual ~ProtoLogMessagesTracker() override;
+
+  struct TrackedProtoLogMessage {
+    uint64_t message_id;
+    std::vector<int64_t> sint64_params;
+    std::vector<double> double_params;
+    std::vector<bool> boolean_params;
+    std::vector<std::string> string_params;
+    tables::ProtoLogTable::Id table_row_id;
+    int64_t timestamp;
+  };
+
+  static ProtoLogMessagesTracker* GetOrCreate(TraceProcessorContext* context) {
+    if (!context->shell_transitions_tracker) {
+      context->shell_transitions_tracker.reset(new ProtoLogMessagesTracker());
+    }
+    return static_cast<ProtoLogMessagesTracker*>(
+        context->shell_transitions_tracker.get());
+  }
+
+  void TrackMessage(TrackedProtoLogMessage tracked_protolog_message);
+  const std::optional<
+      std::vector<ProtoLogMessagesTracker::TrackedProtoLogMessage>*>
+  GetTrackedMessagesByMessageId(uint64_t message_id);
+
+ private:
+  base::FlatHashMap<uint64_t, std::vector<TrackedProtoLogMessage>>
+      tracked_protolog_messages;
+};
+
+}  // namespace trace_processor
+}  // namespace perfetto
+
+#endif  // SRC_TRACE_PROCESSOR_IMPORTERS_PROTO_WINSCOPE_PROTOLOG_MESSAGES_TRACKER_H_
diff --git a/src/trace_processor/importers/proto/winscope/protolog_parser.cc b/src/trace_processor/importers/proto/winscope/protolog_parser.cc
new file mode 100644
index 0000000..0543222
--- /dev/null
+++ b/src/trace_processor/importers/proto/winscope/protolog_parser.cc
@@ -0,0 +1,284 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "src/trace_processor/importers/proto/winscope/protolog_parser.h"
+#include "src/trace_processor/importers/proto/winscope/protolog_messages_tracker.h"
+
+#include "perfetto/ext/base/string_utils.h"
+#include "protos/perfetto/trace/android/protolog.pbzero.h"
+#include "protos/perfetto/trace/interned_data/interned_data.pbzero.h"
+#include "protos/perfetto/trace/profiling/profile_common.pbzero.h"
+#include "protos/perfetto/trace/profiling/profile_packet.pbzero.h"
+#include "src/trace_processor/importers/common/args_tracker.h"
+#include "src/trace_processor/importers/proto/packet_sequence_state_generation.h"
+#include "src/trace_processor/importers/proto/winscope/winscope.descriptor.h"
+#include "src/trace_processor/importers/proto/winscope/winscope_args_parser.h"
+#include "src/trace_processor/storage/trace_storage.h"
+#include "src/trace_processor/types/trace_processor_context.h"
+
+#include <sstream>
+
+namespace perfetto {
+namespace trace_processor {
+
+enum ProtoLogLevel : int32_t {
+  DEBUG = 1,
+  VERBOSE = 2,
+  INFO = 3,
+  WARN = 4,
+  ERROR = 5,
+  WTF = 6,
+};
+
+ProtoLogParser::ProtoLogParser(TraceProcessorContext* context)
+    : context_(context),
+      args_parser_{pool_},
+      log_level_debug_string_id_(context->storage->InternString("DEBUG")),
+      log_level_verbose_string_id_(context->storage->InternString("VERBOSE")),
+      log_level_info_string_id_(context->storage->InternString("INFO")),
+      log_level_warn_string_id_(context->storage->InternString("WARN")),
+      log_level_error_string_id_(context->storage->InternString("ERROR")),
+      log_level_wtf_string_id_(context->storage->InternString("WTF")),
+      log_level_unknown_string_id_(context_->storage->InternString("UNKNOWN")) {
+  pool_.AddFromFileDescriptorSet(kWinscopeDescriptor.data(),
+                                 kWinscopeDescriptor.size());
+}
+
+void ProtoLogParser::ParseProtoLogMessage(
+    PacketSequenceStateGeneration* sequence_state,
+    protozero::ConstBytes blob,
+    int64_t timestamp) {
+  protos::pbzero::ProtoLogMessage::Decoder protolog_message(blob);
+
+  std::vector<int64_t> sint64_params;
+  for (auto it = protolog_message.sint64_params(); it; ++it) {
+    sint64_params.emplace_back(*it);
+  }
+
+  std::vector<double> double_params;
+  for (auto it = protolog_message.double_params(); it; ++it) {
+    double_params.emplace_back(*it);
+  }
+
+  std::vector<bool> boolean_params;
+  for (auto it = protolog_message.boolean_params(); it; ++it) {
+    boolean_params.emplace_back(*it);
+  }
+
+  std::vector<std::string> string_params;
+  if (protolog_message.has_interned_str_params()) {
+    if (sequence_state->state()->IsIncrementalStateValid()) {
+      for (auto it = protolog_message.interned_str_params(); it; ++it) {
+        auto decoder =
+            sequence_state->state()
+                ->current_generation()
+                ->LookupInternedMessage<protos::pbzero::InternedData::
+                                            kProtologStringArgsFieldNumber,
+                                        protos::pbzero::InternedString>(
+                    it.field().as_uint32());
+
+        if (!decoder) {
+          // This shouldn't happen since we already checked the incremental
+          // state is valid.
+          string_params.emplace_back("<ERROR>");
+          context_->storage->IncrementStats(
+              stats::winscope_protolog_missing_interned_arg_parse_errors);
+          continue;
+        }
+
+        string_params.emplace_back(decoder->str().ToStdString());
+      }
+    } else {
+      // If the incremental state is not valid we will not be able to decode
+      // the interned strings correctly with 100% certainty so we will provide
+      // string parameters that are not decoded.
+      string_params.emplace_back("<MISSING_STR_ARG>");
+    }
+  }
+
+  auto* protolog_table = context_->storage->mutable_protolog_table();
+
+  tables::ProtoLogTable::Row row;
+  auto row_id = protolog_table->Insert(row).id;
+
+  auto protolog_message_tracker =
+      ProtoLogMessagesTracker::GetOrCreate(context_);
+  struct ProtoLogMessagesTracker::TrackedProtoLogMessage tracked_message = {
+      protolog_message.message_id(),
+      std::move(sint64_params),
+      std::move(double_params),
+      std::move(boolean_params),
+      std::move(string_params),
+      row_id,
+      timestamp};
+  protolog_message_tracker->TrackMessage(std::move(tracked_message));
+}
+
+void ProtoLogParser::ParseProtoLogViewerConfig(protozero::ConstBytes blob) {
+  auto* protolog_table = context_->storage->mutable_protolog_table();
+
+  protos::pbzero::ProtoLogViewerConfig::Decoder protolog_viewer_config(blob);
+
+  std::unordered_map<uint32_t, std::string> group_tags;
+  for (auto it = protolog_viewer_config.groups(); it; ++it) {
+    protos::pbzero::ProtoLogViewerConfig::Group::Decoder group(*it);
+    group_tags.insert({group.id(), group.tag().ToStdString()});
+  }
+
+  auto protolog_message_tracker =
+      ProtoLogMessagesTracker::GetOrCreate(context_);
+
+  for (auto it = protolog_viewer_config.messages(); it; ++it) {
+    protos::pbzero::ProtoLogViewerConfig::MessageData::Decoder message_data(
+        *it);
+
+    auto tracked_messages_opt =
+        protolog_message_tracker->GetTrackedMessagesByMessageId(
+            message_data.message_id());
+
+    if (tracked_messages_opt.has_value()) {
+      auto group_tag = group_tags.find(message_data.group_id())->second;
+
+      for (const auto& tracked_message : *tracked_messages_opt.value()) {
+        auto formatted_message = FormatMessage(
+            message_data.message().ToStdString(), tracked_message.sint64_params,
+            tracked_message.double_params, tracked_message.boolean_params,
+            tracked_message.string_params);
+
+        auto row =
+            protolog_table->FindById(tracked_message.table_row_id).value();
+
+        row.set_ts(tracked_message.timestamp);
+
+        StringPool::Id level;
+        switch (message_data.level()) {
+          case ProtoLogLevel::DEBUG:
+            level = log_level_debug_string_id_;
+            break;
+          case ProtoLogLevel::VERBOSE:
+            level = log_level_verbose_string_id_;
+            break;
+          case ProtoLogLevel::INFO:
+            level = log_level_info_string_id_;
+            break;
+          case ProtoLogLevel::WARN:
+            level = log_level_warn_string_id_;
+            break;
+          case ProtoLogLevel::ERROR:
+            level = log_level_error_string_id_;
+            break;
+          case ProtoLogLevel::WTF:
+            level = log_level_wtf_string_id_;
+            break;
+          default:
+            level = log_level_unknown_string_id_;
+            break;
+        }
+        row.set_level(level);
+
+        auto tag = context_->storage->InternString(base::StringView(group_tag));
+        row.set_tag(tag);
+
+        auto message = context_->storage->InternString(
+            base::StringView(formatted_message));
+        row.set_message(message);
+      }
+    }
+  }
+}
+
+std::string ProtoLogParser::FormatMessage(
+    const std::string message,
+    const std::vector<int64_t>& sint64_params,
+    const std::vector<double>& double_params,
+    const std::vector<bool>& boolean_params,
+    const std::vector<std::string>& string_params) {
+  std::string formatted_message;
+  formatted_message.reserve(message.size());
+
+  auto sint64_params_itr = sint64_params.begin();
+  auto double_params_itr = double_params.begin();
+  auto boolean_params_itr = boolean_params.begin();
+  auto str_params_itr = string_params.begin();
+
+  for (size_t i = 0; i < message.length();) {
+    if (message.at(i) == '%') {
+      switch (message.at(i + 1)) {
+        case '%':
+          break;
+        case 'd': {
+          base::StackString<32> param("%" PRId64, *sint64_params_itr);
+          formatted_message.append(param.c_str());
+          ++sint64_params_itr;
+          break;
+        }
+        case 'o': {
+          base::StackString<32> param("%" PRIo64, *sint64_params_itr);
+          formatted_message.append(param.c_str());
+          ++sint64_params_itr;
+          break;
+        }
+        case 'x': {
+          base::StackString<32> param("%" PRIx64, *sint64_params_itr);
+          formatted_message.append(param.c_str());
+          ++sint64_params_itr;
+          break;
+        }
+        case 'f': {
+          base::StackString<32> param("%f", *double_params_itr);
+          formatted_message.append(param.c_str());
+          ++double_params_itr;
+          break;
+        }
+        case 'e': {
+          base::StackString<32> param("%e", *double_params_itr);
+          formatted_message.append(param.c_str());
+          ++double_params_itr;
+          break;
+        }
+        case 'g': {
+          base::StackString<32> param("%g", *double_params_itr);
+          formatted_message.append(param.c_str());
+          ++double_params_itr;
+          break;
+        }
+        case 's': {
+          formatted_message.append(str_params_itr->c_str());
+          ++str_params_itr;
+          break;
+          case 'b':
+            formatted_message.append(*boolean_params_itr ? "true" : "false");
+            ++boolean_params_itr;
+            break;
+        }
+        default:
+          // Should never happen
+          context_->storage->IncrementStats(
+              stats::winscope_protolog_invalid_interpolation_parse_errors);
+      }
+
+      i += 2;
+    } else {
+      formatted_message.push_back(message[i]);
+      i += 1;
+    }
+  }
+
+  return formatted_message;
+}
+
+}  // namespace trace_processor
+}  // namespace perfetto
diff --git a/src/trace_processor/importers/proto/winscope/protolog_parser.h b/src/trace_processor/importers/proto/winscope/protolog_parser.h
new file mode 100644
index 0000000..fbcf9d9
--- /dev/null
+++ b/src/trace_processor/importers/proto/winscope/protolog_parser.h
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef SRC_TRACE_PROCESSOR_IMPORTERS_PROTO_WINSCOPE_PROTOLOG_PARSER_H_
+#define SRC_TRACE_PROCESSOR_IMPORTERS_PROTO_WINSCOPE_PROTOLOG_PARSER_H_
+
+#include "protos/perfetto/trace/android/protolog.pbzero.h"
+#include "src/trace_processor/importers/proto/packet_sequence_state.h"
+#include "src/trace_processor/util/descriptors.h"
+#include "src/trace_processor/util/proto_to_args_parser.h"
+
+namespace perfetto {
+
+namespace trace_processor {
+
+class TraceProcessorContext;
+
+class ProtoLogParser {
+ public:
+  explicit ProtoLogParser(TraceProcessorContext*);
+  void ParseProtoLogMessage(PacketSequenceStateGeneration* sequence_state,
+                            protozero::ConstBytes,
+                            int64_t timestamp);
+  void ParseProtoLogViewerConfig(protozero::ConstBytes);
+
+ private:
+  std::string FormatMessage(const std::string message,
+                            const std::vector<int64_t>& sint64_params,
+                            const std::vector<double>& double_params,
+                            const std::vector<bool>& boolean_params,
+                            const std::vector<std::string>& string_params);
+
+  static constexpr auto* kProtoLogMessageProtoName =
+      "perfetto.protos.ProtoLogMessage";
+
+  TraceProcessorContext* const context_;
+  DescriptorPool pool_;
+  util::ProtoToArgsParser args_parser_;
+
+  const StringId log_level_debug_string_id_;
+  const StringId log_level_verbose_string_id_;
+  const StringId log_level_info_string_id_;
+  const StringId log_level_warn_string_id_;
+  const StringId log_level_error_string_id_;
+  const StringId log_level_wtf_string_id_;
+  const StringId log_level_unknown_string_id_;
+};
+}  // namespace trace_processor
+}  // namespace perfetto
+
+#endif  // SRC_TRACE_PROCESSOR_IMPORTERS_PROTO_WINSCOPE_PROTOLOG_PARSER_H_
diff --git a/src/trace_processor/importers/proto/winscope/winscope_module.cc b/src/trace_processor/importers/proto/winscope/winscope_module.cc
index 7f6c154..a59e7eb 100644
--- a/src/trace_processor/importers/proto/winscope/winscope_module.cc
+++ b/src/trace_processor/importers/proto/winscope/winscope_module.cc
@@ -24,18 +24,21 @@
 WinscopeModule::WinscopeModule(TraceProcessorContext* context)
     : surfaceflinger_layers_parser_(context),
       surfaceflinger_transactions_parser_(context),
-      shell_transitions_parser_(context) {
+      shell_transitions_parser_(context),
+      protolog_parser_(context) {
   RegisterForField(TracePacket::kSurfaceflingerLayersSnapshotFieldNumber,
                    context);
   RegisterForField(TracePacket::kSurfaceflingerTransactionsFieldNumber,
                    context);
   RegisterForField(TracePacket::kShellTransitionFieldNumber, context);
   RegisterForField(TracePacket::kShellHandlerMappingsFieldNumber, context);
+  RegisterForField(TracePacket::kProtologMessageFieldNumber, context);
+  RegisterForField(TracePacket::kProtologViewerConfigFieldNumber, context);
 }
 
 void WinscopeModule::ParseTracePacketData(const TracePacket::Decoder& decoder,
                                           int64_t timestamp,
-                                          const TracePacketData&,
+                                          const TracePacketData& data,
                                           uint32_t field_id) {
   switch (field_id) {
     case TracePacket::kSurfaceflingerLayersSnapshotFieldNumber:
@@ -53,6 +56,14 @@
       shell_transitions_parser_.ParseHandlerMappings(
           decoder.shell_handler_mappings());
       return;
+    case TracePacket::kProtologMessageFieldNumber:
+      protolog_parser_.ParseProtoLogMessage(
+          data.sequence_state.get(), decoder.protolog_message(), timestamp);
+      return;
+    case TracePacket::kProtologViewerConfigFieldNumber:
+      protolog_parser_.ParseProtoLogViewerConfig(
+          decoder.protolog_viewer_config());
+      return;
   }
 }
 
diff --git a/src/trace_processor/importers/proto/winscope/winscope_module.h b/src/trace_processor/importers/proto/winscope/winscope_module.h
index fffe42c..6334411 100644
--- a/src/trace_processor/importers/proto/winscope/winscope_module.h
+++ b/src/trace_processor/importers/proto/winscope/winscope_module.h
@@ -21,6 +21,7 @@
 #include "perfetto/base/build_config.h"
 #include "src/trace_processor/importers/common/parser_types.h"
 #include "src/trace_processor/importers/proto/proto_importer_module.h"
+#include "src/trace_processor/importers/proto/winscope/protolog_parser.h"
 #include "src/trace_processor/importers/proto/winscope/shell_transitions_parser.h"
 #include "src/trace_processor/importers/proto/winscope/surfaceflinger_layers_parser.h"
 #include "src/trace_processor/importers/proto/winscope/surfaceflinger_transactions_parser.h"
@@ -43,6 +44,7 @@
   SurfaceFlingerLayersParser surfaceflinger_layers_parser_;
   SurfaceFlingerTransactionsParser surfaceflinger_transactions_parser_;
   ShellTransitionsParser shell_transitions_parser_;
+  ProtoLogParser protolog_parser_;
 };
 
 }  // namespace trace_processor
diff --git a/src/trace_processor/importers/syscalls/syscall_tracker.cc b/src/trace_processor/importers/syscalls/syscall_tracker.cc
index 37be70e..ed71317 100644
--- a/src/trace_processor/importers/syscalls/syscall_tracker.cc
+++ b/src/trace_processor/importers/syscalls/syscall_tracker.cc
@@ -35,7 +35,7 @@
 // of each process from the trace.
 SyscallTracker::SyscallTracker(TraceProcessorContext* context)
     : context_(context) {
-  SetArchitecture(kUnknown);
+  SetArchitecture(Architecture::kUnknown);
 }
 
 SyscallTracker::~SyscallTracker() = default;
diff --git a/src/trace_processor/importers/syscalls/syscall_tracker_unittest.cc b/src/trace_processor/importers/syscalls/syscall_tracker_unittest.cc
index ceafd2f..d57d6de 100644
--- a/src/trace_processor/importers/syscalls/syscall_tracker_unittest.cc
+++ b/src/trace_processor/importers/syscalls/syscall_tracker_unittest.cc
@@ -93,7 +93,7 @@
       .WillOnce(DoAll(SaveArg<3>(&end_name), Return(std::nullopt)));
 
   SyscallTracker* syscall_tracker = SyscallTracker::GetOrCreate(&context);
-  syscall_tracker->SetArchitecture(kAarch64);
+  syscall_tracker->SetArchitecture(Architecture::kAarch64);
   syscall_tracker->Enter(100 /*ts*/, 42 /*utid*/, 63 /*sys_read*/);
   syscall_tracker->Exit(110 /*ts*/, 42 /*utid*/, 63 /*sys_read*/);
   EXPECT_EQ(context.storage->GetString(begin_name), "sys_read");
@@ -110,7 +110,7 @@
       .WillOnce(DoAll(SaveArg<3>(&end_name), Return(std::nullopt)));
 
   SyscallTracker* syscall_tracker = SyscallTracker::GetOrCreate(&context);
-  syscall_tracker->SetArchitecture(kX86_64);
+  syscall_tracker->SetArchitecture(Architecture::kX86_64);
   syscall_tracker->Enter(100 /*ts*/, 42 /*utid*/, 0 /*sys_read*/);
   syscall_tracker->Exit(110 /*ts*/, 42 /*utid*/, 0 /*sys_read*/);
   EXPECT_EQ(context.storage->GetString(begin_name), "sys_read");
@@ -122,7 +122,7 @@
   EXPECT_CALL(*slice_tracker, End(_, _, _, _, _)).Times(0);
 
   SyscallTracker* syscall_tracker = SyscallTracker::GetOrCreate(&context);
-  syscall_tracker->SetArchitecture(kAarch64);
+  syscall_tracker->SetArchitecture(Architecture::kAarch64);
   syscall_tracker->Enter(100 /*ts*/, 42 /*utid*/, 9999);
   syscall_tracker->Exit(110 /*ts*/, 42 /*utid*/, 9999);
 }
diff --git a/src/trace_processor/metrics/sql/android/ad_services_metric.sql b/src/trace_processor/metrics/sql/android/ad_services_metric.sql
index e6d468e..04ba0ed 100644
--- a/src/trace_processor/metrics/sql/android/ad_services_metric.sql
+++ b/src/trace_processor/metrics/sql/android/ad_services_metric.sql
@@ -29,20 +29,14 @@
       SELECT
         RepeatedField(
           AdServicesUiMetric(
-            'main_actitivity_creation_latency', (
-              GET_LATENCY('AdServicesSettingsMainActivity#OnCreate')
-            ),
-            'consent_manager_read_latency', (
-              GET_LATENCY('ConsentManager#ReadOperation')
-            ),
-            'consent_manager_write_latency', (
-              GET_LATENCY('ConsentManager#WriteOperation')
-            ),
-            'consent_manager_initialization_latency', (
-              GET_LATENCY('ConsentManager#Initialization')
-            )
-          )
-        )
+            'main_activity_creation_latency',
+            (GET_LATENCY('AdServicesSettingsMainActivity#OnCreate')),
+            'consent_manager_read_latency',
+            (GET_LATENCY('ConsentManager#ReadOperation')),
+            'consent_manager_write_latency',
+            (GET_LATENCY('ConsentManager#WriteOperation')),
+            'consent_manager_initialization_latency',
+            (GET_LATENCY('ConsentManager#Initialization'))))
     ),
     'app_set_id_metric',
     (
@@ -56,4 +50,18 @@
       SELECT
         RepeatedField(
           AdServicesAdIdMetric('latency', GET_LATENCY('AppSetIdEvent')))
+    ),
+    'odp_metric',
+    (
+      SELECT
+        RepeatedField(
+          OnDevicePersonalizationMetric(
+            'managing_service_initialization_latency',
+            (GET_LATENCY('OdpManagingService#Initialization')),
+            'service_delegate_execute_flow_latency',
+            (GET_LATENCY('OdpManagingServiceDelegate#Execute')),
+            'service_delegate_request_surface_package_latency',
+            (GET_LATENCY('OdpManagingServiceDelegate#RequestSurfacePackage')),
+            'service_delegate_register_web_trigger_latency',
+            (GET_LATENCY('OdpManagingServiceDelegate#RegisterWebTrigger'))))
     ));
diff --git a/src/trace_processor/metrics/sql/android/android_startup.sql b/src/trace_processor/metrics/sql/android/android_startup.sql
index 2033b25..10fa253 100644
--- a/src/trace_processor/metrics/sql/android/android_startup.sql
+++ b/src/trace_processor/metrics/sql/android/android_startup.sql
@@ -194,7 +194,7 @@
       launch_to_main_thread_slice_proto(launches.startup_id, 'bindApplication'),
       'time_activity_manager', (
         SELECT startup_slice_proto(l.ts - launches.ts)
-        FROM internal_startup_events l
+        FROM _startup_events l
         WHERE l.ts BETWEEN launches.ts AND launches.ts + launches.dur
       ),
       'time_post_fork',
diff --git a/src/trace_processor/metrics/sql/android/process_metadata.sql b/src/trace_processor/metrics/sql/android/process_metadata.sql
index f22a05f..855d27f 100644
--- a/src/trace_processor/metrics/sql/android/process_metadata.sql
+++ b/src/trace_processor/metrics/sql/android/process_metadata.sql
@@ -23,7 +23,7 @@
 
 DROP VIEW IF EXISTS uid_package_count;
 CREATE PERFETTO VIEW uid_package_count AS
-SELECT * FROM internal_uid_package_count;
+SELECT * FROM _uid_package_count;
 
 DROP VIEW IF EXISTS process_metadata;
 CREATE PERFETTO VIEW process_metadata AS
diff --git a/src/trace_processor/metrics/sql/android/startup/launches.sql b/src/trace_processor/metrics/sql/android/startup/launches.sql
index cb53fc1..e182af0 100644
--- a/src/trace_processor/metrics/sql/android/startup/launches.sql
+++ b/src/trace_processor/metrics/sql/android/startup/launches.sql
@@ -32,4 +32,4 @@
 
 DROP VIEW IF EXISTS launching_events;
 CREATE PERFETTO VIEW launching_events AS
-SELECT * FROM internal_startup_events;
+SELECT * FROM _startup_events;
diff --git a/src/trace_processor/metrics/sql/chrome/chrome_long_tasks.sql b/src/trace_processor/metrics/sql/chrome/chrome_long_tasks.sql
index 1306984..2ac94b9 100644
--- a/src/trace_processor/metrics/sql/chrome/chrome_long_tasks.sql
+++ b/src/trace_processor/metrics/sql/chrome/chrome_long_tasks.sql
@@ -80,7 +80,7 @@
       mojo.interface_name,
       mojo.ipc_hash,
       mojo.message_type,
-      internal_get_posted_from(s.arg_set_id) as posted_from
+      _get_posted_from(s.arg_set_id) as posted_from
     FROM long_tasks_extracted_slices mojo
     JOIN slice s ON mojo.id = s.id
   )
@@ -90,7 +90,7 @@
     WHEN interface_name IS NOT NULL
       THEN printf('%s %s (hash=%d)', interface_name, message_type, ipc_hash)
     ELSE
-      internal_format_scheduler_task_name(posted_from)
+      _format_scheduler_task_name(posted_from)
     END AS full_name,
   interface_name IS NOT NULL AS is_mojo
 FROM raw_extracted_values;
@@ -105,7 +105,7 @@
   -- Select UI thread BeginMainFrames frames.
   root_slices AS (
     SELECT *
-    FROM INTERNAL_SELECT_BEGIN_MAIN_FRAME_JAVA_SLICES('LongTaskTracker')
+    FROM _SELECT_BEGIN_MAIN_FRAME_JAVA_SLICES('LongTaskTracker')
     UNION ALL
     SELECT id, "Choreographer" as kind, ts, dur, name
     FROM slice
@@ -117,7 +117,7 @@
     SELECT
       s1.id, s1.kind, s2.name AS java_view_name
     FROM root_slices s1
-    JOIN internal_chrome_java_views s2
+    JOIN _chrome_java_views s2
       ON (
         s1.ts < s2.ts AND s1.ts + s1.dur > s2.ts + s2.dur)
   )
@@ -136,7 +136,7 @@
   java_views_tasks AS (
     SELECT
       printf('%s(java_views=%s)', kind, java_views) as full_name,
-      internal_get_java_views_task_type(kind) AS task_type,
+      _get_java_views_task_type(kind) AS task_type,
       id
     FROM long_task_slices_with_java_views
     WHERE kind = "SingleThreadProxy::BeginMainFrame"
@@ -154,12 +154,12 @@
       -- NOTE: unless Navigation category is enabled and recorded on the same
       -- track as the LongTaskTracker slice, frame type will always be unknown.
       printf('%s (%s)',
-        internal_human_readable_navigation_task_name(full_name),
-        IFNULL(internal_extract_frame_type(id), 'unknown frame type')) AS full_name,
+        _human_readable_navigation_task_name(full_name),
+        IFNULL(_extract_frame_type(id), 'unknown frame type')) AS full_name,
       'navigation_task' AS task_type,
       id
     FROM scheduler_tasks_with_mojo
-    WHERE internal_human_readable_navigation_task_name(full_name) IS NOT NULL
+    WHERE _human_readable_navigation_task_name(full_name) IS NOT NULL
   )
 SELECT
   COALESCE(s4.full_name, s3.full_name, s2.full_name, s1.full_name) AS full_name,
@@ -174,7 +174,7 @@
 -- LongTaskTracker slice, so join them separately.
 SELECT
   printf('%s(java_views=%s)', kind, java_views) as full_name,
-  internal_get_java_views_task_type(kind) AS task_type,
+  _get_java_views_task_type(kind) AS task_type,
   id
 FROM long_task_slices_with_java_views
 WHERE kind = "Choreographer";
diff --git a/src/trace_processor/metrics/sql/chrome/chrome_slice_names.sql b/src/trace_processor/metrics/sql/chrome/chrome_slice_names.sql
index 968159b..05a9ae6 100644
--- a/src/trace_processor/metrics/sql/chrome/chrome_slice_names.sql
+++ b/src/trace_processor/metrics/sql/chrome/chrome_slice_names.sql
@@ -21,7 +21,7 @@
   'chrome_version_code', (
     SELECT RepeatedField(int_value)
     FROM metadata
-    WHERE name = 'cr-playstore_version_code'
+    WHERE name GLOB 'cr-*playstore_version_code'
     ORDER BY int_value
   ),
   'slice_name', (
diff --git a/src/trace_processor/metrics/sql/chrome/gesture_jank.sql b/src/trace_processor/metrics/sql/chrome/gesture_jank.sql
index 253bfde..53562b9 100644
--- a/src/trace_processor/metrics/sql/chrome/gesture_jank.sql
+++ b/src/trace_processor/metrics/sql/chrome/gesture_jank.sql
@@ -206,10 +206,10 @@
 CREATE PERFETTO VIEW {{prefix}}_jank_maybe_null_prev_and_next AS
 SELECT
   *,
-  internal_is_janky_frame({{id_field}}, prev_{{id_field}},
+    _is_janky_frame({{id_field}}, prev_{{id_field}},
     prev_ts, begin_ts, maybe_gesture_end,
     gesture_frames_exact, prev_gesture_frames_exact) AS prev_jank,
-  internal_is_janky_frame({{id_field}}, next_{{id_field}},
+    _is_janky_frame({{id_field}}, next_{{id_field}},
     next_ts, begin_ts, maybe_gesture_end,
     gesture_frames_exact, next_gesture_frames_exact) AS next_jank
 FROM {{prefix}}_jank_maybe_null_prev_and_next_without_precompute
@@ -233,7 +233,7 @@
   (next_jank IS NOT NULL AND next_jank)
   OR (prev_jank IS NOT NULL AND prev_jank)
   AS jank,
-  internal_jank_budget(gesture_frames_exact, prev_gesture_frames_exact,
+  _jank_budget(gesture_frames_exact, prev_gesture_frames_exact,
     next_gesture_frames_exact) * avg_vsync_interval AS jank_budget,
   *
 FROM {{prefix}}_jank_maybe_null_prev_and_next
diff --git a/src/trace_processor/perfetto_sql/engine/perfetto_sql_engine.cc b/src/trace_processor/perfetto_sql/engine/perfetto_sql_engine.cc
index bbbd7e4..0ccc219 100644
--- a/src/trace_processor/perfetto_sql/engine/perfetto_sql_engine.cc
+++ b/src/trace_processor/perfetto_sql/engine/perfetto_sql_engine.cc
@@ -17,25 +17,33 @@
 #include "src/trace_processor/perfetto_sql/engine/perfetto_sql_engine.h"
 
 #include <cctype>
+#include <cstddef>
+#include <cstdint>
 #include <memory>
 #include <optional>
 #include <string>
+#include <utility>
 #include <variant>
 #include <vector>
 
+#include "perfetto/base/logging.h"
 #include "perfetto/base/status.h"
 #include "perfetto/ext/base/status_or.h"
 #include "perfetto/ext/base/string_utils.h"
 #include "perfetto/ext/base/string_view.h"
+#include "src/trace_processor/db/runtime_table.h"
+#include "src/trace_processor/db/table.h"
 #include "src/trace_processor/perfetto_sql/engine/created_function.h"
 #include "src/trace_processor/perfetto_sql/engine/function_util.h"
 #include "src/trace_processor/perfetto_sql/engine/perfetto_sql_parser.h"
 #include "src/trace_processor/perfetto_sql/engine/perfetto_sql_preprocessor.h"
 #include "src/trace_processor/perfetto_sql/engine/runtime_table_function.h"
+#include "src/trace_processor/perfetto_sql/intrinsics/table_functions/static_table_function.h"
 #include "src/trace_processor/sqlite/db_sqlite_table.h"
 #include "src/trace_processor/sqlite/scoped_db.h"
 #include "src/trace_processor/sqlite/sql_source.h"
 #include "src/trace_processor/sqlite/sqlite_engine.h"
+#include "src/trace_processor/sqlite/sqlite_table.h"
 #include "src/trace_processor/tp_metatrace.h"
 #include "src/trace_processor/util/status_macros.h"
 
@@ -181,9 +189,10 @@
 }
 
 void PerfettoSqlEngine::RegisterStaticTable(const Table& table,
-                                            const std::string& table_name) {
-  auto context =
-      std::make_unique<DbSqliteTable::Context>(query_cache_.get(), &table);
+                                            const std::string& table_name,
+                                            Table::Schema schema) {
+  auto context = std::make_unique<DbSqliteTable::Context>(
+      query_cache_.get(), &table, std::move(schema));
   static_tables_.Insert(table_name, &table);
   engine_->RegisterVirtualTableModule<DbSqliteTable>(
       table_name, std::move(context), SqliteTable::kEponymousOnly, false);
@@ -403,7 +412,7 @@
                                       "CREATE PERFETTO TABLE"));
 
   size_t column_count = column_names.size();
-  auto table = std::make_unique<RuntimeTable>(pool_, std::move(column_names));
+  RuntimeTable::Builder builder(pool_, std::move(column_names));
   uint32_t rows = 0;
   int res;
   for (res = sqlite3_step(stmt.sqlite_stmt()); res == SQLITE_ROW;
@@ -412,18 +421,18 @@
       int int_i = static_cast<int>(i);
       switch (sqlite3_column_type(stmt.sqlite_stmt(), int_i)) {
         case SQLITE_NULL:
-          RETURN_IF_ERROR(table->AddNull(i));
+          RETURN_IF_ERROR(builder.AddNull(i));
           break;
         case SQLITE_INTEGER:
-          RETURN_IF_ERROR(table->AddInteger(
+          RETURN_IF_ERROR(builder.AddInteger(
               i, sqlite3_column_int64(stmt.sqlite_stmt(), int_i)));
           break;
         case SQLITE_FLOAT:
-          RETURN_IF_ERROR(table->AddFloat(
+          RETURN_IF_ERROR(builder.AddFloat(
               i, sqlite3_column_double(stmt.sqlite_stmt(), int_i)));
           break;
         case SQLITE_TEXT: {
-          RETURN_IF_ERROR(table->AddText(
+          RETURN_IF_ERROR(builder.AddText(
               i, reinterpret_cast<const char*>(
                      sqlite3_column_text(stmt.sqlite_stmt(), int_i))));
           break;
@@ -442,7 +451,7 @@
                            create_table.name.c_str(),
                            sqlite3_errmsg(engine_->db()));
   }
-  RETURN_IF_ERROR(table->AddColumnsAndOverlays(rows));
+  ASSIGN_OR_RETURN(auto table, std::move(builder).Build(rows));
 
   if (runtime_tables_.Find(create_table.name)) {
     if (!create_table.replace) {
diff --git a/src/trace_processor/perfetto_sql/engine/perfetto_sql_engine.h b/src/trace_processor/perfetto_sql/engine/perfetto_sql_engine.h
index 5d47e50..87fd7e7 100644
--- a/src/trace_processor/perfetto_sql/engine/perfetto_sql_engine.h
+++ b/src/trace_processor/perfetto_sql/engine/perfetto_sql_engine.h
@@ -20,12 +20,14 @@
 #include <cstdint>
 #include <memory>
 #include <optional>
+#include <string>
 
 #include "perfetto/base/logging.h"
 #include "perfetto/base/status.h"
 #include "perfetto/ext/base/flat_hash_map.h"
 #include "perfetto/ext/base/status_or.h"
 #include "src/trace_processor/db/runtime_table.h"
+#include "src/trace_processor/db/table.h"
 #include "src/trace_processor/perfetto_sql/engine/perfetto_sql_parser.h"
 #include "src/trace_processor/perfetto_sql/engine/perfetto_sql_preprocessor.h"
 #include "src/trace_processor/perfetto_sql/engine/runtime_table_function.h"
@@ -118,7 +120,9 @@
 
   // Registers a trace processor C++ table with SQLite with an SQL name of
   // |name|.
-  void RegisterStaticTable(const Table&, const std::string& name);
+  void RegisterStaticTable(const Table&,
+                           const std::string& name,
+                           Table::Schema schema);
 
   // Registers a trace processor C++ table function with SQLite.
   void RegisterStaticTableFunction(std::unique_ptr<StaticTableFunction> fn);
diff --git a/src/trace_processor/perfetto_sql/intrinsics/table_functions/BUILD.gn b/src/trace_processor/perfetto_sql/intrinsics/table_functions/BUILD.gn
index d4dce0b..631942d 100644
--- a/src/trace_processor/perfetto_sql/intrinsics/table_functions/BUILD.gn
+++ b/src/trace_processor/perfetto_sql/intrinsics/table_functions/BUILD.gn
@@ -25,6 +25,8 @@
     "connected_flow.h",
     "descendant.cc",
     "descendant.h",
+    "dfs.cc",
+    "dfs.h",
     "dominator_tree.cc",
     "dominator_tree.h",
     "experimental_annotated_stack.cc",
diff --git a/src/trace_processor/perfetto_sql/intrinsics/table_functions/dfs.cc b/src/trace_processor/perfetto_sql/intrinsics/table_functions/dfs.cc
new file mode 100644
index 0000000..05da254
--- /dev/null
+++ b/src/trace_processor/perfetto_sql/intrinsics/table_functions/dfs.cc
@@ -0,0 +1,172 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "src/trace_processor/perfetto_sql/intrinsics/table_functions/dfs.h"
+
+#include <algorithm>
+#include <cstddef>
+#include <cstdint>
+#include <memory>
+#include <optional>
+#include <string>
+#include <utility>
+#include <vector>
+
+#include "perfetto/base/logging.h"
+#include "perfetto/base/status.h"
+#include "perfetto/ext/base/status_or.h"
+#include "perfetto/protozero/proto_decoder.h"
+#include "perfetto/trace_processor/basic_types.h"
+#include "protos/perfetto/trace_processor/metrics_impl.pbzero.h"
+#include "src/trace_processor/containers/string_pool.h"
+#include "src/trace_processor/db/column.h"
+#include "src/trace_processor/db/table.h"
+#include "src/trace_processor/perfetto_sql/intrinsics/table_functions/tables_py.h"
+#include "src/trace_processor/util/status_macros.h"
+
+namespace perfetto::trace_processor {
+namespace tables {
+DfsTable::~DfsTable() = default;
+}  // namespace tables
+
+namespace {
+
+using Destinations = std::vector<uint32_t>;
+
+base::StatusOr<std::vector<Destinations>> ParseSourceToDestionationsMap(
+    protos::pbzero::RepeatedBuilderResult::Decoder& source,
+    protos::pbzero::RepeatedBuilderResult::Decoder& dest) {
+  std::vector<Destinations> source_to_destinations_map;
+  bool parse_error = false;
+  auto source_node_ids = source.int_values(&parse_error);
+  auto dest_node_ids = dest.int_values(&parse_error);
+  for (; source_node_ids && dest_node_ids; ++source_node_ids, ++dest_node_ids) {
+    source_to_destinations_map.resize(
+        std::max(source_to_destinations_map.size(),
+                 std::max(static_cast<size_t>(*source_node_ids + 1),
+                          static_cast<size_t>(*dest_node_ids + 1))));
+    source_to_destinations_map[static_cast<uint32_t>(*source_node_ids)]
+        .push_back(static_cast<uint32_t>(*dest_node_ids));
+  }
+  if (parse_error) {
+    return base::ErrStatus("Failed while parsing source or dest ids");
+  }
+  if (static_cast<bool>(source_node_ids) != static_cast<bool>(dest_node_ids)) {
+    return base::ErrStatus(
+        "dfs: length of source and destination columns is not the same");
+  }
+  return source_to_destinations_map;
+}
+
+void DfsImpl(tables::DfsTable* table,
+             const std::vector<Destinations>& source_to_destinations_map,
+             std::vector<uint8_t>& seen_node_ids,
+             uint32_t id,
+             std::optional<uint32_t> parent_id) {
+  if (seen_node_ids[id]) {
+    return;
+  }
+  seen_node_ids[id] = true;
+
+  tables::DfsTable::Row row;
+  row.node_id = id;
+  row.parent_node_id = parent_id;
+  table->Insert(row);
+
+  PERFETTO_DCHECK(id < source_to_destinations_map.size());
+  for (uint32_t dest : source_to_destinations_map[id]) {
+    DfsImpl(table, source_to_destinations_map, seen_node_ids, dest, id);
+  }
+}
+
+}  // namespace
+
+Dfs::Dfs(StringPool* pool) : pool_(pool) {}
+Dfs::~Dfs() = default;
+
+Table::Schema Dfs::CreateSchema() {
+  return tables::DfsTable::ComputeStaticSchema();
+}
+
+std::string Dfs::TableName() {
+  return tables::DfsTable::Name();
+}
+
+uint32_t Dfs::EstimateRowCount() {
+  // TODO(lalitm): improve this estimate.
+  return 1024;
+}
+
+base::StatusOr<std::unique_ptr<Table>> Dfs::ComputeTable(
+    const std::vector<SqlValue>& arguments) {
+  PERFETTO_CHECK(arguments.size() == 3);
+
+  const SqlValue& raw_source_ids = arguments[0];
+  const SqlValue& raw_dest_ids = arguments[1];
+  const SqlValue& raw_start_node = arguments[2];
+  if (raw_source_ids.is_null() && raw_dest_ids.is_null() &&
+      raw_start_node.is_null()) {
+    return std::unique_ptr<Table>(std::make_unique<tables::DfsTable>(pool_));
+  }
+  if (raw_source_ids.is_null() || raw_dest_ids.is_null() ||
+      raw_start_node.is_null()) {
+    return base::ErrStatus(
+        "dfs: either all arguments should be null or none should be");
+  }
+  if (raw_source_ids.type != SqlValue::kBytes) {
+    return base::ErrStatus("dfs: source_node_ids should be a repeated field");
+  }
+  if (raw_dest_ids.type != SqlValue::kBytes) {
+    return base::ErrStatus("dfs: dest_node_ids should be a repeated field");
+  }
+  if (raw_start_node.type != SqlValue::kLong) {
+    return base::ErrStatus("dfs: start_node_id should be an integer");
+  }
+
+  protos::pbzero::ProtoBuilderResult::Decoder proto_source_ids(
+      static_cast<const uint8_t*>(raw_source_ids.AsBytes()),
+      raw_source_ids.bytes_count);
+  if (!proto_source_ids.is_repeated()) {
+    return base::ErrStatus(
+        "dfs: source_node_ids is not generated by RepeatedField function");
+  }
+  protos::pbzero::RepeatedBuilderResult::Decoder source_ids(
+      proto_source_ids.repeated());
+
+  protos::pbzero::ProtoBuilderResult::Decoder proto_dest_ids(
+      static_cast<const uint8_t*>(raw_dest_ids.AsBytes()),
+      raw_dest_ids.bytes_count);
+  if (!proto_dest_ids.is_repeated()) {
+    return base::ErrStatus(
+        "dfs: dest_node_ids is not generated by RepeatedField function");
+  }
+  protos::pbzero::RepeatedBuilderResult::Decoder dest_ids(
+      proto_dest_ids.repeated());
+
+  ASSIGN_OR_RETURN(auto map,
+                   ParseSourceToDestionationsMap(source_ids, dest_ids));
+  uint32_t start_node_id = static_cast<uint32_t>(raw_start_node.AsLong());
+  if (start_node_id >= map.size()) {
+    return std::unique_ptr<Table>(std::make_unique<tables::DfsTable>(pool_));
+  }
+
+  std::vector<uint8_t> seen_node_ids(map.size());
+  auto table = std::make_unique<tables::DfsTable>(pool_);
+  DfsImpl(table.get(), map, seen_node_ids, start_node_id, std::nullopt);
+  return std::unique_ptr<Table>(std::move(table));
+}
+
+}  // namespace perfetto::trace_processor
diff --git a/src/trace_processor/perfetto_sql/intrinsics/table_functions/dfs.h b/src/trace_processor/perfetto_sql/intrinsics/table_functions/dfs.h
new file mode 100644
index 0000000..8dad16d
--- /dev/null
+++ b/src/trace_processor/perfetto_sql/intrinsics/table_functions/dfs.h
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef SRC_TRACE_PROCESSOR_PERFETTO_SQL_INTRINSICS_TABLE_FUNCTIONS_DFS_H_
+#define SRC_TRACE_PROCESSOR_PERFETTO_SQL_INTRINSICS_TABLE_FUNCTIONS_DFS_H_
+
+#include <cstdint>
+#include <memory>
+#include <string>
+#include <vector>
+
+#include "perfetto/ext/base/status_or.h"
+#include "perfetto/trace_processor/basic_types.h"
+#include "src/trace_processor/containers/string_pool.h"
+#include "src/trace_processor/db/table.h"
+#include "src/trace_processor/perfetto_sql/intrinsics/table_functions/static_table_function.h"
+
+namespace perfetto::trace_processor {
+
+// An SQL table-function which performs a DFS from a given start node in a graph
+// and returns all the nodes which are reachable from the start node.
+//
+// Arguments:
+//  1) |source_node_ids|: RepeatedBuilderResult proto containing a column of
+//     int64 values corresponding to the source of edges.
+//  2) |dest_node_ids|:  RepeatedBuilderResult proto containing a column of
+//     int64 values corresponding to the destination of edges. This number of
+//     values should be the same as |source_node_ids| with each index in
+//     |source_node_ids| acting as the source for the corresponding index in
+//     |dest_node_ids|.
+//  3) |start_node_id|:  ID of the start node in the graph from which
+//     reachability should be computed.
+//
+// Returns:
+//  A table with the nodes reachable from the start node and their "parent" in
+//  the tree generated by the DFS. The schema of the table
+//  is (node_id int64_t, parent_node_id optional<int64_t>).
+//
+// Note: this function is not intended to be used directly from SQL: instead
+// macros exist in the standard library, wrapping it and making it
+// user-friendly.
+class Dfs : public StaticTableFunction {
+ public:
+  explicit Dfs(StringPool*);
+  virtual ~Dfs() override;
+
+  // StaticTableFunction implementation.
+  Table::Schema CreateSchema() override;
+  std::string TableName() override;
+  uint32_t EstimateRowCount() override;
+  base::StatusOr<std::unique_ptr<Table>> ComputeTable(
+      const std::vector<SqlValue>& arguments) override;
+
+ private:
+  StringPool* pool_ = nullptr;
+};
+
+}  // namespace perfetto::trace_processor
+
+#endif  // SRC_TRACE_PROCESSOR_PERFETTO_SQL_INTRINSICS_TABLE_FUNCTIONS_DFS_H_
diff --git a/src/trace_processor/perfetto_sql/intrinsics/table_functions/experimental_slice_layout_unittest.cc b/src/trace_processor/perfetto_sql/intrinsics/table_functions/experimental_slice_layout_unittest.cc
index d97a569..8d09286 100644
--- a/src/trace_processor/perfetto_sql/intrinsics/table_functions/experimental_slice_layout_unittest.cc
+++ b/src/trace_processor/perfetto_sql/intrinsics/table_functions/experimental_slice_layout_unittest.cc
@@ -55,8 +55,8 @@
       continue;
     }
     for (int64_t j = 0; j < dur; ++j) {
-      size_t y = static_cast<size_t>(layout_depth);
-      size_t x = static_cast<size_t>(ts + j);
+      auto y = static_cast<size_t>(layout_depth);
+      auto x = static_cast<size_t>(ts + j);
       while (lines.size() <= y) {
         lines.push_back("");
       }
diff --git a/src/trace_processor/perfetto_sql/intrinsics/table_functions/tables.py b/src/trace_processor/perfetto_sql/intrinsics/table_functions/tables.py
index 04960b8..f71ab9c 100644
--- a/src/trace_processor/perfetto_sql/intrinsics/table_functions/tables.py
+++ b/src/trace_processor/perfetto_sql/intrinsics/table_functions/tables.py
@@ -154,6 +154,22 @@
         C("in_root_node_id", CppOptional(CppUint32()), flags=ColumnFlag.HIDDEN),
     ])
 
+DFS_TABLE = Table(
+    python_module=__file__,
+    class_name="DfsTable",
+    sql_name="__intrinsic_dfs",
+    columns=[
+        C("node_id", CppUint32()),
+        C("parent_node_id", CppOptional(CppUint32())),
+        C("in_source_node_ids",
+          CppOptional(CppString()),
+          flags=ColumnFlag.HIDDEN),
+        C("in_dest_node_ids", CppOptional(CppString()),
+          flags=ColumnFlag.HIDDEN),
+        C("in_start_node_id", CppOptional(CppUint32()),
+          flags=ColumnFlag.HIDDEN),
+    ])
+
 # Keep this list sorted.
 ALL_TABLES = [
     ANCESTOR_SLICE_BY_STACK_TABLE,
@@ -162,6 +178,7 @@
     CONNECTED_FLOW_TABLE,
     DESCENDANT_SLICE_BY_STACK_TABLE,
     DESCENDANT_SLICE_TABLE,
+    DFS_TABLE,
     DOMINATOR_TREE_TABLE,
     EXPERIMENTAL_ANNOTATED_CALLSTACK_TABLE,
     EXPERIMENTAL_COUNTER_DUR_TABLE,
diff --git a/src/trace_processor/perfetto_sql/stdlib/BUILD.gn b/src/trace_processor/perfetto_sql/stdlib/BUILD.gn
index 26b7093..0f84ae8 100644
--- a/src/trace_processor/perfetto_sql/stdlib/BUILD.gn
+++ b/src/trace_processor/perfetto_sql/stdlib/BUILD.gn
@@ -22,13 +22,13 @@
     "android",
     "chrome:chrome_sql",
     "common",
-    "experimental",
     "graphs",
     "intervals",
     "linux",
     "pkvm",
     "prelude",
     "sched",
+    "slices",
   ]
   generated_header = "stdlib.h"
   namespace = "stdlib"
diff --git a/src/trace_processor/perfetto_sql/stdlib/android/BUILD.gn b/src/trace_processor/perfetto_sql/stdlib/android/BUILD.gn
index 7236654..96e2d1a 100644
--- a/src/trace_processor/perfetto_sql/stdlib/android/BUILD.gn
+++ b/src/trace_processor/perfetto_sql/stdlib/android/BUILD.gn
@@ -18,9 +18,11 @@
   deps = [ "startup" ]
   sources = [
     "anrs.sql",
+    "app_process_starts.sql",
     "battery.sql",
     "battery_stats.sql",
     "binder.sql",
+    "broadcasts.sql",
     "dvfs.sql",
     "io.sql",
     "monitor_contention.sql",
diff --git a/src/trace_processor/perfetto_sql/stdlib/android/app_process_starts.sql b/src/trace_processor/perfetto_sql/stdlib/android/app_process_starts.sql
new file mode 100644
index 0000000..45c6e93
--- /dev/null
+++ b/src/trace_processor/perfetto_sql/stdlib/android/app_process_starts.sql
@@ -0,0 +1,175 @@
+--
+-- Copyright 2024 The Android Open Source Project
+--
+-- Licensed under the Apache License, Version 2.0 (the "License");
+-- you may not use this file except in compliance with the License.
+-- You may obtain a copy of the License at
+--
+--     https://www.apache.org/licenses/LICENSE-2.0
+--
+-- Unless required by applicable law or agreed to in writing, software
+-- distributed under the License is distributed on an "AS IS" BASIS,
+-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+-- See the License for the specific language governing permissions and
+-- limitations under the License.
+--
+INCLUDE PERFETTO MODULE common.slices;
+
+-- All process starts.
+CREATE PERFETTO VIEW _proc_start
+AS
+SELECT ts, dur, TRIM(SUBSTR(name, 12)) AS process_name
+FROM thread_slice
+WHERE name GLOB 'Start proc:*' AND process_name = 'system_server';
+
+-- Broadcast, service and activity cold starts.
+CREATE PERFETTO TABLE _cold_start
+AS
+WITH
+  lifecycle_slice AS (
+    SELECT
+      id,
+      ts AS intent_ts,
+      dur AS intent_dur,
+      track_id,
+      name,
+      upid,
+      process_name,
+      pid,
+      utid,
+      CASE
+        WHEN name GLOB 'performCreate:*' THEN 'activity'
+        WHEN name GLOB 'serviceCreate:*' THEN 'service'
+        WHEN name GLOB 'broadcastReceiveComp:*' THEN 'broadcast'
+      END AS reason,
+            CASE
+        WHEN name GLOB 'performCreate:*' THEN STR_SPLIT(name, 'performCreate:', 1)
+        WHEN name GLOB 'serviceCreate:*' THEN STR_SPLIT(STR_SPLIT(name, '=', 2), ' ', 0)
+        WHEN name GLOB 'broadcastReceive*' THEN STR_SPLIT(name, 'broadcastReceiveComp:', 1)
+        END AS intent
+    FROM thread_slice slice
+    WHERE
+      name GLOB 'bindApplication'
+      OR name GLOB 'performCreate:*'
+      OR name GLOB 'serviceCreate:*'
+      OR name GLOB 'broadcastReceiveComp:*'
+    ORDER BY ts
+  ),
+  cold_start AS (
+    SELECT
+      *,
+      lag(name) OVER (PARTITION BY track_id ORDER BY intent_ts) AS bind_app_name,
+      lag(intent_ts) OVER (PARTITION BY track_id ORDER BY intent_ts) AS bind_app_ts,
+      lag(intent_dur) OVER (PARTITION BY track_id ORDER BY intent_ts) AS bind_app_dur,
+      lag(id) OVER (PARTITION BY track_id ORDER BY intent_ts) AS bind_app_id
+    FROM lifecycle_slice
+  )
+SELECT * FROM cold_start WHERE bind_app_name = 'bindApplication';
+
+-- Join Broadcast, service and activity cold starts with process starts.
+CREATE PERFETTO VIEW _cold_proc_start
+AS
+SELECT
+  cold_start.*,
+  MAX(proc_start.ts) AS proc_start_ts,
+  proc_start.dur AS proc_start_dur,
+  cold_start.intent_ts - MAX(proc_start.ts) + cold_start.intent_dur AS total_dur
+FROM _cold_start cold_start
+JOIN _proc_start proc_start
+  ON proc_start.process_name = cold_start.process_name AND cold_start.intent_ts > proc_start.ts
+GROUP BY cold_start.upid;
+
+-- Provider cold starts.
+CREATE PERFETTO TABLE _provider_start
+AS
+WITH
+  provider_start AS (
+    SELECT id AS bind_app_id FROM slice WHERE name = 'bindApplication'
+    EXCEPT
+    SELECT bind_app_id FROM _cold_start
+  )
+SELECT * FROM provider_start JOIN thread_slice ON id = bind_app_id;
+
+-- Join Provider cold starts with process starts.
+CREATE PERFETTO VIEW _provider_proc_start
+AS
+SELECT
+  cold_start.*,
+  MAX(proc_start.ts) AS proc_start_ts,
+  proc_start.dur AS proc_start_dur,
+  cold_start.ts - MAX(proc_start.ts) + cold_start.dur AS total_dur
+FROM _provider_start cold_start
+JOIN _proc_start proc_start
+  ON proc_start.process_name = cold_start.process_name AND cold_start.ts > proc_start.ts
+GROUP BY cold_start.upid;
+
+-- TODO(b/323052521): Refactor this table name to android_startups.
+-- All app cold starts with information about their cold start reason:
+-- broadcast, service, activity or provider.
+CREATE PERFETTO TABLE _android_app_process_starts(
+  -- Slice id of the bindApplication slice in the app. Uniquely identifies a process start.
+  start_id INT,
+  -- Slice id of intent received in the app.
+  id INT,
+  -- Track id of the intent received in the app.
+  track_id INT,
+  -- Name of the process receiving the intent.
+  process_name STRING,
+  -- Pid of the process receiving the intent.
+  pid INT,
+  -- Upid of the process receiving the intent.
+  upid INT,
+  -- Intent action or component responsible for the cold start.
+  intent STRING,
+  -- Process start reason: activity, broadcast, service or provider.
+  reason STRING,
+  -- Timestamp the process start was dispatched from system_server.
+  proc_start_ts INT,
+  -- Duration to dispatch the process start from system_server.
+  proc_start_dur INT,
+  -- Timestamp the bindApplication started in the app.
+  bind_app_ts INT,
+  -- Duration to complete bindApplication in the app.
+  bind_app_dur INT,
+  -- Timestamp the Intent was received in the app.
+  intent_ts INT,
+  -- Duration to handle intent in the app.
+  intent_dur INT,
+  -- Total duration from proc_start dispatched to intent completed.
+  total_dur INT
+) AS
+SELECT
+  bind_app_id AS start_id,
+  id,
+  track_id,
+  process_name,
+  pid,
+  upid,
+  intent,
+  reason,
+  proc_start_ts,
+  proc_start_dur,
+  bind_app_ts,
+  bind_app_dur,
+  intent_ts,
+  intent_dur,
+  total_dur
+FROM _cold_proc_start
+UNION ALL
+SELECT
+  bind_app_id AS start_id,
+  NULL AS id,
+  NULL AS track_id,
+  process_name,
+  pid,
+  upid,
+  NULL AS intent,
+  'provider' AS reason,
+  proc_start_ts,
+  proc_start_dur,
+  ts AS bind_app_ts,
+  dur AS bind_app_dur,
+  NULL AS intent_ts,
+  NULL AS intent_dur,
+  total_dur
+FROM _provider_proc_start;
diff --git a/src/trace_processor/perfetto_sql/stdlib/android/binder.sql b/src/trace_processor/perfetto_sql/stdlib/android/binder.sql
index c512cf6..f4a2476 100644
--- a/src/trace_processor/perfetto_sql/stdlib/android/binder.sql
+++ b/src/trace_processor/perfetto_sql/stdlib/android/binder.sql
@@ -42,7 +42,7 @@
   process_name,
   slice_name;
 
-CREATE PERFETTO TABLE internal_binder_txn_merged AS
+CREATE PERFETTO TABLE _binder_txn_merged AS
 WITH maybe_broken_binder_txn AS (
   -- Fetch the broken binder txns first, i.e, the txns that have children slices
   -- They may be broken because synchronous txns are typically blocked sleeping while
@@ -157,7 +157,7 @@
   binder_txn_id,
   binder_reply_id;
 
-CREATE TABLE internal_oom_score AS
+CREATE TABLE _oom_score AS
   SELECT
     process.upid,
     CAST(c.value AS INT) AS value,
@@ -168,7 +168,7 @@
          JOIN process USING (upid)
    WHERE t.name = 'oom_score_adj';
 
-CREATE INDEX internal_oom_score_idx ON internal_oom_score(upid, ts);
+CREATE INDEX _oom_score_idx ON _oom_score(upid, ts);
 
 -- Breakdown synchronous binder transactions per txn.
 -- It returns data about the client and server ends of every binder transaction.
@@ -223,33 +223,33 @@
   server_oom_score INT
 ) AS
 SELECT binder.*, client_oom.value AS client_oom_score, server_oom.value AS server_oom_score
-FROM internal_binder_txn_merged binder
-LEFT JOIN internal_oom_score client_oom
+FROM _binder_txn_merged binder
+LEFT JOIN _oom_score client_oom
   ON
     binder.client_upid = client_oom.upid
     AND binder.client_ts BETWEEN client_oom.ts AND client_oom.end_ts
-LEFT JOIN internal_oom_score server_oom
+LEFT JOIN _oom_score server_oom
   ON
     binder.server_upid = server_oom.upid
     AND binder.server_ts BETWEEN server_oom.ts AND server_oom.end_ts;
 
-CREATE PERFETTO VIEW internal_binder_txn
+CREATE PERFETTO VIEW _binder_txn
 AS
 SELECT client_ts AS ts, client_dur AS dur, client_utid AS utid, *
 FROM android_sync_binder_metrics_by_txn;
 
-CREATE PERFETTO VIEW internal_binder_reply
+CREATE PERFETTO VIEW _binder_reply
 AS
 SELECT server_ts AS ts, server_dur AS dur, server_utid AS utid, *
 FROM android_sync_binder_metrics_by_txn;
 
-CREATE VIRTUAL TABLE internal_sp_binder_txn_thread_state
+CREATE VIRTUAL TABLE _sp_binder_txn_thread_state
 USING
-  SPAN_JOIN(internal_binder_txn PARTITIONED utid, thread_state PARTITIONED utid);
+  SPAN_JOIN(_binder_txn PARTITIONED utid, thread_state PARTITIONED utid);
 
-CREATE VIRTUAL TABLE internal_sp_binder_reply_thread_state
+CREATE VIRTUAL TABLE _sp_binder_reply_thread_state
 USING
-  SPAN_JOIN(internal_binder_reply PARTITIONED utid, thread_state PARTITIONED utid);
+  SPAN_JOIN(_binder_reply PARTITIONED utid, thread_state PARTITIONED utid);
 
 -- Aggregated thread_states on the client and server side per binder txn
 -- This builds on the data from |android_sync_binder_metrics_by_txn| and
@@ -291,7 +291,7 @@
   state AS thread_state,
   SUM(dur) AS thread_state_dur,
   COUNT(dur) AS thread_state_count
-FROM internal_sp_binder_txn_thread_state
+FROM _sp_binder_txn_thread_state
 GROUP BY binder_txn_id, binder_reply_id, thread_state_type, thread_state
 UNION ALL
 SELECT
@@ -305,7 +305,7 @@
   state AS thread_state,
   SUM(dur) AS thread_state_dur,
   COUNT(dur) AS thread_state_count
-FROM internal_sp_binder_reply_thread_state
+FROM _sp_binder_reply_thread_state
 GROUP BY binder_txn_id, binder_reply_id, thread_state_type, thread_state;
 
 -- Aggregated blocked_functions on the client and server side per binder txn
@@ -348,7 +348,7 @@
   blocked_function,
   SUM(dur) AS blocked_function_dur,
   COUNT(dur) AS blocked_function_count
-FROM internal_sp_binder_txn_thread_state
+FROM _sp_binder_txn_thread_state
 WHERE blocked_function IS NOT NULL
 GROUP BY binder_txn_id, binder_reply_id, blocked_function
 UNION ALL
@@ -363,11 +363,11 @@
   blocked_function,
   SUM(dur) AS blocked_function_dur,
   COUNT(dur) AS blocked_function_count
-FROM internal_sp_binder_reply_thread_state
+FROM _sp_binder_reply_thread_state
 WHERE blocked_function IS NOT NULL
 GROUP BY binder_txn_id, binder_reply_id, blocked_function;
 
-CREATE TABLE internal_async_binder_reply AS
+CREATE TABLE _async_binder_reply AS
 WITH async_reply AS MATERIALIZED (
   SELECT id, ts, dur, track_id, name
   FROM slice
@@ -381,7 +381,7 @@
     LEAD(dur) OVER (PARTITION BY track_id ORDER BY ts) AS next_dur
     FROM async_reply;
 
-CREATE TABLE internal_binder_async_txn_raw AS
+CREATE TABLE _binder_async_txn_raw AS
 SELECT
   slice.id AS binder_txn_id,
   process.name AS client_process,
@@ -402,7 +402,7 @@
   USING (upid)
 WHERE slice.name = 'binder transaction async';
 
-CREATE PERFETTO TABLE internal_binder_async_txn AS
+CREATE PERFETTO TABLE _binder_async_txn AS
 SELECT
   IIF(binder_reply.next_name = 'binder async rcv', NULL, binder_reply.next_name) AS aidl_name,
   IIF(binder_reply.next_name = 'binder async rcv', NULL, binder_reply.next_ts) AS aidl_ts,
@@ -417,10 +417,10 @@
   reply_process.pid AS server_pid,
   binder_reply.ts AS server_ts,
   binder_reply.dur AS server_dur
-FROM internal_binder_async_txn_raw binder_txn
+FROM _binder_async_txn_raw binder_txn
 JOIN flow binder_flow
   ON binder_txn.binder_txn_id = binder_flow.slice_out
-JOIN internal_async_binder_reply binder_reply
+JOIN _async_binder_reply binder_reply
   ON binder_flow.slice_in = binder_reply.id
 JOIN thread_track reply_thread_track
   ON binder_reply.track_id = reply_thread_track.id
@@ -483,12 +483,12 @@
   server_oom_score INT
 ) AS
 SELECT binder.*, client_oom.value AS client_oom_score, server_oom.value AS server_oom_score
-FROM internal_binder_async_txn binder
-LEFT JOIN internal_oom_score client_oom
+FROM _binder_async_txn binder
+LEFT JOIN _oom_score client_oom
   ON
     binder.client_upid = client_oom.upid
     AND binder.client_ts BETWEEN client_oom.ts AND client_oom.end_ts
-LEFT JOIN internal_oom_score server_oom
+LEFT JOIN _oom_score server_oom
   ON
     binder.server_upid = server_oom.upid
     AND binder.server_ts BETWEEN server_oom.ts AND server_oom.end_ts;
diff --git a/src/trace_processor/perfetto_sql/stdlib/experimental/android_broadcast.sql b/src/trace_processor/perfetto_sql/stdlib/android/broadcasts.sql
similarity index 95%
rename from src/trace_processor/perfetto_sql/stdlib/experimental/android_broadcast.sql
rename to src/trace_processor/perfetto_sql/stdlib/android/broadcasts.sql
index f35b751..3afe0bf 100644
--- a/src/trace_processor/perfetto_sql/stdlib/experimental/android_broadcast.sql
+++ b/src/trace_processor/perfetto_sql/stdlib/android/broadcasts.sql
@@ -16,7 +16,7 @@
 
 -- Provides a list of broadcast names and processes they were sent to by the
 -- system_server process on U+ devices.
-CREATE PERFETTO VIEW experimental_android_broadcasts_minsdk_u(
+CREATE PERFETTO VIEW _android_broadcasts_minsdk_u(
   -- The name of the broadcast type which was sent.
   type STRING,
   -- The process name the broadcast was sent to.
diff --git a/src/trace_processor/perfetto_sql/stdlib/android/monitor_contention.sql b/src/trace_processor/perfetto_sql/stdlib/android/monitor_contention.sql
index d67e323..32b818a 100644
--- a/src/trace_processor/perfetto_sql/stdlib/android/monitor_contention.sql
+++ b/src/trace_processor/perfetto_sql/stdlib/android/monitor_contention.sql
@@ -105,7 +105,7 @@
 RETURNS STRING AS
 SELECT STR_SPLIT(STR_SPLIT($slice_name, ")(", 2), ")", 0);
 
-CREATE PERFETTO TABLE internal_valid_android_monitor_contention AS
+CREATE PERFETTO TABLE _valid_android_monitor_contention AS
 SELECT slice.id AS id
 FROM slice
 LEFT JOIN slice child
@@ -178,7 +178,7 @@
 LEFT JOIN ANCESTOR_SLICE(slice.id) binder_reply ON binder_reply.name = 'binder reply'
 LEFT JOIN thread_track binder_reply_thread_track ON binder_reply.track_id = binder_reply_thread_track.id
 LEFT JOIN thread binder_reply_thread ON binder_reply_thread_track.utid = binder_reply_thread.utid
-JOIN internal_valid_android_monitor_contention ON internal_valid_android_monitor_contention.id = slice.id
+JOIN _valid_android_monitor_contention ON _valid_android_monitor_contention.id = slice.id
 JOIN thread blocking_thread ON blocking_thread.tid = blocking_tid AND blocking_thread.upid = thread.upid
 WHERE slice.name GLOB 'monitor contention*'
   AND slice.dur != -1
@@ -186,30 +186,30 @@
   AND short_blocked_method IS NOT NULL
 GROUP BY slice.id;
 
-CREATE INDEX internal_android_monitor_contention_idx
+CREATE INDEX _android_monitor_contention_idx
   ON android_monitor_contention (blocking_utid, ts);
 
 -- Monitor contention slices that are blocked by another monitor contention slice.
 -- They will have a |parent_id| field which is the id of the slice they are blocked by.
-CREATE PERFETTO TABLE internal_children AS
+CREATE PERFETTO TABLE _children AS
 SELECT parent.id AS parent_id, child.* FROM android_monitor_contention child
 JOIN android_monitor_contention parent ON parent.blocked_utid = child.blocking_utid
 AND child.ts BETWEEN parent.ts AND parent.ts + parent.dur;
 
 -- Monitor contention slices that are blocking another monitor contention slice.
 -- They will have a |child_id| field which is the id of the slice they are blocking.
-CREATE PERFETTO TABLE internal_parents AS
+CREATE PERFETTO TABLE _parents AS
 SELECT parent.*, child.id AS child_id FROM android_monitor_contention parent
 JOIN android_monitor_contention child ON parent.blocked_utid = child.blocking_utid
 AND child.ts BETWEEN parent.ts AND parent.ts + parent.dur;
 
 -- Monitor contention slices that are neither blocking nor blocked by another monitor contention
 -- slice. They neither have |parent_id| nor |child_id| fields.
-CREATE TABLE internal_isolated AS
+CREATE TABLE _isolated AS
 WITH parents_and_children AS (
- SELECT id FROM internal_children
+ SELECT id FROM _children
  UNION ALL
- SELECT id FROM internal_parents
+ SELECT id FROM _parents
 ), isolated AS (
     SELECT id FROM android_monitor_contention
     EXCEPT
@@ -242,15 +242,15 @@
 -- @column binder_reply_tid Tid of binder reply slice if lock contention was part of a binder txn.
 -- @column child_id Id of monitor contention slice blocked by this contention.
 CREATE TABLE android_monitor_contention_chain AS
-SELECT NULL AS parent_id, *, NULL AS child_id FROM internal_isolated
+SELECT NULL AS parent_id, *, NULL AS child_id FROM _isolated
 UNION ALL
-SELECT c.*, p.child_id FROM internal_children c
-LEFT JOIN internal_parents p USING(id)
+SELECT c.*, p.child_id FROM _children c
+LEFT JOIN _parents p USING(id)
 UNION
-SELECT c.parent_id, p.* FROM internal_parents p
-LEFT JOIN internal_children c USING(id);
+SELECT c.parent_id, p.* FROM _parents p
+LEFT JOIN _children c USING(id);
 
-CREATE INDEX internal_android_monitor_contention_chain_idx
+CREATE INDEX _android_monitor_contention_chain_idx
   ON android_monitor_contention_chain (blocking_method, blocking_utid, ts);
 
 -- First blocked node on a lock, i.e nodes with |waiter_count| = 0. The |dur| here is adjusted
@@ -258,7 +258,7 @@
 -- the lock. That way, the thread state span joins below only compute the thread states where
 -- the blocking thread is actually holding the lock. This avoids counting the time when another
 -- waiter acquired the lock before the first waiter.
-CREATE PERFETTO VIEW internal_first_blocked_contention
+CREATE PERFETTO VIEW _first_blocked_contention
   AS
 SELECT start.id, start.blocking_utid, start.ts, MIN(end.ts + end.dur) - start.ts AS dur
 FROM android_monitor_contention_chain start
@@ -270,7 +270,7 @@
 WHERE start.waiter_count = 0
 GROUP BY start.id;
 
-CREATE PERFETTO VIEW internal_blocking_thread_state
+CREATE PERFETTO VIEW _blocking_thread_state
 AS
 SELECT utid AS blocking_utid, ts, dur, state, blocked_function
 FROM thread_state;
@@ -309,8 +309,8 @@
 -- @column blocked_function Blocked kernel function of the blocking thread.
 CREATE VIRTUAL TABLE android_monitor_contention_chain_thread_state
 USING
-  SPAN_JOIN(internal_first_blocked_contention PARTITIONED blocking_utid,
-            internal_blocking_thread_state PARTITIONED blocking_utid);
+  SPAN_JOIN(_first_blocked_contention PARTITIONED blocking_utid,
+            _blocking_thread_state PARTITIONED blocking_utid);
 
 -- Aggregated thread_states on the 'blocking thread', the thread holding the lock.
 -- This builds on the data from |android_monitor_contention_chain| and
diff --git a/src/trace_processor/perfetto_sql/stdlib/android/process_metadata.sql b/src/trace_processor/perfetto_sql/stdlib/android/process_metadata.sql
index 6ed7232..86c099b 100644
--- a/src/trace_processor/perfetto_sql/stdlib/android/process_metadata.sql
+++ b/src/trace_processor/perfetto_sql/stdlib/android/process_metadata.sql
@@ -15,7 +15,7 @@
 --
 
 -- Count packages by package UID.
-CREATE PERFETTO TABLE internal_uid_package_count AS
+CREATE PERFETTO TABLE _uid_package_count AS
 SELECT uid, COUNT(1) AS cnt
 FROM package_list
 GROUP BY 1;
@@ -51,20 +51,20 @@
     ELSE process.name
   END AS process_name,
   process.android_appid AS uid,
-  CASE WHEN internal_uid_package_count.cnt > 1 THEN TRUE ELSE NULL END AS shared_uid,
+  CASE WHEN _uid_package_count.cnt > 1 THEN TRUE ELSE NULL END AS shared_uid,
   plist.package_name,
   plist.version_code,
   plist.debuggable
 FROM process
-LEFT JOIN internal_uid_package_count ON process.android_appid = internal_uid_package_count.uid
+LEFT JOIN _uid_package_count ON process.android_appid = _uid_package_count.uid
 LEFT JOIN package_list plist
   ON (
     (
       process.android_appid = plist.uid
-      AND internal_uid_package_count.uid = plist.uid
+      AND _uid_package_count.uid = plist.uid
       AND (
         -- unique match
-        internal_uid_package_count.cnt = 1
+        _uid_package_count.cnt = 1
         -- or process name starts with the package name
         OR process.name GLOB plist.package_name || '*')
     )
diff --git a/src/trace_processor/perfetto_sql/stdlib/android/slices.sql b/src/trace_processor/perfetto_sql/stdlib/android/slices.sql
index 40e6ccf..80691bc 100644
--- a/src/trace_processor/perfetto_sql/stdlib/android/slices.sql
+++ b/src/trace_processor/perfetto_sql/stdlib/android/slices.sql
@@ -14,7 +14,7 @@
 -- limitations under the License.
 
 
-CREATE PERFETTO FUNCTION internal_remove_lambda_name(
+CREATE PERFETTO FUNCTION _remove_lambda_name(
 -- Raw slice name containing at least one "$"
   name STRING)
 -- Removes everything after the first "$"
@@ -37,7 +37,6 @@
 RETURNS STRING AS
 SELECT
   CASE
-    WHEN $name GLOB "Lock contention on*" THEN "Lock contention on <...>"
     WHEN $name GLOB "monitor contention with*" THEN "monitor contention with <...>"
     WHEN $name GLOB "SuspendThreadByThreadId*" THEN "SuspendThreadByThreadId <...>"
     WHEN $name GLOB "LoadApkAssetsFd*" THEN "LoadApkAssetsFd <...>"
@@ -49,15 +48,18 @@
     WHEN $name GLOB "OpenDexFilesFromOat*" THEN "OpenDexFilesFromOat"
     WHEN $name GLOB "Open oat file*" THEN "Open oat file"
     WHEN $name GLOB "GC: Wait For*" THEN "Garbage Collector"
+    -- E.g. Lock contention on thread list lock (owner tid: 1665)
+    -- To: Lock contention on thread list lock <...>
+    WHEN $name GLOB "Lock contention on* (*" THEN substr($name, 0, instr($name, "(")) || "<...>"
     -- Top level handlers slices heuristics:
         -- E.g. android.os.Handler: com.android.systemui.qs.external.TileServiceManager$1
         -- To: Handler: com.android.systemui.qs.external.TileServiceManager
-    WHEN $name GLOB "*Handler: *$*" THEN internal_remove_lambda_name(substr($name, instr($name, "Handler:")))
+    WHEN $name GLOB "*Handler: *$*" THEN _remove_lambda_name(substr($name, instr($name, "Handler:")))
         -- E.g. : android.view.ViewRootImpl$ViewRootHandler: com.android.systemui.someClass$enableMarquee$1
         -- To: Handler: android.view.ViewRootImpl
-    WHEN $name GLOB "*.*.*: *$*" THEN "Handler: " || internal_remove_lambda_name(substr($name, ": "))
+    WHEN $name GLOB "*.*.*: *$*" THEN "Handler: " || _remove_lambda_name(substr($name, ": "))
         -- E.g.: android.os.AsyncTask$InternalHandler: #1
         -- To: Handler: android.os.AsyncTask
-    WHEN $name GLOB "*.*$*: #*" THEN "Handler: " || internal_remove_lambda_name($name)
+    WHEN $name GLOB "*.*$*: #*" THEN "Handler: " || _remove_lambda_name($name)
     ELSE $name
   END;
diff --git a/src/trace_processor/perfetto_sql/stdlib/android/startup/BUILD.gn b/src/trace_processor/perfetto_sql/stdlib/android/startup/BUILD.gn
index 68c9bea..8206b4a 100644
--- a/src/trace_processor/perfetto_sql/stdlib/android/startup/BUILD.gn
+++ b/src/trace_processor/perfetto_sql/stdlib/android/startup/BUILD.gn
@@ -16,10 +16,10 @@
 
 perfetto_sql_source_set("startup") {
   sources = [
-    "internal_startup_events.sql",
-    "internal_startups_maxsdk28.sql",
-    "internal_startups_minsdk29.sql",
-    "internal_startups_minsdk33.sql",
+    "startup_events.sql",
     "startups.sql",
+    "startups_maxsdk28.sql",
+    "startups_minsdk29.sql",
+    "startups_minsdk33.sql",
   ]
 }
diff --git a/src/trace_processor/perfetto_sql/stdlib/android/startup/internal_startup_events.sql b/src/trace_processor/perfetto_sql/stdlib/android/startup/startup_events.sql
similarity index 94%
rename from src/trace_processor/perfetto_sql/stdlib/android/startup/internal_startup_events.sql
rename to src/trace_processor/perfetto_sql/stdlib/android/startup/startup_events.sql
index ed2e44d..25d8519 100644
--- a/src/trace_processor/perfetto_sql/stdlib/android/startup/internal_startup_events.sql
+++ b/src/trace_processor/perfetto_sql/stdlib/android/startup/startup_events.sql
@@ -14,7 +14,7 @@
 -- limitations under the License.
 
 -- All activity startup events.
-CREATE PERFETTO TABLE internal_startup_events AS
+CREATE PERFETTO TABLE _startup_events AS
 SELECT
   ts,
   dur,
diff --git a/src/trace_processor/perfetto_sql/stdlib/android/startup/startups.sql b/src/trace_processor/perfetto_sql/stdlib/android/startup/startups.sql
index fa55876..a38c487 100644
--- a/src/trace_processor/perfetto_sql/stdlib/android/startup/startups.sql
+++ b/src/trace_processor/perfetto_sql/stdlib/android/startup/startups.sql
@@ -15,17 +15,17 @@
 
 INCLUDE PERFETTO MODULE common.slices;
 INCLUDE PERFETTO MODULE android.process_metadata;
-INCLUDE PERFETTO MODULE android.startup.internal_startups_maxsdk28;
-INCLUDE PERFETTO MODULE android.startup.internal_startups_minsdk29;
-INCLUDE PERFETTO MODULE android.startup.internal_startups_minsdk33;
+INCLUDE PERFETTO MODULE android.startup.startups_maxsdk28;
+INCLUDE PERFETTO MODULE android.startup.startups_minsdk29;
+INCLUDE PERFETTO MODULE android.startup.startups_minsdk33;
 
 -- Gather all startup data. Populate by different sdks.
-CREATE PERFETTO TABLE internal_all_startups AS
-SELECT sdk, startup_id, ts, ts_end, dur, package, startup_type FROM internal_startups_maxsdk28
+CREATE PERFETTO TABLE _all_startups AS
+SELECT sdk, startup_id, ts, ts_end, dur, package, startup_type FROM _startups_maxsdk28
 UNION ALL
-SELECT sdk, startup_id, ts, ts_end, dur, package, startup_type FROM internal_startups_minsdk29
+SELECT sdk, startup_id, ts, ts_end, dur, package, startup_type FROM _startups_minsdk29
 UNION ALL
-SELECT sdk, startup_id, ts, ts_end, dur, package, startup_type FROM internal_startups_minsdk33;
+SELECT sdk, startup_id, ts, ts_end, dur, package, startup_type FROM _startups_minsdk33;
 
 -- All activity startups in the trace by startup id.
 -- Populated by different scripts depending on the platform version/contents.
@@ -44,7 +44,7 @@
   startup_type STRING
 ) AS
 SELECT startup_id, ts, ts_end, dur, package, startup_type FROM
-internal_all_startups WHERE ( CASE
+_all_startups WHERE ( CASE
   WHEN slice_count('launchingActivity#*:*') > 0
     THEN sdk = "minsdk33"
   WHEN slice_count('MetricsLogger:*') > 0
@@ -52,25 +52,21 @@
   ELSE sdk = "maxsdk28"
   END);
 
---
--- Create startup processes
---
-
 -- Create a table containing only the slices which are necessary for determining
 -- whether a startup happened.
-CREATE PERFETTO TABLE internal_startup_indicator_slices AS
+CREATE PERFETTO TABLE _startup_indicator_slices AS
 SELECT ts, name, track_id
 FROM slice
 WHERE name IN ('bindApplication', 'activityStart', 'activityResume');
 
-CREATE PERFETTO FUNCTION internal_startup_indicator_slice_count(start_ts LONG,
+CREATE PERFETTO FUNCTION _startup_indicator_slice_count(start_ts LONG,
                                                                 end_ts LONG,
                                                                 utid INT,
                                                                 name STRING)
 RETURNS INT AS
 SELECT COUNT(1)
 FROM thread_track t
-JOIN internal_startup_indicator_slices s ON s.track_id = t.id
+JOIN _startup_indicator_slices s ON s.track_id = t.id
 WHERE
   t.utid = $utid AND
   s.ts >= $start_ts AND
@@ -81,13 +77,12 @@
 --
 -- The vast majority of cases should be a single process. However it is
 -- possible that the process dies during the activity startup and is respawned.
---
--- @column startup_id   Startup id.
--- @column upid         Upid of process on which activity started.
--- @column startup_type Type of the startup.
 CREATE PERFETTO TABLE android_startup_processes(
+  -- Startup id.
   startup_id INT,
+  -- Upid of process on which activity started.
   upid INT,
+  -- Type of the startup.
   startup_type INT
 ) AS
 -- This is intentionally a materialized query. For some reason, if we don't
@@ -109,9 +104,9 @@
       l.startup_id,
       l.startup_type,
       p.upid,
-      INTERNAL_STARTUP_INDICATOR_slice_count(l.ts, l.ts_end, t.utid, 'bindApplication') AS bind_app,
-      INTERNAL_STARTUP_INDICATOR_slice_count(l.ts, l.ts_end, t.utid, 'activityStart') AS a_start,
-      INTERNAL_STARTUP_INDICATOR_slice_count(l.ts, l.ts_end, t.utid, 'activityResume') AS a_resume
+      _startup_indicator_slice_count(l.ts, l.ts_end, t.utid, 'bindApplication') AS bind_app,
+      _startup_indicator_slice_count(l.ts, l.ts_end, t.utid, 'activityStart') AS a_start,
+      _startup_indicator_slice_count(l.ts, l.ts_end, t.utid, 'activityResume') AS a_resume
     FROM android_startups l
     JOIN android_process_metadata p ON (
       l.package = p.package_name
diff --git a/src/trace_processor/perfetto_sql/stdlib/android/startup/internal_startups_maxsdk28.sql b/src/trace_processor/perfetto_sql/stdlib/android/startup/startups_maxsdk28.sql
similarity index 84%
rename from src/trace_processor/perfetto_sql/stdlib/android/startup/internal_startups_maxsdk28.sql
rename to src/trace_processor/perfetto_sql/stdlib/android/startup/startups_maxsdk28.sql
index fa77966..0a7fab2 100644
--- a/src/trace_processor/perfetto_sql/stdlib/android/startup/internal_startups_maxsdk28.sql
+++ b/src/trace_processor/perfetto_sql/stdlib/android/startup/startups_maxsdk28.sql
@@ -13,9 +13,9 @@
 -- See the License for the specific language governing permissions and
 -- limitations under the License.
 
-INCLUDE PERFETTO MODULE android.startup.internal_startup_events;
+INCLUDE PERFETTO MODULE android.startup.startup_events;
 
-CREATE PERFETTO TABLE internal_startups_maxsdk28 AS
+CREATE PERFETTO TABLE _startups_maxsdk28 AS
 SELECT
   "maxsdk28" as sdk,
   ROW_NUMBER() OVER(ORDER BY ts) AS startup_id,
@@ -24,6 +24,6 @@
   le.ts_end - le.ts AS dur,
   package_name AS package,
   NULL AS startup_type
-FROM internal_startup_events le
+FROM _startup_events le
 ORDER BY ts;
 
diff --git a/src/trace_processor/perfetto_sql/stdlib/android/startup/internal_startups_minsdk29.sql b/src/trace_processor/perfetto_sql/stdlib/android/startup/startups_minsdk29.sql
similarity index 73%
rename from src/trace_processor/perfetto_sql/stdlib/android/startup/internal_startups_minsdk29.sql
rename to src/trace_processor/perfetto_sql/stdlib/android/startup/startups_minsdk29.sql
index e9536d1..e10244b 100644
--- a/src/trace_processor/perfetto_sql/stdlib/android/startup/internal_startups_minsdk29.sql
+++ b/src/trace_processor/perfetto_sql/stdlib/android/startup/startups_minsdk29.sql
@@ -13,44 +13,44 @@
 -- See the License for the specific language governing permissions and
 -- limitations under the License.
 
-INCLUDE PERFETTO MODULE android.startup.internal_startup_events;
+INCLUDE PERFETTO MODULE android.startup.startup_events;
 
 -- Marks the beginning of the trace and is equivalent to when the statsd startup
 -- logging begins.
-CREATE PERFETTO VIEW internal_activity_intent_received AS
+CREATE PERFETTO VIEW _activity_intent_received AS
 SELECT ts FROM slice
 WHERE name = 'MetricsLogger:launchObserverNotifyIntentStarted';
 
 -- We partition the trace into spans based on posted activity intents.
 -- We will refine these progressively in the next steps to only encompass
 -- activity starts.
-CREATE PERFETTO TABLE internal_activity_intent_recv_spans AS
+CREATE PERFETTO TABLE _activity_intent_recv_spans AS
 SELECT
   ROW_NUMBER()
   OVER(ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) AS startup_id,
   ts,
   LEAD(ts, 1, (SELECT end_ts FROM trace_bounds)) OVER(ORDER BY ts) - ts AS dur
-FROM internal_activity_intent_received
+FROM _activity_intent_received
 ORDER BY ts;
 
 -- Filter activity_intent_recv_spans, keeping only the ones that triggered
 -- a startup.
-CREATE PERFETTO VIEW internal_startup_partitions AS
-SELECT * FROM internal_activity_intent_recv_spans AS spans
+CREATE PERFETTO VIEW _startup_partitions AS
+SELECT * FROM _activity_intent_recv_spans AS spans
 WHERE 1 = (
   SELECT COUNT(1)
-  FROM internal_startup_events
-  WHERE internal_startup_events.ts BETWEEN spans.ts AND spans.ts + spans.dur);
+  FROM _startup_events
+  WHERE _startup_events.ts BETWEEN spans.ts AND spans.ts + spans.dur);
 
 -- Successful activity startup. The end of the 'launching' event is not related
 -- to whether it actually succeeded or not.
-CREATE PERFETTO VIEW internal_activity_intent_startup_successful AS
+CREATE PERFETTO VIEW _activity_intent_startup_successful AS
 SELECT ts FROM slice
 WHERE name = 'MetricsLogger:launchObserverNotifyActivityLaunchFinished';
 
 -- Use the starting event package name. The finish event package name
 -- is not reliable in the case of failed startups.
-CREATE PERFETTO TABLE internal_startups_minsdk29 AS
+CREATE PERFETTO TABLE _startups_minsdk29 AS
 SELECT
   "minsdk29" as sdk,
   lpart.startup_id,
@@ -59,12 +59,12 @@
   le.ts_end - lpart.ts AS dur,
   package_name AS package,
   NULL AS startup_type
-FROM internal_startup_partitions AS lpart
-JOIN internal_startup_events le ON
+FROM _startup_partitions AS lpart
+JOIN _startup_events le ON
   (le.ts BETWEEN lpart.ts AND lpart.ts + lpart.dur)
   AND (le.ts_end BETWEEN lpart.ts AND lpart.ts + lpart.dur)
 WHERE (
   SELECT COUNT(1)
-  FROM internal_activity_intent_startup_successful AS successful
+  FROM _activity_intent_startup_successful AS successful
   WHERE successful.ts BETWEEN lpart.ts AND lpart.ts + lpart.dur
 ) > 0;
diff --git a/src/trace_processor/perfetto_sql/stdlib/android/startup/internal_startups_minsdk33.sql b/src/trace_processor/perfetto_sql/stdlib/android/startup/startups_minsdk33.sql
similarity index 82%
rename from src/trace_processor/perfetto_sql/stdlib/android/startup/internal_startups_minsdk33.sql
rename to src/trace_processor/perfetto_sql/stdlib/android/startup/startups_minsdk33.sql
index 118dda6..b643808 100644
--- a/src/trace_processor/perfetto_sql/stdlib/android/startup/internal_startups_minsdk33.sql
+++ b/src/trace_processor/perfetto_sql/stdlib/android/startup/startups_minsdk33.sql
@@ -13,9 +13,9 @@
 -- See the License for the specific language governing permissions and
 -- limitations under the License.
 
-INCLUDE PERFETTO MODULE android.startup.internal_startup_events;
+INCLUDE PERFETTO MODULE android.startup.startup_events;
 
-CREATE PERFETTO VIEW internal_startup_async_events AS
+CREATE PERFETTO VIEW _startup_async_events AS
 SELECT
   ts,
   dur,
@@ -26,7 +26,7 @@
   AND dur != 0
   AND INSTR(name, ':') = 0;
 
-CREATE PERFETTO VIEW internal_startup_complete_events AS
+CREATE PERFETTO VIEW _startup_complete_events AS
 SELECT
   CAST(STR_SPLIT(completed, ':', 0) AS INT) AS startup_id,
   STR_SPLIT(completed, ':', 2) AS package_name,
@@ -48,7 +48,7 @@
 )
 GROUP BY 1, 2, 3;
 
-CREATE PERFETTO TABLE internal_startups_minsdk33 AS
+CREATE PERFETTO TABLE _startups_minsdk33 AS
 SELECT
   "minsdk33" as sdk,
   startup_id,
@@ -57,8 +57,8 @@
   dur,
   package_name AS package,
   startup_type
-FROM internal_startup_async_events
-JOIN internal_startup_complete_events USING (startup_id);
+FROM _startup_async_events
+JOIN _startup_complete_events USING (startup_id);
 
 
 
diff --git a/src/trace_processor/perfetto_sql/stdlib/android/thread.sql b/src/trace_processor/perfetto_sql/stdlib/android/thread.sql
index e39e819..d8c0b74 100644
--- a/src/trace_processor/perfetto_sql/stdlib/android/thread.sql
+++ b/src/trace_processor/perfetto_sql/stdlib/android/thread.sql
@@ -13,7 +13,7 @@
 -- See the License for the specific language governing permissions and
 -- limitations under the License.
 
-CREATE PERFETTO FUNCTION internal_thread_prefix(thread_name STRING)
+CREATE PERFETTO FUNCTION _thread_prefix(thread_name STRING)
 RETURNS STRING AS
 SELECT STR_SPLIT(STR_SPLIT(STR_SPLIT(STR_SPLIT($thread_name, "-", 0), "[", 0), ":", 0), " ", 0);
 
@@ -40,7 +40,7 @@
   SELECT
     pid,
     upid,
-    INTERNAL_THREAD_PREFIX(thread.name) AS thread_name_prefix,
+    _THREAD_PREFIX(thread.name) AS thread_name_prefix,
     process.name AS process_name,
     COUNT(thread.start_ts)
       OVER (
diff --git a/src/trace_processor/perfetto_sql/stdlib/chrome/cpu_powerups.sql b/src/trace_processor/perfetto_sql/stdlib/chrome/cpu_powerups.sql
index 3d51765..8657ca5 100644
--- a/src/trace_processor/perfetto_sql/stdlib/chrome/cpu_powerups.sql
+++ b/src/trace_processor/perfetto_sql/stdlib/chrome/cpu_powerups.sql
@@ -71,7 +71,7 @@
     ORDER BY ts ASC;
 
 -- We do not want scheduler slices with utid = 0 (the 'swapper' kernel thread).
-CREATE PERFETTO VIEW internal_cpu_power_valid_sched_slice AS
+CREATE PERFETTO VIEW _cpu_power_valid_sched_slice AS
   SELECT *
   FROM sched_slice
   WHERE utid != 0;
@@ -90,10 +90,10 @@
 --
 -- Here threads T1 and T2 executed in CPU power slice [A,B].  The
 -- time between F and G represents time between threads in the kernel.
-CREATE VIRTUAL TABLE internal_cpu_power_and_sched_slice
+CREATE VIRTUAL TABLE _cpu_power_and_sched_slice
 USING
   SPAN_JOIN(chrome_cpu_power_slice PARTITIONED cpu,
-            internal_cpu_power_valid_sched_slice PARTITIONED cpu);
+            _cpu_power_valid_sched_slice PARTITIONED cpu);
 
 -- The Linux scheduler slices that executed immediately after a
 -- CPU power up.
@@ -121,7 +121,7 @@
   utid,
   previous_power_state,
   powerup_id
-FROM internal_cpu_power_and_sched_slice
+FROM _cpu_power_and_sched_slice
 WHERE power_state = 0     -- Power-ups only.
 GROUP BY cpu, powerup_id
 HAVING ts = MIN(ts)       -- There will only be one MIN sched slice
@@ -137,7 +137,7 @@
 --   slice_id  The slice_id for the top-level slice.
 --   ts        Starting timestamp for the slice.
 --   dur       The duration for the slice.
-CREATE PERFETTO VIEW internal_cpu_power_thread_and_toplevel_slice AS
+CREATE PERFETTO VIEW _cpu_power_thread_and_toplevel_slice AS
   SELECT
     t.utid AS utid,
     s.id AS slice_id,
@@ -164,7 +164,7 @@
 CREATE VIRTUAL TABLE chrome_cpu_power_post_powerup_slice
 USING
   SPAN_JOIN(chrome_cpu_power_first_sched_slice_after_powerup PARTITIONED utid,
-            internal_cpu_power_thread_and_toplevel_slice PARTITIONED utid);
+            _cpu_power_thread_and_toplevel_slice PARTITIONED utid);
 
 -- The first top-level slice that ran after a CPU power-up.
 CREATE PERFETTO VIEW chrome_cpu_power_first_toplevel_slice_after_powerup(
diff --git a/src/trace_processor/perfetto_sql/stdlib/chrome/page_loads.sql b/src/trace_processor/perfetto_sql/stdlib/chrome/page_loads.sql
index 73e44e9..c8d1443 100644
--- a/src/trace_processor/perfetto_sql/stdlib/chrome/page_loads.sql
+++ b/src/trace_processor/perfetto_sql/stdlib/chrome/page_loads.sql
@@ -9,7 +9,7 @@
 
 INCLUDE PERFETTO MODULE common.slices;
 
-CREATE PERFETTO VIEW internal_fcp_metrics AS
+CREATE PERFETTO VIEW _fcp_metrics AS
 SELECT
   ts,
   dur,
@@ -19,7 +19,7 @@
 FROM process_slice
 WHERE name = 'PageLoadMetrics.NavigationToFirstContentfulPaint';
 
-CREATE PERFETTO FUNCTION internal_page_load_metrics(event_name STRING)
+CREATE PERFETTO FUNCTION _page_load_metrics(event_name STRING)
 RETURNS TABLE(
   ts LONG,
   dur LONG,
@@ -92,22 +92,22 @@
   timing_interactive.ts AS mark_interactive_ts,
   fcp.url,
   fcp.browser_upid
-FROM internal_fcp_metrics fcp
+FROM _fcp_metrics fcp
 LEFT JOIN
-  internal_page_load_metrics('PageLoadMetrics.NavigationToLargestContentfulPaint') lcp
+  _page_load_metrics('PageLoadMetrics.NavigationToLargestContentfulPaint') lcp
     USING (navigation_id, browser_upid)
 LEFT JOIN
-  internal_page_load_metrics('PageLoadMetrics.NavigationToDOMContentLoadedEventFired') load_fired
+  _page_load_metrics('PageLoadMetrics.NavigationToDOMContentLoadedEventFired') load_fired
     USING (navigation_id, browser_upid)
 LEFT JOIN
-  internal_page_load_metrics('PageLoadMetrics.NavigationToMainFrameOnLoad') start_load
+  _page_load_metrics('PageLoadMetrics.NavigationToMainFrameOnLoad') start_load
     USING (navigation_id, browser_upid)
 LEFT JOIN
-  internal_page_load_metrics('PageLoadMetrics.UserTimingMarkFullyLoaded') timing_loaded
+  _page_load_metrics('PageLoadMetrics.UserTimingMarkFullyLoaded') timing_loaded
     USING (navigation_id, browser_upid)
 LEFT JOIN
-  internal_page_load_metrics('PageLoadMetrics.UserTimingMarkFullyVisible') timing_visible
+  _page_load_metrics('PageLoadMetrics.UserTimingMarkFullyVisible') timing_visible
     USING (navigation_id, browser_upid)
 LEFT JOIN
-  internal_page_load_metrics('PageLoadMetrics.UserTimingMarkInteractive') timing_interactive
+  _page_load_metrics('PageLoadMetrics.UserTimingMarkInteractive') timing_interactive
     USING (navigation_id, browser_upid);
diff --git a/src/trace_processor/perfetto_sql/stdlib/chrome/scroll_jank/scroll_jank_cause_utils.sql b/src/trace_processor/perfetto_sql/stdlib/chrome/scroll_jank/scroll_jank_cause_utils.sql
index 78d3964..7cad697 100644
--- a/src/trace_processor/perfetto_sql/stdlib/chrome/scroll_jank/scroll_jank_cause_utils.sql
+++ b/src/trace_processor/perfetto_sql/stdlib/chrome/scroll_jank/scroll_jank_cause_utils.sql
@@ -4,7 +4,7 @@
 
 -- Function to retrieve the upid for a surfaceflinger, as these are attributed
 -- to the GPU but are recorded on a different data source (and track group).
-CREATE PERFETTO FUNCTION internal_get_process_id_for_surfaceflinger()
+CREATE PERFETTO FUNCTION _get_process_id_for_surfaceflinger()
 -- The process id for surfaceflinger.
 RETURNS INT AS
 SELECT
@@ -15,7 +15,7 @@
 
 -- Map a generic process type to a specific name or substring of a name that
 -- can be found in the trace process table.
-CREATE PERFETTO TABLE internal_process_type_to_name (
+CREATE PERFETTO TABLE _process_type_to_name (
   -- The process type: one of 'Browser' or 'GPU'.
   process_type STRING,
   -- The process name for Chrome traces.
@@ -38,7 +38,7 @@
   process_glob
 FROM process_names;
 
-CREATE PERFETTO FUNCTION internal_get_process_name(
+CREATE PERFETTO FUNCTION _get_process_name(
   -- The process type: one of 'Browser' or 'GPU'.
   type STRING
 )
@@ -46,11 +46,11 @@
 RETURNS STRING AS
 SELECT
     process_name
-FROM internal_process_type_to_name
+FROM _process_type_to_name
 WHERE process_type = $type
 LIMIT 1;
 
-CREATE PERFETTO FUNCTION internal_get_process_glob(
+CREATE PERFETTO FUNCTION _get_process_glob(
   -- The process type: one of 'Browser' or 'GPU'.
   type STRING
 )
@@ -58,7 +58,7 @@
 RETURNS STRING AS
 SELECT
     process_glob
-FROM internal_process_type_to_name
+FROM _process_type_to_name
 WHERE process_type = $type
 LIMIT 1;
 
@@ -67,8 +67,8 @@
 -- Function to retrieve the chrome process ID for a specific process type. Does
 -- not retrieve the Renderer process, as this is determined when the
 -- EventLatency is known. See function
--- internal_get_renderer_upid_for_event_latency below.
-CREATE PERFETTO FUNCTION internal_get_process_id_by_type(
+-- _get_renderer_upid_for_event_latency below.
+CREATE PERFETTO FUNCTION _get_process_id_by_type(
   -- The process type: one of 'Browser' or 'GPU'.
   type STRING
 )
@@ -79,12 +79,12 @@
 SELECT
   upid
 FROM process
-WHERE name = internal_get_process_name($type)
-  OR name GLOB internal_get_process_glob($type);
+WHERE name = _get_process_name($type)
+  OR name GLOB _get_process_glob($type);
 
 -- Function to retrieve the chrome process ID that a given EventLatency slice
 -- occurred on. This is the Renderer process.
-CREATE PERFETTO FUNCTION internal_get_renderer_upid_for_event_latency(
+CREATE PERFETTO FUNCTION _get_renderer_upid_for_event_latency(
   -- The slice id for an EventLatency slice.
   id INT
 )
@@ -97,7 +97,7 @@
 
 -- Helper function to retrieve all of the upids for a given process, thread,
 -- or EventLatency.
-CREATE PERFETTO FUNCTION internal_processes_by_type_for_event_latency(
+CREATE PERFETTO FUNCTION _processes_by_type_for_event_latency(
   -- The process type that the thread is on: one of 'Browser', 'Renderer' or
   -- 'GPU'.
   type STRING,
@@ -114,7 +114,7 @@
     $type AS process,
     $thread AS thread,
     $event_latency_id AS event_latency_id,
-    internal_get_renderer_upid_for_event_latency($event_latency_id) AS upid
+    _get_renderer_upid_for_event_latency($event_latency_id) AS upid
   WHERE $type = 'Renderer'
   UNION ALL
   -- surfaceflinger upids
@@ -122,7 +122,7 @@
     $type AS process,
     $thread AS thread,
     $event_latency_id AS event_latency_id,
-    internal_get_process_id_for_surfaceflinger() AS upid
+    _get_process_id_for_surfaceflinger() AS upid
   WHERE $type = 'GPU' AND $thread = 'surfaceflinger'
   UNION ALL
   -- Generic Browser and GPU process upids
@@ -131,7 +131,7 @@
     $thread AS thread,
     $event_latency_id AS event_latency_id,
     upid
-  FROM internal_get_process_id_by_type($type)
+  FROM _get_process_id_by_type($type)
   WHERE $type = 'Browser'
     OR ($type = 'GPU' AND $thread != 'surfaceflinger')
 )
@@ -162,7 +162,7 @@
     (
       SELECT DISTINCT
         upid
-      FROM internal_processes_by_type_for_event_latency(
+      FROM _processes_by_type_for_event_latency(
         $process_type,
         $thread_name,
         $event_latency_id)
diff --git a/src/trace_processor/perfetto_sql/stdlib/chrome/scroll_jank/scroll_jank_v3.sql b/src/trace_processor/perfetto_sql/stdlib/chrome/scroll_jank/scroll_jank_v3.sql
index 4b20b6b..ce20041 100644
--- a/src/trace_processor/perfetto_sql/stdlib/chrome/scroll_jank/scroll_jank_v3.sql
+++ b/src/trace_processor/perfetto_sql/stdlib/chrome/scroll_jank/scroll_jank_v3.sql
@@ -36,7 +36,7 @@
 FROM slice
 WHERE name = "InputLatency::GestureScrollUpdate" AND dur != -1;
 
-CREATE PERFETTO TABLE internal_non_coalesced_gesture_scrolls AS
+CREATE PERFETTO TABLE _non_coalesced_gesture_scrolls AS
 SELECT
   id,
   ts,
@@ -73,7 +73,7 @@
     -- presented scroll update they have been coalesced into.
     (
       SELECT id
-      FROM internal_non_coalesced_gesture_scrolls non_coalesced
+      FROM _non_coalesced_gesture_scrolls non_coalesced
       WHERE non_coalesced.ts <= scroll_update.ts
       ORDER BY ts DESC
       LIMIT 1
@@ -91,13 +91,13 @@
     FROM scroll_updates_with_coalesce_info coalesce_info
     WHERE
       coalesce_info.coalesced_to_scroll_update_slice_id =
-        internal_non_coalesced_gesture_scrolls.id
+        _non_coalesced_gesture_scrolls.id
     ORDER BY ts DESC
     LIMIT 1
   ) as last_coalesced_input_ts,
   scroll_update_id,
   scroll_id
-FROM internal_non_coalesced_gesture_scrolls;
+FROM _non_coalesced_gesture_scrolls;
 
 -- Associate every trace_id with it's perceived delta_y on the screen after
 -- prediction.
diff --git a/src/trace_processor/perfetto_sql/stdlib/chrome/scroll_jank/scroll_offsets.sql b/src/trace_processor/perfetto_sql/stdlib/chrome/scroll_jank/scroll_offsets.sql
index 41ead9a..8df0937 100644
--- a/src/trace_processor/perfetto_sql/stdlib/chrome/scroll_jank/scroll_offsets.sql
+++ b/src/trace_processor/perfetto_sql/stdlib/chrome/scroll_jank/scroll_offsets.sql
@@ -32,7 +32,7 @@
 INCLUDE PERFETTO MODULE chrome.scroll_jank.scroll_jank_v3;
 
 -- Non-coalesced scroll update events and their timestamps.
-CREATE PERFETTO VIEW internal_non_coalesced_scrolls AS
+CREATE PERFETTO VIEW _non_coalesced_scrolls AS
 SELECT
   scroll_update_id,
   ts
@@ -45,7 +45,7 @@
 -- this trace event, the deltas recorded represent the true (read "original")
 -- values that the Browser receives from Android, and the only processing is
 -- scaling and translation.
-CREATE PERFETTO TABLE internal_scroll_deltas AS
+CREATE PERFETTO TABLE _scroll_deltas AS
 SELECT
   EXTRACT_ARG(arg_set_id, 'scroll_deltas.trace_id') AS scroll_update_id,
   EXTRACT_ARG(arg_set_id, 'scroll_deltas.original_delta_y') AS delta_y,
@@ -53,25 +53,25 @@
 FROM slice
 WHERE name = "TranslateAndScaleWebInputEvent";
 
--- Associate the raw (original) deltas (internal_scroll_deltas) with the
+-- Associate the raw (original) deltas (_scroll_deltas) with the
 -- corresponding non-coalesced scroll updates
--- (internal_non_coalesced_scroll_updates) to get the timestamp of the event
+-- (_non_coalesced_scroll_updates) to get the timestamp of the event
 -- those deltas. This allows for ordering delta recordings to track them over
 -- time.
-CREATE PERFETTO VIEW internal_non_coalesced_deltas AS
+CREATE PERFETTO VIEW _non_coalesced_deltas AS
 SELECT
   scroll_update_id,
   ts,
   delta_y
-FROM internal_non_coalesced_scrolls
-INNER JOIN internal_scroll_deltas
+FROM _non_coalesced_scrolls
+INNER JOIN _scroll_deltas
   USING (scroll_update_id);
 
 -- Selecting information scroll update events that have been coalesced,
 -- including timestamp and the specific event (scroll update id) it was
 -- coalesced into. Recordings of deltas will need to be associated with the
 -- timestamp of the scroll update they were coalesced into.
-CREATE PERFETTO TABLE internal_scroll_update_coalesce_info AS
+CREATE PERFETTO TABLE _scroll_update_coalesce_info AS
 SELECT
   ts,
   EXTRACT_ARG(arg_set_id, 'scroll_deltas.coalesced_to_trace_id') AS coalesced_to_scroll_update_id,
@@ -80,19 +80,19 @@
 WHERE name = "WebCoalescedInputEvent::CoalesceWith" AND
   coalesced_to_scroll_update_id IS NOT NULL;
 
--- Associate the raw (original) deltas (internal_scroll_deltas) with the
--- corresponding coalesced scroll updates (internal_scroll_update_coalesce_info)
+-- Associate the raw (original) deltas (_scroll_deltas) with the
+-- corresponding coalesced scroll updates (_scroll_update_coalesce_info)
 -- to get the timestamp of the event those deltas were coalesced into. This
 -- allows us to get the scaled coordinates for all of the input events
 -- (original input coordinates can't be used due to scaling).
-CREATE PERFETTO VIEW internal_coalesced_deltas AS
+CREATE PERFETTO VIEW _coalesced_deltas AS
 SELECT
-  internal_scroll_update_coalesce_info.coalesced_to_scroll_update_id AS scroll_update_id,
+  _scroll_update_coalesce_info.coalesced_to_scroll_update_id AS scroll_update_id,
   ts,
-  internal_scroll_deltas.delta_y AS delta_y,
+  _scroll_deltas.delta_y AS delta_y,
   TRUE AS is_coalesced
-FROM internal_scroll_update_coalesce_info
-LEFT JOIN internal_scroll_deltas
+FROM _scroll_update_coalesce_info
+LEFT JOIN _scroll_deltas
   USING (scroll_update_id);
 
 -- All of the presented frame scroll update ids.
@@ -115,7 +115,7 @@
 -- When every GestureScrollUpdate event is processed, the offset set by the
 -- compositor is recorded. This offset is scaled to the device screen size, and
 -- can be used to calculate deltas.
-CREATE PERFETTO VIEW internal_presented_frame_offsets AS
+CREATE PERFETTO VIEW _presented_frame_offsets AS
 SELECT
   EXTRACT_ARG(arg_set_id, 'scroll_deltas.trace_id') AS scroll_update_id,
   EXTRACT_ARG(arg_set_id, 'scroll_deltas.visual_offset_y') AS visual_offset_y
@@ -124,8 +124,8 @@
 
 -- The raw coordinates and pixel offsets for all input events which were part of
 -- a scroll. This includes input events that were converted to scroll events
--- which were presented (internal_non_coalesced_scrolls) and scroll events which
--- were coalesced (internal_coalesced_deltas).
+-- which were presented (_non_coalesced_scrolls) and scroll events which
+-- were coalesced (_coalesced_deltas).
 CREATE PERFETTO TABLE chrome_scroll_input_offsets(
   -- Trace id associated with the scroll.
   scroll_update_id INT,
@@ -143,14 +143,14 @@
     scroll_update_id,
     ts,
     delta_y
-  FROM internal_non_coalesced_deltas
+  FROM _non_coalesced_deltas
   WHERE delta_y IS NOT NULL
   UNION
   SELECT
     scroll_update_id,
     ts,
     delta_y
-  FROM internal_coalesced_deltas
+  FROM _coalesced_deltas
   WHERE delta_y IS NOT NULL
   ORDER BY scroll_update_id, ts)
 SELECT
@@ -165,23 +165,23 @@
 -- Calculate the total visual offset for all presented frames (non-coalesced
 -- scroll updates) that have raw deltas recorded. These visual offsets
 -- correspond with the inverse of the deltas for the presented frame.
-CREATE PERFETTO VIEW internal_preprocessed_presented_frame_offsets AS
+CREATE PERFETTO VIEW _preprocessed_presented_frame_offsets AS
 SELECT
   chrome_full_frame_view.scroll_update_id,
   chrome_full_frame_view.presentation_timestamp AS ts,
   chrome_deltas_presented_frame_scroll_update_ids.id,
-  internal_presented_frame_offsets.visual_offset_y -
-    LAG(internal_presented_frame_offsets.visual_offset_y)
+  _presented_frame_offsets.visual_offset_y -
+    LAG(_presented_frame_offsets.visual_offset_y)
     OVER (ORDER BY chrome_full_frame_view.presentation_timestamp)
       AS presented_frame_visual_offset_y
 FROM chrome_full_frame_view
-LEFT JOIN internal_scroll_deltas
+LEFT JOIN _scroll_deltas
   USING (scroll_update_id)
 LEFT JOIN chrome_deltas_presented_frame_scroll_update_ids
   USING (scroll_update_id)
-LEFT JOIN internal_presented_frame_offsets
+LEFT JOIN _presented_frame_offsets
   USING (scroll_update_id)
-WHERE internal_scroll_deltas.delta_y IS NOT NULL;
+WHERE _scroll_deltas.delta_y IS NOT NULL;
 
 -- The scrolling offsets for the actual (applied) scroll events. These are not
 -- necessarily inclusive of all user scroll events, rather those scroll events
@@ -204,7 +204,7 @@
     id,
     MAX(ts) AS ts,
     SUM(presented_frame_visual_offset_y) * -1 AS delta_y
-  FROM internal_preprocessed_presented_frame_offsets
+  FROM _preprocessed_presented_frame_offsets
   GROUP BY id
   ORDER BY ts)
 SELECT
diff --git a/src/trace_processor/perfetto_sql/stdlib/chrome/scroll_jank/utils.sql b/src/trace_processor/perfetto_sql/stdlib/chrome/scroll_jank/utils.sql
index ea535ec..74141e6 100644
--- a/src/trace_processor/perfetto_sql/stdlib/chrome/scroll_jank/utils.sql
+++ b/src/trace_processor/perfetto_sql/stdlib/chrome/scroll_jank/utils.sql
@@ -17,7 +17,7 @@
 -- Function : function takes scroll ids of frames to verify it's from
 -- the same scroll, and makes sure the frame ts occurred within the scroll
 -- timestamp of the neighbour and computes whether the frame was janky or not.
-CREATE PERFETTO FUNCTION internal_is_janky_frame(cur_gesture_id LONG,
+CREATE PERFETTO FUNCTION _is_janky_frame(cur_gesture_id LONG,
                                       neighbour_gesture_id LONG,
                                       neighbour_ts LONG,
                                       cur_gesture_begin_ts LONG,
@@ -45,7 +45,7 @@
 --
 -- Returns the jank budget in percentage (i.e. 0.75) of vsync interval
 -- percentage.
-CREATE PERFETTO FUNCTION internal_jank_budget(
+CREATE PERFETTO FUNCTION _jank_budget(
   cur_frame_exact FLOAT,
   prev_frame_exact FLOAT,
   next_frame_exact FLOAT
diff --git a/src/trace_processor/perfetto_sql/stdlib/chrome/speedometer.sql b/src/trace_processor/perfetto_sql/stdlib/chrome/speedometer.sql
index e29811a..79b820f 100644
--- a/src/trace_processor/perfetto_sql/stdlib/chrome/speedometer.sql
+++ b/src/trace_processor/perfetto_sql/stdlib/chrome/speedometer.sql
@@ -33,7 +33,7 @@
 -- @column suite_name    Suite name
 -- @column test_name     Test name
 -- @column mark_type     Type of mark (start, sync-end, async-end)
-CREATE PERFETTO VIEW internal_chrome_speedometer_mark
+CREATE PERFETTO VIEW _chrome_speedometer_mark
 AS
 WITH
   speedometer_21_suite_name(suite_name) AS (
@@ -132,7 +132,7 @@
       COUNT()
         OVER (PARTITION BY iteration, suite_name, test_name ORDER BY ts ASC)
         AS mark_count
-    FROM internal_chrome_speedometer_mark
+    FROM _chrome_speedometer_mark
     JOIN slice
       USING (slice_id)
   ),
diff --git a/src/trace_processor/perfetto_sql/stdlib/chrome/startups.sql b/src/trace_processor/perfetto_sql/stdlib/chrome/startups.sql
index 8d7e640..f1e852b 100644
--- a/src/trace_processor/perfetto_sql/stdlib/chrome/startups.sql
+++ b/src/trace_processor/perfetto_sql/stdlib/chrome/startups.sql
@@ -8,7 +8,7 @@
 -- If TimeToFirstVisibleContent is available, then this event will be the
 -- main event of the startup. Otherwise, the event for the start timestamp will
 -- be used.
-CREATE PERFETTO VIEW internal_startup_start_events AS
+CREATE PERFETTO VIEW _startup_start_events AS
 WITH
 starts AS (
   SELECT
@@ -60,7 +60,7 @@
 
 -- Chrome launch causes, not recorded at start time; use the activity id to
 -- join with the actual startup events.
-CREATE PERFETTO VIEW internal_launch_causes AS
+CREATE PERFETTO VIEW _launch_causes AS
 SELECT
   EXTRACT_ARG(arg_set_id, 'startup.activity_id') AS activity_id,
   EXTRACT_ARG(arg_set_id, 'startup.launch_cause') AS launch_cause,
@@ -93,6 +93,6 @@
   start_events.first_visible_content_ts,
   launches.launch_cause,
   start_events.browser_upid
-FROM internal_startup_start_events start_events
-  LEFT JOIN internal_launch_causes launches
+FROM _startup_start_events start_events
+  LEFT JOIN _launch_causes launches
   USING(activity_id, browser_upid);
diff --git a/src/trace_processor/perfetto_sql/stdlib/chrome/tasks.sql b/src/trace_processor/perfetto_sql/stdlib/chrome/tasks.sql
index 0c7b18b..420ef6b 100644
--- a/src/trace_processor/perfetto_sql/stdlib/chrome/tasks.sql
+++ b/src/trace_processor/perfetto_sql/stdlib/chrome/tasks.sql
@@ -8,7 +8,7 @@
 -- argument of descendant ScopedSetIpcHash slice.
 -- This is relevant only for the older Chrome traces, where mojo IPC
 -- hash was reported in a separate ScopedSetIpcHash slice.
-CREATE PERFETTO FUNCTION internal_extract_mojo_ipc_hash(slice_id INT)
+CREATE PERFETTO FUNCTION _extract_mojo_ipc_hash(slice_id INT)
 RETURNS INT AS
 SELECT EXTRACT_ARG(arg_set_id, "chrome_mojo_event_info.ipc_hash")
 FROM descendant_slice($slice_id)
@@ -18,7 +18,7 @@
 
 -- Returns the frame type (main frame vs subframe) for key navigation tasks
 -- which capture the associated RenderFrameHost in an argument.
-CREATE PERFETTO FUNCTION internal_extract_frame_type(slice_id INT)
+CREATE PERFETTO FUNCTION _extract_frame_type(slice_id INT)
 RETURNS INT AS
 SELECT EXTRACT_ARG(arg_set_id, "render_frame_host.frame_type")
 FROM descendant_slice($slice_id)
@@ -31,7 +31,7 @@
 LIMIT 1;
 
 -- Human-readable aliases for a few key navigation tasks.
-CREATE PERFETTO FUNCTION internal_human_readable_navigation_task_name(
+CREATE PERFETTO FUNCTION _human_readable_navigation_task_name(
   task_name STRING)
 RETURNS STRING AS
 SELECT
@@ -47,19 +47,19 @@
   END;
 
 -- Takes a task name and formats it correctly for scheduler tasks.
-CREATE PERFETTO FUNCTION internal_format_scheduler_task_name(task_name STRING)
+CREATE PERFETTO FUNCTION _format_scheduler_task_name(task_name STRING)
 RETURNS STRING AS
 SELECT printf("RunTask(posted_from=%s)", $task_name);
 
 -- Takes the category and determines whether it is "Java" only, as opposed to
 -- "toplevel,Java".
-CREATE PERFETTO FUNCTION internal_java_not_top_level_category(category STRING)
+CREATE PERFETTO FUNCTION _java_not_top_level_category(category STRING)
 RETURNS BOOL AS
 SELECT $category GLOB "*Java*" AND $category not GLOB "*toplevel*";
 
 -- Takes the category and determines whether is any valid
 -- toplevel category or combination of categories.
-CREATE PERFETTO FUNCTION internal_any_top_level_category(category STRING)
+CREATE PERFETTO FUNCTION _any_top_level_category(category STRING)
 RETURNS BOOL AS
 SELECT $category IN ("toplevel", "toplevel,viz", "toplevel,Java");
 
@@ -71,7 +71,7 @@
 -- `CREATE PERFETTO TABLE`.
 
 -- Get task type for a given task kind.
-CREATE PERFETTO FUNCTION internal_get_java_views_task_type(kind STRING)
+CREATE PERFETTO FUNCTION _get_java_views_task_type(kind STRING)
 RETURNS STRING AS
 SELECT
   CASE $kind
@@ -92,7 +92,7 @@
 --
 -- Note: this might include messages received within a sync mojo call.
 -- TODO(altimin): This should use EXTEND_TABLE when it becomes available.
-CREATE TABLE internal_chrome_mojo_slices AS
+CREATE TABLE _chrome_mojo_slices AS
 WITH
 -- Select all new-style (post crrev.com/c/3270337) mojo slices and
 -- generate |task_name| for them.
@@ -119,7 +119,7 @@
 old_associated_mojo_slices AS (
   SELECT
     name AS interface_name,
-    internal_extract_mojo_ipc_hash(id) AS ipc_hash,
+    _extract_mojo_ipc_hash(id) AS ipc_hash,
     "message" AS message_type,
     id
   FROM slice
@@ -134,7 +134,7 @@
       EXTRACT_ARG(arg_set_id, "chrome_mojo_event_info.watcher_notify_interface_tag"),
       EXTRACT_ARG(arg_set_id, "chrome_mojo_event_info.mojo_interface_tag")
     ) AS interface_name,
-    internal_extract_mojo_ipc_hash(id) AS ipc_hash,
+    _extract_mojo_ipc_hash(id) AS ipc_hash,
     "message" AS message_type,
     id
   FROM slice
@@ -148,9 +148,9 @@
 UNION ALL
 SELECT * FROM old_non_associated_mojo_slices;
 
--- As we lookup by ID on |internal_chrome_mojo_slices| table, add an index on
+-- As we lookup by ID on |_chrome_mojo_slices| table, add an index on
 -- id to make lookups fast.
-CREATE INDEX internal_chrome_mojo_slices_idx ON internal_chrome_mojo_slices(id);
+CREATE INDEX _chrome_mojo_slices_idx ON _chrome_mojo_slices(id);
 
 -- This table contains a list of slices corresponding to the _representative_
 -- Chrome Java view operations.
@@ -165,7 +165,7 @@
 --                                      capture toolbar screenshot.
 -- @column is_hardware_screenshot BOOL  Whether this slice is a part of accelerated
 --                                      capture toolbar screenshot.
-CREATE TABLE internal_chrome_java_views AS
+CREATE TABLE _chrome_java_views AS
 WITH
 -- .draw, .onLayout and .onMeasure parts of the java view names don't add much, strip them.
 java_slices_with_trimmed_names AS (
@@ -190,7 +190,7 @@
     -- with either category = "toplevel" or category = "toplevel,Java".
     -- Also filter out the zero duration slices as an attempt to reduce noise as
     -- "Java" category contains misc events (as it's hard to add new categories).
-    WHERE internal_java_not_top_level_category(category) AND dur > 0
+    WHERE _java_not_top_level_category(category) AND dur > 0
   ),
   -- We filter out generic slices from various UI frameworks which don't tell us much about
   -- what exactly this view is doing.
@@ -265,11 +265,11 @@
   java_view.is_software_screenshot,
   java_view.is_hardware_screenshot,
   slice.id as slice_id
-FROM internal_chrome_java_views java_view
+FROM _chrome_java_views java_view
 JOIN slice USING (id);
 
 -- A list of Choreographer tasks (Android frame generation) in Chrome.
-CREATE PERFETTO VIEW internal_chrome_choreographer_tasks
+CREATE PERFETTO VIEW _chrome_choreographer_tasks
 AS
 SELECT
   id,
@@ -281,7 +281,7 @@
 WHERE name GLOB "Looper.dispatch: android.view.Choreographer$FrameHandler*";
 
 -- Extract task's posted_from information from task's arguments.
-CREATE PERFETTO FUNCTION internal_get_posted_from(arg_set_id INT)
+CREATE PERFETTO FUNCTION _get_posted_from(arg_set_id INT)
 RETURNS STRING AS
 WITH posted_from as (
   SELECT
@@ -303,7 +303,7 @@
 -- @column kind          The type of Java slice.
 -- @column ts            The timestamp of the slice.
 -- @column name          The name of the slice.
-CREATE PERFETTO FUNCTION internal_select_begin_main_frame_java_slices(
+CREATE PERFETTO FUNCTION _select_begin_main_frame_java_slices(
   name STRING)
 RETURNS TABLE(id INT, kind STRING, ts LONG, dur LONG, name STRING) AS
 SELECT
@@ -315,7 +315,7 @@
 FROM slice
 WHERE
   (name = $name
-    AND internal_get_posted_from(arg_set_id) =
+    AND _get_posted_from(arg_set_id) =
         "cc/trees/single_thread_proxy.cc:ScheduledActionSendBeginMainFrame");
 
 -- A list of Chrome tasks which were performing operations with Java views,
@@ -323,15 +323,15 @@
 -- @column id INT            Slice id.
 -- @column kind STRING       Type of the task.
 -- @column java_views STRING Concatenated names of Java views used by the task.
-CREATE PERFETTO VIEW internal_chrome_slices_with_java_views AS
+CREATE PERFETTO VIEW _chrome_slices_with_java_views AS
 WITH
   -- Select UI thread BeginMainFrames (which are Chrome scheduler tasks) and
   -- Choreographer frames (which are looper tasks).
   root_slices AS (
     SELECT id, kind
-    FROM INTERNAL_SELECT_BEGIN_MAIN_FRAME_JAVA_SLICES('ThreadControllerImpl::RunTask')
+    FROM _SELECT_BEGIN_MAIN_FRAME_JAVA_SLICES('ThreadControllerImpl::RunTask')
     UNION ALL
-    SELECT id, kind FROM internal_chrome_choreographer_tasks
+    SELECT id, kind FROM _chrome_choreographer_tasks
   ),
   -- Intermediate step to allow us to sort java view names.
   root_slice_and_java_view_not_grouped AS (
@@ -339,7 +339,7 @@
       root.id, root.kind, java_view.name AS java_view_name
     FROM root_slices root
     JOIN descendant_slice(root.id) child
-    JOIN internal_chrome_java_views java_view ON java_view.id = child.id
+    JOIN _chrome_java_views java_view ON java_view.id = child.id
   )
 SELECT
   root.id,
@@ -350,7 +350,7 @@
 GROUP BY root.id;
 
 -- A list of tasks executed by Chrome scheduler.
-CREATE TABLE internal_chrome_scheduler_tasks AS
+CREATE TABLE _chrome_scheduler_tasks AS
 SELECT
   id
 FROM slice
@@ -399,8 +399,8 @@
 SELECT
   task.id,
   "chrome_scheduler_tasks" as type,
-  internal_format_scheduler_task_name(
-    internal_get_posted_from(slice.arg_set_id)) as name,
+  _format_scheduler_task_name(
+    _get_posted_from(slice.arg_set_id)) as name,
   slice.ts,
   slice.dur,
   thread.utid,
@@ -414,8 +414,8 @@
   slice.arg_set_id,
   slice.thread_ts,
   slice.thread_dur,
-  internal_get_posted_from(slice.arg_set_id) as posted_from
-FROM internal_chrome_scheduler_tasks task
+  _get_posted_from(slice.arg_set_id) as posted_from
+FROM _chrome_scheduler_tasks task
 JOIN slice using (id)
 JOIN thread_track ON slice.track_id = thread_track.id
 JOIN thread using (utid)
@@ -424,7 +424,7 @@
 
 -- Select the slice that might be the descendant mojo slice for the given task
 -- slice if it exists.
-CREATE PERFETTO FUNCTION internal_get_descendant_mojo_slice_candidate(
+CREATE PERFETTO FUNCTION _get_descendant_mojo_slice_candidate(
   slice_id INT
 )
 RETURNS INT AS
@@ -446,14 +446,14 @@
 ORDER by depth, ts
 LIMIT 1;
 
-CREATE PERFETTO FUNCTION internal_descendant_mojo_slice(slice_id INT)
+CREATE PERFETTO FUNCTION _descendant_mojo_slice(slice_id INT)
 RETURNS TABLE(task_name STRING) AS
 SELECT
   printf("%s %s (hash=%d)",
     mojo.interface_name, mojo.message_type, mojo.ipc_hash) AS task_name
 FROM slice task
-JOIN internal_chrome_mojo_slices mojo
-  ON mojo.id = internal_get_descendant_mojo_slice_candidate($slice_id)
+JOIN _chrome_mojo_slices mojo
+  ON mojo.id = _get_descendant_mojo_slice_candidate($slice_id)
 WHERE task.id = $slice_id;
 
 -- A list of "Chrome tasks": top-level execution units (e.g. scheduler tasks /
@@ -463,7 +463,7 @@
 -- @column task_name STRING  Name for the given task.
 -- @column task_type STRING  Type of the task (e.g. "scheduler").
 -- @column scheduling_delay INT
-CREATE TABLE internal_chrome_tasks AS
+CREATE TABLE _chrome_tasks AS
 WITH
 -- Select slices from "toplevel" category which do not have another
 -- "toplevel" slice as ancestor. The possible cases include sync mojo messages
@@ -472,7 +472,7 @@
 non_embedded_toplevel_slices AS (
   SELECT * FROM slice
   WHERE
-    internal_any_top_level_category(category)
+    _any_top_level_category(category)
     AND (SELECT count() FROM ancestor_slice(slice.id) anc
       WHERE anc.category GLOB "*toplevel*" or anc.category GLOB "*toplevel.viz*") = 0
 ),
@@ -488,7 +488,7 @@
     "java" as task_type
   FROM slice s
   WHERE
-    internal_java_not_top_level_category(category)
+    _java_not_top_level_category(category)
     AND (SELECT count()
       FROM ancestor_slice(s.id) s2
       WHERE s2.category GLOB "*toplevel*" OR s2.category GLOB "*Java*") = 0
@@ -498,8 +498,8 @@
   SELECT
     id,
     printf('%s(java_views=%s)', kind, java_views) AS task_name,
-    internal_get_java_views_task_type(kind) AS task_type
-  FROM internal_chrome_slices_with_java_views
+    _get_java_views_task_type(kind) AS task_type
+  FROM _chrome_slices_with_java_views
 ),
 scheduler_tasks AS (
   SELECT
@@ -521,7 +521,7 @@
     "mojo" AS task_type
   FROM
     chrome_scheduler_tasks task
-  JOIN INTERNAL_DESCENDANT_MOJO_SLICE(task.id) receive_message
+  JOIN _DESCENDANT_MOJO_SLICE(task.id) receive_message
   WHERE
     task.posted_from IN (
       "mojo/public/cpp/system/simple_watcher.cc:Notify",
@@ -533,8 +533,8 @@
   WITH tasks_with_readable_names AS (
     SELECT
       id,
-      internal_human_readable_navigation_task_name(task_name) as readable_name,
-      IFNULL(internal_extract_frame_type(id), 'unknown frame type') as frame_type
+      _human_readable_navigation_task_name(task_name) as readable_name,
+      IFNULL(_extract_frame_type(id), 'unknown frame type') as frame_type
     FROM
       scheduler_tasks_with_mojo
   )
@@ -627,7 +627,7 @@
   s.thread_ts,
   s.thread_dur,
   cti.name as full_name
-FROM internal_chrome_tasks cti
+FROM _chrome_tasks cti
 JOIN slice s ON cti.id = s.id
 JOIN thread_track tt ON s.track_id = tt.id
 JOIN thread USING (utid)
diff --git a/src/trace_processor/perfetto_sql/stdlib/common/cpus.sql b/src/trace_processor/perfetto_sql/stdlib/common/cpus.sql
index 100d112..d897503 100644
--- a/src/trace_processor/perfetto_sql/stdlib/common/cpus.sql
+++ b/src/trace_processor/perfetto_sql/stdlib/common/cpus.sql
@@ -14,14 +14,14 @@
 -- limitations under the License.
 
 
-CREATE PERFETTO TABLE internal_cpu_sizes AS
+CREATE PERFETTO TABLE _cpu_sizes AS
 SELECT 0 AS n, 'little' AS size
 UNION
 SELECT 1 AS n, 'mid' AS size
 UNION
 SELECT 2 AS n, 'big' AS size;
 
-CREATE PERFETTO TABLE internal_ranked_cpus AS
+CREATE PERFETTO TABLE _ranked_cpus AS
 SELECT
  (DENSE_RANK() OVER win) - 1 AS n,
  cpu
@@ -50,9 +50,9 @@
 -- A descriptive size ('little', 'mid', 'big', etc) or NULL if we have insufficient information.
 RETURNS STRING AS
 SELECT
-  IIF((SELECT COUNT(DISTINCT n) FROM internal_ranked_cpus) >= 2, size, null) as size
-FROM internal_ranked_cpus
-LEFT JOIN internal_cpu_sizes USING(n)
+  IIF((SELECT COUNT(DISTINCT n) FROM _ranked_cpus) >= 2, size, null) as size
+FROM _ranked_cpus
+LEFT JOIN _cpu_sizes USING(n)
 WHERE cpu = $cpu_index;
 
 
@@ -66,4 +66,4 @@
 SELECT
   cpu as cpu_index,
   guess_cpu_size(cpu) AS size
-FROM internal_ranked_cpus;
\ No newline at end of file
+FROM _ranked_cpus;
\ No newline at end of file
diff --git a/src/trace_processor/perfetto_sql/stdlib/common/percentiles.sql b/src/trace_processor/perfetto_sql/stdlib/common/percentiles.sql
index 7ec8afe..47ecde0 100644
--- a/src/trace_processor/perfetto_sql/stdlib/common/percentiles.sql
+++ b/src/trace_processor/perfetto_sql/stdlib/common/percentiles.sql
@@ -16,7 +16,7 @@
 INCLUDE PERFETTO MODULE common.counters;
 INCLUDE PERFETTO MODULE common.timestamps;
 
-CREATE PERFETTO FUNCTION internal_number_generator(upper_limit INT)
+CREATE PERFETTO FUNCTION _number_generator(upper_limit INT)
 RETURNS TABLE(num INT) AS
 WITH nums AS
     (SELECT 1 num UNION SELECT num + 1
@@ -70,7 +70,7 @@
 SELECT
     num AS percentile,
     IFNULL(value, MIN(value) OVER (ORDER BY percentile DESC)) AS value
-FROM INTERNAL_NUMBER_GENERATOR(100) AS nums
+FROM _NUMBER_GENERATOR(100) AS nums
 LEFT JOIN with_gaps ON with_gaps.percentile = nums.num
 ORDER BY percentile DESC;
 
diff --git a/src/trace_processor/perfetto_sql/stdlib/common/slices.sql b/src/trace_processor/perfetto_sql/stdlib/common/slices.sql
index 36176c0..84badb6 100644
--- a/src/trace_processor/perfetto_sql/stdlib/common/slices.sql
+++ b/src/trace_processor/perfetto_sql/stdlib/common/slices.sql
@@ -244,8 +244,8 @@
 WHERE parent_id = $parent_id;
 
 -- Given a slice id, returns the name of the slice.
--- @arg id LONG the slice id which we need the name for.
 CREATE PERFETTO FUNCTION slice_name_from_id(
+  -- The slice id which we need the name for.
   id LONG
 )
 -- The name of slice with the given id.
@@ -253,4 +253,4 @@
 SELECT
   name
 FROM slice
-WHERE $id = id;
\ No newline at end of file
+WHERE $id = id;
diff --git a/src/trace_processor/perfetto_sql/stdlib/common/thread_states.sql b/src/trace_processor/perfetto_sql/stdlib/common/thread_states.sql
index 92818f8..d43d6a1 100644
--- a/src/trace_processor/perfetto_sql/stdlib/common/thread_states.sql
+++ b/src/trace_processor/perfetto_sql/stdlib/common/thread_states.sql
@@ -21,7 +21,7 @@
 -- but they are pretty niche.
 -- Translates the thread state name from a single-letter shorthard to
 -- a human-readable name.
-CREATE PERFETTO FUNCTION internal_translate_thread_state_name(name STRING)
+CREATE PERFETTO FUNCTION _translate_thread_state_name(name STRING)
 RETURNS STRING AS
 SELECT CASE $name
 WHEN 'Running' THEN 'Running'
@@ -50,7 +50,7 @@
 RETURNS STRING AS
 WITH data AS (
   SELECT
-    internal_translate_thread_state_name(state) AS state,
+    _translate_thread_state_name(state) AS state,
     (CASE io_wait
       WHEN 1 THEN ' (IO)'
       WHEN 0 THEN ' (non-IO)'
diff --git a/src/trace_processor/perfetto_sql/stdlib/common/timestamps.sql b/src/trace_processor/perfetto_sql/stdlib/common/timestamps.sql
index a9d8a5a..81b89a4 100644
--- a/src/trace_processor/perfetto_sql/stdlib/common/timestamps.sql
+++ b/src/trace_processor/perfetto_sql/stdlib/common/timestamps.sql
@@ -141,7 +141,7 @@
 -- Converts a duration in days to nanoseconds, which is the default
 -- representation of time durations in trace processor.
 CREATE PERFETTO FUNCTION days(
--- @arg days INT  Time duration in days.
+  -- Time duration in days.
   days INT
 )
 -- Time duration in nanoseconds.
diff --git a/src/trace_processor/perfetto_sql/stdlib/graphs/BUILD.gn b/src/trace_processor/perfetto_sql/stdlib/graphs/BUILD.gn
index 6172cf2..f7d3fca 100644
--- a/src/trace_processor/perfetto_sql/stdlib/graphs/BUILD.gn
+++ b/src/trace_processor/perfetto_sql/stdlib/graphs/BUILD.gn
@@ -15,5 +15,8 @@
 import("../../../../../gn/perfetto_sql.gni")
 
 perfetto_sql_source_set("graphs") {
-  sources = [ "dominator_tree.sql" ]
+  sources = [
+    "dominator_tree.sql",
+    "search.sql",
+  ]
 }
diff --git a/src/trace_processor/perfetto_sql/stdlib/graphs/dominator_tree.sql b/src/trace_processor/perfetto_sql/stdlib/graphs/dominator_tree.sql
index 58bb225..f79fcab 100644
--- a/src/trace_processor/perfetto_sql/stdlib/graphs/dominator_tree.sql
+++ b/src/trace_processor/perfetto_sql/stdlib/graphs/dominator_tree.sql
@@ -40,20 +40,22 @@
 -- WHERE root_type IS NOT NULL;
 --
 -- SELECT *
--- FROM dominator_tree!(
+-- FROM graph_dominator_tree!(
 --   dominator_compatible_heap_graph,
 --   (SELECT max(id) + 1 FROM heap_graph_object)
 -- );
 -- ```
---
--- @column node_id            The id of the node from the input graph.
--- @column dominator_node_id  The id of the node in the input flow-graph which is the
---                            "dominator" of |node_id|.
-CREATE PERFETTO MACRO dominator_tree(
+CREATE PERFETTO MACRO graph_dominator_tree(
   -- A table/view/subquery corresponding to a directed flow-graph on which the
   -- dominator tree should be computed. This table must have the columns
   -- "source_node_id" and "dest_node_id" corresponding to the two nodes on
-  -- either end of the edges of the graph.
+  -- either end of the edges in the graph.
+  --
+  -- Note: the columns must contain uint32 similar to ids in trace processor
+  -- tables (i.e. the values should be relatively dense and close to zero). The
+  -- implementation makes assumptions on this for performance reasons and, if
+  -- this criteria is not, can lead to enormous amounts of memory being
+  -- allocated.
   --
   -- Note: this means that the graph *must* be a single fully connected
   -- component with |root_node_id| (see below) being the "entry node" for this
@@ -65,6 +67,10 @@
   -- tree.
   root_node_id Expr
 )
+-- The returned table has the schema (node_id UINT32, dominator_node_id UINT32).
+-- |node_id| is the id of the node from the input graph and |dominator_node_id|
+-- is the id of the node in the input flow-graph which is the "dominator" of
+-- |node_id|.
 RETURNS TableOrSubquery AS
 (
   WITH __temp_graph_table AS (SELECT * FROM $graph_table)
diff --git a/src/trace_processor/perfetto_sql/stdlib/graphs/search.sql b/src/trace_processor/perfetto_sql/stdlib/graphs/search.sql
new file mode 100644
index 0000000..05cec80
--- /dev/null
+++ b/src/trace_processor/perfetto_sql/stdlib/graphs/search.sql
@@ -0,0 +1,69 @@
+--
+-- Copyright 2024 The Android Open Source Project
+--
+-- Licensed under the Apache License, Version 2.0 (the "License");
+-- you may not use this file except in compliance with the License.
+-- You may obtain a copy of the License at
+--
+--     https://www.apache.org/licenses/LICENSE-2.0
+--
+-- Unless required by applicable law or agreed to in writing, software
+-- distributed under the License is distributed on an "AS IS" BASIS,
+-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+-- See the License for the specific language governing permissions and
+-- limitations under the License.
+
+-- Computes the "reachable" set of nodes in a directed graph from a given
+-- starting node by performing a depth-first search on the graph. The returned
+-- nodes are structured as a tree with parent-child relationships corresponding
+-- to the order in which nodes were encountered by the DFS.
+--
+-- While this macro can be used directly by end users (hence being public),
+-- it is primarily intended as a lower-level building block upon which higher
+-- level functions/macros in the standard library can be built.
+--
+-- Example usage on traces containing heap graphs:
+--
+-- -- Compute the reachable nodes from the first heap root.
+-- SELECT *
+-- FROM graph_reachable_dfs!(
+--   (
+--     SELECT
+--       owner_id AS source_node_id,
+--       owned_id as dest_node_id
+--     FROM heap_graph_reference
+--     WHERE owned_id IS NOT NULL
+--   ),
+--   (SELECT id FROM heap_graph_object WHERE root_type IS NOT NULL LIMIT 1)
+-- );
+-- ```
+CREATE PERFETTO MACRO graph_reachable_dfs(
+  -- A table/view/subquery corresponding to a directed graph on which the
+  -- reachability search should be performed. This table must have the columns
+  -- "source_node_id" and "dest_node_id" corresponding to the two nodes on
+  -- either end of the edges in the graph.
+  --
+  -- Note: the columns must contain uint32 similar to ids in trace processor
+  -- tables (i.e. the values should be relatively dense and close to zero). The
+  -- implementation makes assumptions on this for performance reasons and, if
+  -- this criteria is not, can lead to enormous amounts of memory being
+  -- allocated.
+  graph_table TableOrSubquery,
+  -- The start node to |graph_table| which will be the root of the reachability
+  -- tree.
+  start_node_id Expr
+)
+-- The returned table has the schema (node_id UINT32, parent_node_id UINT32).
+-- |node_id| is the id of the node from the input graph and |parent_node_id|
+-- is the id of the node which was the first encountered predecessor in a DFS
+-- search of the graph.
+RETURNS TableOrSubquery AS
+(
+  WITH __temp_graph_table AS (SELECT * FROM $graph_table)
+  SELECT dt.node_id, dt.parent_node_id
+  FROM __intrinsic_dfs(
+    (SELECT RepeatedField(source_node_id) FROM __temp_graph_table),
+    (SELECT RepeatedField(dest_node_id) FROM __temp_graph_table),
+    $start_node_id
+  ) dt
+);
diff --git a/src/trace_processor/perfetto_sql/stdlib/intervals/overlap.sql b/src/trace_processor/perfetto_sql/stdlib/intervals/overlap.sql
index aca3baa..151d438 100644
--- a/src/trace_processor/perfetto_sql/stdlib/intervals/overlap.sql
+++ b/src/trace_processor/perfetto_sql/stdlib/intervals/overlap.sql
@@ -14,11 +14,10 @@
 -- limitations under the License.
 
 -- Compute the distribution of the overlap of the given intervals over time.
+--
 -- Each interval is a (ts, dur) pair and the overlap represented as a (ts, value)
 -- counter, with the value corresponding to the number of intervals that overlap
 -- the given timestamp and interval until the next timestamp.
--- @column ts     Timestamp when the number of open segments changed.
--- @column value  Number of open segments.
 CREATE PERFETTO MACRO intervals_overlap_count(
     -- Table or subquery containing interval data.
     segments TableOrSubquery,
@@ -26,6 +25,9 @@
     ts_column ColumnName,
     -- Column containing interval durations (usually `dur`).
     dur_column ColumnName)
+-- The returned table has the schema (ts INT64, value UINT32).
+-- |ts| is the timestamp when the number of open segments changed. |value| is
+-- the number of open segments.
 RETURNS TableOrSubquery AS
 (
 -- Algorithm: for each segment, emit a +1 at the start and a -1 at the end.
diff --git a/src/trace_processor/perfetto_sql/stdlib/linux/cpu_idle.sql b/src/trace_processor/perfetto_sql/stdlib/linux/cpu_idle.sql
index d7e9f5d..d4aeeb2 100644
--- a/src/trace_processor/perfetto_sql/stdlib/linux/cpu_idle.sql
+++ b/src/trace_processor/perfetto_sql/stdlib/linux/cpu_idle.sql
@@ -14,7 +14,7 @@
 -- limitations under the License.
 
 -- CPU frequency counter per core.
-CREATE PERFETTO VIEW internal_cpu_freq_counters
+CREATE PERFETTO VIEW _cpu_freq_counters
 AS
 SELECT
   ts,
@@ -27,7 +27,7 @@
 WHERE cct.name = 'cpufreq';
 
 -- CPU idle counter per core.
-CREATE PERFETTO VIEW internal_cpu_idle_counters
+CREATE PERFETTO VIEW _cpu_idle_counters
 AS
 SELECT
   ts,
@@ -41,9 +41,9 @@
 WHERE cct.name = 'cpuidle';
 
 -- Combined cpu freq & idle counter
-CREATE VIRTUAL TABLE internal_freq_idle_counters
+CREATE VIRTUAL TABLE _freq_idle_counters
 USING
-  span_join(internal_cpu_freq_counters PARTITIONED cpu, internal_cpu_idle_counters PARTITIONED cpu);
+  span_join(_cpu_freq_counters PARTITIONED cpu, _cpu_idle_counters PARTITIONED cpu);
 
 -- Aggregates cpu idle statistics per core.
 CREATE PERFETTO TABLE linux_cpu_idle_stats(
@@ -66,7 +66,7 @@
   SELECT
     cpu,
     sum(dur) AS dur
-  FROM internal_freq_idle_counters
+  FROM _freq_idle_counters
   GROUP BY cpu
 )
 SELECT
@@ -76,7 +76,6 @@
   SUM(dur) AS dur,
   SUM(dur) / COUNT(idle_value) AS avg_dur,
   SUM(dur) * 100.0 / (SELECT dur FROM total t WHERE t.cpu = ific.cpu) AS idle_percent
-FROM internal_freq_idle_counters ific
+FROM _freq_idle_counters ific
 WHERE idle_value >=0
 GROUP BY cpu, idle_value;
-
diff --git a/src/trace_processor/perfetto_sql/stdlib/prelude/slices.sql b/src/trace_processor/perfetto_sql/stdlib/prelude/slices.sql
index a669f04..24f470a 100644
--- a/src/trace_processor/perfetto_sql/stdlib/prelude/slices.sql
+++ b/src/trace_processor/perfetto_sql/stdlib/prelude/slices.sql
@@ -29,4 +29,39 @@
 FROM slice ancestor
 JOIN slice descendant
 WHERE ancestor.id = $ancestor_id
-  AND descendant.id = $descendant_id
\ No newline at end of file
+  AND descendant.id = $descendant_id;
+
+CREATE PERFETTO MACRO _interval_intersect(
+  left_table TableOrSubquery,
+  right_table TableOrSubquery
+)
+RETURNS TableOrSubquery AS
+(
+  WITH on_left AS (
+    SELECT
+      B.ts,
+      IIF(
+        A.ts + A.dur <= B.ts + B.dur,
+        A.ts + A.dur - B.ts, B.dur) AS dur,
+      A.id AS left_id,
+      B.id as right_id
+    FROM $left_table A
+    JOIN $right_table B ON (A.ts <= B.ts AND A.ts + A.dur > B.ts)
+  ), on_right AS (
+    SELECT
+      B.ts,
+      IIF(
+        A.ts + A.dur <= B.ts + B.dur,
+        A.ts + A.dur - B.ts, B.dur) AS dur,
+      B.id as left_id,
+      A.id AS right_id
+    FROM $right_table A
+    -- The difference between this table and on_left is the lack of equality on
+    -- A.ts <= B.ts. This is to remove the issue of double accounting
+    -- timestamps that start at the same time.
+    JOIN $left_table B ON (A.ts < B.ts AND A.ts + A.dur > B.ts)
+  )
+  SELECT * FROM on_left
+  UNION ALL
+  SELECT * FROM on_right
+);
\ No newline at end of file
diff --git a/src/trace_processor/perfetto_sql/stdlib/experimental/BUILD.gn b/src/trace_processor/perfetto_sql/stdlib/proto_path/BUILD.gn
similarity index 68%
copy from src/trace_processor/perfetto_sql/stdlib/experimental/BUILD.gn
copy to src/trace_processor/perfetto_sql/stdlib/proto_path/BUILD.gn
index d9a48c1..a0d9582 100644
--- a/src/trace_processor/perfetto_sql/stdlib/experimental/BUILD.gn
+++ b/src/trace_processor/perfetto_sql/stdlib/proto_path/BUILD.gn
@@ -1,4 +1,4 @@
-# Copyright (C) 2022 The Android Open Source Project
+# Copyright (C) 2023 The Android Open Source Project
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.
@@ -14,13 +14,6 @@
 
 import("../../../../../gn/perfetto_sql.gni")
 
-perfetto_sql_source_set("experimental") {
-  sources = [
-    "android_broadcast.sql",
-    "flat_slices.sql",
-    "proto_path.sql",
-    "slices.sql",
-    "thread_executing_span.sql",
-    "thread_state_flattened.sql",
-  ]
+perfetto_sql_source_set("proto_path") {
+  sources = [ "proto_path.sql" ]
 }
diff --git a/src/trace_processor/perfetto_sql/stdlib/experimental/proto_path.sql b/src/trace_processor/perfetto_sql/stdlib/proto_path/proto_path.sql
similarity index 94%
rename from src/trace_processor/perfetto_sql/stdlib/experimental/proto_path.sql
rename to src/trace_processor/perfetto_sql/stdlib/proto_path/proto_path.sql
index 5ab538c..46b3e65 100644
--- a/src/trace_processor/perfetto_sql/stdlib/experimental/proto_path.sql
+++ b/src/trace_processor/perfetto_sql/stdlib/proto_path/proto_path.sql
@@ -15,7 +15,7 @@
 
 -- Creates a Stack consisting of one frame for a path in the
 -- EXPERIMENTAL_PROTO_PATH table.
-CREATE PERFETTO FUNCTION experimental_proto_path_to_frame(
+CREATE PERFETTO FUNCTION _proto_path_to_frame(
 -- Id of the path in EXPERIMENTAL_PROTO_PATH.
   path_id LONG)
 -- Stack with one frame
@@ -31,7 +31,7 @@
 
 -- Creates a Stack following the parent relations in EXPERIMENTAL_PROTO_PATH
 -- table starting at the given path_id.
-CREATE PERFETTO FUNCTION experimental_proto_path_to_stack(
+CREATE PERFETTO FUNCTION _proto_path_to_stack(
 -- Id of the path in EXPERIMENTAL_PROTO_PATH that will be the leaf in the returned stack.
   path_id LONG)
 -- Stack
@@ -61,4 +61,4 @@
 SELECT stack
 FROM R
 WHERE
-  parent_id IS NULL;
\ No newline at end of file
+  parent_id IS NULL;
diff --git a/src/trace_processor/perfetto_sql/stdlib/sched/BUILD.gn b/src/trace_processor/perfetto_sql/stdlib/sched/BUILD.gn
index 143aff0..8e83d6f 100644
--- a/src/trace_processor/perfetto_sql/stdlib/sched/BUILD.gn
+++ b/src/trace_processor/perfetto_sql/stdlib/sched/BUILD.gn
@@ -15,5 +15,9 @@
 import("../../../../../gn/perfetto_sql.gni")
 
 perfetto_sql_source_set("sched") {
-  sources = [ "thread_level_parallelism.sql" ]
+  sources = [
+    "thread_executing_span.sql",
+    "thread_level_parallelism.sql",
+    "thread_state_flattened.sql",
+  ]
 }
diff --git a/src/trace_processor/perfetto_sql/stdlib/experimental/thread_executing_span.sql b/src/trace_processor/perfetto_sql/stdlib/sched/thread_executing_span.sql
similarity index 77%
rename from src/trace_processor/perfetto_sql/stdlib/experimental/thread_executing_span.sql
rename to src/trace_processor/perfetto_sql/stdlib/sched/thread_executing_span.sql
index a02370e..8e74d2f 100644
--- a/src/trace_processor/perfetto_sql/stdlib/experimental/thread_executing_span.sql
+++ b/src/trace_processor/perfetto_sql/stdlib/sched/thread_executing_span.sql
@@ -15,7 +15,7 @@
 --
 
 INCLUDE PERFETTO MODULE common.slices;
-INCLUDE PERFETTO MODULE experimental.flat_slices;
+INCLUDE PERFETTO MODULE slices.flat_slices;
 
 -- A 'thread_executing_span' is thread_state span starting with a runnable slice
 -- until the next runnable slice that's woken up by a process (as opposed
@@ -34,7 +34,7 @@
 -- so this table might contain wakeups from interrupt context, consequently, the
 -- wakeup graph generated might not be accurate.
 --
-CREATE PERFETTO VIEW internal_runnable_state
+CREATE PERFETTO VIEW _runnable_state
 AS
 SELECT
   thread_state.id,
@@ -47,8 +47,8 @@
 WHERE thread_state.dur != -1 AND thread_state.waker_utid IS NOT NULL
    AND (thread_state.irq_context = 0 OR thread_state.irq_context IS NULL);
 
--- Similar to |internal_runnable_state| but finds the first runnable state at thread.
-CREATE PERFETTO VIEW internal_first_runnable_state
+-- Similar to |_runnable_state| but finds the first runnable state at thread.
+CREATE PERFETTO VIEW _first_runnable_state
 AS
 WITH
   first_state AS (
@@ -70,7 +70,7 @@
 
 --
 -- Finds all sleep states including interruptible (S) and uninterruptible (D).
-CREATE PERFETTO VIEW internal_sleep_state
+CREATE PERFETTO VIEW _sleep_state
 AS
 SELECT
   thread_state.id,
@@ -85,7 +85,7 @@
 --
 -- Finds the last execution for every thread to end executing_spans without a Sleep.
 --
-CREATE PERFETTO VIEW internal_thread_end_ts
+CREATE PERFETTO VIEW _thread_end_ts
 AS
 SELECT
   MAX(ts) + dur AS end_ts,
@@ -94,8 +94,8 @@
 WHERE dur != -1
 GROUP BY utid;
 
--- Similar to |internal_sleep_state| but finds the first sleep state in a thread.
-CREATE PERFETTO VIEW internal_first_sleep_state
+-- Similar to |_sleep_state| but finds the first sleep state in a thread.
+CREATE PERFETTO VIEW _first_sleep_state
 AS
 SELECT
   MIN(s.id) AS id,
@@ -104,8 +104,8 @@
   s.state,
   s.blocked_function,
   s.utid
-FROM internal_sleep_state s
-JOIN internal_runnable_state r
+FROM _sleep_state s
+JOIN _runnable_state r
   ON s.utid = r.utid AND (s.ts + s.dur = r.ts)
 GROUP BY s.utid;
 
@@ -114,8 +114,8 @@
 -- More succintly, pairs of S[n-1]-R[n] where R is woken by a process context and S is an
 -- interruptible or uninterruptible sleep state.
 --
--- This is achieved by joining the |internal_runnable_state|.ts with the
--- |internal_sleep_state|.|ts + dur|.
+-- This is achieved by joining the |_runnable_state|.ts with the
+-- |_sleep_state|.|ts + dur|.
 --
 -- With the S-R pairs of a thread, we can re-align to [R-S) intervals with LEADS and LAGS.
 --
@@ -145,7 +145,7 @@
 -- end_ts           = S1_ts.
 -- end_dur          = S1_dur.
 -- end_state        = 'S' or 'D'.
-CREATE TABLE internal_wakeup AS
+CREATE TABLE _wakeup AS
   SELECT
   LAG(r.id, 1) OVER (PARTITION BY r.utid ORDER BY r.ts) AS prev_start_id,
   LAG(r.ts, 1) OVER (PARTITION BY r.utid ORDER BY r.ts) AS prev_start_ts,
@@ -167,10 +167,10 @@
   LEAD(s.dur, 1) OVER (PARTITION BY r.utid ORDER BY r.ts) AS end_dur,
   LEAD(s.state, 1) OVER (PARTITION BY r.utid ORDER BY r.ts) AS end_state,
   LEAD(s.blocked_function, 1) OVER (PARTITION BY r.utid ORDER BY r.ts) AS blocked_function
-FROM internal_runnable_state r
-JOIN internal_sleep_state s
+FROM _runnable_state r
+JOIN _sleep_state s
   ON s.utid = r.utid AND (s.ts + s.dur = r.ts)
-LEFT JOIN internal_thread_end_ts thread_end USING(utid)
+LEFT JOIN _thread_end_ts thread_end USING(utid)
 UNION ALL
   SELECT
   NULL AS prev_start_id,
@@ -193,15 +193,15 @@
   s.dur AS end_dur,
   s.state AS end_state,
   s.blocked_function AS blocked_function
-FROM internal_first_runnable_state r
-LEFT JOIN internal_first_sleep_state s
+FROM _first_runnable_state r
+LEFT JOIN _first_sleep_state s
   ON s.utid = r.utid
-LEFT JOIN internal_thread_end_ts thread_end USING(utid);
+LEFT JOIN _thread_end_ts thread_end USING(utid);
 
--- Improves performance of |internal_wakeup_chain| computation.
+-- Improves performance of |_wakeup_chain| computation.
 CREATE
-  INDEX internal_wakeup_idx
-ON internal_wakeup(waker_utid, start_ts);
+  INDEX _wakeup_idx
+ON _wakeup(waker_utid, start_ts);
 
 --
 -- Builds the parent-child chain from all thread_executing_spans. The parent is the waker and
@@ -210,54 +210,54 @@
 -- Note that this doesn't include the roots. We'll compute the roots below.
 -- This two step process improves performance because it's more efficient to scan
 -- parent and find a child between than to scan child and find the parent it lies between.
-CREATE PERFETTO VIEW internal_wakeup_chain
+CREATE PERFETTO VIEW _wakeup_chain
 AS
 SELECT parent.start_id AS parent_id, child.*
-FROM internal_wakeup parent
-JOIN internal_wakeup child
+FROM _wakeup parent
+JOIN _wakeup child
   ON (
     parent.utid = child.waker_utid
     AND child.start_ts BETWEEN parent.start_ts AND parent.end_ts);
 
 --
--- Finds the roots of the |internal_wakeup_chain|.
-CREATE PERFETTO TABLE internal_wakeup_root
+-- Finds the roots of the |_wakeup_chain|.
+CREATE PERFETTO TABLE _wakeup_root
 AS
 WITH
-  internal_wakeup_root_id AS (
-    SELECT DISTINCT parent_id AS id FROM internal_wakeup_chain
+  _wakeup_root_id AS (
+    SELECT DISTINCT parent_id AS id FROM _wakeup_chain
     EXCEPT
-    SELECT DISTINCT start_id AS id FROM internal_wakeup_chain
+    SELECT DISTINCT start_id AS id FROM _wakeup_chain
   )
-SELECT NULL AS parent_id, internal_wakeup.*
-FROM internal_wakeup
-JOIN internal_wakeup_root_id
-  ON internal_wakeup_root_id.id = internal_wakeup.start_id;
+SELECT NULL AS parent_id, _wakeup.*
+FROM _wakeup
+JOIN _wakeup_root_id
+  ON _wakeup_root_id.id = _wakeup.start_id;
 
 --
--- Finds the leafs of the |internal_wakeup_chain|.
-CREATE PERFETTO TABLE internal_wakeup_leaf AS
+-- Finds the leafs of the |_wakeup_chain|.
+CREATE PERFETTO TABLE _wakeup_leaf AS
 WITH
-  internal_wakeup_leaf_id AS (
-    SELECT DISTINCT start_id AS id FROM internal_wakeup_chain
+  _wakeup_leaf_id AS (
+    SELECT DISTINCT start_id AS id FROM _wakeup_chain
     EXCEPT
-    SELECT DISTINCT parent_id AS id FROM internal_wakeup_chain
+    SELECT DISTINCT parent_id AS id FROM _wakeup_chain
   )
-SELECT internal_wakeup_chain.*
-FROM internal_wakeup_chain
-JOIN internal_wakeup_leaf_id
-  ON internal_wakeup_leaf_id.id = internal_wakeup_chain.start_id;
+SELECT _wakeup_chain.*
+FROM _wakeup_chain
+JOIN _wakeup_leaf_id
+  ON _wakeup_leaf_id.id = _wakeup_chain.start_id;
 
 --
 -- Merges the roots, leafs and the rest of the chain.
-CREATE TABLE internal_wakeup_graph
+CREATE TABLE _wakeup_graph
 AS
-SELECT internal_wakeup_chain.*, 0 AS is_root, (internal_wakeup_leaf.start_id IS NOT NULL) AS is_leaf
-FROM internal_wakeup_chain
-LEFT JOIN internal_wakeup_leaf
+SELECT _wakeup_chain.*, 0 AS is_root, (_wakeup_leaf.start_id IS NOT NULL) AS is_leaf
+FROM _wakeup_chain
+LEFT JOIN _wakeup_leaf
   USING (start_id)
 UNION ALL
-SELECT *, 1 AS is_root, 0 AS is_leaf FROM internal_wakeup_root;
+SELECT *, 1 AS is_root, 0 AS is_leaf FROM _wakeup_root;
 
 -- Thread_executing_span graph of all wakeups across all processes.
 --
@@ -273,7 +273,7 @@
 -- @column blocked_function   Kernel blocked_function of thread state before waking up.
 -- @column is_root            Whether the thread_executing_span is a root.
 -- @column depth              Tree depth of thread executing span from the root.
-CREATE TABLE experimental_thread_executing_span_graph AS
+CREATE TABLE _thread_executing_span_graph AS
 WITH roots AS (
 SELECT
   start_id AS root_id,
@@ -288,7 +288,7 @@
   prev_blocked_function AS blocked_function,
   1 AS is_root,
   0 AS depth
-FROM internal_wakeup_root
+FROM _wakeup_root
 ), chain AS (
   SELECT * FROM roots
   UNION ALL
@@ -305,18 +305,18 @@
     graph.prev_blocked_function AS blocked_function,
     0 AS is_root,
     chain.depth + 1 AS depth
-  FROM internal_wakeup_graph graph
+  FROM _wakeup_graph graph
   JOIN chain ON chain.id = graph.parent_id
 ) SELECT chain.*, thread.upid FROM chain LEFT JOIN thread USING(utid);
 
 -- It finds the MAX between the start of the critical span and the start
 -- of the blocked region. This ensures that the critical path doesn't overlap
 -- the preceding thread_executing_span before the blocked region.
-CREATE PERFETTO FUNCTION internal_critical_path_start_ts(ts LONG, leaf_blocked_ts LONG)
+CREATE PERFETTO FUNCTION _critical_path_start_ts(ts LONG, leaf_blocked_ts LONG)
 RETURNS LONG AS SELECT MAX($ts, IFNULL($leaf_blocked_ts, $ts));
 
--- See |experimental_thread_executing_span_critical_path|
-CREATE PERFETTO TABLE internal_critical_path
+-- See |_thread_executing_span_critical_path|
+CREATE PERFETTO TABLE _critical_path
 AS
 WITH chain AS (
   SELECT
@@ -332,14 +332,14 @@
     blocked_function AS critical_path_blocked_function,
     utid AS critical_path_utid,
     upid AS critical_path_upid
-  FROM experimental_thread_executing_span_graph graph
+  FROM _thread_executing_span_graph graph
   UNION ALL
   SELECT
     graph.parent_id,
     graph.id,
-    internal_critical_path_start_ts(graph.ts, chain.critical_path_blocked_ts) AS ts,
-    MIN(internal_critical_path_start_ts(graph.ts, chain.critical_path_blocked_ts) + graph.dur, chain.ts)
-      - internal_critical_path_start_ts(graph.ts, chain.critical_path_blocked_ts) AS dur,
+    _critical_path_start_ts(graph.ts, chain.critical_path_blocked_ts) AS ts,
+    MIN(_critical_path_start_ts(graph.ts, chain.critical_path_blocked_ts) + graph.dur, chain.ts)
+      - _critical_path_start_ts(graph.ts, chain.critical_path_blocked_ts) AS dur,
     graph.utid,
     chain.critical_path_id,
     chain.critical_path_blocked_ts,
@@ -348,7 +348,7 @@
     chain.critical_path_blocked_function,
     chain.critical_path_utid,
     chain.critical_path_upid
-  FROM experimental_thread_executing_span_graph graph
+  FROM _thread_executing_span_graph graph
   JOIN chain ON (chain.parent_id = graph.id AND (chain.ts > chain.critical_path_blocked_ts))
 ) SELECT * FROM chain;
 
@@ -356,7 +356,7 @@
 -- every sleeping thread state is computed and unioned with the thread executing spans on that thread.
 -- The duration of a thread executing span in the critical path is the range between the start of the
 -- thread_executing_span and the start of the next span in the critical path.
-CREATE PERFETTO FUNCTION experimental_thread_executing_span_critical_path(
+CREATE PERFETTO FUNCTION _thread_executing_span_critical_path(
   -- Utid of the thread to compute the critical path for.
   critical_path_utid INT,
   -- Timestamp.
@@ -394,7 +394,7 @@
       critical_path_blocked_state,
       critical_path_blocked_function,
       critical_path_utid
-    FROM internal_critical_path span
+    FROM _critical_path span
     WHERE (($critical_path_utid IS NOT NULL AND span.critical_path_utid = $critical_path_utid) OR ($critical_path_utid IS NULL))
       AND ((ts BETWEEN $ts AND $ts + $dur) OR ($ts BETWEEN ts AND ts + dur))
 ) SELECT
@@ -409,19 +409,19 @@
       critical_path_utid
    FROM span_starts;
 
--- Limited thread_state view that will later be span joined with the |experimental_thread_executing_span_graph|.
-CREATE PERFETTO VIEW internal_span_thread_state_view
+-- Limited thread_state view that will later be span joined with the |_thread_executing_span_graph|.
+CREATE PERFETTO VIEW _span_thread_state_view
 AS SELECT id AS thread_state_id, ts, dur, utid, state, blocked_function as function, io_wait, cpu FROM thread_state;
 
--- |experimental_thread_executing_span_graph| span joined with thread_state information.
-CREATE VIRTUAL TABLE internal_span_graph_thread_state_sp
+-- |_thread_executing_span_graph| span joined with thread_state information.
+CREATE VIRTUAL TABLE _span_graph_thread_state_sp
 USING
   SPAN_JOIN(
-    experimental_thread_executing_span_graph PARTITIONED utid,
-    internal_span_thread_state_view PARTITIONED utid);
+    _thread_executing_span_graph PARTITIONED utid,
+    _span_thread_state_view PARTITIONED utid);
 
--- Limited slice_view that will later be span joined with the |experimental_thread_executing_span_graph|.
-CREATE PERFETTO VIEW internal_span_slice_view
+-- Limited slice_view that will later be span joined with the |_thread_executing_span_graph|.
+CREATE PERFETTO VIEW _span_slice_view
 AS
 SELECT
   slice_id,
@@ -430,31 +430,31 @@
   CAST(ts AS INT) AS ts,
   CAST(dur AS INT) AS dur,
   utid
-FROM experimental_slice_flattened;
+FROM _slice_flattened;
 
--- |experimental_thread_executing_span_graph| span joined with slice information.
-CREATE VIRTUAL TABLE internal_span_graph_slice_sp
+-- |_thread_executing_span_graph| span joined with slice information.
+CREATE VIRTUAL TABLE _span_graph_slice_sp
 USING
   SPAN_JOIN(
-    experimental_thread_executing_span_graph PARTITIONED utid,
-    internal_span_slice_view PARTITIONED utid);
+    _thread_executing_span_graph PARTITIONED utid,
+    _span_slice_view PARTITIONED utid);
 
--- Limited |experimental_thread_executing_span_graph| + thread_state view.
-CREATE PERFETTO VIEW internal_span_graph_thread_state
+-- Limited |_thread_executing_span_graph| + thread_state view.
+CREATE PERFETTO VIEW _span_graph_thread_state
 AS
 SELECT ts, dur, id, thread_state_id, state, function, io_wait, cpu
-FROM internal_span_graph_thread_state_sp;
+FROM _span_graph_thread_state_sp;
 
--- Limited |experimental_thread_executing_span_graph| + slice view.
-CREATE PERFETTO VIEW internal_span_graph_slice
+-- Limited |_thread_executing_span_graph| + slice view.
+CREATE PERFETTO VIEW _span_graph_slice
 AS
 SELECT ts, dur, id, slice_id, slice_depth, slice_name
-FROM internal_span_graph_slice_sp;
+FROM _span_graph_slice_sp;
 
--- |experimental_thread_executing_span_graph| + thread_state view joined with critical_path information.
-CREATE PERFETTO TABLE internal_critical_path_thread_state AS
+-- |_thread_executing_span_graph| + thread_state view joined with critical_path information.
+CREATE PERFETTO TABLE _critical_path_thread_state AS
 WITH span AS MATERIALIZED (
-    SELECT * FROM internal_critical_path
+    SELECT * FROM _critical_path
   ),
   span_starts AS (
     SELECT
@@ -474,7 +474,7 @@
       thread_state.cpu,
       thread_state.io_wait
     FROM span
-    JOIN internal_span_graph_thread_state_sp thread_state USING(id)
+    JOIN _span_graph_thread_state_sp thread_state USING(id)
   )
 SELECT
   id,
@@ -494,21 +494,21 @@
 FROM span_starts
 WHERE MIN(span_end_ts, thread_state_end_ts) - ts > 0;
 
--- |experimental_thread_executing_span_graph| + thread_state + critical_path span joined with
--- |experimental_thread_executing_span_graph| + slice view.
-CREATE VIRTUAL TABLE internal_critical_path_sp
+-- |_thread_executing_span_graph| + thread_state + critical_path span joined with
+-- |_thread_executing_span_graph| + slice view.
+CREATE VIRTUAL TABLE _critical_path_sp
 USING
   SPAN_LEFT_JOIN(
-    internal_critical_path_thread_state PARTITIONED id,
-     internal_span_graph_slice PARTITIONED id);
+    _critical_path_thread_state PARTITIONED id,
+     _span_graph_slice PARTITIONED id);
 
 -- Flattened slices span joined with their thread_states. This contains the 'self' information
 -- without 'critical_path' (blocking) information.
-CREATE VIRTUAL TABLE internal_self_sp USING
-  SPAN_LEFT_JOIN(thread_state PARTITIONED utid, experimental_slice_flattened PARTITIONED utid);
+CREATE VIRTUAL TABLE _self_sp USING
+  SPAN_LEFT_JOIN(thread_state PARTITIONED utid, _slice_flattened PARTITIONED utid);
 
--- Limited view of |internal_self_sp|.
-CREATE PERFETTO VIEW internal_self_view
+-- Limited view of |_self_sp|.
+CREATE PERFETTO VIEW _self_view
   AS
   SELECT
     id AS self_thread_state_id,
@@ -522,18 +522,18 @@
     io_wait AS self_io_wait,
     name AS self_slice_name,
     depth AS self_slice_depth
-    FROM internal_self_sp;
+    FROM _self_sp;
 
 -- Self and critical path span join. This contains the union of the time intervals from the following:
 --  a. Self slice stack + thread_state.
 --  b. Critical path stack + thread_state.
-CREATE VIRTUAL TABLE internal_self_and_critical_path_sp
+CREATE VIRTUAL TABLE _self_and_critical_path_sp
 USING
   SPAN_JOIN(
-    internal_self_view PARTITIONED critical_path_utid,
-    internal_critical_path_sp PARTITIONED critical_path_utid);
+    _self_view PARTITIONED critical_path_utid,
+    _critical_path_sp PARTITIONED critical_path_utid);
 
--- Returns a view of |internal_self_and_critical_path_sp| unpivoted over the following columns:
+-- Returns a view of |_self_and_critical_path_sp| unpivoted over the following columns:
 -- self thread_state.
 -- self blocked_function (if one exists).
 -- self process_name (enabled with |enable_process_name|).
@@ -545,7 +545,7 @@
 -- critical_path slice_stack (enabled with |enable_critical_path_slice|).
 -- running cpu (if one exists).
 -- A 'stack' is the group of resulting unpivoted rows sharing the same timestamp.
-CREATE PERFETTO FUNCTION internal_critical_path_stack(critical_path_utid INT, ts LONG, dur LONG, enable_process_name INT, enable_thread_name INT, enable_self_slice INT, enable_critical_path_slice INT)
+CREATE PERFETTO FUNCTION _critical_path_stack(critical_path_utid INT, ts LONG, dur LONG, enable_process_name INT, enable_thread_name INT, enable_self_slice INT, enable_critical_path_slice INT)
 RETURNS
   TABLE(
     id INT,
@@ -580,7 +580,7 @@
       MAX(ts, $ts) AS ts,
       MIN(ts + dur, $ts + $dur) AS end_ts,
       critical_path_utid
-    FROM internal_self_and_critical_path_sp
+    FROM _self_and_critical_path_sp
     WHERE dur > 0 AND critical_path_utid = $critical_path_utid
   ),
   -- This is the final step that gets the |dur| of each span from the start and
@@ -883,34 +883,36 @@
 -- stacked from top to bottom: self thread_state, self blocked_function, self process_name,
 -- self thread_name, slice stack, critical_path thread_state, critical_path process_name,
 -- critical_path thread_name, critical_path slice_stack, running_cpu.
---
--- @arg critical_path_utid INT    Thread utid to filter critical paths to.
--- @arg ts LONG                   Timestamp of start of time range to filter critical paths to.
--- @arg dur LONG                  Duration of time range to filter critical paths to.
---
--- @column id                     Id of the thread_state or slice in the thread_executing_span.
--- @column ts                     Timestamp of slice in the critical path.
--- @column dur                    Duration of slice in the critical path.
--- @column utid                   Utid of thread that emitted the slice.
--- @column stack_depth            Stack depth of the entitity in the debug track.
--- @column name                   Name of entity in the critical path (could be a thread_state, kernel blocked_function, process_name, thread_name, slice name or cpu).
--- @column table_name             Table name of entity in the critical path (could be either slice or thread_state).
--- @column critical_path_utid     Thread Utid the critical path was filtered to.
-CREATE PERFETTO FUNCTION experimental_thread_executing_span_critical_path_stack(critical_path_utid INT, ts LONG, dur LONG)
+CREATE PERFETTO FUNCTION _thread_executing_span_critical_path_stack(
+  -- Thread utid to filter critical paths to.
+  critical_path_utid INT,
+  -- Timestamp of start of time range to filter critical paths to.
+  ts LONG,
+  -- Duration of time range to filter critical paths to.
+  dur LONG)
 RETURNS
   TABLE(
+    -- Id of the thread_state or slice in the thread_executing_span.
     id INT,
+    -- Timestamp of slice in the critical path.
     ts LONG,
+    -- Duration of slice in the critical path.
     dur LONG,
+    -- Utid of thread that emitted the slice.
     utid INT,
+    -- Stack depth of the entitity in the debug track.
     stack_depth INT,
+    -- Name of entity in the critical path (could be a thread_state, kernel blocked_function, process_name, thread_name, slice name or cpu).
     name STRING,
+    -- Table name of entity in the critical path (could be either slice or thread_state).
     table_name STRING,
-    critical_path_utid INT) AS
-SELECT * FROM internal_critical_path_stack($critical_path_utid, $ts, $dur, 1, 1, 1, 1);
+    -- Utid of the thread the critical path was filtered to.
+    critical_path_utid INT
+) AS
+SELECT * FROM _critical_path_stack($critical_path_utid, $ts, $dur, 1, 1, 1, 1);
 
--- Returns a pprof aggregation of the stacks in |internal_critical_path_stack|.
-CREATE PERFETTO FUNCTION internal_critical_path_graph(graph_title STRING, critical_path_utid INT, ts LONG, dur LONG, enable_process_name INT, enable_thread_name INT, enable_self_slice INT, enable_critical_path_slice INT)
+-- Returns a pprof aggregation of the stacks in |_critical_path_stack|.
+CREATE PERFETTO FUNCTION _critical_path_graph(graph_title STRING, critical_path_utid INT, ts LONG, dur LONG, enable_process_name INT, enable_thread_name INT, enable_self_slice INT, enable_critical_path_slice INT)
 RETURNS TABLE(pprof BYTES)
 AS
 WITH
@@ -923,7 +925,7 @@
       critical_path_utid,
       stack_depth
     FROM
-      internal_critical_path_stack($critical_path_utid, $ts, $dur, $enable_process_name, $enable_thread_name, $enable_self_slice, $enable_critical_path_slice)
+      _critical_path_stack($critical_path_utid, $ts, $dur, $enable_process_name, $enable_thread_name, $enable_self_slice, $enable_critical_path_slice)
   ),
   graph AS (
     SELECT CAT_STACKS($graph_title) AS stack
@@ -960,8 +962,8 @@
   )
 SELECT EXPERIMENTAL_PROFILE(stack, 'duration', 'ns', dur) AS pprof FROM stacks;
 
--- Returns a pprof aggreagation of the stacks in |experimental_thread_executing_span_critical_path_stack|
-CREATE PERFETTO FUNCTION experimental_thread_executing_span_critical_path_graph(
+-- Returns a pprof aggreagation of the stacks in |_thread_executing_span_critical_path_stack|
+CREATE PERFETTO FUNCTION _thread_executing_span_critical_path_graph(
   -- Descriptive name for the graph.
   graph_title STRING,
   -- Thread utid to filter critical paths to.
@@ -975,4 +977,4 @@
   pprof BYTES
 )
 AS
-SELECT * FROM internal_critical_path_graph($graph_title, $critical_path_utid, $ts, $dur, 1, 1, 1, 1);
+SELECT * FROM _critical_path_graph($graph_title, $critical_path_utid, $ts, $dur, 1, 1, 1, 1);
diff --git a/src/trace_processor/perfetto_sql/stdlib/experimental/thread_state_flattened.sql b/src/trace_processor/perfetto_sql/stdlib/sched/thread_state_flattened.sql
similarity index 89%
rename from src/trace_processor/perfetto_sql/stdlib/experimental/thread_state_flattened.sql
rename to src/trace_processor/perfetto_sql/stdlib/sched/thread_state_flattened.sql
index 0574382..2ba1406 100644
--- a/src/trace_processor/perfetto_sql/stdlib/experimental/thread_state_flattened.sql
+++ b/src/trace_processor/perfetto_sql/stdlib/sched/thread_state_flattened.sql
@@ -13,18 +13,18 @@
 -- See the License for the specific language governing permissions and
 -- limitations under the License.
 
-INCLUDE PERFETTO MODULE experimental.flat_slices;
+INCLUDE PERFETTO MODULE slices.flat_slices;
 
 -- Create a table which joins the thread state across the flattened slices.
-CREATE VIRTUAL TABLE internal_experimental_span_joined_thread USING
-  SPAN_JOIN(experimental_slice_flattened PARTITIONED utid, thread_state PARTITIONED utid);
+CREATE VIRTUAL TABLE __span_joined_thread USING
+  SPAN_JOIN(_slice_flattened PARTITIONED utid, thread_state PARTITIONED utid);
 
 -- Get the thread state breakdown of a flattened slice from its slice id.
 -- This table pivoted and summed for better visualization and aggregation.
 -- The concept of a "flat slice" is to take the data in the slice table and
 -- remove all notion of nesting. For more information, read the description
--- of experimental_slice_flattened.
-CREATE PERFETTO FUNCTION experimental_get_flattened_thread_state(
+-- of _slice_flattened.
+CREATE PERFETTO FUNCTION _get_flattened_thread_state(
   -- Id of the slice of interest.
   slice_id LONG,
   -- Utid.
@@ -84,7 +84,7 @@
   blocked_function,
   waker_utid,
   irq_context
-FROM internal_experimental_span_joined_thread
+FROM __span_joined_thread
 WHERE
   track_id = (SELECT track_id FROM interesting_slice)
   AND ts >= (SELECT ts FROM interesting_slice)
@@ -94,8 +94,8 @@
 -- This table pivoted and summed for better visualization and aggragation.
 -- The concept of a "flat slice" is to take the data in the slice table and
 -- remove all notion of nesting. For more information, read the description
--- of experimental_slice_flattened.
-CREATE PERFETTO FUNCTION experimental_get_flattened_thread_state_aggregated(
+-- of _slice_flattened.
+CREATE PERFETTO FUNCTION _get_flattened_thread_state_aggregated(
   -- Slice id.
   slice_id LONG,
   -- Utid.
@@ -145,7 +145,7 @@
 WITH
 final_table AS (
   SELECT *
-  FROM experimental_get_flattened_thread_state($slice_id, $utid)
+  FROM _get_flattened_thread_state($slice_id, $utid)
 )
 SELECT
 fs.slice_id,
diff --git a/src/trace_processor/perfetto_sql/stdlib/experimental/BUILD.gn b/src/trace_processor/perfetto_sql/stdlib/slices/BUILD.gn
similarity index 75%
rename from src/trace_processor/perfetto_sql/stdlib/experimental/BUILD.gn
rename to src/trace_processor/perfetto_sql/stdlib/slices/BUILD.gn
index d9a48c1..ac79369 100644
--- a/src/trace_processor/perfetto_sql/stdlib/experimental/BUILD.gn
+++ b/src/trace_processor/perfetto_sql/stdlib/slices/BUILD.gn
@@ -1,4 +1,4 @@
-# Copyright (C) 2022 The Android Open Source Project
+# Copyright (C) 2023 The Android Open Source Project
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.
@@ -14,13 +14,9 @@
 
 import("../../../../../gn/perfetto_sql.gni")
 
-perfetto_sql_source_set("experimental") {
+perfetto_sql_source_set("slices") {
   sources = [
-    "android_broadcast.sql",
     "flat_slices.sql",
-    "proto_path.sql",
     "slices.sql",
-    "thread_executing_span.sql",
-    "thread_state_flattened.sql",
   ]
 }
diff --git a/src/trace_processor/perfetto_sql/stdlib/experimental/flat_slices.sql b/src/trace_processor/perfetto_sql/stdlib/slices/flat_slices.sql
similarity index 93%
rename from src/trace_processor/perfetto_sql/stdlib/experimental/flat_slices.sql
rename to src/trace_processor/perfetto_sql/stdlib/slices/flat_slices.sql
index 4b1d69e..4353ed2 100644
--- a/src/trace_processor/perfetto_sql/stdlib/experimental/flat_slices.sql
+++ b/src/trace_processor/perfetto_sql/stdlib/slices/flat_slices.sql
@@ -28,9 +28,14 @@
 -- Note that, no slices will be generated for intervals without without any slices.
 --
 -- As an example, consider the following slice stack:
+-- ```
 -- A-------------B.
 -- ----C----D----.
--- The flattened slice will be: A----C----D----B.
+-- ```
+-- The flattened slice will be:
+-- ```
+-- A----C----D----B.
+-- ```
 --
 -- @column slice_id           Id of most active slice.
 -- @column ts                 Timestamp when `slice.id` became the most active slice.
@@ -46,7 +51,7 @@
 -- @column upid               Alias for `process.upid`.
 -- @column pid                Alias for `process.pid`.
 -- @column process_name       Alias for `process.name`.
-CREATE TABLE experimental_slice_flattened AS
+CREATE TABLE _slice_flattened AS
 -- The algorithm proceeds as follows:
 -- 1. Find the start and end timestamps of all slices.
 -- 2. Iterate the generated timestamps within a stack in chronoligical order.
@@ -97,9 +102,9 @@
 WHERE depth != -1;
 
 CREATE
-  INDEX experimental_slice_flattened_id_idx
-ON experimental_slice_flattened(slice_id);
+  INDEX _slice_flattened_id_idx
+ON _slice_flattened(slice_id);
 
 CREATE
-  INDEX experimental_slice_flattened_ts_idx
-ON experimental_slice_flattened(ts);
+  INDEX _slice_flattened_ts_idx
+ON _slice_flattened(ts);
diff --git a/src/trace_processor/perfetto_sql/stdlib/experimental/slices.sql b/src/trace_processor/perfetto_sql/stdlib/slices/slices.sql
similarity index 97%
rename from src/trace_processor/perfetto_sql/stdlib/experimental/slices.sql
rename to src/trace_processor/perfetto_sql/stdlib/slices/slices.sql
index 757e7b0..20383b3 100644
--- a/src/trace_processor/perfetto_sql/stdlib/experimental/slices.sql
+++ b/src/trace_processor/perfetto_sql/stdlib/slices/slices.sql
@@ -19,7 +19,7 @@
 -- `thread_slice` and `process_slice`, this view contains all slices,
 -- with thread- and process-related columns set to NULL if the slice
 -- is not associated with a thread or a process.
-CREATE PERFETTO VIEW experimental_slice_with_thread_and_process_info(
+CREATE PERFETTO VIEW _slice_with_thread_and_process_info(
   -- Alias for `slice.id`.
   id INT,
   -- Alias for `slice.type`.
diff --git a/src/trace_processor/sqlite/db_sqlite_table.cc b/src/trace_processor/sqlite/db_sqlite_table.cc
index 9753e76..c59b9ea 100644
--- a/src/trace_processor/sqlite/db_sqlite_table.cc
+++ b/src/trace_processor/sqlite/db_sqlite_table.cc
@@ -156,13 +156,13 @@
 base::Status DbSqliteTable::Init(int, const char* const*, Schema* schema) {
   switch (context_->computation) {
     case TableComputation::kStatic:
-      schema_ = context_->static_table->ComputeSchema();
+      schema_ = context_->static_schema;
       break;
     case TableComputation::kRuntime:
       runtime_table_ = context_->get_runtime_table(name());
       PERFETTO_CHECK(runtime_table_);
       PERFETTO_CHECK(!runtime_table_->columns().empty());
-      schema_ = runtime_table_->ComputeSchema();
+      schema_ = runtime_table_->schema();
       break;
     case TableComputation::kTableFunction:
       schema_ = context_->static_table_function->CreateSchema();
@@ -759,10 +759,12 @@
 }
 
 DbSqliteTableContext::DbSqliteTableContext(QueryCache* query_cache,
-                                           const Table* table)
+                                           const Table* table,
+                                           Table::Schema schema)
     : cache(query_cache),
       computation(Computation::kStatic),
-      static_table(table) {}
+      static_table(table),
+      static_schema(std::move(schema)) {}
 
 DbSqliteTableContext::DbSqliteTableContext(
     QueryCache* query_cache,
@@ -770,8 +772,8 @@
     std::function<void(std::string)> erase_table)
     : cache(query_cache),
       computation(Computation::kRuntime),
-      get_runtime_table(get_table),
-      erase_runtime_table(erase_table) {}
+      get_runtime_table(std::move(get_table)),
+      erase_runtime_table(std::move(erase_table)) {}
 
 DbSqliteTableContext::DbSqliteTableContext(
     QueryCache* query_cache,
diff --git a/src/trace_processor/sqlite/db_sqlite_table.h b/src/trace_processor/sqlite/db_sqlite_table.h
index b6824af..9e599ed 100644
--- a/src/trace_processor/sqlite/db_sqlite_table.h
+++ b/src/trace_processor/sqlite/db_sqlite_table.h
@@ -50,7 +50,9 @@
     // Table is defined in runtime.
     kRuntime
   };
-  DbSqliteTableContext(QueryCache* query_cache, const Table* table);
+  DbSqliteTableContext(QueryCache* query_cache,
+                       const Table* table,
+                       Table::Schema schema);
   DbSqliteTableContext(QueryCache* query_cache,
                        std::function<RuntimeTable*(std::string)> get_table,
                        std::function<void(std::string)> erase_table);
@@ -62,6 +64,7 @@
 
   // Only valid when computation == TableComputation::kStatic.
   const Table* static_table = nullptr;
+  Table::Schema static_schema;
 
   // Only valid when computation == TableComputation::kRuntime.
   // Those functions implement the interactions with
diff --git a/src/trace_processor/storage/stats.h b/src/trace_processor/storage/stats.h
index 1d572a7..ba4406a 100644
--- a/src/trace_processor/storage/stats.h
+++ b/src/trace_processor/storage/stats.h
@@ -61,14 +61,14 @@
   F(ftrace_cpu_overrun_begin,             kIndexed, kInfo,     kTrace,    ""), \
   F(ftrace_cpu_overrun_end,               kIndexed, kInfo,     kTrace,    ""), \
   F(ftrace_cpu_overrun_delta,             kIndexed, kDataLoss, kTrace,         \
-      "The kernel ftrace buffer cannot keep up with the rate of events "       \
-      "produced. Indexed by CPU. This is likely a misconfiguration."),         \
+       "The kernel ftrace buffer cannot keep up with the rate of events "      \
+       "produced. Indexed by CPU. This is likely a misconfiguration."),        \
   F(ftrace_cpu_read_events_begin,         kIndexed, kInfo,     kTrace,    ""), \
   F(ftrace_cpu_read_events_end,           kIndexed, kInfo,     kTrace,    ""), \
   F(ftrace_cpu_read_events_delta,         kIndexed, kInfo,     kTrace,    ""), \
   F(ftrace_setup_errors,                  kSingle,  kInfo,     kTrace,         \
-  "One or more atrace/ftrace categories were not found or failed to enable. "  \
-  "See ftrace_setup_errors in the metadata table for more details."),          \
+       "One or more atrace/ftrace categories were not found or failed to "     \
+       "enable. See ftrace_setup_errors in the metadata table for details."),  \
   F(fuchsia_non_numeric_counters,         kSingle,  kError,    kAnalysis, ""), \
   F(fuchsia_timestamp_overflow,           kSingle,  kError,    kAnalysis, ""), \
   F(fuchsia_invalid_event,                kSingle,  kError,    kAnalysis, ""), \
@@ -91,6 +91,21 @@
   F(rss_stat_unknown_thread_for_mm_id,    kSingle,  kInfo,     kAnalysis, ""), \
   F(sched_switch_out_of_order,            kSingle,  kError,    kAnalysis, ""), \
   F(slice_out_of_order,                   kSingle,  kError,    kAnalysis, ""), \
+  F(filter_input_bytes,                   kSingle,  kInfo,     kTrace,         \
+       "Number of bytes pre-TraceFilter. The trace file would have been this " \
+       "many bytes big if the TraceConfig didn't specify any TraceFilter. "    \
+       "This affects the actual buffer usage, as filtering happens only "      \
+       "when writing into the trace file (or over IPC)."),                     \
+  F(filter_input_packets,                 kSingle,  kInfo,     kTrace,         \
+       "Number of packets pre-TraceFilter. The trace file would have had so "  \
+       "many packets if the TraceConfig didn't specify any TraceFilter."),     \
+  F(filter_output_bytes,                  kSingle,  kInfo,     kTrace,         \
+       "Number of bytes that made it through the TraceFilter, before the "     \
+       "(optional) Zlib compression stage."),                                  \
+  F(filter_time_taken_ns,                 kSingle,  kInfo,     kTrace,         \
+       "Time cumulatively spent running the TraceFilter throughout the "       \
+       "tracing session by MaybeFilterPackets()."),                            \
+  F(filter_errors,                        kSingle,  kError,    kTrace,    ""), \
   F(flow_duplicate_id,                    kSingle,  kError,    kTrace,    ""), \
   F(flow_no_enclosing_slice,              kSingle,  kError,    kTrace,    ""), \
   F(flow_step_without_start,              kSingle,  kInfo,     kTrace,    ""), \
@@ -108,6 +123,11 @@
   F(traced_buf_buffer_size,               kIndexed, kInfo,     kTrace,    ""), \
   F(traced_buf_bytes_overwritten,         kIndexed, kInfo,     kTrace,    ""), \
   F(traced_buf_bytes_read,                kIndexed, kInfo,     kTrace,    ""), \
+  F(traced_buf_bytes_filtered_out,        kIndexed, kInfo,     kTrace,         \
+       "Number of bytes discarded (input - output) by the TraceFilter for "    \
+       "each buffer. It is a subset of, but does not add up perfectly to, "    \
+       "(filter_input_bytes - filter_output_bytes) because of the synthetic "  \
+       "metadata and stats packets generated by the tracing service itself."), \
   F(traced_buf_bytes_written,             kIndexed, kInfo,     kTrace,    ""), \
   F(traced_buf_chunks_discarded,          kIndexed, kInfo,     kTrace,    ""), \
   F(traced_buf_chunks_overwritten,        kIndexed, kInfo,     kTrace,    ""), \
@@ -272,6 +292,12 @@
       "Shell transition packet has unknown fields, which results "             \
       "in some arguments missing. You may need a newer version of trace "      \
       "processor to parse them."),                                             \
+  F(winscope_protolog_invalid_interpolation_parse_errors,                      \
+                                          kSingle,  kInfo,     kAnalysis,      \
+      "ProtoLog message string has invalid interplation parameter."),          \
+  F(winscope_protolog_missing_interned_arg_parse_errors,                       \
+                                          kSingle,  kInfo,     kAnalysis,      \
+      "Failed to find interned ProtoLog argument."),          \
   F(ftrace_missing_event_id,              kSingle,  kInfo,    kAnalysis,       \
       "Indicates that the ftrace event was dropped because the event id was "  \
       "missing. This is an 'info' stat rather than an error stat because "     \
diff --git a/src/trace_processor/storage/trace_storage.h b/src/trace_processor/storage/trace_storage.h
index 87ac1d2..ce0599d 100644
--- a/src/trace_processor/storage/trace_storage.h
+++ b/src/trace_processor/storage/trace_storage.h
@@ -793,6 +793,11 @@
     return &window_manager_shell_transition_handlers_table_;
   }
 
+  const tables::ProtoLogTable& protolog_table() const {
+    return protolog_table_;
+  }
+  tables::ProtoLogTable* mutable_protolog_table() { return &protolog_table_; }
+
   const tables::ExperimentalProtoPathTable& experimental_proto_path_table()
       const {
     return experimental_proto_path_table_;
@@ -1059,6 +1064,7 @@
       window_manager_shell_transitions_table_{&string_pool_};
   tables::WindowManagerShellTransitionHandlersTable
       window_manager_shell_transition_handlers_table_{&string_pool_};
+  tables::ProtoLogTable protolog_table_{&string_pool_};
 
   tables::ExperimentalProtoPathTable experimental_proto_path_table_{
       &string_pool_};
diff --git a/src/trace_processor/tables/BUILD.gn b/src/trace_processor/tables/BUILD.gn
index 1bbce44..d93256b 100644
--- a/src/trace_processor/tables/BUILD.gn
+++ b/src/trace_processor/tables/BUILD.gn
@@ -41,7 +41,9 @@
   deps = [
     "../../../gn:default_deps",
     "../../../include/perfetto/ext/base",
+    "../containers",
     "../db",
+    "../db/column",
   ]
   public_deps = [ ":tables_python" ]
 }
@@ -58,6 +60,7 @@
     ":tables",
     "../../../gn:default_deps",
     "../../../gn:gtest_and_gmock",
+    "../containers",
     "../db",
   ]
 }
diff --git a/src/trace_processor/tables/macros_internal.h b/src/trace_processor/tables/macros_internal.h
index 22085f2..d1fae7a 100644
--- a/src/trace_processor/tables/macros_internal.h
+++ b/src/trace_processor/tables/macros_internal.h
@@ -17,11 +17,20 @@
 #ifndef SRC_TRACE_PROCESSOR_TABLES_MACROS_INTERNAL_H_
 #define SRC_TRACE_PROCESSOR_TABLES_MACROS_INTERNAL_H_
 
+#include <cstddef>
+#include <cstdint>
 #include <type_traits>
+#include <utility>
+#include <vector>
 
-#include "perfetto/ext/base/small_vector.h"
+#include "perfetto/base/logging.h"
+#include "src/trace_processor/containers/row_map.h"
+#include "src/trace_processor/containers/string_pool.h"
+#include "src/trace_processor/db/column.h"
+#include "src/trace_processor/db/column/types.h"
+#include "src/trace_processor/db/column_storage.h"
+#include "src/trace_processor/db/column_storage_overlay.h"
 #include "src/trace_processor/db/table.h"
-#include "src/trace_processor/db/typed_column.h"
 
 namespace perfetto {
 namespace trace_processor {
@@ -63,7 +72,7 @@
 class MacroTable : public Table {
  protected:
   // Constructors for tables created by the regular constructor.
-  MacroTable(StringPool* pool, const Table* parent = nullptr)
+  MacroTable(StringPool* pool, const MacroTable* parent = nullptr)
       : Table(pool), allow_inserts_(true), parent_(parent) {
     if (!parent) {
       overlays_.emplace_back();
@@ -82,7 +91,7 @@
 
   // Constructor for tables created by SelectAndExtendParent.
   MacroTable(StringPool* pool,
-             const Table& parent,
+             const MacroTable& parent,
              const RowMap& parent_overlay)
       : Table(pool), allow_inserts_(false) {
     row_count_ = parent_overlay.size();
@@ -154,7 +163,7 @@
   ColumnStorage<StringPool::Id> type_;
 
  private:
-  const Table* parent_ = nullptr;
+  const MacroTable* parent_ = nullptr;
 };
 
 // Abstract iterator class for macro tables.
diff --git a/src/trace_processor/tables/py_tables_benchmark.cc b/src/trace_processor/tables/py_tables_benchmark.cc
index 45a96e8..b93d724 100644
--- a/src/trace_processor/tables/py_tables_benchmark.cc
+++ b/src/trace_processor/tables/py_tables_benchmark.cc
@@ -85,7 +85,7 @@
 
   auto it = static_cast<Table&>(child).IterateRows();
   for (auto _ : state) {
-    for (uint32_t i = 0; i < child.GetColumnCount(); ++i) {
+    for (uint32_t i = 0; i < child.columns().size(); ++i) {
       benchmark::DoNotOptimize(it.Get(i));
     }
     it.Next();
diff --git a/src/trace_processor/tables/table_destructors.cc b/src/trace_processor/tables/table_destructors.cc
index 298a0aa..c34e4d3 100644
--- a/src/trace_processor/tables/table_destructors.cc
+++ b/src/trace_processor/tables/table_destructors.cc
@@ -133,6 +133,7 @@
     default;
 WindowManagerShellTransitionHandlersTable::
     ~WindowManagerShellTransitionHandlersTable() = default;
+ProtoLogTable::~ProtoLogTable() = default;
 
 }  // namespace tables
 
diff --git a/src/trace_processor/tables/winscope_tables.py b/src/trace_processor/tables/winscope_tables.py
index 12e7cef..830f88e 100644
--- a/src/trace_processor/tables/winscope_tables.py
+++ b/src/trace_processor/tables/winscope_tables.py
@@ -103,8 +103,29 @@
             'handler_name': 'The name of the handler',
         }))
 
+PROTOLOG_TABLE = Table(
+    python_module=__file__,
+    class_name='ProtoLogTable',
+    sql_name='protolog',
+    columns=[
+        C('ts', CppInt64()),
+        C('level', CppString()),
+        C('tag', CppString()),
+        C('message', CppString()),
+    ],
+    tabledoc=TableDoc(
+        doc='Protolog',
+        group='Winscope',
+        columns={
+            'ts': 'The timestamp the log message was sent',
+            'level': 'The log level of the protolog message',
+            'tag': 'The log tag of the protolog message',
+            'message': 'The protolog message',
+        }))
+
 # Keep this list sorted.
 ALL_TABLES = [
+    PROTOLOG_TABLE,
     SURFACE_FLINGER_LAYERS_SNAPSHOT_TABLE,
     SURFACE_FLINGER_LAYER_TABLE,
     SURFACE_FLINGER_TRANSACTIONS_TABLE,
diff --git a/src/trace_processor/trace_processor_impl.cc b/src/trace_processor/trace_processor_impl.cc
index 7261fab..41fdab3 100644
--- a/src/trace_processor/trace_processor_impl.cc
+++ b/src/trace_processor/trace_processor_impl.cc
@@ -56,6 +56,7 @@
 #include "src/trace_processor/perfetto_sql/intrinsics/functions/clock_functions.h"
 #include "src/trace_processor/perfetto_sql/intrinsics/functions/create_function.h"
 #include "src/trace_processor/perfetto_sql/intrinsics/functions/create_view_function.h"
+#include "src/trace_processor/perfetto_sql/intrinsics/functions/import.h"
 #include "src/trace_processor/perfetto_sql/intrinsics/functions/layout_functions.h"
 #include "src/trace_processor/perfetto_sql/intrinsics/functions/math.h"
 #include "src/trace_processor/perfetto_sql/intrinsics/functions/pprof_functions.h"
@@ -69,6 +70,7 @@
 #include "src/trace_processor/perfetto_sql/intrinsics/table_functions/ancestor.h"
 #include "src/trace_processor/perfetto_sql/intrinsics/table_functions/connected_flow.h"
 #include "src/trace_processor/perfetto_sql/intrinsics/table_functions/descendant.h"
+#include "src/trace_processor/perfetto_sql/intrinsics/table_functions/dfs.h"
 #include "src/trace_processor/perfetto_sql/intrinsics/table_functions/dominator_tree.h"
 #include "src/trace_processor/perfetto_sql/intrinsics/table_functions/experimental_annotated_stack.h"
 #include "src/trace_processor/perfetto_sql/intrinsics/table_functions/experimental_counter_dur.h"
@@ -100,8 +102,7 @@
 #include "protos/perfetto/trace/trace.pbzero.h"
 #include "protos/perfetto/trace/trace_packet.pbzero.h"
 
-namespace perfetto {
-namespace trace_processor {
+namespace perfetto::trace_processor {
 namespace {
 
 template <typename SqlFunction, typename Ptr = typename SqlFunction::Context*>
@@ -837,6 +838,8 @@
   RegisterStaticTable(
       storage->window_manager_shell_transition_handlers_table());
 
+  RegisterStaticTable(storage->protolog_table());
+
   RegisterStaticTable(storage->metadata_table());
   RegisterStaticTable(storage->cpu_table());
   RegisterStaticTable(storage->cpu_freq_table());
@@ -891,6 +894,8 @@
       new ExperimentalFlatSlice(&context_)));
   engine_->RegisterStaticTableFunction(
       std::make_unique<DominatorTree>(context_.storage->mutable_string_pool()));
+  engine_->RegisterStaticTableFunction(
+      std::make_unique<Dfs>(context_.storage->mutable_string_pool()));
 
   // Metrics.
   RegisterAllProtoBuilderFunctions(&pool_, engine_.get(), this);
@@ -1005,5 +1010,4 @@
   return base::OkStatus();
 }
 
-}  // namespace trace_processor
-}  // namespace perfetto
+}  // namespace perfetto::trace_processor
diff --git a/src/trace_processor/trace_processor_impl.h b/src/trace_processor/trace_processor_impl.h
index d627f42..4c08f23 100644
--- a/src/trace_processor/trace_processor_impl.h
+++ b/src/trace_processor/trace_processor_impl.h
@@ -20,33 +20,24 @@
 #include <sqlite3.h>
 
 #include <atomic>
-#include <functional>
-#include <map>
+#include <cstddef>
+#include <cstdint>
 #include <memory>
 #include <string>
+#include <unordered_map>
 #include <vector>
 
-#include "perfetto/ext/base/flat_hash_map.h"
-#include "perfetto/ext/base/string_view.h"
+#include "perfetto/base/status.h"
 #include "perfetto/trace_processor/basic_types.h"
-#include "perfetto/trace_processor/status.h"
 #include "perfetto/trace_processor/trace_processor.h"
+#include "src/trace_processor/metrics/metrics.h"
 #include "src/trace_processor/perfetto_sql/engine/perfetto_sql_engine.h"
 #include "src/trace_processor/perfetto_sql/intrinsics/functions/create_function.h"
 #include "src/trace_processor/perfetto_sql/intrinsics/functions/create_view_function.h"
-#include "src/trace_processor/perfetto_sql/intrinsics/functions/import.h"
-#include "src/trace_processor/sqlite/db_sqlite_table.h"
-#include "src/trace_processor/sqlite/query_cache.h"
-#include "src/trace_processor/sqlite/scoped_db.h"
-#include "src/trace_processor/sqlite/sqlite_engine.h"
 #include "src/trace_processor/trace_processor_storage_impl.h"
-#include "src/trace_processor/util/sql_modules.h"
-
-#include "src/trace_processor/metrics/metrics.h"
 #include "src/trace_processor/util/descriptors.h"
 
-namespace perfetto {
-namespace trace_processor {
+namespace perfetto::trace_processor {
 
 // Coordinates the loading of traces from an arbitrary source and allows
 // execution of SQL queries on the events in these traces.
@@ -110,7 +101,8 @@
 
   template <typename Table>
   void RegisterStaticTable(const Table& table) {
-    engine_->RegisterStaticTable(table, Table::Name());
+    engine_->RegisterStaticTable(table, Table::Name(),
+                                 Table::ComputeStaticSchema());
   }
 
   bool IsRootMetricField(const std::string& metric_name);
@@ -140,7 +132,6 @@
   bool notify_eof_called_ = false;
 };
 
-}  // namespace trace_processor
-}  // namespace perfetto
+}  // namespace perfetto::trace_processor
 
 #endif  // SRC_TRACE_PROCESSOR_TRACE_PROCESSOR_IMPL_H_
diff --git a/src/trace_processor/util/status_macros.h b/src/trace_processor/util/status_macros.h
index d7acb98..c902bac 100644
--- a/src/trace_processor/util/status_macros.h
+++ b/src/trace_processor/util/status_macros.h
@@ -38,6 +38,6 @@
   PERFETTO_INTERNAL_MACRO_CONCAT(auto status_or, __LINE__) = rhs;    \
   RETURN_IF_ERROR(                                                   \
       PERFETTO_INTERNAL_MACRO_CONCAT(status_or, __LINE__).status()); \
-  lhs = std::move(rhs.value())
+  lhs = std::move(PERFETTO_INTERNAL_MACRO_CONCAT(status_or, __LINE__).value())
 
 #endif  // SRC_TRACE_PROCESSOR_UTIL_STATUS_MACROS_H_
diff --git a/src/traced/probes/ftrace/ftrace_config_muxer_unittest.cc b/src/traced/probes/ftrace/ftrace_config_muxer_unittest.cc
index a231932..92acbf3 100644
--- a/src/traced/probes/ftrace/ftrace_config_muxer_unittest.cc
+++ b/src/traced/probes/ftrace/ftrace_config_muxer_unittest.cc
@@ -48,10 +48,11 @@
 constexpr int kFakePrintEventId = 20;
 constexpr int kSysEnterId = 329;
 
-constexpr size_t kFakeSyscallCount = 2;
-constexpr const char* kFakeSyscalls[] = {
-    "sys_open",
-    "sys_read",
+struct FakeSyscallTable {
+  static constexpr char names[] =
+      "sys_open\0"
+      "sys_read\0";
+  static constexpr SyscallTable::OffT offsets[]{0, 9};
 };
 
 std::string PageSizeKb() {
@@ -151,7 +152,7 @@
   }
 
   SyscallTable GetSyscallTable() {
-    return SyscallTable(kFakeSyscalls, kFakeSyscallCount);
+    return SyscallTable::Load<FakeSyscallTable>();
   }
 
   std::unique_ptr<ProtoTranslationTable> CreateFakeTable(
diff --git a/src/traced/probes/ftrace/ftrace_controller_unittest.cc b/src/traced/probes/ftrace/ftrace_controller_unittest.cc
index c9a5ca1..debdbfa 100644
--- a/src/traced/probes/ftrace/ftrace_controller_unittest.cc
+++ b/src/traced/probes/ftrace/ftrace_controller_unittest.cc
@@ -103,8 +103,8 @@
 
 std::unique_ptr<FtraceConfigMuxer> FakeMuxer(FtraceProcfs* ftrace,
                                              ProtoTranslationTable* table) {
-  return std::unique_ptr<FtraceConfigMuxer>(
-      new FtraceConfigMuxer(ftrace, table, SyscallTable(kUnknown), {}));
+  return std::unique_ptr<FtraceConfigMuxer>(new FtraceConfigMuxer(
+      ftrace, table, SyscallTable(Architecture::kUnknown), {}));
 }
 
 class MockFtraceProcfs : public FtraceProcfs {
diff --git a/src/traced/service/BUILD.gn b/src/traced/service/BUILD.gn
index 542560a..aaf7cc4 100644
--- a/src/traced/service/BUILD.gn
+++ b/src/traced/service/BUILD.gn
@@ -19,10 +19,10 @@
 # log buffers.
 executable("traced") {
   deps = [
-    # traced, traced_probes and perfetto_cmd depend on "libperfetto" instead of
-    # directly on lib. This is to reduce binary size on android builds. All the
-    # code is built into libperfetto and the executables are just tiny shells
-    # that call into the xxx_main() defined in the library.
+    # Both traced and traced_probes depend on "libprefetto" instead of directly
+    # on lib. This is to reduce binary size on android builds. All the code is
+    # built into libperfetto and the executables are just tiny shells that call
+    # into the xxx_main() defined in the library.
     "../../../:libperfetto",
     "../../../gn:default_deps",
     "../../../include/perfetto/ext/traced",
diff --git a/test/BUILD.gn b/test/BUILD.gn
index bb318b3..f0a5ae6 100644
--- a/test/BUILD.gn
+++ b/test/BUILD.gn
@@ -25,6 +25,7 @@
       "../gn:gtest_and_gmock",
       "../include/perfetto/ext/ipc",
       "../include/perfetto/ext/traced",
+      "../include/perfetto/ext/tracing/core:test_support",
       "../include/perfetto/protozero",
       "../protos/perfetto/config:cpp",
       "../protos/perfetto/config:zero",
diff --git a/test/cts/test_apps/src/android/perfetto/cts/app/JavaOomActivity.java b/test/cts/test_apps/src/android/perfetto/cts/app/JavaOomActivity.java
index f73c135..35808b9 100644
--- a/test/cts/test_apps/src/android/perfetto/cts/app/JavaOomActivity.java
+++ b/test/cts/test_apps/src/android/perfetto/cts/app/JavaOomActivity.java
@@ -26,6 +26,14 @@
         new Thread(() -> {
             try {
                 byte[] alloc = new byte[Integer.MAX_VALUE];
+                // The return statement below is required to keep the allocation
+                // above when generating DEX. Without the return statement there is
+                // no way for a debugger to break where `alloc` is in scope and
+                // therefore javac will not generate local variable information for it.
+                // Without local variable information dexers (both D8 and R8) will
+                // remove the dead allocation as without local variable information it
+                // is dead even in debug mode. See b/322478366#comment3.
+                return;
             } catch (OutOfMemoryError e) {
             }
         }).start();
diff --git a/test/test_helper.h b/test/test_helper.h
index 462861d..b43ae0a 100644
--- a/test/test_helper.h
+++ b/test/test_helper.h
@@ -468,7 +468,6 @@
       pass_env("TMPDIR", &subprocess_);
       pass_env("TMP", &subprocess_);
       pass_env("TEMP", &subprocess_);
-      pass_env("LD_LIBRARY_PATH", &subprocess_);
       cmd.push_back(base::GetCurExecutableDir() + "/" + argv0);
       cmd.insert(cmd.end(), args.begin(), args.end());
     }
diff --git a/test/trace_processor/diff_tests/include_index.py b/test/trace_processor/diff_tests/include_index.py
index a84267a..743b8da 100644
--- a/test/trace_processor/diff_tests/include_index.py
+++ b/test/trace_processor/diff_tests/include_index.py
@@ -52,6 +52,7 @@
 from diff_tests.parser.android.tests_surfaceflinger_layers import SurfaceFlingerLayers
 from diff_tests.parser.android.tests_surfaceflinger_transactions import SurfaceFlingerTransactions
 from diff_tests.parser.android.tests_shell_transitions import ShellTransitions
+from diff_tests.parser.android.tests_protolog import ProtoLog
 from diff_tests.parser.android_fs.tests import AndroidFs
 from diff_tests.parser.atrace.tests import Atrace
 from diff_tests.parser.atrace.tests_error_handling import AtraceErrorHandling
@@ -180,6 +181,7 @@
                                   'SurfaceFlingerTransactions').fetch(),
       *ShellTransitions(index_path, 'parser/android',
                         'ShellTransitions').fetch(),
+      *ProtoLog(index_path, 'parser/android', 'ProtoLog').fetch(),
       *TrackEvent(index_path, 'parser/track_event', 'TrackEvent').fetch(),
       *TranslatedArgs(index_path, 'parser/translated_args',
                       'TranslatedArgs').fetch(),
diff --git a/test/trace_processor/diff_tests/metrics/android/ad_services_metric.py b/test/trace_processor/diff_tests/metrics/android/ad_services_metric.py
index a24b3c6..f1e8aad 100644
--- a/test/trace_processor/diff_tests/metrics/android/ad_services_metric.py
+++ b/test/trace_processor/diff_tests/metrics/android/ad_services_metric.py
@@ -21,9 +21,15 @@
 CONSENT_MANAGER_READ_EVENT = "ConsentManager#ReadOperation"
 CONSENT_MANAGER_WRITE_EVENT = "ConsentManager#WriteOperation"
 MAIN_ACTIVITY_CREATION_EVENT = "AdServicesSettingsMainActivity#OnCreate"
+
 AD_ID_CACHE_EVENT = "AdIdCacheEvent"
 APP_SET_ID_EVENT = "AppSetIdEvent"
 
+ODP_MANAGER_INITIALIZATION_EVENT = "OdpManagingService#Initialization"
+ODP_MANAGER_EXECUTE_EVENT = "OdpManagingServiceDelegate#Execute"
+ODP_MANAGER_REQUEST_SURFACE_PACKAGE_EVENT = "OdpManagingServiceDelegate#RequestSurfacePackage"
+ODP_MANAGER_REGISTER_WEB_TRIGGER_EVENT = "OdpManagingServiceDelegate#RegisterWebTrigger"
+
 trace = synth_common.create_trace()
 
 trace.add_ftrace_packet(cpu=0)
@@ -45,5 +51,17 @@
     ts=1500, tid=43, pid=43, buf=CONSENT_MANAGER_READ_EVENT)
 trace.add_atrace_end(ts=1650, tid=43, pid=43)
 
+trace.add_atrace_begin(
+    ts=2500, tid=43, pid=44, buf=ODP_MANAGER_INITIALIZATION_EVENT)
+trace.add_atrace_end(ts=2550, tid=43, pid=44)
+trace.add_atrace_begin(
+    ts=2600, tid=43, pid=44, buf=ODP_MANAGER_EXECUTE_EVENT)
+trace.add_atrace_end(ts=2700, tid=43, pid=44)
+trace.add_atrace_begin(
+    ts=2800, tid=43, pid=44, buf=ODP_MANAGER_REQUEST_SURFACE_PACKAGE_EVENT)
+trace.add_atrace_end(ts=2950, tid=43, pid=44)
+trace.add_atrace_begin(
+    ts=3000, tid=43, pid=44, buf=ODP_MANAGER_REGISTER_WEB_TRIGGER_EVENT)
+trace.add_atrace_end(ts=3200, tid=43, pid=44)
 
 sys.stdout.buffer.write(trace.trace.SerializeToString())
diff --git a/test/trace_processor/diff_tests/metrics/android/android_blocking_calls_cuj_metric.out b/test/trace_processor/diff_tests/metrics/android/android_blocking_calls_cuj_metric.out
index 707bd49..9dd8da6 100644
--- a/test/trace_processor/diff_tests/metrics/android/android_blocking_calls_cuj_metric.out
+++ b/test/trace_processor/diff_tests/metrics/android/android_blocking_calls_cuj_metric.out
@@ -50,7 +50,7 @@
       pid: 3000
     }
     ts: 2000000
-    dur: 240000000
+    dur: 260000000
     blocking_calls {
       name: "Contending for pthread mutex"
       cnt: 1
@@ -132,7 +132,27 @@
       min_dur_ns: 10000000
     }
     blocking_calls {
-      name: "Lock contention on <...>"
+      name: "Lock contention on a monitor lock <...>"
+      cnt: 1
+      total_dur_ms: 10
+      max_dur_ms: 10
+      min_dur_ms: 10
+      total_dur_ns: 10000000
+      max_dur_ns: 10000000
+      min_dur_ns: 10000000
+    }
+    blocking_calls {
+      name: "Lock contention on thread list lock <...>"
+      cnt: 1
+      total_dur_ms: 10
+      max_dur_ms: 10
+      min_dur_ms: 10
+      total_dur_ns: 10000000
+      max_dur_ns: 10000000
+      min_dur_ns: 10000000
+    }
+    blocking_calls {
+      name: "Lock contention on thread suspend count lock <...>"
       cnt: 1
       total_dur_ms: 10
       max_dur_ms: 10
diff --git a/test/trace_processor/diff_tests/metrics/android/android_blocking_calls_cuj_metric.py b/test/trace_processor/diff_tests/metrics/android/android_blocking_calls_cuj_metric.py
index 5a3b40c..8e005a1 100755
--- a/test/trace_processor/diff_tests/metrics/android/android_blocking_calls_cuj_metric.py
+++ b/test/trace_processor/diff_tests/metrics/android/android_blocking_calls_cuj_metric.py
@@ -30,6 +30,8 @@
     'monitor contention with something else', 'SuspendThreadByThreadId 123',
     'LoadApkAssetsFd 123', 'binder transaction', 'inflate',
     'Lock contention on thread list lock (owner tid: 1665)',
+    "Lock contention on thread suspend count lock (owner tid: 0)",
+    "Lock contention on a monitor lock (owner tid: 0)",
     'android.os.Handler: kotlinx.coroutines.CancellableContinuationImpl',
     'relayoutWindow*', 'measure', 'layout', 'configChanged',
     'Contending for pthread mutex', 'ImageDecoder#decodeBitmap',
diff --git a/test/trace_processor/diff_tests/metrics/android/tests.py b/test/trace_processor/diff_tests/metrics/android/tests.py
index 65e7690..ce254fb 100644
--- a/test/trace_processor/diff_tests/metrics/android/tests.py
+++ b/test/trace_processor/diff_tests/metrics/android/tests.py
@@ -213,7 +213,13 @@
              latency: 0.0001
            }
            ad_id_metric {
-             latency:0.0003
+             latency: 0.0003
+           }
+           odp_metric {
+             managing_service_initialization_latency: 0.00005
+             service_delegate_execute_flow_latency: 0.0001
+             service_delegate_request_surface_package_latency: 0.00015
+             service_delegate_register_web_trigger_latency: 0.0002
            }
          }
         """))
diff --git a/test/trace_processor/diff_tests/parser/android/protolog.textproto b/test/trace_processor/diff_tests/parser/android/protolog.textproto
new file mode 100644
index 0000000..4ab660d
--- /dev/null
+++ b/test/trace_processor/diff_tests/parser/android/protolog.textproto
@@ -0,0 +1,133 @@
+packet {
+  trusted_uid: 1000
+  trusted_packet_sequence_id: 2
+  sequence_flags: 1
+  previous_packet_dropped: true
+  trusted_pid: 1716
+  first_packet_on_sequence: true
+}
+packet {
+  trusted_uid: 1000
+  trusted_packet_sequence_id: 2
+  interned_data {
+    protolog_string_args {
+      iid: 1
+      str: "MyTestString"
+    }
+  }
+  trusted_pid: 1716
+}
+packet {
+  trusted_uid: 1000
+  trusted_packet_sequence_id: 2
+  sequence_flags: 2
+  trusted_pid: 1716
+  timestamp: 857384100
+  protolog_message {
+    message_id: 6924537961316301726
+    interned_str_params: 1
+    sint64_params: 888
+    double_params: 8.88
+    boolean_params: 1
+  }
+}
+packet {
+  trusted_uid: 1000
+  trusted_packet_sequence_id: 3
+  sequence_flags: 1
+  previous_packet_dropped: true
+  trusted_pid: 1716
+  first_packet_on_sequence: true
+}
+packet {
+  trusted_uid: 1000
+  trusted_packet_sequence_id: 3
+  trusted_pid: 1716
+  timestamp: 857384110
+  protolog_message {
+    message_id: 1994837961123301128
+    sint64_params: 888
+    sint64_params: 888
+    sint64_params: 888
+    double_params: 888
+    double_params: 888
+  }
+}
+packet {
+  trusted_uid: 1000
+  trusted_packet_sequence_id: 3
+  interned_data {
+    protolog_string_args {
+      iid: 1
+      str: "MyOtherTestString"
+    }
+  }
+  trusted_pid: 1716
+}
+packet {
+  trusted_uid: 1000
+  trusted_packet_sequence_id: 3
+  interned_data {
+    protolog_string_args {
+      iid: 2
+      str: "SomeOtherTestString"
+    }
+  }
+  trusted_pid: 1716
+}
+packet {
+  trusted_uid: 1000
+  trusted_packet_sequence_id: 3
+  sequence_flags: 2
+  trusted_pid: 1716
+  timestamp: 857384130
+  protolog_message {
+    message_id: 9274895847396301003
+    interned_str_params: 1
+    interned_str_params: 1
+    interned_str_params: 2
+    interned_str_params: 1
+  }
+}
+packet {
+  trusted_uid: 10224
+  trusted_packet_sequence_id: 10
+  previous_packet_dropped: true
+  trusted_pid: 2063
+  first_packet_on_sequence: true
+  protolog_viewer_config {
+    messages {
+      message_id: 6924537961316301726
+      message: "Test message with a string (%s), an int (%d), a double %g, and a boolean %b."
+      level: PROTOLOG_LEVEL_DEBUG
+      group_id: 1
+    }
+    messages {
+      message_id: 1994837961123301128
+      message: "Test message with different int formats: %d, 0o%o, 0x%x, %f, %e."
+      level: PROTOLOG_LEVEL_WARN
+      group_id: 2
+    }
+    messages {
+      message_id: 9274895847396301003
+      message: "Message re-using interned string '%s' == '%s', but '%s' != '%s'"
+      level: PROTOLOG_LEVEL_ERROR
+      group_id: 3
+    }
+    groups {
+      id: 1
+      name: "MY_FIRST_GROUP"
+      tag: "MyFirstGroup"
+    }
+    groups {
+      id: 2
+      name: "MY_SECOND_GROUP"
+      tag: "MySecondGroup"
+    }
+    groups {
+      id: 3
+      name: "MY_THIRD_GROUP"
+      tag: "MyThirdGroup"
+    }
+  }
+}
\ No newline at end of file
diff --git a/test/trace_processor/diff_tests/parser/android/tests_protolog.py b/test/trace_processor/diff_tests/parser/android/tests_protolog.py
new file mode 100644
index 0000000..6db8cfe
--- /dev/null
+++ b/test/trace_processor/diff_tests/parser/android/tests_protolog.py
@@ -0,0 +1,33 @@
+#!/usr/bin/env python3
+# Copyright (C) 2023 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License a
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+from python.generators.diff_tests.testing import Path
+from python.generators.diff_tests.testing import Csv
+from python.generators.diff_tests.testing import DiffTestBlueprint
+from python.generators.diff_tests.testing import TestSuite
+
+
+class ProtoLog(TestSuite):
+
+  def test_has_expected_protolog_rows(self):
+    return DiffTestBlueprint(
+        trace=Path('protolog.textproto'),
+        query="SELECT id, ts, level, tag, message FROM protolog;",
+        out=Csv("""
+        "id","ts","level","tag","message"
+        0,857384100,"DEBUG","MyFirstGroup","Test message with a string (MyTestString), an int (1776), a double 8.88, and a boolean true."
+        1,857384110,"WARN","MySecondGroup","Test message with different int formats: 1776, 0o3360, 0x6f0, 888.000000, 8.880000e+02."
+        2,857384130,"ERROR","MyThirdGroup","Message re-using interned string 'MyOtherTestString' == 'MyOtherTestString', but 'SomeOtherTestString' != 'MyOtherTestString'"
+        """))
diff --git a/test/trace_processor/diff_tests/parser/parsing/chrome_metadata.out b/test/trace_processor/diff_tests/parser/parsing/chrome_metadata.out
index 873e349..5635f53 100644
--- a/test/trace_processor/diff_tests/parser/parsing/chrome_metadata.out
+++ b/test/trace_processor/diff_tests/parser/parsing/chrome_metadata.out
@@ -1,10 +1,11 @@
 "id","type","name","key_type","int_value","str_value"
-0,"metadata","trace_uuid","single","[NULL]","00000000-0000-0000-dcce-849205cfb03e" 
+0,"metadata","trace_uuid","single","[NULL]","00000000-0000-0000-afe8-083bd6899d9d"
 1,"metadata","trace_time_clock_id","single",6,"[NULL]"
-2,"metadata","cr-playstore_version_code","single",101,"[NULL]"
-3,"metadata","cr-enabled_categories","single","[NULL]","cat1,cat2,cat3"
-4,"metadata","cr-background_tracing_metadata","single","[NULL]","CgUlDsAbXx2RziSz"
-5,"metadata","cr-scenario_name_hash","single",3005533841,"[NULL]"
-6,"metadata","cr-triggered_rule_name_hash","single",1595654158,"[NULL]"
-7,"metadata","trace_size_bytes","single",64,"[NULL]"
-8,"metadata","trace_type","single","[NULL]","proto"
+2,"metadata","cr-a-playstore_version_code","single",101,"[NULL]"
+3,"metadata","cr-a-enabled_categories","single","[NULL]","cat1,cat2,cat3"
+4,"metadata","cr-a-field_trial_hashes","single","[NULL]","{ name: 123, group: 456 } { name: 789, group: 120 } "
+5,"metadata","cr-background_tracing_metadata","single","[NULL]","CgUlDsAbXx2RziSz"
+6,"metadata","cr-scenario_name_hash","single",3005533841,"[NULL]"
+7,"metadata","cr-triggered_rule_name_hash","single",1595654158,"[NULL]"
+8,"metadata","trace_size_bytes","single",78,"[NULL]"
+9,"metadata","trace_type","single","[NULL]","proto"
diff --git a/test/trace_processor/diff_tests/parser/parsing/tests.py b/test/trace_processor/diff_tests/parser/parsing/tests.py
index 90067a7..5df7a52 100644
--- a/test/trace_processor/diff_tests/parser/parsing/tests.py
+++ b/test/trace_processor/diff_tests/parser/parsing/tests.py
@@ -643,6 +643,14 @@
             }
             chrome_version_code: 101
             enabled_categories: "cat1,cat2,cat3"
+            field_trial_hashes {
+              name: 123
+              group: 456
+            }
+            field_trial_hashes {
+              name: 789
+              group: 120
+            }
           }
         }
         """),
@@ -651,6 +659,69 @@
         """,
         out=Path('chrome_metadata.out'))
 
+  def test_chrome_metadata_multiple(self):
+    return DiffTestBlueprint(
+        trace=TextProto(r"""
+        packet {
+          clock_snapshot {
+            clocks {
+              clock_id: 6
+              timestamp: 101000002
+            }
+          }
+          trusted_packet_sequence_id: 1
+          timestamp: 101000002
+        }
+        packet {
+          trusted_packet_sequence_id: 1
+          timestamp: 101000002
+          chrome_metadata {
+            chrome_version_code: 101
+            enabled_categories: "cat1,cat2,cat3"
+            field_trial_hashes {
+              name: 123
+              group: 456
+            }
+            field_trial_hashes {
+              name: 789
+              group: 120
+            }
+          }
+        }
+        packet {
+          trusted_packet_sequence_id: 1
+          timestamp: 101000002
+          chrome_metadata {
+            chrome_version_code: 102
+            enabled_categories: "cat3,cat4,cat5"
+            field_trial_hashes {
+              name: 1234
+              group: 5678
+            }
+            field_trial_hashes {
+              name: 9012
+              group: 3456
+            }
+          }
+        }
+        """),
+        query="""
+        SELECT * FROM metadata;
+        """,
+        out=Csv("""
+        "id","type","name","key_type","int_value","str_value"
+        0,"metadata","trace_uuid","single","[NULL]","00000000-0000-0000-0de8-df55233147f0"
+        1,"metadata","trace_time_clock_id","single",6,"[NULL]"
+        2,"metadata","cr-a-playstore_version_code","single",101,"[NULL]"
+        3,"metadata","cr-a-enabled_categories","single","[NULL]","cat1,cat2,cat3"
+        4,"metadata","cr-a-field_trial_hashes","single","[NULL]","{ name: 123, group: 456 } { name: 789, group: 120 } "
+        5,"metadata","cr-b-playstore_version_code","single",102,"[NULL]"
+        6,"metadata","cr-b-enabled_categories","single","[NULL]","cat3,cat4,cat5"
+        7,"metadata","cr-b-field_trial_hashes","single","[NULL]","{ name: 1234, group: 5678 } { name: 9012, group: 3456 } "
+        8,"metadata","trace_size_bytes","single",110,"[NULL]"
+        9,"metadata","trace_type","single","[NULL]","proto"
+        """))
+
   # CPU info
   def test_cpu(self):
     return DiffTestBlueprint(
diff --git a/test/trace_processor/diff_tests/stdlib/android/android_slice_standardization.py b/test/trace_processor/diff_tests/stdlib/android/android_slice_standardization.py
index 0b07010..aaa1bd3 100644
--- a/test/trace_processor/diff_tests/stdlib/android/android_slice_standardization.py
+++ b/test/trace_processor/diff_tests/stdlib/android/android_slice_standardization.py
@@ -29,6 +29,8 @@
 
 slices_to_standardize = [
     "Lock contention on thread list lock (owner tid: 1665)",
+    "Lock contention on thread suspend count lock (owner tid: 0)",
+    "Lock contention on a monitor lock (owner tid: 0)",
     "monitor contention with owner BG Thread #1 (30) at",
     "SuspendThreadByThreadId suspended Primes-1 id=19",
     "LoadApkAssetsFd({ParcelFileDescriptor: java.io.FileDescriptor@340019d})",
diff --git a/test/trace_processor/diff_tests/stdlib/android/tests.py b/test/trace_processor/diff_tests/stdlib/android/tests.py
index c6bc6da..7c0ef86 100644
--- a/test/trace_processor/diff_tests/stdlib/android/tests.py
+++ b/test/trace_processor/diff_tests/stdlib/android/tests.py
@@ -229,7 +229,9 @@
         """,
         out=Csv("""
         "name"
-        "Lock contention on <...>"
+        "Lock contention on thread list lock <...>"
+        "Lock contention on thread suspend count lock <...>"
+        "Lock contention on a monitor lock <...>"
         "monitor contention with <...>"
         "SuspendThreadByThreadId <...>"
         "LoadApkAssetsFd <...>"
@@ -1028,3 +1030,29 @@
          "bus_throughput Frequency",553000.000000,2000000,50.000000
          "bus_throughput Frequency",1014000.000000,2000000,50.000000
          """))
+
+  def test_app_process_starts(self):
+    return DiffTestBlueprint(
+        trace=DataPath('sched_wakeup_trace.atr'),
+        query="""
+        INCLUDE PERFETTO MODULE android.app_process_starts;
+        SELECT
+        process_name,
+        pid,
+        intent,
+        reason,
+        proc_start_ts,
+        proc_start_dur,
+        bind_app_ts,
+        bind_app_dur,
+        intent_ts,
+        intent_dur,
+        total_dur
+        FROM _android_app_process_starts
+        ORDER BY proc_start_ts
+      """,
+        out=Csv("""
+        "process_name","pid","intent","reason","proc_start_ts","proc_start_dur","bind_app_ts","bind_app_dur","intent_ts","intent_dur","total_dur"
+        "com.android.providers.media.module",3487,"com.android.providers.media.fuse.ExternalStorageServiceImpl","service",1737343157905,6527831,1737386174098,156129409,1737542356088,2114114,201312297
+        "com.android.externalstorage",3549," android.os.storage.action.VOLUME_STATE_CHANGED","broadcast",1739987238947,9277039,1740045665263,20602351,1740066288912,1480586,80530551
+      """))
diff --git a/test/trace_processor/diff_tests/stdlib/graphs/dominator_tree_tests.py b/test/trace_processor/diff_tests/stdlib/graphs/dominator_tree_tests.py
index d0462af..0ad4ddf 100644
--- a/test/trace_processor/diff_tests/stdlib/graphs/dominator_tree_tests.py
+++ b/test/trace_processor/diff_tests/stdlib/graphs/dominator_tree_tests.py
@@ -31,7 +31,7 @@
             SELECT 0 as source_node_id, 0 AS dest_node_id
             WHERE FALSE
           )
-          SELECT * FROM dominator_tree!(foo, NULL)
+          SELECT * FROM graph_dominator_tree!(foo, NULL)
         """,
         out=Csv("""
         "node_id","dominator_node_id"
@@ -48,7 +48,7 @@
             UNION ALL
             SELECT 10, 10
           )
-          SELECT * FROM dominator_tree!(foo, 5);
+          SELECT * FROM graph_dominator_tree!(foo, 5);
         """,
         out=Csv("""
         "node_id","dominator_node_id"
@@ -69,7 +69,7 @@
           UNION ALL
           VALUES (0, 10);
 
-          SELECT * FROM dominator_tree!(foo, 0);
+          SELECT * FROM graph_dominator_tree!(foo, 0);
         """,
         out=Csv("""
         "node_id","dominator_node_id"
@@ -112,7 +112,7 @@
               NULL,
               char(dominator_node_id)
             ) AS dominator_node_id
-          FROM dominator_tree!(bar, unicode('R'))
+          FROM graph_dominator_tree!(bar, unicode('R'))
           ORDER BY node_id;
         """,
         out=Csv("""
@@ -149,7 +149,7 @@
           UNION ALL
           VALUES (1, 10);
 
-          SELECT * FROM dominator_tree!(foo, 1) ORDER BY node_id;
+          SELECT * FROM graph_dominator_tree!(foo, 1) ORDER BY node_id;
         """,
         out=Csv("""
         "node_id","dominator_node_id"
@@ -177,7 +177,7 @@
           VALUES (0, 1), (0, 11), (0, 21);
 
           SELECT *
-          FROM dominator_tree!(foo, 0)
+          FROM graph_dominator_tree!(foo, 0)
           ORDER BY node_id;
         """,
         out=Csv("""
diff --git a/test/trace_processor/diff_tests/stdlib/slices/tests.py b/test/trace_processor/diff_tests/stdlib/slices/tests.py
index 4f814cc..9b565bb 100644
--- a/test/trace_processor/diff_tests/stdlib/slices/tests.py
+++ b/test/trace_processor/diff_tests/stdlib/slices/tests.py
@@ -54,10 +54,10 @@
     return DiffTestBlueprint(
         trace=Path('trace.py'),
         query="""
-        INCLUDE PERFETTO MODULE experimental.slices;
+        INCLUDE PERFETTO MODULE slices.slices;
 
         SELECT name, ts, dur, depth, thread_name, tid, process_name, pid
-        FROM experimental_slice_with_thread_and_process_info;
+        FROM _slice_with_thread_and_process_info;
       """,
         out=Csv("""
         "name","ts","dur","depth","thread_name","tid","process_name","pid"
@@ -143,10 +143,10 @@
     return DiffTestBlueprint(
         trace=DataPath('chrome_input_with_frame_view.pftrace'),
         query="""
-        INCLUDE PERFETTO MODULE experimental.flat_slices;
+        INCLUDE PERFETTO MODULE slices.flat_slices;
 
         SELECT e.name, e.ts, e.dur, e.depth
-        FROM experimental_slice_flattened e
+        FROM _slice_flattened e
         JOIN thread_track ON e.track_id = thread_track.id
         JOIN thread USING(utid)
         WHERE thread.tid = 30944;
diff --git a/test/trace_processor/diff_tests/tables/tests.py b/test/trace_processor/diff_tests/tables/tests.py
index 5a8f393..eabf714 100644
--- a/test/trace_processor/diff_tests/tables/tests.py
+++ b/test/trace_processor/diff_tests/tables/tests.py
@@ -212,6 +212,41 @@
         "
         """))
 
+  # Ftrace stats imports in metadata and stats tables
+  def test_filter_stats(self):
+    return DiffTestBlueprint(
+        trace=TextProto("""
+          packet { trace_stats{ filter_stats {
+            input_packets: 836
+            input_bytes: 25689644
+            output_bytes: 24826981
+            errors: 12
+            time_taken_ns: 1228178548
+            bytes_discarded_per_buffer: 1
+            bytes_discarded_per_buffer: 34
+            bytes_discarded_per_buffer: 29
+            bytes_discarded_per_buffer: 0
+            bytes_discarded_per_buffer: 862588
+          }}}"""),
+        query="""
+        SELECT name, value FROM stats
+        WHERE name like 'filter_%' OR name = 'traced_buf_bytes_filtered_out'
+        ORDER by name ASC
+        """,
+        out=Csv("""
+        "name","value"
+        "filter_errors",12
+        "filter_input_bytes",25689644
+        "filter_input_packets",836
+        "filter_output_bytes",24826981
+        "filter_time_taken_ns",1228178548
+        "traced_buf_bytes_filtered_out",1
+        "traced_buf_bytes_filtered_out",34
+        "traced_buf_bytes_filtered_out",29
+        "traced_buf_bytes_filtered_out",0
+        "traced_buf_bytes_filtered_out",862588
+        """))
+
   # cpu_track table
   def test_cpu_track_table(self):
     return DiffTestBlueprint(
@@ -268,8 +303,8 @@
     return DiffTestBlueprint(
         trace=DataPath('android_monitor_contention_trace.atr'),
         query="""
-      INCLUDE PERFETTO MODULE experimental.thread_state_flattened;
-      select * from experimental_get_flattened_thread_state_aggregated(11155, NULL);
+      INCLUDE PERFETTO MODULE sched.thread_state_flattened;
+      select * from _get_flattened_thread_state_aggregated(11155, NULL);
       """,
         out=Path('thread_state_flattened_aggregated_csv.out'))
 
@@ -277,8 +312,8 @@
     return DiffTestBlueprint(
         trace=DataPath('android_monitor_contention_trace.atr'),
         query="""
-      INCLUDE PERFETTO MODULE experimental.thread_state_flattened;
-      select * from experimental_get_flattened_thread_state(11155, NULL);
+      INCLUDE PERFETTO MODULE sched.thread_state_flattened;
+      select * from _get_flattened_thread_state(11155, NULL);
       """,
         out=Path('thread_state_flattened_csv.out'))
 
diff --git a/test/trace_processor/diff_tests/tables/tests_sched.py b/test/trace_processor/diff_tests/tables/tests_sched.py
index 3e82086..399cb55 100644
--- a/test/trace_processor/diff_tests/tables/tests_sched.py
+++ b/test/trace_processor/diff_tests/tables/tests_sched.py
@@ -126,7 +126,7 @@
     return DiffTestBlueprint(
         trace=DataPath('sched_wakeup_trace.atr'),
         query="""
-        INCLUDE PERFETTO MODULE experimental.thread_executing_span;
+        INCLUDE PERFETTO MODULE sched.thread_executing_span;
         SELECT
           root_id,
           parent_id,
@@ -140,7 +140,7 @@
           blocked_function,
           is_root,
           depth
-        FROM experimental_thread_executing_span_graph
+        FROM _thread_executing_span_graph
           WHERE blocked_function IS NOT NULL
         ORDER BY ts
         LIMIT 10
@@ -163,7 +163,7 @@
     return DiffTestBlueprint(
         trace=DataPath('sched_wakeup_trace.atr'),
         query="""
-        INCLUDE PERFETTO MODULE experimental.thread_executing_span;
+        INCLUDE PERFETTO MODULE sched.thread_executing_span;
         SELECT
           root_id,
           parent_id,
@@ -177,7 +177,7 @@
           blocked_function,
           is_root,
           depth
-        FROM experimental_thread_executing_span_graph
+        FROM _thread_executing_span_graph
           WHERE ts = 1735842081507 AND dur = 293868
         """,
         out=Csv("""
@@ -185,12 +185,12 @@
         357,369,376,1735842081507,293868,1465,230,"[NULL]","[NULL]","[NULL]",0,4
         """))
 
-  def test_thread_executing_span_internal_runnable_state_has_no_running(self):
+  def test_thread_executing_span_runnable_state_has_no_running(self):
     return DiffTestBlueprint(
         trace=DataPath('sched_wakeup_trace.atr'),
         query="""
-        INCLUDE PERFETTO MODULE experimental.thread_executing_span;
-        SELECT COUNT(*) AS count FROM internal_runnable_state WHERE state = 'Running'
+        INCLUDE PERFETTO MODULE sched.thread_executing_span;
+        SELECT COUNT(*) AS count FROM _runnable_state WHERE state = 'Running'
         """,
         out=Csv("""
         "count"
@@ -201,8 +201,8 @@
     return DiffTestBlueprint(
         trace=DataPath('sched_wakeup_trace.atr'),
         query="""
-        INCLUDE PERFETTO MODULE experimental.thread_executing_span;
-        SELECT ts,dur FROM experimental_thread_executing_span_graph
+        INCLUDE PERFETTO MODULE sched.thread_executing_span;
+        SELECT ts,dur FROM _thread_executing_span_graph
           WHERE dur IS NULL OR ts IS NULL
         """,
         out=Csv("""
@@ -213,8 +213,8 @@
     return DiffTestBlueprint(
         trace=DataPath('sched_switch_original.pb'),
         query="""
-        INCLUDE PERFETTO MODULE experimental.thread_executing_span;
-        SELECT COUNT(*) AS count FROM experimental_thread_executing_span_graph
+        INCLUDE PERFETTO MODULE sched.thread_executing_span;
+        SELECT COUNT(*) AS count FROM _thread_executing_span_graph
         """,
         out=Csv("""
         "count"
@@ -225,7 +225,7 @@
     return DiffTestBlueprint(
         trace=DataPath('sched_wakeup_trace.atr'),
         query="""
-        INCLUDE PERFETTO MODULE experimental.thread_executing_span;
+        INCLUDE PERFETTO MODULE sched.thread_executing_span;
         SELECT
           id,
           ts,
@@ -236,7 +236,7 @@
           critical_path_blocked_state,
           critical_path_blocked_function,
           critical_path_utid INT
-        FROM experimental_thread_executing_span_critical_path(NULL, start_ts, end_ts), trace_bounds
+        FROM _thread_executing_span_critical_path(NULL, start_ts, end_ts), trace_bounds
         ORDER BY ts
         LIMIT 10
         """,
@@ -258,7 +258,7 @@
     return DiffTestBlueprint(
         trace=DataPath('sched_wakeup_trace.atr'),
         query="""
-        INCLUDE PERFETTO MODULE experimental.thread_executing_span;
+        INCLUDE PERFETTO MODULE sched.thread_executing_span;
         SELECT
           id,
           ts,
@@ -269,7 +269,7 @@
           critical_path_blocked_state,
           critical_path_blocked_function,
           critical_path_utid INT
-        FROM experimental_thread_executing_span_critical_path((select utid from thread where tid = 3487), start_ts, end_ts), trace_bounds
+        FROM _thread_executing_span_critical_path((select utid from thread where tid = 3487), start_ts, end_ts), trace_bounds
         ORDER BY ts
         LIMIT 10
         """,
@@ -291,7 +291,7 @@
     return DiffTestBlueprint(
         trace=DataPath('sched_wakeup_trace.atr'),
         query="""
-        INCLUDE PERFETTO MODULE experimental.thread_executing_span;
+        INCLUDE PERFETTO MODULE sched.thread_executing_span;
         SELECT
           id,
           ts,
@@ -301,7 +301,7 @@
           name,
           table_name,
           critical_path_utid
-        FROM experimental_thread_executing_span_critical_path_stack((select utid from thread where tid = 3487), start_ts, end_ts), trace_bounds
+        FROM _thread_executing_span_critical_path_stack((select utid from thread where tid = 3487), start_ts, end_ts), trace_bounds
         ORDER BY ts
         LIMIT 11
         """,
@@ -324,8 +324,8 @@
     return DiffTestBlueprint(
         trace=DataPath('sched_wakeup_trace.atr'),
         query="""
-        INCLUDE PERFETTO MODULE experimental.thread_executing_span;
-        SELECT HEX(pprof) FROM experimental_thread_executing_span_critical_path_graph("critical path", (select utid from thread where tid = 3487), 1737488133487, 16000), trace_bounds
+        INCLUDE PERFETTO MODULE sched.thread_executing_span;
+        SELECT HEX(pprof) FROM _thread_executing_span_critical_path_graph("critical path", (select utid from thread where tid = 3487), 1737488133487, 16000), trace_bounds
       """,
         out=BinaryProto(
             message_type="perfetto.third_party.perftools.profiles.Profile",
diff --git a/test/traced_integrationtest.cc b/test/traced_integrationtest.cc
index 589e7cd..0ea703b 100644
--- a/test/traced_integrationtest.cc
+++ b/test/traced_integrationtest.cc
@@ -26,6 +26,7 @@
 #include "perfetto/ext/base/unix_socket.h"
 #include "perfetto/ext/base/utils.h"
 #include "perfetto/ext/tracing/core/commit_data_request.h"
+#include "perfetto/ext/tracing/core/null_consumer_endpoint_for_testing.h"
 #include "perfetto/ext/tracing/core/trace_packet.h"
 #include "perfetto/ext/tracing/core/tracing_service.h"
 #include "perfetto/protozero/scattered_heap_buffer.h"
@@ -57,6 +58,11 @@
 
 }  // namespace
 
+TEST(PerfettoTracedIntegrationTest, NullConsumerEndpointBuilds) {
+  NullConsumerEndpointForTesting npe;
+  npe.StartTracing();
+}
+
 TEST(PerfettoTracedIntegrationTest, TestFakeProducer) {
   base::TestTaskRunner task_runner;
 
diff --git a/tools/check_sql_modules.py b/tools/check_sql_modules.py
index 1cacd51..27e95cb 100755
--- a/tools/check_sql_modules.py
+++ b/tools/check_sql_modules.py
@@ -14,7 +14,7 @@
 # limitations under the License.
 
 # This tool checks that every SQL object created without prefix
-# 'internal_' is documented with proper schema.
+# '_' is documented with proper schema.
 
 import argparse
 from typing import List, Tuple
@@ -35,24 +35,21 @@
 # Allowlist path are relative to the stdlib root.
 CREATE_TABLE_ALLOWLIST = {
     '/android/binder.sql': [
-        'internal_oom_score', 'internal_async_binder_reply',
-        'internal_binder_async_txn_raw'
+        '_oom_score', '_async_binder_reply', '_binder_async_txn_raw'
     ],
     '/android/monitor_contention.sql': [
-        'internal_isolated', 'android_monitor_contention_chain',
+        '_isolated', 'android_monitor_contention_chain',
         'android_monitor_contention'
     ],
     '/chrome/tasks.sql': [
-        'internal_chrome_mojo_slices', 'internal_chrome_java_views',
-        'internal_chrome_scheduler_tasks', 'internal_chrome_tasks'
+        '_chrome_mojo_slices', '_chrome_java_views', '_chrome_scheduler_tasks',
+        '_chrome_tasks'
     ],
-    ('/experimental/'
-     'thread_executing_span.sql'): [
-        'internal_wakeup', 'experimental_thread_executing_span_graph',
-        'internal_critical_path', 'internal_wakeup_graph',
-        'experimental_thread_executing_span_graph'
+    '/sched/thread_executing_span.sql': [
+        '_wakeup', '_thread_executing_span_graph', '_critical_path',
+        '_wakeup_graph', '_thread_executing_span_graph'
     ],
-    '/experimental/flat_slices.sql': ['experimental_slice_flattened']
+    '/slices/flat_slices.sql': ['_slice_flattened']
 }
 
 
@@ -93,7 +90,7 @@
       with open(path, 'r') as f:
         sql = f.read()
 
-      parsed = parse_file(path, sql)
+      parsed = parse_file(rel_path, sql)
       modules.append((path, sql, parsed))
 
       if args.verbose:
diff --git a/tools/extract_linux_syscall_tables b/tools/extract_linux_syscall_tables
index e7c5b2d..05f676f 100755
--- a/tools/extract_linux_syscall_tables
+++ b/tools/extract_linux_syscall_tables
@@ -1,19 +1,58 @@
 #!/usr/bin/env python3
 
+import os
 import re
 import sys
 
 from urllib.request import urlopen
 
+PROJECT_ROOT = os.path.dirname(os.path.dirname(os.path.realpath(__file__)))
+SELF_PATH = os.path.relpath(__file__, PROJECT_ROOT).replace('\\', '/')
+
 syscalls = {}
+archs = ['aarch32', 'aarch64', 'armeabi', 'x86', 'x86_64']
 
-
-def print_table(name):
-  tab = syscalls[name]
-  print('\n\n----------------- BEGIN OF %s -----------------' % name)
-  for i in range(max(tab.keys()) + 1):
-    print('"%s",  // %d' % (tab.get(i, ''), i))
-  print('----------------- END OF %s -----------------' % name)
+def print_tables():
+  print('// DO NOT EDIT. Auto-generated by %s' % SELF_PATH)
+  print('#ifndef SRC_KERNEL_UTILS_SYSCALL_TABLE_GENERATED_H_')
+  print('#define SRC_KERNEL_UTILS_SYSCALL_TABLE_GENERATED_H_')
+  print('')
+  print('#include <stdint.h>')
+  print('')
+  print('namespace perfetto {')
+  print('')
+  # First of all merge all the syscall names from all tables and emit one big
+  # string with unique names.
+  syscall_names = set()
+  for arch in archs:
+    tab = syscalls[arch]
+    for i in range(max(tab.keys()) + 1):
+      syscall_names.add(tab.get(i, ''))
+  print('constexpr char kAllSyscalllNames[] =')
+  offset_by_name = {}
+  last_off = 0
+  for syscall_name in sorted(syscall_names):
+    if syscall_name in offset_by_name:
+      continue
+    print('  "%s\\0"' % syscall_name)
+    offset_by_name[syscall_name] = last_off
+    last_off += len(syscall_name) + 1
+  if last_off >= 0xffff:
+    raise Exception('SyscallTable::OffT must be increased to uint32_t')
+  print(';\n')
+  # Then print the individual tables.
+  for arch in archs:
+    tab = syscalls[arch]
+    print('struct SyscallTable_%s {' % arch)
+    print('  static constexpr const char* names = kAllSyscalllNames;')
+    print('  static constexpr SyscallTable::OffT offsets[] {')
+    for i in range(max(tab.keys()) + 1):
+      syscall_name = tab.get(i, '')
+      print('%d, // %d: %s' % (offset_by_name[syscall_name], i, syscall_name))
+    print('  };')
+    print('};\n')
+  print('}  // namespace perfetto')
+  print('#endif  // SRC_KERNEL_UTILS_SYSCALL_TABLE_GENERATED_H_')
 
 
 # Parses a .tbl file (new format).
@@ -61,11 +100,7 @@
   response = urlopen(KSRC + 'include/uapi/asm-generic/unistd.h')
   syscalls['aarch64'] = parse_def(response.read().decode())
 
-  print_table('x86_64')
-  print_table('x86')
-  print_table('aarch64')
-  print_table('armeabi')
-  print_table('aarch32')
+  print_tables()
 
 
 if __name__ == '__main__':
diff --git a/tools/gen_stdlib_docs_json.py b/tools/gen_stdlib_docs_json.py
index f5f8e5d..513b932 100755
--- a/tools/gen_stdlib_docs_json.py
+++ b/tools/gen_stdlib_docs_json.py
@@ -82,6 +82,7 @@
         'imports': [{
             'name': table.name,
             'desc': table.desc,
+            'summary_desc': table.desc.split('\n\n')[0].replace('\n', ' '),
             'type': table.type,
             'cols': {
                 col_name: {
@@ -93,6 +94,7 @@
         'functions': [{
             'name': function.name,
             'desc': function.desc,
+            'summary_desc': function.desc.split('\n\n')[0].replace('\n', ' '),
             'args': {
                 arg_name: {
                     'type': arg.type,
@@ -105,6 +107,7 @@
         'table_functions': [{
             'name': function.name,
             'desc': function.desc,
+            'summary_desc': function.desc.split('\n\n')[0].replace('\n', ' '),
             'args': {
                 arg_name: {
                     'type': arg.type,
@@ -118,6 +121,19 @@
                 } for (col_name, col) in function.cols.items()
             },
         } for function in docs.table_functions],
+        'macros': [{
+            'name': macro.name,
+            'desc': macro.desc,
+            'summary_desc': macro.desc.split('\n\n')[0].replace('\n', ' '),
+            'return_desc': macro.return_desc,
+            'return_type': macro.return_type,
+            'args': {
+                arg_name: {
+                    'type': arg.type,
+                    'desc': arg.description,
+                } for (arg_name, arg) in macro.args.items()
+            },
+        } for macro in docs.macros],
     }
     modules[module_name].append(file_dict)
 
diff --git a/tools/run_android_test b/tools/run_android_test
index 98a776a..63aba7b 100755
--- a/tools/run_android_test
+++ b/tools/run_android_test
@@ -166,16 +166,9 @@
   # See https://android.googlesource.com/platform/system/core/+/main/rootdir/etc/ld.config.txt.
   AdbPush(test_bin, "/data/nativetest")
 
-  ld_library_paths = []
   # These two binaries are required to run perfetto_integrationtests.
   AdbPush(os.path.join(args.out_dir, "perfetto"), "/data/nativetest")
   AdbPush(os.path.join(args.out_dir, "trigger_perfetto"), "/data/nativetest")
-  if os.path.exists(os.path.join(args.out_dir, "libperfetto.so")):
-    # libperfetto.so is required by the two binaries.
-    libperfetto_ondevice_dir = "%s/ld_library_path/" % (target_dir);
-    AdbCall('shell', 'mkdir -p "%s"' % (libperfetto_ondevice_dir))
-    AdbPush(os.path.join(args.out_dir, "libperfetto.so"), libperfetto_ondevice_dir)
-    ld_library_paths.append(libperfetto_ondevice_dir)
 
   if not args.no_data_deps:
     for dep in EnumerateDataDeps():
@@ -186,9 +179,7 @@
   env = ' '.join(args.env if args.env is not None else []) + ' '
   if os.path.exists(sanitizer_libs):
     AdbPush(sanitizer_libs, target_dir)
-    ld_library_paths.append("%s/sanitizer_libs" % (target_dir))
-  if ld_library_paths:
-    env += 'LD_LIBRARY_PATH=' + ':'.join(ld_library_paths) + ' '
+    env += 'LD_LIBRARY_PATH="%s/sanitizer_libs" ' % (target_dir)
   cmd = 'cd %s;' % target_dir
   binary = env + '/data/nativetest/%s' % args.test_name
   cmd += binary
diff --git a/ui/src/assets/details.scss b/ui/src/assets/details.scss
index ccf6a70..094d83c 100644
--- a/ui/src/assets/details.scss
+++ b/ui/src/assets/details.scss
@@ -703,7 +703,6 @@
   }
 }
 
-
 .pf-noselection {
   height: 100%;
-}
\ No newline at end of file
+}
diff --git a/ui/src/assets/widgets/empty_state.scss b/ui/src/assets/widgets/empty_state.scss
index 9ab17d7..cd70e14 100644
--- a/ui/src/assets/widgets/empty_state.scss
+++ b/ui/src/assets/widgets/empty_state.scss
@@ -21,36 +21,29 @@
   padding: 10px;
   user-select: none;
   color: $pf-minimal-foreground;
+  margin: auto;
+  justify-content: center;
 
   & > i {
-    margin: auto;
     font-size: 5em; // Size of the icon is relative to the font size.
     margin-bottom: 8px;
   }
 
-  .pf-empty-state-header {
-    margin-bottom: 8px;
+  // Limit width to the size of the container and use no wrap & elipsis to
+  // stop the size getting out of control.
+  max-width: 100%;
+  overflow: hidden;
+  text-overflow: ellipsis;
+  white-space: nowrap;
 
-    // Limit width to the size of the container and use no wrap & elipsis to
-    // stop the size getting out of control.
-    max-width: 100%;
-    overflow: hidden;
-    text-overflow: ellipsis;
-    white-space: nowrap;
-
-    .pf-empty-state-title {
-      text-align: center;
-      font-weight: bolder;
-      margin-bottom: 2px;
-    }
-
-    .pf-empty-state-detail {
-      text-align: center;
-      font-size: smaller;
-    }
+  .pf-empty-state-title {
+    text-align: center;
+    font-weight: bolder;
+    margin-bottom: 2px;
   }
 
   .pf-empty-state-content {
-    margin: auto;
+    text-align: center;
+    font-size: smaller;
   }
 }
diff --git a/ui/src/base/semantic_icons.ts b/ui/src/base/semantic_icons.ts
index 21fc9d2..6a8340e 100644
--- a/ui/src/base/semantic_icons.ts
+++ b/ui/src/base/semantic_icons.ts
@@ -37,4 +37,5 @@
   static readonly SelectAll = 'select_all';
   static readonly Deselect = 'deselect';
   static readonly Star = 'star';
+  static readonly ChangeTab = 'tab';
 }
diff --git a/ui/src/common/plugins.ts b/ui/src/common/plugins.ts
index 9535b08..efbd8c0 100644
--- a/ui/src/common/plugins.ts
+++ b/ui/src/common/plugins.ts
@@ -20,7 +20,7 @@
 import {globals} from '../frontend/globals';
 import {
   Command,
-  CurrentSelectionSection,
+  DetailsPanel,
   EngineProxy,
   MetricVisualisation,
   Migrate,
@@ -41,6 +41,7 @@
 import {Actions} from './actions';
 import {Registry} from './registry';
 import {SCROLLING_TRACK_GROUP} from './state';
+import {addQueryResultsTab} from '../frontend/query_result_tab';
 
 // Every plugin gets its own PluginContext. This is how we keep track
 // what each plugin is doing and how we can blame issues on particular
@@ -160,17 +161,16 @@
   registerTab(desc: TabDescriptor): void {
     if (!this.alive) return;
 
-    globals.tabManager.registerTab(desc);
-    this.trash.addCallback(() => globals.tabManager.unregisterTab(desc.uri));
+    const unregister = globals.tabManager.registerTab(desc);
+    this.trash.add(unregister);
   }
 
-  registerCurrentSelectionSection(section: CurrentSelectionSection): void {
+  registerDetailsPanel(section: DetailsPanel): void {
     if (!this.alive) return;
 
     const tabMan = globals.tabManager;
-    tabMan.registerCurrentSelectionSection(section);
-    this.trash.addCallback(
-      () => tabMan.unregisterCurrentSelectionSection(section));
+    const unregister = tabMan.registerDetailsPanel(section);
+    this.trash.add(unregister);
   }
 
   get sidebar() {
@@ -179,7 +179,7 @@
 
   readonly tabs = {
     openQuery: (query: string, title: string) => {
-      globals.openQuery(query, title);
+      addQueryResultsTab({query, title});
     },
 
     showTab(uri: string):
diff --git a/ui/src/common/recordingV2/recording_config_utils.ts b/ui/src/common/recordingV2/recording_config_utils.ts
index c204872..a14415b 100644
--- a/ui/src/common/recordingV2/recording_config_utils.ts
+++ b/ui/src/common/recordingV2/recording_config_utils.ts
@@ -497,6 +497,7 @@
     addCategoryAndDisabledByDefault('scheduler');
     addCategoryAndDisabledByDefault('p2p');
     addCategoryAndDisabledByDefault('net');
+    chromeCategories.add('base');
   }
 
   if (uiCfg.video) {
diff --git a/ui/src/common/tab_registry.ts b/ui/src/common/tab_registry.ts
index d564c9b..e9493de 100644
--- a/ui/src/common/tab_registry.ts
+++ b/ui/src/common/tab_registry.ts
@@ -12,8 +12,8 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-import {Disposable} from '../base/disposable';
-import {CurrentSelectionSection, TabDescriptor} from '../public';
+import {Disposable, DisposableCallback} from '../base/disposable';
+import {DetailsPanel, TabDescriptor} from '../public';
 
 export interface ResolvedTab {
   uri: string;
@@ -26,7 +26,7 @@
  */
 export class TabManager implements Disposable {
   private _registry = new Map<string, TabDescriptor>();
-  private _currentSelectionSectionReg = new Set<CurrentSelectionSection>();
+  private _detailsPanelsRegistry = new Set<DetailsPanel>();
   private _currentTabs = new Map<string, TabDescriptor>();
 
   dispose(): void {
@@ -37,20 +37,18 @@
     this._currentTabs.clear();
   }
 
-  registerTab(desc: TabDescriptor): void {
+  registerTab(desc: TabDescriptor): Disposable {
     this._registry.set(desc.uri, desc);
+    return new DisposableCallback(() => {
+      this._registry.delete(desc.uri);
+    });
   }
 
-  unregisterTab(uri: string): void {
-    this._registry.delete(uri);
-  }
-
-  registerCurrentSelectionSection(section: CurrentSelectionSection): void {
-    this._currentSelectionSectionReg.add(section);
-  }
-
-  unregisterCurrentSelectionSection(section: CurrentSelectionSection): void {
-    this._currentSelectionSectionReg.delete(section);
+  registerDetailsPanel(section: DetailsPanel): Disposable {
+    this._detailsPanelsRegistry.add(section);
+    return new DisposableCallback(() => {
+      this._detailsPanelsRegistry.delete(section);
+    });
   }
 
   resolveTab(uri: string): TabDescriptor|undefined {
@@ -61,8 +59,8 @@
     return Array.from(this._registry.values());
   }
 
-  get currentSelectionSections(): CurrentSelectionSection[] {
-    return Array.from(this._currentSelectionSectionReg);
+  get detailsPanels(): DetailsPanel[] {
+    return Array.from(this._detailsPanelsRegistry);
   }
 
   /**
diff --git a/ui/src/controller/trace_controller.ts b/ui/src/controller/trace_controller.ts
index f752427..b5c6994 100644
--- a/ui/src/controller/trace_controller.ts
+++ b/ui/src/controller/trace_controller.ts
@@ -59,6 +59,7 @@
   publishRealtimeOffset,
   publishThreads,
 } from '../frontend/publish';
+import {addQueryResultsTab} from '../frontend/query_result_tab';
 import {Router} from '../frontend/router';
 import {Engine} from '../trace_processor/engine';
 import {HttpRpcEngine} from '../trace_processor/http_rpc_engine';
@@ -629,7 +630,10 @@
           pendingDeeplink.visStart, pendingDeeplink.visEnd);
       }
       if (pendingDeeplink.query !== undefined) {
-        globals.openQuery(pendingDeeplink.query, 'Deeplink Query');
+        addQueryResultsTab({
+          query: pendingDeeplink.query,
+          title: 'Deeplink Query',
+        });
       }
     }
 
diff --git a/ui/src/core/feature_flags.ts b/ui/src/core/feature_flags.ts
index c6c98bd..f00d535 100644
--- a/ui/src/core/feature_flags.ts
+++ b/ui/src/core/feature_flags.ts
@@ -244,3 +244,10 @@
   description: 'Record using V2 interface',
   defaultValue: false,
 });
+
+export const TABS_V2_FLAG = featureFlags.register({
+  id: 'tabsv2',
+  name: 'Tabs V2',
+  description: 'Use Tabs V2',
+  defaultValue: false,
+});
diff --git a/ui/src/frontend/aggregation_panel.ts b/ui/src/frontend/aggregation_panel.ts
index c7f3eb8..f104f9a 100644
--- a/ui/src/frontend/aggregation_panel.ts
+++ b/ui/src/frontend/aggregation_panel.ts
@@ -19,21 +19,47 @@
   AggregateData,
   Column,
   ThreadStateExtra,
+  isEmptyData,
 } from '../common/aggregation_data';
 import {colorForState} from '../common/colorizer';
 import {translateState} from '../common/thread_state';
 
 import {globals} from './globals';
 import {DurationWidget} from './widgets/duration';
+import {EmptyState} from '../widgets/empty_state';
+import {Anchor} from '../widgets/anchor';
+import {Icons} from '../base/semantic_icons';
 
 export interface AggregationPanelAttrs {
-  data: AggregateData;
+  data?: AggregateData;
   kind: string;
 }
 
 export class AggregationPanel implements
     m.ClassComponent<AggregationPanelAttrs> {
   view({attrs}: m.CVnode<AggregationPanelAttrs>) {
+    if (!globals.state.currentSelection) {
+      return m(EmptyState, {
+        className: 'pf-noselection',
+        title: 'Nothing selected',
+      }, 'Aggregation data will appear here');
+    }
+
+    if (!attrs.data || isEmptyData(attrs.data)) {
+      return m(EmptyState,
+        {
+          className: 'pf-noselection',
+          title: 'No relevant tracks in selection',
+        },
+        m(Anchor, {
+          icon: Icons.ChangeTab,
+          onclick: () => {
+            globals.dispatch(Actions.showTab({uri: 'current_selection'}));
+          },
+        }, 'Go to current selection tab'),
+      );
+    }
+
     return m(
       '.details-panel',
       m('.details-panel-heading.aggregation',
diff --git a/ui/src/frontend/aggregation_tab.ts b/ui/src/frontend/aggregation_tab.ts
new file mode 100644
index 0000000..4ad888c
--- /dev/null
+++ b/ui/src/frontend/aggregation_tab.ts
@@ -0,0 +1,160 @@
+// Copyright (C) 2024 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use size file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+import m from 'mithril';
+import {Disposable, Trash} from '../base/disposable';
+import {AggregationPanel} from './aggregation_panel';
+import {globals} from './globals';
+import {Area, AreaSelection} from '../common/state';
+import {Anchor} from '../widgets/anchor';
+import {Actions} from '../common/actions';
+import {isEmptyData} from '../common/aggregation_data';
+import {DetailsShell} from '../widgets/details_shell';
+import {Section} from '../widgets/section';
+import {GridLayout} from '../widgets/grid_layout';
+import {Icons} from '../base/semantic_icons';
+import {Tree, TreeNode} from '../widgets/tree';
+import {Timestamp} from './widgets/timestamp';
+
+interface AreaDetailsPanelAttrs {
+  selection: AreaSelection;
+}
+
+class AreaDetailsPanel implements m.ClassComponent<AreaDetailsPanelAttrs> {
+  view(vnode: m.Vnode<AreaDetailsPanelAttrs>): m.Children {
+    const {
+      selection,
+    } = vnode.attrs;
+
+    const areaId = selection.areaId;
+    const area = globals.state.areas[areaId];
+
+    return m(DetailsShell,
+      {
+        title: 'Area Selection',
+      },
+      m(GridLayout,
+        this.renderDetailsSection(area),
+        this.renderLinksSection(),
+      ),
+    );
+  }
+
+  private renderDetailsSection(area: Area) {
+    return m(Section,
+      {
+        title: 'Details',
+      },
+      m(Tree,
+        m(TreeNode, {left: 'Start', right: m(Timestamp, {ts: area.start})}),
+        m(TreeNode, {left: 'End', right: m(Timestamp, {ts: area.end})}),
+        m(TreeNode, {left: 'Track Count', right: area.tracks.length}),
+      ),
+    );
+  }
+
+  private renderLinksSection() {
+    const aggTabLinks: m.Children = [];
+    globals.aggregateDataStore.forEach((value, type) => {
+      if (!isEmptyData(value)) {
+        const anchor = m(Anchor,
+          {
+            icon: Icons.ChangeTab,
+            onclick: () => {
+              globals.dispatch(Actions.showTab({uri: uriForAggType(type)}));
+            },
+          },
+          value.tabName,
+        );
+        const node = m(TreeNode, {left: anchor});
+        aggTabLinks.push(node);
+      }
+    });
+    if (aggTabLinks.length === 0) return undefined;
+    return m(Section,
+      {
+        title: 'Relevant Aggregations',
+      },
+      m(Tree, aggTabLinks),
+    );
+  }
+}
+
+function uriForAggType(type: string): string {
+  return `aggregationTab#${type}`;
+}
+
+export class AggregationsTabs implements Disposable {
+  private tabs = [
+    {
+      type: 'cpu_aggregation',
+      title: 'CPU by thread',
+    },
+    {
+      type: 'thread_state_aggregation',
+      title: 'Thread States',
+    },
+    {
+      type: 'cpu_by_process_aggregation',
+      title: 'CPU by process',
+    },
+    {
+      type: 'slice_aggregation',
+      title: 'Slices',
+    },
+    {
+      type: 'counter_aggregation',
+      title: 'Counters',
+    },
+    {
+      type: 'frame_aggregation',
+      title: 'Frames',
+    },
+  ];
+
+  private trash = new Trash();
+
+  constructor() {
+    for (const {type, title} of this.tabs) {
+      const unregister = globals.tabManager.registerTab({
+        uri: uriForAggType(type),
+        isEphemeral: false,
+        content: {
+          getTitle: () => `Aggregation: ${title}`,
+          render: () => {
+            const data = globals.aggregateDataStore.get(type);
+            return m(AggregationPanel, {kind: type, data});
+          },
+        },
+      });
+      this.trash.add(unregister);
+    }
+
+    const unregister = globals.tabManager.registerDetailsPanel({
+      render(selection) {
+        if (selection.kind === 'AREA') {
+          return m(AreaDetailsPanel, {selection});
+        } else {
+          return undefined;
+        }
+      },
+    });
+
+    this.trash.add(unregister);
+  }
+
+  dispose(): void {
+    this.trash.dispose();
+  }
+}
diff --git a/ui/src/frontend/app.ts b/ui/src/frontend/app.ts
index 8eed31d..015b893 100644
--- a/ui/src/frontend/app.ts
+++ b/ui/src/frontend/app.ts
@@ -43,23 +43,24 @@
 import {HotkeyGlyphs} from '../widgets/hotkey_glyphs';
 import {maybeRenderFullscreenModalDialog} from '../widgets/modal';
 
-import {addTab} from './bottom_tab';
 import {onClickCopy} from './clipboard';
 import {CookieConsent} from './cookie_consent';
 import {globals} from './globals';
 import {toggleHelp} from './help_modal';
+import {Notes} from './notes';
 import {Omnibox, OmniboxOption} from './omnibox';
-import {runQueryInNewTab} from './query_result_tab';
+import {addQueryResultsTab} from './query_result_tab';
 import {verticalScrollToTrack} from './scroll_helper';
 import {executeSearch} from './search_handler';
 import {Sidebar} from './sidebar';
-import {SqlTableTab} from './sql_table/tab';
-import {SqlTables} from './sql_table/well_known_tables';
 import {Utid} from './sql_types';
 import {getThreadInfo} from './thread_and_process_info';
 import {Topbar} from './topbar';
 import {shareTrace} from './trace_attrs';
 import {addDebugSliceTrack} from './debug_tracks';
+import {AggregationsTabs} from './aggregation_tab';
+import {addSqlTableTab} from './sql_table/tab';
+import {SqlTables} from './sql_table/well_known_tables';
 
 function renderPermalink(): m.Children {
   const permalink = globals.state.permalink;
@@ -149,6 +150,8 @@
   constructor() {
     const unreg = globals.commandManager.registerCommandSource(this);
     this.trash.add(unreg);
+    this.trash.add(new Notes());
+    this.trash.add(new AggregationsTabs());
   }
 
   private getEngine(): EngineProxy|undefined {
@@ -320,7 +323,7 @@
 
             if (engine !== undefined && trackUtid != 0) {
               await runQuery(
-                `SELECT IMPORT('experimental.thread_executing_span');`,
+                `SELECT IMPORT('sched.thread_executing_span');`,
                 engine);
               await addDebugSliceTrack(
                 engine,
@@ -335,7 +338,7 @@
                       process.name AS process_name,
                       'thread_state' AS table_name
                     FROM
-                      experimental_thread_executing_span_critical_path(
+                      _thread_executing_span_critical_path(
                           ${trackUtid},
                           ${window.start},
                           ${window.end} - ${window.start}) cr
@@ -362,7 +365,7 @@
 
             if (engine !== undefined && trackUtid != 0) {
               await runQuery(
-                `SELECT IMPORT('experimental.thread_executing_span');`,
+                `SELECT IMPORT('sched.thread_executing_span');`,
                 engine);
               await addDebugSliceTrack(
                 engine,
@@ -370,7 +373,7 @@
                   sqlSource: `
                         SELECT cr.id, cr.utid, cr.ts, cr.dur, cr.name, cr.table_name
                         FROM
-                        internal_critical_path_stack(
+                        _critical_path_stack(
                           ${trackUtid},
                           ${window.start},
                           ${window.end} - ${
@@ -395,17 +398,16 @@
             const engine = this.getEngine();
 
             if (engine !== undefined && trackUtid != 0) {
-              runQueryInNewTab(
-                `SELECT IMPORT('experimental.thread_executing_span');
+              addQueryResultsTab({
+                query: `SELECT IMPORT('sched.thread_executing_span');
                    SELECT *
                       FROM
-                        experimental_thread_executing_span_critical_path_graph(
+                        _thread_executing_span_critical_path_graph(
                         "criical_path",
                          ${trackUtid},
                          ${window.start},
                          ${window.end} - ${window.start}) cr`,
-                'Critical path',
-                'omnibox_query');
+                title: 'Critical path'});
             }
           },
     },
@@ -414,12 +416,9 @@
       name: 'Show slice table',
       callback:
           () => {
-            addTab({
-              kind: SqlTableTab.kind,
-              config: {
-                table: SqlTables.slice,
-                displayName: 'slice',
-              },
+            addSqlTableTab({
+              table: SqlTables.slice,
+              displayName: 'slice',
             });
           },
     },
@@ -722,11 +721,13 @@
         this.queryText = value;
         raf.scheduleFullRedraw();
       },
-      onSubmit: (value, alt) => {
-        globals.openQuery(
-          undoCommonChatAppReplacements(value),
-          alt ? 'Pinned query' : 'Omnibox query',
-          alt ? undefined : 'omnibox_query');
+      onSubmit: (query, alt) => {
+        const config = {
+          query: undoCommonChatAppReplacements(query),
+          title: alt ? 'Pinned query' : 'Omnibox query',
+        };
+        const tag = alt? undefined : 'omnibox_query';
+        addQueryResultsTab(config, tag);
       },
       onClose: () => {
         this.queryText = '';
diff --git a/ui/src/frontend/chrome_slice_details_tab.ts b/ui/src/frontend/chrome_slice_details_tab.ts
index 6f5502b..920c8c8 100644
--- a/ui/src/frontend/chrome_slice_details_tab.ts
+++ b/ui/src/frontend/chrome_slice_details_tab.ts
@@ -44,6 +44,7 @@
 import {asSliceSqlId} from './sql_types';
 import {DurationWidget} from './widgets/duration';
 import {addDebugSliceTrack} from './debug_tracks';
+import {addQueryResultsTab} from './query_result_tab';
 
 interface ContextMenuItem {
   name: string;
@@ -91,10 +92,10 @@
   {
     name: 'Average duration of slice name',
     shouldDisplay: (slice: SliceDetails) => hasName(slice),
-    run: (slice: SliceDetails) => globals.openQuery(
-      `SELECT AVG(dur) / 1e9 FROM slice WHERE name = '${slice.name!}'`,
-      `${slice.name} average dur`,
-    ),
+    run: (slice: SliceDetails) => addQueryResultsTab({
+      query: `SELECT AVG(dur) / 1e9 FROM slice WHERE name = '${slice.name!}'`,
+      title: `${slice.name} average dur`,
+    }),
   },
   {
     name: 'Binder txn names + monitor contention on thread',
diff --git a/ui/src/frontend/details_panel.ts b/ui/src/frontend/details_panel.ts
index 3edce5d..3aabbf1 100644
--- a/ui/src/frontend/details_panel.ts
+++ b/ui/src/frontend/details_panel.ts
@@ -26,8 +26,7 @@
 import {ChromeSliceDetailsTab} from './chrome_slice_details_tab';
 import {CounterDetailsPanel} from './counter_panel';
 import {CpuProfileDetailsPanel} from './cpu_profile_panel';
-import {DEFAULT_DETAILS_CONTENT_HEIGHT} from './css_constants';
-import {DragHandle} from './drag_handle';
+import {DragHandle, getDefaultDetailsHeight} from './drag_handle';
 import {FlamegraphDetailsPanel} from './flamegraph_panel';
 import {
   FlowEventsAreaSelectedPanel,
@@ -41,16 +40,8 @@
 import {SliceDetailsPanel} from './slice_details_panel';
 import {ThreadStateTab} from './thread_state_tab';
 
-const DRAG_HANDLE_HEIGHT_PX = 28;
-
 export const CURRENT_SELECTION_TAG = 'current_selection';
 
-function getDetailsHeight() {
-  // This needs to be a function instead of a const to ensure the CSS constants
-  // have been initialized by the time we perform this calculation;
-  return DEFAULT_DETAILS_CONTENT_HEIGHT + DRAG_HANDLE_HEIGHT_PX;
-}
-
 function hasLogs(): boolean {
   const data =
       globals.trackDataStore.get(LogExistsKey) as LogExists | undefined;
@@ -126,7 +117,7 @@
 addSelectionChangeObserver(handleSelectionChange);
 
 export class DetailsPanel implements m.ClassComponent {
-  private detailsHeight = getDetailsHeight();
+  private detailsHeight = getDefaultDetailsHeight();
 
   view() {
     interface DetailsPanel {
diff --git a/ui/src/frontend/drag_handle.ts b/ui/src/frontend/drag_handle.ts
index 425899c..21f044b 100644
--- a/ui/src/frontend/drag_handle.ts
+++ b/ui/src/frontend/drag_handle.ts
@@ -47,6 +47,9 @@
 
   // Called when tab dropdown entry is clicked.
   onClick: () => void;
+
+  // Whether this tab is checked or not
+  checked: boolean;
 }
 
 export interface DragHandleAttrs {
@@ -73,19 +76,19 @@
   onTabClose?: (key: string) => void;
 }
 
-export function getDetailsHeight() {
+export function getDefaultDetailsHeight() {
   // This needs to be a function instead of a const to ensure the CSS constants
   // have been initialized by the time we perform this calculation;
-  return DEFAULT_DETAILS_CONTENT_HEIGHT + DRAG_HANDLE_HEIGHT_PX;
+  return DRAG_HANDLE_HEIGHT_PX + DEFAULT_DETAILS_CONTENT_HEIGHT;
 }
 
 function getFullScreenHeight() {
-  const panelContainer =
-      document.querySelector('.pan-and-zoom-content') as HTMLElement;
-  if (panelContainer !== null) {
-    return panelContainer.clientHeight;
+  const page = document.querySelector('.page') as HTMLElement;
+  if (page === null) {
+    // Fall back to at least partially open.
+    return getDefaultDetailsHeight();
   } else {
-    return getDetailsHeight();
+    return page.clientHeight;
   }
 }
 
@@ -96,8 +99,9 @@
   private resize: (height: number) => void = () => {};
   private isClosed = this.height <= 0;
   private isFullscreen = false;
-  // We can't get real fullscreen height until the pan_and_zoom_handler exists.
-  private fullscreenHeight = getDetailsHeight();
+  // We can't get real fullscreen height until the pan_and_zoom_handler
+  // exists.
+  private fullscreenHeight = 0;
   private trash: Trash = new Trash();
 
   oncreate({dom, attrs}: m.CVnodeDOM<DragHandleAttrs>) {
@@ -188,6 +192,8 @@
             onclick: () => {
               this.isClosed = false;
               this.isFullscreen = true;
+              // Ensure fullscreenHeight is up to date.
+              this.fullscreenHeight = getFullScreenHeight();
               this.resize(this.fullscreenHeight);
               raf.scheduleFullRedraw();
             },
@@ -205,7 +211,7 @@
               if (this.height === 0) {
                 this.isClosed = false;
                 if (this.previousHeight === 0) {
-                  this.previousHeight = getDetailsHeight();
+                  this.previousHeight = getDefaultDetailsHeight();
                 }
                 this.resize(this.previousHeight);
               } else {
@@ -241,6 +247,7 @@
           key: entry.key,
           label: entry.title,
           onclick: () => entry.onClick(),
+          icon: entry.checked ? 'check_box' : 'check_box_outline_blank',
         });
       }),
     );
diff --git a/ui/src/frontend/globals.ts b/ui/src/frontend/globals.ts
index 205beab..2f0cd7f 100644
--- a/ui/src/frontend/globals.ts
+++ b/ui/src/frontend/globals.ts
@@ -238,8 +238,6 @@
   clearSearch?: boolean;
 }
 
-type OpenQueryHandler = (query: string, title: string, tag?: string) => void;
-
 /**
  * Global accessors for state/dispatch in the frontend.
  */
@@ -286,7 +284,6 @@
   private _realtimeOffset = Time.ZERO;
   private _utcOffset = Time.ZERO;
   private _traceTzOffset = Time.ZERO;
-  private _openQueryHandler?: OpenQueryHandler;
   private _tabManager = new TabManager();
   private _trackManager = new TrackManager(this._store);
 
@@ -872,22 +869,6 @@
     return {start, end};
   }
 
-  // The implementation of the query results tab is not part of the core so we
-  // decouple globals from the implementation using this registration interface.
-  // Once we move the implementation to a plugin, this decoupling will be
-  // simpler as we just need to call a command with a well-known ID, and a
-  // plugin will provide the implementation.
-  registerOpenQueryHandler(cb: OpenQueryHandler) {
-    this._openQueryHandler = cb;
-  }
-
-  // Runs a query and displays results in a new tab.
-  // Queries will override previously opened queries with the same tag.
-  // If the tag is omitted, the results will always open in a new tab.
-  openQuery(query: string, title: string, tag?: string) {
-    assertExists(this._openQueryHandler)(query, title, tag);
-  }
-
   panToTimestamp(ts: time): void {
     horizontalScrollToTs(ts);
   }
diff --git a/ui/src/frontend/notes.ts b/ui/src/frontend/notes.ts
new file mode 100644
index 0000000..2b51603
--- /dev/null
+++ b/ui/src/frontend/notes.ts
@@ -0,0 +1,47 @@
+import {Disposable, Trash} from '../base/disposable';
+import {assertExists} from '../base/logging';
+import {uuidv4} from '../base/uuid';
+import {BottomTabToSCSAdapter} from '../public';
+
+import {globals} from './globals';
+import {NotesEditorTab} from './notes_panel';
+
+function getEngine() {
+  const engineId = assertExists(globals.getCurrentEngine()).id;
+  const engine = assertExists(globals.engines.get(engineId));
+  return engine;
+}
+
+/**
+ * Registers with the tab manager to show notes details panels when notes are
+ * selected.
+ *
+ * Notes are core functionality thus don't really belong in a plugin.
+ */
+export class Notes implements Disposable {
+  private trash = new Trash();
+
+  constructor() {
+    const unregister = globals.tabManager.registerDetailsPanel(
+      new BottomTabToSCSAdapter({
+        tabFactory: (selection) => {
+          if (selection.kind === 'NOTE') {
+            return new NotesEditorTab({
+              config: {
+                id: selection.id,
+              },
+              engine: getEngine().getProxy('Notes'),
+              uuid: uuidv4(),
+            });
+          } else {
+            return undefined;
+          }
+        },
+      }));
+    this.trash.add(unregister);
+  }
+
+  dispose(): void {
+    this.trash.dispose();
+  }
+}
diff --git a/ui/src/frontend/omnibox.ts b/ui/src/frontend/omnibox.ts
index 5d809c9..b7945da 100644
--- a/ui/src/frontend/omnibox.ts
+++ b/ui/src/frontend/omnibox.ts
@@ -249,7 +249,7 @@
     if (!options) return null;
 
     if (options.length === 0) {
-      return m(EmptyState, {header: 'No matching options...'});
+      return m(EmptyState, {title: 'No matching options...'});
     } else {
       return m(
         '.pf-omnibox-dropdown',
diff --git a/ui/src/frontend/pivot_table.ts b/ui/src/frontend/pivot_table.ts
index 483ead2..d241534 100644
--- a/ui/src/frontend/pivot_table.ts
+++ b/ui/src/frontend/pivot_table.ts
@@ -29,7 +29,6 @@
 import {raf} from '../core/raf_scheduler';
 import {ColumnType} from '../trace_processor/query_result';
 
-import {addTab} from './bottom_tab';
 import {globals} from './globals';
 import {
   aggregationIndex,
@@ -47,7 +46,7 @@
 } from './pivot_table_types';
 import {PopupMenuButton, popupMenuIcon, PopupMenuItem} from './popup_menu';
 import {ReorderableCell, ReorderableCellGroup} from './reorderable_cells';
-import {SqlTableTab} from './sql_table/tab';
+import {addSqlTableTab} from './sql_table/tab';
 import {SqlTables} from './sql_table/well_known_tables';
 import {AttributeModalHolder} from './tables/attribute_modal_holder';
 import {DurationWidget} from './widgets/duration';
@@ -136,12 +135,9 @@
             if (this.constrainToArea) {
               queryFilters.push(...areaFilters(area));
             }
-            addTab({
-              kind: SqlTableTab.kind,
-              config: {
-                table: SqlTables.slice,
-                filters: queryFilters,
-              },
+            addSqlTableTab({
+              table: SqlTables.slice,
+              filters: queryFilters,
             });
           },
         },
diff --git a/ui/src/frontend/query_page.ts b/ui/src/frontend/query_page.ts
index 98a4881..4ff1715 100644
--- a/ui/src/frontend/query_page.ts
+++ b/ui/src/frontend/query_page.ts
@@ -24,11 +24,10 @@
 import {Callout} from '../widgets/callout';
 import {Editor} from '../widgets/editor';
 
-import {addTab} from './bottom_tab';
 import {globals} from './globals';
 import {createPage} from './pages';
 import {QueryHistoryComponent, queryHistoryStorage} from './query_history';
-import {QueryResultTab} from './query_result_tab';
+import {addQueryResultsTab} from './query_result_tab';
 import {QueryTable} from './query_table';
 
 interface QueryPageState {
@@ -52,15 +51,14 @@
   if (engine) {
     runQuery(undoCommonChatAppReplacements(query), engine)
       .then((resp: QueryResponse) => {
-        addTab({
-          kind: QueryResultTab.kind,
-          tag: 'analyze_page_query',
-          config: {
+        addQueryResultsTab(
+          {
             query: query,
             title: 'Standalone Query',
             prefetchedResponse: resp,
           },
-        });
+          'analyze_page_query',
+        );
         // We might have started to execute another query. Ignore it in that
         // case.
         if (state.executedQuery !== query) {
diff --git a/ui/src/frontend/query_result_tab.ts b/ui/src/frontend/query_result_tab.ts
index 2f0c903..d42dd48 100644
--- a/ui/src/frontend/query_result_tab.ts
+++ b/ui/src/frontend/query_result_tab.ts
@@ -34,21 +34,12 @@
   closeTab,
   NewBottomTabArgs,
 } from './bottom_tab';
-import {globals} from './globals';
 import {QueryTable} from './query_table';
-
-export function runQueryInNewTab(query: string, title: string, tag?: string) {
-  return addTab({
-    kind: QueryResultTab.kind,
-    tag,
-    config: {
-      query,
-      title,
-    },
-  });
-}
-
-globals.registerOpenQueryHandler(runQueryInNewTab);
+import {TABS_V2_FLAG} from '../core/feature_flags';
+import {globals} from './globals';
+import {Actions} from '../common/actions';
+import {BottomTabToTabAdapter} from '../public/utils';
+import {EngineProxy} from '../public';
 
 interface QueryResultTabConfig {
   readonly query: string;
@@ -58,6 +49,42 @@
   readonly prefetchedResponse?: QueryResponse;
 }
 
+// External interface for adding a new query results tab
+// Automatically decided whether to add v1 or v2 tab
+export function addQueryResultsTab(
+  config: QueryResultTabConfig, tag?: string): void {
+  if (TABS_V2_FLAG.get()) {
+    const queryResultsTab = new QueryResultTab({
+      config,
+      engine: getEngine(),
+      uuid: uuidv4(),
+    });
+
+    const uri = 'queryResults#' + (tag ?? uuidv4());
+
+    globals.tabManager.registerTab({
+      uri,
+      content: new BottomTabToTabAdapter(queryResultsTab),
+      isEphemeral: true,
+    });
+
+    globals.dispatch(Actions.showTab({uri}));
+  } else {
+    return addTab({
+      kind: QueryResultTab.kind,
+      tag,
+      config,
+    });
+  }
+}
+
+// TODO(stevegolton): Find a way to make this more elegant.
+function getEngine(): EngineProxy {
+  const engConfig = globals.getCurrentEngine();
+  const engineId = assertExists(engConfig).id;
+  return assertExists(globals.engines.get(engineId)).getProxy('QueryResult');
+}
+
 export class QueryResultTab extends BottomTab<QueryResultTabConfig> {
   static readonly kind = 'dev.perfetto.QueryResultTab';
 
diff --git a/ui/src/frontend/slice_args.ts b/ui/src/frontend/slice_args.ts
index 9d4c122..341fbe1 100644
--- a/ui/src/frontend/slice_args.ts
+++ b/ui/src/frontend/slice_args.ts
@@ -32,10 +32,9 @@
 import {MenuItem, PopupMenu2} from '../widgets/menu';
 import {TreeNode} from '../widgets/tree';
 
-import {addTab} from './bottom_tab';
 import {globals} from './globals';
 import {Arg} from './sql/args';
-import {SqlTableTab} from './sql_table/tab';
+import {addSqlTableTab} from './sql_table/tab';
 import {SqlTables} from './sql_table/well_known_tables';
 
 // Renders slice arguments (key/value pairs) as a subtree.
@@ -96,17 +95,14 @@
         label: 'Find slices with same arg value',
         icon: 'search',
         onclick: () => {
-          addTab({
-            kind: SqlTableTab.kind,
-            config: {
-              table: SqlTables.slice,
-              filters: [{
-                type: 'arg_filter',
-                argSetIdColumn: 'arg_set_id',
-                argName: fullKey,
-                op: `= ${sqliteString(displayValue)}`,
-              }],
-            },
+          addSqlTableTab({
+            table: SqlTables.slice,
+            filters: [{
+              type: 'arg_filter',
+              argSetIdColumn: 'arg_set_id',
+              argName: fullKey,
+              op: `= ${sqliteString(displayValue)}`,
+            }],
           });
         },
       }),
diff --git a/ui/src/frontend/slice_details.ts b/ui/src/frontend/slice_details.ts
index 282ecc8..c8c97b0 100644
--- a/ui/src/frontend/slice_details.ts
+++ b/ui/src/frontend/slice_details.ts
@@ -24,14 +24,13 @@
 import {SqlRef} from '../widgets/sql_ref';
 import {Tree, TreeNode} from '../widgets/tree';
 
-import {addTab} from './bottom_tab';
 import {globals} from './globals';
 import {SliceDetails} from './sql/slice';
 import {
   BreakdownByThreadState,
   BreakdownByThreadStateTreeNode,
 } from './sql/thread_state';
-import {SqlTableTab} from './sql_table/tab';
+import {addSqlTableTab} from './sql_table/tab';
 import {SqlTables} from './sql_table/well_known_tables';
 import {getProcessName, getThreadName} from './thread_and_process_info';
 import {DurationWidget} from './widgets/duration';
@@ -65,13 +64,10 @@
           m(MenuItem, {
             label: 'Slices with the same name',
             onclick: () => {
-              addTab({
-                kind: SqlTableTab.kind,
-                config: {
-                  table: SqlTables.slice,
-                  displayName: 'slice',
-                  filters: [`name = ${sqliteString(slice.name)}`],
-                },
+              addSqlTableTab({
+                table: SqlTables.slice,
+                displayName: 'slice',
+                filters: [`name = ${sqliteString(slice.name)}`],
               });
             },
           }),
diff --git a/ui/src/frontend/sql_table/tab.ts b/ui/src/frontend/sql_table/tab.ts
index bd704cd..109f398 100644
--- a/ui/src/frontend/sql_table/tab.ts
+++ b/ui/src/frontend/sql_table/tab.ts
@@ -21,16 +21,55 @@
 import {Button} from '../../widgets/button';
 import {DetailsShell} from '../../widgets/details_shell';
 import {Popup, PopupPosition} from '../../widgets/popup';
-import {BottomTab, bottomTabRegistry, NewBottomTabArgs} from '../bottom_tab';
+import {addTab, BottomTab, bottomTabRegistry, NewBottomTabArgs} from '../bottom_tab';
 
-import {SqlTableState} from './state';
+import {Filter, SqlTableState} from './state';
 import {SqlTable} from './table';
 import {SqlTableDescription, tableDisplayName} from './table_description';
+import {TABS_V2_FLAG} from '../../core/feature_flags';
+import {EngineProxy} from '../../public';
+import {globals} from '../globals';
+import {assertExists} from '../../base/logging';
+import {uuidv4} from '../../base/uuid';
+import {BottomTabToTabAdapter} from '../../public/utils';
+import {Actions} from '../../common/actions';
 
 interface SqlTableTabConfig {
   table: SqlTableDescription;
   displayName?: string;
-  filters?: string[];
+  filters?: Filter[];
+}
+
+export function addSqlTableTab(config: SqlTableTabConfig): void {
+  if (TABS_V2_FLAG.get()) {
+    const queryResultsTab = new SqlTableTab({
+      config,
+      engine: getEngine(),
+      uuid: uuidv4(),
+    });
+
+    const uri = 'sqlTable#' + uuidv4();
+
+    globals.tabManager.registerTab({
+      uri,
+      content: new BottomTabToTabAdapter(queryResultsTab),
+      isEphemeral: true,
+    });
+
+    globals.dispatch(Actions.showTab({uri}));
+  } else {
+    return addTab({
+      kind: SqlTableTab.kind,
+      config,
+    });
+  }
+}
+
+// TODO(stevegolton): Find a way to make this more elegant.
+function getEngine(): EngineProxy {
+  const engConfig = globals.getCurrentEngine();
+  const engineId = assertExists(engConfig).id;
+  return assertExists(globals.engines.get(engineId)).getProxy('QueryResult');
 }
 
 export class SqlTableTab extends BottomTab<SqlTableTabConfig> {
diff --git a/ui/src/frontend/tab_panel.ts b/ui/src/frontend/tab_panel.ts
index 46d4380..53ba2e7 100644
--- a/ui/src/frontend/tab_panel.ts
+++ b/ui/src/frontend/tab_panel.ts
@@ -21,7 +21,6 @@
 
 import {
   DragHandle,
-  getDetailsHeight,
   Tab,
   TabDropdownEntry,
 } from './drag_handle';
@@ -32,7 +31,8 @@
 }
 
 export class TabPanel implements m.ClassComponent {
-  private detailsHeight = getDetailsHeight();
+  // Tabs panel starts collapsed.
+  private detailsHeight = 0;
 
   view() {
     const tabMan = globals.tabManager;
@@ -67,10 +67,18 @@
     const tabDropdownEntries =
         globals.tabManager.tabs.filter((tab) => tab.isEphemeral === false)
           .map(({content, uri}): TabDropdownEntry => {
+            // Check if the tab is already open
+            const isOpen = globals.state.tabs.openTabs.find((openTabUri) => {
+              return openTabUri === uri;
+            });
+            const clickAction = isOpen ?
+              Actions.hideTab({uri}) :
+              Actions.showTab({uri});
             return {
               key: uri,
               title: content.getTitle(),
-              onClick: () => globals.dispatch(Actions.showTab({uri})),
+              onClick: () => globals.dispatch(clickAction),
+              checked: isOpen !== undefined,
             };
           });
 
@@ -104,12 +112,11 @@
     if (!exists(cs)) {
       return m(EmptyState, {
         className: 'pf-noselection',
-        header: 'No selection',
-        detail: 'Please select something',
-      });
+        title: 'Nothing selected',
+      }, 'Selection details will appear here');
     }
 
-    const sectionReg = globals.tabManager.currentSelectionSections;
+    const sectionReg = globals.tabManager.detailsPanels;
     const allSections = Array.from(sectionReg.values());
 
     // Get the first "truthy" current selection section
@@ -119,10 +126,9 @@
     if (!Boolean(section)) {
       return m(EmptyState, {
         className: 'pf-noselection',
-        header: 'No details available',
-        detail: `Selection kind: '${cs.kind}'`,
+        title: 'No details available',
         icon: 'warning',
-      });
+      }, `Selection kind: '${cs.kind}'`);
     } else {
       return section;
     }
diff --git a/ui/src/frontend/thread_state_tab.ts b/ui/src/frontend/thread_state_tab.ts
index 3d4047f..1c881ec 100644
--- a/ui/src/frontend/thread_state_tab.ts
+++ b/ui/src/frontend/thread_state_tab.ts
@@ -291,7 +291,7 @@
     ), m(Button,
       {
         label: 'Critical path lite',
-        onclick: () => runQuery(`INCLUDE PERFETTO MODULE experimental.thread_executing_span;`, this.engine)
+        onclick: () => runQuery(`INCLUDE PERFETTO MODULE sched.thread_executing_span;`, this.engine)
           .then(() => addDebugSliceTrack(
             this.engine,
             {
@@ -306,7 +306,7 @@
                       process.name AS process_name,
                       'thread_state' AS table_name
                     FROM
-                      experimental_thread_executing_span_critical_path(
+                      _thread_executing_span_critical_path(
                         ${this.state?.thread?.utid},
                         trace_bounds.start_ts,
                         trace_bounds.end_ts - trace_bounds.start_ts) cr,
@@ -323,7 +323,7 @@
     ), m(Button,
       {
         label: 'Critical path',
-        onclick: () => runQuery(`INCLUDE PERFETTO MODULE experimental.thread_executing_span;`, this.engine)
+        onclick: () => runQuery(`INCLUDE PERFETTO MODULE sched.thread_executing_span;`, this.engine)
           .then(() => addDebugSliceTrack(
             this.engine,
             {
@@ -331,7 +331,7 @@
                   `
                     SELECT cr.id, cr.utid, cr.ts, cr.dur, cr.name, cr.table_name
                       FROM
-                        experimental_thread_executing_span_critical_path_stack(
+                        _thread_executing_span_critical_path_stack(
                           ${this.state?.thread?.utid},
                           trace_bounds.start_ts,
                           trace_bounds.end_ts - trace_bounds.start_ts) cr,
diff --git a/ui/src/frontend/viewer_page.ts b/ui/src/frontend/viewer_page.ts
index 5f918af..b8ff6c6 100644
--- a/ui/src/frontend/viewer_page.ts
+++ b/ui/src/frontend/viewer_page.ts
@@ -19,7 +19,7 @@
 import {Time} from '../base/time';
 import {Actions} from '../common/actions';
 import {TrackCacheEntry} from '../common/track_cache';
-import {featureFlags} from '../core/feature_flags';
+import {TABS_V2_FLAG, featureFlags} from '../core/feature_flags';
 import {raf} from '../core/raf_scheduler';
 import {TrackTags} from '../public';
 
@@ -47,13 +47,6 @@
   defaultValue: true,
 });
 
-const TABS_V2 = featureFlags.register({
-  id: 'tabsv2',
-  name: 'Tabs V2',
-  description: 'Use Tabs V2',
-  defaultValue: false,
-});
-
 // Checks if the mousePos is within 3px of the start or end of the
 // current selected time range.
 function onTimeRangeBoundary(mousePos: number): 'START'|'END'|null {
@@ -353,7 +346,7 @@
   }
 
   private renderTabPanel() {
-    if (TABS_V2.get()) {
+    if (TABS_V2_FLAG.get()) {
       return m(TabPanel);
     } else {
       return m(DetailsPanel);
diff --git a/ui/src/frontend/widgets_page.ts b/ui/src/frontend/widgets_page.ts
index 1244612..a148856 100644
--- a/ui/src/frontend/widgets_page.ts
+++ b/ui/src/frontend/widgets_page.ts
@@ -555,16 +555,14 @@
       }),
       m(WidgetShowcase, {
         label: 'Empty State',
-        renderWidget: ({header, content, detail}) =>
+        renderWidget: ({header, content}) =>
           m(EmptyState,
             {
-              header: header && 'No search results found...',
-              detail: detail && 'Please try a different search query',
+              title: header && 'No search results found...',
             },
             content && m(Button, {label: 'Try again'})),
         initialOpts: {
           header: true,
-          detail: true,
           content: true,
         },
       }),
diff --git a/ui/src/plugins/dev.perfetto.AndroidLongBatteryTracing/index.ts b/ui/src/plugins/dev.perfetto.AndroidLongBatteryTracing/index.ts
index 9625bb1..9a37b09 100644
--- a/ui/src/plugins/dev.perfetto.AndroidLongBatteryTracing/index.ts
+++ b/ui/src/plugins/dev.perfetto.AndroidLongBatteryTracing/index.ts
@@ -215,8 +215,6 @@
   USING SPAN_JOIN(RilSignalStrength PARTITIONED track_id, ScreenOn)`;
 
 const MODEM_RIL_CHANNELS_PREAMBLE = `
-  SELECT IMPORT('android.battery_stats');
-
   CREATE OR REPLACE PERFETTO FUNCTION EXTRACT_KEY_VALUE(source STRING, key_name STRING) RETURNS STRING AS
   SELECT SUBSTR(trimmed, INSTR(trimmed, "=")+1, INSTR(trimmed, ",") - INSTR(trimmed, "=") - 1)
   FROM (SELECT SUBSTR($source, INSTR($source, $key_name)) AS trimmed);`;
@@ -932,17 +930,21 @@
     return action;
   }
 
-  async addBatteryStatsEvents(e: EngineProxy, groupId: string):
-      Promise<DeferredAction<{}>[]> {
+  async addBatteryStatsEvents(
+    e: EngineProxy, features: Set<string>,
+    groupId: string): Promise<DeferredAction<{}>[]> {
+    if (!features.has('track.battery_stats')) {
+      return [];
+    }
+
     const query = (name: string, track: string): Promise<DeferredAction<{}>> =>
       this.addSliceTrack(
-        e,
-        name,
-        `SELECT ts, dur, str_value AS name
+        e, name, `SELECT ts, dur, str_value AS name
             FROM android_battery_stats_event_slices
             WHERE track_name = "${track}"`,
         groupId);
 
+    await e.query(`SELECT IMPORT('android.battery_stats');`);
     return flatten([
       query('Top App', 'battery_stats.top'),
       this.addSliceTrack(
@@ -1205,13 +1207,13 @@
     ]);
   }
 
-  findGroupId(name: string) {
+  findGroupId(name: string): string|undefined {
     for (const group of Object.values(globals.state.trackGroups)) {
       if (group.name === name) {
         return group.id;
       }
     }
-    throw new Error(`No group ${name} found`);
+    return undefined;
   }
 
   addGroup(groupName: string):
@@ -1268,6 +1270,10 @@
       select distinct 'track.' || lower(name) as feature
       from track where name in ('RIL', 'suspend_backoff')`);
 
+    await addFeatures(`
+      select distinct 'track.battery_stats' as feature
+      from track where name like 'battery_stats.%'`);
+
     return features;
   }
 
@@ -1276,14 +1282,16 @@
     const features: Set<string> = await this.findFeatures(ctx.engine);
 
     const miscGroupId = this.findGroupId('Misc Global Tracks');
-
-    if (features.has('atom.thermal_throttling_severity_state_changed')) {
-      actions.push(this.addSliceTrack(
-        ctx.engine, 'Thermal throttling', THERMAL_THROTTLING, miscGroupId));
+    if (miscGroupId) {
+      if (features.has('atom.thermal_throttling_severity_state_changed')) {
+        actions.push(this.addSliceTrack(
+          ctx.engine, 'Thermal throttling', THERMAL_THROTTLING, miscGroupId));
+      }
+      actions.push(
+        this.addBatteryStatsEvents(ctx.engine, features, miscGroupId));
     }
 
     actions.push(
-      this.addBatteryStatsEvents(ctx.engine, miscGroupId),
       this.addNetworkSummary(ctx.engine, features),
       this.addModemDetail(ctx.engine, features),
       this.addKernelWakelocks(ctx.engine, features),
diff --git a/ui/src/public/index.ts b/ui/src/public/index.ts
index beafacb..e87447a 100644
--- a/ui/src/public/index.ts
+++ b/ui/src/public/index.ts
@@ -327,7 +327,7 @@
   onShow?(): void;
 }
 
-export interface CurrentSelectionSection {
+export interface DetailsPanel {
   render(selection: Selection): m.Children;
 }
 
@@ -402,8 +402,9 @@
   // is deactivated or when the trace is unloaded.
   registerTab(tab: TabDescriptor): void;
 
-  // Register a current selection handler.
-  registerCurrentSelectionSection(sel: CurrentSelectionSection): void;
+  // Register a hook into the current selection tab rendering logic that allows
+  // customization of the current selection tab content.
+  registerDetailsPanel(sel: DetailsPanel): void;
 
   // Create a store mounted over the top of this plugin's persistent state.
   mountStore<T>(migrate: Migrate<T>): Store<T>;
diff --git a/ui/src/public/utils.ts b/ui/src/public/utils.ts
index 028c3a0..cb3d814 100644
--- a/ui/src/public/utils.ts
+++ b/ui/src/public/utils.ts
@@ -17,7 +17,7 @@
 import {Selection} from '../common/state';
 import {BottomTab} from '../frontend/bottom_tab';
 
-import {CurrentSelectionSection, Tab} from '.';
+import {DetailsPanel, Tab} from '.';
 
 export function getTrackName(args: Partial<{
   name: string | null,
@@ -127,7 +127,7 @@
       },
     })
  */
-export class BottomTabToSCSAdapter implements CurrentSelectionSection {
+export class BottomTabToSCSAdapter implements DetailsPanel {
   private oldSelection?: Selection;
   private bottomTab?: BottomTab;
   private attrs: BottomTabAdapterAttrs;
diff --git a/ui/src/tracks/android_log/index.ts b/ui/src/tracks/android_log/index.ts
index 28e2fe8..860890d 100644
--- a/ui/src/tracks/android_log/index.ts
+++ b/ui/src/tracks/android_log/index.ts
@@ -12,11 +12,14 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+import m from 'mithril';
+
 import {duration, Time, time} from '../../base/time';
 import {LIMIT, TrackData} from '../../common/track_data';
 import {TimelineFetcher} from '../../common/track_helper';
 import {checkerboardExcept} from '../../frontend/checkerboard';
 import {globals} from '../../frontend/globals';
+import {LogPanel} from '../../frontend/logs_panel';
 import {PanelSize} from '../../frontend/panel';
 import {
   EngineProxy,
@@ -158,6 +161,16 @@
         track: () => new AndroidLogTrack(ctx.engine),
       });
     }
+
+    // Eternal tabs should always be available even if there is nothing to show
+    ctx.registerTab({
+      isEphemeral: false,
+      uri: 'android_logs',
+      content: {
+        render: () => m(LogPanel),
+        getTitle: () => 'Android Logs',
+      },
+    });
   }
 }
 
diff --git a/ui/src/tracks/chrome_critical_user_interactions/index.ts b/ui/src/tracks/chrome_critical_user_interactions/index.ts
index 29c16ca..1357d5c 100644
--- a/ui/src/tracks/chrome_critical_user_interactions/index.ts
+++ b/ui/src/tracks/chrome_critical_user_interactions/index.ts
@@ -17,13 +17,17 @@
 import {Actions} from '../../common/actions';
 import {SCROLLING_TRACK_GROUP} from '../../common/state';
 import {OnSliceClickArgs} from '../../frontend/base_slice_track';
-import {GenericSliceDetailsTab} from '../../frontend/generic_slice_details_tab';
+import {
+  GenericSliceDetailsTab,
+  GenericSliceDetailsTabConfig,
+} from '../../frontend/generic_slice_details_tab';
 import {globals} from '../../frontend/globals';
 import {
   NAMED_ROW,
   NamedSliceTrackTypes,
 } from '../../frontend/named_slice_track';
 import {
+  BottomTabToSCSAdapter,
   NUM,
   Plugin,
   PluginContext,
@@ -212,6 +216,52 @@
       track: (trackCtx) => new CriticalUserInteractionTrack(
         {engine: ctx.engine, trackKey: trackCtx.trackKey}),
     });
+
+    ctx.registerDetailsPanel(new BottomTabToSCSAdapter({
+      tabFactory: (selection) => {
+        if (selection.kind === 'GENERIC_SLICE' &&
+            selection.detailsPanelConfig.kind === PageLoadDetailsPanel.kind) {
+          const config = selection.detailsPanelConfig.config;
+          return new PageLoadDetailsPanel({
+            config: config as GenericSliceDetailsTabConfig,
+            engine: ctx.engine,
+            uuid: uuidv4(),
+          });
+        }
+        return undefined;
+      },
+    }));
+
+    ctx.registerDetailsPanel(new BottomTabToSCSAdapter({
+      tabFactory: (selection) => {
+        if (selection.kind === 'GENERIC_SLICE' &&
+            selection.detailsPanelConfig.kind === StartupDetailsPanel.kind) {
+          const config = selection.detailsPanelConfig.config;
+          return new StartupDetailsPanel({
+            config: config as GenericSliceDetailsTabConfig,
+            engine: ctx.engine,
+            uuid: uuidv4(),
+          });
+        }
+        return undefined;
+      },
+    }));
+
+    ctx.registerDetailsPanel(new BottomTabToSCSAdapter({
+      tabFactory: (selection) => {
+        if (selection.kind === 'GENERIC_SLICE' &&
+            selection.detailsPanelConfig.kind ===
+                WebContentInteractionPanel.kind) {
+          const config = selection.detailsPanelConfig.config;
+          return new WebContentInteractionPanel({
+            config: config as GenericSliceDetailsTabConfig,
+            engine: ctx.engine,
+            uuid: uuidv4(),
+          });
+        }
+        return undefined;
+      },
+    }));
   }
 
   onActivate(ctx: PluginContext): void {
diff --git a/ui/src/tracks/chrome_scroll_jank/index.ts b/ui/src/tracks/chrome_scroll_jank/index.ts
index 38d41dd..9c8f2c3 100644
--- a/ui/src/tracks/chrome_scroll_jank/index.ts
+++ b/ui/src/tracks/chrome_scroll_jank/index.ts
@@ -21,6 +21,10 @@
 import {ObjectByKey} from '../../common/state';
 import {featureFlags} from '../../core/feature_flags';
 import {
+  GenericSliceDetailsTabConfig,
+} from '../../frontend/generic_slice_details_tab';
+import {
+  BottomTabToSCSAdapter,
   NUM,
   Plugin,
   PluginContext,
@@ -33,12 +37,15 @@
 import {NULL_TRACK_URI} from '../null_track';
 
 import {ChromeTasksScrollJankTrack} from './chrome_tasks_scroll_jank_track';
+import {EventLatencySliceDetailsPanel} from './event_latency_details_panel';
 import {
   addLatencyTracks,
   EventLatencyTrack,
   JANKY_LATENCY_NAME,
 } from './event_latency_track';
+import {ScrollDetailsPanel} from './scroll_details_panel';
 import {ScrollJankCauseMap} from './scroll_jank_cause_map';
+import {ScrollJankV3DetailsPanel} from './scroll_jank_v3_details_panel';
 import {
   addScrollJankV3ScrollTrack,
   ScrollJankV3Track,
@@ -227,6 +234,21 @@
         });
       },
     });
+
+    ctx.registerDetailsPanel(new BottomTabToSCSAdapter({
+      tabFactory: (selection) => {
+        if (selection.kind === 'GENERIC_SLICE' &&
+            selection.detailsPanelConfig.kind === ScrollDetailsPanel.kind) {
+          const config = selection.detailsPanelConfig.config;
+          return new ScrollDetailsPanel({
+            config: config as GenericSliceDetailsTabConfig,
+            engine: ctx.engine,
+            uuid: uuidv4(),
+          });
+        }
+        return undefined;
+      },
+    }));
   }
 
   private async addEventLatencyTrack(ctx: PluginContextTrace): Promise<void> {
@@ -307,6 +329,22 @@
         return new EventLatencyTrack({engine: ctx.engine, trackKey}, baseTable);
       },
     });
+
+    ctx.registerDetailsPanel(new BottomTabToSCSAdapter({
+      tabFactory: (selection) => {
+        if (selection.kind === 'GENERIC_SLICE' &&
+            selection.detailsPanelConfig.kind ===
+                EventLatencySliceDetailsPanel.kind) {
+          const config = selection.detailsPanelConfig.config;
+          return new EventLatencySliceDetailsPanel({
+            config: config as GenericSliceDetailsTabConfig,
+            engine: ctx.engine,
+            uuid: uuidv4(),
+          });
+        }
+        return undefined;
+      },
+    }));
   }
 
   private async addScrollJankV3ScrollTrack(ctx: PluginContextTrace):
@@ -325,6 +363,22 @@
         });
       },
     });
+
+    ctx.registerDetailsPanel(new BottomTabToSCSAdapter({
+      tabFactory: (selection) => {
+        if (selection.kind === 'GENERIC_SLICE' &&
+            selection.detailsPanelConfig.kind ===
+                ScrollJankV3DetailsPanel.kind) {
+          const config = selection.detailsPanelConfig.config;
+          return new ScrollJankV3DetailsPanel({
+            config: config as GenericSliceDetailsTabConfig,
+            engine: ctx.engine,
+            uuid: uuidv4(),
+          });
+        }
+        return undefined;
+      },
+    }));
   }
 }
 
diff --git a/ui/src/tracks/chrome_slices/index.ts b/ui/src/tracks/chrome_slices/index.ts
index f232352..998ebfd 100644
--- a/ui/src/tracks/chrome_slices/index.ts
+++ b/ui/src/tracks/chrome_slices/index.ts
@@ -15,6 +15,8 @@
 import {BigintMath as BIMath} from '../../base/bigint_math';
 import {clamp} from '../../base/math_utils';
 import {Duration, duration, time} from '../../base/time';
+import {uuidv4} from '../../base/uuid';
+import {ChromeSliceDetailsTab} from '../../frontend/chrome_slice_details_tab';
 import {
   NAMED_ROW,
   NamedSliceTrack,
@@ -27,6 +29,7 @@
 } from '../../frontend/slice_track';
 import {NewTrackArgs} from '../../frontend/track';
 import {
+  BottomTabToSCSAdapter,
   EngineProxy,
   Plugin,
   PluginContext,
@@ -292,6 +295,22 @@
         },
       });
     }
+
+    ctx.registerDetailsPanel(new BottomTabToSCSAdapter({
+      tabFactory: (sel) => {
+        if (sel.kind !== 'CHROME_SLICE') {
+          return undefined;
+        }
+        return new ChromeSliceDetailsTab({
+          config: {
+            table: sel.table ?? 'slice',
+            id: sel.id,
+          },
+          engine: ctx.engine,
+          uuid: uuidv4(),
+        });
+      },
+    }));
   }
 }
 
diff --git a/ui/src/tracks/counter/index.ts b/ui/src/tracks/counter/index.ts
index 4ac8a37..144ece1 100644
--- a/ui/src/tracks/counter/index.ts
+++ b/ui/src/tracks/counter/index.ts
@@ -28,6 +28,7 @@
   TimelineFetcher,
 } from '../../common/track_helper';
 import {checkerboardExcept} from '../../frontend/checkerboard';
+import {CounterDetailsPanel} from '../../frontend/counter_panel';
 import {globals} from '../../frontend/globals';
 import {PanelSize} from '../../frontend/panel';
 import {
@@ -630,6 +631,16 @@
     await this.addCpuPerfCounterTracks(ctx);
     await this.addThreadCounterTracks(ctx);
     await this.addProcessCounterTracks(ctx);
+
+    ctx.registerDetailsPanel({
+      render: (sel) => {
+        if (sel.kind === 'COUNTER') {
+          return m(CounterDetailsPanel);
+        } else {
+          return undefined;
+        }
+      },
+    });
   }
 
   private async addCounterTracks(ctx: PluginContextTrace) {
diff --git a/ui/src/tracks/cpu_profile/index.ts b/ui/src/tracks/cpu_profile/index.ts
index 3c7b2f0..29f703b 100644
--- a/ui/src/tracks/cpu_profile/index.ts
+++ b/ui/src/tracks/cpu_profile/index.ts
@@ -19,6 +19,7 @@
 import {colorForSample} from '../../common/colorizer';
 import {TrackData} from '../../common/track_data';
 import {TimelineFetcher} from '../../common/track_helper';
+import {CpuProfileDetailsPanel} from '../../frontend/cpu_profile_panel';
 import {globals} from '../../frontend/globals';
 import {PanelSize} from '../../frontend/panel';
 import {TimeScale} from '../../frontend/time_scale';
@@ -283,6 +284,16 @@
         track: () => new CpuProfileTrack(ctx.engine, utid),
       });
     }
+
+    ctx.registerDetailsPanel({
+      render: (sel) => {
+        if (sel.kind === 'CPU_PROFILE_SAMPLE') {
+          return m(CpuProfileDetailsPanel);
+        } else {
+          return undefined;
+        }
+      },
+    });
   }
 }
 
diff --git a/ui/src/tracks/cpu_slices/index.ts b/ui/src/tracks/cpu_slices/index.ts
index 0596894..149d014 100644
--- a/ui/src/tracks/cpu_slices/index.ts
+++ b/ui/src/tracks/cpu_slices/index.ts
@@ -33,6 +33,7 @@
 import {checkerboardExcept} from '../../frontend/checkerboard';
 import {globals} from '../../frontend/globals';
 import {PanelSize} from '../../frontend/panel';
+import {SliceDetailsPanel} from '../../frontend/slice_details_panel';
 import {
   EngineProxy,
   Plugin,
@@ -509,6 +510,14 @@
         track: ({trackKey}) => new CpuSliceTrack(ctx.engine, trackKey, cpu),
       });
     }
+
+    ctx.registerDetailsPanel({
+      render: (sel) => {
+        if (sel.kind === 'SLICE') {
+          return m(SliceDetailsPanel);
+        }
+      },
+    });
   }
 
   async guessCpuSizes(engine: EngineProxy): Promise<Map<number, string>> {
diff --git a/ui/src/tracks/debug/index.ts b/ui/src/tracks/debug/index.ts
index 089c69b..7beeb7a 100644
--- a/ui/src/tracks/debug/index.ts
+++ b/ui/src/tracks/debug/index.ts
@@ -13,7 +13,9 @@
 // limitations under the License.
 
 import {DEBUG_SLICE_TRACK_URI} from '../../frontend/debug_tracks';
+import {uuidv4} from '../../base/uuid';
 import {
+  BottomTabToSCSAdapter,
   Plugin,
   PluginContext,
   PluginContextTrace,
@@ -21,7 +23,9 @@
 } from '../../public';
 
 import {DebugCounterTrack} from './counter_track';
+import {DebugSliceDetailsTab} from './details_tab';
 import {DebugTrackV2} from './slice_track';
+import {GenericSliceDetailsTabConfig} from '../../frontend/generic_slice_details_tab';
 
 export const DEBUG_COUNTER_TRACK_URI = 'perfetto.DebugCounter';
 
@@ -33,6 +37,22 @@
       uri: DEBUG_SLICE_TRACK_URI,
       track: (trackCtx) => new DebugTrackV2(ctx.engine, trackCtx),
     });
+
+    ctx.registerDetailsPanel(new BottomTabToSCSAdapter({
+      tabFactory: (selection) => {
+        if (selection.kind === 'GENERIC_SLICE' &&
+            selection.detailsPanelConfig.kind === DebugSliceDetailsTab.kind) {
+          const config = selection.detailsPanelConfig.config;
+          return new DebugSliceDetailsTab({
+            config: config as GenericSliceDetailsTabConfig,
+            engine: ctx.engine,
+            uuid: uuidv4(),
+          });
+        }
+        return undefined;
+      },
+    }));
+
     ctx.registerTrack({
       uri: DEBUG_COUNTER_TRACK_URI,
       track: (trackCtx) => new DebugCounterTrack(ctx.engine, trackCtx),
diff --git a/ui/src/tracks/flows/index.ts b/ui/src/tracks/flows/index.ts
new file mode 100644
index 0000000..523b854
--- /dev/null
+++ b/ui/src/tracks/flows/index.ts
@@ -0,0 +1,52 @@
+// Copyright (C) 2024 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+import {
+  FlowEventsAreaSelectedPanel,
+  FlowEventsPanel,
+} from '../../frontend/flow_events_panel';
+import {globals} from '../../frontend/globals';
+import {
+  Plugin,
+  PluginContext,
+  PluginContextTrace,
+  PluginDescriptor,
+} from '../../public';
+
+class FlowsPlugin implements Plugin {
+  onActivate(_ctx: PluginContext): void {}
+
+  async onTraceLoad(ctx: PluginContextTrace): Promise<void> {
+    ctx.registerTab({
+      isEphemeral: false,
+      uri: 'perfetto.Flows#FlowEvents',
+      content: {
+        render: () => {
+          const selection = globals.state.currentSelection;
+          if (selection?.kind === 'AREA') {
+            return m(FlowEventsAreaSelectedPanel);
+          } else {
+            return m(FlowEventsPanel);
+          }
+        },
+        getTitle: () => 'Flow Events',
+      },
+    });
+  }
+}
+
+export const plugin: PluginDescriptor = {
+  pluginId: 'perfetto.Flows',
+  plugin: FlowsPlugin,
+};
diff --git a/ui/src/tracks/ftrace/index.ts b/ui/src/tracks/ftrace/index.ts
index dd1a2b7..eb5c548 100644
--- a/ui/src/tracks/ftrace/index.ts
+++ b/ui/src/tracks/ftrace/index.ts
@@ -12,11 +12,14 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+import m from 'mithril';
+
 import {duration, Time, time} from '../../base/time';
 import {colorForFtrace} from '../../common/colorizer';
 import {LIMIT, TrackData} from '../../common/track_data';
 import {TimelineFetcher} from '../../common/track_helper';
 import {checkerboardExcept} from '../../frontend/checkerboard';
+import {FtracePanel} from '../../frontend/ftrace_panel';
 import {globals} from '../../frontend/globals';
 import {PanelSize} from '../../frontend/panel';
 import {
@@ -150,6 +153,15 @@
         },
       });
     }
+
+    ctx.registerTab({
+      uri: 'perfetto.FtraceRaw#FtraceEventsTab',
+      isEphemeral: false,
+      content: {
+        render: () => m(FtracePanel),
+        getTitle: () => 'Ftrace Events',
+      },
+    });
   }
 
   private async lookupCpuCores(engine: EngineProxy): Promise<number[]> {
diff --git a/ui/src/tracks/heap_profile/index.ts b/ui/src/tracks/heap_profile/index.ts
index 684404d..50c458b 100644
--- a/ui/src/tracks/heap_profile/index.ts
+++ b/ui/src/tracks/heap_profile/index.ts
@@ -22,6 +22,7 @@
   OnSliceClickArgs,
   OnSliceOverArgs,
 } from '../../frontend/base_slice_track';
+import {FlamegraphDetailsPanel} from '../../frontend/flamegraph_panel';
 import {globals} from '../../frontend/globals';
 import {NewTrackArgs} from '../../frontend/track';
 import {
@@ -116,10 +117,10 @@
   onActivate(_ctx: PluginContext): void {}
   async onTraceLoad(ctx: PluginContextTrace): Promise<void> {
     const result = await ctx.engine.query(`
-    select distinct(upid) from heap_profile_allocation
-    union
-    select distinct(upid) from heap_graph_object
-  `);
+      select distinct(upid) from heap_profile_allocation
+      union
+      select distinct(upid) from heap_graph_object
+    `);
     for (const it = result.iter({upid: NUM}); it.valid(); it.next()) {
       const upid = it.upid;
       ctx.registerTrack({
@@ -137,6 +138,16 @@
         },
       });
     }
+
+    ctx.registerDetailsPanel({
+      render: (sel) => {
+        if (sel.kind === 'HEAP_PROFILE') {
+          return m(FlamegraphDetailsPanel);
+        } else {
+          return undefined;
+        }
+      },
+    });
   }
 }
 
diff --git a/ui/src/tracks/perf_samples_profile/index.ts b/ui/src/tracks/perf_samples_profile/index.ts
index 05ed875..a4b57e5 100644
--- a/ui/src/tracks/perf_samples_profile/index.ts
+++ b/ui/src/tracks/perf_samples_profile/index.ts
@@ -19,6 +19,7 @@
 import {TrackData} from '../../common/track_data';
 import {TimelineFetcher} from '../../common/track_helper';
 import {FLAMEGRAPH_HOVERED_COLOR} from '../../frontend/flamegraph';
+import {FlamegraphDetailsPanel} from '../../frontend/flamegraph_panel';
 import {globals} from '../../frontend/globals';
 import {PanelSize} from '../../frontend/panel';
 import {TimeScale} from '../../frontend/time_scale';
@@ -223,7 +224,7 @@
       select distinct upid, pid
       from perf_sample join thread using (utid) join process using (upid)
       where callsite_id is not null
-  `);
+    `);
     for (const it = result.iter({upid: NUM, pid: NUM}); it.valid(); it.next()) {
       const upid = it.upid;
       const pid = it.pid;
@@ -235,6 +236,16 @@
         track: () => new PerfSamplesProfileTrack(ctx.engine, upid),
       });
     }
+
+    ctx.registerDetailsPanel({
+      render: (sel) => {
+        if (sel.kind === 'PERF_SAMPLES') {
+          return m(FlamegraphDetailsPanel);
+        } else {
+          return undefined;
+        }
+      },
+    });
   }
 }
 
diff --git a/ui/src/tracks/pivot_table/index.ts b/ui/src/tracks/pivot_table/index.ts
new file mode 100644
index 0000000..e9d14cd
--- /dev/null
+++ b/ui/src/tracks/pivot_table/index.ts
@@ -0,0 +1,48 @@
+// Copyright (C) 2024 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+import {PIVOT_TABLE_REDUX_FLAG} from '../../controller/pivot_table_controller';
+import {globals} from '../../frontend/globals';
+import {PivotTable} from '../../frontend/pivot_table';
+import {
+  Plugin,
+  PluginContext,
+  PluginContextTrace,
+  PluginDescriptor,
+} from '../../public';
+
+class PivotTablePlugin implements Plugin {
+  onActivate(_ctx: PluginContext): void {}
+
+  async onTraceLoad(ctx: PluginContextTrace): Promise<void> {
+    if (PIVOT_TABLE_REDUX_FLAG.get()) {
+      ctx.registerTab({
+        isEphemeral: false,
+        uri: 'perfetto.PivotTable#PivotTable',
+        content: {
+          render: () => m(PivotTable, {
+            selectionArea:
+                globals.state.nonSerializableState.pivotTable.selectionArea,
+          }),
+          getTitle: () => 'Pivot Table',
+        },
+      });
+    }
+  }
+}
+
+export const plugin: PluginDescriptor = {
+  pluginId: 'perfetto.PivotTable',
+  plugin: PivotTablePlugin,
+};
diff --git a/ui/src/tracks/screenshots/index.ts b/ui/src/tracks/screenshots/index.ts
index 254dadb..fc2c6da 100644
--- a/ui/src/tracks/screenshots/index.ts
+++ b/ui/src/tracks/screenshots/index.ts
@@ -12,11 +12,16 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+import {uuidv4} from '../../base/uuid';
 import {AddTrackArgs} from '../../common/actions';
 import {
+  GenericSliceDetailsTabConfig,
+} from '../../frontend/generic_slice_details_tab';
+import {
   NamedSliceTrackTypes,
 } from '../../frontend/named_slice_track';
 import {
+  BottomTabToSCSAdapter,
   NUM,
   Plugin,
   PluginContext,
@@ -106,6 +111,21 @@
           });
         },
       });
+
+      ctx.registerDetailsPanel(new BottomTabToSCSAdapter({
+        tabFactory: (selection) => {
+          if (selection.kind === 'GENERIC_SLICE' &&
+              selection.detailsPanelConfig.kind === ScreenshotTab.kind) {
+            const config = selection.detailsPanelConfig.config;
+            return new ScreenshotTab({
+              config: config as GenericSliceDetailsTabConfig,
+              engine: ctx.engine,
+              uuid: uuidv4(),
+            });
+          }
+          return undefined;
+        },
+      }));
     }
   }
 }
diff --git a/ui/src/tracks/thread_state/index.ts b/ui/src/tracks/thread_state/index.ts
index 62ef1fe..7d3f1f0 100644
--- a/ui/src/tracks/thread_state/index.ts
+++ b/ui/src/tracks/thread_state/index.ts
@@ -27,7 +27,10 @@
 import {checkerboardExcept} from '../../frontend/checkerboard';
 import {globals} from '../../frontend/globals';
 import {PanelSize} from '../../frontend/panel';
+import {asThreadStateSqlId} from '../../frontend/sql_types';
+import {ThreadStateTab} from '../../frontend/thread_state_tab';
 import {
+  BottomTabToSCSAdapter,
   EngineProxy,
   Plugin,
   PluginContext,
@@ -365,6 +368,21 @@
         },
       });
     }
+
+    ctx.registerDetailsPanel(new BottomTabToSCSAdapter({
+      tabFactory: (sel) => {
+        if (sel.kind !== 'THREAD_STATE') {
+          return undefined;
+        }
+        return new ThreadStateTab({
+          config: {
+            id: asThreadStateSqlId(sel.id),
+          },
+          engine: ctx.engine,
+          uuid: uuidv4(),
+        });
+      },
+    }));
   }
 }
 
diff --git a/ui/src/widgets/empty_state.ts b/ui/src/widgets/empty_state.ts
index ce64242..abcf38f 100644
--- a/ui/src/widgets/empty_state.ts
+++ b/ui/src/widgets/empty_state.ts
@@ -18,9 +18,11 @@
   // Which material icon to show.
   // Defaults to 'search'.
   icon?: string;
+
   // Some text to show under the icon. No text shown if omitted.
-  header?: string;
-  detail?: string;
+  title?: string;
+
+  // Additional class name applied to our container.
   className?: string;
 }
 
@@ -32,20 +34,15 @@
   view({attrs, children}: m.Vnode<EmptyStateAttrs, this>): void|m.Children {
     const {
       icon = 'search',  // Icon defaults to the search symbol
-      header,
-      detail,
+      title,
       className,
     } = attrs;
     return m(
       '.pf-empty-state',
       {className},
       m('i.material-icons', icon),
-      m(
-        '.pf-empty-state-header',
-        header && m('.pf-empty-state-title', header),
-        detail && m('.pf-empty-state-detail', detail),
-      ),
-      m('div.pf-empty-state-content', children),
+      title && m('.pf-empty-state-title', title),
+      m('.pf-empty-state-content', children),
     );
   }
 }
diff --git a/ui/src/widgets/multiselect.ts b/ui/src/widgets/multiselect.ts
index bb2e782..b839563 100644
--- a/ui/src/widgets/multiselect.ts
+++ b/ui/src/widgets/multiselect.ts
@@ -91,7 +91,7 @@
 
     if (options.length === 0) {
       return m(EmptyState, {
-        header: `No results for '${this.searchText}'`,
+        title: `No results for '${this.searchText}'`,
       });
     } else {
       return [m(