• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2019 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include "src/trace_processor/importers/ftrace/ftrace_parser.h"
18 
19 #include "perfetto/base/logging.h"
20 #include "perfetto/protozero/proto_decoder.h"
21 #include "src/trace_processor/importers/common/args_tracker.h"
22 #include "src/trace_processor/importers/common/process_tracker.h"
23 #include "src/trace_processor/importers/ftrace/binder_tracker.h"
24 #include "src/trace_processor/importers/proto/async_track_set_tracker.h"
25 #include "src/trace_processor/importers/syscalls/syscall_tracker.h"
26 #include "src/trace_processor/importers/systrace/systrace_parser.h"
27 #include "src/trace_processor/storage/stats.h"
28 #include "src/trace_processor/storage/trace_storage.h"
29 #include "src/trace_processor/types/softirq_action.h"
30 
31 #include "protos/perfetto/common/gpu_counter_descriptor.pbzero.h"
32 #include "protos/perfetto/trace/ftrace/binder.pbzero.h"
33 #include "protos/perfetto/trace/ftrace/cpuhp.pbzero.h"
34 #include "protos/perfetto/trace/ftrace/dmabuf_heap.pbzero.h"
35 #include "protos/perfetto/trace/ftrace/dpu.pbzero.h"
36 #include "protos/perfetto/trace/ftrace/fastrpc.pbzero.h"
37 #include "protos/perfetto/trace/ftrace/ftrace.pbzero.h"
38 #include "protos/perfetto/trace/ftrace/ftrace_event.pbzero.h"
39 #include "protos/perfetto/trace/ftrace/ftrace_stats.pbzero.h"
40 #include "protos/perfetto/trace/ftrace/g2d.pbzero.h"
41 #include "protos/perfetto/trace/ftrace/generic.pbzero.h"
42 #include "protos/perfetto/trace/ftrace/gpu_mem.pbzero.h"
43 #include "protos/perfetto/trace/ftrace/ion.pbzero.h"
44 #include "protos/perfetto/trace/ftrace/irq.pbzero.h"
45 #include "protos/perfetto/trace/ftrace/kmem.pbzero.h"
46 #include "protos/perfetto/trace/ftrace/lowmemorykiller.pbzero.h"
47 #include "protos/perfetto/trace/ftrace/mali.pbzero.h"
48 #include "protos/perfetto/trace/ftrace/mm_event.pbzero.h"
49 #include "protos/perfetto/trace/ftrace/oom.pbzero.h"
50 #include "protos/perfetto/trace/ftrace/power.pbzero.h"
51 #include "protos/perfetto/trace/ftrace/raw_syscalls.pbzero.h"
52 #include "protos/perfetto/trace/ftrace/sched.pbzero.h"
53 #include "protos/perfetto/trace/ftrace/scm.pbzero.h"
54 #include "protos/perfetto/trace/ftrace/sde.pbzero.h"
55 #include "protos/perfetto/trace/ftrace/signal.pbzero.h"
56 #include "protos/perfetto/trace/ftrace/systrace.pbzero.h"
57 #include "protos/perfetto/trace/ftrace/task.pbzero.h"
58 #include "protos/perfetto/trace/ftrace/thermal.pbzero.h"
59 #include "protos/perfetto/trace/ftrace/workqueue.pbzero.h"
60 #include "protos/perfetto/trace/interned_data/interned_data.pbzero.h"
61 
62 namespace perfetto {
63 namespace trace_processor {
64 
65 namespace {
66 
67 using protozero::ConstBytes;
68 using protozero::ProtoDecoder;
69 
70 // kthreadd is the parent process for all kernel threads and always has
71 // pid == 2 on Linux and Android.
72 const uint32_t kKthreaddPid = 2;
73 const char kKthreaddName[] = "kthreadd";
74 
75 struct FtraceEventAndFieldId {
76   uint32_t event_id;
77   uint32_t field_id;
78 };
79 
80 // Contains a list of all the proto fields in ftrace events which represent
81 // kernel functions. This list is used to convert the iids in these fields to
82 // proper kernel symbols.
83 // TODO(lalitm): going through this array is O(n) on a hot-path (see
84 // ParseTypedFtraceToRaw). Consider changing this if we end up adding a lot of
85 // events here.
86 constexpr auto kKernelFunctionFields = std::array<FtraceEventAndFieldId, 3>{
87     {FtraceEventAndFieldId{
88          protos::pbzero::FtraceEvent::kSchedBlockedReasonFieldNumber,
89          protos::pbzero::SchedBlockedReasonFtraceEvent::kCallerFieldNumber},
90      FtraceEventAndFieldId{
91          protos::pbzero::FtraceEvent::kWorkqueueExecuteStartFieldNumber,
92          protos::pbzero::WorkqueueExecuteStartFtraceEvent::
93              kFunctionFieldNumber},
94      FtraceEventAndFieldId{
95          protos::pbzero::FtraceEvent::kWorkqueueQueueWorkFieldNumber,
96          protos::pbzero::WorkqueueQueueWorkFtraceEvent::kFunctionFieldNumber}}};
97 
98 }  // namespace
99 
FtraceParser(TraceProcessorContext * context)100 FtraceParser::FtraceParser(TraceProcessorContext* context)
101     : context_(context),
102       rss_stat_tracker_(context),
103       sched_wakeup_name_id_(context->storage->InternString("sched_wakeup")),
104       sched_waking_name_id_(context->storage->InternString("sched_waking")),
105       cpu_freq_name_id_(context->storage->InternString("cpufreq")),
106       gpu_freq_name_id_(context->storage->InternString("gpufreq")),
107       cpu_idle_name_id_(context->storage->InternString("cpuidle")),
108       ion_total_id_(context->storage->InternString("mem.ion")),
109       ion_change_id_(context->storage->InternString("mem.ion_change")),
110       ion_buffer_id_(context->storage->InternString("mem.ion_buffer")),
111       dma_heap_total_id_(context->storage->InternString("mem.dma_heap")),
112       dma_heap_change_id_(
113           context->storage->InternString("mem.dma_heap_change")),
114       dma_buffer_id_(context->storage->InternString("mem.dma_buffer")),
115       ion_total_unknown_id_(context->storage->InternString("mem.ion.unknown")),
116       ion_change_unknown_id_(
117           context->storage->InternString("mem.ion_change.unknown")),
118       signal_generate_id_(context->storage->InternString("signal_generate")),
119       signal_deliver_id_(context->storage->InternString("signal_deliver")),
120       oom_score_adj_id_(context->storage->InternString("oom_score_adj")),
121       lmk_id_(context->storage->InternString("mem.lmk")),
122       comm_name_id_(context->storage->InternString("comm")),
123       signal_name_id_(context_->storage->InternString("signal.sig")),
124       oom_kill_id_(context_->storage->InternString("mem.oom_kill")),
125       workqueue_id_(context_->storage->InternString("workqueue")),
126       irq_id_(context_->storage->InternString("irq")),
127       ret_arg_id_(context_->storage->InternString("ret")),
128       vec_arg_id_(context->storage->InternString("vec")),
129       gpu_mem_total_name_id_(context->storage->InternString("GPU Memory")),
130       gpu_mem_total_unit_id_(context->storage->InternString(
131           std::to_string(protos::pbzero::GpuCounterDescriptor::BYTE).c_str())),
132       gpu_mem_total_global_desc_id_(context->storage->InternString(
133           "Total GPU memory used by the entire system")),
134       gpu_mem_total_proc_desc_id_(context->storage->InternString(
135           "Total GPU memory used by this process")),
136       sched_blocked_reason_id_(
137           context->storage->InternString("sched_blocked_reason")),
138       io_wait_id_(context->storage->InternString("io_wait")),
139       function_id_(context->storage->InternString("function")) {
140   // Build the lookup table for the strings inside ftrace events (e.g. the
141   // name of ftrace event fields and the names of their args).
142   for (size_t i = 0; i < GetDescriptorsSize(); i++) {
143     auto* descriptor = GetMessageDescriptorForId(i);
144     if (!descriptor->name) {
145       ftrace_message_strings_.emplace_back();
146       continue;
147     }
148 
149     FtraceMessageStrings ftrace_strings;
150     ftrace_strings.message_name_id =
151         context->storage->InternString(descriptor->name);
152 
153     for (size_t fid = 0; fid <= descriptor->max_field_id; fid++) {
154       const auto& field = descriptor->fields[fid];
155       if (!field.name)
156         continue;
157       ftrace_strings.field_name_ids[fid] =
158           context->storage->InternString(field.name);
159     }
160     ftrace_message_strings_.emplace_back(ftrace_strings);
161   }
162 
163   // Array initialization causes a spurious warning due to llvm bug.
164   // See https://bugs.llvm.org/show_bug.cgi?id=21629
165   fast_rpc_delta_names_[0] =
166       context->storage->InternString("mem.fastrpc_change[ASDP]");
167   fast_rpc_delta_names_[1] =
168       context->storage->InternString("mem.fastrpc_change[MDSP]");
169   fast_rpc_delta_names_[2] =
170       context->storage->InternString("mem.fastrpc_change[SDSP]");
171   fast_rpc_delta_names_[3] =
172       context->storage->InternString("mem.fastrpc_change[CDSP]");
173   fast_rpc_total_names_[0] =
174       context->storage->InternString("mem.fastrpc[ASDP]");
175   fast_rpc_total_names_[1] =
176       context->storage->InternString("mem.fastrpc[MDSP]");
177   fast_rpc_total_names_[2] =
178       context->storage->InternString("mem.fastrpc[SDSP]");
179   fast_rpc_total_names_[3] =
180       context->storage->InternString("mem.fastrpc[CDSP]");
181 
182   mm_event_counter_names_ = {
183       {MmEventCounterNames(
184            context->storage->InternString("mem.mm.min_flt.count"),
185            context->storage->InternString("mem.mm.min_flt.max_lat"),
186            context->storage->InternString("mem.mm.min_flt.avg_lat")),
187        MmEventCounterNames(
188            context->storage->InternString("mem.mm.maj_flt.count"),
189            context->storage->InternString("mem.mm.maj_flt.max_lat"),
190            context->storage->InternString("mem.mm.maj_flt.avg_lat")),
191        MmEventCounterNames(
192            context->storage->InternString("mem.mm.read_io.count"),
193            context->storage->InternString("mem.mm.read_io.max_lat"),
194            context->storage->InternString("mem.mm.read_io.avg_lat")),
195        MmEventCounterNames(
196            context->storage->InternString("mem.mm.compaction.count"),
197            context->storage->InternString("mem.mm.compaction.max_lat"),
198            context->storage->InternString("mem.mm.compaction.avg_lat")),
199        MmEventCounterNames(
200            context->storage->InternString("mem.mm.reclaim.count"),
201            context->storage->InternString("mem.mm.reclaim.max_lat"),
202            context->storage->InternString("mem.mm.reclaim.avg_lat")),
203        MmEventCounterNames(
204            context->storage->InternString("mem.mm.swp_flt.count"),
205            context->storage->InternString("mem.mm.swp_flt.max_lat"),
206            context->storage->InternString("mem.mm.swp_flt.avg_lat")),
207        MmEventCounterNames(
208            context->storage->InternString("mem.mm.kern_alloc.count"),
209            context->storage->InternString("mem.mm.kern_alloc.max_lat"),
210            context->storage->InternString("mem.mm.kern_alloc.avg_lat"))}};
211 }
212 
ParseFtraceStats(ConstBytes blob)213 void FtraceParser::ParseFtraceStats(ConstBytes blob) {
214   protos::pbzero::FtraceStats::Decoder evt(blob.data, blob.size);
215   size_t phase =
216       evt.phase() == protos::pbzero::FtraceStats_Phase_END_OF_TRACE ? 1 : 0;
217 
218   // This code relies on the fact that each ftrace_cpu_XXX_end event is
219   // just after the corresponding ftrace_cpu_XXX_begin event.
220   static_assert(
221       stats::ftrace_cpu_read_events_end - stats::ftrace_cpu_read_events_begin ==
222               1 &&
223           stats::ftrace_cpu_entries_end - stats::ftrace_cpu_entries_begin == 1,
224       "ftrace_cpu_XXX stats definition are messed up");
225 
226   auto* storage = context_->storage.get();
227   for (auto it = evt.cpu_stats(); it; ++it) {
228     protos::pbzero::FtraceCpuStats::Decoder cpu_stats(*it);
229     int cpu = static_cast<int>(cpu_stats.cpu());
230     storage->SetIndexedStats(stats::ftrace_cpu_entries_begin + phase, cpu,
231                              static_cast<int64_t>(cpu_stats.entries()));
232     storage->SetIndexedStats(stats::ftrace_cpu_overrun_begin + phase, cpu,
233                              static_cast<int64_t>(cpu_stats.overrun()));
234     storage->SetIndexedStats(stats::ftrace_cpu_commit_overrun_begin + phase,
235                              cpu,
236                              static_cast<int64_t>(cpu_stats.commit_overrun()));
237     storage->SetIndexedStats(stats::ftrace_cpu_bytes_read_begin + phase, cpu,
238                              static_cast<int64_t>(cpu_stats.bytes_read()));
239 
240     // oldest_event_ts can often be set to very high values, possibly because
241     // of wrapping. Ensure that we are not overflowing to avoid ubsan
242     // complaining.
243     double oldest_event_ts = cpu_stats.oldest_event_ts() * 1e9;
244     // NB: This comparison is correct only because of the >=, it would be
245     // incorrect with >. std::numeric_limits<int64_t>::max() converted to
246     // a double is the next value representable as a double that is *larger*
247     // than std::numeric_limits<int64_t>::max(). All values that are
248     // representable as doubles and < than that value are thus representable as
249     // int64_t.
250     if (oldest_event_ts >=
251         static_cast<double>(std::numeric_limits<int64_t>::max())) {
252       storage->SetIndexedStats(stats::ftrace_cpu_oldest_event_ts_begin + phase,
253                                cpu, std::numeric_limits<int64_t>::max());
254     } else {
255       storage->SetIndexedStats(stats::ftrace_cpu_oldest_event_ts_begin + phase,
256                                cpu, static_cast<int64_t>(oldest_event_ts));
257     }
258 
259     storage->SetIndexedStats(stats::ftrace_cpu_now_ts_begin + phase, cpu,
260                              static_cast<int64_t>(cpu_stats.now_ts() * 1e9));
261     storage->SetIndexedStats(stats::ftrace_cpu_dropped_events_begin + phase,
262                              cpu,
263                              static_cast<int64_t>(cpu_stats.dropped_events()));
264     storage->SetIndexedStats(stats::ftrace_cpu_read_events_begin + phase, cpu,
265                              static_cast<int64_t>(cpu_stats.read_events()));
266   }
267 }
268 
269 PERFETTO_ALWAYS_INLINE
ParseFtraceEvent(uint32_t cpu,const TimestampedTracePiece & ttp)270 util::Status FtraceParser::ParseFtraceEvent(uint32_t cpu,
271                                             const TimestampedTracePiece& ttp) {
272   int64_t ts = ttp.timestamp;
273 
274   // On the first ftrace packet, check the metadata table for the
275   // ts of the event which is specified in the config. If it exists we can use
276   // it to filter out ftrace packets which happen earlier than it.
277   if (PERFETTO_UNLIKELY(!has_seen_first_ftrace_packet_)) {
278     DropFtraceDataBefore drop_before = context_->config.drop_ftrace_data_before;
279     switch (drop_before) {
280       case DropFtraceDataBefore::kNoDrop: {
281         drop_ftrace_data_before_ts_ = 0;
282         break;
283       }
284       case DropFtraceDataBefore::kAllDataSourcesStarted:
285       case DropFtraceDataBefore::kTracingStarted: {
286         metadata::KeyId event_key =
287             drop_before == DropFtraceDataBefore::kAllDataSourcesStarted
288                 ? metadata::all_data_source_started_ns
289                 : metadata::tracing_started_ns;
290         const auto& metadata = context_->storage->metadata_table();
291         base::Optional<uint32_t> opt_row =
292             metadata.name().IndexOf(metadata::kNames[event_key]);
293         if (opt_row) {
294           drop_ftrace_data_before_ts_ = *metadata.int_value()[*opt_row];
295         }
296         break;
297       }
298     }
299     has_seen_first_ftrace_packet_ = true;
300   }
301 
302   if (PERFETTO_UNLIKELY(ts < drop_ftrace_data_before_ts_)) {
303     context_->storage->IncrementStats(
304         stats::ftrace_packet_before_tracing_start);
305     return util::OkStatus();
306   }
307 
308   using protos::pbzero::FtraceEvent;
309   SchedEventTracker* sched_tracker = SchedEventTracker::GetOrCreate(context_);
310 
311   // Handle the (optional) alternative encoding format for sched_switch.
312   if (ttp.type == TimestampedTracePiece::Type::kInlineSchedSwitch) {
313     const auto& event = ttp.sched_switch;
314     sched_tracker->PushSchedSwitchCompact(cpu, ts, event.prev_state,
315                                           static_cast<uint32_t>(event.next_pid),
316                                           event.next_prio, event.next_comm);
317     return util::OkStatus();
318   }
319 
320   // Handle the (optional) alternative encoding format for sched_waking.
321   if (ttp.type == TimestampedTracePiece::Type::kInlineSchedWaking) {
322     const auto& event = ttp.sched_waking;
323     sched_tracker->PushSchedWakingCompact(
324         cpu, ts, static_cast<uint32_t>(event.pid), event.target_cpu, event.prio,
325         event.comm);
326     return util::OkStatus();
327   }
328 
329   PERFETTO_DCHECK(ttp.type == TimestampedTracePiece::Type::kFtraceEvent);
330   const TraceBlobView& event = ttp.ftrace_event.event;
331   PacketSequenceStateGeneration* seq_state =
332       ttp.ftrace_event.sequence_state.get();
333   ProtoDecoder decoder(event.data(), event.length());
334   uint64_t raw_pid = 0;
335   if (auto pid_field = decoder.FindField(FtraceEvent::kPidFieldNumber)) {
336     raw_pid = pid_field.as_uint64();
337   } else {
338     return util::ErrStatus("Pid field not found in ftrace packet");
339   }
340   uint32_t pid = static_cast<uint32_t>(raw_pid);
341 
342   for (auto fld = decoder.ReadField(); fld.valid(); fld = decoder.ReadField()) {
343     bool is_metadata_field = fld.id() == FtraceEvent::kPidFieldNumber ||
344                              fld.id() == FtraceEvent::kTimestampFieldNumber;
345     if (is_metadata_field)
346       continue;
347 
348     ConstBytes data = fld.as_bytes();
349     if (fld.id() == FtraceEvent::kGenericFieldNumber) {
350       ParseGenericFtrace(ts, cpu, pid, data);
351     } else if (fld.id() != FtraceEvent::kSchedSwitchFieldNumber) {
352       // sched_switch parsing populates the raw table by itself
353       ParseTypedFtraceToRaw(fld.id(), ts, cpu, pid, data, seq_state);
354     }
355 
356     switch (fld.id()) {
357       case FtraceEvent::kSchedSwitchFieldNumber: {
358         ParseSchedSwitch(cpu, ts, data);
359         break;
360       }
361       case FtraceEvent::kSchedWakeupFieldNumber: {
362         ParseSchedWakeup(ts, data);
363         break;
364       }
365       case FtraceEvent::kSchedWakingFieldNumber: {
366         ParseSchedWaking(ts, data);
367         break;
368       }
369       case FtraceEvent::kSchedProcessFreeFieldNumber: {
370         ParseSchedProcessFree(ts, data);
371         break;
372       }
373       case FtraceEvent::kCpuFrequencyFieldNumber: {
374         ParseCpuFreq(ts, data);
375         break;
376       }
377       case FtraceEvent::kGpuFrequencyFieldNumber: {
378         ParseGpuFreq(ts, data);
379         break;
380       }
381       case FtraceEvent::kCpuIdleFieldNumber: {
382         ParseCpuIdle(ts, data);
383         break;
384       }
385       case FtraceEvent::kPrintFieldNumber: {
386         ParsePrint(ts, pid, data);
387         break;
388       }
389       case FtraceEvent::kZeroFieldNumber: {
390         ParseZero(ts, pid, data);
391         break;
392       }
393       case FtraceEvent::kRssStatFieldNumber: {
394         rss_stat_tracker_.ParseRssStat(ts, pid, data);
395         break;
396       }
397       case FtraceEvent::kIonHeapGrowFieldNumber: {
398         ParseIonHeapGrowOrShrink(ts, pid, data, true);
399         break;
400       }
401       case FtraceEvent::kIonHeapShrinkFieldNumber: {
402         ParseIonHeapGrowOrShrink(ts, pid, data, false);
403         break;
404       }
405       case FtraceEvent::kIonStatFieldNumber: {
406         ParseIonStat(ts, pid, data);
407         break;
408       }
409       case FtraceEvent::kDmaHeapStatFieldNumber: {
410         ParseDmaHeapStat(ts, pid, data);
411         break;
412       }
413       case FtraceEvent::kSignalGenerateFieldNumber: {
414         ParseSignalGenerate(ts, data);
415         break;
416       }
417       case FtraceEvent::kSignalDeliverFieldNumber: {
418         ParseSignalDeliver(ts, pid, data);
419         break;
420       }
421       case FtraceEvent::kLowmemoryKillFieldNumber: {
422         ParseLowmemoryKill(ts, data);
423         break;
424       }
425       case FtraceEvent::kOomScoreAdjUpdateFieldNumber: {
426         ParseOOMScoreAdjUpdate(ts, data);
427         break;
428       }
429       case FtraceEvent::kMarkVictimFieldNumber: {
430         ParseOOMKill(ts, data);
431         break;
432       }
433       case FtraceEvent::kMmEventRecordFieldNumber: {
434         ParseMmEventRecord(ts, pid, data);
435         break;
436       }
437       case FtraceEvent::kSysEnterFieldNumber: {
438         ParseSysEvent(ts, pid, true, data);
439         break;
440       }
441       case FtraceEvent::kSysExitFieldNumber: {
442         ParseSysEvent(ts, pid, false, data);
443         break;
444       }
445       case FtraceEvent::kTaskNewtaskFieldNumber: {
446         ParseTaskNewTask(ts, pid, data);
447         break;
448       }
449       case FtraceEvent::kTaskRenameFieldNumber: {
450         ParseTaskRename(data);
451         break;
452       }
453       case FtraceEvent::kBinderTransactionFieldNumber: {
454         ParseBinderTransaction(ts, pid, data);
455         break;
456       }
457       case FtraceEvent::kBinderTransactionReceivedFieldNumber: {
458         ParseBinderTransactionReceived(ts, pid, data);
459         break;
460       }
461       case FtraceEvent::kBinderTransactionAllocBufFieldNumber: {
462         ParseBinderTransactionAllocBuf(ts, pid, data);
463         break;
464       }
465       case FtraceEvent::kBinderLockFieldNumber: {
466         ParseBinderLock(ts, pid, data);
467         break;
468       }
469       case FtraceEvent::kBinderUnlockFieldNumber: {
470         ParseBinderUnlock(ts, pid, data);
471         break;
472       }
473       case FtraceEvent::kBinderLockedFieldNumber: {
474         ParseBinderLocked(ts, pid, data);
475         break;
476       }
477       case FtraceEvent::kSdeTracingMarkWriteFieldNumber: {
478         ParseSdeTracingMarkWrite(ts, pid, data);
479         break;
480       }
481       case FtraceEvent::kClockSetRateFieldNumber: {
482         ParseClockSetRate(ts, data);
483         break;
484       }
485       case FtraceEvent::kClockEnableFieldNumber: {
486         ParseClockEnable(ts, data);
487         break;
488       }
489       case FtraceEvent::kClockDisableFieldNumber: {
490         ParseClockDisable(ts, data);
491         break;
492       }
493       case FtraceEvent::kScmCallStartFieldNumber: {
494         ParseScmCallStart(ts, pid, data);
495         break;
496       }
497       case FtraceEvent::kScmCallEndFieldNumber: {
498         ParseScmCallEnd(ts, pid, data);
499         break;
500       }
501       case FtraceEvent::kWorkqueueExecuteStartFieldNumber: {
502         ParseWorkqueueExecuteStart(ts, pid, data, seq_state);
503         break;
504       }
505       case FtraceEvent::kWorkqueueExecuteEndFieldNumber: {
506         ParseWorkqueueExecuteEnd(ts, pid, data);
507         break;
508       }
509       case FtraceEvent::kIrqHandlerEntryFieldNumber: {
510         ParseIrqHandlerEntry(cpu, ts, data);
511         break;
512       }
513       case FtraceEvent::kIrqHandlerExitFieldNumber: {
514         ParseIrqHandlerExit(cpu, ts, data);
515         break;
516       }
517       case FtraceEvent::kSoftirqEntryFieldNumber: {
518         ParseSoftIrqEntry(cpu, ts, data);
519         break;
520       }
521       case FtraceEvent::kSoftirqExitFieldNumber: {
522         ParseSoftIrqExit(cpu, ts, data);
523         break;
524       }
525       case FtraceEvent::kGpuMemTotalFieldNumber: {
526         ParseGpuMemTotal(ts, data);
527         break;
528       }
529       case FtraceEvent::kThermalTemperatureFieldNumber: {
530         ParseThermalTemperature(ts, data);
531         break;
532       }
533       case FtraceEvent::kCdevUpdateFieldNumber: {
534         ParseCdevUpdate(ts, data);
535         break;
536       }
537       case FtraceEvent::kSchedBlockedReasonFieldNumber: {
538         ParseSchedBlockedReason(ts, data, seq_state);
539         break;
540       }
541       case FtraceEvent::kFastrpcDmaStatFieldNumber: {
542         ParseFastRpcDmaStat(ts, pid, data);
543         break;
544       }
545       case FtraceEvent::kG2dTracingMarkWriteFieldNumber: {
546         ParseG2dTracingMarkWrite(ts, pid, data);
547         break;
548       }
549       case FtraceEvent::kDpuTracingMarkWriteFieldNumber: {
550         ParseDpuTracingMarkWrite(ts, pid, data);
551         break;
552       }
553       case FtraceEvent::kMaliTracingMarkWriteFieldNumber: {
554         ParseMaliTracingMarkWrite(ts, pid, data);
555         break;
556       }
557       case FtraceEvent::kCpuhpPauseFieldNumber: {
558         ParseCpuhpPause(ts, pid, data);
559         break;
560       }
561       default:
562         break;
563     }
564   }
565 
566   PERFETTO_DCHECK(!decoder.bytes_left());
567   return util::OkStatus();
568 }
569 
ParseGenericFtrace(int64_t ts,uint32_t cpu,uint32_t tid,ConstBytes blob)570 void FtraceParser::ParseGenericFtrace(int64_t ts,
571                                       uint32_t cpu,
572                                       uint32_t tid,
573                                       ConstBytes blob) {
574   protos::pbzero::GenericFtraceEvent::Decoder evt(blob.data, blob.size);
575   StringId event_id = context_->storage->InternString(evt.event_name());
576   UniqueTid utid = context_->process_tracker->GetOrCreateThread(tid);
577   RawId id = context_->storage->mutable_raw_table()
578                  ->Insert({ts, event_id, cpu, utid})
579                  .id;
580   auto inserter = context_->args_tracker->AddArgsTo(id);
581 
582   for (auto it = evt.field(); it; ++it) {
583     protos::pbzero::GenericFtraceEvent::Field::Decoder fld(*it);
584     auto field_name_id = context_->storage->InternString(fld.name());
585     if (fld.has_int_value()) {
586       inserter.AddArg(field_name_id, Variadic::Integer(fld.int_value()));
587     } else if (fld.has_uint_value()) {
588       inserter.AddArg(
589           field_name_id,
590           Variadic::Integer(static_cast<int64_t>(fld.uint_value())));
591     } else if (fld.has_str_value()) {
592       StringId str_value = context_->storage->InternString(fld.str_value());
593       inserter.AddArg(field_name_id, Variadic::String(str_value));
594     }
595   }
596 }
597 
ParseTypedFtraceToRaw(uint32_t ftrace_id,int64_t timestamp,uint32_t cpu,uint32_t tid,ConstBytes blob,PacketSequenceStateGeneration * seq_state)598 void FtraceParser::ParseTypedFtraceToRaw(
599     uint32_t ftrace_id,
600     int64_t timestamp,
601     uint32_t cpu,
602     uint32_t tid,
603     ConstBytes blob,
604     PacketSequenceStateGeneration* seq_state) {
605   if (PERFETTO_UNLIKELY(!context_->config.ingest_ftrace_in_raw_table))
606     return;
607 
608   ProtoDecoder decoder(blob.data, blob.size);
609   if (ftrace_id >= GetDescriptorsSize()) {
610     PERFETTO_DLOG("Event with id: %d does not exist and cannot be parsed.",
611                   ftrace_id);
612     return;
613   }
614 
615   MessageDescriptor* m = GetMessageDescriptorForId(ftrace_id);
616   const auto& message_strings = ftrace_message_strings_[ftrace_id];
617   UniqueTid utid = context_->process_tracker->GetOrCreateThread(tid);
618   RawId id =
619       context_->storage->mutable_raw_table()
620           ->Insert({timestamp, message_strings.message_name_id, cpu, utid})
621           .id;
622   auto inserter = context_->args_tracker->AddArgsTo(id);
623 
624   for (auto fld = decoder.ReadField(); fld.valid(); fld = decoder.ReadField()) {
625     uint16_t field_id = fld.id();
626     if (PERFETTO_UNLIKELY(field_id >= kMaxFtraceEventFields)) {
627       PERFETTO_DLOG(
628           "Skipping ftrace arg - proto field id is too large (%" PRIu16 ")",
629           field_id);
630       continue;
631     }
632 
633     ProtoSchemaType type = m->fields[field_id].type;
634     StringId name_id = message_strings.field_name_ids[field_id];
635 
636     // Check if this field represents a kernel function.
637     auto it = std::find_if(
638         kKernelFunctionFields.begin(), kKernelFunctionFields.end(),
639         [ftrace_id, field_id](const FtraceEventAndFieldId& ev) {
640           return ev.event_id == ftrace_id && ev.field_id == field_id;
641         });
642     if (it != kKernelFunctionFields.end()) {
643       PERFETTO_CHECK(type == ProtoSchemaType::kUint64);
644 
645       auto* interned_string = seq_state->LookupInternedMessage<
646           protos::pbzero::InternedData::kKernelSymbolsFieldNumber,
647           protos::pbzero::InternedString>(fld.as_uint64());
648 
649       // If we don't have the string for this field (can happen if symbolization
650       // wasn't enabled, if reading the symbols errored out or on legacy traces)
651       // then just add the field as a normal arg.
652       if (interned_string) {
653         protozero::ConstBytes str = interned_string->str();
654         StringId str_id = context_->storage->InternString(base::StringView(
655             reinterpret_cast<const char*>(str.data), str.size));
656         inserter.AddArg(name_id, Variadic::String(str_id));
657         continue;
658       }
659     }
660 
661     switch (type) {
662       case ProtoSchemaType::kInt32:
663       case ProtoSchemaType::kInt64:
664       case ProtoSchemaType::kSfixed32:
665       case ProtoSchemaType::kSfixed64:
666       case ProtoSchemaType::kSint32:
667       case ProtoSchemaType::kSint64:
668       case ProtoSchemaType::kBool:
669       case ProtoSchemaType::kEnum: {
670         inserter.AddArg(name_id, Variadic::Integer(fld.as_int64()));
671         break;
672       }
673       case ProtoSchemaType::kUint32:
674       case ProtoSchemaType::kUint64:
675       case ProtoSchemaType::kFixed32:
676       case ProtoSchemaType::kFixed64: {
677         // Note that SQLite functions will still treat unsigned values
678         // as a signed 64 bit integers (but the translation back to ftrace
679         // refers to this storage directly).
680         inserter.AddArg(name_id, Variadic::UnsignedInteger(fld.as_uint64()));
681         break;
682       }
683       case ProtoSchemaType::kString:
684       case ProtoSchemaType::kBytes: {
685         StringId value = context_->storage->InternString(fld.as_string());
686         inserter.AddArg(name_id, Variadic::String(value));
687         break;
688       }
689       case ProtoSchemaType::kDouble: {
690         inserter.AddArg(name_id, Variadic::Real(fld.as_double()));
691         break;
692       }
693       case ProtoSchemaType::kFloat: {
694         inserter.AddArg(name_id,
695                         Variadic::Real(static_cast<double>(fld.as_float())));
696         break;
697       }
698       case ProtoSchemaType::kUnknown:
699       case ProtoSchemaType::kGroup:
700       case ProtoSchemaType::kMessage:
701         PERFETTO_DLOG("Could not store %s as a field in args table.",
702                       ProtoSchemaToString(type));
703         break;
704     }
705   }
706 }
707 
708 PERFETTO_ALWAYS_INLINE
ParseSchedSwitch(uint32_t cpu,int64_t timestamp,ConstBytes blob)709 void FtraceParser::ParseSchedSwitch(uint32_t cpu,
710                                     int64_t timestamp,
711                                     ConstBytes blob) {
712   protos::pbzero::SchedSwitchFtraceEvent::Decoder ss(blob.data, blob.size);
713   uint32_t prev_pid = static_cast<uint32_t>(ss.prev_pid());
714   uint32_t next_pid = static_cast<uint32_t>(ss.next_pid());
715   SchedEventTracker::GetOrCreate(context_)->PushSchedSwitch(
716       cpu, timestamp, prev_pid, ss.prev_comm(), ss.prev_prio(), ss.prev_state(),
717       next_pid, ss.next_comm(), ss.next_prio());
718 }
719 
ParseSchedWakeup(int64_t timestamp,ConstBytes blob)720 void FtraceParser::ParseSchedWakeup(int64_t timestamp, ConstBytes blob) {
721   protos::pbzero::SchedWakeupFtraceEvent::Decoder sw(blob.data, blob.size);
722   uint32_t wakee_pid = static_cast<uint32_t>(sw.pid());
723   StringId name_id = context_->storage->InternString(sw.comm());
724   auto utid = context_->process_tracker->UpdateThreadName(
725       wakee_pid, name_id, ThreadNamePriority::kFtrace);
726   context_->event_tracker->PushInstant(timestamp, sched_wakeup_name_id_, utid,
727                                        RefType::kRefUtid);
728 }
729 
ParseSchedWaking(int64_t timestamp,ConstBytes blob)730 void FtraceParser::ParseSchedWaking(int64_t timestamp, ConstBytes blob) {
731   protos::pbzero::SchedWakingFtraceEvent::Decoder sw(blob.data, blob.size);
732   uint32_t wakee_pid = static_cast<uint32_t>(sw.pid());
733   StringId name_id = context_->storage->InternString(sw.comm());
734   auto utid = context_->process_tracker->UpdateThreadName(
735       wakee_pid, name_id, ThreadNamePriority::kFtrace);
736   context_->event_tracker->PushInstant(timestamp, sched_waking_name_id_, utid,
737                                        RefType::kRefUtid);
738 }
739 
ParseSchedProcessFree(int64_t timestamp,ConstBytes blob)740 void FtraceParser::ParseSchedProcessFree(int64_t timestamp, ConstBytes blob) {
741   protos::pbzero::SchedProcessFreeFtraceEvent::Decoder ex(blob.data, blob.size);
742   uint32_t pid = static_cast<uint32_t>(ex.pid());
743   context_->process_tracker->EndThread(timestamp, pid);
744 }
745 
ParseCpuFreq(int64_t timestamp,ConstBytes blob)746 void FtraceParser::ParseCpuFreq(int64_t timestamp, ConstBytes blob) {
747   protos::pbzero::CpuFrequencyFtraceEvent::Decoder freq(blob.data, blob.size);
748   uint32_t cpu = freq.cpu_id();
749   uint32_t new_freq = freq.state();
750   TrackId track =
751       context_->track_tracker->InternCpuCounterTrack(cpu_freq_name_id_, cpu);
752   context_->event_tracker->PushCounter(timestamp, new_freq, track);
753 }
754 
ParseGpuFreq(int64_t timestamp,ConstBytes blob)755 void FtraceParser::ParseGpuFreq(int64_t timestamp, ConstBytes blob) {
756   protos::pbzero::GpuFrequencyFtraceEvent::Decoder freq(blob.data, blob.size);
757   uint32_t gpu = freq.gpu_id();
758   uint32_t new_freq = freq.state();
759   TrackId track =
760       context_->track_tracker->InternGpuCounterTrack(gpu_freq_name_id_, gpu);
761   context_->event_tracker->PushCounter(timestamp, new_freq, track);
762 }
763 
ParseCpuIdle(int64_t timestamp,ConstBytes blob)764 void FtraceParser::ParseCpuIdle(int64_t timestamp, ConstBytes blob) {
765   protos::pbzero::CpuIdleFtraceEvent::Decoder idle(blob.data, blob.size);
766   uint32_t cpu = idle.cpu_id();
767   uint32_t new_state = idle.state();
768   TrackId track =
769       context_->track_tracker->InternCpuCounterTrack(cpu_idle_name_id_, cpu);
770   context_->event_tracker->PushCounter(timestamp, new_state, track);
771 }
772 
ParsePrint(int64_t timestamp,uint32_t pid,ConstBytes blob)773 void FtraceParser::ParsePrint(int64_t timestamp,
774                               uint32_t pid,
775                               ConstBytes blob) {
776   protos::pbzero::PrintFtraceEvent::Decoder evt(blob.data, blob.size);
777   SystraceParser::GetOrCreate(context_)->ParsePrintEvent(timestamp, pid,
778                                                          evt.buf());
779 }
780 
ParseZero(int64_t timestamp,uint32_t pid,ConstBytes blob)781 void FtraceParser::ParseZero(int64_t timestamp, uint32_t pid, ConstBytes blob) {
782   protos::pbzero::ZeroFtraceEvent::Decoder evt(blob.data, blob.size);
783   uint32_t tgid = static_cast<uint32_t>(evt.pid());
784   SystraceParser::GetOrCreate(context_)->ParseZeroEvent(
785       timestamp, pid, evt.flag(), evt.name(), tgid, evt.value());
786 }
787 
ParseSdeTracingMarkWrite(int64_t timestamp,uint32_t pid,ConstBytes blob)788 void FtraceParser::ParseSdeTracingMarkWrite(int64_t timestamp,
789                                             uint32_t pid,
790                                             ConstBytes blob) {
791   protos::pbzero::SdeTracingMarkWriteFtraceEvent::Decoder evt(blob.data,
792                                                               blob.size);
793   if (!evt.has_trace_type() && !evt.has_trace_begin()) {
794     context_->storage->IncrementStats(stats::systrace_parse_failure);
795     return;
796   }
797 
798   uint32_t tgid = static_cast<uint32_t>(evt.pid());
799   SystraceParser::GetOrCreate(context_)->ParseTracingMarkWrite(
800       timestamp, pid, static_cast<char>(evt.trace_type()), evt.trace_begin(),
801       evt.trace_name(), tgid, evt.value());
802 }
803 
ParseDpuTracingMarkWrite(int64_t timestamp,uint32_t pid,ConstBytes blob)804 void FtraceParser::ParseDpuTracingMarkWrite(int64_t timestamp,
805                                             uint32_t pid,
806                                             ConstBytes blob) {
807   protos::pbzero::DpuTracingMarkWriteFtraceEvent::Decoder evt(blob.data,
808                                                               blob.size);
809   if (!evt.type()) {
810     context_->storage->IncrementStats(stats::systrace_parse_failure);
811     return;
812   }
813 
814   uint32_t tgid = static_cast<uint32_t>(evt.pid());
815   SystraceParser::GetOrCreate(context_)->ParseTracingMarkWrite(
816       timestamp, pid, static_cast<char>(evt.type()), false /*trace_begin*/,
817       evt.name(), tgid, evt.value());
818 }
819 
ParseG2dTracingMarkWrite(int64_t timestamp,uint32_t pid,ConstBytes blob)820 void FtraceParser::ParseG2dTracingMarkWrite(int64_t timestamp,
821                                             uint32_t pid,
822                                             ConstBytes blob) {
823   protos::pbzero::G2dTracingMarkWriteFtraceEvent::Decoder evt(blob.data,
824                                                               blob.size);
825   if (!evt.type()) {
826     context_->storage->IncrementStats(stats::systrace_parse_failure);
827     return;
828   }
829 
830   uint32_t tgid = static_cast<uint32_t>(evt.pid());
831   SystraceParser::GetOrCreate(context_)->ParseTracingMarkWrite(
832       timestamp, pid, static_cast<char>(evt.type()), false /*trace_begin*/,
833       evt.name(), tgid, evt.value());
834 }
835 
ParseMaliTracingMarkWrite(int64_t timestamp,uint32_t pid,ConstBytes blob)836 void FtraceParser::ParseMaliTracingMarkWrite(int64_t timestamp,
837                                              uint32_t pid,
838                                              ConstBytes blob) {
839   protos::pbzero::MaliTracingMarkWriteFtraceEvent::Decoder evt(blob.data,
840                                                                blob.size);
841   if (!evt.type()) {
842     context_->storage->IncrementStats(stats::systrace_parse_failure);
843     return;
844   }
845 
846   uint32_t tgid = static_cast<uint32_t>(evt.pid());
847   SystraceParser::GetOrCreate(context_)->ParseTracingMarkWrite(
848       timestamp, pid, static_cast<char>(evt.type()), false /*trace_begin*/,
849       evt.name(), tgid, evt.value());
850 }
851 
852 /** Parses ion heap events present in Pixel kernels. */
ParseIonHeapGrowOrShrink(int64_t timestamp,uint32_t pid,ConstBytes blob,bool grow)853 void FtraceParser::ParseIonHeapGrowOrShrink(int64_t timestamp,
854                                             uint32_t pid,
855                                             ConstBytes blob,
856                                             bool grow) {
857   protos::pbzero::IonHeapGrowFtraceEvent::Decoder ion(blob.data, blob.size);
858   int64_t change_bytes = static_cast<int64_t>(ion.len()) * (grow ? 1 : -1);
859   // The total_allocated ftrace event reports the value before the
860   // atomic_long_add / sub takes place.
861   int64_t total_bytes = ion.total_allocated() + change_bytes;
862   StringId global_name_id = ion_total_unknown_id_;
863   StringId change_name_id = ion_change_unknown_id_;
864 
865   if (ion.has_heap_name()) {
866     char counter_name[255];
867     base::StringView heap_name = ion.heap_name();
868     snprintf(counter_name, sizeof(counter_name), "mem.ion.%.*s",
869              int(heap_name.size()), heap_name.data());
870     global_name_id = context_->storage->InternString(counter_name);
871     snprintf(counter_name, sizeof(counter_name), "mem.ion_change.%.*s",
872              int(heap_name.size()), heap_name.data());
873     change_name_id = context_->storage->InternString(counter_name);
874   }
875 
876   // Push the global counter.
877   TrackId track =
878       context_->track_tracker->InternGlobalCounterTrack(global_name_id);
879   context_->event_tracker->PushCounter(timestamp,
880                                        static_cast<double>(total_bytes), track);
881 
882   // Push the change counter.
883   // TODO(b/121331269): these should really be instant events.
884   UniqueTid utid = context_->process_tracker->GetOrCreateThread(pid);
885   track =
886       context_->track_tracker->InternThreadCounterTrack(change_name_id, utid);
887   context_->event_tracker->PushCounter(
888       timestamp, static_cast<double>(change_bytes), track);
889 
890   // We are reusing the same function for ion_heap_grow and ion_heap_shrink.
891   // It is fine as the arguments are the same, but we need to be sure that the
892   // protobuf field id for both are the same.
893   static_assert(
894       static_cast<int>(
895           protos::pbzero::IonHeapGrowFtraceEvent::kTotalAllocatedFieldNumber) ==
896               static_cast<int>(protos::pbzero::IonHeapShrinkFtraceEvent::
897                                    kTotalAllocatedFieldNumber) &&
898           static_cast<int>(
899               protos::pbzero::IonHeapGrowFtraceEvent::kLenFieldNumber) ==
900               static_cast<int>(
901                   protos::pbzero::IonHeapShrinkFtraceEvent::kLenFieldNumber) &&
902           static_cast<int>(
903               protos::pbzero::IonHeapGrowFtraceEvent::kHeapNameFieldNumber) ==
904               static_cast<int>(protos::pbzero::IonHeapShrinkFtraceEvent::
905                                    kHeapNameFieldNumber),
906       "ION field mismatch");
907 }
908 
909 /** Parses ion heap events (introduced in 4.19 kernels). */
ParseIonStat(int64_t timestamp,uint32_t pid,protozero::ConstBytes data)910 void FtraceParser::ParseIonStat(int64_t timestamp,
911                                 uint32_t pid,
912                                 protozero::ConstBytes data) {
913   protos::pbzero::IonStatFtraceEvent::Decoder ion(data.data, data.size);
914   // Push the global counter.
915   TrackId track =
916       context_->track_tracker->InternGlobalCounterTrack(ion_total_id_);
917   context_->event_tracker->PushCounter(
918       timestamp, static_cast<double>(ion.total_allocated()), track);
919 
920   // Push the change counter.
921   // TODO(b/121331269): these should really be instant events.
922   UniqueTid utid = context_->process_tracker->GetOrCreateThread(pid);
923   track =
924       context_->track_tracker->InternThreadCounterTrack(ion_change_id_, utid);
925   context_->event_tracker->PushCounter(timestamp,
926                                        static_cast<double>(ion.len()), track);
927 
928   // Global track for individual buffer tracking
929   auto async_track =
930       context_->async_track_set_tracker->InternGlobalTrackSet(ion_buffer_id_);
931   if (ion.len() > 0) {
932     TrackId start_id =
933         context_->async_track_set_tracker->Begin(async_track, ion.buffer_id());
934     std::string buf = std::to_string(ion.len() / 1024) + " kB";
935     context_->slice_tracker->Begin(
936         timestamp, start_id, kNullStringId,
937         context_->storage->InternString(base::StringView(buf)));
938   } else {
939     TrackId end_id =
940         context_->async_track_set_tracker->End(async_track, ion.buffer_id());
941     context_->slice_tracker->End(timestamp, end_id);
942   }
943 }
944 
ParseDmaHeapStat(int64_t timestamp,uint32_t pid,protozero::ConstBytes data)945 void FtraceParser::ParseDmaHeapStat(int64_t timestamp,
946                                     uint32_t pid,
947                                     protozero::ConstBytes data) {
948   protos::pbzero::DmaHeapStatFtraceEvent::Decoder dma_heap(data.data,
949                                                            data.size);
950   // Push the global counter.
951   TrackId track =
952       context_->track_tracker->InternGlobalCounterTrack(dma_heap_total_id_);
953   context_->event_tracker->PushCounter(
954       timestamp, static_cast<double>(dma_heap.total_allocated()), track);
955 
956   // Push the change counter.
957   // TODO(b/121331269): these should really be instant events.
958   UniqueTid utid = context_->process_tracker->GetOrCreateThread(pid);
959   track = context_->track_tracker->InternThreadCounterTrack(dma_heap_change_id_,
960                                                             utid);
961   context_->event_tracker->PushCounter(
962       timestamp, static_cast<double>(dma_heap.len()), track);
963 
964   // Global track for individual buffer tracking
965   auto async_track =
966       context_->async_track_set_tracker->InternGlobalTrackSet(dma_buffer_id_);
967   if (dma_heap.len() > 0) {
968     TrackId start_id = context_->async_track_set_tracker->Begin(
969         async_track, static_cast<int64_t>(dma_heap.inode()));
970     std::string buf = std::to_string(dma_heap.len() / 1024) + " kB";
971     context_->slice_tracker->Begin(
972         timestamp, start_id, kNullStringId,
973         context_->storage->InternString(base::StringView(buf)));
974   } else {
975     TrackId end_id = context_->async_track_set_tracker->End(
976         async_track, static_cast<int64_t>(dma_heap.inode()));
977     context_->slice_tracker->End(timestamp, end_id);
978   }
979 }
980 
981 // This event has both the pid of the thread that sent the signal and the
982 // destination of the signal. Currently storing the pid of the destination.
ParseSignalGenerate(int64_t timestamp,ConstBytes blob)983 void FtraceParser::ParseSignalGenerate(int64_t timestamp, ConstBytes blob) {
984   protos::pbzero::SignalGenerateFtraceEvent::Decoder sig(blob.data, blob.size);
985 
986   UniqueTid utid = context_->process_tracker->GetOrCreateThread(
987       static_cast<uint32_t>(sig.pid()));
988   InstantId id = context_->event_tracker->PushInstant(
989       timestamp, signal_generate_id_, utid, RefType::kRefUtid);
990 
991   context_->args_tracker->AddArgsTo(id).AddArg(signal_name_id_,
992                                                Variadic::Integer(sig.sig()));
993 }
994 
ParseSignalDeliver(int64_t timestamp,uint32_t pid,ConstBytes blob)995 void FtraceParser::ParseSignalDeliver(int64_t timestamp,
996                                       uint32_t pid,
997                                       ConstBytes blob) {
998   protos::pbzero::SignalDeliverFtraceEvent::Decoder sig(blob.data, blob.size);
999   UniqueTid utid = context_->process_tracker->GetOrCreateThread(pid);
1000   InstantId id = context_->event_tracker->PushInstant(
1001       timestamp, signal_deliver_id_, utid, RefType::kRefUtid);
1002 
1003   context_->args_tracker->AddArgsTo(id).AddArg(signal_name_id_,
1004                                                Variadic::Integer(sig.sig()));
1005 }
1006 
ParseLowmemoryKill(int64_t timestamp,ConstBytes blob)1007 void FtraceParser::ParseLowmemoryKill(int64_t timestamp, ConstBytes blob) {
1008   // TODO(hjd): Store the pagecache_size, pagecache_limit and free fields
1009   // in an args table
1010   protos::pbzero::LowmemoryKillFtraceEvent::Decoder lmk(blob.data, blob.size);
1011 
1012   // Store the pid of the event that is lmk-ed.
1013   auto pid = static_cast<uint32_t>(lmk.pid());
1014   auto opt_utid = context_->process_tracker->GetThreadOrNull(pid);
1015 
1016   // Don't add LMK events for threads we've never seen before. This works around
1017   // the case where we get an LMK event after a thread has already been killed.
1018   if (!opt_utid)
1019     return;
1020 
1021   InstantId id = context_->event_tracker->PushInstant(
1022       timestamp, lmk_id_, opt_utid.value(), RefType::kRefUtid, true);
1023 
1024   // Store the comm as an arg.
1025   auto comm_id = context_->storage->InternString(
1026       lmk.has_comm() ? lmk.comm() : base::StringView());
1027   context_->args_tracker->AddArgsTo(id).AddArg(comm_name_id_,
1028                                                Variadic::String(comm_id));
1029 }
1030 
ParseOOMScoreAdjUpdate(int64_t timestamp,ConstBytes blob)1031 void FtraceParser::ParseOOMScoreAdjUpdate(int64_t timestamp, ConstBytes blob) {
1032   protos::pbzero::OomScoreAdjUpdateFtraceEvent::Decoder evt(blob.data,
1033                                                             blob.size);
1034   // The int16_t static cast is because older version of the on-device tracer
1035   // had a bug on negative varint encoding (b/120618641).
1036   int16_t oom_adj = static_cast<int16_t>(evt.oom_score_adj());
1037   uint32_t tid = static_cast<uint32_t>(evt.pid());
1038   UniqueTid utid = context_->process_tracker->GetOrCreateThread(tid);
1039   context_->event_tracker->PushProcessCounterForThread(timestamp, oom_adj,
1040                                                        oom_score_adj_id_, utid);
1041 }
1042 
ParseOOMKill(int64_t timestamp,ConstBytes blob)1043 void FtraceParser::ParseOOMKill(int64_t timestamp, ConstBytes blob) {
1044   protos::pbzero::MarkVictimFtraceEvent::Decoder evt(blob.data, blob.size);
1045   UniqueTid utid = context_->process_tracker->GetOrCreateThread(
1046       static_cast<uint32_t>(evt.pid()));
1047   context_->event_tracker->PushInstant(timestamp, oom_kill_id_, utid,
1048                                        RefType::kRefUtid, true);
1049 }
1050 
ParseMmEventRecord(int64_t timestamp,uint32_t pid,ConstBytes blob)1051 void FtraceParser::ParseMmEventRecord(int64_t timestamp,
1052                                       uint32_t pid,
1053                                       ConstBytes blob) {
1054   protos::pbzero::MmEventRecordFtraceEvent::Decoder evt(blob.data, blob.size);
1055   uint32_t type = evt.type();
1056   UniqueTid utid = context_->process_tracker->GetOrCreateThread(pid);
1057 
1058   if (type >= mm_event_counter_names_.size()) {
1059     context_->storage->IncrementStats(stats::mm_unknown_type);
1060     return;
1061   }
1062 
1063   const auto& counter_names = mm_event_counter_names_[type];
1064   context_->event_tracker->PushProcessCounterForThread(
1065       timestamp, evt.count(), counter_names.count, utid);
1066   context_->event_tracker->PushProcessCounterForThread(
1067       timestamp, evt.max_lat(), counter_names.max_lat, utid);
1068   context_->event_tracker->PushProcessCounterForThread(
1069       timestamp, evt.avg_lat(), counter_names.avg_lat, utid);
1070 }
1071 
ParseSysEvent(int64_t timestamp,uint32_t pid,bool is_enter,ConstBytes blob)1072 void FtraceParser::ParseSysEvent(int64_t timestamp,
1073                                  uint32_t pid,
1074                                  bool is_enter,
1075                                  ConstBytes blob) {
1076   protos::pbzero::SysEnterFtraceEvent::Decoder evt(blob.data, blob.size);
1077   uint32_t syscall_num = static_cast<uint32_t>(evt.id());
1078   UniqueTid utid = context_->process_tracker->GetOrCreateThread(pid);
1079 
1080   SyscallTracker* syscall_tracker = SyscallTracker::GetOrCreate(context_);
1081   if (is_enter) {
1082     syscall_tracker->Enter(timestamp, utid, syscall_num);
1083   } else {
1084     syscall_tracker->Exit(timestamp, utid, syscall_num);
1085   }
1086 
1087   // We are reusing the same function for sys_enter and sys_exit.
1088   // It is fine as the arguments are the same, but we need to be sure that the
1089   // protobuf field id for both are the same.
1090   static_assert(
1091       static_cast<int>(protos::pbzero::SysEnterFtraceEvent::kIdFieldNumber) ==
1092           static_cast<int>(protos::pbzero::SysExitFtraceEvent::kIdFieldNumber),
1093       "field mismatch");
1094 }
1095 
ParseTaskNewTask(int64_t timestamp,uint32_t source_tid,ConstBytes blob)1096 void FtraceParser::ParseTaskNewTask(int64_t timestamp,
1097                                     uint32_t source_tid,
1098                                     ConstBytes blob) {
1099   protos::pbzero::TaskNewtaskFtraceEvent::Decoder evt(blob.data, blob.size);
1100   uint32_t clone_flags = static_cast<uint32_t>(evt.clone_flags());
1101   uint32_t new_tid = static_cast<uint32_t>(evt.pid());
1102   StringId new_comm = context_->storage->InternString(evt.comm());
1103   auto* proc_tracker = context_->process_tracker.get();
1104 
1105   // task_newtask is raised both in the case of a new process creation (fork()
1106   // family) and thread creation (clone(CLONE_THREAD, ...)).
1107   static const uint32_t kCloneThread = 0x00010000;  // From kernel's sched.h.
1108 
1109   // If the process is a fork, start a new process except if the source tid is
1110   // kthreadd in which case just make it a new thread associated with kthreadd.
1111   if ((clone_flags & kCloneThread) == 0 && source_tid != kKthreaddPid) {
1112     // This is a plain-old fork() or equivalent.
1113     proc_tracker->StartNewProcess(timestamp, source_tid, new_tid, new_comm);
1114     return;
1115   }
1116 
1117   if (source_tid == kKthreaddPid) {
1118     context_->process_tracker->SetProcessMetadata(
1119         kKthreaddPid, base::nullopt, kKthreaddName, base::StringView());
1120   }
1121 
1122   // This is a pthread_create or similar. Bind the two threads together, so
1123   // they get resolved to the same process.
1124   auto source_utid = proc_tracker->GetOrCreateThread(source_tid);
1125   auto new_utid = proc_tracker->StartNewThread(timestamp, new_tid);
1126   proc_tracker->UpdateThreadNameByUtid(new_utid, new_comm,
1127                                        ThreadNamePriority::kFtrace);
1128   proc_tracker->AssociateThreads(source_utid, new_utid);
1129 }
1130 
ParseTaskRename(ConstBytes blob)1131 void FtraceParser::ParseTaskRename(ConstBytes blob) {
1132   protos::pbzero::TaskRenameFtraceEvent::Decoder evt(blob.data, blob.size);
1133   uint32_t tid = static_cast<uint32_t>(evt.pid());
1134   StringId comm = context_->storage->InternString(evt.newcomm());
1135   context_->process_tracker->UpdateThreadName(tid, comm,
1136                                               ThreadNamePriority::kFtrace);
1137   context_->process_tracker->UpdateProcessNameFromThreadName(tid, comm);
1138 }
1139 
ParseBinderTransaction(int64_t timestamp,uint32_t pid,ConstBytes blob)1140 void FtraceParser::ParseBinderTransaction(int64_t timestamp,
1141                                           uint32_t pid,
1142                                           ConstBytes blob) {
1143   protos::pbzero::BinderTransactionFtraceEvent::Decoder evt(blob.data,
1144                                                             blob.size);
1145   int32_t dest_node = static_cast<int32_t>(evt.target_node());
1146   int32_t dest_tgid = static_cast<int32_t>(evt.to_proc());
1147   int32_t dest_tid = static_cast<int32_t>(evt.to_thread());
1148   int32_t transaction_id = static_cast<int32_t>(evt.debug_id());
1149   bool is_reply = static_cast<int32_t>(evt.reply()) == 1;
1150   uint32_t flags = static_cast<uint32_t>(evt.flags());
1151   auto code_str = base::IntToHexString(evt.code()) + " Java Layer Dependent";
1152   StringId code = context_->storage->InternString(base::StringView(code_str));
1153   BinderTracker::GetOrCreate(context_)->Transaction(
1154       timestamp, pid, transaction_id, dest_node, dest_tgid, dest_tid, is_reply,
1155       flags, code);
1156 }
1157 
ParseBinderTransactionReceived(int64_t timestamp,uint32_t pid,ConstBytes blob)1158 void FtraceParser::ParseBinderTransactionReceived(int64_t timestamp,
1159                                                   uint32_t pid,
1160                                                   ConstBytes blob) {
1161   protos::pbzero::BinderTransactionReceivedFtraceEvent::Decoder evt(blob.data,
1162                                                                     blob.size);
1163   int32_t transaction_id = static_cast<int32_t>(evt.debug_id());
1164   BinderTracker::GetOrCreate(context_)->TransactionReceived(timestamp, pid,
1165                                                             transaction_id);
1166 }
1167 
ParseBinderTransactionAllocBuf(int64_t timestamp,uint32_t pid,ConstBytes blob)1168 void FtraceParser::ParseBinderTransactionAllocBuf(int64_t timestamp,
1169                                                   uint32_t pid,
1170                                                   ConstBytes blob) {
1171   protos::pbzero::BinderTransactionAllocBufFtraceEvent::Decoder evt(blob.data,
1172                                                                     blob.size);
1173   uint64_t data_size = static_cast<uint64_t>(evt.data_size());
1174   uint64_t offsets_size = static_cast<uint64_t>(evt.offsets_size());
1175 
1176   BinderTracker::GetOrCreate(context_)->TransactionAllocBuf(
1177       timestamp, pid, data_size, offsets_size);
1178 }
1179 
ParseBinderLocked(int64_t timestamp,uint32_t pid,ConstBytes blob)1180 void FtraceParser::ParseBinderLocked(int64_t timestamp,
1181                                      uint32_t pid,
1182                                      ConstBytes blob) {
1183   protos::pbzero::BinderLockedFtraceEvent::Decoder evt(blob.data, blob.size);
1184   BinderTracker::GetOrCreate(context_)->Locked(timestamp, pid);
1185 }
1186 
ParseBinderLock(int64_t timestamp,uint32_t pid,ConstBytes blob)1187 void FtraceParser::ParseBinderLock(int64_t timestamp,
1188                                    uint32_t pid,
1189                                    ConstBytes blob) {
1190   protos::pbzero::BinderLockFtraceEvent::Decoder evt(blob.data, blob.size);
1191   BinderTracker::GetOrCreate(context_)->Lock(timestamp, pid);
1192 }
1193 
ParseBinderUnlock(int64_t timestamp,uint32_t pid,ConstBytes blob)1194 void FtraceParser::ParseBinderUnlock(int64_t timestamp,
1195                                      uint32_t pid,
1196                                      ConstBytes blob) {
1197   protos::pbzero::BinderUnlockFtraceEvent::Decoder evt(blob.data, blob.size);
1198   BinderTracker::GetOrCreate(context_)->Unlock(timestamp, pid);
1199 }
1200 
ParseClockSetRate(int64_t timestamp,ConstBytes blob)1201 void FtraceParser::ParseClockSetRate(int64_t timestamp, ConstBytes blob) {
1202   protos::pbzero::ClockSetRateFtraceEvent::Decoder evt(blob.data, blob.size);
1203   static const char kSubtitle[] = "Frequency";
1204   ClockRate(timestamp, evt.name(), kSubtitle, evt.state());
1205 }
1206 
ParseClockEnable(int64_t timestamp,ConstBytes blob)1207 void FtraceParser::ParseClockEnable(int64_t timestamp, ConstBytes blob) {
1208   protos::pbzero::ClockEnableFtraceEvent::Decoder evt(blob.data, blob.size);
1209   static const char kSubtitle[] = "State";
1210   ClockRate(timestamp, evt.name(), kSubtitle, evt.state());
1211 }
1212 
ParseClockDisable(int64_t timestamp,ConstBytes blob)1213 void FtraceParser::ParseClockDisable(int64_t timestamp, ConstBytes blob) {
1214   protos::pbzero::ClockDisableFtraceEvent::Decoder evt(blob.data, blob.size);
1215   static const char kSubtitle[] = "State";
1216   ClockRate(timestamp, evt.name(), kSubtitle, evt.state());
1217 }
1218 
ClockRate(int64_t timestamp,base::StringView clock_name,base::StringView subtitle,uint64_t rate)1219 void FtraceParser::ClockRate(int64_t timestamp,
1220                              base::StringView clock_name,
1221                              base::StringView subtitle,
1222                              uint64_t rate) {
1223   char counter_name[255];
1224   snprintf(counter_name, sizeof(counter_name), "%.*s %.*s",
1225            int(clock_name.size()), clock_name.data(), int(subtitle.size()),
1226            subtitle.data());
1227   StringId name = context_->storage->InternString(counter_name);
1228   TrackId track = context_->track_tracker->InternGlobalCounterTrack(name);
1229   context_->event_tracker->PushCounter(timestamp, static_cast<double>(rate),
1230                                        track);
1231 }
1232 
ParseScmCallStart(int64_t timestamp,uint32_t pid,ConstBytes blob)1233 void FtraceParser::ParseScmCallStart(int64_t timestamp,
1234                                      uint32_t pid,
1235                                      ConstBytes blob) {
1236   UniqueTid utid = context_->process_tracker->GetOrCreateThread(pid);
1237   TrackId track_id = context_->track_tracker->InternThreadTrack(utid);
1238   protos::pbzero::ScmCallStartFtraceEvent::Decoder evt(blob.data, blob.size);
1239 
1240   char str[64];
1241   sprintf(str, "scm id=%#" PRIx64, evt.x0());
1242   StringId name_id = context_->storage->InternString(str);
1243   context_->slice_tracker->Begin(timestamp, track_id, kNullStringId, name_id);
1244 }
1245 
ParseScmCallEnd(int64_t timestamp,uint32_t pid,ConstBytes blob)1246 void FtraceParser::ParseScmCallEnd(int64_t timestamp,
1247                                    uint32_t pid,
1248                                    ConstBytes blob) {
1249   protos::pbzero::ScmCallEndFtraceEvent::Decoder evt(blob.data, blob.size);
1250   UniqueTid utid = context_->process_tracker->GetOrCreateThread(pid);
1251   TrackId track_id = context_->track_tracker->InternThreadTrack(utid);
1252   context_->slice_tracker->End(timestamp, track_id);
1253 }
1254 
ParseWorkqueueExecuteStart(int64_t timestamp,uint32_t pid,ConstBytes blob,PacketSequenceStateGeneration * seq_state)1255 void FtraceParser::ParseWorkqueueExecuteStart(
1256     int64_t timestamp,
1257     uint32_t pid,
1258     ConstBytes blob,
1259     PacketSequenceStateGeneration* seq_state) {
1260   protos::pbzero::WorkqueueExecuteStartFtraceEvent::Decoder evt(blob.data,
1261                                                                 blob.size);
1262 
1263   auto* interned_string = seq_state->LookupInternedMessage<
1264       protos::pbzero::InternedData::kKernelSymbolsFieldNumber,
1265       protos::pbzero::InternedString>(static_cast<uint32_t>(evt.function()));
1266   StringId name_id;
1267   if (interned_string) {
1268     protozero::ConstBytes str = interned_string->str();
1269     name_id = context_->storage->InternString(
1270         base::StringView(reinterpret_cast<const char*>(str.data), str.size));
1271   } else {
1272     char slice_name[255];
1273     snprintf(slice_name, base::ArraySize(slice_name), "%#" PRIx64,
1274              evt.function());
1275     name_id = context_->storage->InternString(base::StringView(slice_name));
1276   }
1277 
1278   UniqueTid utid = context_->process_tracker->GetOrCreateThread(pid);
1279   TrackId track = context_->track_tracker->InternThreadTrack(utid);
1280   context_->slice_tracker->Begin(timestamp, track, workqueue_id_, name_id);
1281 }
1282 
ParseWorkqueueExecuteEnd(int64_t timestamp,uint32_t pid,ConstBytes blob)1283 void FtraceParser::ParseWorkqueueExecuteEnd(int64_t timestamp,
1284                                             uint32_t pid,
1285                                             ConstBytes blob) {
1286   protos::pbzero::WorkqueueExecuteEndFtraceEvent::Decoder evt(blob.data,
1287                                                               blob.size);
1288   UniqueTid utid = context_->process_tracker->GetOrCreateThread(pid);
1289   TrackId track = context_->track_tracker->InternThreadTrack(utid);
1290   context_->slice_tracker->End(timestamp, track, workqueue_id_);
1291 }
1292 
ParseIrqHandlerEntry(uint32_t cpu,int64_t timestamp,protozero::ConstBytes blob)1293 void FtraceParser::ParseIrqHandlerEntry(uint32_t cpu,
1294                                         int64_t timestamp,
1295                                         protozero::ConstBytes blob) {
1296   protos::pbzero::IrqHandlerEntryFtraceEvent::Decoder evt(blob.data, blob.size);
1297   char track_name[255];
1298   snprintf(track_name, sizeof(track_name), "Irq Cpu %d", cpu);
1299   StringId track_name_id = context_->storage->InternString(track_name);
1300   char slice_name[255];
1301   base::StringView irq_name = evt.name();
1302   snprintf(slice_name, sizeof(slice_name), "IRQ (%.*s)", int(irq_name.size()),
1303            irq_name.data());
1304   StringId slice_name_id = context_->storage->InternString(slice_name);
1305   TrackId track = context_->track_tracker->InternCpuTrack(track_name_id, cpu);
1306   context_->slice_tracker->Begin(timestamp, track, irq_id_, slice_name_id);
1307 }
1308 
ParseIrqHandlerExit(uint32_t cpu,int64_t timestamp,protozero::ConstBytes blob)1309 void FtraceParser::ParseIrqHandlerExit(uint32_t cpu,
1310                                        int64_t timestamp,
1311                                        protozero::ConstBytes blob) {
1312   protos::pbzero::IrqHandlerExitFtraceEvent::Decoder evt(blob.data, blob.size);
1313   char track_name[255];
1314   snprintf(track_name, sizeof(track_name), "Irq Cpu %d", cpu);
1315   StringId track_name_id = context_->storage->InternString(track_name);
1316   TrackId track = context_->track_tracker->InternCpuTrack(track_name_id, cpu);
1317   char status[255];
1318   snprintf(status, sizeof(status), "%s",
1319            evt.ret() == 1 ? "handled" : "unhandled");
1320   StringId status_id = context_->storage->InternString(status);
1321   auto args_inserter = [this,
1322                         &status_id](ArgsTracker::BoundInserter* inserter) {
1323     inserter->AddArg(ret_arg_id_, Variadic::String(status_id));
1324   };
1325   context_->slice_tracker->End(timestamp, track, irq_id_, {}, args_inserter);
1326 }
1327 
ParseSoftIrqEntry(uint32_t cpu,int64_t timestamp,protozero::ConstBytes blob)1328 void FtraceParser::ParseSoftIrqEntry(uint32_t cpu,
1329                                      int64_t timestamp,
1330                                      protozero::ConstBytes blob) {
1331   protos::pbzero::SoftirqEntryFtraceEvent::Decoder evt(blob.data, blob.size);
1332   char track_name[255];
1333   snprintf(track_name, sizeof(track_name), "SoftIrq Cpu %d", cpu);
1334   StringId track_name_id = context_->storage->InternString(track_name);
1335   auto num_actions = sizeof(kActionNames) / sizeof(*kActionNames);
1336   if (evt.vec() >= num_actions) {
1337     PERFETTO_DFATAL("No action name at index %d for softirq event.", evt.vec());
1338     return;
1339   }
1340   base::StringView slice_name = kActionNames[evt.vec()];
1341   StringId slice_name_id = context_->storage->InternString(slice_name);
1342   TrackId track = context_->track_tracker->InternCpuTrack(track_name_id, cpu);
1343   context_->slice_tracker->Begin(timestamp, track, irq_id_, slice_name_id);
1344 }
1345 
ParseSoftIrqExit(uint32_t cpu,int64_t timestamp,protozero::ConstBytes blob)1346 void FtraceParser::ParseSoftIrqExit(uint32_t cpu,
1347                                     int64_t timestamp,
1348                                     protozero::ConstBytes blob) {
1349   protos::pbzero::SoftirqExitFtraceEvent::Decoder evt(blob.data, blob.size);
1350   char track_name[255];
1351   snprintf(track_name, sizeof(track_name), "SoftIrq Cpu %d", cpu);
1352   StringId track_name_id = context_->storage->InternString(track_name);
1353   TrackId track = context_->track_tracker->InternCpuTrack(track_name_id, cpu);
1354   auto vec = evt.vec();
1355   auto args_inserter = [this, vec](ArgsTracker::BoundInserter* inserter) {
1356     inserter->AddArg(vec_arg_id_, Variadic::Integer(vec));
1357   };
1358   context_->slice_tracker->End(timestamp, track, irq_id_, {}, args_inserter);
1359 }
1360 
ParseGpuMemTotal(int64_t timestamp,protozero::ConstBytes data)1361 void FtraceParser::ParseGpuMemTotal(int64_t timestamp,
1362                                     protozero::ConstBytes data) {
1363   protos::pbzero::GpuMemTotalFtraceEvent::Decoder gpu_mem_total(data.data,
1364                                                                 data.size);
1365 
1366   TrackId track = kInvalidTrackId;
1367   const uint32_t pid = gpu_mem_total.pid();
1368   if (pid == 0) {
1369     // Pid 0 is used to indicate the global total
1370     track = context_->track_tracker->InternGlobalCounterTrack(
1371         gpu_mem_total_name_id_, gpu_mem_total_unit_id_,
1372         gpu_mem_total_global_desc_id_);
1373   } else {
1374     // Process emitting the packet can be different from the pid in the event.
1375     UniqueTid utid = context_->process_tracker->UpdateThread(pid, pid);
1376     UniquePid upid = context_->storage->thread_table().upid()[utid].value_or(0);
1377     track = context_->track_tracker->InternProcessCounterTrack(
1378         gpu_mem_total_name_id_, upid, gpu_mem_total_unit_id_,
1379         gpu_mem_total_proc_desc_id_);
1380   }
1381   context_->event_tracker->PushCounter(
1382       timestamp, static_cast<double>(gpu_mem_total.size()), track);
1383 }
1384 
ParseThermalTemperature(int64_t timestamp,protozero::ConstBytes blob)1385 void FtraceParser::ParseThermalTemperature(int64_t timestamp,
1386                                            protozero::ConstBytes blob) {
1387   protos::pbzero::ThermalTemperatureFtraceEvent::Decoder evt(blob.data,
1388                                                              blob.size);
1389   char counter_name[255];
1390   base::StringView thermal_zone = evt.thermal_zone();
1391   snprintf(counter_name, sizeof(counter_name), "%.*s Temperature",
1392            int(thermal_zone.size()), thermal_zone.data());
1393   StringId name = context_->storage->InternString(counter_name);
1394   TrackId track = context_->track_tracker->InternGlobalCounterTrack(name);
1395   context_->event_tracker->PushCounter(timestamp, evt.temp(), track);
1396 }
1397 
ParseCdevUpdate(int64_t timestamp,protozero::ConstBytes blob)1398 void FtraceParser::ParseCdevUpdate(int64_t timestamp,
1399                                    protozero::ConstBytes blob) {
1400   protos::pbzero::CdevUpdateFtraceEvent::Decoder evt(blob.data, blob.size);
1401   char counter_name[255];
1402   base::StringView type = evt.type();
1403   snprintf(counter_name, sizeof(counter_name), "%.*s Cooling Device",
1404            int(type.size()), type.data());
1405   StringId name = context_->storage->InternString(counter_name);
1406   TrackId track = context_->track_tracker->InternGlobalCounterTrack(name);
1407   context_->event_tracker->PushCounter(
1408       timestamp, static_cast<double>(evt.target()), track);
1409 }
1410 
ParseSchedBlockedReason(int64_t timestamp,protozero::ConstBytes blob,PacketSequenceStateGeneration * seq_state)1411 void FtraceParser::ParseSchedBlockedReason(
1412     int64_t timestamp,
1413     protozero::ConstBytes blob,
1414     PacketSequenceStateGeneration* seq_state) {
1415   protos::pbzero::SchedBlockedReasonFtraceEvent::Decoder evt(blob);
1416   uint32_t pid = static_cast<uint32_t>(evt.pid());
1417   auto utid = context_->process_tracker->GetOrCreateThread(pid);
1418   InstantId id = context_->event_tracker->PushInstant(
1419       timestamp, sched_blocked_reason_id_, utid, RefType::kRefUtid, false);
1420 
1421   auto inserter = context_->args_tracker->AddArgsTo(id);
1422   inserter.AddArg(io_wait_id_, Variadic::Boolean(evt.io_wait()));
1423 
1424   uint32_t caller_iid = static_cast<uint32_t>(evt.caller());
1425   auto* interned_string = seq_state->LookupInternedMessage<
1426       protos::pbzero::InternedData::kKernelSymbolsFieldNumber,
1427       protos::pbzero::InternedString>(caller_iid);
1428 
1429   if (interned_string) {
1430     protozero::ConstBytes str = interned_string->str();
1431     StringId str_id = context_->storage->InternString(
1432         base::StringView(reinterpret_cast<const char*>(str.data), str.size));
1433     inserter.AddArg(function_id_, Variadic::String(str_id));
1434   }
1435 }
1436 
ParseFastRpcDmaStat(int64_t timestamp,uint32_t pid,protozero::ConstBytes blob)1437 void FtraceParser::ParseFastRpcDmaStat(int64_t timestamp,
1438                                        uint32_t pid,
1439                                        protozero::ConstBytes blob) {
1440   protos::pbzero::FastrpcDmaStatFtraceEvent::Decoder evt(blob.data, blob.size);
1441 
1442   StringId name;
1443   if (0 <= evt.cid() && evt.cid() < static_cast<int32_t>(kFastRpcCounterSize)) {
1444     name = fast_rpc_delta_names_[static_cast<size_t>(evt.cid())];
1445   } else {
1446     char str[64];
1447     snprintf(str, sizeof(str), "mem.fastrpc[%" PRId32 "]", evt.cid());
1448     name = context_->storage->InternString(str);
1449   }
1450 
1451   StringId total_name;
1452   if (0 <= evt.cid() && evt.cid() < static_cast<int32_t>(kFastRpcCounterSize)) {
1453     total_name = fast_rpc_total_names_[static_cast<size_t>(evt.cid())];
1454   } else {
1455     char str[64];
1456     snprintf(str, sizeof(str), "mem.fastrpc[%" PRId32 "]", evt.cid());
1457     total_name = context_->storage->InternString(str);
1458   }
1459 
1460   // Push the global counter.
1461   TrackId track = context_->track_tracker->InternGlobalCounterTrack(total_name);
1462   context_->event_tracker->PushCounter(
1463       timestamp, static_cast<double>(evt.total_allocated()), track);
1464 
1465   // Push the change counter.
1466   // TODO(b/121331269): these should really be instant events.
1467   UniqueTid utid = context_->process_tracker->GetOrCreateThread(pid);
1468   TrackId delta_track =
1469       context_->track_tracker->InternThreadCounterTrack(name, utid);
1470   context_->event_tracker->PushCounter(
1471       timestamp, static_cast<double>(evt.len()), delta_track);
1472 }
1473 
ParseCpuhpPause(int64_t,uint32_t,protozero::ConstBytes blob)1474 void FtraceParser::ParseCpuhpPause(int64_t,
1475                                    uint32_t,
1476                                    protozero::ConstBytes blob) {
1477   protos::pbzero::CpuhpPauseFtraceEvent::Decoder evt(blob.data, blob.size);
1478   // TODO(b/183110813): Parse and visualize this event.
1479 }
1480 
1481 }  // namespace trace_processor
1482 }  // namespace perfetto
1483