blob: 22ded8000ef6a62a166a0db359d9b191c8ba9206 [file] [log] [blame]
Steven Rostedt538bafb2009-08-17 16:18:06 +02001/*
2 * Copyright (C) 2009, Steven Rostedt <srostedt@redhat.com>
3 *
4 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; version 2 of the License (not later!)
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 *
19 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
20 */
Steven Rostedt538bafb2009-08-17 16:18:06 +020021#include <dirent.h>
22#include <stdio.h>
23#include <stdlib.h>
24#include <string.h>
25#include <getopt.h>
26#include <stdarg.h>
27#include <sys/types.h>
28#include <sys/stat.h>
29#include <sys/wait.h>
30#include <sys/mman.h>
31#include <pthread.h>
32#include <fcntl.h>
33#include <unistd.h>
Steven Rostedt538bafb2009-08-17 16:18:06 +020034#include <errno.h>
35
Frederic Weisbecker1ef2ed12009-08-28 03:09:58 +020036#include "../perf.h"
Steven Rostedt538bafb2009-08-17 16:18:06 +020037#include "util.h"
38#include "trace-event.h"
39
40static int input_fd;
41
Steven Rostedt538bafb2009-08-17 16:18:06 +020042int file_bigendian;
43int host_bigendian;
44static int long_size;
45
Tom Zanussi92155452010-04-01 23:59:21 -050046static ssize_t calc_data_size;
Tom Zanussi454c4072010-05-01 01:41:20 -050047static bool repipe;
Tom Zanussi92155452010-04-01 23:59:21 -050048
49static int do_read(int fd, void *buf, int size)
50{
51 int rsize = size;
52
53 while (size) {
54 int ret = read(fd, buf, size);
55
56 if (ret <= 0)
57 return -1;
58
Tom Zanussi454c4072010-05-01 01:41:20 -050059 if (repipe) {
60 int retw = write(STDOUT_FILENO, buf, ret);
61
62 if (retw <= 0 || retw != ret)
63 die("repiping input file");
64 }
65
Tom Zanussi92155452010-04-01 23:59:21 -050066 size -= ret;
67 buf += ret;
68 }
69
70 return rsize;
71}
72
Steven Rostedt538bafb2009-08-17 16:18:06 +020073static int read_or_die(void *data, int size)
74{
75 int r;
76
Tom Zanussi92155452010-04-01 23:59:21 -050077 r = do_read(input_fd, data, size);
78 if (r <= 0)
Steven Rostedt538bafb2009-08-17 16:18:06 +020079 die("reading input file (size expected=%d received=%d)",
80 size, r);
Tom Zanussi92155452010-04-01 23:59:21 -050081
82 if (calc_data_size)
83 calc_data_size += r;
84
Steven Rostedt538bafb2009-08-17 16:18:06 +020085 return r;
86}
87
Tom Zanussicbb5cf72010-05-04 23:02:10 -050088/* If it fails, the next read will report it */
89static void skip(int size)
90{
91 char buf[BUFSIZ];
92 int r;
93
94 while (size) {
95 r = size > BUFSIZ ? BUFSIZ : size;
96 read_or_die(buf, r);
97 size -= r;
98 };
99}
100
Arnaldo Carvalho de Meloda378962012-06-27 13:08:42 -0300101static unsigned int read4(struct pevent *pevent)
Steven Rostedt538bafb2009-08-17 16:18:06 +0200102{
103 unsigned int data;
104
105 read_or_die(&data, 4);
Arnaldo Carvalho de Meloda378962012-06-27 13:08:42 -0300106 return __data2host4(pevent, data);
Steven Rostedt538bafb2009-08-17 16:18:06 +0200107}
108
Arnaldo Carvalho de Meloda378962012-06-27 13:08:42 -0300109static unsigned long long read8(struct pevent *pevent)
Steven Rostedt538bafb2009-08-17 16:18:06 +0200110{
111 unsigned long long data;
112
113 read_or_die(&data, 8);
Arnaldo Carvalho de Meloda378962012-06-27 13:08:42 -0300114 return __data2host8(pevent, data);
Steven Rostedt538bafb2009-08-17 16:18:06 +0200115}
116
117static char *read_string(void)
118{
119 char buf[BUFSIZ];
120 char *str = NULL;
121 int size = 0;
Xiao Guangrongf887f302010-02-04 16:46:42 +0800122 off_t r;
Tom Zanussi92155452010-04-01 23:59:21 -0500123 char c;
Steven Rostedt538bafb2009-08-17 16:18:06 +0200124
125 for (;;) {
Tom Zanussi92155452010-04-01 23:59:21 -0500126 r = read(input_fd, &c, 1);
Steven Rostedt538bafb2009-08-17 16:18:06 +0200127 if (r < 0)
128 die("reading input file");
129
130 if (!r)
131 die("no data");
132
Tom Zanussi454c4072010-05-01 01:41:20 -0500133 if (repipe) {
134 int retw = write(STDOUT_FILENO, &c, 1);
135
136 if (retw <= 0 || retw != r)
137 die("repiping input file string");
138 }
139
Tom Zanussi92155452010-04-01 23:59:21 -0500140 buf[size++] = c;
141
142 if (!c)
Steven Rostedt538bafb2009-08-17 16:18:06 +0200143 break;
Steven Rostedt538bafb2009-08-17 16:18:06 +0200144 }
145
Tom Zanussi92155452010-04-01 23:59:21 -0500146 if (calc_data_size)
147 calc_data_size += size;
Ingo Molnar6f4596d2009-09-03 16:22:45 +0200148
Namhyung Kima4c98362013-03-21 16:18:49 +0900149 str = malloc(size);
150 if (str)
151 memcpy(str, buf, size);
Steven Rostedt538bafb2009-08-17 16:18:06 +0200152
153 return str;
154}
155
Namhyung Kima4c98362013-03-21 16:18:49 +0900156static int read_proc_kallsyms(struct pevent *pevent)
Steven Rostedt538bafb2009-08-17 16:18:06 +0200157{
158 unsigned int size;
159 char *buf;
160
Arnaldo Carvalho de Meloda378962012-06-27 13:08:42 -0300161 size = read4(pevent);
Steven Rostedt538bafb2009-08-17 16:18:06 +0200162 if (!size)
Namhyung Kima4c98362013-03-21 16:18:49 +0900163 return 0;
Steven Rostedt538bafb2009-08-17 16:18:06 +0200164
Namhyung Kima4c98362013-03-21 16:18:49 +0900165 buf = malloc(size + 1);
166 if (buf == NULL)
167 return -1;
168
Steven Rostedt538bafb2009-08-17 16:18:06 +0200169 read_or_die(buf, size);
OGAWA Hirofumi7691b1e2009-12-06 20:10:49 +0900170 buf[size] = '\0';
Steven Rostedt538bafb2009-08-17 16:18:06 +0200171
Arnaldo Carvalho de Meloda378962012-06-27 13:08:42 -0300172 parse_proc_kallsyms(pevent, buf, size);
Steven Rostedt538bafb2009-08-17 16:18:06 +0200173
174 free(buf);
Namhyung Kima4c98362013-03-21 16:18:49 +0900175 return 0;
Steven Rostedt538bafb2009-08-17 16:18:06 +0200176}
177
Namhyung Kima4c98362013-03-21 16:18:49 +0900178static int read_ftrace_printk(struct pevent *pevent)
Steven Rostedt538bafb2009-08-17 16:18:06 +0200179{
180 unsigned int size;
181 char *buf;
182
Arnaldo Carvalho de Meloda378962012-06-27 13:08:42 -0300183 size = read4(pevent);
Steven Rostedt538bafb2009-08-17 16:18:06 +0200184 if (!size)
Namhyung Kima4c98362013-03-21 16:18:49 +0900185 return 0;
Steven Rostedt538bafb2009-08-17 16:18:06 +0200186
Namhyung Kima4c98362013-03-21 16:18:49 +0900187 buf = malloc(size);
188 if (buf == NULL)
189 return -1;
190
Steven Rostedt538bafb2009-08-17 16:18:06 +0200191 read_or_die(buf, size);
192
Arnaldo Carvalho de Meloda378962012-06-27 13:08:42 -0300193 parse_ftrace_printk(pevent, buf, size);
Steven Rostedt538bafb2009-08-17 16:18:06 +0200194
195 free(buf);
Namhyung Kima4c98362013-03-21 16:18:49 +0900196 return 0;
Steven Rostedt538bafb2009-08-17 16:18:06 +0200197}
198
Namhyung Kima4c98362013-03-21 16:18:49 +0900199static int read_header_files(struct pevent *pevent)
Steven Rostedt538bafb2009-08-17 16:18:06 +0200200{
201 unsigned long long size;
Steven Rostedt538bafb2009-08-17 16:18:06 +0200202 char *header_event;
203 char buf[BUFSIZ];
204
205 read_or_die(buf, 12);
206
207 if (memcmp(buf, "header_page", 12) != 0)
208 die("did not read header page");
209
Arnaldo Carvalho de Meloda378962012-06-27 13:08:42 -0300210 size = read8(pevent);
Frederic Weisbeckerd00a47c2010-05-01 03:08:46 +0200211 skip(size);
Steven Rostedt538bafb2009-08-17 16:18:06 +0200212
213 /*
214 * The size field in the page is of type long,
215 * use that instead, since it represents the kernel.
216 */
217 long_size = header_page_size_size;
218
219 read_or_die(buf, 13);
220 if (memcmp(buf, "header_event", 13) != 0)
221 die("did not read header event");
222
Arnaldo Carvalho de Meloda378962012-06-27 13:08:42 -0300223 size = read8(pevent);
Namhyung Kima4c98362013-03-21 16:18:49 +0900224 header_event = malloc(size);
225 if (header_event == NULL)
226 return -1;
227
Steven Rostedt538bafb2009-08-17 16:18:06 +0200228 read_or_die(header_event, size);
229 free(header_event);
Namhyung Kima4c98362013-03-21 16:18:49 +0900230 return 0;
Steven Rostedt538bafb2009-08-17 16:18:06 +0200231}
232
Namhyung Kima4c98362013-03-21 16:18:49 +0900233static int read_ftrace_file(struct pevent *pevent, unsigned long long size)
Steven Rostedt538bafb2009-08-17 16:18:06 +0200234{
235 char *buf;
236
Namhyung Kima4c98362013-03-21 16:18:49 +0900237 buf = malloc(size);
238 if (buf == NULL)
239 return -1;
240
Steven Rostedt538bafb2009-08-17 16:18:06 +0200241 read_or_die(buf, size);
Arnaldo Carvalho de Meloda378962012-06-27 13:08:42 -0300242 parse_ftrace_file(pevent, buf, size);
Steven Rostedt538bafb2009-08-17 16:18:06 +0200243 free(buf);
Namhyung Kima4c98362013-03-21 16:18:49 +0900244 return 0;
Steven Rostedt538bafb2009-08-17 16:18:06 +0200245}
246
Namhyung Kima4c98362013-03-21 16:18:49 +0900247static int read_event_file(struct pevent *pevent, char *sys,
Arnaldo Carvalho de Meloda378962012-06-27 13:08:42 -0300248 unsigned long long size)
Steven Rostedt538bafb2009-08-17 16:18:06 +0200249{
250 char *buf;
251
Namhyung Kima4c98362013-03-21 16:18:49 +0900252 buf = malloc(size);
253 if (buf == NULL)
254 return -1;
255
Steven Rostedt538bafb2009-08-17 16:18:06 +0200256 read_or_die(buf, size);
Arnaldo Carvalho de Meloda378962012-06-27 13:08:42 -0300257 parse_event_file(pevent, buf, size, sys);
Steven Rostedt538bafb2009-08-17 16:18:06 +0200258 free(buf);
Namhyung Kima4c98362013-03-21 16:18:49 +0900259 return 0;
Steven Rostedt538bafb2009-08-17 16:18:06 +0200260}
261
Namhyung Kima4c98362013-03-21 16:18:49 +0900262static int read_ftrace_files(struct pevent *pevent)
Steven Rostedt538bafb2009-08-17 16:18:06 +0200263{
264 unsigned long long size;
265 int count;
266 int i;
Namhyung Kima4c98362013-03-21 16:18:49 +0900267 int ret;
Steven Rostedt538bafb2009-08-17 16:18:06 +0200268
Arnaldo Carvalho de Meloda378962012-06-27 13:08:42 -0300269 count = read4(pevent);
Steven Rostedt538bafb2009-08-17 16:18:06 +0200270
271 for (i = 0; i < count; i++) {
Arnaldo Carvalho de Meloda378962012-06-27 13:08:42 -0300272 size = read8(pevent);
Namhyung Kima4c98362013-03-21 16:18:49 +0900273 ret = read_ftrace_file(pevent, size);
274 if (ret)
275 return ret;
Steven Rostedt538bafb2009-08-17 16:18:06 +0200276 }
Namhyung Kima4c98362013-03-21 16:18:49 +0900277 return 0;
Steven Rostedt538bafb2009-08-17 16:18:06 +0200278}
279
Namhyung Kima4c98362013-03-21 16:18:49 +0900280static int read_event_files(struct pevent *pevent)
Steven Rostedt538bafb2009-08-17 16:18:06 +0200281{
282 unsigned long long size;
283 char *sys;
284 int systems;
285 int count;
286 int i,x;
Namhyung Kima4c98362013-03-21 16:18:49 +0900287 int ret;
Steven Rostedt538bafb2009-08-17 16:18:06 +0200288
Arnaldo Carvalho de Meloda378962012-06-27 13:08:42 -0300289 systems = read4(pevent);
Steven Rostedt538bafb2009-08-17 16:18:06 +0200290
291 for (i = 0; i < systems; i++) {
292 sys = read_string();
Namhyung Kima4c98362013-03-21 16:18:49 +0900293 if (sys == NULL)
294 return -1;
Steven Rostedt538bafb2009-08-17 16:18:06 +0200295
Arnaldo Carvalho de Meloda378962012-06-27 13:08:42 -0300296 count = read4(pevent);
Steven Rostedt538bafb2009-08-17 16:18:06 +0200297 for (x=0; x < count; x++) {
Arnaldo Carvalho de Meloda378962012-06-27 13:08:42 -0300298 size = read8(pevent);
Namhyung Kima4c98362013-03-21 16:18:49 +0900299 ret = read_event_file(pevent, sys, size);
300 if (ret)
301 return ret;
Steven Rostedt538bafb2009-08-17 16:18:06 +0200302 }
303 }
Namhyung Kima4c98362013-03-21 16:18:49 +0900304 return 0;
Steven Rostedt538bafb2009-08-17 16:18:06 +0200305}
306
Arnaldo Carvalho de Meloda378962012-06-27 13:08:42 -0300307ssize_t trace_report(int fd, struct pevent **ppevent, bool __repipe)
Steven Rostedt538bafb2009-08-17 16:18:06 +0200308{
Steven Rostedt538bafb2009-08-17 16:18:06 +0200309 char buf[BUFSIZ];
310 char test[] = { 23, 8, 68 };
311 char *version;
Ingo Molnard9340c12009-09-12 10:08:34 +0200312 int show_version = 0;
Steven Rostedt538bafb2009-08-17 16:18:06 +0200313 int show_funcs = 0;
314 int show_printk = 0;
Namhyung Kim3dce2ce2013-03-21 16:18:48 +0900315 ssize_t size = -1;
316 struct pevent *pevent;
Namhyung Kima4c98362013-03-21 16:18:49 +0900317 int err;
Namhyung Kim3dce2ce2013-03-21 16:18:48 +0900318
319 *ppevent = NULL;
Tom Zanussi92155452010-04-01 23:59:21 -0500320
321 calc_data_size = 1;
Tom Zanussi454c4072010-05-01 01:41:20 -0500322 repipe = __repipe;
Steven Rostedt538bafb2009-08-17 16:18:06 +0200323
Frederic Weisbecker03456a12009-10-06 23:36:47 +0200324 input_fd = fd;
Steven Rostedt538bafb2009-08-17 16:18:06 +0200325
326 read_or_die(buf, 3);
327 if (memcmp(buf, test, 3) != 0)
Arnaldo Carvalho de Meloe2561362009-11-21 14:31:26 -0200328 die("no trace data in the file");
Steven Rostedt538bafb2009-08-17 16:18:06 +0200329
330 read_or_die(buf, 7);
331 if (memcmp(buf, "tracing", 7) != 0)
Arnaldo Carvalho de Meloe2561362009-11-21 14:31:26 -0200332 die("not a trace file (missing 'tracing' tag)");
Steven Rostedt538bafb2009-08-17 16:18:06 +0200333
334 version = read_string();
Namhyung Kima4c98362013-03-21 16:18:49 +0900335 if (version == NULL)
336 return -1;
Ingo Molnard9340c12009-09-12 10:08:34 +0200337 if (show_version)
338 printf("version = %s\n", version);
Steven Rostedt538bafb2009-08-17 16:18:06 +0200339 free(version);
340
341 read_or_die(buf, 1);
342 file_bigendian = buf[0];
343 host_bigendian = bigendian();
344
Namhyung Kim3dce2ce2013-03-21 16:18:48 +0900345 pevent = read_trace_init(file_bigendian, host_bigendian);
346 if (pevent == NULL) {
347 pr_debug("read_trace_init failed");
348 goto out;
349 }
Steven Rostedtaaf045f2012-04-06 00:47:56 +0200350
Steven Rostedt538bafb2009-08-17 16:18:06 +0200351 read_or_die(buf, 1);
352 long_size = buf[0];
353
Namhyung Kim3dce2ce2013-03-21 16:18:48 +0900354 page_size = read4(pevent);
Steven Rostedt538bafb2009-08-17 16:18:06 +0200355
Namhyung Kima4c98362013-03-21 16:18:49 +0900356 err = read_header_files(pevent);
357 if (err)
358 goto out;
359 err = read_ftrace_files(pevent);
360 if (err)
361 goto out;
362 err = read_event_files(pevent);
363 if (err)
364 goto out;
365 err = read_proc_kallsyms(pevent);
366 if (err)
367 goto out;
368 err = read_ftrace_printk(pevent);
369 if (err)
370 goto out;
Steven Rostedt538bafb2009-08-17 16:18:06 +0200371
Tom Zanussi92155452010-04-01 23:59:21 -0500372 size = calc_data_size - 1;
373 calc_data_size = 0;
Tom Zanussi454c4072010-05-01 01:41:20 -0500374 repipe = false;
Tom Zanussi92155452010-04-01 23:59:21 -0500375
Steven Rostedt538bafb2009-08-17 16:18:06 +0200376 if (show_funcs) {
Namhyung Kim3dce2ce2013-03-21 16:18:48 +0900377 pevent_print_funcs(pevent);
378 } else if (show_printk) {
379 pevent_print_printk(pevent);
Steven Rostedt538bafb2009-08-17 16:18:06 +0200380 }
381
Namhyung Kim3dce2ce2013-03-21 16:18:48 +0900382 *ppevent = pevent;
383 pevent = NULL;
384
385out:
386 if (pevent)
387 pevent_free(pevent);
Tom Zanussi92155452010-04-01 23:59:21 -0500388 return size;
Steven Rostedt538bafb2009-08-17 16:18:06 +0200389}