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>
41 #include "trace-event.h"
51 static unsigned long page_size
;
53 static ssize_t calc_data_size
;
56 static int do_read(int fd
, void *buf
, int size
)
61 int ret
= read(fd
, buf
, size
);
67 int retw
= write(STDOUT_FILENO
, buf
, ret
);
69 if (retw
<= 0 || retw
!= ret
)
70 die("repiping input file");
80 static int read_or_die(void *data
, int size
)
84 r
= do_read(input_fd
, data
, size
);
86 die("reading input file (size expected=%d received=%d)",
95 /* If it fails, the next read will report it */
96 static void skip(int size
)
102 r
= size
> BUFSIZ
? BUFSIZ
: size
;
108 static unsigned int read4(void)
112 read_or_die(&data
, 4);
113 return __data2host4(data
);
116 static unsigned long long read8(void)
118 unsigned long long data
;
120 read_or_die(&data
, 8);
121 return __data2host8(data
);
124 static char *read_string(void)
133 r
= read(input_fd
, &c
, 1);
135 die("reading input file");
141 int retw
= write(STDOUT_FILENO
, &c
, 1);
143 if (retw
<= 0 || retw
!= r
)
144 die("repiping input file string");
154 calc_data_size
+= size
;
156 str
= malloc_or_die(size
);
157 memcpy(str
, buf
, size
);
162 static void read_proc_kallsyms(void)
171 buf
= malloc_or_die(size
+ 1);
172 read_or_die(buf
, size
);
175 parse_proc_kallsyms(buf
, size
);
180 static void read_ftrace_printk(void)
189 buf
= malloc_or_die(size
);
190 read_or_die(buf
, size
);
192 parse_ftrace_printk(buf
, size
);
197 static void read_header_files(void)
199 unsigned long long size
;
203 read_or_die(buf
, 12);
205 if (memcmp(buf
, "header_page", 12) != 0)
206 die("did not read header page");
212 * The size field in the page is of type long,
213 * use that instead, since it represents the kernel.
215 long_size
= header_page_size_size
;
217 read_or_die(buf
, 13);
218 if (memcmp(buf
, "header_event", 13) != 0)
219 die("did not read header event");
222 header_event
= malloc_or_die(size
);
223 read_or_die(header_event
, size
);
227 static void read_ftrace_file(unsigned long long size
)
231 buf
= malloc_or_die(size
);
232 read_or_die(buf
, size
);
233 parse_ftrace_file(buf
, size
);
237 static void read_event_file(char *sys
, unsigned long long size
)
241 buf
= malloc_or_die(size
);
242 read_or_die(buf
, size
);
243 parse_event_file(buf
, size
, sys
);
247 static void read_ftrace_files(void)
249 unsigned long long size
;
255 for (i
= 0; i
< count
; i
++) {
257 read_ftrace_file(size
);
261 static void read_event_files(void)
263 unsigned long long size
;
271 for (i
= 0; i
< systems
; i
++) {
275 for (x
=0; x
< count
; x
++) {
277 read_event_file(sys
, size
);
283 unsigned long long offset
;
284 unsigned long long size
;
285 unsigned long long timestamp
;
293 static struct cpu_data
*cpu_data
;
295 static void update_cpu_data_index(int cpu
)
297 cpu_data
[cpu
].offset
+= page_size
;
298 cpu_data
[cpu
].size
-= page_size
;
299 cpu_data
[cpu
].index
= 0;
302 static void get_next_page(int cpu
)
307 if (!cpu_data
[cpu
].page
)
311 if (cpu_data
[cpu
].size
<= page_size
) {
312 free(cpu_data
[cpu
].page
);
313 cpu_data
[cpu
].page
= NULL
;
317 update_cpu_data_index(cpu
);
319 /* other parts of the code may expect the pointer to not move */
320 save_seek
= lseek(input_fd
, 0, SEEK_CUR
);
322 ret
= lseek(input_fd
, cpu_data
[cpu
].offset
, SEEK_SET
);
323 if (ret
== (off_t
)-1)
324 die("failed to lseek");
325 ret
= read(input_fd
, cpu_data
[cpu
].page
, page_size
);
327 die("failed to read page");
329 /* reset the file pointer back */
330 lseek(input_fd
, save_seek
, SEEK_SET
);
335 munmap(cpu_data
[cpu
].page
, page_size
);
336 cpu_data
[cpu
].page
= NULL
;
338 if (cpu_data
[cpu
].size
<= page_size
)
341 update_cpu_data_index(cpu
);
343 cpu_data
[cpu
].page
= mmap(NULL
, page_size
, PROT_READ
, MAP_PRIVATE
,
344 input_fd
, cpu_data
[cpu
].offset
);
345 if (cpu_data
[cpu
].page
== MAP_FAILED
)
346 die("failed to mmap cpu %d at offset 0x%llx",
347 cpu
, cpu_data
[cpu
].offset
);
350 static unsigned int type_len4host(unsigned int type_len_ts
)
353 return (type_len_ts
>> 27) & ((1 << 5) - 1);
355 return type_len_ts
& ((1 << 5) - 1);
358 static unsigned int ts4host(unsigned int type_len_ts
)
361 return type_len_ts
& ((1 << 27) - 1);
363 return type_len_ts
>> 5;
366 static int calc_index(void *ptr
, int cpu
)
368 return (unsigned long)ptr
- (unsigned long)cpu_data
[cpu
].page
;
371 struct record
*trace_peek_data(int cpu
)
374 void *page
= cpu_data
[cpu
].page
;
375 int idx
= cpu_data
[cpu
].index
;
376 void *ptr
= page
+ idx
;
377 unsigned long long extend
;
378 unsigned int type_len_ts
;
379 unsigned int type_len
;
381 unsigned int length
= 0;
383 if (cpu_data
[cpu
].next
)
384 return cpu_data
[cpu
].next
;
390 /* FIXME: handle header page */
391 if (header_page_ts_size
!= 8)
392 die("expected a long long type for timestamp");
393 cpu_data
[cpu
].timestamp
= data2host8(ptr
);
395 switch (header_page_size_size
) {
397 cpu_data
[cpu
].page_size
= data2host4(ptr
);
401 cpu_data
[cpu
].page_size
= data2host8(ptr
);
405 die("bad long size");
407 ptr
= cpu_data
[cpu
].page
+ header_page_data_offset
;
411 idx
= calc_index(ptr
, cpu
);
413 if (idx
>= cpu_data
[cpu
].page_size
) {
415 return trace_peek_data(cpu
);
418 type_len_ts
= data2host4(ptr
);
421 type_len
= type_len4host(type_len_ts
);
422 delta
= ts4host(type_len_ts
);
425 case RINGBUF_TYPE_PADDING
:
427 die("error, hit unexpected end of page");
428 length
= data2host4(ptr
);
434 case RINGBUF_TYPE_TIME_EXTEND
:
435 extend
= data2host4(ptr
);
439 cpu_data
[cpu
].timestamp
+= extend
;
442 case RINGBUF_TYPE_TIME_STAMP
:
446 length
= data2host4(ptr
);
448 die("here! length=%d", length
);
451 length
= type_len
* 4;
455 cpu_data
[cpu
].timestamp
+= delta
;
457 data
= malloc_or_die(sizeof(*data
));
458 memset(data
, 0, sizeof(*data
));
460 data
->ts
= cpu_data
[cpu
].timestamp
;
465 cpu_data
[cpu
].index
= calc_index(ptr
, cpu
);
466 cpu_data
[cpu
].next
= data
;
471 struct record
*trace_read_data(int cpu
)
475 data
= trace_peek_data(cpu
);
476 cpu_data
[cpu
].next
= NULL
;
481 ssize_t
trace_report(int fd
, bool __repipe
)
484 char test
[] = { 23, 8, 68 };
486 int show_version
= 0;
497 if (memcmp(buf
, test
, 3) != 0)
498 die("no trace data in the file");
501 if (memcmp(buf
, "tracing", 7) != 0)
502 die("not a trace file (missing 'tracing' tag)");
504 version
= read_string();
506 printf("version = %s\n", version
);
510 file_bigendian
= buf
[0];
511 host_bigendian
= bigendian();
522 read_proc_kallsyms();
523 read_ftrace_printk();
525 size
= calc_data_size
- 1;