1 /* 2 * builtin-report.c 3 * 4 * Builtin report command: Analyze the perf.data input file, 5 * look up and read DSOs and symbol information and display 6 * a histogram of results, along various sorting keys. 7 */ 8 #include "builtin.h" 9 10 #include "util/util.h" 11 12 #include "util/color.h" 13 #include <linux/list.h> 14 #include "util/cache.h" 15 #include <linux/rbtree.h> 16 #include "util/symbol.h" 17 #include "util/string.h" 18 #include "util/callchain.h" 19 #include "util/strlist.h" 20 21 #include "perf.h" 22 #include "util/header.h" 23 24 #include "util/parse-options.h" 25 #include "util/parse-events.h" 26 27 #define SHOW_KERNEL 1 28 #define SHOW_USER 2 29 #define SHOW_HV 4 30 31 static char const *input_name = "perf.data"; 32 static char *vmlinux = NULL; 33 34 static char default_sort_order[] = "comm,dso,symbol"; 35 static char *sort_order = default_sort_order; 36 static char *dso_list_str, *comm_list_str, *sym_list_str, 37 *col_width_list_str; 38 static struct strlist *dso_list, *comm_list, *sym_list; 39 static char *field_sep; 40 41 static int input; 42 static int show_mask = SHOW_KERNEL | SHOW_USER | SHOW_HV; 43 44 static int dump_trace = 0; 45 #define dprintf(x...) do { if (dump_trace) printf(x); } while (0) 46 #define cdprintf(x...) do { if (dump_trace) color_fprintf(stdout, color, x); } while (0) 47 48 static int verbose; 49 #define eprintf(x...) do { if (verbose) fprintf(stderr, x); } while (0) 50 51 static int modules; 52 53 static int full_paths; 54 static int show_nr_samples; 55 56 static unsigned long page_size; 57 static unsigned long mmap_window = 32; 58 59 static char default_parent_pattern[] = "^sys_|^do_page_fault"; 60 static char *parent_pattern = default_parent_pattern; 61 static regex_t parent_regex; 62 63 static int exclude_other = 1; 64 65 static char callchain_default_opt[] = "fractal,0.5"; 66 67 static int callchain; 68 69 static 70 struct callchain_param callchain_param = { 71 .mode = CHAIN_GRAPH_ABS, 72 .min_percent = 0.5 73 }; 74 75 static u64 sample_type; 76 77 struct ip_event { 78 struct perf_event_header header; 79 u64 ip; 80 u32 pid, tid; 81 unsigned char __more_data[]; 82 }; 83 84 struct mmap_event { 85 struct perf_event_header header; 86 u32 pid, tid; 87 u64 start; 88 u64 len; 89 u64 pgoff; 90 char filename[PATH_MAX]; 91 }; 92 93 struct comm_event { 94 struct perf_event_header header; 95 u32 pid, tid; 96 char comm[16]; 97 }; 98 99 struct fork_event { 100 struct perf_event_header header; 101 u32 pid, ppid; 102 u32 tid, ptid; 103 }; 104 105 struct lost_event { 106 struct perf_event_header header; 107 u64 id; 108 u64 lost; 109 }; 110 111 struct read_event { 112 struct perf_event_header header; 113 u32 pid,tid; 114 u64 value; 115 u64 format[3]; 116 }; 117 118 typedef union event_union { 119 struct perf_event_header header; 120 struct ip_event ip; 121 struct mmap_event mmap; 122 struct comm_event comm; 123 struct fork_event fork; 124 struct lost_event lost; 125 struct read_event read; 126 } event_t; 127 128 static int repsep_fprintf(FILE *fp, const char *fmt, ...) 129 { 130 int n; 131 va_list ap; 132 133 va_start(ap, fmt); 134 if (!field_sep) 135 n = vfprintf(fp, fmt, ap); 136 else { 137 char *bf = NULL; 138 n = vasprintf(&bf, fmt, ap); 139 if (n > 0) { 140 char *sep = bf; 141 while (1) { 142 sep = strchr(sep, *field_sep); 143 if (sep == NULL) 144 break; 145 *sep = '.'; 146 } 147 } 148 fputs(bf, fp); 149 free(bf); 150 } 151 va_end(ap); 152 return n; 153 } 154 155 static LIST_HEAD(dsos); 156 static struct dso *kernel_dso; 157 static struct dso *vdso; 158 static struct dso *hypervisor_dso; 159 160 static void dsos__add(struct dso *dso) 161 { 162 list_add_tail(&dso->node, &dsos); 163 } 164 165 static struct dso *dsos__find(const char *name) 166 { 167 struct dso *pos; 168 169 list_for_each_entry(pos, &dsos, node) 170 if (strcmp(pos->name, name) == 0) 171 return pos; 172 return NULL; 173 } 174 175 static struct dso *dsos__findnew(const char *name) 176 { 177 struct dso *dso = dsos__find(name); 178 int nr; 179 180 if (dso) 181 return dso; 182 183 dso = dso__new(name, 0); 184 if (!dso) 185 goto out_delete_dso; 186 187 nr = dso__load(dso, NULL, verbose); 188 if (nr < 0) { 189 eprintf("Failed to open: %s\n", name); 190 goto out_delete_dso; 191 } 192 if (!nr) 193 eprintf("No symbols found in: %s, maybe install a debug package?\n", name); 194 195 dsos__add(dso); 196 197 return dso; 198 199 out_delete_dso: 200 dso__delete(dso); 201 return NULL; 202 } 203 204 static void dsos__fprintf(FILE *fp) 205 { 206 struct dso *pos; 207 208 list_for_each_entry(pos, &dsos, node) 209 dso__fprintf(pos, fp); 210 } 211 212 static struct symbol *vdso__find_symbol(struct dso *dso, u64 ip) 213 { 214 return dso__find_symbol(dso, ip); 215 } 216 217 static int load_kernel(void) 218 { 219 int err; 220 221 kernel_dso = dso__new("[kernel]", 0); 222 if (!kernel_dso) 223 return -1; 224 225 err = dso__load_kernel(kernel_dso, vmlinux, NULL, verbose, modules); 226 if (err <= 0) { 227 dso__delete(kernel_dso); 228 kernel_dso = NULL; 229 } else 230 dsos__add(kernel_dso); 231 232 vdso = dso__new("[vdso]", 0); 233 if (!vdso) 234 return -1; 235 236 vdso->find_symbol = vdso__find_symbol; 237 238 dsos__add(vdso); 239 240 hypervisor_dso = dso__new("[hypervisor]", 0); 241 if (!hypervisor_dso) 242 return -1; 243 dsos__add(hypervisor_dso); 244 245 return err; 246 } 247 248 static char __cwd[PATH_MAX]; 249 static char *cwd = __cwd; 250 static int cwdlen; 251 252 static int strcommon(const char *pathname) 253 { 254 int n = 0; 255 256 while (n < cwdlen && pathname[n] == cwd[n]) 257 ++n; 258 259 return n; 260 } 261 262 struct map { 263 struct list_head node; 264 u64 start; 265 u64 end; 266 u64 pgoff; 267 u64 (*map_ip)(struct map *, u64); 268 struct dso *dso; 269 }; 270 271 static u64 map__map_ip(struct map *map, u64 ip) 272 { 273 return ip - map->start + map->pgoff; 274 } 275 276 static u64 vdso__map_ip(struct map *map __used, u64 ip) 277 { 278 return ip; 279 } 280 281 static inline int is_anon_memory(const char *filename) 282 { 283 return strcmp(filename, "//anon") == 0; 284 } 285 286 static struct map *map__new(struct mmap_event *event) 287 { 288 struct map *self = malloc(sizeof(*self)); 289 290 if (self != NULL) { 291 const char *filename = event->filename; 292 char newfilename[PATH_MAX]; 293 int anon; 294 295 if (cwd) { 296 int n = strcommon(filename); 297 298 if (n == cwdlen) { 299 snprintf(newfilename, sizeof(newfilename), 300 ".%s", filename + n); 301 filename = newfilename; 302 } 303 } 304 305 anon = is_anon_memory(filename); 306 307 if (anon) { 308 snprintf(newfilename, sizeof(newfilename), "/tmp/perf-%d.map", event->pid); 309 filename = newfilename; 310 } 311 312 self->start = event->start; 313 self->end = event->start + event->len; 314 self->pgoff = event->pgoff; 315 316 self->dso = dsos__findnew(filename); 317 if (self->dso == NULL) 318 goto out_delete; 319 320 if (self->dso == vdso || anon) 321 self->map_ip = vdso__map_ip; 322 else 323 self->map_ip = map__map_ip; 324 } 325 return self; 326 out_delete: 327 free(self); 328 return NULL; 329 } 330 331 static struct map *map__clone(struct map *self) 332 { 333 struct map *map = malloc(sizeof(*self)); 334 335 if (!map) 336 return NULL; 337 338 memcpy(map, self, sizeof(*self)); 339 340 return map; 341 } 342 343 static int map__overlap(struct map *l, struct map *r) 344 { 345 if (l->start > r->start) { 346 struct map *t = l; 347 l = r; 348 r = t; 349 } 350 351 if (l->end > r->start) 352 return 1; 353 354 return 0; 355 } 356 357 static size_t map__fprintf(struct map *self, FILE *fp) 358 { 359 return fprintf(fp, " %Lx-%Lx %Lx %s\n", 360 self->start, self->end, self->pgoff, self->dso->name); 361 } 362 363 364 struct thread { 365 struct rb_node rb_node; 366 struct list_head maps; 367 pid_t pid; 368 char *comm; 369 }; 370 371 static struct thread *thread__new(pid_t pid) 372 { 373 struct thread *self = malloc(sizeof(*self)); 374 375 if (self != NULL) { 376 self->pid = pid; 377 self->comm = malloc(32); 378 if (self->comm) 379 snprintf(self->comm, 32, ":%d", self->pid); 380 INIT_LIST_HEAD(&self->maps); 381 } 382 383 return self; 384 } 385 386 static unsigned int dsos__col_width, 387 comms__col_width, 388 threads__col_width; 389 390 static int thread__set_comm(struct thread *self, const char *comm) 391 { 392 if (self->comm) 393 free(self->comm); 394 self->comm = strdup(comm); 395 if (!self->comm) 396 return -ENOMEM; 397 398 if (!col_width_list_str && !field_sep && 399 (!comm_list || strlist__has_entry(comm_list, comm))) { 400 unsigned int slen = strlen(comm); 401 if (slen > comms__col_width) { 402 comms__col_width = slen; 403 threads__col_width = slen + 6; 404 } 405 } 406 407 return 0; 408 } 409 410 static size_t thread__fprintf(struct thread *self, FILE *fp) 411 { 412 struct map *pos; 413 size_t ret = fprintf(fp, "Thread %d %s\n", self->pid, self->comm); 414 415 list_for_each_entry(pos, &self->maps, node) 416 ret += map__fprintf(pos, fp); 417 418 return ret; 419 } 420 421 422 static struct rb_root threads; 423 static struct thread *last_match; 424 425 static struct thread *threads__findnew(pid_t pid) 426 { 427 struct rb_node **p = &threads.rb_node; 428 struct rb_node *parent = NULL; 429 struct thread *th; 430 431 /* 432 * Font-end cache - PID lookups come in blocks, 433 * so most of the time we dont have to look up 434 * the full rbtree: 435 */ 436 if (last_match && last_match->pid == pid) 437 return last_match; 438 439 while (*p != NULL) { 440 parent = *p; 441 th = rb_entry(parent, struct thread, rb_node); 442 443 if (th->pid == pid) { 444 last_match = th; 445 return th; 446 } 447 448 if (pid < th->pid) 449 p = &(*p)->rb_left; 450 else 451 p = &(*p)->rb_right; 452 } 453 454 th = thread__new(pid); 455 if (th != NULL) { 456 rb_link_node(&th->rb_node, parent, p); 457 rb_insert_color(&th->rb_node, &threads); 458 last_match = th; 459 } 460 461 return th; 462 } 463 464 static void thread__insert_map(struct thread *self, struct map *map) 465 { 466 struct map *pos, *tmp; 467 468 list_for_each_entry_safe(pos, tmp, &self->maps, node) { 469 if (map__overlap(pos, map)) { 470 if (verbose >= 2) { 471 printf("overlapping maps:\n"); 472 map__fprintf(map, stdout); 473 map__fprintf(pos, stdout); 474 } 475 476 if (map->start <= pos->start && map->end > pos->start) 477 pos->start = map->end; 478 479 if (map->end >= pos->end && map->start < pos->end) 480 pos->end = map->start; 481 482 if (verbose >= 2) { 483 printf("after collision:\n"); 484 map__fprintf(pos, stdout); 485 } 486 487 if (pos->start >= pos->end) { 488 list_del_init(&pos->node); 489 free(pos); 490 } 491 } 492 } 493 494 list_add_tail(&map->node, &self->maps); 495 } 496 497 static int thread__fork(struct thread *self, struct thread *parent) 498 { 499 struct map *map; 500 501 if (self->comm) 502 free(self->comm); 503 self->comm = strdup(parent->comm); 504 if (!self->comm) 505 return -ENOMEM; 506 507 list_for_each_entry(map, &parent->maps, node) { 508 struct map *new = map__clone(map); 509 if (!new) 510 return -ENOMEM; 511 thread__insert_map(self, new); 512 } 513 514 return 0; 515 } 516 517 static struct map *thread__find_map(struct thread *self, u64 ip) 518 { 519 struct map *pos; 520 521 if (self == NULL) 522 return NULL; 523 524 list_for_each_entry(pos, &self->maps, node) 525 if (ip >= pos->start && ip <= pos->end) 526 return pos; 527 528 return NULL; 529 } 530 531 static size_t threads__fprintf(FILE *fp) 532 { 533 size_t ret = 0; 534 struct rb_node *nd; 535 536 for (nd = rb_first(&threads); nd; nd = rb_next(nd)) { 537 struct thread *pos = rb_entry(nd, struct thread, rb_node); 538 539 ret += thread__fprintf(pos, fp); 540 } 541 542 return ret; 543 } 544 545 /* 546 * histogram, sorted on item, collects counts 547 */ 548 549 static struct rb_root hist; 550 551 struct hist_entry { 552 struct rb_node rb_node; 553 554 struct thread *thread; 555 struct map *map; 556 struct dso *dso; 557 struct symbol *sym; 558 struct symbol *parent; 559 u64 ip; 560 char level; 561 struct callchain_node callchain; 562 struct rb_root sorted_chain; 563 564 u64 count; 565 }; 566 567 /* 568 * configurable sorting bits 569 */ 570 571 struct sort_entry { 572 struct list_head list; 573 574 char *header; 575 576 int64_t (*cmp)(struct hist_entry *, struct hist_entry *); 577 int64_t (*collapse)(struct hist_entry *, struct hist_entry *); 578 size_t (*print)(FILE *fp, struct hist_entry *, unsigned int width); 579 unsigned int *width; 580 bool elide; 581 }; 582 583 static int64_t cmp_null(void *l, void *r) 584 { 585 if (!l && !r) 586 return 0; 587 else if (!l) 588 return -1; 589 else 590 return 1; 591 } 592 593 /* --sort pid */ 594 595 static int64_t 596 sort__thread_cmp(struct hist_entry *left, struct hist_entry *right) 597 { 598 return right->thread->pid - left->thread->pid; 599 } 600 601 static size_t 602 sort__thread_print(FILE *fp, struct hist_entry *self, unsigned int width) 603 { 604 return repsep_fprintf(fp, "%*s:%5d", width - 6, 605 self->thread->comm ?: "", self->thread->pid); 606 } 607 608 static struct sort_entry sort_thread = { 609 .header = "Command: Pid", 610 .cmp = sort__thread_cmp, 611 .print = sort__thread_print, 612 .width = &threads__col_width, 613 }; 614 615 /* --sort comm */ 616 617 static int64_t 618 sort__comm_cmp(struct hist_entry *left, struct hist_entry *right) 619 { 620 return right->thread->pid - left->thread->pid; 621 } 622 623 static int64_t 624 sort__comm_collapse(struct hist_entry *left, struct hist_entry *right) 625 { 626 char *comm_l = left->thread->comm; 627 char *comm_r = right->thread->comm; 628 629 if (!comm_l || !comm_r) 630 return cmp_null(comm_l, comm_r); 631 632 return strcmp(comm_l, comm_r); 633 } 634 635 static size_t 636 sort__comm_print(FILE *fp, struct hist_entry *self, unsigned int width) 637 { 638 return repsep_fprintf(fp, "%*s", width, self->thread->comm); 639 } 640 641 static struct sort_entry sort_comm = { 642 .header = "Command", 643 .cmp = sort__comm_cmp, 644 .collapse = sort__comm_collapse, 645 .print = sort__comm_print, 646 .width = &comms__col_width, 647 }; 648 649 /* --sort dso */ 650 651 static int64_t 652 sort__dso_cmp(struct hist_entry *left, struct hist_entry *right) 653 { 654 struct dso *dso_l = left->dso; 655 struct dso *dso_r = right->dso; 656 657 if (!dso_l || !dso_r) 658 return cmp_null(dso_l, dso_r); 659 660 return strcmp(dso_l->name, dso_r->name); 661 } 662 663 static size_t 664 sort__dso_print(FILE *fp, struct hist_entry *self, unsigned int width) 665 { 666 if (self->dso) 667 return repsep_fprintf(fp, "%-*s", width, self->dso->name); 668 669 return repsep_fprintf(fp, "%*llx", width, (u64)self->ip); 670 } 671 672 static struct sort_entry sort_dso = { 673 .header = "Shared Object", 674 .cmp = sort__dso_cmp, 675 .print = sort__dso_print, 676 .width = &dsos__col_width, 677 }; 678 679 /* --sort symbol */ 680 681 static int64_t 682 sort__sym_cmp(struct hist_entry *left, struct hist_entry *right) 683 { 684 u64 ip_l, ip_r; 685 686 if (left->sym == right->sym) 687 return 0; 688 689 ip_l = left->sym ? left->sym->start : left->ip; 690 ip_r = right->sym ? right->sym->start : right->ip; 691 692 return (int64_t)(ip_r - ip_l); 693 } 694 695 static size_t 696 sort__sym_print(FILE *fp, struct hist_entry *self, unsigned int width __used) 697 { 698 size_t ret = 0; 699 700 if (verbose) 701 ret += repsep_fprintf(fp, "%#018llx ", (u64)self->ip); 702 703 ret += repsep_fprintf(fp, "[%c] ", self->level); 704 if (self->sym) { 705 ret += repsep_fprintf(fp, "%s", self->sym->name); 706 707 if (self->sym->module) 708 ret += repsep_fprintf(fp, "\t[%s]", 709 self->sym->module->name); 710 } else { 711 ret += repsep_fprintf(fp, "%#016llx", (u64)self->ip); 712 } 713 714 return ret; 715 } 716 717 static struct sort_entry sort_sym = { 718 .header = "Symbol", 719 .cmp = sort__sym_cmp, 720 .print = sort__sym_print, 721 }; 722 723 /* --sort parent */ 724 725 static int64_t 726 sort__parent_cmp(struct hist_entry *left, struct hist_entry *right) 727 { 728 struct symbol *sym_l = left->parent; 729 struct symbol *sym_r = right->parent; 730 731 if (!sym_l || !sym_r) 732 return cmp_null(sym_l, sym_r); 733 734 return strcmp(sym_l->name, sym_r->name); 735 } 736 737 static size_t 738 sort__parent_print(FILE *fp, struct hist_entry *self, unsigned int width) 739 { 740 return repsep_fprintf(fp, "%-*s", width, 741 self->parent ? self->parent->name : "[other]"); 742 } 743 744 static unsigned int parent_symbol__col_width; 745 746 static struct sort_entry sort_parent = { 747 .header = "Parent symbol", 748 .cmp = sort__parent_cmp, 749 .print = sort__parent_print, 750 .width = &parent_symbol__col_width, 751 }; 752 753 static int sort__need_collapse = 0; 754 static int sort__has_parent = 0; 755 756 struct sort_dimension { 757 char *name; 758 struct sort_entry *entry; 759 int taken; 760 }; 761 762 static struct sort_dimension sort_dimensions[] = { 763 { .name = "pid", .entry = &sort_thread, }, 764 { .name = "comm", .entry = &sort_comm, }, 765 { .name = "dso", .entry = &sort_dso, }, 766 { .name = "symbol", .entry = &sort_sym, }, 767 { .name = "parent", .entry = &sort_parent, }, 768 }; 769 770 static LIST_HEAD(hist_entry__sort_list); 771 772 static int sort_dimension__add(char *tok) 773 { 774 unsigned int i; 775 776 for (i = 0; i < ARRAY_SIZE(sort_dimensions); i++) { 777 struct sort_dimension *sd = &sort_dimensions[i]; 778 779 if (sd->taken) 780 continue; 781 782 if (strncasecmp(tok, sd->name, strlen(tok))) 783 continue; 784 785 if (sd->entry->collapse) 786 sort__need_collapse = 1; 787 788 if (sd->entry == &sort_parent) { 789 int ret = regcomp(&parent_regex, parent_pattern, REG_EXTENDED); 790 if (ret) { 791 char err[BUFSIZ]; 792 793 regerror(ret, &parent_regex, err, sizeof(err)); 794 fprintf(stderr, "Invalid regex: %s\n%s", 795 parent_pattern, err); 796 exit(-1); 797 } 798 sort__has_parent = 1; 799 } 800 801 list_add_tail(&sd->entry->list, &hist_entry__sort_list); 802 sd->taken = 1; 803 804 return 0; 805 } 806 807 return -ESRCH; 808 } 809 810 static int64_t 811 hist_entry__cmp(struct hist_entry *left, struct hist_entry *right) 812 { 813 struct sort_entry *se; 814 int64_t cmp = 0; 815 816 list_for_each_entry(se, &hist_entry__sort_list, list) { 817 cmp = se->cmp(left, right); 818 if (cmp) 819 break; 820 } 821 822 return cmp; 823 } 824 825 static int64_t 826 hist_entry__collapse(struct hist_entry *left, struct hist_entry *right) 827 { 828 struct sort_entry *se; 829 int64_t cmp = 0; 830 831 list_for_each_entry(se, &hist_entry__sort_list, list) { 832 int64_t (*f)(struct hist_entry *, struct hist_entry *); 833 834 f = se->collapse ?: se->cmp; 835 836 cmp = f(left, right); 837 if (cmp) 838 break; 839 } 840 841 return cmp; 842 } 843 844 static size_t ipchain__fprintf_graph_line(FILE *fp, int depth, int depth_mask) 845 { 846 int i; 847 size_t ret = 0; 848 849 ret += fprintf(fp, "%s", " "); 850 851 for (i = 0; i < depth; i++) 852 if (depth_mask & (1 << i)) 853 ret += fprintf(fp, "| "); 854 else 855 ret += fprintf(fp, " "); 856 857 ret += fprintf(fp, "\n"); 858 859 return ret; 860 } 861 static size_t 862 ipchain__fprintf_graph(FILE *fp, struct callchain_list *chain, int depth, 863 int depth_mask, int count, u64 total_samples, 864 int hits) 865 { 866 int i; 867 size_t ret = 0; 868 869 ret += fprintf(fp, "%s", " "); 870 for (i = 0; i < depth; i++) { 871 if (depth_mask & (1 << i)) 872 ret += fprintf(fp, "|"); 873 else 874 ret += fprintf(fp, " "); 875 if (!count && i == depth - 1) { 876 double percent; 877 878 percent = hits * 100.0 / total_samples; 879 ret += percent_color_fprintf(fp, "--%2.2f%%-- ", percent); 880 } else 881 ret += fprintf(fp, "%s", " "); 882 } 883 if (chain->sym) 884 ret += fprintf(fp, "%s\n", chain->sym->name); 885 else 886 ret += fprintf(fp, "%p\n", (void *)(long)chain->ip); 887 888 return ret; 889 } 890 891 static size_t 892 callchain__fprintf_graph(FILE *fp, struct callchain_node *self, 893 u64 total_samples, int depth, int depth_mask) 894 { 895 struct rb_node *node, *next; 896 struct callchain_node *child; 897 struct callchain_list *chain; 898 int new_depth_mask = depth_mask; 899 u64 new_total; 900 size_t ret = 0; 901 int i; 902 903 if (callchain_param.mode == CHAIN_GRAPH_REL) 904 new_total = self->cumul_hit; 905 else 906 new_total = total_samples; 907 908 node = rb_first(&self->rb_root); 909 while (node) { 910 child = rb_entry(node, struct callchain_node, rb_node); 911 912 /* 913 * The depth mask manages the output of pipes that show 914 * the depth. We don't want to keep the pipes of the current 915 * level for the last child of this depth 916 */ 917 next = rb_next(node); 918 if (!next) 919 new_depth_mask &= ~(1 << (depth - 1)); 920 921 /* 922 * But we keep the older depth mask for the line seperator 923 * to keep the level link until we reach the last child 924 */ 925 ret += ipchain__fprintf_graph_line(fp, depth, depth_mask); 926 i = 0; 927 list_for_each_entry(chain, &child->val, list) { 928 if (chain->ip >= PERF_CONTEXT_MAX) 929 continue; 930 ret += ipchain__fprintf_graph(fp, chain, depth, 931 new_depth_mask, i++, 932 new_total, 933 child->cumul_hit); 934 } 935 ret += callchain__fprintf_graph(fp, child, new_total, 936 depth + 1, 937 new_depth_mask | (1 << depth)); 938 node = next; 939 } 940 941 return ret; 942 } 943 944 static size_t 945 callchain__fprintf_flat(FILE *fp, struct callchain_node *self, 946 u64 total_samples) 947 { 948 struct callchain_list *chain; 949 size_t ret = 0; 950 951 if (!self) 952 return 0; 953 954 ret += callchain__fprintf_flat(fp, self->parent, total_samples); 955 956 957 list_for_each_entry(chain, &self->val, list) { 958 if (chain->ip >= PERF_CONTEXT_MAX) 959 continue; 960 if (chain->sym) 961 ret += fprintf(fp, " %s\n", chain->sym->name); 962 else 963 ret += fprintf(fp, " %p\n", 964 (void *)(long)chain->ip); 965 } 966 967 return ret; 968 } 969 970 static size_t 971 hist_entry_callchain__fprintf(FILE *fp, struct hist_entry *self, 972 u64 total_samples) 973 { 974 struct rb_node *rb_node; 975 struct callchain_node *chain; 976 size_t ret = 0; 977 978 rb_node = rb_first(&self->sorted_chain); 979 while (rb_node) { 980 double percent; 981 982 chain = rb_entry(rb_node, struct callchain_node, rb_node); 983 percent = chain->hit * 100.0 / total_samples; 984 switch (callchain_param.mode) { 985 case CHAIN_FLAT: 986 ret += percent_color_fprintf(fp, " %6.2f%%\n", 987 percent); 988 ret += callchain__fprintf_flat(fp, chain, total_samples); 989 break; 990 case CHAIN_GRAPH_ABS: /* Falldown */ 991 case CHAIN_GRAPH_REL: 992 ret += callchain__fprintf_graph(fp, chain, 993 total_samples, 1, 1); 994 default: 995 break; 996 } 997 ret += fprintf(fp, "\n"); 998 rb_node = rb_next(rb_node); 999 } 1000 1001 return ret; 1002 } 1003 1004 1005 static size_t 1006 hist_entry__fprintf(FILE *fp, struct hist_entry *self, u64 total_samples) 1007 { 1008 struct sort_entry *se; 1009 size_t ret; 1010 1011 if (exclude_other && !self->parent) 1012 return 0; 1013 1014 if (total_samples) 1015 ret = percent_color_fprintf(fp, 1016 field_sep ? "%.2f" : " %6.2f%%", 1017 (self->count * 100.0) / total_samples); 1018 else 1019 ret = fprintf(fp, field_sep ? "%lld" : "%12lld ", self->count); 1020 1021 if (show_nr_samples) { 1022 if (field_sep) 1023 fprintf(fp, "%c%lld", *field_sep, self->count); 1024 else 1025 fprintf(fp, "%11lld", self->count); 1026 } 1027 1028 list_for_each_entry(se, &hist_entry__sort_list, list) { 1029 if (se->elide) 1030 continue; 1031 1032 fprintf(fp, "%s", field_sep ?: " "); 1033 ret += se->print(fp, self, se->width ? *se->width : 0); 1034 } 1035 1036 ret += fprintf(fp, "\n"); 1037 1038 if (callchain) 1039 hist_entry_callchain__fprintf(fp, self, total_samples); 1040 1041 return ret; 1042 } 1043 1044 /* 1045 * 1046 */ 1047 1048 static void dso__calc_col_width(struct dso *self) 1049 { 1050 if (!col_width_list_str && !field_sep && 1051 (!dso_list || strlist__has_entry(dso_list, self->name))) { 1052 unsigned int slen = strlen(self->name); 1053 if (slen > dsos__col_width) 1054 dsos__col_width = slen; 1055 } 1056 1057 self->slen_calculated = 1; 1058 } 1059 1060 static struct symbol * 1061 resolve_symbol(struct thread *thread, struct map **mapp, 1062 struct dso **dsop, u64 *ipp) 1063 { 1064 struct dso *dso = dsop ? *dsop : NULL; 1065 struct map *map = mapp ? *mapp : NULL; 1066 u64 ip = *ipp; 1067 1068 if (!thread) 1069 return NULL; 1070 1071 if (dso) 1072 goto got_dso; 1073 1074 if (map) 1075 goto got_map; 1076 1077 map = thread__find_map(thread, ip); 1078 if (map != NULL) { 1079 /* 1080 * We have to do this here as we may have a dso 1081 * with no symbol hit that has a name longer than 1082 * the ones with symbols sampled. 1083 */ 1084 if (!sort_dso.elide && !map->dso->slen_calculated) 1085 dso__calc_col_width(map->dso); 1086 1087 if (mapp) 1088 *mapp = map; 1089 got_map: 1090 ip = map->map_ip(map, ip); 1091 1092 dso = map->dso; 1093 } else { 1094 /* 1095 * If this is outside of all known maps, 1096 * and is a negative address, try to look it 1097 * up in the kernel dso, as it might be a 1098 * vsyscall (which executes in user-mode): 1099 */ 1100 if ((long long)ip < 0) 1101 dso = kernel_dso; 1102 } 1103 dprintf(" ...... dso: %s\n", dso ? dso->name : "<not found>"); 1104 dprintf(" ...... map: %Lx -> %Lx\n", *ipp, ip); 1105 *ipp = ip; 1106 1107 if (dsop) 1108 *dsop = dso; 1109 1110 if (!dso) 1111 return NULL; 1112 got_dso: 1113 return dso->find_symbol(dso, ip); 1114 } 1115 1116 static int call__match(struct symbol *sym) 1117 { 1118 if (sym->name && !regexec(&parent_regex, sym->name, 0, NULL, 0)) 1119 return 1; 1120 1121 return 0; 1122 } 1123 1124 static struct symbol ** 1125 resolve_callchain(struct thread *thread, struct map *map __used, 1126 struct ip_callchain *chain, struct hist_entry *entry) 1127 { 1128 u64 context = PERF_CONTEXT_MAX; 1129 struct symbol **syms = NULL; 1130 unsigned int i; 1131 1132 if (callchain) { 1133 syms = calloc(chain->nr, sizeof(*syms)); 1134 if (!syms) { 1135 fprintf(stderr, "Can't allocate memory for symbols\n"); 1136 exit(-1); 1137 } 1138 } 1139 1140 for (i = 0; i < chain->nr; i++) { 1141 u64 ip = chain->ips[i]; 1142 struct dso *dso = NULL; 1143 struct symbol *sym; 1144 1145 if (ip >= PERF_CONTEXT_MAX) { 1146 context = ip; 1147 continue; 1148 } 1149 1150 switch (context) { 1151 case PERF_CONTEXT_HV: 1152 dso = hypervisor_dso; 1153 break; 1154 case PERF_CONTEXT_KERNEL: 1155 dso = kernel_dso; 1156 break; 1157 default: 1158 break; 1159 } 1160 1161 sym = resolve_symbol(thread, NULL, &dso, &ip); 1162 1163 if (sym) { 1164 if (sort__has_parent && call__match(sym) && 1165 !entry->parent) 1166 entry->parent = sym; 1167 if (!callchain) 1168 break; 1169 syms[i] = sym; 1170 } 1171 } 1172 1173 return syms; 1174 } 1175 1176 /* 1177 * collect histogram counts 1178 */ 1179 1180 static int 1181 hist_entry__add(struct thread *thread, struct map *map, struct dso *dso, 1182 struct symbol *sym, u64 ip, struct ip_callchain *chain, 1183 char level, u64 count) 1184 { 1185 struct rb_node **p = &hist.rb_node; 1186 struct rb_node *parent = NULL; 1187 struct hist_entry *he; 1188 struct symbol **syms = NULL; 1189 struct hist_entry entry = { 1190 .thread = thread, 1191 .map = map, 1192 .dso = dso, 1193 .sym = sym, 1194 .ip = ip, 1195 .level = level, 1196 .count = count, 1197 .parent = NULL, 1198 .sorted_chain = RB_ROOT 1199 }; 1200 int cmp; 1201 1202 if ((sort__has_parent || callchain) && chain) 1203 syms = resolve_callchain(thread, map, chain, &entry); 1204 1205 while (*p != NULL) { 1206 parent = *p; 1207 he = rb_entry(parent, struct hist_entry, rb_node); 1208 1209 cmp = hist_entry__cmp(&entry, he); 1210 1211 if (!cmp) { 1212 he->count += count; 1213 if (callchain) { 1214 append_chain(&he->callchain, chain, syms); 1215 free(syms); 1216 } 1217 return 0; 1218 } 1219 1220 if (cmp < 0) 1221 p = &(*p)->rb_left; 1222 else 1223 p = &(*p)->rb_right; 1224 } 1225 1226 he = malloc(sizeof(*he)); 1227 if (!he) 1228 return -ENOMEM; 1229 *he = entry; 1230 if (callchain) { 1231 callchain_init(&he->callchain); 1232 append_chain(&he->callchain, chain, syms); 1233 free(syms); 1234 } 1235 rb_link_node(&he->rb_node, parent, p); 1236 rb_insert_color(&he->rb_node, &hist); 1237 1238 return 0; 1239 } 1240 1241 static void hist_entry__free(struct hist_entry *he) 1242 { 1243 free(he); 1244 } 1245 1246 /* 1247 * collapse the histogram 1248 */ 1249 1250 static struct rb_root collapse_hists; 1251 1252 static void collapse__insert_entry(struct hist_entry *he) 1253 { 1254 struct rb_node **p = &collapse_hists.rb_node; 1255 struct rb_node *parent = NULL; 1256 struct hist_entry *iter; 1257 int64_t cmp; 1258 1259 while (*p != NULL) { 1260 parent = *p; 1261 iter = rb_entry(parent, struct hist_entry, rb_node); 1262 1263 cmp = hist_entry__collapse(iter, he); 1264 1265 if (!cmp) { 1266 iter->count += he->count; 1267 hist_entry__free(he); 1268 return; 1269 } 1270 1271 if (cmp < 0) 1272 p = &(*p)->rb_left; 1273 else 1274 p = &(*p)->rb_right; 1275 } 1276 1277 rb_link_node(&he->rb_node, parent, p); 1278 rb_insert_color(&he->rb_node, &collapse_hists); 1279 } 1280 1281 static void collapse__resort(void) 1282 { 1283 struct rb_node *next; 1284 struct hist_entry *n; 1285 1286 if (!sort__need_collapse) 1287 return; 1288 1289 next = rb_first(&hist); 1290 while (next) { 1291 n = rb_entry(next, struct hist_entry, rb_node); 1292 next = rb_next(&n->rb_node); 1293 1294 rb_erase(&n->rb_node, &hist); 1295 collapse__insert_entry(n); 1296 } 1297 } 1298 1299 /* 1300 * reverse the map, sort on count. 1301 */ 1302 1303 static struct rb_root output_hists; 1304 1305 static void output__insert_entry(struct hist_entry *he, u64 min_callchain_hits) 1306 { 1307 struct rb_node **p = &output_hists.rb_node; 1308 struct rb_node *parent = NULL; 1309 struct hist_entry *iter; 1310 1311 if (callchain) 1312 callchain_param.sort(&he->sorted_chain, &he->callchain, 1313 min_callchain_hits, &callchain_param); 1314 1315 while (*p != NULL) { 1316 parent = *p; 1317 iter = rb_entry(parent, struct hist_entry, rb_node); 1318 1319 if (he->count > iter->count) 1320 p = &(*p)->rb_left; 1321 else 1322 p = &(*p)->rb_right; 1323 } 1324 1325 rb_link_node(&he->rb_node, parent, p); 1326 rb_insert_color(&he->rb_node, &output_hists); 1327 } 1328 1329 static void output__resort(u64 total_samples) 1330 { 1331 struct rb_node *next; 1332 struct hist_entry *n; 1333 struct rb_root *tree = &hist; 1334 u64 min_callchain_hits; 1335 1336 min_callchain_hits = total_samples * (callchain_param.min_percent / 100); 1337 1338 if (sort__need_collapse) 1339 tree = &collapse_hists; 1340 1341 next = rb_first(tree); 1342 1343 while (next) { 1344 n = rb_entry(next, struct hist_entry, rb_node); 1345 next = rb_next(&n->rb_node); 1346 1347 rb_erase(&n->rb_node, tree); 1348 output__insert_entry(n, min_callchain_hits); 1349 } 1350 } 1351 1352 static size_t output__fprintf(FILE *fp, u64 total_samples) 1353 { 1354 struct hist_entry *pos; 1355 struct sort_entry *se; 1356 struct rb_node *nd; 1357 size_t ret = 0; 1358 unsigned int width; 1359 char *col_width = col_width_list_str; 1360 1361 fprintf(fp, "# Samples: %Ld\n", (u64)total_samples); 1362 fprintf(fp, "#\n"); 1363 1364 fprintf(fp, "# Overhead"); 1365 if (show_nr_samples) { 1366 if (field_sep) 1367 fprintf(fp, "%cSamples", *field_sep); 1368 else 1369 fputs(" Samples ", fp); 1370 } 1371 list_for_each_entry(se, &hist_entry__sort_list, list) { 1372 if (se->elide) 1373 continue; 1374 if (field_sep) { 1375 fprintf(fp, "%c%s", *field_sep, se->header); 1376 continue; 1377 } 1378 width = strlen(se->header); 1379 if (se->width) { 1380 if (col_width_list_str) { 1381 if (col_width) { 1382 *se->width = atoi(col_width); 1383 col_width = strchr(col_width, ','); 1384 if (col_width) 1385 ++col_width; 1386 } 1387 } 1388 width = *se->width = max(*se->width, width); 1389 } 1390 fprintf(fp, " %*s", width, se->header); 1391 } 1392 fprintf(fp, "\n"); 1393 1394 if (field_sep) 1395 goto print_entries; 1396 1397 fprintf(fp, "# ........"); 1398 if (show_nr_samples) 1399 fprintf(fp, " .........."); 1400 list_for_each_entry(se, &hist_entry__sort_list, list) { 1401 unsigned int i; 1402 1403 if (se->elide) 1404 continue; 1405 1406 fprintf(fp, " "); 1407 if (se->width) 1408 width = *se->width; 1409 else 1410 width = strlen(se->header); 1411 for (i = 0; i < width; i++) 1412 fprintf(fp, "."); 1413 } 1414 fprintf(fp, "\n"); 1415 1416 fprintf(fp, "#\n"); 1417 1418 print_entries: 1419 for (nd = rb_first(&output_hists); nd; nd = rb_next(nd)) { 1420 pos = rb_entry(nd, struct hist_entry, rb_node); 1421 ret += hist_entry__fprintf(fp, pos, total_samples); 1422 } 1423 1424 if (sort_order == default_sort_order && 1425 parent_pattern == default_parent_pattern) { 1426 fprintf(fp, "#\n"); 1427 fprintf(fp, "# (For a higher level overview, try: perf report --sort comm,dso)\n"); 1428 fprintf(fp, "#\n"); 1429 } 1430 fprintf(fp, "\n"); 1431 1432 return ret; 1433 } 1434 1435 static void register_idle_thread(void) 1436 { 1437 struct thread *thread = threads__findnew(0); 1438 1439 if (thread == NULL || 1440 thread__set_comm(thread, "[idle]")) { 1441 fprintf(stderr, "problem inserting idle task.\n"); 1442 exit(-1); 1443 } 1444 } 1445 1446 static unsigned long total = 0, 1447 total_mmap = 0, 1448 total_comm = 0, 1449 total_fork = 0, 1450 total_unknown = 0, 1451 total_lost = 0; 1452 1453 static int validate_chain(struct ip_callchain *chain, event_t *event) 1454 { 1455 unsigned int chain_size; 1456 1457 chain_size = event->header.size; 1458 chain_size -= (unsigned long)&event->ip.__more_data - (unsigned long)event; 1459 1460 if (chain->nr*sizeof(u64) > chain_size) 1461 return -1; 1462 1463 return 0; 1464 } 1465 1466 static int 1467 process_sample_event(event_t *event, unsigned long offset, unsigned long head) 1468 { 1469 char level; 1470 int show = 0; 1471 struct dso *dso = NULL; 1472 struct thread *thread = threads__findnew(event->ip.pid); 1473 u64 ip = event->ip.ip; 1474 u64 period = 1; 1475 struct map *map = NULL; 1476 void *more_data = event->ip.__more_data; 1477 struct ip_callchain *chain = NULL; 1478 int cpumode; 1479 1480 if (sample_type & PERF_SAMPLE_PERIOD) { 1481 period = *(u64 *)more_data; 1482 more_data += sizeof(u64); 1483 } 1484 1485 dprintf("%p [%p]: PERF_EVENT_SAMPLE (IP, %d): %d: %p period: %Ld\n", 1486 (void *)(offset + head), 1487 (void *)(long)(event->header.size), 1488 event->header.misc, 1489 event->ip.pid, 1490 (void *)(long)ip, 1491 (long long)period); 1492 1493 if (sample_type & PERF_SAMPLE_CALLCHAIN) { 1494 unsigned int i; 1495 1496 chain = (void *)more_data; 1497 1498 dprintf("... chain: nr:%Lu\n", chain->nr); 1499 1500 if (validate_chain(chain, event) < 0) { 1501 eprintf("call-chain problem with event, skipping it.\n"); 1502 return 0; 1503 } 1504 1505 if (dump_trace) { 1506 for (i = 0; i < chain->nr; i++) 1507 dprintf("..... %2d: %016Lx\n", i, chain->ips[i]); 1508 } 1509 } 1510 1511 dprintf(" ... thread: %s:%d\n", thread->comm, thread->pid); 1512 1513 if (thread == NULL) { 1514 eprintf("problem processing %d event, skipping it.\n", 1515 event->header.type); 1516 return -1; 1517 } 1518 1519 if (comm_list && !strlist__has_entry(comm_list, thread->comm)) 1520 return 0; 1521 1522 cpumode = event->header.misc & PERF_EVENT_MISC_CPUMODE_MASK; 1523 1524 if (cpumode == PERF_EVENT_MISC_KERNEL) { 1525 show = SHOW_KERNEL; 1526 level = 'k'; 1527 1528 dso = kernel_dso; 1529 1530 dprintf(" ...... dso: %s\n", dso->name); 1531 1532 } else if (cpumode == PERF_EVENT_MISC_USER) { 1533 1534 show = SHOW_USER; 1535 level = '.'; 1536 1537 } else { 1538 show = SHOW_HV; 1539 level = 'H'; 1540 1541 dso = hypervisor_dso; 1542 1543 dprintf(" ...... dso: [hypervisor]\n"); 1544 } 1545 1546 if (show & show_mask) { 1547 struct symbol *sym = resolve_symbol(thread, &map, &dso, &ip); 1548 1549 if (dso_list && dso && dso->name && !strlist__has_entry(dso_list, dso->name)) 1550 return 0; 1551 1552 if (sym_list && sym && !strlist__has_entry(sym_list, sym->name)) 1553 return 0; 1554 1555 if (hist_entry__add(thread, map, dso, sym, ip, chain, level, period)) { 1556 eprintf("problem incrementing symbol count, skipping event\n"); 1557 return -1; 1558 } 1559 } 1560 total += period; 1561 1562 return 0; 1563 } 1564 1565 static int 1566 process_mmap_event(event_t *event, unsigned long offset, unsigned long head) 1567 { 1568 struct thread *thread = threads__findnew(event->mmap.pid); 1569 struct map *map = map__new(&event->mmap); 1570 1571 dprintf("%p [%p]: PERF_EVENT_MMAP %d: [%p(%p) @ %p]: %s\n", 1572 (void *)(offset + head), 1573 (void *)(long)(event->header.size), 1574 event->mmap.pid, 1575 (void *)(long)event->mmap.start, 1576 (void *)(long)event->mmap.len, 1577 (void *)(long)event->mmap.pgoff, 1578 event->mmap.filename); 1579 1580 if (thread == NULL || map == NULL) { 1581 dprintf("problem processing PERF_EVENT_MMAP, skipping event.\n"); 1582 return 0; 1583 } 1584 1585 thread__insert_map(thread, map); 1586 total_mmap++; 1587 1588 return 0; 1589 } 1590 1591 static int 1592 process_comm_event(event_t *event, unsigned long offset, unsigned long head) 1593 { 1594 struct thread *thread = threads__findnew(event->comm.pid); 1595 1596 dprintf("%p [%p]: PERF_EVENT_COMM: %s:%d\n", 1597 (void *)(offset + head), 1598 (void *)(long)(event->header.size), 1599 event->comm.comm, event->comm.pid); 1600 1601 if (thread == NULL || 1602 thread__set_comm(thread, event->comm.comm)) { 1603 dprintf("problem processing PERF_EVENT_COMM, skipping event.\n"); 1604 return -1; 1605 } 1606 total_comm++; 1607 1608 return 0; 1609 } 1610 1611 static int 1612 process_task_event(event_t *event, unsigned long offset, unsigned long head) 1613 { 1614 struct thread *thread = threads__findnew(event->fork.pid); 1615 struct thread *parent = threads__findnew(event->fork.ppid); 1616 1617 dprintf("%p [%p]: PERF_EVENT_%s: (%d:%d):(%d:%d)\n", 1618 (void *)(offset + head), 1619 (void *)(long)(event->header.size), 1620 event->header.type == PERF_EVENT_FORK ? "FORK" : "EXIT", 1621 event->fork.pid, event->fork.tid, 1622 event->fork.ppid, event->fork.ptid); 1623 1624 /* 1625 * A thread clone will have the same PID for both 1626 * parent and child. 1627 */ 1628 if (thread == parent) 1629 return 0; 1630 1631 if (event->header.type == PERF_EVENT_EXIT) 1632 return 0; 1633 1634 if (!thread || !parent || thread__fork(thread, parent)) { 1635 dprintf("problem processing PERF_EVENT_FORK, skipping event.\n"); 1636 return -1; 1637 } 1638 total_fork++; 1639 1640 return 0; 1641 } 1642 1643 static int 1644 process_lost_event(event_t *event, unsigned long offset, unsigned long head) 1645 { 1646 dprintf("%p [%p]: PERF_EVENT_LOST: id:%Ld: lost:%Ld\n", 1647 (void *)(offset + head), 1648 (void *)(long)(event->header.size), 1649 event->lost.id, 1650 event->lost.lost); 1651 1652 total_lost += event->lost.lost; 1653 1654 return 0; 1655 } 1656 1657 static void trace_event(event_t *event) 1658 { 1659 unsigned char *raw_event = (void *)event; 1660 char *color = PERF_COLOR_BLUE; 1661 int i, j; 1662 1663 if (!dump_trace) 1664 return; 1665 1666 dprintf("."); 1667 cdprintf("\n. ... raw event: size %d bytes\n", event->header.size); 1668 1669 for (i = 0; i < event->header.size; i++) { 1670 if ((i & 15) == 0) { 1671 dprintf("."); 1672 cdprintf(" %04x: ", i); 1673 } 1674 1675 cdprintf(" %02x", raw_event[i]); 1676 1677 if (((i & 15) == 15) || i == event->header.size-1) { 1678 cdprintf(" "); 1679 for (j = 0; j < 15-(i & 15); j++) 1680 cdprintf(" "); 1681 for (j = 0; j < (i & 15); j++) { 1682 if (isprint(raw_event[i-15+j])) 1683 cdprintf("%c", raw_event[i-15+j]); 1684 else 1685 cdprintf("."); 1686 } 1687 cdprintf("\n"); 1688 } 1689 } 1690 dprintf(".\n"); 1691 } 1692 1693 static int 1694 process_read_event(event_t *event, unsigned long offset, unsigned long head) 1695 { 1696 dprintf("%p [%p]: PERF_EVENT_READ: %d %d %Lu\n", 1697 (void *)(offset + head), 1698 (void *)(long)(event->header.size), 1699 event->read.pid, 1700 event->read.tid, 1701 event->read.value); 1702 1703 return 0; 1704 } 1705 1706 static int 1707 process_event(event_t *event, unsigned long offset, unsigned long head) 1708 { 1709 trace_event(event); 1710 1711 switch (event->header.type) { 1712 case PERF_EVENT_SAMPLE: 1713 return process_sample_event(event, offset, head); 1714 1715 case PERF_EVENT_MMAP: 1716 return process_mmap_event(event, offset, head); 1717 1718 case PERF_EVENT_COMM: 1719 return process_comm_event(event, offset, head); 1720 1721 case PERF_EVENT_FORK: 1722 case PERF_EVENT_EXIT: 1723 return process_task_event(event, offset, head); 1724 1725 case PERF_EVENT_LOST: 1726 return process_lost_event(event, offset, head); 1727 1728 case PERF_EVENT_READ: 1729 return process_read_event(event, offset, head); 1730 1731 /* 1732 * We dont process them right now but they are fine: 1733 */ 1734 1735 case PERF_EVENT_THROTTLE: 1736 case PERF_EVENT_UNTHROTTLE: 1737 return 0; 1738 1739 default: 1740 return -1; 1741 } 1742 1743 return 0; 1744 } 1745 1746 static struct perf_header *header; 1747 1748 static u64 perf_header__sample_type(void) 1749 { 1750 u64 sample_type = 0; 1751 int i; 1752 1753 for (i = 0; i < header->attrs; i++) { 1754 struct perf_header_attr *attr = header->attr[i]; 1755 1756 if (!sample_type) 1757 sample_type = attr->attr.sample_type; 1758 else if (sample_type != attr->attr.sample_type) 1759 die("non matching sample_type"); 1760 } 1761 1762 return sample_type; 1763 } 1764 1765 static int __cmd_report(void) 1766 { 1767 int ret, rc = EXIT_FAILURE; 1768 unsigned long offset = 0; 1769 unsigned long head, shift; 1770 struct stat stat; 1771 event_t *event; 1772 uint32_t size; 1773 char *buf; 1774 1775 register_idle_thread(); 1776 1777 input = open(input_name, O_RDONLY); 1778 if (input < 0) { 1779 fprintf(stderr, " failed to open file: %s", input_name); 1780 if (!strcmp(input_name, "perf.data")) 1781 fprintf(stderr, " (try 'perf record' first)"); 1782 fprintf(stderr, "\n"); 1783 exit(-1); 1784 } 1785 1786 ret = fstat(input, &stat); 1787 if (ret < 0) { 1788 perror("failed to stat file"); 1789 exit(-1); 1790 } 1791 1792 if (!stat.st_size) { 1793 fprintf(stderr, "zero-sized file, nothing to do!\n"); 1794 exit(0); 1795 } 1796 1797 header = perf_header__read(input); 1798 head = header->data_offset; 1799 1800 sample_type = perf_header__sample_type(); 1801 1802 if (!(sample_type & PERF_SAMPLE_CALLCHAIN)) { 1803 if (sort__has_parent) { 1804 fprintf(stderr, "selected --sort parent, but no" 1805 " callchain data. Did you call" 1806 " perf record without -g?\n"); 1807 exit(-1); 1808 } 1809 if (callchain) { 1810 fprintf(stderr, "selected -c but no callchain data." 1811 " Did you call perf record without" 1812 " -g?\n"); 1813 exit(-1); 1814 } 1815 } 1816 1817 if (load_kernel() < 0) { 1818 perror("failed to load kernel symbols"); 1819 return EXIT_FAILURE; 1820 } 1821 1822 if (!full_paths) { 1823 if (getcwd(__cwd, sizeof(__cwd)) == NULL) { 1824 perror("failed to get the current directory"); 1825 return EXIT_FAILURE; 1826 } 1827 cwdlen = strlen(cwd); 1828 } else { 1829 cwd = NULL; 1830 cwdlen = 0; 1831 } 1832 1833 shift = page_size * (head / page_size); 1834 offset += shift; 1835 head -= shift; 1836 1837 remap: 1838 buf = (char *)mmap(NULL, page_size * mmap_window, PROT_READ, 1839 MAP_SHARED, input, offset); 1840 if (buf == MAP_FAILED) { 1841 perror("failed to mmap file"); 1842 exit(-1); 1843 } 1844 1845 more: 1846 event = (event_t *)(buf + head); 1847 1848 size = event->header.size; 1849 if (!size) 1850 size = 8; 1851 1852 if (head + event->header.size >= page_size * mmap_window) { 1853 int ret; 1854 1855 shift = page_size * (head / page_size); 1856 1857 ret = munmap(buf, page_size * mmap_window); 1858 assert(ret == 0); 1859 1860 offset += shift; 1861 head -= shift; 1862 goto remap; 1863 } 1864 1865 size = event->header.size; 1866 1867 dprintf("\n%p [%p]: event: %d\n", 1868 (void *)(offset + head), 1869 (void *)(long)event->header.size, 1870 event->header.type); 1871 1872 if (!size || process_event(event, offset, head) < 0) { 1873 1874 dprintf("%p [%p]: skipping unknown header type: %d\n", 1875 (void *)(offset + head), 1876 (void *)(long)(event->header.size), 1877 event->header.type); 1878 1879 total_unknown++; 1880 1881 /* 1882 * assume we lost track of the stream, check alignment, and 1883 * increment a single u64 in the hope to catch on again 'soon'. 1884 */ 1885 1886 if (unlikely(head & 7)) 1887 head &= ~7ULL; 1888 1889 size = 8; 1890 } 1891 1892 head += size; 1893 1894 if (offset + head >= header->data_offset + header->data_size) 1895 goto done; 1896 1897 if (offset + head < (unsigned long)stat.st_size) 1898 goto more; 1899 1900 done: 1901 rc = EXIT_SUCCESS; 1902 close(input); 1903 1904 dprintf(" IP events: %10ld\n", total); 1905 dprintf(" mmap events: %10ld\n", total_mmap); 1906 dprintf(" comm events: %10ld\n", total_comm); 1907 dprintf(" fork events: %10ld\n", total_fork); 1908 dprintf(" lost events: %10ld\n", total_lost); 1909 dprintf(" unknown events: %10ld\n", total_unknown); 1910 1911 if (dump_trace) 1912 return 0; 1913 1914 if (verbose >= 3) 1915 threads__fprintf(stdout); 1916 1917 if (verbose >= 2) 1918 dsos__fprintf(stdout); 1919 1920 collapse__resort(); 1921 output__resort(total); 1922 output__fprintf(stdout, total); 1923 1924 return rc; 1925 } 1926 1927 static int 1928 parse_callchain_opt(const struct option *opt __used, const char *arg, 1929 int unset __used) 1930 { 1931 char *tok; 1932 char *endptr; 1933 1934 callchain = 1; 1935 1936 if (!arg) 1937 return 0; 1938 1939 tok = strtok((char *)arg, ","); 1940 if (!tok) 1941 return -1; 1942 1943 /* get the output mode */ 1944 if (!strncmp(tok, "graph", strlen(arg))) 1945 callchain_param.mode = CHAIN_GRAPH_ABS; 1946 1947 else if (!strncmp(tok, "flat", strlen(arg))) 1948 callchain_param.mode = CHAIN_FLAT; 1949 1950 else if (!strncmp(tok, "fractal", strlen(arg))) 1951 callchain_param.mode = CHAIN_GRAPH_REL; 1952 1953 else 1954 return -1; 1955 1956 /* get the min percentage */ 1957 tok = strtok(NULL, ","); 1958 if (!tok) 1959 goto setup; 1960 1961 callchain_param.min_percent = strtod(tok, &endptr); 1962 if (tok == endptr) 1963 return -1; 1964 1965 setup: 1966 if (register_callchain_param(&callchain_param) < 0) { 1967 fprintf(stderr, "Can't register callchain params\n"); 1968 return -1; 1969 } 1970 return 0; 1971 } 1972 1973 static const char * const report_usage[] = { 1974 "perf report [<options>] <command>", 1975 NULL 1976 }; 1977 1978 static const struct option options[] = { 1979 OPT_STRING('i', "input", &input_name, "file", 1980 "input file name"), 1981 OPT_BOOLEAN('v', "verbose", &verbose, 1982 "be more verbose (show symbol address, etc)"), 1983 OPT_BOOLEAN('D', "dump-raw-trace", &dump_trace, 1984 "dump raw trace in ASCII"), 1985 OPT_STRING('k', "vmlinux", &vmlinux, "file", "vmlinux pathname"), 1986 OPT_BOOLEAN('m', "modules", &modules, 1987 "load module symbols - WARNING: use only with -k and LIVE kernel"), 1988 OPT_BOOLEAN('n', "show-nr-samples", &show_nr_samples, 1989 "Show a column with the number of samples"), 1990 OPT_STRING('s', "sort", &sort_order, "key[,key2...]", 1991 "sort by key(s): pid, comm, dso, symbol, parent"), 1992 OPT_BOOLEAN('P', "full-paths", &full_paths, 1993 "Don't shorten the pathnames taking into account the cwd"), 1994 OPT_STRING('p', "parent", &parent_pattern, "regex", 1995 "regex filter to identify parent, see: '--sort parent'"), 1996 OPT_BOOLEAN('x', "exclude-other", &exclude_other, 1997 "Only display entries with parent-match"), 1998 OPT_CALLBACK_DEFAULT('g', "call-graph", NULL, "output_type,min_percent", 1999 "Display callchains using output_type and min percent threshold. " 2000 "Default: fractal,0.5", &parse_callchain_opt, callchain_default_opt), 2001 OPT_STRING('d', "dsos", &dso_list_str, "dso[,dso...]", 2002 "only consider symbols in these dsos"), 2003 OPT_STRING('C', "comms", &comm_list_str, "comm[,comm...]", 2004 "only consider symbols in these comms"), 2005 OPT_STRING('S', "symbols", &sym_list_str, "symbol[,symbol...]", 2006 "only consider these symbols"), 2007 OPT_STRING('w', "column-widths", &col_width_list_str, 2008 "width[,width...]", 2009 "don't try to adjust column width, use these fixed values"), 2010 OPT_STRING('t', "field-separator", &field_sep, "separator", 2011 "separator for columns, no spaces will be added between " 2012 "columns '.' is reserved."), 2013 OPT_END() 2014 }; 2015 2016 static void setup_sorting(void) 2017 { 2018 char *tmp, *tok, *str = strdup(sort_order); 2019 2020 for (tok = strtok_r(str, ", ", &tmp); 2021 tok; tok = strtok_r(NULL, ", ", &tmp)) { 2022 if (sort_dimension__add(tok) < 0) { 2023 error("Unknown --sort key: `%s'", tok); 2024 usage_with_options(report_usage, options); 2025 } 2026 } 2027 2028 free(str); 2029 } 2030 2031 static void setup_list(struct strlist **list, const char *list_str, 2032 struct sort_entry *se, const char *list_name, 2033 FILE *fp) 2034 { 2035 if (list_str) { 2036 *list = strlist__new(true, list_str); 2037 if (!*list) { 2038 fprintf(stderr, "problems parsing %s list\n", 2039 list_name); 2040 exit(129); 2041 } 2042 if (strlist__nr_entries(*list) == 1) { 2043 fprintf(fp, "# %s: %s\n", list_name, 2044 strlist__entry(*list, 0)->s); 2045 se->elide = true; 2046 } 2047 } 2048 } 2049 2050 int cmd_report(int argc, const char **argv, const char *prefix __used) 2051 { 2052 symbol__init(); 2053 2054 page_size = getpagesize(); 2055 2056 argc = parse_options(argc, argv, options, report_usage, 0); 2057 2058 setup_sorting(); 2059 2060 if (parent_pattern != default_parent_pattern) { 2061 sort_dimension__add("parent"); 2062 sort_parent.elide = 1; 2063 } else 2064 exclude_other = 0; 2065 2066 /* 2067 * Any (unrecognized) arguments left? 2068 */ 2069 if (argc) 2070 usage_with_options(report_usage, options); 2071 2072 setup_pager(); 2073 2074 setup_list(&dso_list, dso_list_str, &sort_dso, "dso", stdout); 2075 setup_list(&comm_list, comm_list_str, &sort_comm, "comm", stdout); 2076 setup_list(&sym_list, sym_list_str, &sort_sym, "symbol", stdout); 2077 2078 if (field_sep && *field_sep == '.') { 2079 fputs("'.' is the only non valid --field-separator argument\n", 2080 stderr); 2081 exit(129); 2082 } 2083 2084 return __cmd_report(); 2085 } 2086