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