main.cc revision d404ea1f6a7f4fa896229ea9da8000dd717eb499
1/*
2 * Copyright (C) 2018 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include <inttypes.h>
18
19#include <stdio.h>
20#include <algorithm>
21#include <fstream>
22#include <iostream>
23#include <istream>
24#include <map>
25#include <memory>
26#include <ostream>
27#include <sstream>
28#include <string>
29#include <utility>
30
31#include <google/protobuf/compiler/importer.h>
32#include <google/protobuf/dynamic_message.h>
33#include <google/protobuf/io/zero_copy_stream_impl.h>
34#include <google/protobuf/text_format.h>
35#include <google/protobuf/util/field_comparator.h>
36#include <google/protobuf/util/message_differencer.h>
37
38#include "perfetto/base/logging.h"
39#include "perfetto/trace/trace.pb.h"
40#include "perfetto/trace/trace_packet.pb.h"
41
42namespace perfetto {
43namespace {
44
45const char kTraceHeader[] = R"({
46  "traceEvents": [],
47)";
48
49const char kTraceFooter[] = R"(\n",
50  "controllerTraceDataKey": "systraceController"
51})";
52
53const char kFtraceHeader[] =
54    ""
55    "  \"systemTraceEvents\": \""
56    "# tracer: nop\\n"
57    "#\\n"
58    "# entries-in-buffer/entries-written: 30624/30624   #P:4\\n"
59    "#\\n"
60    "#                                      _-----=> irqs-off\\n"
61    "#                                     / _----=> need-resched\\n"
62    "#                                    | / _---=> hardirq/softirq\\n"
63    "#                                    || / _--=> preempt-depth\\n"
64    "#                                    ||| /     delay\\n"
65    "#           TASK-PID    TGID   CPU#  ||||    TIMESTAMP  FUNCTION\\n"
66    "#              | |        |      |   ||||       |         |\\n";
67
68using google::protobuf::Descriptor;
69using google::protobuf::DynamicMessageFactory;
70using google::protobuf::FileDescriptor;
71using google::protobuf::Message;
72using google::protobuf::TextFormat;
73using google::protobuf::compiler::DiskSourceTree;
74using google::protobuf::compiler::Importer;
75using google::protobuf::compiler::MultiFileErrorCollector;
76using google::protobuf::io::OstreamOutputStream;
77using protos::BinderLockedFtraceEvent;
78using protos::BinderLockFtraceEvent;
79using protos::BinderSetPriorityFtraceEvent;
80using protos::BinderTransactionFtraceEvent;
81using protos::BinderTransactionReceivedFtraceEvent;
82using protos::BinderUnlockFtraceEvent;
83using protos::BlockRqIssueFtraceEvent;
84using protos::CgroupAttachTaskFtraceEvent;
85using protos::CgroupDestroyRootFtraceEvent;
86using protos::CgroupMkdirFtraceEvent;
87using protos::CgroupReleaseFtraceEvent;
88using protos::CgroupRemountFtraceEvent;
89using protos::CgroupRenameFtraceEvent;
90using protos::CgroupRmdirFtraceEvent;
91using protos::CgroupSetupRootFtraceEvent;
92using protos::CgroupTransferTasksFtraceEvent;
93using protos::ClockDisableFtraceEvent;
94using protos::ClockEnableFtraceEvent;
95using protos::ClockSetRateFtraceEvent;
96using protos::CpuFrequencyFtraceEvent;
97using protos::CpuFrequencyLimitsFtraceEvent;
98using protos::CpuIdleFtraceEvent;
99using protos::Ext4DaWriteBeginFtraceEvent;
100using protos::Ext4DaWriteEndFtraceEvent;
101using protos::Ext4SyncFileEnterFtraceEvent;
102using protos::Ext4SyncFileExitFtraceEvent;
103using protos::FtraceEvent;
104using protos::FtraceEventBundle;
105using protos::I2cReadFtraceEvent;
106using protos::I2cReplyFtraceEvent;
107using protos::I2cResultFtraceEvent;
108using protos::I2cWriteFtraceEvent;
109using protos::IpiEntryFtraceEvent;
110using protos::IpiExitFtraceEvent;
111using protos::IpiRaiseFtraceEvent;
112using protos::IrqHandlerEntryFtraceEvent;
113using protos::IrqHandlerExitFtraceEvent;
114using protos::LowmemoryKillFtraceEvent;
115using protos::MdpCmdKickoffFtraceEvent;
116using protos::MdpCmdPingpongDoneFtraceEvent;
117using protos::MdpCmdReadptrDoneFtraceEvent;
118using protos::MdpCmdReleaseBwFtraceEvent;
119using protos::MdpCmdWaitPingpongFtraceEvent;
120using protos::MdpCommitFtraceEvent;
121using protos::MdpCompareBwFtraceEvent;
122using protos::MdpMisrCrcFtraceEvent;
123using protos::MdpMixerUpdateFtraceEvent;
124using protos::MdpPerfPrefillCalcFtraceEvent;
125using protos::MdpPerfSetOtFtraceEvent;
126using protos::MdpPerfSetPanicLutsFtraceEvent;
127using protos::MdpPerfSetQosLutsFtraceEvent;
128using protos::MdpPerfSetWmLevelsFtraceEvent;
129using protos::MdpPerfUpdateBusFtraceEvent;
130using protos::MdpSsppChangeFtraceEvent;
131using protos::MdpSsppSetFtraceEvent;
132using protos::MdpTraceCounterFtraceEvent;
133using protos::MdpVideoUnderrunDoneFtraceEvent;
134using protos::MmCompactionBeginFtraceEvent;
135using protos::MmCompactionDeferCompactionFtraceEvent;
136using protos::MmCompactionDeferredFtraceEvent;
137using protos::MmCompactionDeferResetFtraceEvent;
138using protos::MmCompactionEndFtraceEvent;
139using protos::MmCompactionFinishedFtraceEvent;
140using protos::MmCompactionIsolateFreepagesFtraceEvent;
141using protos::MmCompactionIsolateMigratepagesFtraceEvent;
142using protos::MmCompactionKcompactdSleepFtraceEvent;
143using protos::MmCompactionKcompactdWakeFtraceEvent;
144using protos::MmCompactionMigratepagesFtraceEvent;
145using protos::MmCompactionSuitableFtraceEvent;
146using protos::MmCompactionTryToCompactPagesFtraceEvent;
147using protos::MmCompactionWakeupKcompactdFtraceEvent;
148using protos::MmFilemapAddToPageCacheFtraceEvent;
149using protos::MmFilemapDeleteFromPageCacheFtraceEvent;
150using protos::MmVmscanDirectReclaimBeginFtraceEvent;
151using protos::MmVmscanDirectReclaimEndFtraceEvent;
152using protos::MmVmscanKswapdSleepFtraceEvent;
153using protos::MmVmscanKswapdWakeFtraceEvent;
154using protos::PrintFtraceEvent;
155using protos::ProcessTree;
156using protos::RegulatorDisableCompleteFtraceEvent;
157using protos::RegulatorDisableFtraceEvent;
158using protos::RegulatorEnableCompleteFtraceEvent;
159using protos::RegulatorEnableDelayFtraceEvent;
160using protos::RegulatorEnableFtraceEvent;
161using protos::RegulatorSetVoltageCompleteFtraceEvent;
162using protos::RegulatorSetVoltageFtraceEvent;
163using protos::RotatorBwAoAsContextFtraceEvent;
164using protos::SchedBlockedReasonFtraceEvent;
165using protos::SchedCpuHotplugFtraceEvent;
166using protos::SchedSwitchFtraceEvent;
167using protos::SchedWakeupFtraceEvent;
168using protos::SchedWakeupNewFtraceEvent;
169using protos::SchedWakingFtraceEvent;
170using protos::SmbusReadFtraceEvent;
171using protos::SmbusReplyFtraceEvent;
172using protos::SmbusResultFtraceEvent;
173using protos::SmbusWriteFtraceEvent;
174using protos::SoftirqEntryFtraceEvent;
175using protos::SoftirqExitFtraceEvent;
176using protos::SoftirqRaiseFtraceEvent;
177using protos::SuspendResumeFtraceEvent;
178using protos::SyncPtFtraceEvent;
179using protos::SyncTimelineFtraceEvent;
180using protos::SyncWaitFtraceEvent;
181using protos::Trace;
182using protos::TracePacket;
183using protos::TracingMarkWriteFtraceEvent;
184using protos::WorkqueueActivateWorkFtraceEvent;
185using protos::WorkqueueExecuteEndFtraceEvent;
186using protos::WorkqueueExecuteStartFtraceEvent;
187using protos::WorkqueueQueueWorkFtraceEvent;
188using Process = protos::ProcessTree::Process;
189
190// TODO(hjd): Add tests.
191
192class MFE : public MultiFileErrorCollector {
193  virtual void AddError(const std::string& filename,
194                        int line,
195                        int column,
196                        const std::string& message) {
197    PERFETTO_ELOG("Error %s %d:%d: %s", filename.c_str(), line, column,
198                  message.c_str());
199  }
200
201  virtual void AddWarning(const std::string& filename,
202                          int line,
203                          int column,
204                          const std::string& message) {
205    PERFETTO_ELOG("Error %s %d:%d: %s", filename.c_str(), line, column,
206                  message.c_str());
207  }
208};
209
210const char* GetFlag(int32_t state) {
211  state &= 511;
212  if (state & 1)
213    return "S";
214  if (state & 2)
215    return "D";
216  if (state & 4)
217    return "T";
218  if (state & 8)
219    return "t";
220  if (state & 16)
221    return "Z";
222  if (state & 32)
223    return "X";
224  if (state & 64)
225    return "x";
226  if (state & 128)
227    return "W";
228  return "R";
229}
230
231const char* MmCompactionRetArray[] = {
232    "deferred", "skipped",          "continue",          "partial",
233    "complete", "no_suitable_page", "not_suitable_zone", "contended"};
234
235const char* MmCompactionSuitableArray[] = {"DMA", "Normal", "Movable"};
236
237const char* SoftirqArray[] = {"HI",      "TIMER",        "NET_TX",  "NET_RX",
238                              "BLOCK",   "BLOCK_IOPOLL", "TASKLET", "SCHED",
239                              "HRTIMER", "RCU"};
240
241uint64_t TimestampToSeconds(uint64_t timestamp) {
242  return timestamp / 1000000000ul;
243}
244
245uint64_t TimestampToMicroseconds(uint64_t timestamp) {
246  return (timestamp / 1000) % 1000000ul;
247}
248
249std::string FormatPrefix(uint64_t timestamp, uint64_t cpu) {
250  char line[2048];
251  uint64_t seconds = TimestampToSeconds(timestamp);
252  uint64_t useconds = TimestampToMicroseconds(timestamp);
253  sprintf(line,
254          "<idle>-0     (-----) [%03" PRIu64 "] d..3 %" PRIu64 ".%.6" PRIu64
255          ": ",
256          cpu, seconds, useconds);
257  return std::string(line);
258}
259
260std::string FormatSchedSwitch(const SchedSwitchFtraceEvent& sched_switch) {
261  char line[2048];
262  sprintf(line,
263          "sched_switch: prev_comm=%s "
264          "prev_pid=%d prev_prio=%d prev_state=%s ==> next_comm=%s next_pid=%d "
265          "next_prio=%d\\n",
266          sched_switch.prev_comm().c_str(), sched_switch.prev_pid(),
267          sched_switch.prev_prio(), GetFlag(sched_switch.prev_state()),
268          sched_switch.next_comm().c_str(), sched_switch.next_pid(),
269          sched_switch.next_prio());
270  return std::string(line);
271}
272
273std::string FormatSchedWakeup(const SchedWakeupFtraceEvent& sched_wakeup) {
274  char line[2048];
275  sprintf(line,
276          "sched_wakeup: comm=%s "
277          "pid=%d prio=%d success=%d target_cpu=%03d\\n",
278          sched_wakeup.comm().c_str(), sched_wakeup.pid(), sched_wakeup.prio(),
279          sched_wakeup.success(), sched_wakeup.target_cpu());
280  return std::string(line);
281}
282
283std::string FormatSchedBlockedReason(
284    const SchedBlockedReasonFtraceEvent& event) {
285  char line[2048];
286  sprintf(line, "sched_blocked_reason: pid=%d iowait=%d caller=%llxS\\n",
287          event.pid(), event.io_wait(), event.caller());
288  return std::string(line);
289}
290
291std::string FormatPrint(const PrintFtraceEvent& print) {
292  char line[2048];
293  std::string msg = print.buf();
294  // Remove any newlines in the message. It's not entirely clear what the right
295  // behaviour is here. Maybe we should escape them instead?
296  msg.erase(std::remove(msg.begin(), msg.end(), '\n'), msg.end());
297  sprintf(line, "tracing_mark_write: %s\\n", msg.c_str());
298  return std::string(line);
299}
300
301std::string FormatCpuFrequency(const CpuFrequencyFtraceEvent& event) {
302  char line[2048];
303  sprintf(line, "cpu_frequency: state=%" PRIu32 " cpu_id=%" PRIu32 "\\n",
304          event.state(), event.cpu_id());
305  return std::string(line);
306}
307
308std::string FormatCpuFrequencyLimits(
309    const CpuFrequencyLimitsFtraceEvent& event) {
310  char line[2048];
311  sprintf(line,
312          "cpu_frequency_limits: min_freq=%" PRIu32 "max_freq=%" PRIu32
313          " cpu_id=%" PRIu32 "\\n",
314          event.min_freq(), event.max_freq(), event.cpu_id());
315  return std::string(line);
316}
317
318std::string FormatCpuIdle(const CpuIdleFtraceEvent& event) {
319  char line[2048];
320  sprintf(line, "cpu_idle: state=%" PRIu32 " cpu_id=%" PRIu32 "\\n",
321          event.state(), event.cpu_id());
322  return std::string(line);
323}
324
325std::string FormatClockSetRate(const ClockSetRateFtraceEvent& event) {
326  char line[2048];
327  sprintf(line, "clock_set_rate: %s state=%llu cpu_id=%llu\\n",
328          event.name().empty() ? "todo" : event.name().c_str(), event.state(),
329          event.cpu_id());
330  return std::string(line);
331}
332
333std::string FormatClockEnable(const ClockEnableFtraceEvent& event) {
334  char line[2048];
335  sprintf(line, "clock_enable: %s state=%llu cpu_id=%llu\\n",
336          event.name().empty() ? "todo" : event.name().c_str(), event.state(),
337          event.cpu_id());
338  return std::string(line);
339}
340
341std::string FormatClockDisable(const ClockDisableFtraceEvent& event) {
342  char line[2048];
343  sprintf(line, "clock_disable: %s state=%llu cpu_id=%llu\\n",
344          event.name().empty() ? "todo" : event.name().c_str(), event.state(),
345          event.cpu_id());
346  return std::string(line);
347}
348
349std::string FormatTracingMarkWrite(const TracingMarkWriteFtraceEvent& event) {
350  char line[2048];
351  sprintf(line, "tracing_mark_write: %s|%d|%s\\n",
352          event.trace_begin() ? "B" : "E", event.pid(),
353          event.trace_name().c_str());
354  return std::string(line);
355}
356
357std::string FormatBinderLocked(const BinderLockedFtraceEvent& event) {
358  char line[2048];
359  sprintf(line, "binder_locked: tag=%s\\n", event.tag().c_str());
360  return std::string(line);
361}
362
363std::string FormatBinderUnlock(const BinderUnlockFtraceEvent& event) {
364  char line[2048];
365  sprintf(line, "binder_unlock: tag=%s\\n", event.tag().c_str());
366  return std::string(line);
367}
368
369std::string FormatBinderLock(const BinderLockFtraceEvent& event) {
370  char line[2048];
371  sprintf(line, "binder_lock: tag=%s\\n", event.tag().c_str());
372  return std::string(line);
373}
374
375std::string FormatBinderTransaction(const BinderTransactionFtraceEvent& event) {
376  char line[2048];
377  sprintf(line,
378          "binder_transaction: transaction=%d dest_node=%d dest_proc=%d "
379          "dest_thread=%d reply=%d flags=0x%x code=0x%x\\n",
380          event.debug_id(), event.target_node(), event.to_proc(),
381          event.to_thread(), event.reply(), event.flags(), event.code());
382  return std::string(line);
383}
384
385std::string FormatBinderTransactionReceived(
386    const BinderTransactionReceivedFtraceEvent& event) {
387  char line[2048];
388  sprintf(line, "binder_transaction_received: transaction=%d\\n",
389          event.debug_id());
390  return std::string(line);
391}
392
393std::string FormatExt4SyncFileEnter(const Ext4SyncFileEnterFtraceEvent& event) {
394  char line[2048];
395  sprintf(line,
396          "ext4_sync_file_enter: dev %d,%d ino %lu parent %lu datasync %d \\n",
397          (unsigned int)(event.dev() >> 20),
398          (unsigned int)(event.dev() & ((1U << 20) - 1)),
399          (unsigned long)event.ino(), (unsigned long)event.parent(),
400          event.datasync());
401  return std::string(line);
402}
403
404std::string FormatExt4SyncFileExit(const Ext4SyncFileExitFtraceEvent& event) {
405  char line[2048];
406  sprintf(line, "ext4_sync_file_exit: dev %d,%d ino %lu ret %d\\n",
407          (unsigned int)(event.dev() >> 20),
408          (unsigned int)(event.dev() & ((1U << 20) - 1)),
409          (unsigned long)event.ino(), event.ret());
410  return std::string(line);
411}
412
413std::string FormatExt4DaWriteBegin(const Ext4DaWriteBeginFtraceEvent& event) {
414  char line[2048];
415  sprintf(line,
416          "ext4_da_write_begin: dev %d,%d ino %lu pos %lld len %u flags %u\\n",
417          (unsigned int)(event.dev() >> 20),
418          (unsigned int)(event.dev() & ((1U << 20) - 1)),
419          (unsigned long)event.ino(), event.pos(), event.len(), event.flags());
420  return std::string(line);
421}
422
423std::string FormatExt4DaWriteEnd(const Ext4DaWriteEndFtraceEvent& event) {
424  char line[2048];
425  sprintf(line,
426          "ext4_da_write_end: dev %d,%d ino %lu pos %lld len %u copied %u\\n",
427          (unsigned int)(event.dev() >> 20),
428          (unsigned int)(event.dev() & ((1U << 20) - 1)),
429          (unsigned long)event.ino(), event.pos(), event.len(), event.copied());
430  return std::string(line);
431}
432
433std::string FormatBlockRqIssue(const BlockRqIssueFtraceEvent& event) {
434  char line[2048];
435  sprintf(line, "block_rq_issue: %d,%d %s %u (%s) %llu + %u [%s]\\n",
436          (unsigned int)(event.dev() >> 20),
437          (unsigned int)(event.dev() & ((1U << 20) - 1)), event.rwbs().c_str(),
438          event.bytes(), event.cmd().c_str(),
439          (unsigned long long)event.sector(), event.nr_sector(),
440          event.comm().c_str());
441  return std::string(line);
442}
443
444std::string FormatI2cRead(const I2cReadFtraceEvent& event) {
445  char line[2048];
446  sprintf(line, "i2c_read: i2c-%d #%u a=%03x f=%04x l=%u\\n",
447          event.adapter_nr(), event.msg_nr(), event.addr(), event.flags(),
448          event.len());
449  return std::string(line);
450}
451
452std::string FormatI2cResult(const I2cResultFtraceEvent& event) {
453  char line[2048];
454  sprintf(line, "i2c_result: i2c-%d n=%u ret=%d\\n", event.adapter_nr(),
455          event.nr_msgs(), event.ret());
456  return std::string(line);
457}
458
459std::string FormatIrqHandlerEntry(const IrqHandlerEntryFtraceEvent& event) {
460  char line[2048];
461  sprintf(line, "irq_handler_entry: irq=%d name=%s\\n", event.irq(),
462          event.name().c_str());
463  return std::string(line);
464}
465
466std::string FormatIrqHandlerExit(const IrqHandlerExitFtraceEvent& event) {
467  char line[2048];
468  sprintf(line, "irq_handler_exit: irq=%d ret=%s\\n", event.irq(),
469          event.ret() ? "handled" : "unhandled");
470  return std::string(line);
471}
472
473std::string FormatMmVmscanKswapdWake(
474    const MmVmscanKswapdWakeFtraceEvent& event) {
475  char line[2048];
476  sprintf(line, "mm_vmscan_kswapd_wake: nid=%d order=%d\\n", event.nid(),
477          event.order());
478  return std::string(line);
479}
480
481std::string FormatMmVmscanKswapdSleep(
482    const MmVmscanKswapdSleepFtraceEvent& event) {
483  char line[2048];
484  sprintf(line, "mm_vmscan_kswapd_sleep: nid=%d\\n", event.nid());
485  return std::string(line);
486}
487
488std::string FormatRegulatorEnable(const RegulatorEnableFtraceEvent& event) {
489  char line[2048];
490  sprintf(line, "regulator_enable: name=%s\\n", event.name().c_str());
491  return std::string(line);
492}
493
494std::string FormatRegulatorEnableDelay(
495    const RegulatorEnableDelayFtraceEvent& event) {
496  char line[2048];
497  sprintf(line, "regulator_enable_delay: name=%s\\n", event.name().c_str());
498  return std::string(line);
499}
500
501std::string FormatRegulatorEnableComplete(
502    const RegulatorEnableCompleteFtraceEvent& event) {
503  char line[2048];
504  sprintf(line, "regulator_enable_complete: name=%s\\n", event.name().c_str());
505  return std::string(line);
506}
507
508std::string FormatRegulatorDisable(const RegulatorDisableFtraceEvent& event) {
509  char line[2048];
510  sprintf(line, "regulator_disable: name=%s\\n", event.name().c_str());
511  return std::string(line);
512}
513
514std::string FormatRegulatorDisableComplete(
515    const RegulatorDisableCompleteFtraceEvent& event) {
516  char line[2048];
517  sprintf(line, "regulator_disable_complete: name=%s\\n", event.name().c_str());
518  return std::string(line);
519}
520
521std::string FormatRegulatorSetVoltage(
522    const RegulatorSetVoltageFtraceEvent& event) {
523  char line[2048];
524  sprintf(line, "regulator_set_voltage: name=%s (%d-%d)\\n",
525          event.name().c_str(), event.min(), event.max());
526  return std::string(line);
527}
528
529std::string FormatRegulatorSetVoltageComplete(
530    const RegulatorSetVoltageCompleteFtraceEvent& event) {
531  char line[2048];
532  sprintf(line, "regulator_set_voltage_complete: name=%s, val=%u\\n",
533          event.name().c_str(), event.val());
534  return std::string(line);
535}
536
537std::string FormatSchedCpuHotplug(const SchedCpuHotplugFtraceEvent& event) {
538  char line[2048];
539  sprintf(line, "sched_cpu_hotplug: cpu %d %s error=%d\\n",
540          event.affected_cpu(), event.status() ? "online" : "offline",
541          event.error());
542  return std::string(line);
543}
544
545std::string FormatSyncTimeline(const SyncTimelineFtraceEvent& event) {
546  char line[2048];
547  sprintf(line, "sync_timeline: name=%s value=%s\\n", event.name().c_str(),
548          event.value().c_str());
549  return std::string(line);
550}
551
552std::string FormatSyncWait(const SyncWaitFtraceEvent& event) {
553  char line[2048];
554  sprintf(line, "sync_wait: %s name=%s state=%d\\n",
555          event.begin() ? "begin" : "end", event.name().c_str(),
556          event.status());
557  return std::string(line);
558}
559
560std::string FormatSyncPt(const SyncPtFtraceEvent& event) {
561  char line[2048];
562  sprintf(line, "sync_pt: name=%s value=%s\\n", event.timeline().c_str(),
563          event.value().c_str());
564  return std::string(line);
565}
566
567int TraceToText(std::istream* input, std::ostream* output) {
568  DiskSourceTree dst;
569  dst.MapPath("perfetto", "protos/perfetto");
570  MFE mfe;
571  Importer importer(&dst, &mfe);
572  const FileDescriptor* parsed_file =
573      importer.Import("perfetto/trace/trace.proto");
574
575  DynamicMessageFactory dmf;
576  const Descriptor* trace_descriptor = parsed_file->message_type(0);
577  const Message* msg_root = dmf.GetPrototype(trace_descriptor);
578  Message* msg = msg_root->New();
579
580  if (!msg->ParseFromIstream(input)) {
581    PERFETTO_ELOG("Could not parse input.");
582    return 1;
583  }
584  OstreamOutputStream zero_copy_output(output);
585  TextFormat::Print(*msg, &zero_copy_output);
586  return 0;
587}
588
589std::string FormatSoftirqRaise(const SoftirqRaiseFtraceEvent& event) {
590  char line[2048];
591  sprintf(line, "softirq_raise: vec=%u [action=%s]\\n", event.vec(),
592          SoftirqArray[event.vec()]);
593  return std::string(line);
594}
595
596std::string FormatSoftirqEntry(const SoftirqEntryFtraceEvent& event) {
597  char line[2048];
598  sprintf(line, "softirq_entry: vec=%u [action=%s]\\n", event.vec(),
599          SoftirqArray[event.vec()]);
600  return std::string(line);
601}
602
603std::string FormatSoftirqExit(const SoftirqExitFtraceEvent& event) {
604  char line[2048];
605  sprintf(line, "softirq_exit: vec=%u [action=%s]\\n", event.vec(),
606          SoftirqArray[event.vec()]);
607  return std::string(line);
608}
609
610std::string FormatI2cWrite(const I2cWriteFtraceEvent& event) {
611  char line[2048];
612  // TODO(hjd): Check event.buf().
613  sprintf(line, "i2c_write: i2c-%d #%u a=%03x f=%04x l=%u\\n",
614          event.adapter_nr(), event.msg_nr(), event.addr(), event.flags(),
615          event.len());
616  return std::string(line);
617}
618
619std::string FormatI2cReply(const I2cReplyFtraceEvent& event) {
620  char line[2048];
621  // TODO(hjd): Check event.buf().
622  sprintf(line, "i2c_reply: i2c-%d #%u a=%03x f=%04x l=%u\\n",
623          event.adapter_nr(), event.msg_nr(), event.addr(), event.flags(),
624          event.len());
625  return std::string(line);
626}
627
628// TODO(hjd): Check gfp_flags
629std::string FormatMmVmscanDirectReclaimBegin(
630    const MmVmscanDirectReclaimBeginFtraceEvent& event) {
631  char line[2048];
632  sprintf(line, "mm_vmscan_direct_reclaim_begin: order=%d may_writepage=%d\\n",
633          event.order(), event.may_writepage());
634  return std::string(line);
635}
636
637std::string FormatMmVmscanDirectReclaimEnd(
638    const MmVmscanDirectReclaimEndFtraceEvent& event) {
639  char line[2048];
640  sprintf(line, "mm_vmscan_direct_reclaim_end: nr_reclaimed=%llu\\n",
641          event.nr_reclaimed());
642  return std::string(line);
643}
644
645std::string FormatLowmemoryKill(const LowmemoryKillFtraceEvent& event) {
646  char line[2048];
647  sprintf(line,
648          "lowmemory_kill: %s (%d), page cache %lldkB (limit %lldkB), free "
649          "%lldKb\\n",
650          event.comm().c_str(), event.pid(), event.pagecache_size(),
651          event.pagecache_limit(), event.free());
652  return std::string(line);
653}
654
655std::string FormatWorkqueueExecuteStart(
656    const WorkqueueExecuteStartFtraceEvent& event) {
657  char line[2048];
658  sprintf(line, "workqueue_execute_start: work struct %llx: function %llxf\\n",
659          event.work(), event.function());
660  return std::string(line);
661}
662
663std::string FormatWorkqueueExecuteEnd(
664    const WorkqueueExecuteEndFtraceEvent& event) {
665  char line[2048];
666  sprintf(line, "workqueue_execute_end: work struct %llx\\n", event.work());
667  return std::string(line);
668}
669
670std::string FormatWorkqueueQueueWork(
671    const WorkqueueQueueWorkFtraceEvent& event) {
672  char line[2048];
673  sprintf(
674      line,
675      "workqueue_queue_work: work struct=%llx function=%llxf workqueue=%llx "
676      "req_cpu=%u cpu=%u\\n",
677      event.work(), event.function(), event.workqueue(), event.req_cpu(),
678      event.cpu());
679  return std::string(line);
680}
681
682std::string FormatWorkqueueActivateWork(
683    const WorkqueueActivateWorkFtraceEvent& event) {
684  char line[2048];
685  sprintf(line, "workqueue_activate_work: work struct %llx\\n", event.work());
686  return std::string(line);
687}
688
689std::string FormatMmCompactionBegin(const MmCompactionBeginFtraceEvent& event) {
690  char line[2048];
691  sprintf(line,
692          "mm_compaction_begin: zone_start=0x%llx migrate_pfn=0x%llx "
693          "free_pfn=0x%llx zone_end=0x%llx, mode=%s\\n",
694          event.zone_start(), event.migrate_pfn(), event.free_pfn(),
695          event.zone_end(), event.sync() ? "sync" : "async");
696  return std::string(line);
697}
698
699std::string FormatMmCompactionDeferCompaction(
700    const MmCompactionDeferCompactionFtraceEvent& event) {
701  char line[2048];
702  sprintf(line,
703          "mm_compaction_defer_compaction: node=%d zone=%-8s order=%d "
704          "order_failed=%d consider=%u limit=%lu\\n",
705          event.nid(), MmCompactionSuitableArray[event.idx()], event.order(),
706          event.order_failed(), event.considered(), 1UL << event.defer_shift());
707  return std::string(line);
708}
709
710std::string FormatMmCompactionDeferred(
711    const MmCompactionDeferredFtraceEvent& event) {
712  char line[2048];
713  sprintf(line,
714          "mm_compaction_deferred: node=%d zone=%-8s order=%d order_failed=%d "
715          "consider=%u limit=%lu\\n",
716          event.nid(), MmCompactionSuitableArray[event.idx()], event.order(),
717          event.order_failed(), event.considered(), 1UL << event.defer_shift());
718  return std::string(line);
719}
720
721std::string FormatMmCompactionDeferReset(
722    const MmCompactionDeferResetFtraceEvent& event) {
723  char line[2048];
724  sprintf(line,
725          "mm_compaction_defer_reset: node=%d zone=%-8s order=%d "
726          "order_failed=%d consider=%u limit=%lu\\n",
727          event.nid(), MmCompactionSuitableArray[event.idx()], event.order(),
728          event.order_failed(), event.considered(), 1UL << event.defer_shift());
729  return std::string(line);
730}
731
732std::string FormatMmCompactionEnd(const MmCompactionEndFtraceEvent& event) {
733  char line[2048];
734  sprintf(line,
735          "mm_compaction_end: zone_start=0x%llx migrate_pfn=0x%llx "
736          "free_pfn=0x%llx zone_end=0x%llx, mode=%s status=%s\\n",
737          event.zone_start(), event.migrate_pfn(), event.free_pfn(),
738          event.zone_end(), event.sync() ? "sync" : "aysnc",
739          MmCompactionRetArray[event.status()]);
740  return std::string(line);
741}
742
743std::string FormatMmCompactionFinished(
744    const MmCompactionFinishedFtraceEvent& event) {
745  char line[2048];
746  sprintf(line, "mm_compaction_finished: node=%d zone=%-8s order=%d ret=%s\\n",
747          event.nid(), MmCompactionSuitableArray[event.idx()], event.order(),
748          MmCompactionRetArray[event.ret()]);
749  return std::string(line);
750}
751
752std::string FormatMmCompactionIsolateFreepages(
753    const MmCompactionIsolateFreepagesFtraceEvent& event) {
754  char line[2048];
755  sprintf(line,
756          "mm_compaction_isolate_freepages: range=(0x%llx ~ 0x%llx) "
757          "nr_scanned=%llu nr_taken=%llu\\n",
758          event.start_pfn(), event.end_pfn(), event.nr_scanned(),
759          event.nr_taken());
760  return std::string(line);
761}
762
763std::string FormatMmCompactionIsolateMigratepages(
764    const MmCompactionIsolateMigratepagesFtraceEvent& event) {
765  char line[2048];
766  sprintf(line,
767          "mm_compaction_isolate_migratepages: range=(0x%llx ~ 0x%llx) "
768          "nr_scanned=%llu nr_taken=%llu\\n",
769          event.start_pfn(), event.end_pfn(), event.nr_scanned(),
770          event.nr_taken());
771  return std::string(line);
772}
773
774std::string FormatMmCompactionKcompactdSleep(
775    const MmCompactionKcompactdSleepFtraceEvent& event) {
776  char line[2048];
777  sprintf(line, "mm_compaction_kcompactd_sleep: nid=%d\\n", event.nid());
778  return std::string(line);
779}
780
781std::string FormatMmCompactionKcompactdWake(
782    const MmCompactionKcompactdWakeFtraceEvent& event) {
783  char line[2048];
784  sprintf(line,
785          "mm_compaction_kcompactd_wake: nid=%d order=%d classzone_idx=%-8s\\n",
786          event.nid(), event.order(),
787          MmCompactionSuitableArray[event.classzone_idx()]);
788  return std::string(line);
789}
790
791std::string FormatMmCompactionMigratepages(
792    const MmCompactionMigratepagesFtraceEvent& event) {
793  char line[2048];
794  sprintf(line,
795          "mm_compaction_migratepages: nr_migrated=%llu nr_failed=%llu\\n",
796          event.nr_migrated(), event.nr_failed());
797  return std::string(line);
798}
799
800std::string FormatMmCompactionSuitable(
801    const MmCompactionSuitableFtraceEvent& event) {
802  char line[2048];
803  sprintf(line, "mm_compaction_suitable: node=%d zone=%-8s order=%d ret=%s\\n",
804          event.nid(), MmCompactionSuitableArray[event.idx()], event.order(),
805          MmCompactionRetArray[event.ret()]);
806  return std::string(line);
807}
808
809std::string FormatMmCompactionTryToCompactPages(
810    const MmCompactionTryToCompactPagesFtraceEvent& event) {
811  char line[2048];
812  sprintf(
813      line,
814      "mm_compaction_try_to_compact_pages: order=%d gfp_mask=0x%x mode=%d\\n",
815      event.order(), event.gfp_mask(),
816      event.mode());  // convert to int?
817  return std::string(line);
818}
819
820std::string FormatMmCompactionWakeupKcompactd(
821    const MmCompactionWakeupKcompactdFtraceEvent& event) {
822  char line[2048];
823  sprintf(
824      line,
825      "mm_compaction_wakeup_kcompactd: nid=%d order=%d classzone_idx=%-8s\\n",
826      event.nid(), event.order(),
827      MmCompactionSuitableArray[event.classzone_idx()]);
828  return std::string(line);
829}
830
831std::string FormatSuspendResume(const SuspendResumeFtraceEvent& event) {
832  char line[2048];
833  sprintf(line, "suspend_resume: %s[%u] %s\\n", event.action().c_str(),
834          event.val(), event.start() ? "begin" : "end");
835  return std::string(line);
836}
837
838std::string FormatSchedWakeupNew(const SchedWakeupNewFtraceEvent& event) {
839  char line[2048];
840  sprintf(line, "sched_wakeup_new: comm=%s pid=%d prio=%d target_cpu=%03d\\n",
841          event.comm().c_str(), event.pid(), event.prio(), event.target_cpu());
842  return std::string(line);
843}
844
845// TODO(taylori): Confirm correct format for this.
846std::string FormatProcess(const Process& process) {
847  char line[2048];
848  sprintf(line, "process: pid=%d ppid=%d cmdline=%s\\n", process.pid(),
849          process.ppid(), process.cmdline(0).c_str());
850  std::string output = std::string(line);
851  for (auto thread : process.threads()) {
852    char thread_line[2048];
853    sprintf(thread_line, "thread: tid=%d name=%s\\n", thread.tid(),
854            thread.name().c_str());
855    output += thread_line;
856  }
857  return output;
858}
859
860int TraceToSystrace(std::istream* input, std::ostream* output) {
861  std::multimap<uint64_t, std::string> sorted;
862
863  std::string raw;
864  std::istreambuf_iterator<char> begin(*input), end;
865  raw.assign(begin, end);
866  Trace trace;
867  if (!trace.ParseFromString(raw)) {
868    PERFETTO_ELOG("Could not parse input.");
869    return 1;
870  }
871
872  for (const TracePacket& packet : trace.packet()) {
873    if (packet.has_process_tree()) {
874      const ProcessTree& process_tree = packet.process_tree();
875      for (const auto& process : process_tree.processes()) {
876        std::string line = FormatProcess(process);
877        sorted.emplace(0, line);
878      }
879    }
880
881    if (!packet.has_ftrace_events())
882      continue;
883
884    const FtraceEventBundle& bundle = packet.ftrace_events();
885    for (const FtraceEvent& event : bundle.event()) {
886      std::string line;
887      if (event.has_sched_switch()) {
888        const auto& inner = event.sched_switch();
889        line = FormatSchedSwitch(inner);
890      } else if (event.has_sched_wakeup()) {
891        const auto& inner = event.sched_wakeup();
892        line = FormatSchedWakeup(inner);
893      } else if (event.has_sched_blocked_reason()) {
894        const auto& inner = event.sched_blocked_reason();
895        line = FormatSchedBlockedReason(inner);
896      } else if (event.has_tracing_mark_write()) {
897        const auto& inner = event.tracing_mark_write();
898        line = FormatTracingMarkWrite(inner);
899      } else if (event.has_binder_locked()) {
900        const auto& inner = event.binder_locked();
901        line = FormatBinderLocked(inner);
902      } else if (event.has_binder_unlock()) {
903        const auto& inner = event.binder_unlock();
904        line = FormatBinderUnlock(inner);
905      } else if (event.has_binder_lock()) {
906        const auto& inner = event.binder_lock();
907        line = FormatBinderLock(inner);
908      } else if (event.has_binder_transaction()) {
909        const auto& inner = event.binder_transaction();
910        line = FormatBinderTransaction(inner);
911      } else if (event.has_binder_transaction_received()) {
912        const auto& inner = event.binder_transaction_received();
913        line = FormatBinderTransactionReceived(inner);
914      } else if (event.has_ext4_sync_file_enter()) {
915        const auto& inner = event.ext4_sync_file_enter();
916        line = FormatExt4SyncFileEnter(inner);
917      } else if (event.has_ext4_sync_file_exit()) {
918        const auto& inner = event.ext4_sync_file_exit();
919        line = FormatExt4SyncFileExit(inner);
920      } else if (event.has_ext4_da_write_begin()) {
921        const auto& inner = event.ext4_da_write_begin();
922        line = FormatExt4DaWriteBegin(inner);
923      } else if (event.has_ext4_da_write_end()) {
924        const auto& inner = event.ext4_da_write_end();
925        line = FormatExt4DaWriteEnd(inner);
926      } else if (event.has_block_rq_issue()) {
927        const auto& inner = event.block_rq_issue();
928        line = FormatBlockRqIssue(inner);
929      } else if (event.has_i2c_read()) {
930        const auto& inner = event.i2c_read();
931        line = FormatI2cRead(inner);
932      } else if (event.has_i2c_result()) {
933        const auto& inner = event.i2c_result();
934        line = FormatI2cResult(inner);
935      } else if (event.has_irq_handler_entry()) {
936        const auto& inner = event.irq_handler_entry();
937        line = FormatIrqHandlerEntry(inner);
938      } else if (event.has_irq_handler_exit()) {
939        const auto& inner = event.irq_handler_exit();
940        line = FormatIrqHandlerExit(inner);
941      } else if (event.has_mm_vmscan_kswapd_wake()) {
942        const auto& inner = event.mm_vmscan_kswapd_wake();
943        line = FormatMmVmscanKswapdWake(inner);
944      } else if (event.has_mm_vmscan_kswapd_sleep()) {
945        const auto& inner = event.mm_vmscan_kswapd_sleep();
946        line = FormatMmVmscanKswapdSleep(inner);
947      } else if (event.has_regulator_enable()) {
948        const auto& inner = event.regulator_enable();
949        line = FormatRegulatorEnable(inner);
950      } else if (event.has_regulator_enable_delay()) {
951        const auto& inner = event.regulator_enable_delay();
952        line = FormatRegulatorEnableDelay(inner);
953      } else if (event.has_regulator_enable_complete()) {
954        const auto& inner = event.regulator_enable_complete();
955        line = FormatRegulatorEnableComplete(inner);
956      } else if (event.has_regulator_disable()) {
957        const auto& inner = event.regulator_disable();
958        line = FormatRegulatorDisable(inner);
959      } else if (event.has_regulator_disable_complete()) {
960        const auto& inner = event.regulator_disable_complete();
961        line = FormatRegulatorDisableComplete(inner);
962      } else if (event.has_regulator_set_voltage()) {
963        const auto& inner = event.regulator_set_voltage();
964        line = FormatRegulatorSetVoltage(inner);
965      } else if (event.has_regulator_set_voltage_complete()) {
966        const auto& inner = event.regulator_set_voltage_complete();
967        line = FormatRegulatorSetVoltageComplete(inner);
968      } else if (event.has_sched_cpu_hotplug()) {
969        const auto& inner = event.sched_cpu_hotplug();
970        line = FormatSchedCpuHotplug(inner);
971      } else if (event.has_sync_timeline()) {
972        const auto& inner = event.sync_timeline();
973        line = FormatSyncTimeline(inner);
974      } else if (event.has_sync_wait()) {
975        const auto& inner = event.sync_wait();
976        line = FormatSyncWait(inner);
977      } else if (event.has_sync_pt()) {
978        const auto& inner = event.sync_pt();
979        line = FormatSyncPt(inner);
980      } else if (event.has_print()) {
981        const auto& inner = event.print();
982        line = FormatPrint(inner);
983      } else if (event.has_cpu_frequency()) {
984        const auto& inner = event.cpu_frequency();
985        line = FormatCpuFrequency(inner);
986      } else if (event.has_cpu_frequency_limits()) {
987        const auto& inner = event.cpu_frequency_limits();
988        line = FormatCpuFrequencyLimits(inner);
989      } else if (event.has_cpu_idle()) {
990        const auto& inner = event.cpu_idle();
991        line = FormatCpuIdle(inner);
992      } else if (event.has_clock_set_rate()) {
993        const auto& inner = event.clock_set_rate();
994        line = FormatClockSetRate(inner);
995      } else if (event.has_clock_enable()) {
996        const auto& inner = event.clock_enable();
997        line = FormatClockEnable(inner);
998      } else if (event.has_clock_disable()) {
999        const auto& inner = event.clock_disable();
1000        line = FormatClockDisable(inner);
1001      } else if (event.has_i2c_write()) {
1002        const auto& inner = event.i2c_write();
1003        line = FormatI2cWrite(inner);
1004      } else if (event.has_i2c_reply()) {
1005        const auto& inner = event.i2c_reply();
1006        line = FormatI2cReply(inner);
1007      } else if (event.has_softirq_raise()) {
1008        const auto& inner = event.softirq_raise();
1009        line = FormatSoftirqRaise(inner);
1010      } else if (event.has_softirq_entry()) {
1011        const auto& inner = event.softirq_entry();
1012        line = FormatSoftirqEntry(inner);
1013      } else if (event.has_softirq_exit()) {
1014        const auto& inner = event.softirq_exit();
1015        line = FormatSoftirqExit(inner);
1016      } else if (event.has_mm_vmscan_direct_reclaim_begin()) {
1017        const auto& inner = event.mm_vmscan_direct_reclaim_begin();
1018        line = FormatMmVmscanDirectReclaimBegin(inner);
1019      } else if (event.has_mm_vmscan_direct_reclaim_end()) {
1020        const auto& inner = event.mm_vmscan_direct_reclaim_end();
1021        line = FormatMmVmscanDirectReclaimEnd(inner);
1022      } else if (event.has_lowmemory_kill()) {
1023        const auto& inner = event.lowmemory_kill();
1024        line = FormatLowmemoryKill(inner);
1025      } else if (event.has_workqueue_execute_start()) {
1026        const auto& inner = event.workqueue_execute_start();
1027        line = FormatWorkqueueExecuteStart(inner);
1028      } else if (event.has_workqueue_execute_end()) {
1029        const auto& inner = event.workqueue_execute_end();
1030        line = FormatWorkqueueExecuteEnd(inner);
1031      } else if (event.has_workqueue_queue_work()) {
1032        const auto& inner = event.workqueue_queue_work();
1033        line = FormatWorkqueueQueueWork(inner);
1034      } else if (event.has_workqueue_activate_work()) {
1035        const auto& inner = event.workqueue_activate_work();
1036        line = FormatWorkqueueActivateWork(inner);
1037      } else if (event.has_mm_compaction_begin()) {
1038        const auto& inner = event.mm_compaction_begin();
1039        line = FormatMmCompactionBegin(inner);
1040      } else if (event.has_mm_compaction_deferred()) {
1041        const auto& inner = event.mm_compaction_deferred();
1042        line = FormatMmCompactionDeferred(inner);
1043      } else if (event.has_mm_compaction_defer_reset()) {
1044        const auto& inner = event.mm_compaction_defer_reset();
1045        line = FormatMmCompactionDeferReset(inner);
1046      } else if (event.has_mm_compaction_end()) {
1047        const auto& inner = event.mm_compaction_end();
1048        line = FormatMmCompactionEnd(inner);
1049      } else if (event.has_mm_compaction_finished()) {
1050        const auto& inner = event.mm_compaction_finished();
1051        line = FormatMmCompactionFinished(inner);
1052      } else if (event.has_mm_compaction_isolate_freepages()) {
1053        const auto& inner = event.mm_compaction_isolate_freepages();
1054        line = FormatMmCompactionIsolateFreepages(inner);
1055      } else if (event.has_mm_compaction_isolate_migratepages()) {
1056        const auto& inner = event.mm_compaction_isolate_migratepages();
1057        line = FormatMmCompactionIsolateMigratepages(inner);
1058      } else if (event.has_mm_compaction_kcompactd_sleep()) {
1059        const auto& inner = event.mm_compaction_kcompactd_sleep();
1060        line = FormatMmCompactionKcompactdSleep(inner);
1061      } else if (event.has_mm_compaction_kcompactd_wake()) {
1062        const auto& inner = event.mm_compaction_kcompactd_wake();
1063        line = FormatMmCompactionKcompactdWake(inner);
1064      } else if (event.has_mm_compaction_migratepages()) {
1065        const auto& inner = event.mm_compaction_migratepages();
1066        line = FormatMmCompactionMigratepages(inner);
1067      } else if (event.has_mm_compaction_suitable()) {
1068        const auto& inner = event.mm_compaction_suitable();
1069        line = FormatMmCompactionSuitable(inner);
1070      } else if (event.has_mm_compaction_try_to_compact_pages()) {
1071        const auto& inner = event.mm_compaction_try_to_compact_pages();
1072        line = FormatMmCompactionTryToCompactPages(inner);
1073      } else if (event.has_mm_compaction_wakeup_kcompactd()) {
1074        const auto& inner = event.mm_compaction_wakeup_kcompactd();
1075        line = FormatMmCompactionWakeupKcompactd(inner);
1076      } else if (event.has_suspend_resume()) {
1077        const auto& inner = event.suspend_resume();
1078        line = FormatSuspendResume(inner);
1079      } else if (event.has_sched_wakeup_new()) {
1080        const auto& inner = event.sched_wakeup_new();
1081        line = FormatSchedWakeupNew(inner);
1082      } else {
1083        continue;
1084      }
1085      sorted.emplace(event.timestamp(),
1086                     FormatPrefix(event.timestamp(), bundle.cpu()) + line);
1087    }
1088  }
1089
1090  *output << kTraceHeader;
1091  *output << kFtraceHeader;
1092
1093  for (auto it = sorted.begin(); it != sorted.end(); it++)
1094    *output << it->second;
1095
1096  *output << kTraceFooter;
1097
1098  return 0;
1099}
1100
1101}  // namespace
1102}  // namespace perfetto
1103
1104namespace {
1105
1106int Usage(int argc, char** argv) {
1107  printf("Usage: %s [systrace|text] < trace.proto > trace.txt\n", argv[0]);
1108  return 1;
1109}
1110
1111}  // namespace
1112
1113int main(int argc, char** argv) {
1114  if (argc != 2)
1115    return Usage(argc, argv);
1116
1117  std::string format(argv[1]);
1118
1119  if (format != "systrace" && format != "text")
1120    return Usage(argc, argv);
1121
1122  bool systrace = format == "systrace";
1123
1124  if (systrace) {
1125    return perfetto::TraceToSystrace(&std::cin, &std::cout);
1126  } else {
1127    return perfetto::TraceToText(&std::cin, &std::cout);
1128  }
1129}
1130