xref: /aosp_15_r20/external/perfetto/src/trace_processor/perfetto_sql/intrinsics/functions/to_ftrace.cc (revision 6dbdd20afdafa5e3ca9b8809fa73465d530080dc)
1 /*
2  * Copyright (C) 2023 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/perfetto_sql/intrinsics/functions/to_ftrace.h"
18 
19 #include <cstddef>
20 #include <cstdint>
21 #include <cstdlib>
22 #include <functional>
23 #include <optional>
24 #include <vector>
25 
26 #include "perfetto/base/logging.h"
27 #include "perfetto/base/status.h"
28 #include "perfetto/ext/base/string_view.h"
29 #include "perfetto/ext/base/string_writer.h"
30 #include "perfetto/public/compiler.h"
31 #include "perfetto/trace_processor/basic_types.h"
32 #include "src/trace_processor/containers/null_term_string_view.h"
33 #include "src/trace_processor/db/column/types.h"
34 #include "src/trace_processor/importers/common/system_info_tracker.h"
35 #include "src/trace_processor/importers/ftrace/ftrace_descriptors.h"
36 #include "src/trace_processor/sqlite/bindings/sqlite_type.h"
37 #include "src/trace_processor/sqlite/bindings/sqlite_value.h"
38 #include "src/trace_processor/storage/trace_storage.h"
39 #include "src/trace_processor/tables/metadata_tables_py.h"
40 #include "src/trace_processor/types/gfp_flags.h"
41 #include "src/trace_processor/types/softirq_action.h"
42 #include "src/trace_processor/types/task_state.h"
43 #include "src/trace_processor/types/trace_processor_context.h"
44 #include "src/trace_processor/types/variadic.h"
45 
46 #include "protos/perfetto/trace/ftrace/binder.pbzero.h"
47 #include "protos/perfetto/trace/ftrace/cgroup.pbzero.h"
48 #include "protos/perfetto/trace/ftrace/clk.pbzero.h"
49 #include "protos/perfetto/trace/ftrace/dpu.pbzero.h"
50 #include "protos/perfetto/trace/ftrace/filemap.pbzero.h"
51 #include "protos/perfetto/trace/ftrace/ftrace.pbzero.h"
52 #include "protos/perfetto/trace/ftrace/ftrace_event.pbzero.h"
53 #include "protos/perfetto/trace/ftrace/g2d.pbzero.h"
54 #include "protos/perfetto/trace/ftrace/irq.pbzero.h"
55 #include "protos/perfetto/trace/ftrace/mdss.pbzero.h"
56 #include "protos/perfetto/trace/ftrace/panel.pbzero.h"
57 #include "protos/perfetto/trace/ftrace/power.pbzero.h"
58 #include "protos/perfetto/trace/ftrace/samsung.pbzero.h"
59 #include "protos/perfetto/trace/ftrace/sched.pbzero.h"
60 #include "protos/perfetto/trace/ftrace/workqueue.pbzero.h"
61 #include "src/trace_processor/types/version_number.h"
62 
63 namespace perfetto::trace_processor {
64 
65 namespace {
66 
67 struct FtraceTime {
FtraceTimeperfetto::trace_processor::__anon346618c20111::FtraceTime68   FtraceTime(int64_t ns)
69       : secs(ns / 1000000000LL), micros((ns - secs * 1000000000LL) / 1000) {}
70 
71   const int64_t secs;
72   const int64_t micros;
73 };
74 
GetArgQuery(const tables::ArgTable & table,uint32_t arg_set_id)75 Query GetArgQuery(const tables::ArgTable& table, uint32_t arg_set_id) {
76   Query q;
77   q.constraints = {table.arg_set_id().eq(arg_set_id)};
78   return q;
79 }
80 
81 class ArgsSerializer {
82  public:
83   ArgsSerializer(TraceProcessorContext*,
84                  ArgSetId arg_set_id,
85                  NullTermStringView event_name,
86                  std::vector<std::optional<uint32_t>>* field_id_to_arg_index,
87                  base::StringWriter*);
88 
89   void SerializeArgs();
90 
91  private:
92   using ValueWriter = std::function<void(const Variadic&)>;
93   using SerializerValueWriter = void (ArgsSerializer::*)(const Variadic&);
94 
95   // Arg writing functions.
WriteArgForField(uint32_t field_id,const ValueWriter & writer)96   void WriteArgForField(uint32_t field_id, const ValueWriter& writer) {
97     std::optional<uint32_t> row = FieldIdToRow(field_id);
98     if (!row)
99       return;
100     WriteArgAtRow(*row, writer);
101   }
WriteArgForField(uint32_t field_id,base::StringView key,const ValueWriter & writer)102   void WriteArgForField(uint32_t field_id,
103                         base::StringView key,
104                         const ValueWriter& writer) {
105     std::optional<uint32_t> row = FieldIdToRow(field_id);
106     if (!row)
107       return;
108     WriteArg(key, storage_->GetArgValue(*row), writer);
109   }
WriteArgAtRow(uint32_t arg_row,const ValueWriter & writer)110   void WriteArgAtRow(uint32_t arg_row, const ValueWriter& writer) {
111     const auto& args = storage_->arg_table();
112     const auto& key = storage_->GetString(args.key()[arg_row]);
113     WriteArg(key, storage_->GetArgValue(arg_row), writer);
114   }
115   void WriteArg(base::StringView key,
116                 Variadic value,
117                 const ValueWriter& writer);
118 
119   // Value writing functions.
WriteValueForField(uint32_t field_id,const ValueWriter & writer)120   void WriteValueForField(uint32_t field_id, const ValueWriter& writer) {
121     std::optional<uint32_t> row = FieldIdToRow(field_id);
122     if (!row)
123       return;
124     writer(storage_->GetArgValue(*row));
125   }
WriteKernelFnValue(const Variadic & value)126   void WriteKernelFnValue(const Variadic& value) {
127     if (value.type == Variadic::Type::kUint) {
128       writer_->AppendHexInt(value.uint_value);
129     } else if (value.type == Variadic::Type::kString) {
130       WriteValue(value);
131     } else {
132       PERFETTO_DFATAL("Invalid field type %d", static_cast<int>(value.type));
133     }
134   }
135   void WriteValue(const Variadic&);
136 
137   // The default value writer which uses the |WriteValue| function.
DVW()138   ValueWriter DVW() { return Wrap(&ArgsSerializer::WriteValue); }
Wrap(SerializerValueWriter writer)139   ValueWriter Wrap(SerializerValueWriter writer) {
140     return [this, writer](const Variadic& v) { (this->*writer)(v); };
141   }
142 
143   // Converts a field id to a row in the args table.
FieldIdToRow(uint32_t field_id)144   std::optional<uint32_t> FieldIdToRow(uint32_t field_id) {
145     PERFETTO_DCHECK(field_id > 0);
146     PERFETTO_DCHECK(field_id < field_id_to_arg_index_->size());
147     std::optional<uint32_t> index_in_arg_set =
148         (*field_id_to_arg_index_)[field_id];
149     return index_in_arg_set.has_value()
150                ? std::make_optional(start_row_ + *index_in_arg_set)
151                : std::nullopt;
152   }
153 
154   const TraceStorage* storage_ = nullptr;
155   TraceProcessorContext* context_ = nullptr;
156   NullTermStringView event_name_;
157   std::vector<std::optional<uint32_t>>* field_id_to_arg_index_;
158 
159   tables::ArgTable::ConstIterator it_;
160   uint32_t start_row_ = 0;
161 
162   base::StringWriter* writer_ = nullptr;
163 };
164 
ArgsSerializer(TraceProcessorContext * context,ArgSetId arg_set_id,NullTermStringView event_name,std::vector<std::optional<uint32_t>> * field_id_to_arg_index,base::StringWriter * writer)165 ArgsSerializer::ArgsSerializer(
166     TraceProcessorContext* context,
167     ArgSetId arg_set_id,
168     NullTermStringView event_name,
169     std::vector<std::optional<uint32_t>>* field_id_to_arg_index,
170     base::StringWriter* writer)
171     : storage_(context->storage.get()),
172       context_(context),
173       event_name_(event_name),
174       field_id_to_arg_index_(field_id_to_arg_index),
175       it_(context->storage->arg_table().FilterToIterator(
176           GetArgQuery(context->storage->arg_table(), arg_set_id))),
177       writer_(writer) {
178   // We assume that the row map is a contiguous range (which is always the case
179   // because arg_set_ids are contiguous by definition).
180   start_row_ = it_ ? it_.row_number().row_number() : 0;
181 
182   // If the vector already has entries, we've previously cached the mapping
183   // from field id to arg index.
184   if (!field_id_to_arg_index->empty())
185     return;
186 
187   auto* descriptor = GetMessageDescriptorForName(event_name);
188   if (!descriptor) {
189     // If we don't have a descriptor, this event must be a generic ftrace event.
190     // As we can't possibly have any special handling for generic events, just
191     // add a row to the vector (for the invalid field id 0) to remove future
192     // lookups for this event name.
193     field_id_to_arg_index->resize(1);
194     return;
195   }
196 
197   // If we have a descriptor, try and create the mapping from proto field id
198   // to the index in the arg set.
199   size_t max = descriptor->max_field_id;
200 
201   // We need to reserve an index for the invalid field id 0.
202   field_id_to_arg_index_->resize(max + 1);
203 
204   // Go through each field id and find the entry in the args table for that
205   auto it = storage_->arg_table().FilterToIterator(
206       GetArgQuery(context->storage->arg_table(), arg_set_id));
207   for (uint32_t r = 0; it; ++it, ++r) {
208     for (uint32_t i = 1; i <= max; ++i) {
209       base::StringView key = context->storage->GetString(it.key());
210       if (key == descriptor->fields[i].name) {
211         (*field_id_to_arg_index)[i] = r;
212         break;
213       }
214     }
215   }
216 }
217 
SerializeArgs()218 void ArgsSerializer::SerializeArgs() {
219   if (!it_)
220     return;
221 
222   if (event_name_ == "sched_switch") {
223     using SS = protos::pbzero::SchedSwitchFtraceEvent;
224 
225     WriteArgForField(SS::kPrevCommFieldNumber, DVW());
226     WriteArgForField(SS::kPrevPidFieldNumber, DVW());
227     WriteArgForField(SS::kPrevPrioFieldNumber, DVW());
228     WriteArgForField(SS::kPrevStateFieldNumber, [this](const Variadic& value) {
229       PERFETTO_DCHECK(value.type == Variadic::Type::kInt);
230       auto state = static_cast<uint16_t>(value.int_value);
231       std::optional<VersionNumber> kernel_version =
232           SystemInfoTracker::GetOrCreate(context_)->GetKernelVersion();
233       writer_->AppendString(
234           ftrace_utils::TaskState::FromRawPrevState(state, kernel_version)
235               .ToString('|')
236               .data());
237     });
238     writer_->AppendLiteral(" ==>");
239     WriteArgForField(SS::kNextCommFieldNumber, DVW());
240     WriteArgForField(SS::kNextPidFieldNumber, DVW());
241     WriteArgForField(SS::kNextPrioFieldNumber, DVW());
242     return;
243   } else if (event_name_ == "sched_wakeup") {
244     using SW = protos::pbzero::SchedWakeupFtraceEvent;
245     WriteArgForField(SW::kCommFieldNumber, DVW());
246     WriteArgForField(SW::kPidFieldNumber, DVW());
247     WriteArgForField(SW::kPrioFieldNumber, DVW());
248     WriteArgForField(SW::kTargetCpuFieldNumber, [this](const Variadic& value) {
249       PERFETTO_DCHECK(value.type == Variadic::Type::kInt);
250       writer_->AppendPaddedInt<'0', 3>(value.int_value);
251     });
252     return;
253   } else if (event_name_ == "clock_set_rate") {
254     using CSR = protos::pbzero::ClockSetRateFtraceEvent;
255     writer_->AppendLiteral(" ");
256     WriteValueForField(CSR::kNameFieldNumber, DVW());
257     WriteArgForField(CSR::kStateFieldNumber, DVW());
258     WriteArgForField(CSR::kCpuIdFieldNumber, DVW());
259     return;
260   } else if (event_name_ == "clk_set_rate") {
261     using CSR = protos::pbzero::ClkSetRateFtraceEvent;
262     writer_->AppendLiteral(" ");
263     WriteValueForField(CSR::kNameFieldNumber, DVW());
264     writer_->AppendLiteral(" ");
265     WriteValueForField(CSR::kRateFieldNumber, DVW());
266     return;
267   } else if (event_name_ == "clock_enable") {
268     using CE = protos::pbzero::ClockEnableFtraceEvent;
269     WriteValueForField(CE::kNameFieldNumber, DVW());
270     WriteArgForField(CE::kStateFieldNumber, DVW());
271     WriteArgForField(CE::kCpuIdFieldNumber, DVW());
272     return;
273   } else if (event_name_ == "clock_disable") {
274     using CD = protos::pbzero::ClockDisableFtraceEvent;
275     WriteValueForField(CD::kNameFieldNumber, DVW());
276     WriteArgForField(CD::kStateFieldNumber, DVW());
277     WriteArgForField(CD::kCpuIdFieldNumber, DVW());
278     return;
279   } else if (event_name_ == "binder_transaction") {
280     using BT = protos::pbzero::BinderTransactionFtraceEvent;
281     writer_->AppendString(" transaction=");
282     WriteValueForField(BT::kDebugIdFieldNumber, [this](const Variadic& value) {
283       PERFETTO_DCHECK(value.type == Variadic::Type::kInt);
284       writer_->AppendUnsignedInt(static_cast<uint32_t>(value.int_value));
285     });
286 
287     writer_->AppendString(" dest_node=");
288     WriteValueForField(
289         BT::kTargetNodeFieldNumber, [this](const Variadic& value) {
290           PERFETTO_DCHECK(value.type == Variadic::Type::kInt);
291           writer_->AppendUnsignedInt(static_cast<uint32_t>(value.int_value));
292         });
293 
294     writer_->AppendString(" dest_proc=");
295     WriteValueForField(BT::kToProcFieldNumber, DVW());
296 
297     writer_->AppendString(" dest_thread=");
298     WriteValueForField(BT::kToThreadFieldNumber, DVW());
299 
300     writer_->AppendString(" reply=");
301     WriteValueForField(BT::kReplyFieldNumber, DVW());
302 
303     writer_->AppendString(" flags=0x");
304     WriteValueForField(BT::kFlagsFieldNumber, [this](const Variadic& value) {
305       PERFETTO_DCHECK(value.type == Variadic::Type::kUint);
306       writer_->AppendHexInt(value.uint_value);
307     });
308 
309     writer_->AppendString(" code=0x");
310     WriteValueForField(BT::kCodeFieldNumber, [this](const Variadic& value) {
311       PERFETTO_DCHECK(value.type == Variadic::Type::kUint);
312       writer_->AppendHexInt(value.uint_value);
313     });
314     return;
315   } else if (event_name_ == "binder_transaction_alloc_buf") {
316     using BTAB = protos::pbzero::BinderTransactionAllocBufFtraceEvent;
317     writer_->AppendString(" transaction=");
318     WriteValueForField(
319         BTAB::kDebugIdFieldNumber, [this](const Variadic& value) {
320           PERFETTO_DCHECK(value.type == Variadic::Type::kInt);
321           writer_->AppendUnsignedInt(static_cast<uint32_t>(value.int_value));
322         });
323     WriteArgForField(BTAB::kDataSizeFieldNumber, DVW());
324     WriteArgForField(BTAB::kOffsetsSizeFieldNumber, DVW());
325     return;
326   } else if (event_name_ == "binder_transaction_received") {
327     using BTR = protos::pbzero::BinderTransactionReceivedFtraceEvent;
328     writer_->AppendString(" transaction=");
329     WriteValueForField(BTR::kDebugIdFieldNumber, [this](const Variadic& value) {
330       PERFETTO_DCHECK(value.type == Variadic::Type::kInt);
331       writer_->AppendUnsignedInt(static_cast<uint32_t>(value.int_value));
332     });
333     return;
334   } else if (event_name_ == "mm_filemap_add_to_page_cache") {
335     using MFA = protos::pbzero::MmFilemapAddToPageCacheFtraceEvent;
336     writer_->AppendString(" dev ");
337     WriteValueForField(MFA::kSDevFieldNumber, [this](const Variadic& value) {
338       PERFETTO_DCHECK(value.type == Variadic::Type::kUint);
339       writer_->AppendUnsignedInt(value.uint_value >> 20);
340     });
341     writer_->AppendString(":");
342     WriteValueForField(MFA::kSDevFieldNumber, [this](const Variadic& value) {
343       PERFETTO_DCHECK(value.type == Variadic::Type::kUint);
344       writer_->AppendUnsignedInt(value.uint_value & ((1 << 20) - 1));
345     });
346     writer_->AppendString(" ino ");
347     WriteValueForField(MFA::kIInoFieldNumber, [this](const Variadic& value) {
348       PERFETTO_DCHECK(value.type == Variadic::Type::kUint);
349       writer_->AppendHexInt(value.uint_value);
350     });
351     writer_->AppendString(" page=0000000000000000");
352     writer_->AppendString(" pfn=");
353     WriteValueForField(MFA::kPfnFieldNumber, DVW());
354     writer_->AppendString(" ofs=");
355     WriteValueForField(MFA::kIndexFieldNumber, [this](const Variadic& value) {
356       PERFETTO_DCHECK(value.type == Variadic::Type::kUint);
357       writer_->AppendUnsignedInt(value.uint_value << 12);
358     });
359     return;
360   } else if (event_name_ == "print") {
361     using P = protos::pbzero::PrintFtraceEvent;
362 
363     writer_->AppendChar(' ');
364     WriteValueForField(P::kBufFieldNumber, [this](const Variadic& value) {
365       PERFETTO_DCHECK(value.type == Variadic::Type::kString);
366 
367       NullTermStringView str = storage_->GetString(value.string_value);
368       // If the last character is a newline in a print, just drop it.
369       auto chars_to_print = !str.empty() && str.c_str()[str.size() - 1] == '\n'
370                                 ? str.size() - 1
371                                 : str.size();
372       writer_->AppendString(str.c_str(), chars_to_print);
373     });
374     return;
375   } else if (event_name_ == "sched_blocked_reason") {
376     using SBR = protos::pbzero::SchedBlockedReasonFtraceEvent;
377     WriteArgForField(SBR::kPidFieldNumber, DVW());
378     WriteArgForField(SBR::kIoWaitFieldNumber, DVW());
379     WriteArgForField(SBR::kCallerFieldNumber,
380                      Wrap(&ArgsSerializer::WriteKernelFnValue));
381     return;
382   } else if (event_name_ == "workqueue_activate_work") {
383     using WAW = protos::pbzero::WorkqueueActivateWorkFtraceEvent;
384     writer_->AppendString(" work struct ");
385     WriteValueForField(WAW::kWorkFieldNumber, [this](const Variadic& value) {
386       PERFETTO_DCHECK(value.type == Variadic::Type::kUint);
387       writer_->AppendHexInt(value.uint_value);
388     });
389     return;
390   } else if (event_name_ == "workqueue_execute_start") {
391     using WES = protos::pbzero::WorkqueueExecuteStartFtraceEvent;
392     writer_->AppendString(" work struct ");
393     WriteValueForField(WES::kWorkFieldNumber, [this](const Variadic& value) {
394       PERFETTO_DCHECK(value.type == Variadic::Type::kUint);
395       writer_->AppendHexInt(value.uint_value);
396     });
397     writer_->AppendString(": function ");
398     WriteValueForField(WES::kFunctionFieldNumber,
399                        Wrap(&ArgsSerializer::WriteKernelFnValue));
400     return;
401   } else if (event_name_ == "workqueue_execute_end") {
402     using WE = protos::pbzero::WorkqueueExecuteEndFtraceEvent;
403     writer_->AppendString(" work struct ");
404     WriteValueForField(WE::kWorkFieldNumber, [this](const Variadic& value) {
405       PERFETTO_DCHECK(value.type == Variadic::Type::kUint);
406       writer_->AppendHexInt(value.uint_value);
407     });
408     return;
409   } else if (event_name_ == "workqueue_queue_work") {
410     using WQW = protos::pbzero::WorkqueueQueueWorkFtraceEvent;
411     writer_->AppendString(" work struct=");
412     WriteValueForField(WQW::kWorkFieldNumber, [this](const Variadic& value) {
413       PERFETTO_DCHECK(value.type == Variadic::Type::kUint);
414       writer_->AppendHexInt(value.uint_value);
415     });
416     WriteArgForField(WQW::kFunctionFieldNumber,
417                      Wrap(&ArgsSerializer::WriteKernelFnValue));
418     WriteArgForField(WQW::kWorkqueueFieldNumber, [this](const Variadic& value) {
419       PERFETTO_DCHECK(value.type == Variadic::Type::kUint);
420       writer_->AppendHexInt(value.uint_value);
421     });
422     WriteValueForField(WQW::kReqCpuFieldNumber, DVW());
423     WriteValueForField(WQW::kCpuFieldNumber, DVW());
424     return;
425   } else if (event_name_ == "irq_handler_entry") {
426     using IEN = protos::pbzero::IrqHandlerEntryFtraceEvent;
427     WriteArgForField(IEN::kIrqFieldNumber, DVW());
428     WriteArgForField(IEN::kNameFieldNumber, DVW());
429     return;
430   } else if (event_name_ == "irq_handler_exit") {
431     using IEX = protos::pbzero::IrqHandlerExitFtraceEvent;
432     WriteArgForField(IEX::kIrqFieldNumber, DVW());
433     writer_->AppendString(" ret=");
434     WriteValueForField(IEX::kRetFieldNumber, [this](const Variadic& value) {
435       PERFETTO_DCHECK(value.type == Variadic::Type::kInt);
436       writer_->AppendString(value.int_value ? "handled" : "unhandled");
437     });
438     return;
439   } else if (event_name_ == "softirq_entry") {
440     using SIE = protos::pbzero::SoftirqEntryFtraceEvent;
441     WriteArgForField(SIE::kVecFieldNumber, DVW());
442     writer_->AppendString(" [action=");
443     WriteValueForField(SIE::kVecFieldNumber, [this](const Variadic& value) {
444       PERFETTO_DCHECK(value.type == Variadic::Type::kUint);
445       writer_->AppendString(kActionNames[value.uint_value]);
446     });
447     writer_->AppendString("]");
448     return;
449   } else if (event_name_ == "softirq_exit") {
450     using SIX = protos::pbzero::SoftirqExitFtraceEvent;
451     WriteArgForField(SIX::kVecFieldNumber, DVW());
452     writer_->AppendString(" [action=");
453     WriteValueForField(SIX::kVecFieldNumber, [this](const Variadic& value) {
454       PERFETTO_DCHECK(value.type == Variadic::Type::kUint);
455       writer_->AppendString(kActionNames[value.uint_value]);
456     });
457     writer_->AppendString("]");
458     return;
459   } else if (event_name_ == "tracing_mark_write") {
460     using TMW = protos::pbzero::TracingMarkWriteFtraceEvent;
461     WriteValueForField(TMW::kTraceBeginFieldNumber,
462                        [this](const Variadic& value) {
463                          PERFETTO_DCHECK(value.type == Variadic::Type::kUint);
464                          writer_->AppendChar(value.uint_value ? 'B' : 'E');
465                        });
466     writer_->AppendString("|");
467     WriteValueForField(TMW::kPidFieldNumber, DVW());
468     writer_->AppendString("|");
469     WriteValueForField(TMW::kTraceNameFieldNumber, DVW());
470     return;
471   } else if (event_name_ == "dpu_tracing_mark_write") {
472     using TMW = protos::pbzero::DpuTracingMarkWriteFtraceEvent;
473     WriteValueForField(TMW::kTypeFieldNumber, [this](const Variadic& value) {
474       PERFETTO_DCHECK(value.type == Variadic::Type::kUint);
475       writer_->AppendChar(static_cast<char>(value.uint_value));
476     });
477     writer_->AppendString("|");
478     WriteValueForField(TMW::kPidFieldNumber, DVW());
479     writer_->AppendString("|");
480     WriteValueForField(TMW::kNameFieldNumber, DVW());
481     writer_->AppendString("|");
482     WriteValueForField(TMW::kValueFieldNumber, DVW());
483     return;
484   } else if (event_name_ == "panel_write_generic") {
485     using TMW = protos::pbzero::PanelWriteGenericFtraceEvent;
486     WriteValueForField(TMW::kTypeFieldNumber, [this](const Variadic& value) {
487       PERFETTO_DCHECK(value.type == Variadic::Type::kUint);
488       writer_->AppendChar(static_cast<char>(value.uint_value));
489     });
490     writer_->AppendString("|");
491     WriteValueForField(TMW::kPidFieldNumber, DVW());
492     writer_->AppendString("|");
493     WriteValueForField(TMW::kNameFieldNumber, DVW());
494     writer_->AppendString("|");
495     WriteValueForField(TMW::kValueFieldNumber, DVW());
496     return;
497   } else if (event_name_ == "g2d_tracing_mark_write") {
498     using TMW = protos::pbzero::G2dTracingMarkWriteFtraceEvent;
499     WriteValueForField(TMW::kTypeFieldNumber, [this](const Variadic& value) {
500       PERFETTO_DCHECK(value.type == Variadic::Type::kUint);
501       writer_->AppendChar(static_cast<char>(value.uint_value));
502     });
503     writer_->AppendString("|");
504     WriteValueForField(TMW::kPidFieldNumber, DVW());
505     writer_->AppendString("|");
506     WriteValueForField(TMW::kNameFieldNumber, DVW());
507     writer_->AppendString("|");
508     WriteValueForField(TMW::kValueFieldNumber, DVW());
509     return;
510   } else if (event_name_ == "samsung_tracing_mark_write") {
511     using TMW = protos::pbzero::SamsungTracingMarkWriteFtraceEvent;
512     WriteValueForField(
513         TMW::kTraceTypeFieldNumber, [this](const Variadic& value) {
514           PERFETTO_DCHECK(value.type == Variadic::Type::kUint);
515           writer_->AppendChar(static_cast<char>(value.uint_value));
516         });
517     writer_->AppendString("|");
518     WriteValueForField(TMW::kPidFieldNumber, DVW());
519     writer_->AppendString("|");
520     WriteValueForField(TMW::kTraceNameFieldNumber, DVW());
521     writer_->AppendString("|");
522     WriteValueForField(TMW::kValueFieldNumber, DVW());
523     return;
524   } else if (event_name_ == "cgroup_attach_task") {
525     using CAT = protos::pbzero::CgroupAttachTaskFtraceEvent;
526     WriteArgForField(CAT::kDstRootFieldNumber, DVW());
527     WriteArgForField(CAT::kDstIdFieldNumber, DVW());
528     WriteArgForField(CAT::kCnameFieldNumber, "cgroup", DVW());
529     WriteArgForField(CAT::kDstLevelFieldNumber, DVW());
530     WriteArgForField(CAT::kDstPathFieldNumber, DVW());
531     WriteArgForField(CAT::kPidFieldNumber, DVW());
532     WriteArgForField(CAT::kCommFieldNumber, DVW());
533     return;
534   }
535   for (; it_; ++it_) {
536     WriteArgAtRow(it_.row_number().row_number(), DVW());
537   }
538 }
539 
WriteArg(base::StringView key,Variadic value,const ValueWriter & writer)540 void ArgsSerializer::WriteArg(base::StringView key,
541                               Variadic value,
542                               const ValueWriter& writer) {
543   writer_->AppendChar(' ');
544   writer_->AppendString(key.data(), key.size());
545   writer_->AppendChar('=');
546 
547   if (key == "gfp_flags") {
548     auto kernel_version =
549         SystemInfoTracker::GetOrCreate(context_)->GetKernelVersion();
550     WriteGfpFlag(value.uint_value, kernel_version, writer_);
551     return;
552   }
553   writer(value);
554 }
555 
WriteValue(const Variadic & value)556 void ArgsSerializer::WriteValue(const Variadic& value) {
557   switch (value.type) {
558     case Variadic::kInt:
559       writer_->AppendInt(value.int_value);
560       break;
561     case Variadic::kUint:
562       writer_->AppendUnsignedInt(value.uint_value);
563       break;
564     case Variadic::kString: {
565       const auto& str = storage_->GetString(value.string_value);
566       writer_->AppendString(str.c_str(), str.size());
567       break;
568     }
569     case Variadic::kReal:
570       writer_->AppendDouble(value.real_value);
571       break;
572     case Variadic::kPointer:
573       writer_->AppendUnsignedInt(value.pointer_value);
574       break;
575     case Variadic::kBool:
576       writer_->AppendBool(value.bool_value);
577       break;
578     case Variadic::kJson: {
579       const auto& str = storage_->GetString(value.json_value);
580       writer_->AppendString(str.c_str(), str.size());
581       break;
582     }
583     case Variadic::kNull:
584       writer_->AppendLiteral("[NULL]");
585       break;
586   }
587 }
588 
589 }  // namespace
590 
Run(Context * context,size_t argc,sqlite3_value ** argv,SqlValue & out,Destructors & destructors)591 base::Status ToFtrace::Run(Context* context,
592                            size_t argc,
593                            sqlite3_value** argv,
594                            SqlValue& out,
595                            Destructors& destructors) {
596   if (argc != 1 || sqlite::value::Type(argv[0]) != sqlite::Type::kInteger) {
597     return base::ErrStatus("Usage: to_ftrace(id)");
598   }
599   uint32_t row = static_cast<uint32_t>(sqlite3_value_int64(argv[0]));
600 
601   auto str = context->serializer.SerializeToString(row);
602   if (str.get() == nullptr) {
603     return base::ErrStatus("to_ftrace: Cannot serialize row id %u", row);
604   }
605 
606   out = SqlValue::String(str.release());
607   destructors.string_destructor = str.get_deleter();
608   return base::OkStatus();
609 }
610 
SystraceSerializer(TraceProcessorContext * context)611 SystraceSerializer::SystraceSerializer(TraceProcessorContext* context)
612     : context_(context) {
613   storage_ = context_->storage.get();
614 }
615 
SerializeToString(uint32_t raw_row)616 SystraceSerializer::ScopedCString SystraceSerializer::SerializeToString(
617     uint32_t raw_row) {
618   const auto& raw = storage_->raw_table();
619 
620   char line[4096];
621   base::StringWriter writer(line, sizeof(line));
622 
623   StringId event_name_id = raw.name()[raw_row];
624   NullTermStringView event_name = storage_->GetString(event_name_id);
625   if (event_name.StartsWith("chrome_event.") ||
626       event_name.StartsWith("track_event.")) {
627     return ScopedCString(nullptr, nullptr);
628   }
629 
630   SerializePrefix(raw_row, &writer);
631 
632   writer.AppendChar(' ');
633   if (event_name == "print" || event_name == "g2d_tracing_mark_write" ||
634       event_name == "dpu_tracing_mark_write") {
635     writer.AppendString("tracing_mark_write");
636   } else {
637     writer.AppendString(event_name.c_str(), event_name.size());
638   }
639   writer.AppendChar(':');
640 
641   ArgsSerializer serializer(context_, raw.arg_set_id()[raw_row], event_name,
642                             &proto_id_to_arg_index_by_event_[event_name_id],
643                             &writer);
644   serializer.SerializeArgs();
645 
646   return {writer.CreateStringCopy(), free};
647 }
648 
SerializePrefix(uint32_t raw_row,base::StringWriter * writer)649 void SystraceSerializer::SerializePrefix(uint32_t raw_row,
650                                          base::StringWriter* writer) {
651   const auto& raw = storage_->raw_table();
652   const auto& cpu_table = storage_->cpu_table();
653 
654   int64_t ts = raw.ts()[raw_row];
655   auto ucpu = raw.ucpu()[raw_row];
656   auto cpu = cpu_table.cpu()[ucpu.value];
657 
658   UniqueTid utid = raw.utid()[raw_row];
659   uint32_t tid = storage_->thread_table().tid()[utid];
660 
661   uint32_t tgid = 0;
662   auto opt_upid = storage_->thread_table().upid()[utid];
663   if (opt_upid.has_value()) {
664     tgid = storage_->process_table().pid()[*opt_upid];
665   }
666   auto name = storage_->thread_table().name().GetString(utid);
667 
668   FtraceTime ftrace_time(ts);
669   if (tid == 0) {
670     name = "<idle>";
671   } else if (name.empty()) {
672     name = "<unknown>";
673   }
674 
675   int64_t padding = 16 - static_cast<int64_t>(name.size());
676   if (padding > 0) {
677     writer->AppendChar(' ', static_cast<size_t>(padding));
678   }
679   for (size_t i = 0; i < name.size(); ++i) {
680     char c = name.data()[i];
681     writer->AppendChar(c == '-' ? '_' : c);
682   }
683   writer->AppendChar('-');
684 
685   size_t pre_pid_pos = writer->pos();
686   writer->AppendInt(tid);
687   size_t pid_chars = writer->pos() - pre_pid_pos;
688   if (PERFETTO_LIKELY(pid_chars < 5)) {
689     writer->AppendChar(' ', 5 - pid_chars);
690   }
691 
692   writer->AppendLiteral(" (");
693   if (tgid == 0) {
694     writer->AppendLiteral("-----");
695   } else {
696     writer->AppendPaddedInt<' ', 5>(tgid);
697   }
698   writer->AppendLiteral(") [");
699   writer->AppendPaddedInt<'0', 3>(cpu ? *cpu : 0);
700   writer->AppendLiteral("] .... ");
701 
702   writer->AppendInt(ftrace_time.secs);
703   writer->AppendChar('.');
704   writer->AppendPaddedInt<'0', 6>(ftrace_time.micros);
705   writer->AppendChar(':');
706 }
707 
708 }  // namespace perfetto::trace_processor
709