2 * Copyright (C) 2009, Steven Rostedt <srostedt@redhat.com>
4 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
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!)
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.
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
19 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
21 #define _FILE_OFFSET_BITS 64
29 #include <sys/types.h>
40 #include "trace-event.h"
50 static ssize_t calc_data_size
;
53 static void *malloc_or_die(int size
)
63 static int do_read(int fd
, void *buf
, int size
)
68 int ret
= read(fd
, buf
, size
);
74 int retw
= write(STDOUT_FILENO
, buf
, ret
);
76 if (retw
<= 0 || retw
!= ret
)
77 die("repiping input file");
87 static int read_or_die(void *data
, int size
)
91 r
= do_read(input_fd
, data
, size
);
93 die("reading input file (size expected=%d received=%d)",
102 /* If it fails, the next read will report it */
103 static void skip(int size
)
109 r
= size
> BUFSIZ
? BUFSIZ
: size
;
115 static unsigned int read4(struct pevent
*pevent
)
119 read_or_die(&data
, 4);
120 return __data2host4(pevent
, data
);
123 static unsigned long long read8(struct pevent
*pevent
)
125 unsigned long long data
;
127 read_or_die(&data
, 8);
128 return __data2host8(pevent
, data
);
131 static char *read_string(void)
140 r
= read(input_fd
, &c
, 1);
142 die("reading input file");
148 int retw
= write(STDOUT_FILENO
, &c
, 1);
150 if (retw
<= 0 || retw
!= r
)
151 die("repiping input file string");
161 calc_data_size
+= size
;
163 str
= malloc_or_die(size
);
164 memcpy(str
, buf
, size
);
169 static void read_proc_kallsyms(struct pevent
*pevent
)
174 size
= read4(pevent
);
178 buf
= malloc_or_die(size
+ 1);
179 read_or_die(buf
, size
);
182 parse_proc_kallsyms(pevent
, buf
, size
);
187 static void read_ftrace_printk(struct pevent
*pevent
)
192 size
= read4(pevent
);
196 buf
= malloc_or_die(size
);
197 read_or_die(buf
, size
);
199 parse_ftrace_printk(pevent
, buf
, size
);
204 static void read_header_files(struct pevent
*pevent
)
206 unsigned long long size
;
210 read_or_die(buf
, 12);
212 if (memcmp(buf
, "header_page", 12) != 0)
213 die("did not read header page");
215 size
= read8(pevent
);
219 * The size field in the page is of type long,
220 * use that instead, since it represents the kernel.
222 long_size
= header_page_size_size
;
224 read_or_die(buf
, 13);
225 if (memcmp(buf
, "header_event", 13) != 0)
226 die("did not read header event");
228 size
= read8(pevent
);
229 header_event
= malloc_or_die(size
);
230 read_or_die(header_event
, size
);
234 static void read_ftrace_file(struct pevent
*pevent
, unsigned long long size
)
238 buf
= malloc_or_die(size
);
239 read_or_die(buf
, size
);
240 parse_ftrace_file(pevent
, buf
, size
);
244 static void read_event_file(struct pevent
*pevent
, char *sys
,
245 unsigned long long size
)
249 buf
= malloc_or_die(size
);
250 read_or_die(buf
, size
);
251 parse_event_file(pevent
, buf
, size
, sys
);
255 static void read_ftrace_files(struct pevent
*pevent
)
257 unsigned long long size
;
261 count
= read4(pevent
);
263 for (i
= 0; i
< count
; i
++) {
264 size
= read8(pevent
);
265 read_ftrace_file(pevent
, size
);
269 static void read_event_files(struct pevent
*pevent
)
271 unsigned long long size
;
277 systems
= read4(pevent
);
279 for (i
= 0; i
< systems
; i
++) {
282 count
= read4(pevent
);
283 for (x
=0; x
< count
; x
++) {
284 size
= read8(pevent
);
285 read_event_file(pevent
, sys
, size
);
291 unsigned long long offset
;
292 unsigned long long size
;
293 unsigned long long timestamp
;
294 struct pevent_record
*next
;
301 static struct cpu_data
*cpu_data
;
303 static void update_cpu_data_index(int cpu
)
305 cpu_data
[cpu
].offset
+= page_size
;
306 cpu_data
[cpu
].size
-= page_size
;
307 cpu_data
[cpu
].index
= 0;
310 static void get_next_page(int cpu
)
315 if (!cpu_data
[cpu
].page
)
319 if (cpu_data
[cpu
].size
<= page_size
) {
320 free(cpu_data
[cpu
].page
);
321 cpu_data
[cpu
].page
= NULL
;
325 update_cpu_data_index(cpu
);
327 /* other parts of the code may expect the pointer to not move */
328 save_seek
= lseek(input_fd
, 0, SEEK_CUR
);
330 ret
= lseek(input_fd
, cpu_data
[cpu
].offset
, SEEK_SET
);
331 if (ret
== (off_t
)-1)
332 die("failed to lseek");
333 ret
= read(input_fd
, cpu_data
[cpu
].page
, page_size
);
335 die("failed to read page");
337 /* reset the file pointer back */
338 lseek(input_fd
, save_seek
, SEEK_SET
);
343 munmap(cpu_data
[cpu
].page
, page_size
);
344 cpu_data
[cpu
].page
= NULL
;
346 if (cpu_data
[cpu
].size
<= page_size
)
349 update_cpu_data_index(cpu
);
351 cpu_data
[cpu
].page
= mmap(NULL
, page_size
, PROT_READ
, MAP_PRIVATE
,
352 input_fd
, cpu_data
[cpu
].offset
);
353 if (cpu_data
[cpu
].page
== MAP_FAILED
)
354 die("failed to mmap cpu %d at offset 0x%llx",
355 cpu
, cpu_data
[cpu
].offset
);
358 static unsigned int type_len4host(unsigned int type_len_ts
)
361 return (type_len_ts
>> 27) & ((1 << 5) - 1);
363 return type_len_ts
& ((1 << 5) - 1);
366 static unsigned int ts4host(unsigned int type_len_ts
)
369 return type_len_ts
& ((1 << 27) - 1);
371 return type_len_ts
>> 5;
374 static int calc_index(void *ptr
, int cpu
)
376 return (unsigned long)ptr
- (unsigned long)cpu_data
[cpu
].page
;
379 struct pevent_record
*trace_peek_data(struct pevent
*pevent
, int cpu
)
381 struct pevent_record
*data
;
382 void *page
= cpu_data
[cpu
].page
;
383 int idx
= cpu_data
[cpu
].index
;
384 void *ptr
= page
+ idx
;
385 unsigned long long extend
;
386 unsigned int type_len_ts
;
387 unsigned int type_len
;
389 unsigned int length
= 0;
391 if (cpu_data
[cpu
].next
)
392 return cpu_data
[cpu
].next
;
398 /* FIXME: handle header page */
399 if (header_page_ts_size
!= 8)
400 die("expected a long long type for timestamp");
401 cpu_data
[cpu
].timestamp
= data2host8(pevent
, ptr
);
403 switch (header_page_size_size
) {
405 cpu_data
[cpu
].page_size
= data2host4(pevent
, ptr
);
409 cpu_data
[cpu
].page_size
= data2host8(pevent
, ptr
);
413 die("bad long size");
415 ptr
= cpu_data
[cpu
].page
+ header_page_data_offset
;
419 idx
= calc_index(ptr
, cpu
);
421 if (idx
>= cpu_data
[cpu
].page_size
) {
423 return trace_peek_data(pevent
, cpu
);
426 type_len_ts
= data2host4(pevent
, ptr
);
429 type_len
= type_len4host(type_len_ts
);
430 delta
= ts4host(type_len_ts
);
433 case RINGBUF_TYPE_PADDING
:
435 die("error, hit unexpected end of page");
436 length
= data2host4(pevent
, ptr
);
442 case RINGBUF_TYPE_TIME_EXTEND
:
443 extend
= data2host4(pevent
, ptr
);
447 cpu_data
[cpu
].timestamp
+= extend
;
450 case RINGBUF_TYPE_TIME_STAMP
:
454 length
= data2host4(pevent
, ptr
);
456 die("here! length=%d", length
);
459 length
= type_len
* 4;
463 cpu_data
[cpu
].timestamp
+= delta
;
465 data
= malloc_or_die(sizeof(*data
));
466 memset(data
, 0, sizeof(*data
));
468 data
->ts
= cpu_data
[cpu
].timestamp
;
473 cpu_data
[cpu
].index
= calc_index(ptr
, cpu
);
474 cpu_data
[cpu
].next
= data
;
479 struct pevent_record
*trace_read_data(struct pevent
*pevent
, int cpu
)
481 struct pevent_record
*data
;
483 data
= trace_peek_data(pevent
, cpu
);
484 cpu_data
[cpu
].next
= NULL
;
489 ssize_t
trace_report(int fd
, struct pevent
**ppevent
, bool __repipe
)
492 char test
[] = { 23, 8, 68 };
494 int show_version
= 0;
505 if (memcmp(buf
, test
, 3) != 0)
506 die("no trace data in the file");
509 if (memcmp(buf
, "tracing", 7) != 0)
510 die("not a trace file (missing 'tracing' tag)");
512 version
= read_string();
514 printf("version = %s\n", version
);
518 file_bigendian
= buf
[0];
519 host_bigendian
= bigendian();
521 *ppevent
= read_trace_init(file_bigendian
, host_bigendian
);
522 if (*ppevent
== NULL
)
523 die("read_trace_init failed");
528 page_size
= read4(*ppevent
);
530 read_header_files(*ppevent
);
532 read_ftrace_files(*ppevent
);
533 read_event_files(*ppevent
);
534 read_proc_kallsyms(*ppevent
);
535 read_ftrace_printk(*ppevent
);
537 size
= calc_data_size
- 1;
542 pevent_print_funcs(*ppevent
);
546 pevent_print_printk(*ppevent
);