perf_counter: Ammend cleanup in fork() fail
[deliverable/linux.git] / Documentation / perf_counter / builtin-report.c
CommitLineData
53cb8bc2 1#include "util/util.h"
16f762a2 2#include "builtin.h"
53cb8bc2 3
35a50c8a 4#include "util/list.h"
a930d2c0 5#include "util/cache.h"
35a50c8a 6#include "util/rbtree.h"
a2928c42 7#include "util/symbol.h"
8fa66bdc 8
53cb8bc2
IM
9#include "perf.h"
10
11#include "util/parse-options.h"
12#include "util/parse-events.h"
13
8fa66bdc
ACM
14#define SHOW_KERNEL 1
15#define SHOW_USER 2
16#define SHOW_HV 4
17
23ac9cbe 18static char const *input_name = "perf.data";
450aaa2b 19static char *vmlinux = NULL;
37f440cb 20static char *sort_order = "pid,symbol";
8fa66bdc
ACM
21static int input;
22static int show_mask = SHOW_KERNEL | SHOW_USER | SHOW_HV;
23
97b07b69 24static int dump_trace = 0;
16f762a2 25static int verbose;
97b07b69 26
8fa66bdc
ACM
27static unsigned long page_size;
28static unsigned long mmap_window = 32;
29
53cb8bc2 30const char *perf_event_names[] = {
8fa66bdc
ACM
31 [PERF_EVENT_MMAP] = " PERF_EVENT_MMAP",
32 [PERF_EVENT_MUNMAP] = " PERF_EVENT_MUNMAP",
33 [PERF_EVENT_COMM] = " PERF_EVENT_COMM",
34};
35
36struct ip_event {
37 struct perf_event_header header;
38 __u64 ip;
39 __u32 pid, tid;
40};
41struct mmap_event {
42 struct perf_event_header header;
43 __u32 pid, tid;
44 __u64 start;
45 __u64 len;
46 __u64 pgoff;
47 char filename[PATH_MAX];
48};
49struct comm_event {
50 struct perf_event_header header;
51 __u32 pid,tid;
52 char comm[16];
53};
54
55typedef union event_union {
56 struct perf_event_header header;
57 struct ip_event ip;
58 struct mmap_event mmap;
59 struct comm_event comm;
60} event_t;
61
8fa66bdc
ACM
62static LIST_HEAD(dsos);
63static struct dso *kernel_dso;
64
65static void dsos__add(struct dso *dso)
66{
67 list_add_tail(&dso->node, &dsos);
68}
69
70static struct dso *dsos__find(const char *name)
71{
72 struct dso *pos;
73
74 list_for_each_entry(pos, &dsos, node)
75 if (strcmp(pos->name, name) == 0)
76 return pos;
77 return NULL;
78}
79
80static struct dso *dsos__findnew(const char *name)
81{
82 struct dso *dso = dsos__find(name);
b7a16eac 83 int nr;
8fa66bdc
ACM
84
85 if (dso == NULL) {
0085c954 86 dso = dso__new(name, 0);
b7a16eac
PZ
87 if (!dso)
88 goto out_delete_dso;
89
69ee69f6 90 nr = dso__load(dso, NULL);
b7a16eac
PZ
91 if (nr < 0) {
92 fprintf(stderr, "Failed to open: %s\n", name);
8fa66bdc 93 goto out_delete_dso;
b7a16eac
PZ
94 }
95 if (!nr) {
96 fprintf(stderr,
97 "Failed to find debug symbols for: %s, maybe install a debug package?\n",
98 name);
99 }
8fa66bdc
ACM
100
101 dsos__add(dso);
102 }
103
104 return dso;
105
106out_delete_dso:
107 dso__delete(dso);
108 return NULL;
109}
110
16f762a2 111static void dsos__fprintf(FILE *fp)
8fa66bdc
ACM
112{
113 struct dso *pos;
114
115 list_for_each_entry(pos, &dsos, node)
116 dso__fprintf(pos, fp);
117}
118
450aaa2b
PZ
119static int load_kernel(void)
120{
a827c875 121 int err;
450aaa2b 122
0085c954 123 kernel_dso = dso__new("[kernel]", 0);
450aaa2b 124 if (!kernel_dso)
a2928c42 125 return -1;
450aaa2b 126
69ee69f6 127 err = dso__load_kernel(kernel_dso, vmlinux, NULL);
a2928c42
ACM
128 if (err) {
129 dso__delete(kernel_dso);
130 kernel_dso = NULL;
131 } else
132 dsos__add(kernel_dso);
450aaa2b 133
a2928c42 134 return err;
450aaa2b
PZ
135}
136
8fa66bdc
ACM
137struct map {
138 struct list_head node;
139 uint64_t start;
140 uint64_t end;
141 uint64_t pgoff;
142 struct dso *dso;
143};
144
145static struct map *map__new(struct mmap_event *event)
146{
147 struct map *self = malloc(sizeof(*self));
148
149 if (self != NULL) {
150 self->start = event->start;
151 self->end = event->start + event->len;
152 self->pgoff = event->pgoff;
153
154 self->dso = dsos__findnew(event->filename);
155 if (self->dso == NULL)
156 goto out_delete;
157 }
158 return self;
159out_delete:
160 free(self);
161 return NULL;
162}
163
3a4b8cc7
ACM
164struct thread;
165
8fa66bdc 166struct thread {
ce7e4365 167 struct rb_node rb_node;
8fa66bdc 168 struct list_head maps;
8fa66bdc
ACM
169 pid_t pid;
170 char *comm;
171};
172
173static struct thread *thread__new(pid_t pid)
174{
175 struct thread *self = malloc(sizeof(*self));
176
177 if (self != NULL) {
178 self->pid = pid;
179 self->comm = NULL;
180 INIT_LIST_HEAD(&self->maps);
8fa66bdc
ACM
181 }
182
183 return self;
184}
185
8fa66bdc
ACM
186static int thread__set_comm(struct thread *self, const char *comm)
187{
188 self->comm = strdup(comm);
189 return self->comm ? 0 : -ENOMEM;
190}
191
16f762a2 192static struct rb_root threads;
8fa66bdc 193
ce7e4365 194static struct thread *threads__findnew(pid_t pid)
8fa66bdc 195{
ce7e4365
ACM
196 struct rb_node **p = &threads.rb_node;
197 struct rb_node *parent = NULL;
198 struct thread *th;
8fa66bdc 199
ce7e4365
ACM
200 while (*p != NULL) {
201 parent = *p;
202 th = rb_entry(parent, struct thread, rb_node);
8fa66bdc 203
ce7e4365
ACM
204 if (th->pid == pid)
205 return th;
8fa66bdc 206
ce7e4365
ACM
207 if (pid < th->pid)
208 p = &(*p)->rb_left;
209 else
210 p = &(*p)->rb_right;
8fa66bdc
ACM
211 }
212
ce7e4365
ACM
213 th = thread__new(pid);
214 if (th != NULL) {
215 rb_link_node(&th->rb_node, parent, p);
216 rb_insert_color(&th->rb_node, &threads);
217 }
218 return th;
8fa66bdc
ACM
219}
220
221static void thread__insert_map(struct thread *self, struct map *map)
222{
223 list_add_tail(&map->node, &self->maps);
224}
225
226static struct map *thread__find_map(struct thread *self, uint64_t ip)
227{
16f762a2
IM
228 struct map *pos;
229
8fa66bdc
ACM
230 if (self == NULL)
231 return NULL;
232
8fa66bdc
ACM
233 list_for_each_entry(pos, &self->maps, node)
234 if (ip >= pos->start && ip <= pos->end)
235 return pos;
236
237 return NULL;
238}
239
e7fb08b1
PZ
240/*
241 * histogram, sorted on item, collects counts
242 */
243
244static struct rb_root hist;
245
246struct hist_entry {
247 struct rb_node rb_node;
248
249 struct thread *thread;
250 struct map *map;
251 struct dso *dso;
252 struct symbol *sym;
253 uint64_t ip;
254 char level;
255
256 uint32_t count;
257};
258
1aa16738
PZ
259/*
260 * configurable sorting bits
261 */
262
263struct sort_entry {
264 struct list_head list;
265
ca8cdeef
PZ
266 char *header;
267
1aa16738
PZ
268 int64_t (*cmp)(struct hist_entry *, struct hist_entry *);
269 size_t (*print)(FILE *fp, struct hist_entry *);
270};
271
e7fb08b1 272static int64_t
1aa16738 273sort__thread_cmp(struct hist_entry *left, struct hist_entry *right)
e7fb08b1 274{
1aa16738
PZ
275 return right->thread->pid - left->thread->pid;
276}
277
278static size_t
279sort__thread_print(FILE *fp, struct hist_entry *self)
280{
ca8cdeef 281 return fprintf(fp, " %16s:%5d", self->thread->comm ?: "", self->thread->pid);
1aa16738 282}
e7fb08b1 283
1aa16738 284static struct sort_entry sort_thread = {
ca8cdeef 285 .header = " Command: Pid ",
1aa16738
PZ
286 .cmp = sort__thread_cmp,
287 .print = sort__thread_print,
288};
289
992444b1
PZ
290static int64_t
291sort__comm_cmp(struct hist_entry *left, struct hist_entry *right)
292{
293 char *comm_l = left->thread->comm;
294 char *comm_r = right->thread->comm;
295
296 if (!comm_l || !comm_r) {
297 if (!comm_l && !comm_r)
298 return 0;
299 else if (!comm_l)
300 return -1;
301 else
302 return 1;
303 }
304
305 return strcmp(comm_l, comm_r);
306}
307
308static size_t
309sort__comm_print(FILE *fp, struct hist_entry *self)
310{
2d65537e 311 return fprintf(fp, " %16s", self->thread->comm ?: "<unknown>");
992444b1
PZ
312}
313
314static struct sort_entry sort_comm = {
ca8cdeef 315 .header = " Command",
992444b1
PZ
316 .cmp = sort__comm_cmp,
317 .print = sort__comm_print,
318};
319
55e5ec41
PZ
320static int64_t
321sort__dso_cmp(struct hist_entry *left, struct hist_entry *right)
322{
323 struct dso *dso_l = left->dso;
324 struct dso *dso_r = right->dso;
325
326 if (!dso_l || !dso_r) {
327 if (!dso_l && !dso_r)
328 return 0;
329 else if (!dso_l)
330 return -1;
331 else
332 return 1;
333 }
334
335 return strcmp(dso_l->name, dso_r->name);
336}
337
338static size_t
339sort__dso_print(FILE *fp, struct hist_entry *self)
340{
2d65537e 341 return fprintf(fp, " %64s", self->dso ? self->dso->name : "<unknown>");
55e5ec41
PZ
342}
343
344static struct sort_entry sort_dso = {
ca8cdeef 345 .header = " Shared Object",
55e5ec41
PZ
346 .cmp = sort__dso_cmp,
347 .print = sort__dso_print,
348};
349
1aa16738
PZ
350static int64_t
351sort__sym_cmp(struct hist_entry *left, struct hist_entry *right)
352{
353 uint64_t ip_l, ip_r;
e7fb08b1
PZ
354
355 if (left->sym == right->sym)
356 return 0;
357
358 ip_l = left->sym ? left->sym->start : left->ip;
359 ip_r = right->sym ? right->sym->start : right->ip;
360
361 return (int64_t)(ip_r - ip_l);
362}
363
1aa16738
PZ
364static size_t
365sort__sym_print(FILE *fp, struct hist_entry *self)
366{
367 size_t ret = 0;
368
1aa16738 369 if (verbose)
2d65537e 370 ret += fprintf(fp, " %#018llx", (unsigned long long)self->ip);
1aa16738 371
ca8cdeef
PZ
372 ret += fprintf(fp, " %s: %s",
373 self->dso ? self->dso->name : "<unknown>",
374 self->sym ? self->sym->name : "<unknown>");
1aa16738
PZ
375
376 return ret;
377}
378
379static struct sort_entry sort_sym = {
ca8cdeef
PZ
380 .header = "Shared Object: Symbol",
381 .cmp = sort__sym_cmp,
382 .print = sort__sym_print,
1aa16738
PZ
383};
384
37f440cb
PZ
385struct sort_dimension {
386 char *name;
387 struct sort_entry *entry;
388 int taken;
389};
390
391static struct sort_dimension sort_dimensions[] = {
392 { .name = "pid", .entry = &sort_thread, },
992444b1 393 { .name = "comm", .entry = &sort_comm, },
55e5ec41 394 { .name = "dso", .entry = &sort_dso, },
37f440cb
PZ
395 { .name = "symbol", .entry = &sort_sym, },
396};
397
1aa16738
PZ
398static LIST_HEAD(hist_entry__sort_list);
399
37f440cb
PZ
400static int sort_dimension__add(char *tok)
401{
402 int i;
403
404 for (i = 0; i < ARRAY_SIZE(sort_dimensions); i++) {
405 struct sort_dimension *sd = &sort_dimensions[i];
406
407 if (sd->taken)
408 continue;
409
410 if (strcmp(tok, sd->name))
411 continue;
412
413 list_add_tail(&sd->entry->list, &hist_entry__sort_list);
414 sd->taken = 1;
415 return 0;
416 }
417
418 return -ESRCH;
419}
420
1aa16738
PZ
421static void setup_sorting(void)
422{
37f440cb
PZ
423 char *tmp, *tok, *str = strdup(sort_order);
424
425 for (tok = strtok_r(str, ", ", &tmp);
426 tok; tok = strtok_r(NULL, ", ", &tmp))
427 sort_dimension__add(tok);
428
429 free(str);
1aa16738
PZ
430}
431
432static int64_t
433hist_entry__cmp(struct hist_entry *left, struct hist_entry *right)
434{
435 struct sort_entry *se;
436 int64_t cmp = 0;
437
438 list_for_each_entry(se, &hist_entry__sort_list, list) {
439 cmp = se->cmp(left, right);
440 if (cmp)
441 break;
442 }
443
444 return cmp;
445}
446
447static size_t
448hist_entry__fprintf(FILE *fp, struct hist_entry *self, uint64_t total_samples)
449{
450 struct sort_entry *se;
451 size_t ret;
452
453 if (total_samples) {
2d65537e 454 ret = fprintf(fp, " %5.2f%%",
1aa16738
PZ
455 (self->count * 100.0) / total_samples);
456 } else
457 ret = fprintf(fp, "%12d ", self->count);
458
459 list_for_each_entry(se, &hist_entry__sort_list, list)
460 ret += se->print(fp, self);
461
462 ret += fprintf(fp, "\n");
463
464 return ret;
465}
466
467/*
468 * collect histogram counts
469 */
470
e7fb08b1
PZ
471static int
472hist_entry__add(struct thread *thread, struct map *map, struct dso *dso,
473 struct symbol *sym, uint64_t ip, char level)
8fa66bdc 474{
e7fb08b1
PZ
475 struct rb_node **p = &hist.rb_node;
476 struct rb_node *parent = NULL;
477 struct hist_entry *he;
478 struct hist_entry entry = {
479 .thread = thread,
480 .map = map,
481 .dso = dso,
482 .sym = sym,
483 .ip = ip,
484 .level = level,
485 .count = 1,
486 };
487 int cmp;
488
489 while (*p != NULL) {
490 parent = *p;
491 he = rb_entry(parent, struct hist_entry, rb_node);
492
493 cmp = hist_entry__cmp(&entry, he);
494
495 if (!cmp) {
496 he->count++;
497 return 0;
498 }
499
500 if (cmp < 0)
501 p = &(*p)->rb_left;
502 else
503 p = &(*p)->rb_right;
ce7e4365 504 }
e7fb08b1
PZ
505
506 he = malloc(sizeof(*he));
507 if (!he)
508 return -ENOMEM;
509 *he = entry;
510 rb_link_node(&he->rb_node, parent, p);
511 rb_insert_color(&he->rb_node, &hist);
512
513 return 0;
8fa66bdc
ACM
514}
515
e7fb08b1
PZ
516/*
517 * reverse the map, sort on count.
518 */
519
520static struct rb_root output_hists;
521
522static void output__insert_entry(struct hist_entry *he)
3a4b8cc7 523{
e7fb08b1 524 struct rb_node **p = &output_hists.rb_node;
3a4b8cc7 525 struct rb_node *parent = NULL;
e7fb08b1 526 struct hist_entry *iter;
3a4b8cc7
ACM
527
528 while (*p != NULL) {
529 parent = *p;
e7fb08b1 530 iter = rb_entry(parent, struct hist_entry, rb_node);
3a4b8cc7 531
e7fb08b1 532 if (he->count > iter->count)
3a4b8cc7
ACM
533 p = &(*p)->rb_left;
534 else
535 p = &(*p)->rb_right;
536 }
537
e7fb08b1
PZ
538 rb_link_node(&he->rb_node, parent, p);
539 rb_insert_color(&he->rb_node, &output_hists);
3a4b8cc7
ACM
540}
541
e7fb08b1 542static void output__resort(void)
3a4b8cc7 543{
e7fb08b1
PZ
544 struct rb_node *next = rb_first(&hist);
545 struct hist_entry *n;
3a4b8cc7 546
e7fb08b1
PZ
547 while (next) {
548 n = rb_entry(next, struct hist_entry, rb_node);
549 next = rb_next(&n->rb_node);
3a4b8cc7 550
e7fb08b1
PZ
551 rb_erase(&n->rb_node, &hist);
552 output__insert_entry(n);
3a4b8cc7
ACM
553 }
554}
555
e7fb08b1 556static size_t output__fprintf(FILE *fp, uint64_t total_samples)
3a4b8cc7 557{
e7fb08b1 558 struct hist_entry *pos;
2d65537e 559 struct sort_entry *se;
3a4b8cc7
ACM
560 struct rb_node *nd;
561 size_t ret = 0;
562
ca8cdeef
PZ
563 fprintf(fp, "#\n");
564
565 fprintf(fp, "# Overhead");
566 list_for_each_entry(se, &hist_entry__sort_list, list)
567 fprintf(fp, " %s", se->header);
568 fprintf(fp, "\n");
569
570 fprintf(fp, "# ........");
2d65537e 571 list_for_each_entry(se, &hist_entry__sort_list, list) {
ca8cdeef
PZ
572 int i;
573
574 fprintf(fp, " ");
575 for (i = 0; i < strlen(se->header); i++)
576 fprintf(fp, ".");
2d65537e 577 }
ca8cdeef
PZ
578 fprintf(fp, "\n");
579
580 fprintf(fp, "#\n");
2d65537e 581
e7fb08b1
PZ
582 for (nd = rb_first(&output_hists); nd; nd = rb_next(nd)) {
583 pos = rb_entry(nd, struct hist_entry, rb_node);
584 ret += hist_entry__fprintf(fp, pos, total_samples);
3a4b8cc7
ACM
585 }
586
587 return ret;
588}
589
e7fb08b1 590
53cb8bc2 591static int __cmd_report(void)
8fa66bdc
ACM
592{
593 unsigned long offset = 0;
594 unsigned long head = 0;
595 struct stat stat;
596 char *buf;
597 event_t *event;
598 int ret, rc = EXIT_FAILURE;
6142f9ec 599 uint32_t size;
f49515b1 600 unsigned long total = 0, total_mmap = 0, total_comm = 0, total_unknown = 0;
8fa66bdc 601
8fa66bdc
ACM
602 input = open(input_name, O_RDONLY);
603 if (input < 0) {
604 perror("failed to open file");
605 exit(-1);
606 }
607
608 ret = fstat(input, &stat);
609 if (ret < 0) {
610 perror("failed to stat file");
611 exit(-1);
612 }
613
614 if (!stat.st_size) {
615 fprintf(stderr, "zero-sized file, nothing to do!\n");
616 exit(0);
617 }
618
450aaa2b 619 if (load_kernel() < 0) {
a2928c42 620 perror("failed to load kernel symbols");
8fa66bdc
ACM
621 return EXIT_FAILURE;
622 }
623
624remap:
625 buf = (char *)mmap(NULL, page_size * mmap_window, PROT_READ,
626 MAP_SHARED, input, offset);
627 if (buf == MAP_FAILED) {
628 perror("failed to mmap file");
629 exit(-1);
630 }
631
632more:
633 event = (event_t *)(buf + head);
634
6142f9ec
PZ
635 size = event->header.size;
636 if (!size)
637 size = 8;
638
8fa66bdc
ACM
639 if (head + event->header.size >= page_size * mmap_window) {
640 unsigned long shift = page_size * (head / page_size);
641 int ret;
642
643 ret = munmap(buf, page_size * mmap_window);
644 assert(ret == 0);
645
646 offset += shift;
647 head -= shift;
648 goto remap;
649 }
650
6142f9ec
PZ
651 size = event->header.size;
652 if (!size)
653 goto broken_event;
8fa66bdc 654
8fa66bdc
ACM
655 if (event->header.misc & PERF_EVENT_MISC_OVERFLOW) {
656 char level;
657 int show = 0;
658 struct dso *dso = NULL;
659 struct thread *thread = threads__findnew(event->ip.pid);
f17e04af 660 uint64_t ip = event->ip.ip;
e7fb08b1 661 struct map *map = NULL;
8fa66bdc 662
97b07b69 663 if (dump_trace) {
f49515b1
IM
664 fprintf(stderr, "%p [%p]: PERF_EVENT (IP, %d): %d: %p\n",
665 (void *)(offset + head),
666 (void *)(long)(event->header.size),
97b07b69
IM
667 event->header.misc,
668 event->ip.pid,
16f762a2 669 (void *)(long)ip);
97b07b69
IM
670 }
671
ce7e4365 672 if (thread == NULL) {
55717314 673 fprintf(stderr, "problem processing %d event, skipping it.\n",
ce7e4365 674 event->header.type);
55717314 675 goto broken_event;
ce7e4365 676 }
8fa66bdc
ACM
677
678 if (event->header.misc & PERF_EVENT_MISC_KERNEL) {
679 show = SHOW_KERNEL;
680 level = 'k';
e7fb08b1 681
8fa66bdc 682 dso = kernel_dso;
e7fb08b1 683
8fa66bdc 684 } else if (event->header.misc & PERF_EVENT_MISC_USER) {
16f762a2 685
8fa66bdc
ACM
686 show = SHOW_USER;
687 level = '.';
16f762a2
IM
688
689 map = thread__find_map(thread, ip);
f17e04af 690 if (map != NULL) {
8fa66bdc 691 dso = map->dso;
f17e04af
PZ
692 ip -= map->start + map->pgoff;
693 }
e7fb08b1 694
8fa66bdc
ACM
695 } else {
696 show = SHOW_HV;
697 level = 'H';
698 }
699
700 if (show & show_mask) {
f17e04af 701 struct symbol *sym = dso__find_symbol(dso, ip);
8fa66bdc 702
e7fb08b1
PZ
703 if (hist_entry__add(thread, map, dso, sym, ip, level)) {
704 fprintf(stderr,
55717314
IM
705 "problem incrementing symbol count, skipping event\n");
706 goto broken_event;
ce7e4365 707 }
8fa66bdc
ACM
708 }
709 total++;
710 } else switch (event->header.type) {
711 case PERF_EVENT_MMAP: {
712 struct thread *thread = threads__findnew(event->mmap.pid);
713 struct map *map = map__new(&event->mmap);
714
97b07b69 715 if (dump_trace) {
f49515b1
IM
716 fprintf(stderr, "%p [%p]: PERF_EVENT_MMAP: [%p(%p) @ %p]: %s\n",
717 (void *)(offset + head),
718 (void *)(long)(event->header.size),
16f762a2
IM
719 (void *)(long)event->mmap.start,
720 (void *)(long)event->mmap.len,
721 (void *)(long)event->mmap.pgoff,
97b07b69
IM
722 event->mmap.filename);
723 }
ce7e4365 724 if (thread == NULL || map == NULL) {
55717314
IM
725 fprintf(stderr, "problem processing PERF_EVENT_MMAP, skipping event.\n");
726 goto broken_event;
ce7e4365 727 }
8fa66bdc 728 thread__insert_map(thread, map);
97b07b69 729 total_mmap++;
8fa66bdc
ACM
730 break;
731 }
732 case PERF_EVENT_COMM: {
733 struct thread *thread = threads__findnew(event->comm.pid);
734
97b07b69 735 if (dump_trace) {
f49515b1
IM
736 fprintf(stderr, "%p [%p]: PERF_EVENT_COMM: %s:%d\n",
737 (void *)(offset + head),
738 (void *)(long)(event->header.size),
97b07b69
IM
739 event->comm.comm, event->comm.pid);
740 }
8fa66bdc 741 if (thread == NULL ||
ce7e4365 742 thread__set_comm(thread, event->comm.comm)) {
55717314
IM
743 fprintf(stderr, "problem processing PERF_EVENT_COMM, skipping event.\n");
744 goto broken_event;
ce7e4365 745 }
97b07b69 746 total_comm++;
8fa66bdc
ACM
747 break;
748 }
97b07b69 749 default: {
6142f9ec 750broken_event:
b7a16eac
PZ
751 if (dump_trace)
752 fprintf(stderr, "%p [%p]: skipping unknown header type: %d\n",
753 (void *)(offset + head),
754 (void *)(long)(event->header.size),
755 event->header.type);
756
3e706114 757 total_unknown++;
6142f9ec
PZ
758
759 /*
760 * assume we lost track of the stream, check alignment, and
761 * increment a single u64 in the hope to catch on again 'soon'.
762 */
763
764 if (unlikely(head & 7))
765 head &= ~7ULL;
766
767 size = 8;
97b07b69 768 }
8fa66bdc
ACM
769 }
770
6142f9ec 771 head += size;
f49515b1 772
8fa66bdc
ACM
773 if (offset + head < stat.st_size)
774 goto more;
775
776 rc = EXIT_SUCCESS;
8fa66bdc 777 close(input);
97b07b69
IM
778
779 if (dump_trace) {
3e706114
IM
780 fprintf(stderr, " IP events: %10ld\n", total);
781 fprintf(stderr, " mmap events: %10ld\n", total_mmap);
782 fprintf(stderr, " comm events: %10ld\n", total_comm);
783 fprintf(stderr, " unknown events: %10ld\n", total_unknown);
97b07b69
IM
784
785 return 0;
786 }
787
e7fb08b1 788 if (verbose >= 2)
16f762a2 789 dsos__fprintf(stdout);
16f762a2 790
e7fb08b1
PZ
791 output__resort();
792 output__fprintf(stdout, total);
8fa66bdc 793
8fa66bdc
ACM
794 return rc;
795}
796
53cb8bc2
IM
797static const char * const report_usage[] = {
798 "perf report [<options>] <command>",
799 NULL
800};
801
802static const struct option options[] = {
803 OPT_STRING('i', "input", &input_name, "file",
804 "input file name"),
815e777f
ACM
805 OPT_BOOLEAN('v', "verbose", &verbose,
806 "be more verbose (show symbol address, etc)"),
97b07b69
IM
807 OPT_BOOLEAN('D', "dump-raw-trace", &dump_trace,
808 "dump raw trace in ASCII"),
450aaa2b 809 OPT_STRING('k', "vmlinux", &vmlinux, "file", "vmlinux pathname"),
63299f05
IM
810 OPT_STRING('s', "sort", &sort_order, "key[,key2...]",
811 "sort by key(s): pid, comm, dso, symbol. Default: pid,symbol"),
53cb8bc2
IM
812 OPT_END()
813};
814
815int cmd_report(int argc, const char **argv, const char *prefix)
816{
a2928c42 817 symbol__init();
53cb8bc2
IM
818
819 page_size = getpagesize();
820
821 parse_options(argc, argv, options, report_usage, 0);
822
1aa16738
PZ
823 setup_sorting();
824
a930d2c0
IM
825 setup_pager();
826
53cb8bc2
IM
827 return __cmd_report();
828}
This page took 0.073474 seconds and 5 git commands to generate.