9 #include "util/cache.h"
10 #include "util/rbtree.h"
14 #include "util/parse-options.h"
15 #include "util/parse-events.h"
21 static char const *input_name = "perf.data";
22 static char *vmlinux = NULL;
24 static int show_mask = SHOW_KERNEL | SHOW_USER | SHOW_HV;
26 static int dump_trace = 0;
29 static unsigned long page_size;
30 static unsigned long mmap_window = 32;
32 const char *perf_event_names[] = {
33 [PERF_EVENT_MMAP] = " PERF_EVENT_MMAP",
34 [PERF_EVENT_MUNMAP] = " PERF_EVENT_MUNMAP",
35 [PERF_EVENT_COMM] = " PERF_EVENT_COMM",
39 struct perf_event_header header;
44 struct perf_event_header header;
49 char filename[PATH_MAX];
52 struct perf_event_header header;
57 typedef union event_union {
58 struct perf_event_header header;
60 struct mmap_event mmap;
61 struct comm_event comm;
65 struct rb_node rb_node;
71 static struct symbol *symbol__new(uint64_t start, uint64_t len, const char *name)
73 struct symbol *self = malloc(sizeof(*self) + strlen(name) + 1);
77 self->end = start + len;
78 strcpy(self->name, name);
84 static void symbol__delete(struct symbol *self)
89 static size_t symbol__fprintf(struct symbol *self, FILE *fp)
91 return fprintf(fp, " %llx-%llx %s\n",
92 self->start, self->end, self->name);
96 struct list_head node;
101 static struct dso *dso__new(const char *name)
103 struct dso *self = malloc(sizeof(*self) + strlen(name) + 1);
106 strcpy(self->name, name);
107 self->syms = RB_ROOT;
113 static void dso__delete_symbols(struct dso *self)
116 struct rb_node *next = rb_first(&self->syms);
119 pos = rb_entry(next, struct symbol, rb_node);
120 next = rb_next(&pos->rb_node);
125 static void dso__delete(struct dso *self)
127 dso__delete_symbols(self);
131 static void dso__insert_symbol(struct dso *self, struct symbol *sym)
133 struct rb_node **p = &self->syms.rb_node;
134 struct rb_node *parent = NULL;
135 const uint64_t ip = sym->start;
140 s = rb_entry(parent, struct symbol, rb_node);
146 rb_link_node(&sym->rb_node, parent, p);
147 rb_insert_color(&sym->rb_node, &self->syms);
150 static struct symbol *dso__find_symbol(struct dso *self, uint64_t ip)
157 n = self->syms.rb_node;
160 struct symbol *s = rb_entry(n, struct symbol, rb_node);
164 else if (ip > s->end)
174 * elf_symtab__for_each_symbol - iterate thru all the symbols
176 * @self: struct elf_symtab instance to iterate
177 * @index: uint32_t index
178 * @sym: GElf_Sym iterator
180 #define elf_symtab__for_each_symbol(syms, nr_syms, index, sym) \
181 for (index = 0, gelf_getsym(syms, index, &sym);\
183 index++, gelf_getsym(syms, index, &sym))
185 static inline uint8_t elf_sym__type(const GElf_Sym *sym)
187 return GELF_ST_TYPE(sym->st_info);
190 static inline int elf_sym__is_function(const GElf_Sym *sym)
192 return elf_sym__type(sym) == STT_FUNC &&
194 sym->st_shndx != SHN_UNDEF &&
198 static inline const char *elf_sym__name(const GElf_Sym *sym,
199 const Elf_Data *symstrs)
201 return symstrs->d_buf + sym->st_name;
204 static Elf_Scn *elf_section_by_name(Elf *elf, GElf_Ehdr *ep,
205 GElf_Shdr *shp, const char *name,
211 while ((sec = elf_nextscn(elf, sec)) != NULL) {
214 gelf_getshdr(sec, shp);
215 str = elf_strptr(elf, ep->e_shstrndx, shp->sh_name);
216 if (!strcmp(name, str)) {
227 static int dso__load_sym(struct dso *self, int fd, char *name)
241 elf = elf_begin(fd, ELF_C_READ_MMAP, NULL);
243 fprintf(stderr, "%s: cannot read %s ELF file.\n",
248 if (gelf_getehdr(elf, &ehdr) == NULL) {
249 fprintf(stderr, "%s: cannot get elf header.\n", __func__);
253 sec = elf_section_by_name(elf, &ehdr, &shdr, ".symtab", NULL);
255 sec = elf_section_by_name(elf, &ehdr, &shdr, ".dynsym", NULL);
260 syms = elf_getdata(sec, NULL);
264 sec = elf_getscn(elf, shdr.sh_link);
268 symstrs = elf_getdata(sec, NULL);
272 nr_syms = shdr.sh_size / shdr.sh_entsize;
274 elf_symtab__for_each_symbol(syms, nr_syms, index, sym) {
277 if (!elf_sym__is_function(&sym))
280 sec = elf_getscn(elf, sym.st_shndx);
284 gelf_getshdr(sec, &shdr);
285 sym.st_value -= shdr.sh_addr - shdr.sh_offset;
287 f = symbol__new(sym.st_value, sym.st_size,
288 elf_sym__name(&sym, symstrs));
292 dso__insert_symbol(self, f);
304 static int dso__load(struct dso *self)
306 int size = strlen(self->name) + sizeof("/usr/lib/debug%s.debug");
307 char *name = malloc(size);
319 snprintf(name, size, "/usr/lib/debug%s.debug", self->name);
322 snprintf(name, size, "/usr/lib/debug%s", self->name);
324 case 2: /* Sane people */
325 snprintf(name, size, "%s", self->name);
333 fd = open(name, O_RDONLY);
336 ret = dso__load_sym(self, fd, name);
340 * Some people seem to have debuginfo files _WITHOUT_ debug info!?!?
350 static size_t dso__fprintf(struct dso *self, FILE *fp)
352 size_t ret = fprintf(fp, "dso: %s\n", self->name);
355 for (nd = rb_first(&self->syms); nd; nd = rb_next(nd)) {
356 struct symbol *pos = rb_entry(nd, struct symbol, rb_node);
357 ret += symbol__fprintf(pos, fp);
363 static LIST_HEAD(dsos);
364 static struct dso *kernel_dso;
366 static void dsos__add(struct dso *dso)
368 list_add_tail(&dso->node, &dsos);
371 static struct dso *dsos__find(const char *name)
375 list_for_each_entry(pos, &dsos, node)
376 if (strcmp(pos->name, name) == 0)
381 static struct dso *dsos__findnew(const char *name)
383 struct dso *dso = dsos__find(name);
387 dso = dso__new(name);
393 fprintf(stderr, "Failed to open: %s\n", name);
398 "Failed to find debug symbols for: %s, maybe install a debug package?\n",
412 static void dsos__fprintf(FILE *fp)
416 list_for_each_entry(pos, &dsos, node)
417 dso__fprintf(pos, fp);
420 static int hex(char ch)
422 if ((ch >= '0') && (ch <= '9'))
424 if ((ch >= 'a') && (ch <= 'f'))
425 return ch - 'a' + 10;
426 if ((ch >= 'A') && (ch <= 'F'))
427 return ch - 'A' + 10;
432 * While we find nice hex chars, build a long_val.
433 * Return number of chars processed.
435 static int hex2long(char *ptr, unsigned long *long_val)
441 const int hex_val = hex(*p);
446 *long_val = (*long_val << 4) | hex_val;
453 static int load_kallsyms(void)
455 struct rb_node *nd, *prevnd;
460 kernel_dso = dso__new("[kernel]");
461 if (kernel_dso == NULL)
464 file = fopen("/proc/kallsyms", "r");
468 while (!feof(file)) {
474 line_len = getline(&line, &n, file);
481 line[--line_len] = '\0'; /* \n */
483 len = hex2long(line, &start);
486 if (len + 2 >= line_len)
489 symbol_type = toupper(line[len]);
491 * We're interested only in code ('T'ext)
493 if (symbol_type != 'T' && symbol_type != 'W')
496 * Well fix up the end later, when we have all sorted.
498 sym = symbol__new(start, 0xdead, line + len + 2);
503 dso__insert_symbol(kernel_dso, sym);
507 * Now that we have all sorted out, just set the ->end of all
510 prevnd = rb_first(&kernel_dso->syms);
513 goto out_delete_line;
515 for (nd = rb_next(prevnd); nd; nd = rb_next(nd)) {
516 struct symbol *prev = rb_entry(prevnd, struct symbol, rb_node),
517 *curr = rb_entry(nd, struct symbol, rb_node);
519 prev->end = curr->start - 1;
523 dsos__add(kernel_dso);
532 dso__delete(kernel_dso);
536 static int load_kernel(void)
543 fd = open(vmlinux, O_RDONLY);
547 kernel_dso = dso__new("[kernel]");
551 nr = dso__load_sym(kernel_dso, fd, vmlinux);
556 dsos__add(kernel_dso);
562 dso__delete(kernel_dso);
566 return load_kallsyms();
570 struct list_head node;
577 static struct map *map__new(struct mmap_event *event)
579 struct map *self = malloc(sizeof(*self));
582 self->start = event->start;
583 self->end = event->start + event->len;
584 self->pgoff = event->pgoff;
586 self->dso = dsos__findnew(event->filename);
587 if (self->dso == NULL)
598 static const char *thread__name(struct thread *self, char *bf, size_t size);
601 struct rb_node rb_node;
602 struct list_head maps;
607 static const char *thread__name(struct thread *self, char *bf, size_t size)
612 snprintf(bf, sizeof(bf), ":%u", self->pid);
616 static struct thread *thread__new(pid_t pid)
618 struct thread *self = malloc(sizeof(*self));
623 INIT_LIST_HEAD(&self->maps);
629 static int thread__set_comm(struct thread *self, const char *comm)
631 self->comm = strdup(comm);
632 return self->comm ? 0 : -ENOMEM;
635 static struct rb_root threads;
637 static struct thread *threads__findnew(pid_t pid)
639 struct rb_node **p = &threads.rb_node;
640 struct rb_node *parent = NULL;
645 th = rb_entry(parent, struct thread, rb_node);
656 th = thread__new(pid);
658 rb_link_node(&th->rb_node, parent, p);
659 rb_insert_color(&th->rb_node, &threads);
664 static void thread__insert_map(struct thread *self, struct map *map)
666 list_add_tail(&map->node, &self->maps);
669 static struct map *thread__find_map(struct thread *self, uint64_t ip)
676 list_for_each_entry(pos, &self->maps, node)
677 if (ip >= pos->start && ip <= pos->end)
684 * histogram, sorted on item, collects counts
687 static struct rb_root hist;
690 struct rb_node rb_node;
692 struct thread *thread;
703 * configurable sorting bits
707 struct list_head list;
709 int64_t (*cmp)(struct hist_entry *, struct hist_entry *);
710 size_t (*print)(FILE *fp, struct hist_entry *);
714 sort__thread_cmp(struct hist_entry *left, struct hist_entry *right)
716 return right->thread->pid - left->thread->pid;
720 sort__thread_print(FILE *fp, struct hist_entry *self)
724 return fprintf(fp, "%14s ",
725 thread__name(self->thread, bf, sizeof(bf)));
728 static struct sort_entry sort_thread = {
729 .cmp = sort__thread_cmp,
730 .print = sort__thread_print,
734 sort__sym_cmp(struct hist_entry *left, struct hist_entry *right)
738 if (left->sym == right->sym)
741 ip_l = left->sym ? left->sym->start : left->ip;
742 ip_r = right->sym ? right->sym->start : right->ip;
744 return (int64_t)(ip_r - ip_l);
748 sort__sym_print(FILE *fp, struct hist_entry *self)
752 ret += fprintf(fp, "[%c] ", self->level);
755 ret += fprintf(fp, "%#018llx ", (unsigned long long)self->ip);
757 if (self->level != '.')
758 ret += fprintf(fp, "%s ",
759 self->sym ? self->sym->name : "<unknown>");
761 ret += fprintf(fp, "%s: %s ",
762 self->dso ? self->dso->name : "<unknown>",
763 self->sym ? self->sym->name : "<unknown>");
768 static struct sort_entry sort_sym = {
769 .cmp = sort__sym_cmp,
770 .print = sort__sym_print,
773 static LIST_HEAD(hist_entry__sort_list);
775 static void setup_sorting(void)
777 list_add_tail(&sort_thread.list, &hist_entry__sort_list);
778 list_add_tail(&sort_sym.list, &hist_entry__sort_list);
782 hist_entry__cmp(struct hist_entry *left, struct hist_entry *right)
784 struct sort_entry *se;
787 list_for_each_entry(se, &hist_entry__sort_list, list) {
788 cmp = se->cmp(left, right);
797 hist_entry__fprintf(FILE *fp, struct hist_entry *self, uint64_t total_samples)
799 struct sort_entry *se;
803 ret = fprintf(fp, "%5.2f%% ",
804 (self->count * 100.0) / total_samples);
806 ret = fprintf(fp, "%12d ", self->count);
808 list_for_each_entry(se, &hist_entry__sort_list, list)
809 ret += se->print(fp, self);
811 ret += fprintf(fp, "\n");
817 * collect histogram counts
821 hist_entry__add(struct thread *thread, struct map *map, struct dso *dso,
822 struct symbol *sym, uint64_t ip, char level)
824 struct rb_node **p = &hist.rb_node;
825 struct rb_node *parent = NULL;
826 struct hist_entry *he;
827 struct hist_entry entry = {
840 he = rb_entry(parent, struct hist_entry, rb_node);
842 cmp = hist_entry__cmp(&entry, he);
855 he = malloc(sizeof(*he));
859 rb_link_node(&he->rb_node, parent, p);
860 rb_insert_color(&he->rb_node, &hist);
866 * reverse the map, sort on count.
869 static struct rb_root output_hists;
871 static void output__insert_entry(struct hist_entry *he)
873 struct rb_node **p = &output_hists.rb_node;
874 struct rb_node *parent = NULL;
875 struct hist_entry *iter;
879 iter = rb_entry(parent, struct hist_entry, rb_node);
881 if (he->count > iter->count)
887 rb_link_node(&he->rb_node, parent, p);
888 rb_insert_color(&he->rb_node, &output_hists);
891 static void output__resort(void)
893 struct rb_node *next = rb_first(&hist);
894 struct hist_entry *n;
897 n = rb_entry(next, struct hist_entry, rb_node);
898 next = rb_next(&n->rb_node);
900 rb_erase(&n->rb_node, &hist);
901 output__insert_entry(n);
905 static size_t output__fprintf(FILE *fp, uint64_t total_samples)
907 struct hist_entry *pos;
911 for (nd = rb_first(&output_hists); nd; nd = rb_next(nd)) {
912 pos = rb_entry(nd, struct hist_entry, rb_node);
913 ret += hist_entry__fprintf(fp, pos, total_samples);
920 static int __cmd_report(void)
922 unsigned long offset = 0;
923 unsigned long head = 0;
927 int ret, rc = EXIT_FAILURE;
929 unsigned long total = 0, total_mmap = 0, total_comm = 0, total_unknown = 0;
931 input = open(input_name, O_RDONLY);
933 perror("failed to open file");
937 ret = fstat(input, &stat);
939 perror("failed to stat file");
944 fprintf(stderr, "zero-sized file, nothing to do!\n");
948 if (load_kernel() < 0) {
949 perror("failed to open kallsyms");
954 buf = (char *)mmap(NULL, page_size * mmap_window, PROT_READ,
955 MAP_SHARED, input, offset);
956 if (buf == MAP_FAILED) {
957 perror("failed to mmap file");
962 event = (event_t *)(buf + head);
964 size = event->header.size;
968 if (head + event->header.size >= page_size * mmap_window) {
969 unsigned long shift = page_size * (head / page_size);
972 ret = munmap(buf, page_size * mmap_window);
980 size = event->header.size;
984 if (event->header.misc & PERF_EVENT_MISC_OVERFLOW) {
987 struct dso *dso = NULL;
988 struct thread *thread = threads__findnew(event->ip.pid);
989 uint64_t ip = event->ip.ip;
990 struct map *map = NULL;
993 fprintf(stderr, "%p [%p]: PERF_EVENT (IP, %d): %d: %p\n",
994 (void *)(offset + head),
995 (void *)(long)(event->header.size),
1001 if (thread == NULL) {
1002 fprintf(stderr, "problem processing %d event, bailing out\n",
1003 event->header.type);
1007 if (event->header.misc & PERF_EVENT_MISC_KERNEL) {
1013 } else if (event->header.misc & PERF_EVENT_MISC_USER) {
1018 map = thread__find_map(thread, ip);
1021 ip -= map->start + map->pgoff;
1029 if (show & show_mask) {
1030 struct symbol *sym = dso__find_symbol(dso, ip);
1032 if (hist_entry__add(thread, map, dso, sym, ip, level)) {
1034 "problem incrementing symbol count, bailing out\n");
1039 } else switch (event->header.type) {
1040 case PERF_EVENT_MMAP: {
1041 struct thread *thread = threads__findnew(event->mmap.pid);
1042 struct map *map = map__new(&event->mmap);
1045 fprintf(stderr, "%p [%p]: PERF_EVENT_MMAP: [%p(%p) @ %p]: %s\n",
1046 (void *)(offset + head),
1047 (void *)(long)(event->header.size),
1048 (void *)(long)event->mmap.start,
1049 (void *)(long)event->mmap.len,
1050 (void *)(long)event->mmap.pgoff,
1051 event->mmap.filename);
1053 if (thread == NULL || map == NULL) {
1054 fprintf(stderr, "problem processing PERF_EVENT_MMAP, bailing out\n");
1057 thread__insert_map(thread, map);
1061 case PERF_EVENT_COMM: {
1062 struct thread *thread = threads__findnew(event->comm.pid);
1065 fprintf(stderr, "%p [%p]: PERF_EVENT_COMM: %s:%d\n",
1066 (void *)(offset + head),
1067 (void *)(long)(event->header.size),
1068 event->comm.comm, event->comm.pid);
1070 if (thread == NULL ||
1071 thread__set_comm(thread, event->comm.comm)) {
1072 fprintf(stderr, "problem processing PERF_EVENT_COMM, bailing out\n");
1081 fprintf(stderr, "%p [%p]: skipping unknown header type: %d\n",
1082 (void *)(offset + head),
1083 (void *)(long)(event->header.size),
1084 event->header.type);
1089 * assume we lost track of the stream, check alignment, and
1090 * increment a single u64 in the hope to catch on again 'soon'.
1093 if (unlikely(head & 7))
1102 if (offset + head < stat.st_size)
1110 fprintf(stderr, " IP events: %10ld\n", total);
1111 fprintf(stderr, " mmap events: %10ld\n", total_mmap);
1112 fprintf(stderr, " comm events: %10ld\n", total_comm);
1113 fprintf(stderr, " unknown events: %10ld\n", total_unknown);
1119 dsos__fprintf(stdout);
1122 output__fprintf(stdout, total);
1127 static const char * const report_usage[] = {
1128 "perf report [<options>] <command>",
1132 static const struct option options[] = {
1133 OPT_STRING('i', "input", &input_name, "file",
1135 OPT_BOOLEAN('v', "verbose", &verbose,
1136 "be more verbose (show symbol address, etc)"),
1137 OPT_BOOLEAN('D', "dump-raw-trace", &dump_trace,
1138 "dump raw trace in ASCII"),
1139 OPT_STRING('k', "vmlinux", &vmlinux, "file", "vmlinux pathname"),
1143 int cmd_report(int argc, const char **argv, const char *prefix)
1145 elf_version(EV_CURRENT);
1147 page_size = getpagesize();
1149 parse_options(argc, argv, options, report_usage, 0);
1155 return __cmd_report();