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