perf tools: Get rid of redundant _FILE_OFFSET_BITS definition
[linux-3.10.git] / tools / perf / util / trace-event-read.c
1 /*
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  */
21 #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>
34 #include <errno.h>
35
36 #include "../perf.h"
37 #include "util.h"
38 #include "trace-event.h"
39
40 static int input_fd;
41
42 int file_bigendian;
43 int host_bigendian;
44 static int long_size;
45
46 static ssize_t calc_data_size;
47 static bool repipe;
48
49 static 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
59 static 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
69                 if (repipe) {
70                         int retw = write(STDOUT_FILENO, buf, ret);
71
72                         if (retw <= 0 || retw != ret)
73                                 die("repiping input file");
74                 }
75
76                 size -= ret;
77                 buf += ret;
78         }
79
80         return rsize;
81 }
82
83 static int read_or_die(void *data, int size)
84 {
85         int r;
86
87         r = do_read(input_fd, data, size);
88         if (r <= 0)
89                 die("reading input file (size expected=%d received=%d)",
90                     size, r);
91
92         if (calc_data_size)
93                 calc_data_size += r;
94
95         return r;
96 }
97
98 /* If it fails, the next read will report it */
99 static 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
111 static unsigned int read4(struct pevent *pevent)
112 {
113         unsigned int data;
114
115         read_or_die(&data, 4);
116         return __data2host4(pevent, data);
117 }
118
119 static unsigned long long read8(struct pevent *pevent)
120 {
121         unsigned long long data;
122
123         read_or_die(&data, 8);
124         return __data2host8(pevent, data);
125 }
126
127 static char *read_string(void)
128 {
129         char buf[BUFSIZ];
130         char *str = NULL;
131         int size = 0;
132         off_t r;
133         char c;
134
135         for (;;) {
136                 r = read(input_fd, &c, 1);
137                 if (r < 0)
138                         die("reading input file");
139
140                 if (!r)
141                         die("no data");
142
143                 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
150                 buf[size++] = c;
151
152                 if (!c)
153                         break;
154         }
155
156         if (calc_data_size)
157                 calc_data_size += size;
158
159         str = malloc_or_die(size);
160         memcpy(str, buf, size);
161
162         return str;
163 }
164
165 static void read_proc_kallsyms(struct pevent *pevent)
166 {
167         unsigned int size;
168         char *buf;
169
170         size = read4(pevent);
171         if (!size)
172                 return;
173
174         buf = malloc_or_die(size + 1);
175         read_or_die(buf, size);
176         buf[size] = '\0';
177
178         parse_proc_kallsyms(pevent, buf, size);
179
180         free(buf);
181 }
182
183 static void read_ftrace_printk(struct pevent *pevent)
184 {
185         unsigned int size;
186         char *buf;
187
188         size = read4(pevent);
189         if (!size)
190                 return;
191
192         buf = malloc_or_die(size);
193         read_or_die(buf, size);
194
195         parse_ftrace_printk(pevent, buf, size);
196
197         free(buf);
198 }
199
200 static void read_header_files(struct pevent *pevent)
201 {
202         unsigned long long size;
203         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
211         size = read8(pevent);
212         skip(size);
213
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
224         size = read8(pevent);
225         header_event = malloc_or_die(size);
226         read_or_die(header_event, size);
227         free(header_event);
228 }
229
230 static void read_ftrace_file(struct pevent *pevent, unsigned long long size)
231 {
232         char *buf;
233
234         buf = malloc_or_die(size);
235         read_or_die(buf, size);
236         parse_ftrace_file(pevent, buf, size);
237         free(buf);
238 }
239
240 static void read_event_file(struct pevent *pevent, char *sys,
241                             unsigned long long size)
242 {
243         char *buf;
244
245         buf = malloc_or_die(size);
246         read_or_die(buf, size);
247         parse_event_file(pevent, buf, size, sys);
248         free(buf);
249 }
250
251 static void read_ftrace_files(struct pevent *pevent)
252 {
253         unsigned long long size;
254         int count;
255         int i;
256
257         count = read4(pevent);
258
259         for (i = 0; i < count; i++) {
260                 size = read8(pevent);
261                 read_ftrace_file(pevent, size);
262         }
263 }
264
265 static void read_event_files(struct pevent *pevent)
266 {
267         unsigned long long size;
268         char *sys;
269         int systems;
270         int count;
271         int i,x;
272
273         systems = read4(pevent);
274
275         for (i = 0; i < systems; i++) {
276                 sys = read_string();
277
278                 count = read4(pevent);
279                 for (x=0; x < count; x++) {
280                         size = read8(pevent);
281                         read_event_file(pevent, sys, size);
282                 }
283         }
284 }
285
286 ssize_t trace_report(int fd, struct pevent **ppevent, bool __repipe)
287 {
288         char buf[BUFSIZ];
289         char test[] = { 23, 8, 68 };
290         char *version;
291         int show_version = 0;
292         int show_funcs = 0;
293         int show_printk = 0;
294         ssize_t size;
295
296         calc_data_size = 1;
297         repipe = __repipe;
298
299         input_fd = fd;
300
301         read_or_die(buf, 3);
302         if (memcmp(buf, test, 3) != 0)
303                 die("no trace data in the file");
304
305         read_or_die(buf, 7);
306         if (memcmp(buf, "tracing", 7) != 0)
307                 die("not a trace file (missing 'tracing' tag)");
308
309         version = read_string();
310         if (show_version)
311                 printf("version = %s\n", version);
312         free(version);
313
314         read_or_die(buf, 1);
315         file_bigendian = buf[0];
316         host_bigendian = bigendian();
317
318         *ppevent = read_trace_init(file_bigendian, host_bigendian);
319         if (*ppevent == NULL)
320                 die("read_trace_init failed");
321
322         read_or_die(buf, 1);
323         long_size = buf[0];
324
325         page_size = read4(*ppevent);
326
327         read_header_files(*ppevent);
328
329         read_ftrace_files(*ppevent);
330         read_event_files(*ppevent);
331         read_proc_kallsyms(*ppevent);
332         read_ftrace_printk(*ppevent);
333
334         size = calc_data_size - 1;
335         calc_data_size = 0;
336         repipe = false;
337
338         if (show_funcs) {
339                 pevent_print_funcs(*ppevent);
340                 return size;
341         }
342         if (show_printk) {
343                 pevent_print_printk(*ppevent);
344                 return size;
345         }
346
347         return size;
348 }