blob: ba752d765ac3483393c19ececb904ec6191d607a [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
Steven Rostedtaaf045f2012-04-06 00:47:56 +020049static void *malloc_or_die(int size)
50{
51 void *ret;
52
53 ret = malloc(size);
54 if (!ret)
55 die("malloc");
56 return ret;
57}
58
Tom Zanussi92155452010-04-01 23:59:21 -050059static int do_read(int fd, void *buf, int size)
60{
61 int rsize = size;
62
63 while (size) {
64 int ret = read(fd, buf, size);
65
66 if (ret <= 0)
67 return -1;
68
Tom Zanussi454c4072010-05-01 01:41:20 -050069 if (repipe) {
70 int retw = write(STDOUT_FILENO, buf, ret);
71
72 if (retw <= 0 || retw != ret)
73 die("repiping input file");
74 }
75
Tom Zanussi92155452010-04-01 23:59:21 -050076 size -= ret;
77 buf += ret;
78 }
79
80 return rsize;
81}
82
Steven Rostedt538bafb2009-08-17 16:18:06 +020083static int read_or_die(void *data, int size)
84{
85 int r;
86
Tom Zanussi92155452010-04-01 23:59:21 -050087 r = do_read(input_fd, data, size);
88 if (r <= 0)
Steven Rostedt538bafb2009-08-17 16:18:06 +020089 die("reading input file (size expected=%d received=%d)",
90 size, r);
Tom Zanussi92155452010-04-01 23:59:21 -050091
92 if (calc_data_size)
93 calc_data_size += r;
94
Steven Rostedt538bafb2009-08-17 16:18:06 +020095 return r;
96}
97
Tom Zanussicbb5cf72010-05-04 23:02:10 -050098/* If it fails, the next read will report it */
99static void skip(int size)
100{
101 char buf[BUFSIZ];
102 int r;
103
104 while (size) {
105 r = size > BUFSIZ ? BUFSIZ : size;
106 read_or_die(buf, r);
107 size -= r;
108 };
109}
110
Arnaldo Carvalho de Meloda378962012-06-27 13:08:42 -0300111static unsigned int read4(struct pevent *pevent)
Steven Rostedt538bafb2009-08-17 16:18:06 +0200112{
113 unsigned int data;
114
115 read_or_die(&data, 4);
Arnaldo Carvalho de Meloda378962012-06-27 13:08:42 -0300116 return __data2host4(pevent, data);
Steven Rostedt538bafb2009-08-17 16:18:06 +0200117}
118
Arnaldo Carvalho de Meloda378962012-06-27 13:08:42 -0300119static unsigned long long read8(struct pevent *pevent)
Steven Rostedt538bafb2009-08-17 16:18:06 +0200120{
121 unsigned long long data;
122
123 read_or_die(&data, 8);
Arnaldo Carvalho de Meloda378962012-06-27 13:08:42 -0300124 return __data2host8(pevent, data);
Steven Rostedt538bafb2009-08-17 16:18:06 +0200125}
126
127static char *read_string(void)
128{
129 char buf[BUFSIZ];
130 char *str = NULL;
131 int size = 0;
Xiao Guangrongf887f302010-02-04 16:46:42 +0800132 off_t r;
Tom Zanussi92155452010-04-01 23:59:21 -0500133 char c;
Steven Rostedt538bafb2009-08-17 16:18:06 +0200134
135 for (;;) {
Tom Zanussi92155452010-04-01 23:59:21 -0500136 r = read(input_fd, &c, 1);
Steven Rostedt538bafb2009-08-17 16:18:06 +0200137 if (r < 0)
138 die("reading input file");
139
140 if (!r)
141 die("no data");
142
Tom Zanussi454c4072010-05-01 01:41:20 -0500143 if (repipe) {
144 int retw = write(STDOUT_FILENO, &c, 1);
145
146 if (retw <= 0 || retw != r)
147 die("repiping input file string");
148 }
149
Tom Zanussi92155452010-04-01 23:59:21 -0500150 buf[size++] = c;
151
152 if (!c)
Steven Rostedt538bafb2009-08-17 16:18:06 +0200153 break;
Steven Rostedt538bafb2009-08-17 16:18:06 +0200154 }
155
Tom Zanussi92155452010-04-01 23:59:21 -0500156 if (calc_data_size)
157 calc_data_size += size;
Ingo Molnar6f4596d2009-09-03 16:22:45 +0200158
Tom Zanussi92155452010-04-01 23:59:21 -0500159 str = malloc_or_die(size);
160 memcpy(str, buf, size);
Steven Rostedt538bafb2009-08-17 16:18:06 +0200161
162 return str;
163}
164
Arnaldo Carvalho de Meloda378962012-06-27 13:08:42 -0300165static void read_proc_kallsyms(struct pevent *pevent)
Steven Rostedt538bafb2009-08-17 16:18:06 +0200166{
167 unsigned int size;
168 char *buf;
169
Arnaldo Carvalho de Meloda378962012-06-27 13:08:42 -0300170 size = read4(pevent);
Steven Rostedt538bafb2009-08-17 16:18:06 +0200171 if (!size)
172 return;
173
OGAWA Hirofumi7691b1e2009-12-06 20:10:49 +0900174 buf = malloc_or_die(size + 1);
Steven Rostedt538bafb2009-08-17 16:18:06 +0200175 read_or_die(buf, size);
OGAWA Hirofumi7691b1e2009-12-06 20:10:49 +0900176 buf[size] = '\0';
Steven Rostedt538bafb2009-08-17 16:18:06 +0200177
Arnaldo Carvalho de Meloda378962012-06-27 13:08:42 -0300178 parse_proc_kallsyms(pevent, buf, size);
Steven Rostedt538bafb2009-08-17 16:18:06 +0200179
180 free(buf);
181}
182
Arnaldo Carvalho de Meloda378962012-06-27 13:08:42 -0300183static void read_ftrace_printk(struct pevent *pevent)
Steven Rostedt538bafb2009-08-17 16:18:06 +0200184{
185 unsigned int size;
186 char *buf;
187
Arnaldo Carvalho de Meloda378962012-06-27 13:08:42 -0300188 size = read4(pevent);
Steven Rostedt538bafb2009-08-17 16:18:06 +0200189 if (!size)
190 return;
191
192 buf = malloc_or_die(size);
193 read_or_die(buf, size);
194
Arnaldo Carvalho de Meloda378962012-06-27 13:08:42 -0300195 parse_ftrace_printk(pevent, buf, size);
Steven Rostedt538bafb2009-08-17 16:18:06 +0200196
197 free(buf);
198}
199
Arnaldo Carvalho de Meloda378962012-06-27 13:08:42 -0300200static void read_header_files(struct pevent *pevent)
Steven Rostedt538bafb2009-08-17 16:18:06 +0200201{
202 unsigned long long size;
Steven Rostedt538bafb2009-08-17 16:18:06 +0200203 char *header_event;
204 char buf[BUFSIZ];
205
206 read_or_die(buf, 12);
207
208 if (memcmp(buf, "header_page", 12) != 0)
209 die("did not read header page");
210
Arnaldo Carvalho de Meloda378962012-06-27 13:08:42 -0300211 size = read8(pevent);
Frederic Weisbeckerd00a47c2010-05-01 03:08:46 +0200212 skip(size);
Steven Rostedt538bafb2009-08-17 16:18:06 +0200213
214 /*
215 * The size field in the page is of type long,
216 * use that instead, since it represents the kernel.
217 */
218 long_size = header_page_size_size;
219
220 read_or_die(buf, 13);
221 if (memcmp(buf, "header_event", 13) != 0)
222 die("did not read header event");
223
Arnaldo Carvalho de Meloda378962012-06-27 13:08:42 -0300224 size = read8(pevent);
Steven Rostedt538bafb2009-08-17 16:18:06 +0200225 header_event = malloc_or_die(size);
226 read_or_die(header_event, size);
227 free(header_event);
228}
229
Arnaldo Carvalho de Meloda378962012-06-27 13:08:42 -0300230static void read_ftrace_file(struct pevent *pevent, unsigned long long size)
Steven Rostedt538bafb2009-08-17 16:18:06 +0200231{
232 char *buf;
233
234 buf = malloc_or_die(size);
235 read_or_die(buf, size);
Arnaldo Carvalho de Meloda378962012-06-27 13:08:42 -0300236 parse_ftrace_file(pevent, buf, size);
Steven Rostedt538bafb2009-08-17 16:18:06 +0200237 free(buf);
238}
239
Arnaldo Carvalho de Meloda378962012-06-27 13:08:42 -0300240static void read_event_file(struct pevent *pevent, char *sys,
241 unsigned long long size)
Steven Rostedt538bafb2009-08-17 16:18:06 +0200242{
243 char *buf;
244
245 buf = malloc_or_die(size);
246 read_or_die(buf, size);
Arnaldo Carvalho de Meloda378962012-06-27 13:08:42 -0300247 parse_event_file(pevent, buf, size, sys);
Steven Rostedt538bafb2009-08-17 16:18:06 +0200248 free(buf);
249}
250
Arnaldo Carvalho de Meloda378962012-06-27 13:08:42 -0300251static void read_ftrace_files(struct pevent *pevent)
Steven Rostedt538bafb2009-08-17 16:18:06 +0200252{
253 unsigned long long size;
254 int count;
255 int i;
256
Arnaldo Carvalho de Meloda378962012-06-27 13:08:42 -0300257 count = read4(pevent);
Steven Rostedt538bafb2009-08-17 16:18:06 +0200258
259 for (i = 0; i < count; i++) {
Arnaldo Carvalho de Meloda378962012-06-27 13:08:42 -0300260 size = read8(pevent);
261 read_ftrace_file(pevent, size);
Steven Rostedt538bafb2009-08-17 16:18:06 +0200262 }
263}
264
Arnaldo Carvalho de Meloda378962012-06-27 13:08:42 -0300265static void read_event_files(struct pevent *pevent)
Steven Rostedt538bafb2009-08-17 16:18:06 +0200266{
267 unsigned long long size;
268 char *sys;
269 int systems;
270 int count;
271 int i,x;
272
Arnaldo Carvalho de Meloda378962012-06-27 13:08:42 -0300273 systems = read4(pevent);
Steven Rostedt538bafb2009-08-17 16:18:06 +0200274
275 for (i = 0; i < systems; i++) {
276 sys = read_string();
277
Arnaldo Carvalho de Meloda378962012-06-27 13:08:42 -0300278 count = read4(pevent);
Steven Rostedt538bafb2009-08-17 16:18:06 +0200279 for (x=0; x < count; x++) {
Arnaldo Carvalho de Meloda378962012-06-27 13:08:42 -0300280 size = read8(pevent);
281 read_event_file(pevent, sys, size);
Steven Rostedt538bafb2009-08-17 16:18:06 +0200282 }
283 }
284}
285
Arnaldo Carvalho de Meloda378962012-06-27 13:08:42 -0300286ssize_t trace_report(int fd, struct pevent **ppevent, bool __repipe)
Steven Rostedt538bafb2009-08-17 16:18:06 +0200287{
Steven Rostedt538bafb2009-08-17 16:18:06 +0200288 char buf[BUFSIZ];
289 char test[] = { 23, 8, 68 };
290 char *version;
Ingo Molnard9340c12009-09-12 10:08:34 +0200291 int show_version = 0;
Steven Rostedt538bafb2009-08-17 16:18:06 +0200292 int show_funcs = 0;
293 int show_printk = 0;
Namhyung Kim3dce2ce2013-03-21 16:18:48 +0900294 ssize_t size = -1;
295 struct pevent *pevent;
296
297 *ppevent = NULL;
Tom Zanussi92155452010-04-01 23:59:21 -0500298
299 calc_data_size = 1;
Tom Zanussi454c4072010-05-01 01:41:20 -0500300 repipe = __repipe;
Steven Rostedt538bafb2009-08-17 16:18:06 +0200301
Frederic Weisbecker03456a12009-10-06 23:36:47 +0200302 input_fd = fd;
Steven Rostedt538bafb2009-08-17 16:18:06 +0200303
304 read_or_die(buf, 3);
305 if (memcmp(buf, test, 3) != 0)
Arnaldo Carvalho de Meloe2561362009-11-21 14:31:26 -0200306 die("no trace data in the file");
Steven Rostedt538bafb2009-08-17 16:18:06 +0200307
308 read_or_die(buf, 7);
309 if (memcmp(buf, "tracing", 7) != 0)
Arnaldo Carvalho de Meloe2561362009-11-21 14:31:26 -0200310 die("not a trace file (missing 'tracing' tag)");
Steven Rostedt538bafb2009-08-17 16:18:06 +0200311
312 version = read_string();
Ingo Molnard9340c12009-09-12 10:08:34 +0200313 if (show_version)
314 printf("version = %s\n", version);
Steven Rostedt538bafb2009-08-17 16:18:06 +0200315 free(version);
316
317 read_or_die(buf, 1);
318 file_bigendian = buf[0];
319 host_bigendian = bigendian();
320
Namhyung Kim3dce2ce2013-03-21 16:18:48 +0900321 pevent = read_trace_init(file_bigendian, host_bigendian);
322 if (pevent == NULL) {
323 pr_debug("read_trace_init failed");
324 goto out;
325 }
Steven Rostedtaaf045f2012-04-06 00:47:56 +0200326
Steven Rostedt538bafb2009-08-17 16:18:06 +0200327 read_or_die(buf, 1);
328 long_size = buf[0];
329
Namhyung Kim3dce2ce2013-03-21 16:18:48 +0900330 page_size = read4(pevent);
Steven Rostedt538bafb2009-08-17 16:18:06 +0200331
Namhyung Kim3dce2ce2013-03-21 16:18:48 +0900332 read_header_files(pevent);
333 read_ftrace_files(pevent);
334 read_event_files(pevent);
335 read_proc_kallsyms(pevent);
336 read_ftrace_printk(pevent);
Steven Rostedt538bafb2009-08-17 16:18:06 +0200337
Tom Zanussi92155452010-04-01 23:59:21 -0500338 size = calc_data_size - 1;
339 calc_data_size = 0;
Tom Zanussi454c4072010-05-01 01:41:20 -0500340 repipe = false;
Tom Zanussi92155452010-04-01 23:59:21 -0500341
Steven Rostedt538bafb2009-08-17 16:18:06 +0200342 if (show_funcs) {
Namhyung Kim3dce2ce2013-03-21 16:18:48 +0900343 pevent_print_funcs(pevent);
344 } else if (show_printk) {
345 pevent_print_printk(pevent);
Steven Rostedt538bafb2009-08-17 16:18:06 +0200346 }
347
Namhyung Kim3dce2ce2013-03-21 16:18:48 +0900348 *ppevent = pevent;
349 pevent = NULL;
350
351out:
352 if (pevent)
353 pevent_free(pevent);
Tom Zanussi92155452010-04-01 23:59:21 -0500354 return size;
Steven Rostedt538bafb2009-08-17 16:18:06 +0200355}