blob: 8d1e811b325ae4f3dbe8798e8655d69f1b303f0f [file] [log] [blame]
Hector Dearman20b3c1c2018-01-15 15:34:03 +00001/*
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
Primiano Tuccic64b05f2019-12-05 10:30:52 +000017#include <stdio.h>
18
Hector Dearman20b3c1c2018-01-15 15:34:03 +000019#include <fstream>
20#include <iostream>
Lalit Maganti84d6adf2019-07-19 19:59:05 +053021#include <limits>
Isabelle Taylor453dbd52019-07-19 11:47:41 +010022#include <vector>
Hector Dearman20b3c1c2018-01-15 15:34:03 +000023
Hector Dearman20b3c1c2018-01-15 15:34:03 +000024#include "perfetto/base/logging.h"
Neda Topoljanacc597f532019-10-09 16:39:59 +010025#include "perfetto/ext/base/string_utils.h"
Florian Mayer3be55fb2019-11-22 13:08:47 +000026#include "tools/trace_to_text/deobfuscate_profile.h"
Neda Topoljanac39288012019-09-25 15:25:01 +010027#include "tools/trace_to_text/symbolize_profile.h"
Eric Secklera60a6b42019-10-07 10:35:48 +010028#include "tools/trace_to_text/trace_to_json.h"
Florian Mayer0ca7fb42018-11-15 21:13:42 +000029#include "tools/trace_to_text/trace_to_profile.h"
Primiano Tucci20dc8f72018-10-23 12:28:29 +010030#include "tools/trace_to_text/trace_to_systrace.h"
31#include "tools/trace_to_text/trace_to_text.h"
Lalit Maganti9b78d5d2019-07-19 09:02:33 +010032
Primiano Tucci02c11762019-08-30 00:57:59 +020033#if PERFETTO_BUILDFLAG(PERFETTO_VERSION_GEN)
Hector Dearmandc1fb892019-03-05 13:20:09 +000034#include "perfetto_version.gen.h"
35#else
36#define PERFETTO_GET_GIT_REVISION() "unknown"
37#endif
38
Primiano Tuccic64b05f2019-12-05 10:30:52 +000039#if !PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
40#include <unistd.h>
41#endif
42
Hector Dearman566badf2019-09-26 17:15:43 +010043namespace perfetto {
44namespace trace_to_text {
Hector Dearman20b3c1c2018-01-15 15:34:03 +000045namespace {
46
Primiano Tucci3cbb10a2018-04-10 17:52:40 +010047int Usage(const char* argv0) {
Florian Mayer1d000842019-10-24 14:52:57 +010048 fprintf(stderr,
Lalit Maganti9b3a6c72019-10-25 10:33:08 +010049 "Usage: %s systrace|json|ctrace|text|profile [--pid PID] "
50 "[--timestamps TIMESTAMP1,TIMESTAMP2,...] "
51 "[--truncate start|end] "
52 "[--full-sort] "
53 "[trace.pb] "
54 "[trace.txt]\n"
55 "\nProfile mode only:\n"
56 "\t--timestamps TIMESTAMP1,TIMESTAMP2,... generate profiles "
57 "only for these timestamps\n"
58 "\t--pid PID generate profiles only for this process id\n",
59 argv0);
Hector Dearman20b3c1c2018-01-15 15:34:03 +000060 return 1;
61}
62
Neda Topoljanacc597f532019-10-09 16:39:59 +010063uint64_t StringToUint64OrDie(const char* str) {
64 char* end;
65 uint64_t number = static_cast<uint64_t>(strtoll(str, &end, 10));
66 if (*end != '\0') {
67 PERFETTO_ELOG("Invalid %s. Expected decimal integer.", str);
68 exit(1);
69 }
70 return number;
71}
72
Hector Dearman566badf2019-09-26 17:15:43 +010073int Main(int argc, char** argv) {
Isabelle Taylor453dbd52019-07-19 11:47:41 +010074 std::vector<const char*> positional_args;
Hector Dearman566badf2019-09-26 17:15:43 +010075 Keep truncate_keep = Keep::kAll;
Neda Topoljanacc597f532019-10-09 16:39:59 +010076 uint64_t pid = 0;
77 std::vector<uint64_t> timestamps;
Lalit Maganti9b3a6c72019-10-25 10:33:08 +010078 bool full_sort = false;
Hector Dearmandc1fb892019-03-05 13:20:09 +000079 for (int i = 1; i < argc; i++) {
80 if (strcmp(argv[i], "-v") == 0 || strcmp(argv[i], "--version") == 0) {
81 printf("%s\n", PERFETTO_GET_GIT_REVISION());
82 return 0;
Isabelle Taylor453dbd52019-07-19 11:47:41 +010083 } else if (strcmp(argv[i], "-t") == 0 ||
84 strcmp(argv[i], "--truncate") == 0) {
Isabelle Taylor53a982a2019-08-08 14:26:38 +010085 i++;
86 if (i <= argc && strcmp(argv[i], "start") == 0) {
Hector Dearman566badf2019-09-26 17:15:43 +010087 truncate_keep = Keep::kStart;
Isabelle Taylor53a982a2019-08-08 14:26:38 +010088 } else if (i <= argc && strcmp(argv[i], "end") == 0) {
Hector Dearman566badf2019-09-26 17:15:43 +010089 truncate_keep = Keep::kEnd;
Isabelle Taylor53a982a2019-08-08 14:26:38 +010090 } else {
91 PERFETTO_ELOG(
92 "--truncate must specify whether to keep the end or the "
93 "start of the trace.");
94 return Usage(argv[0]);
95 }
Neda Topoljanacc597f532019-10-09 16:39:59 +010096 } else if (i <= argc && strcmp(argv[i], "--pid") == 0) {
97 i++;
98 pid = StringToUint64OrDie(argv[i]);
99 } else if (i <= argc && strcmp(argv[i], "--timestamps") == 0) {
100 i++;
101 std::vector<std::string> ts_strings = base::SplitString(argv[i], ",");
102 for (const std::string& ts : ts_strings) {
103 timestamps.emplace_back(StringToUint64OrDie(ts.c_str()));
104 }
Lalit Maganti9b3a6c72019-10-25 10:33:08 +0100105 } else if (strcmp(argv[i], "--full-sort") == 0) {
106 full_sort = true;
Isabelle Taylor453dbd52019-07-19 11:47:41 +0100107 } else {
108 positional_args.push_back(argv[i]);
Hector Dearmandc1fb892019-03-05 13:20:09 +0000109 }
110 }
111
Isabelle Taylor453dbd52019-07-19 11:47:41 +0100112 if (positional_args.size() < 1)
Primiano Tucci3cbb10a2018-04-10 17:52:40 +0100113 return Usage(argv[0]);
Hector Dearman20b3c1c2018-01-15 15:34:03 +0000114
Primiano Tucci1c752c12018-10-23 09:27:19 +0100115 std::istream* input_stream;
116 std::ifstream file_istream;
Isabelle Taylor453dbd52019-07-19 11:47:41 +0100117 if (positional_args.size() > 1) {
118 const char* file_path = positional_args[1];
Primiano Tucci1c752c12018-10-23 09:27:19 +0100119 file_istream.open(file_path, std::ios_base::in | std::ios_base::binary);
120 if (!file_istream.is_open())
121 PERFETTO_FATAL("Could not open %s", file_path);
122 input_stream = &file_istream;
123 } else {
124 if (isatty(STDIN_FILENO)) {
125 PERFETTO_ELOG("Reading from stdin but it's connected to a TTY");
126 PERFETTO_LOG("It is unlikely that you want to type in some binary.");
127 PERFETTO_LOG("Either pass a file path to the cmdline or pipe stdin");
128 return Usage(argv[0]);
129 }
130 input_stream = &std::cin;
131 }
132
133 std::ostream* output_stream;
134 std::ofstream file_ostream;
Isabelle Taylor453dbd52019-07-19 11:47:41 +0100135 if (positional_args.size() > 2) {
136 const char* file_path = positional_args[2];
Primiano Tucci1c752c12018-10-23 09:27:19 +0100137 file_ostream.open(file_path, std::ios_base::out | std::ios_base::trunc);
138 if (!file_ostream.is_open())
139 PERFETTO_FATAL("Could not open %s", file_path);
140 output_stream = &file_ostream;
141 } else {
142 output_stream = &std::cout;
Primiano Tucci1c752c12018-10-23 09:27:19 +0100143 }
144
Isabelle Taylor453dbd52019-07-19 11:47:41 +0100145 std::string format(positional_args[0]);
Hector Dearman20b3c1c2018-01-15 15:34:03 +0000146
Neda Topoljanacc597f532019-10-09 16:39:59 +0100147 if (format != "profile" && (pid != 0 || !timestamps.empty())) {
148 PERFETTO_ELOG(
149 "--pid and --timestamps are supported only for profile format.");
150 return 1;
151 }
152
Hector Dearman1b8b3422019-03-26 16:54:08 +0000153 if (format == "json")
Eric Secklera60a6b42019-10-07 10:35:48 +0100154 return TraceToJson(input_stream, output_stream, /*compress=*/false,
Lalit Maganti9b3a6c72019-10-25 10:33:08 +0100155 truncate_keep, full_sort);
Hector Dearman566badf2019-09-26 17:15:43 +0100156
Hector Dearman1b8b3422019-03-26 16:54:08 +0000157 if (format == "systrace")
Eric Secklera60a6b42019-10-07 10:35:48 +0100158 return TraceToSystrace(input_stream, output_stream, /*compress=*/false,
Lalit Maganti9b3a6c72019-10-25 10:33:08 +0100159 truncate_keep, full_sort);
Hector Dearman566badf2019-09-26 17:15:43 +0100160
161 if (format == "ctrace")
Eric Secklera60a6b42019-10-07 10:35:48 +0100162 return TraceToSystrace(input_stream, output_stream, /*compress=*/true,
Lalit Maganti9b3a6c72019-10-25 10:33:08 +0100163 truncate_keep, full_sort);
Hector Dearman566badf2019-09-26 17:15:43 +0100164
165 if (truncate_keep != Keep::kAll) {
Isabelle Taylor453dbd52019-07-19 11:47:41 +0100166 PERFETTO_ELOG(
167 "--truncate is unsupported for text|profile|symbolize format.");
168 return 1;
169 }
170
Lalit Maganti9b3a6c72019-10-25 10:33:08 +0100171 if (full_sort) {
172 PERFETTO_ELOG(
173 "--full-sort is unsupported for text|profile|symbolize format.");
174 return 1;
175 }
176
Primiano Tucci45c9b182018-03-29 14:10:51 +0100177 if (format == "text")
Hector Dearman566badf2019-09-26 17:15:43 +0100178 return TraceToText(input_stream, output_stream);
Primiano Tuccif0269902018-04-13 11:13:19 +0100179
Hector Dearman566badf2019-09-26 17:15:43 +0100180 if (format == "profile")
Neda Topoljanacc597f532019-10-09 16:39:59 +0100181 return TraceToProfile(input_stream, output_stream, pid, timestamps);
Florian Mayer0ca7fb42018-11-15 21:13:42 +0000182
Florian Mayer0b063752019-07-08 19:51:31 +0100183 if (format == "symbolize")
Hector Dearman566badf2019-09-26 17:15:43 +0100184 return SymbolizeProfile(input_stream, output_stream);
Florian Mayer0b063752019-07-08 19:51:31 +0100185
Florian Mayer3be55fb2019-11-22 13:08:47 +0000186 if (format == "deobfuscate")
187 return DeobfuscateProfile(input_stream, output_stream);
Primiano Tucci3cbb10a2018-04-10 17:52:40 +0100188 return Usage(argv[0]);
Hector Dearman20b3c1c2018-01-15 15:34:03 +0000189}
Hector Dearman566badf2019-09-26 17:15:43 +0100190
191} // namespace
192} // namespace trace_to_text
193} // namespace perfetto
194
195int main(int argc, char** argv) {
196 return perfetto::trace_to_text::Main(argc, argv);
197}