1 // SPDX-License-Identifier: GPL-2.0
2 /*
3 * Copyright (C) 2009, 2010 Red Hat Inc, Steven Rostedt <[email protected]>
4 *
5 * Updates:
6 * Copyright (C) 2019, VMware, Tzvetomir Stoyanov <[email protected]>
7 */
8 #include <stdlib.h>
9 #include <unistd.h>
10 #include <getopt.h>
11 #include <sys/stat.h>
12 #include <fcntl.h>
13 #include <errno.h>
14
15 #include "trace-local.h"
16
17 #define TRACING_STR "tracing"
18 #define HEAD_PAGE_STR "header_page"
19 #define HEAD_PAGE_EVENT "header_event"
20 #define HEAD_OPTIONS "options "
21 #define HEAD_LATENCY "latency "
22 #define HEAD_FLYRECORD "flyrecord"
23
24 #define DUMP_SIZE 1024
25
26 static struct tep_handle *tep;
27 static unsigned int trace_cpus;
28 static int has_clock;
29 static unsigned long file_version;
30 static bool read_compress;
31 static struct tracecmd_compression *compress;
32 static char *meta_strings;
33 static int meta_strings_size;
34
35 enum dump_items {
36 SUMMARY = (1 << 0),
37 HEAD_PAGE = (1 << 1),
38 HEAD_EVENT = (1 << 2),
39 FTRACE_FORMAT = (1 << 3),
40 EVENT_SYSTEMS = (1 << 4),
41 EVENT_FORMAT = (1 << 5),
42 KALLSYMS = (1 << 6),
43 TRACE_PRINTK = (1 << 7),
44 CMDLINES = (1 << 8),
45 OPTIONS = (1 << 9),
46 FLYRECORD = (1 << 10),
47 CLOCK = (1 << 11),
48 SECTIONS = (1 << 12),
49 STRINGS = (1 << 13),
50 };
51
52 struct file_section {
53 int id;
54 unsigned long long offset;
55 struct file_section *next;
56 enum dump_items verbosity;
57 };
58
59 static struct file_section *sections;
60
61 enum dump_items verbosity;
62
63 #define DUMP_CHECK(X) ((X) & verbosity)
64
65 #define do_print(ids, fmt, ...) \
66 do { \
67 if (!(ids) || DUMP_CHECK(ids)) \
68 tracecmd_plog(fmt, ##__VA_ARGS__); \
69 } while (0)
70
read_fd(int fd,char * dst,int len)71 static int read_fd(int fd, char *dst, int len)
72 {
73 size_t size = 0;
74 int r;
75
76 do {
77 r = read(fd, dst+size, len);
78 if (r > 0) {
79 size += r;
80 len -= r;
81 } else
82 break;
83 } while (r > 0);
84
85 if (len)
86 return -1;
87 return size;
88 }
89
read_compressed(int fd,char * dst,int len)90 static int read_compressed(int fd, char *dst, int len)
91 {
92
93 if (read_compress)
94 return tracecmd_compress_buffer_read(compress, dst, len);
95
96 return read_fd(fd, dst, len);
97 }
98
do_lseek(int fd,int offset,int whence)99 static int do_lseek(int fd, int offset, int whence)
100 {
101 if (read_compress)
102 return tracecmd_compress_lseek(compress, offset, whence);
103
104 return lseek64(fd, offset, whence);
105 }
106
read_file_string(int fd,char * dst,int len)107 static int read_file_string(int fd, char *dst, int len)
108 {
109 size_t size = 0;
110 int r;
111
112 do {
113 r = read_compressed(fd, dst+size, 1);
114 if (r > 0) {
115 size++;
116 len--;
117 } else
118 break;
119 if (!dst[size - 1])
120 break;
121 } while (r > 0 && len);
122
123 if (!size || dst[size - 1])
124 return -1;
125 return 0;
126 }
127
read_file_bytes(int fd,char * dst,int len)128 static int read_file_bytes(int fd, char *dst, int len)
129 {
130 int ret;
131
132 ret = read_compressed(fd, dst, len);
133 return ret < 0 ? ret : 0;
134 }
135
read_dump_string(int fd,int size,enum dump_items id)136 static void read_dump_string(int fd, int size, enum dump_items id)
137 {
138 char buf[DUMP_SIZE];
139 int lsize;
140
141 while (size) {
142 lsize = (size < DUMP_SIZE) ? size : DUMP_SIZE - 1;
143 if (read_file_bytes(fd, buf, lsize))
144 die("cannot read %d bytes", lsize);
145 buf[lsize] = 0;
146 do_print(id, "%s", buf);
147 size -= lsize;
148 }
149
150 do_print(id, "\n");
151 }
152
read_file_number(int fd,void * digit,int size)153 static int read_file_number(int fd, void *digit, int size)
154 {
155 unsigned long long val;
156 char buf[8];
157
158 if (size > 8)
159 return -1;
160
161 if (read_file_bytes(fd, buf, size))
162 return -1;
163
164 val = tep_read_number(tep, buf, size);
165 switch (size) {
166 case 1:
167 *((char *)digit) = val;
168 break;
169 case 2:
170 *((unsigned short *)digit) = val;
171 break;
172 case 4:
173 *((unsigned int *)digit) = val;
174 break;
175 case 8:
176 *((unsigned long long *)digit) = val;
177 break;
178 default:
179 return -1;
180 }
181
182 return 0;
183 }
184
get_metadata_string(int offset)185 static const char *get_metadata_string(int offset)
186 {
187 if (!meta_strings || offset < 0 || meta_strings_size <= offset)
188 return NULL;
189
190 return meta_strings + offset;
191 }
192
dump_initial_format(int fd)193 static void dump_initial_format(int fd)
194 {
195 char magic[] = TRACECMD_MAGIC;
196 char buf[DUMP_SIZE];
197 int val4;
198
199 do_print(SUMMARY, "\t[Initial format]\n");
200
201 /* check initial bytes */
202 if (read_file_bytes(fd, buf, sizeof(magic)))
203 die("cannot read %zu bytes magic", sizeof(magic));
204 if (memcmp(buf, magic, sizeof(magic)) != 0)
205 die("wrong file magic");
206
207 /* check initial tracing string */
208 if (read_file_bytes(fd, buf, strlen(TRACING_STR)))
209 die("cannot read %zu bytes tracing string", strlen(TRACING_STR));
210 buf[strlen(TRACING_STR)] = 0;
211 if (strncmp(buf, TRACING_STR, strlen(TRACING_STR)) != 0)
212 die("wrong tracing string: %s", buf);
213
214 /* get file version */
215 if (read_file_string(fd, buf, DUMP_SIZE))
216 die("no version string");
217
218 do_print(SUMMARY, "\t\t%s\t[Version]\n", buf);
219 file_version = strtol(buf, NULL, 10);
220 if (!file_version && errno)
221 die("Invalid file version string %s", buf);
222 if (!tracecmd_is_version_supported(file_version))
223 die("Unsupported file version %lu", file_version);
224
225 /* get file endianness*/
226 if (read_file_bytes(fd, buf, 1))
227 die("cannot read file endianness");
228 do_print(SUMMARY, "\t\t%d\t[%s endian]\n", buf[0], buf[0]?"Big":"Little");
229
230 tep_set_file_bigendian(tep, buf[0]);
231 tep_set_local_bigendian(tep, tracecmd_host_bigendian());
232
233 /* get file bytes per long*/
234 if (read_file_bytes(fd, buf, 1))
235 die("cannot read file bytes per long");
236 do_print(SUMMARY, "\t\t%d\t[Bytes in a long]\n", buf[0]);
237
238 if (read_file_number(fd, &val4, 4))
239 die("cannot read file page size");
240 do_print(SUMMARY, "\t\t%d\t[Page size, bytes]\n", val4);
241 }
242
dump_compress(int fd)243 static void dump_compress(int fd)
244 {
245 char zname[DUMP_SIZE];
246 char zver[DUMP_SIZE];
247
248 if (file_version < FILE_VERSION_COMPRESSION)
249 return;
250
251 /* get compression header */
252 if (read_file_string(fd, zname, DUMP_SIZE))
253 die("no compression header");
254
255 if (read_file_string(fd, zver, DUMP_SIZE))
256 die("no compression version");
257
258 do_print((SUMMARY), "\t\t%s\t[Compression algorithm]\n", zname);
259 do_print((SUMMARY), "\t\t%s\t[Compression version]\n", zver);
260
261 if (strcmp(zname, "none")) {
262 compress = tracecmd_compress_alloc(zname, zver, fd, tep, NULL);
263 if (!compress)
264 die("cannot uncompress the file");
265 }
266 }
267
dump_header_page(int fd)268 static void dump_header_page(int fd)
269 {
270 unsigned long long size;
271 char buf[DUMP_SIZE];
272
273 do_print((SUMMARY | HEAD_PAGE), "\t[Header page, ");
274
275 /* check header string */
276 if (read_file_bytes(fd, buf, strlen(HEAD_PAGE_STR) + 1))
277 die("cannot read %zu bytes header string", strlen(HEAD_PAGE_STR));
278 if (strncmp(buf, HEAD_PAGE_STR, strlen(HEAD_PAGE_STR)) != 0)
279 die("wrong header string: %s", buf);
280
281 if (read_file_number(fd, &size, 8))
282 die("cannot read the size of the page header information");
283
284 do_print((SUMMARY | HEAD_PAGE), "%lld bytes]\n", size);
285
286 read_dump_string(fd, size, HEAD_PAGE);
287 }
288
dump_header_event(int fd)289 static void dump_header_event(int fd)
290 {
291 unsigned long long size;
292 char buf[DUMP_SIZE];
293
294 do_print((SUMMARY | HEAD_EVENT), "\t[Header event, ");
295
296 /* check header string */
297 if (read_file_bytes(fd, buf, strlen(HEAD_PAGE_EVENT) + 1))
298 die("cannot read %zu bytes header string", strlen(HEAD_PAGE_EVENT));
299 if (strncmp(buf, HEAD_PAGE_EVENT, strlen(HEAD_PAGE_EVENT)) != 0)
300 die("wrong header string: %s", buf);
301
302 if (read_file_number(fd, &size, 8))
303 die("cannot read the size of the page header information");
304
305 do_print((SUMMARY | HEAD_EVENT), "%lld bytes]\n", size);
306
307 read_dump_string(fd, size, HEAD_EVENT);
308 }
309
uncompress_reset(void)310 static void uncompress_reset(void)
311 {
312 if (compress && file_version >= FILE_VERSION_COMPRESSION) {
313 read_compress = false;
314 tracecmd_compress_reset(compress);
315 }
316 }
317
uncompress_block(void)318 static int uncompress_block(void)
319 {
320 int ret = 0;
321
322 if (compress && file_version >= FILE_VERSION_COMPRESSION) {
323 ret = tracecmd_uncompress_block(compress);
324 if (!ret)
325 read_compress = true;
326
327 }
328
329 return ret;
330 }
331
dump_ftrace_events_format(int fd)332 static void dump_ftrace_events_format(int fd)
333 {
334 unsigned long long size;
335 unsigned int count;
336
337 do_print((SUMMARY | FTRACE_FORMAT), "\t[Ftrace format, ");
338 if (read_file_number(fd, &count, 4))
339 die("cannot read the count of the ftrace events");
340
341 do_print((SUMMARY | FTRACE_FORMAT), "%d events]\n", count);
342
343 while (count) {
344 if (read_file_number(fd, &size, 8))
345 die("cannot read the size of the %d ftrace event", count);
346 read_dump_string(fd, size, FTRACE_FORMAT);
347 count--;
348 }
349 }
350
dump_events_format(int fd)351 static void dump_events_format(int fd)
352 {
353 unsigned long long size;
354 unsigned int systems;
355 unsigned int events;
356 char buf[DUMP_SIZE];
357
358 do_print((SUMMARY | EVENT_FORMAT | EVENT_SYSTEMS), "\t[Events format, ");
359
360 if (read_file_number(fd, &systems, 4))
361 die("cannot read the count of the event systems");
362
363 do_print((SUMMARY | EVENT_FORMAT | EVENT_SYSTEMS), "%d systems]\n", systems);
364
365 while (systems) {
366
367 if (read_file_string(fd, buf, DUMP_SIZE))
368 die("cannot read the name of the %dth system", systems);
369 if (read_file_number(fd, &events, 4))
370 die("cannot read the count of the events in system %s",
371 buf);
372 do_print(EVENT_SYSTEMS, "\t\t%s %d [system, events]\n", buf, events);
373 while (events) {
374 if (read_file_number(fd, &size, 8))
375 die("cannot read the format size of the %dth event from system %s",
376 events, buf);
377 read_dump_string(fd, size, EVENT_FORMAT);
378 events--;
379 }
380 systems--;
381 }
382 }
383
dump_kallsyms(int fd)384 static void dump_kallsyms(int fd)
385 {
386 unsigned int size;
387
388 do_print((SUMMARY | KALLSYMS), "\t[Kallsyms, ");
389
390 if (read_file_number(fd, &size, 4))
391 die("cannot read the size of the kallsyms");
392
393 do_print((SUMMARY | KALLSYMS), "%d bytes]\n", size);
394
395 read_dump_string(fd, size, KALLSYMS);
396 }
397
dump_printk(int fd)398 static void dump_printk(int fd)
399 {
400 unsigned int size;
401
402 do_print((SUMMARY | TRACE_PRINTK), "\t[Trace printk, ");
403
404 if (read_file_number(fd, &size, 4))
405 die("cannot read the size of the trace printk");
406
407 do_print((SUMMARY | TRACE_PRINTK), "%d bytes]\n", size);
408
409 read_dump_string(fd, size, TRACE_PRINTK);
410 }
411
dump_cmdlines(int fd)412 static void dump_cmdlines(int fd)
413 {
414 unsigned long long size;
415
416 do_print((SUMMARY | CMDLINES), "\t[Saved command lines, ");
417
418 if (read_file_number(fd, &size, 8))
419 die("cannot read the size of the saved command lines");
420
421 do_print((SUMMARY | CMDLINES), "%d bytes]\n", size);
422
423 read_dump_string(fd, size, CMDLINES);
424 }
425
dump_cpus_count(int fd)426 static void dump_cpus_count(int fd)
427 {
428 if (read_file_number(fd, &trace_cpus, 4))
429 die("cannot read the cpu count");
430
431 do_print(SUMMARY, "\t%d [CPUs with tracing data]\n", trace_cpus);
432 }
433
dump_option_string(int fd,int size,char * desc)434 static void dump_option_string(int fd, int size, char *desc)
435 {
436 do_print(OPTIONS, "\t\t[Option %s, %d bytes]\n", desc, size);
437 if (size)
438 read_dump_string(fd, size, OPTIONS);
439 }
440
dump_section_header(int fd,enum dump_items v,unsigned short * flags)441 static void dump_section_header(int fd, enum dump_items v, unsigned short *flags)
442 {
443 unsigned long long offset, size;
444 unsigned short fl;
445 unsigned short id;
446 const char *desc;
447 int desc_id;
448
449 offset = lseek64(fd, 0, SEEK_CUR);
450 if (read_file_number(fd, &id, 2))
451 die("cannot read the section id");
452
453 if (read_file_number(fd, &fl, 2))
454 die("cannot read the section flags");
455
456 if (read_file_number(fd, &desc_id, 4))
457 die("no section description");
458
459 desc = get_metadata_string(desc_id);
460 if (!desc)
461 desc = "Unknown";
462
463 if (read_file_number(fd, &size, 8))
464 die("cannot read section size");
465
466 do_print(v, "\t[Section %d @ %lld: \"%s\", flags 0x%X, %lld bytes]\n",
467 id, offset, desc, fl, size);
468
469 if (flags)
470 *flags = fl;
471 }
472
dump_option_buffer(int fd,unsigned short option,int size)473 static void dump_option_buffer(int fd, unsigned short option, int size)
474 {
475 unsigned long long total_size = 0;
476 unsigned long long data_size;
477 unsigned long long current;
478 unsigned long long offset;
479 unsigned short flags;
480 char clock[DUMP_SIZE];
481 char name[DUMP_SIZE];
482 int page_size;
483 int cpus = 0;
484 int id;
485 int i;
486
487 if (size < 8)
488 die("broken buffer option with size %d", size);
489
490 if (read_file_number(fd, &offset, 8))
491 die("cannot read the offset of the buffer option");
492
493 if (read_file_string(fd, name, DUMP_SIZE))
494 die("cannot read the name of the buffer option");
495
496 if (file_version < FILE_VERSION_SECTIONS) {
497 do_print(OPTIONS|FLYRECORD, "\t\t[Option BUFFER, %d bytes]\n", size);
498 do_print(OPTIONS|FLYRECORD, "%lld [offset]\n", offset);
499 do_print(OPTIONS|FLYRECORD, "\"%s\" [name]\n", name);
500 return;
501 }
502
503 current = lseek64(fd, 0, SEEK_CUR);
504 if (lseek64(fd, offset, SEEK_SET) == (off_t)-1)
505 die("cannot goto buffer offset %lld", offset);
506
507 dump_section_header(fd, FLYRECORD, &flags);
508
509 if (lseek64(fd, current, SEEK_SET) == (off_t)-1)
510 die("cannot go back to buffer option");
511
512 do_print(OPTIONS|FLYRECORD, "\t\t[Option BUFFER, %d bytes]\n", size);
513 do_print(OPTIONS|FLYRECORD, "%lld [offset]\n", offset);
514 do_print(OPTIONS|FLYRECORD, "\"%s\" [name]\n", name);
515
516 if (read_file_string(fd, clock, DUMP_SIZE))
517 die("cannot read clock of the buffer option");
518
519 do_print(OPTIONS|FLYRECORD, "\"%s\" [clock]\n", clock);
520 if (option == TRACECMD_OPTION_BUFFER) {
521 if (read_file_number(fd, &page_size, 4))
522 die("cannot read the page size of the buffer option");
523 do_print(OPTIONS|FLYRECORD, "%d [Page size, bytes]\n", page_size);
524
525 if (read_file_number(fd, &cpus, 4))
526 die("cannot read the cpu count of the buffer option");
527
528 do_print(OPTIONS|FLYRECORD, "%d [CPUs]:\n", cpus);
529 for (i = 0; i < cpus; i++) {
530 if (read_file_number(fd, &id, 4))
531 die("cannot read the id of cpu %d from the buffer option", i);
532
533 if (read_file_number(fd, &offset, 8))
534 die("cannot read the offset of cpu %d from the buffer option", i);
535
536 if (read_file_number(fd, &data_size, 8))
537 die("cannot read the data size of cpu %d from the buffer option", i);
538
539 total_size += data_size;
540 do_print(OPTIONS|FLYRECORD, " %d %lld\t%lld\t[id, data offset and size]\n",
541 id, offset, data_size);
542 }
543 do_print(SUMMARY, "\t\[buffer \"%s\", \"%s\" clock, %d page size, "
544 "%d cpus, %lld bytes flyrecord data]\n",
545 name, clock, page_size, cpus, total_size);
546 } else {
547 do_print(SUMMARY, "\t\[buffer \"%s\", \"%s\" clock, latency data]\n", name, clock);
548 }
549
550 }
551
dump_option_int(int fd,int size,char * desc)552 static void dump_option_int(int fd, int size, char *desc)
553 {
554 int val;
555
556 do_print(OPTIONS, "\t\t[Option %s, %d bytes]\n", desc, size);
557 read_file_number(fd, &val, size);
558 do_print(OPTIONS, "%d\n", val);
559 }
560
dump_option_xlong(int fd,int size,char * desc)561 static void dump_option_xlong(int fd, int size, char *desc)
562 {
563 long long val;
564
565 do_print(OPTIONS, "\t\t[Option %s, %d bytes]\n", desc, size);
566 read_file_number(fd, &val, size);
567 do_print(OPTIONS, "0x%llX\n", val);
568 }
569
570 struct time_shift_cpu {
571 unsigned int count;
572 long long *scalings;
573 long long *frac;
574 long long *offsets;
575 unsigned long long *times;
576 };
577
dump_option_timeshift(int fd,int size)578 static void dump_option_timeshift(int fd, int size)
579 {
580 struct time_shift_cpu *cpus_data;
581 long long trace_id;
582 unsigned int flags;
583 unsigned int cpus;
584 int i, j;
585
586 /*
587 * long long int (8 bytes) trace session ID
588 * int (4 bytes) count of timestamp offsets.
589 * long long array of size [count] of times,
590 * when the offsets were calculated.
591 * long long array of size [count] of timestamp offsets.
592 */
593 if (size < 12) {
594 do_print(OPTIONS, "Broken time shift option, size %s", size);
595 return;
596 }
597 do_print(OPTIONS, "\t\t[Option TimeShift, %d bytes]\n", size);
598 read_file_number(fd, &trace_id, 8);
599 size -= 8;
600 do_print(OPTIONS, "0x%llX [peer's trace id]\n", trace_id);
601 read_file_number(fd, &flags, 4);
602 size -= 4;
603 do_print(OPTIONS, "0x%llX [peer's protocol flags]\n", flags);
604 read_file_number(fd, &cpus, 4);
605 size -= 4;
606 do_print(OPTIONS, "0x%llX [peer's CPU count]\n", cpus);
607 cpus_data = calloc(cpus, sizeof(struct time_shift_cpu));
608 if (!cpus_data)
609 return;
610 for (j = 0; j < cpus; j++) {
611 if (size < 4)
612 goto out;
613 read_file_number(fd, &cpus_data[j].count, 4);
614 size -= 4;
615 do_print(OPTIONS, "%lld [samples count for CPU %d]\n", cpus_data[j].count, j);
616 cpus_data[j].times = calloc(cpus_data[j].count, sizeof(long long));
617 cpus_data[j].offsets = calloc(cpus_data[j].count, sizeof(long long));
618 cpus_data[j].scalings = calloc(cpus_data[j].count, sizeof(long long));
619 cpus_data[j].frac = calloc(cpus_data[j].count, sizeof(long long));
620 if (!cpus_data[j].times || !cpus_data[j].offsets ||
621 !cpus_data[j].scalings || !cpus_data[j].frac)
622 goto out;
623 for (i = 0; i < cpus_data[j].count; i++) {
624 if (size < 8)
625 goto out;
626 read_file_number(fd, cpus_data[j].times + i, 8);
627 size -= 8;
628 }
629 for (i = 0; i < cpus_data[j].count; i++) {
630 if (size < 8)
631 goto out;
632 read_file_number(fd, cpus_data[j].offsets + i, 8);
633 size -= 8;
634 }
635 for (i = 0; i < cpus_data[j].count; i++) {
636 if (size < 8)
637 goto out;
638 read_file_number(fd, cpus_data[j].scalings + i, 8);
639 size -= 8;
640 }
641 }
642
643 if (size > 0) {
644 for (j = 0; j < cpus; j++) {
645 if (!cpus_data[j].frac)
646 goto out;
647 for (i = 0; i < cpus_data[j].count; i++) {
648 if (size < 8)
649 goto out;
650 read_file_number(fd, cpus_data[j].frac + i, 8);
651 size -= 8;
652 }
653 }
654 }
655
656 for (j = 0; j < cpus; j++) {
657 for (i = 0; i < cpus_data[j].count; i++)
658 do_print(OPTIONS, "\t%lld %lld %llu %llu[offset * scaling >> fraction @ time]\n",
659 cpus_data[j].offsets[i], cpus_data[j].scalings[i],
660 cpus_data[j].frac[i], cpus_data[j].times[i]);
661
662 }
663
664 out:
665 if (j < cpus)
666 do_print(OPTIONS, "Broken time shift option\n");
667 for (j = 0; j < cpus; j++) {
668 free(cpus_data[j].times);
669 free(cpus_data[j].offsets);
670 free(cpus_data[j].scalings);
671 free(cpus_data[j].frac);
672 }
673 free(cpus_data);
674 }
675
dump_option_guest(int fd,int size)676 void dump_option_guest(int fd, int size)
677 {
678 unsigned long long trace_id;
679 char *buf, *p;
680 int cpu, pid;
681 int cpus;
682 int i;
683
684 do_print(OPTIONS, "\t\t[Option GUEST, %d bytes]\n", size);
685
686 /*
687 * Guest name, null terminated string
688 * long long (8 bytes) trace-id
689 * int (4 bytes) number of guest CPUs
690 * array of size number of guest CPUs:
691 * int (4 bytes) Guest CPU id
692 * int (4 bytes) Host PID, running the guest CPU
693 */
694 buf = calloc(1, size);
695 if (!buf)
696 return;
697 if (read_file_bytes(fd, buf, size))
698 goto out;
699
700 p = buf;
701 do_print(OPTIONS, "%s [Guest name]\n", p);
702 size -= strlen(buf) + 1;
703 p += strlen(buf) + 1;
704
705 if (size < sizeof(long long))
706 goto out;
707 trace_id = tep_read_number(tep, p, sizeof(long long));
708 size -= sizeof(long long);
709 p += sizeof(long long);
710 do_print(OPTIONS, "0x%llX [trace id]\n", trace_id);
711
712 if (size < sizeof(int))
713 goto out;
714 cpus = tep_read_number(tep, p, sizeof(int));
715 size -= sizeof(int);
716 p += sizeof(int);
717 do_print(OPTIONS, "%d [Guest CPUs]\n", cpus);
718
719 for (i = 0; i < cpus; i++) {
720 if (size < 2 * sizeof(int))
721 goto out;
722 cpu = tep_read_number(tep, p, sizeof(int));
723 size -= sizeof(int);
724 p += sizeof(int);
725 pid = tep_read_number(tep, p, sizeof(int));
726 size -= sizeof(int);
727 p += sizeof(int);
728 do_print(OPTIONS, " %d %d [guest cpu, host pid]\n", cpu, pid);
729 }
730
731 out:
732 free(buf);
733 }
734
dump_option_tsc2nsec(int fd,int size)735 void dump_option_tsc2nsec(int fd, int size)
736 {
737 int mult, shift;
738 unsigned long long offset;
739
740 do_print(OPTIONS, "\n\t\t[Option TSC2NSEC, %d bytes]\n", size);
741
742 if (read_file_number(fd, &mult, 4))
743 die("cannot read tsc2nsec multiplier");
744 if (read_file_number(fd, &shift, 4))
745 die("cannot read tsc2nsec shift");
746 if (read_file_number(fd, &offset, 8))
747 die("cannot read tsc2nsec offset");
748 do_print(OPTIONS, "%d %d %llu [multiplier, shift, offset]\n", mult, shift, offset);
749 }
750
dump_option_section(int fd,unsigned int size,unsigned short id,char * desc,enum dump_items v)751 static void dump_option_section(int fd, unsigned int size,
752 unsigned short id, char *desc, enum dump_items v)
753 {
754 struct file_section *sec;
755
756 sec = calloc(1, sizeof(struct file_section));
757 if (!sec)
758 die("cannot allocate new section");
759
760 sec->next = sections;
761 sections = sec;
762 sec->id = id;
763 sec->verbosity = v;
764 if (read_file_number(fd, &sec->offset, 8))
765 die("cannot read the option %d offset", id);
766
767 do_print(OPTIONS, "\t\t[Option %s, %d bytes] @ %lld\n", desc, size, sec->offset);
768 }
769
dump_sections(int fd,int count)770 static void dump_sections(int fd, int count)
771 {
772 struct file_section *sec = sections;
773 unsigned short flags;
774
775 while (sec) {
776 if (lseek64(fd, sec->offset, SEEK_SET) == (off_t)-1)
777 die("cannot goto option offset %lld", sec->offset);
778
779 dump_section_header(fd, sec->verbosity, &flags);
780
781 if ((flags & TRACECMD_SEC_FL_COMPRESS) && uncompress_block())
782 die("cannot uncompress section block");
783
784 switch (sec->id) {
785 case TRACECMD_OPTION_HEADER_INFO:
786 dump_header_page(fd);
787 dump_header_event(fd);
788 break;
789 case TRACECMD_OPTION_FTRACE_EVENTS:
790 dump_ftrace_events_format(fd);
791 break;
792 case TRACECMD_OPTION_EVENT_FORMATS:
793 dump_events_format(fd);
794 break;
795 case TRACECMD_OPTION_KALLSYMS:
796 dump_kallsyms(fd);
797 break;
798 case TRACECMD_OPTION_PRINTK:
799 dump_printk(fd);
800 break;
801 case TRACECMD_OPTION_CMDLINES:
802 dump_cmdlines(fd);
803 break;
804 }
805 uncompress_reset();
806 sec = sec->next;
807 }
808 do_print(SUMMARY|SECTIONS, "\t[%d sections]\n", count);
809 }
810
811 static int dump_options_read(int fd);
812
dump_option_done(int fd,int size)813 static int dump_option_done(int fd, int size)
814 {
815 unsigned long long offset;
816
817 do_print(OPTIONS, "\t\t[Option DONE, %d bytes]\n", size);
818
819 if (file_version < FILE_VERSION_SECTIONS || size < 8)
820 return 0;
821
822 if (read_file_number(fd, &offset, 8))
823 die("cannot read the next options offset");
824
825 do_print(OPTIONS, "%lld\n", offset);
826 if (!offset)
827 return 0;
828
829 if (lseek64(fd, offset, SEEK_SET) == (off_t)-1)
830 die("cannot goto next options offset %lld", offset);
831
832 do_print(OPTIONS, "\n\n");
833
834 return dump_options_read(fd);
835 }
836
dump_options_read(int fd)837 static int dump_options_read(int fd)
838 {
839 unsigned short flags = 0;
840 unsigned short option;
841 unsigned int size;
842 int count = 0;
843
844 if (file_version >= FILE_VERSION_SECTIONS)
845 dump_section_header(fd, OPTIONS, &flags);
846
847 if ((flags & TRACECMD_SEC_FL_COMPRESS) && uncompress_block())
848 die("cannot uncompress file block");
849
850 for (;;) {
851 if (read_file_number(fd, &option, 2))
852 die("cannot read the option id");
853 if (option == TRACECMD_OPTION_DONE && file_version < FILE_VERSION_SECTIONS)
854 break;
855 if (read_file_number(fd, &size, 4))
856 die("cannot read the option size");
857
858 count++;
859 switch (option) {
860 case TRACECMD_OPTION_DATE:
861 dump_option_string(fd, size, "DATE");
862 break;
863 case TRACECMD_OPTION_CPUSTAT:
864 dump_option_string(fd, size, "CPUSTAT");
865 break;
866 case TRACECMD_OPTION_BUFFER:
867 case TRACECMD_OPTION_BUFFER_TEXT:
868 dump_option_buffer(fd, option, size);
869 break;
870 case TRACECMD_OPTION_TRACECLOCK:
871 do_print(OPTIONS, "\t\t[Option TRACECLOCK, %d bytes]\n", size);
872 read_dump_string(fd, size, OPTIONS | CLOCK);
873 has_clock = 1;
874 break;
875 case TRACECMD_OPTION_UNAME:
876 dump_option_string(fd, size, "UNAME");
877 break;
878 case TRACECMD_OPTION_HOOK:
879 dump_option_string(fd, size, "HOOK");
880 break;
881 case TRACECMD_OPTION_OFFSET:
882 dump_option_string(fd, size, "OFFSET");
883 break;
884 case TRACECMD_OPTION_CPUCOUNT:
885 dump_option_int(fd, size, "CPUCOUNT");
886 break;
887 case TRACECMD_OPTION_VERSION:
888 dump_option_string(fd, size, "VERSION");
889 break;
890 case TRACECMD_OPTION_PROCMAPS:
891 dump_option_string(fd, size, "PROCMAPS");
892 break;
893 case TRACECMD_OPTION_TRACEID:
894 dump_option_xlong(fd, size, "TRACEID");
895 break;
896 case TRACECMD_OPTION_TIME_SHIFT:
897 dump_option_timeshift(fd, size);
898 break;
899 case TRACECMD_OPTION_GUEST:
900 dump_option_guest(fd, size);
901 break;
902 case TRACECMD_OPTION_TSC2NSEC:
903 dump_option_tsc2nsec(fd, size);
904 break;
905 case TRACECMD_OPTION_HEADER_INFO:
906 dump_option_section(fd, size, option, "HEADERS", HEAD_PAGE | HEAD_EVENT);
907 break;
908 case TRACECMD_OPTION_FTRACE_EVENTS:
909 dump_option_section(fd, size, option, "FTRACE EVENTS", FTRACE_FORMAT);
910 break;
911 case TRACECMD_OPTION_EVENT_FORMATS:
912 dump_option_section(fd, size, option,
913 "EVENT FORMATS", EVENT_SYSTEMS | EVENT_FORMAT);
914 break;
915 case TRACECMD_OPTION_KALLSYMS:
916 dump_option_section(fd, size, option, "KALLSYMS", KALLSYMS);
917 break;
918 case TRACECMD_OPTION_PRINTK:
919 dump_option_section(fd, size, option, "PRINTK", TRACE_PRINTK);
920 break;
921 case TRACECMD_OPTION_CMDLINES:
922 dump_option_section(fd, size, option, "CMDLINES", CMDLINES);
923 break;
924 case TRACECMD_OPTION_DONE:
925 uncompress_reset();
926 count += dump_option_done(fd, size);
927 return count;
928 default:
929 do_print(OPTIONS, " %d %d\t[Unknown option, size - skipping]\n",
930 option, size);
931 do_lseek(fd, size, SEEK_CUR);
932 break;
933 }
934 }
935 uncompress_reset();
936 return count;
937 }
938
dump_options(int fd)939 static void dump_options(int fd)
940 {
941 int count;
942
943 count = dump_options_read(fd);
944 do_print(SUMMARY|OPTIONS, "\t[%d options]\n", count);
945 }
946
dump_latency(int fd)947 static void dump_latency(int fd)
948 {
949 do_print(SUMMARY, "\t[Latency tracing data]\n");
950 }
951
dump_clock(int fd)952 static void dump_clock(int fd)
953 {
954 long long size;
955 char *clock;
956
957 do_print((SUMMARY | CLOCK), "\t[Tracing clock]\n");
958 if (!has_clock) {
959 do_print((SUMMARY | CLOCK), "\t\t No tracing clock saved in the file\n");
960 return;
961 }
962 if (read_file_number(fd, &size, 8))
963 die("cannot read clock size");
964 clock = calloc(1, size);
965 if (!clock)
966 die("cannot allocate clock %lld bytes", size);
967
968 if (read_file_bytes(fd, clock, size))
969 die("cannot read clock %lld bytes", size);
970 clock[size] = 0;
971 do_print((SUMMARY | CLOCK), "\t\t%s\n", clock);
972 free(clock);
973 }
974
dump_flyrecord(int fd)975 static void dump_flyrecord(int fd)
976 {
977 long long cpu_offset;
978 long long cpu_size;
979 int i;
980
981 do_print((SUMMARY | FLYRECORD), "\t[Flyrecord tracing data]\n");
982
983 for (i = 0; i < trace_cpus; i++) {
984 if (read_file_number(fd, &cpu_offset, 8))
985 die("cannot read the cpu %d offset", i);
986 if (read_file_number(fd, &cpu_size, 8))
987 die("cannot read the cpu %d size", i);
988 do_print(FLYRECORD, "\t %10.lld %10.lld\t[offset, size of cpu %d]\n",
989 cpu_offset, cpu_size, i);
990 }
991 dump_clock(fd);
992 }
993
dump_therest(int fd)994 static void dump_therest(int fd)
995 {
996 char str[10];
997
998 for (;;) {
999 if (read_file_bytes(fd, str, 10))
1000 die("cannot read the rest of the header");
1001
1002 if (strncmp(str, HEAD_OPTIONS, 10) == 0)
1003 dump_options(fd);
1004 else if (strncmp(str, HEAD_LATENCY, 10) == 0)
1005 dump_latency(fd);
1006 else if (strncmp(str, HEAD_FLYRECORD, 10) == 0)
1007 dump_flyrecord(fd);
1008 else {
1009 lseek64(fd, -10, SEEK_CUR);
1010 break;
1011 }
1012 }
1013 }
1014
dump_v6_file(int fd)1015 static void dump_v6_file(int fd)
1016 {
1017 dump_header_page(fd);
1018 dump_header_event(fd);
1019 dump_ftrace_events_format(fd);
1020 dump_events_format(fd);
1021 dump_kallsyms(fd);
1022 dump_printk(fd);
1023 dump_cmdlines(fd);
1024 dump_cpus_count(fd);
1025 dump_therest(fd);
1026 }
1027
read_metadata_strings(int fd,unsigned long long size)1028 static int read_metadata_strings(int fd, unsigned long long size)
1029 {
1030 char *str, *strings;
1031 int psize;
1032 int ret;
1033
1034 strings = realloc(meta_strings, meta_strings_size + size);
1035 if (!strings)
1036 return -1;
1037 meta_strings = strings;
1038
1039 ret = read_file_bytes(fd, meta_strings + meta_strings_size, size);
1040 if (ret < 0)
1041 return -1;
1042
1043 do_print(STRINGS, "\t[String @ offset]\n");
1044 psize = 0;
1045 while (psize < size) {
1046 str = meta_strings + meta_strings_size + psize;
1047 do_print(STRINGS, "\t\t\"%s\" @ %d\n", str, meta_strings_size + psize);
1048 psize += strlen(str) + 1;
1049 }
1050
1051 meta_strings_size += size;
1052
1053 return 0;
1054 }
1055
get_meta_strings(int fd)1056 static void get_meta_strings(int fd)
1057 {
1058 unsigned long long offset, size;
1059 unsigned int csize, rsize;
1060 unsigned short fl, id;
1061 int desc_id;
1062
1063 offset = lseek64(fd, 0, SEEK_CUR);
1064 do {
1065 if (read_file_number(fd, &id, 2))
1066 break;
1067 if (read_file_number(fd, &fl, 2))
1068 die("cannot read section flags");
1069 if (read_file_number(fd, &desc_id, 4))
1070 die("cannot read section description");
1071 if (read_file_number(fd, &size, 8))
1072 die("cannot read section size");
1073 if (id == TRACECMD_OPTION_STRINGS) {
1074 if ((fl & TRACECMD_SEC_FL_COMPRESS)) {
1075 read_file_number(fd, &csize, 4);
1076 read_file_number(fd, &rsize, 4);
1077 lseek64(fd, -8, SEEK_CUR);
1078 if (uncompress_block())
1079 break;
1080 } else {
1081 rsize = size;
1082 }
1083 read_metadata_strings(fd, rsize);
1084 uncompress_reset();
1085 } else {
1086 if (lseek64(fd, size, SEEK_CUR) == (off_t)-1)
1087 break;
1088 }
1089 } while (1);
1090
1091 if (lseek64(fd, offset, SEEK_SET) == (off_t)-1)
1092 die("cannot restore the original file location");
1093 }
1094
walk_v7_sections(int fd)1095 static int walk_v7_sections(int fd)
1096 {
1097 unsigned long long offset, soffset, size;
1098 unsigned short fl;
1099 unsigned short id;
1100 int csize, rsize;
1101 int count = 0;
1102 int desc_id;
1103 const char *desc;
1104
1105 offset = lseek64(fd, 0, SEEK_CUR);
1106 do {
1107 soffset = lseek64(fd, 0, SEEK_CUR);
1108 if (read_file_number(fd, &id, 2))
1109 break;
1110
1111 if (read_file_number(fd, &fl, 2))
1112 die("cannot read section flags");
1113
1114 if (read_file_number(fd, &desc_id, 4))
1115 die("cannot read section description");
1116
1117 desc = get_metadata_string(desc_id);
1118 if (!desc)
1119 desc = "Unknown";
1120
1121 if (read_file_number(fd, &size, 8))
1122 die("cannot read section size");
1123
1124 if (id >= TRACECMD_OPTION_MAX)
1125 do_print(SECTIONS, "Unknown section id %d: %s", id, desc);
1126
1127 count++;
1128 if (fl & TRACECMD_SEC_FL_COMPRESS) {
1129 if (id == TRACECMD_OPTION_BUFFER ||
1130 id == TRACECMD_OPTION_BUFFER_TEXT) {
1131 do_print(SECTIONS,
1132 "\t[Section %2d @ %-16lld\t\"%s\", flags 0x%X, "
1133 "%lld compressed bytes]\n",
1134 id, soffset, desc, fl, size);
1135 } else {
1136 if (read_file_number(fd, &csize, 4))
1137 die("cannot read section size");
1138
1139 if (read_file_number(fd, &rsize, 4))
1140 die("cannot read section size");
1141
1142 do_print(SECTIONS, "\t[Section %2d @ %-16lld\t\"%s\", flags 0x%X, "
1143 "%d compressed, %d uncompressed]\n",
1144 id, soffset, desc, fl, csize, rsize);
1145 size -= 8;
1146 }
1147 } else {
1148 do_print(SECTIONS, "\t[Section %2d @ %-16lld\t\"%s\", flags 0x%X, %lld bytes]\n",
1149 id, soffset, desc, fl, size);
1150 }
1151
1152 if (lseek64(fd, size, SEEK_CUR) == (off_t)-1)
1153 break;
1154 } while (1);
1155
1156 if (lseek64(fd, offset, SEEK_SET) == (off_t)-1)
1157 die("cannot restore the original file location");
1158
1159 return count;
1160 }
1161
dump_v7_file(int fd)1162 static void dump_v7_file(int fd)
1163 {
1164 long long offset;
1165 int sections;
1166
1167 if (read_file_number(fd, &offset, 8))
1168 die("cannot read offset of the first option section");
1169
1170 get_meta_strings(fd);
1171 sections = walk_v7_sections(fd);
1172
1173 if (lseek64(fd, offset, SEEK_SET) == (off_t)-1)
1174 die("cannot goto options offset %lld", offset);
1175
1176 dump_options(fd);
1177 dump_sections(fd, sections);
1178 }
1179
free_sections(void)1180 static void free_sections(void)
1181 {
1182 struct file_section *del;
1183
1184 while (sections) {
1185 del = sections;
1186 sections = sections->next;
1187 free(del);
1188 }
1189 }
1190
dump_file(const char * file)1191 static void dump_file(const char *file)
1192 {
1193 int fd;
1194
1195 tep = tep_alloc();
1196 if (!tep)
1197 return;
1198
1199 fd = open(file, O_RDONLY);
1200 if (fd < 0)
1201 die("cannot open '%s'\n", file);
1202
1203 do_print(SUMMARY, "\n Tracing meta data in file %s:\n", file);
1204
1205 dump_initial_format(fd);
1206 dump_compress(fd);
1207 if (file_version < FILE_VERSION_SECTIONS)
1208 dump_v6_file(fd);
1209 else
1210 dump_v7_file(fd);
1211 free_sections();
1212 tep_free(tep);
1213 tep = NULL;
1214 close(fd);
1215 }
1216
1217 enum {
1218 OPT_sections = 240,
1219 OPT_strings = 241,
1220 OPT_verbose = 242,
1221 OPT_clock = 243,
1222 OPT_all = 244,
1223 OPT_summary = 245,
1224 OPT_flyrecord = 246,
1225 OPT_options = 247,
1226 OPT_cmd_lines = 248,
1227 OPT_printk = 249,
1228 OPT_kallsyms = 250,
1229 OPT_events = 251,
1230 OPT_systems = 252,
1231 OPT_ftrace = 253,
1232 OPT_head_event = 254,
1233 OPT_head_page = 255,
1234 };
1235
trace_dump(int argc,char ** argv)1236 void trace_dump(int argc, char **argv)
1237 {
1238 char *input_file = NULL;
1239 bool validate = false;
1240 int c;
1241
1242 if (argc < 2)
1243 usage(argv);
1244
1245 if (strcmp(argv[1], "dump") != 0)
1246 usage(argv);
1247 for (;;) {
1248 int option_index = 0;
1249 static struct option long_options[] = {
1250 {"all", no_argument, NULL, OPT_all},
1251 {"summary", no_argument, NULL, OPT_summary},
1252 {"head-page", no_argument, NULL, OPT_head_page},
1253 {"head-event", no_argument, NULL, OPT_head_event},
1254 {"ftrace-events", no_argument, NULL, OPT_ftrace},
1255 {"systems", no_argument, NULL, OPT_systems},
1256 {"events", no_argument, NULL, OPT_events},
1257 {"kallsyms", no_argument, NULL, OPT_kallsyms},
1258 {"printk", no_argument, NULL, OPT_printk},
1259 {"cmd-lines", no_argument, NULL, OPT_cmd_lines},
1260 {"options", no_argument, NULL, OPT_options},
1261 {"flyrecord", no_argument, NULL, OPT_flyrecord},
1262 {"clock", no_argument, NULL, OPT_clock},
1263 {"strings", no_argument, NULL, OPT_strings},
1264 {"sections", no_argument, NULL, OPT_sections},
1265 {"validate", no_argument, NULL, 'v'},
1266 {"help", no_argument, NULL, '?'},
1267 {"verbose", optional_argument, NULL, OPT_verbose},
1268 {NULL, 0, NULL, 0}
1269 };
1270
1271 c = getopt_long (argc-1, argv+1, "+hvai:",
1272 long_options, &option_index);
1273 if (c == -1)
1274 break;
1275 switch (c) {
1276 case 'h':
1277 usage(argv);
1278 break;
1279 case 'i':
1280 input_file = optarg;
1281 break;
1282 case 'v':
1283 validate = true;
1284 break;
1285 case OPT_all:
1286 verbosity = 0xFFFFFFFF;
1287 break;
1288 case OPT_summary:
1289 verbosity |= SUMMARY;
1290 break;
1291 case OPT_flyrecord:
1292 verbosity |= FLYRECORD;
1293 break;
1294 case OPT_options:
1295 verbosity |= OPTIONS;
1296 break;
1297 case OPT_cmd_lines:
1298 verbosity |= CMDLINES;
1299 break;
1300 case OPT_printk:
1301 verbosity |= TRACE_PRINTK;
1302 break;
1303 case OPT_kallsyms:
1304 verbosity |= KALLSYMS;
1305 break;
1306 case OPT_events:
1307 verbosity |= EVENT_FORMAT;
1308 break;
1309 case OPT_systems:
1310 verbosity |= EVENT_SYSTEMS;
1311 break;
1312 case OPT_ftrace:
1313 verbosity |= FTRACE_FORMAT;
1314 break;
1315 case OPT_head_event:
1316 verbosity |= HEAD_EVENT;
1317 break;
1318 case OPT_head_page:
1319 verbosity |= HEAD_PAGE;
1320 break;
1321 case OPT_clock:
1322 verbosity |= CLOCK;
1323 break;
1324 case OPT_verbose:
1325 if (trace_set_verbose(optarg) < 0)
1326 die("invalid verbose level %s", optarg);
1327 break;
1328 case OPT_strings:
1329 verbosity |= STRINGS;
1330 break;
1331 case OPT_sections:
1332 verbosity |= SECTIONS;
1333 break;
1334 default:
1335 usage(argv);
1336 }
1337 }
1338
1339 if ((argc - optind) >= 2) {
1340 if (input_file)
1341 usage(argv);
1342 input_file = argv[optind + 1];
1343 }
1344
1345 if (!input_file)
1346 input_file = DEFAULT_INPUT_FILE;
1347
1348 if (!verbosity && !validate)
1349 verbosity = SUMMARY;
1350
1351 dump_file(input_file);
1352
1353 if (validate)
1354 tracecmd_plog("File %s is a valid trace-cmd file\n", input_file);
1355 }
1356