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