aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf/builtin-report.c
diff options
context:
space:
mode:
Diffstat (limited to 'tools/perf/builtin-report.c')
-rw-r--r--tools/perf/builtin-report.c595
1 files changed, 488 insertions, 107 deletions
diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c
index 5eb5566f0c95..4e5cc266311e 100644
--- a/tools/perf/builtin-report.c
+++ b/tools/perf/builtin-report.c
@@ -10,13 +10,16 @@
10#include "util/util.h" 10#include "util/util.h"
11 11
12#include "util/color.h" 12#include "util/color.h"
13#include "util/list.h" 13#include <linux/list.h>
14#include "util/cache.h" 14#include "util/cache.h"
15#include "util/rbtree.h" 15#include <linux/rbtree.h>
16#include "util/symbol.h" 16#include "util/symbol.h"
17#include "util/string.h" 17#include "util/string.h"
18#include "util/callchain.h"
19#include "util/strlist.h"
18 20
19#include "perf.h" 21#include "perf.h"
22#include "util/header.h"
20 23
21#include "util/parse-options.h" 24#include "util/parse-options.h"
22#include "util/parse-events.h" 25#include "util/parse-events.h"
@@ -30,6 +33,8 @@ static char *vmlinux = NULL;
30 33
31static char default_sort_order[] = "comm,dso"; 34static char default_sort_order[] = "comm,dso";
32static char *sort_order = default_sort_order; 35static char *sort_order = default_sort_order;
36static char *dso_list_str, *comm_list_str, *sym_list_str;
37static struct strlist *dso_list, *comm_list, *sym_list;
33 38
34static int input; 39static int input;
35static int show_mask = SHOW_KERNEL | SHOW_USER | SHOW_HV; 40static int show_mask = SHOW_KERNEL | SHOW_USER | SHOW_HV;
@@ -41,6 +46,8 @@ static int dump_trace = 0;
41static int verbose; 46static int verbose;
42#define eprintf(x...) do { if (verbose) fprintf(stderr, x); } while (0) 47#define eprintf(x...) do { if (verbose) fprintf(stderr, x); } while (0)
43 48
49static int modules;
50
44static int full_paths; 51static int full_paths;
45 52
46static unsigned long page_size; 53static unsigned long page_size;
@@ -52,6 +59,18 @@ static regex_t parent_regex;
52 59
53static int exclude_other = 1; 60static int exclude_other = 1;
54 61
62static char callchain_default_opt[] = "fractal,0.5";
63
64static int callchain;
65
66static
67struct callchain_param callchain_param = {
68 .mode = CHAIN_GRAPH_ABS,
69 .min_percent = 0.5
70};
71
72static u64 sample_type;
73
55struct ip_event { 74struct ip_event {
56 struct perf_event_header header; 75 struct perf_event_header header;
57 u64 ip; 76 u64 ip;
@@ -59,11 +78,6 @@ struct ip_event {
59 unsigned char __more_data[]; 78 unsigned char __more_data[];
60}; 79};
61 80
62struct ip_callchain {
63 u64 nr;
64 u64 ips[0];
65};
66
67struct mmap_event { 81struct mmap_event {
68 struct perf_event_header header; 82 struct perf_event_header header;
69 u32 pid, tid; 83 u32 pid, tid;
@@ -97,6 +111,13 @@ struct lost_event {
97 u64 lost; 111 u64 lost;
98}; 112};
99 113
114struct read_event {
115 struct perf_event_header header;
116 u32 pid,tid;
117 u64 value;
118 u64 format[3];
119};
120
100typedef union event_union { 121typedef union event_union {
101 struct perf_event_header header; 122 struct perf_event_header header;
102 struct ip_event ip; 123 struct ip_event ip;
@@ -105,11 +126,13 @@ typedef union event_union {
105 struct fork_event fork; 126 struct fork_event fork;
106 struct period_event period; 127 struct period_event period;
107 struct lost_event lost; 128 struct lost_event lost;
129 struct read_event read;
108} event_t; 130} event_t;
109 131
110static LIST_HEAD(dsos); 132static LIST_HEAD(dsos);
111static struct dso *kernel_dso; 133static struct dso *kernel_dso;
112static struct dso *vdso; 134static struct dso *vdso;
135static struct dso *hypervisor_dso;
113 136
114static void dsos__add(struct dso *dso) 137static void dsos__add(struct dso *dso)
115{ 138{
@@ -165,7 +188,7 @@ static void dsos__fprintf(FILE *fp)
165 188
166static struct symbol *vdso__find_symbol(struct dso *dso, u64 ip) 189static struct symbol *vdso__find_symbol(struct dso *dso, u64 ip)
167{ 190{
168 return dso__find_symbol(kernel_dso, ip); 191 return dso__find_symbol(dso, ip);
169} 192}
170 193
171static int load_kernel(void) 194static int load_kernel(void)
@@ -176,8 +199,8 @@ static int load_kernel(void)
176 if (!kernel_dso) 199 if (!kernel_dso)
177 return -1; 200 return -1;
178 201
179 err = dso__load_kernel(kernel_dso, vmlinux, NULL, verbose); 202 err = dso__load_kernel(kernel_dso, vmlinux, NULL, verbose, modules);
180 if (err) { 203 if (err <= 0) {
181 dso__delete(kernel_dso); 204 dso__delete(kernel_dso);
182 kernel_dso = NULL; 205 kernel_dso = NULL;
183 } else 206 } else
@@ -191,6 +214,11 @@ static int load_kernel(void)
191 214
192 dsos__add(vdso); 215 dsos__add(vdso);
193 216
217 hypervisor_dso = dso__new("[hypervisor]", 0);
218 if (!hypervisor_dso)
219 return -1;
220 dsos__add(hypervisor_dso);
221
194 return err; 222 return err;
195} 223}
196 224
@@ -222,14 +250,14 @@ static u64 map__map_ip(struct map *map, u64 ip)
222 return ip - map->start + map->pgoff; 250 return ip - map->start + map->pgoff;
223} 251}
224 252
225static u64 vdso__map_ip(struct map *map, u64 ip) 253static u64 vdso__map_ip(struct map *map __used, u64 ip)
226{ 254{
227 return ip; 255 return ip;
228} 256}
229 257
230static inline int is_anon_memory(const char *filename) 258static inline int is_anon_memory(const char *filename)
231{ 259{
232 return strcmp(filename, "//anon") == 0; 260 return strcmp(filename, "//anon") == 0;
233} 261}
234 262
235static struct map *map__new(struct mmap_event *event) 263static struct map *map__new(struct mmap_event *event)
@@ -400,9 +428,27 @@ static void thread__insert_map(struct thread *self, struct map *map)
400 428
401 list_for_each_entry_safe(pos, tmp, &self->maps, node) { 429 list_for_each_entry_safe(pos, tmp, &self->maps, node) {
402 if (map__overlap(pos, map)) { 430 if (map__overlap(pos, map)) {
403 list_del_init(&pos->node); 431 if (verbose >= 2) {
404 /* XXX leaks dsos */ 432 printf("overlapping maps:\n");
405 free(pos); 433 map__fprintf(map, stdout);
434 map__fprintf(pos, stdout);
435 }
436
437 if (map->start <= pos->start && map->end > pos->start)
438 pos->start = map->end;
439
440 if (map->end >= pos->end && map->start < pos->end)
441 pos->end = map->start;
442
443 if (verbose >= 2) {
444 printf("after collision:\n");
445 map__fprintf(pos, stdout);
446 }
447
448 if (pos->start >= pos->end) {
449 list_del_init(&pos->node);
450 free(pos);
451 }
406 } 452 }
407 } 453 }
408 454
@@ -464,17 +510,19 @@ static size_t threads__fprintf(FILE *fp)
464static struct rb_root hist; 510static struct rb_root hist;
465 511
466struct hist_entry { 512struct hist_entry {
467 struct rb_node rb_node; 513 struct rb_node rb_node;
468 514
469 struct thread *thread; 515 struct thread *thread;
470 struct map *map; 516 struct map *map;
471 struct dso *dso; 517 struct dso *dso;
472 struct symbol *sym; 518 struct symbol *sym;
473 struct symbol *parent; 519 struct symbol *parent;
474 u64 ip; 520 u64 ip;
475 char level; 521 char level;
476 522 struct callchain_node callchain;
477 u64 count; 523 struct rb_root sorted_chain;
524
525 u64 count;
478}; 526};
479 527
480/* 528/*
@@ -609,7 +657,11 @@ sort__sym_print(FILE *fp, struct hist_entry *self)
609 657
610 if (self->sym) { 658 if (self->sym) {
611 ret += fprintf(fp, "[%c] %s", 659 ret += fprintf(fp, "[%c] %s",
612 self->dso == kernel_dso ? 'k' : '.', self->sym->name); 660 self->dso == kernel_dso ? 'k' :
661 self->dso == hypervisor_dso ? 'h' : '.', self->sym->name);
662
663 if (self->sym->module)
664 ret += fprintf(fp, "\t[%s]", self->sym->module->name);
613 } else { 665 } else {
614 ret += fprintf(fp, "%#016llx", (u64)self->ip); 666 ret += fprintf(fp, "%#016llx", (u64)self->ip);
615 } 667 }
@@ -674,7 +726,7 @@ static LIST_HEAD(hist_entry__sort_list);
674 726
675static int sort_dimension__add(char *tok) 727static int sort_dimension__add(char *tok)
676{ 728{
677 int i; 729 unsigned int i;
678 730
679 for (i = 0; i < ARRAY_SIZE(sort_dimensions); i++) { 731 for (i = 0; i < ARRAY_SIZE(sort_dimensions); i++) {
680 struct sort_dimension *sd = &sort_dimensions[i]; 732 struct sort_dimension *sd = &sort_dimensions[i];
@@ -744,34 +796,180 @@ hist_entry__collapse(struct hist_entry *left, struct hist_entry *right)
744 return cmp; 796 return cmp;
745} 797}
746 798
799static size_t ipchain__fprintf_graph_line(FILE *fp, int depth, int depth_mask)
800{
801 int i;
802 size_t ret = 0;
803
804 ret += fprintf(fp, "%s", " ");
805
806 for (i = 0; i < depth; i++)
807 if (depth_mask & (1 << i))
808 ret += fprintf(fp, "| ");
809 else
810 ret += fprintf(fp, " ");
811
812 ret += fprintf(fp, "\n");
813
814 return ret;
815}
747static size_t 816static size_t
748hist_entry__fprintf(FILE *fp, struct hist_entry *self, u64 total_samples) 817ipchain__fprintf_graph(FILE *fp, struct callchain_list *chain, int depth,
818 int depth_mask, int count, u64 total_samples,
819 int hits)
749{ 820{
750 struct sort_entry *se; 821 int i;
751 size_t ret; 822 size_t ret = 0;
752 823
753 if (exclude_other && !self->parent) 824 ret += fprintf(fp, "%s", " ");
754 return 0; 825 for (i = 0; i < depth; i++) {
826 if (depth_mask & (1 << i))
827 ret += fprintf(fp, "|");
828 else
829 ret += fprintf(fp, " ");
830 if (!count && i == depth - 1) {
831 double percent;
832
833 percent = hits * 100.0 / total_samples;
834 ret += percent_color_fprintf(fp, "--%2.2f%%-- ", percent);
835 } else
836 ret += fprintf(fp, "%s", " ");
837 }
838 if (chain->sym)
839 ret += fprintf(fp, "%s\n", chain->sym->name);
840 else
841 ret += fprintf(fp, "%p\n", (void *)(long)chain->ip);
842
843 return ret;
844}
845
846static size_t
847callchain__fprintf_graph(FILE *fp, struct callchain_node *self,
848 u64 total_samples, int depth, int depth_mask)
849{
850 struct rb_node *node, *next;
851 struct callchain_node *child;
852 struct callchain_list *chain;
853 int new_depth_mask = depth_mask;
854 u64 new_total;
855 size_t ret = 0;
856 int i;
755 857
756 if (total_samples) { 858 if (callchain_param.mode == CHAIN_GRAPH_REL)
757 double percent = self->count * 100.0 / total_samples; 859 new_total = self->cumul_hit;
758 char *color = PERF_COLOR_NORMAL; 860 else
861 new_total = total_samples;
862
863 node = rb_first(&self->rb_root);
864 while (node) {
865 child = rb_entry(node, struct callchain_node, rb_node);
759 866
760 /* 867 /*
761 * We color high-overhead entries in red, mid-overhead 868 * The depth mask manages the output of pipes that show
762 * entries in green - and keep the low overhead places 869 * the depth. We don't want to keep the pipes of the current
763 * normal: 870 * level for the last child of this depth
764 */ 871 */
765 if (percent >= 5.0) { 872 next = rb_next(node);
766 color = PERF_COLOR_RED; 873 if (!next)
767 } else { 874 new_depth_mask &= ~(1 << (depth - 1));
768 if (percent >= 0.5) 875
769 color = PERF_COLOR_GREEN; 876 /*
877 * But we keep the older depth mask for the line seperator
878 * to keep the level link until we reach the last child
879 */
880 ret += ipchain__fprintf_graph_line(fp, depth, depth_mask);
881 i = 0;
882 list_for_each_entry(chain, &child->val, list) {
883 if (chain->ip >= PERF_CONTEXT_MAX)
884 continue;
885 ret += ipchain__fprintf_graph(fp, chain, depth,
886 new_depth_mask, i++,
887 new_total,
888 child->cumul_hit);
889 }
890 ret += callchain__fprintf_graph(fp, child, new_total,
891 depth + 1,
892 new_depth_mask | (1 << depth));
893 node = next;
894 }
895
896 return ret;
897}
898
899static size_t
900callchain__fprintf_flat(FILE *fp, struct callchain_node *self,
901 u64 total_samples)
902{
903 struct callchain_list *chain;
904 size_t ret = 0;
905
906 if (!self)
907 return 0;
908
909 ret += callchain__fprintf_flat(fp, self->parent, total_samples);
910
911
912 list_for_each_entry(chain, &self->val, list) {
913 if (chain->ip >= PERF_CONTEXT_MAX)
914 continue;
915 if (chain->sym)
916 ret += fprintf(fp, " %s\n", chain->sym->name);
917 else
918 ret += fprintf(fp, " %p\n",
919 (void *)(long)chain->ip);
920 }
921
922 return ret;
923}
924
925static size_t
926hist_entry_callchain__fprintf(FILE *fp, struct hist_entry *self,
927 u64 total_samples)
928{
929 struct rb_node *rb_node;
930 struct callchain_node *chain;
931 size_t ret = 0;
932
933 rb_node = rb_first(&self->sorted_chain);
934 while (rb_node) {
935 double percent;
936
937 chain = rb_entry(rb_node, struct callchain_node, rb_node);
938 percent = chain->hit * 100.0 / total_samples;
939 switch (callchain_param.mode) {
940 case CHAIN_FLAT:
941 ret += percent_color_fprintf(fp, " %6.2f%%\n",
942 percent);
943 ret += callchain__fprintf_flat(fp, chain, total_samples);
944 break;
945 case CHAIN_GRAPH_ABS: /* Falldown */
946 case CHAIN_GRAPH_REL:
947 ret += callchain__fprintf_graph(fp, chain,
948 total_samples, 1, 1);
949 default:
950 break;
770 } 951 }
952 ret += fprintf(fp, "\n");
953 rb_node = rb_next(rb_node);
954 }
955
956 return ret;
957}
958
771 959
772 ret = color_fprintf(fp, color, " %6.2f%%", 960static size_t
961hist_entry__fprintf(FILE *fp, struct hist_entry *self, u64 total_samples)
962{
963 struct sort_entry *se;
964 size_t ret;
965
966 if (exclude_other && !self->parent)
967 return 0;
968
969 if (total_samples)
970 ret = percent_color_fprintf(fp, " %6.2f%%",
773 (self->count * 100.0) / total_samples); 971 (self->count * 100.0) / total_samples);
774 } else 972 else
775 ret = fprintf(fp, "%12Ld ", self->count); 973 ret = fprintf(fp, "%12Ld ", self->count);
776 974
777 list_for_each_entry(se, &hist_entry__sort_list, list) { 975 list_for_each_entry(se, &hist_entry__sort_list, list) {
@@ -784,6 +982,9 @@ hist_entry__fprintf(FILE *fp, struct hist_entry *self, u64 total_samples)
784 982
785 ret += fprintf(fp, "\n"); 983 ret += fprintf(fp, "\n");
786 984
985 if (callchain)
986 hist_entry_callchain__fprintf(fp, self, total_samples);
987
787 return ret; 988 return ret;
788} 989}
789 990
@@ -797,7 +998,7 @@ resolve_symbol(struct thread *thread, struct map **mapp,
797{ 998{
798 struct dso *dso = dsop ? *dsop : NULL; 999 struct dso *dso = dsop ? *dsop : NULL;
799 struct map *map = mapp ? *mapp : NULL; 1000 struct map *map = mapp ? *mapp : NULL;
800 uint64_t ip = *ipp; 1001 u64 ip = *ipp;
801 1002
802 if (!thread) 1003 if (!thread)
803 return NULL; 1004 return NULL;
@@ -814,7 +1015,6 @@ resolve_symbol(struct thread *thread, struct map **mapp,
814 *mapp = map; 1015 *mapp = map;
815got_map: 1016got_map:
816 ip = map->map_ip(map, ip); 1017 ip = map->map_ip(map, ip);
817 *ipp = ip;
818 1018
819 dso = map->dso; 1019 dso = map->dso;
820 } else { 1020 } else {
@@ -828,6 +1028,8 @@ got_map:
828 dso = kernel_dso; 1028 dso = kernel_dso;
829 } 1029 }
830 dprintf(" ...... dso: %s\n", dso ? dso->name : "<not found>"); 1030 dprintf(" ...... dso: %s\n", dso ? dso->name : "<not found>");
1031 dprintf(" ...... map: %Lx -> %Lx\n", *ipp, ip);
1032 *ipp = ip;
831 1033
832 if (dsop) 1034 if (dsop)
833 *dsop = dso; 1035 *dsop = dso;
@@ -846,6 +1048,58 @@ static int call__match(struct symbol *sym)
846 return 0; 1048 return 0;
847} 1049}
848 1050
1051static struct symbol **
1052resolve_callchain(struct thread *thread, struct map *map __used,
1053 struct ip_callchain *chain, struct hist_entry *entry)
1054{
1055 u64 context = PERF_CONTEXT_MAX;
1056 struct symbol **syms = NULL;
1057 unsigned int i;
1058
1059 if (callchain) {
1060 syms = calloc(chain->nr, sizeof(*syms));
1061 if (!syms) {
1062 fprintf(stderr, "Can't allocate memory for symbols\n");
1063 exit(-1);
1064 }
1065 }
1066
1067 for (i = 0; i < chain->nr; i++) {
1068 u64 ip = chain->ips[i];
1069 struct dso *dso = NULL;
1070 struct symbol *sym;
1071
1072 if (ip >= PERF_CONTEXT_MAX) {
1073 context = ip;
1074 continue;
1075 }
1076
1077 switch (context) {
1078 case PERF_CONTEXT_HV:
1079 dso = hypervisor_dso;
1080 break;
1081 case PERF_CONTEXT_KERNEL:
1082 dso = kernel_dso;
1083 break;
1084 default:
1085 break;
1086 }
1087
1088 sym = resolve_symbol(thread, NULL, &dso, &ip);
1089
1090 if (sym) {
1091 if (sort__has_parent && call__match(sym) &&
1092 !entry->parent)
1093 entry->parent = sym;
1094 if (!callchain)
1095 break;
1096 syms[i] = sym;
1097 }
1098 }
1099
1100 return syms;
1101}
1102
849/* 1103/*
850 * collect histogram counts 1104 * collect histogram counts
851 */ 1105 */
@@ -858,6 +1112,7 @@ hist_entry__add(struct thread *thread, struct map *map, struct dso *dso,
858 struct rb_node **p = &hist.rb_node; 1112 struct rb_node **p = &hist.rb_node;
859 struct rb_node *parent = NULL; 1113 struct rb_node *parent = NULL;
860 struct hist_entry *he; 1114 struct hist_entry *he;
1115 struct symbol **syms = NULL;
861 struct hist_entry entry = { 1116 struct hist_entry entry = {
862 .thread = thread, 1117 .thread = thread,
863 .map = map, 1118 .map = map,
@@ -867,39 +1122,12 @@ hist_entry__add(struct thread *thread, struct map *map, struct dso *dso,
867 .level = level, 1122 .level = level,
868 .count = count, 1123 .count = count,
869 .parent = NULL, 1124 .parent = NULL,
1125 .sorted_chain = RB_ROOT
870 }; 1126 };
871 int cmp; 1127 int cmp;
872 1128
873 if (sort__has_parent && chain) { 1129 if ((sort__has_parent || callchain) && chain)
874 u64 context = PERF_CONTEXT_MAX; 1130 syms = resolve_callchain(thread, map, chain, &entry);
875 int i;
876
877 for (i = 0; i < chain->nr; i++) {
878 u64 ip = chain->ips[i];
879 struct dso *dso = NULL;
880 struct symbol *sym;
881
882 if (ip >= PERF_CONTEXT_MAX) {
883 context = ip;
884 continue;
885 }
886
887 switch (context) {
888 case PERF_CONTEXT_KERNEL:
889 dso = kernel_dso;
890 break;
891 default:
892 break;
893 }
894
895 sym = resolve_symbol(thread, NULL, &dso, &ip);
896
897 if (sym && call__match(sym)) {
898 entry.parent = sym;
899 break;
900 }
901 }
902 }
903 1131
904 while (*p != NULL) { 1132 while (*p != NULL) {
905 parent = *p; 1133 parent = *p;
@@ -909,6 +1137,10 @@ hist_entry__add(struct thread *thread, struct map *map, struct dso *dso,
909 1137
910 if (!cmp) { 1138 if (!cmp) {
911 he->count += count; 1139 he->count += count;
1140 if (callchain) {
1141 append_chain(&he->callchain, chain, syms);
1142 free(syms);
1143 }
912 return 0; 1144 return 0;
913 } 1145 }
914 1146
@@ -922,6 +1154,11 @@ hist_entry__add(struct thread *thread, struct map *map, struct dso *dso,
922 if (!he) 1154 if (!he)
923 return -ENOMEM; 1155 return -ENOMEM;
924 *he = entry; 1156 *he = entry;
1157 if (callchain) {
1158 callchain_init(&he->callchain);
1159 append_chain(&he->callchain, chain, syms);
1160 free(syms);
1161 }
925 rb_link_node(&he->rb_node, parent, p); 1162 rb_link_node(&he->rb_node, parent, p);
926 rb_insert_color(&he->rb_node, &hist); 1163 rb_insert_color(&he->rb_node, &hist);
927 1164
@@ -992,12 +1229,16 @@ static void collapse__resort(void)
992 1229
993static struct rb_root output_hists; 1230static struct rb_root output_hists;
994 1231
995static void output__insert_entry(struct hist_entry *he) 1232static void output__insert_entry(struct hist_entry *he, u64 min_callchain_hits)
996{ 1233{
997 struct rb_node **p = &output_hists.rb_node; 1234 struct rb_node **p = &output_hists.rb_node;
998 struct rb_node *parent = NULL; 1235 struct rb_node *parent = NULL;
999 struct hist_entry *iter; 1236 struct hist_entry *iter;
1000 1237
1238 if (callchain)
1239 callchain_param.sort(&he->sorted_chain, &he->callchain,
1240 min_callchain_hits, &callchain_param);
1241
1001 while (*p != NULL) { 1242 while (*p != NULL) {
1002 parent = *p; 1243 parent = *p;
1003 iter = rb_entry(parent, struct hist_entry, rb_node); 1244 iter = rb_entry(parent, struct hist_entry, rb_node);
@@ -1012,11 +1253,14 @@ static void output__insert_entry(struct hist_entry *he)
1012 rb_insert_color(&he->rb_node, &output_hists); 1253 rb_insert_color(&he->rb_node, &output_hists);
1013} 1254}
1014 1255
1015static void output__resort(void) 1256static void output__resort(u64 total_samples)
1016{ 1257{
1017 struct rb_node *next; 1258 struct rb_node *next;
1018 struct hist_entry *n; 1259 struct hist_entry *n;
1019 struct rb_root *tree = &hist; 1260 struct rb_root *tree = &hist;
1261 u64 min_callchain_hits;
1262
1263 min_callchain_hits = total_samples * (callchain_param.min_percent / 100);
1020 1264
1021 if (sort__need_collapse) 1265 if (sort__need_collapse)
1022 tree = &collapse_hists; 1266 tree = &collapse_hists;
@@ -1028,7 +1272,7 @@ static void output__resort(void)
1028 next = rb_next(&n->rb_node); 1272 next = rb_next(&n->rb_node);
1029 1273
1030 rb_erase(&n->rb_node, tree); 1274 rb_erase(&n->rb_node, tree);
1031 output__insert_entry(n); 1275 output__insert_entry(n, min_callchain_hits);
1032 } 1276 }
1033} 1277}
1034 1278
@@ -1054,7 +1298,7 @@ static size_t output__fprintf(FILE *fp, u64 total_samples)
1054 1298
1055 fprintf(fp, "# ........"); 1299 fprintf(fp, "# ........");
1056 list_for_each_entry(se, &hist_entry__sort_list, list) { 1300 list_for_each_entry(se, &hist_entry__sort_list, list) {
1057 int i; 1301 unsigned int i;
1058 1302
1059 if (exclude_other && (se == &sort_parent)) 1303 if (exclude_other && (se == &sort_parent))
1060 continue; 1304 continue;
@@ -1115,7 +1359,7 @@ static int validate_chain(struct ip_callchain *chain, event_t *event)
1115} 1359}
1116 1360
1117static int 1361static int
1118process_overflow_event(event_t *event, unsigned long offset, unsigned long head) 1362process_sample_event(event_t *event, unsigned long offset, unsigned long head)
1119{ 1363{
1120 char level; 1364 char level;
1121 int show = 0; 1365 int show = 0;
@@ -1126,13 +1370,14 @@ process_overflow_event(event_t *event, unsigned long offset, unsigned long head)
1126 struct map *map = NULL; 1370 struct map *map = NULL;
1127 void *more_data = event->ip.__more_data; 1371 void *more_data = event->ip.__more_data;
1128 struct ip_callchain *chain = NULL; 1372 struct ip_callchain *chain = NULL;
1373 int cpumode;
1129 1374
1130 if (event->header.type & PERF_SAMPLE_PERIOD) { 1375 if (sample_type & PERF_SAMPLE_PERIOD) {
1131 period = *(u64 *)more_data; 1376 period = *(u64 *)more_data;
1132 more_data += sizeof(u64); 1377 more_data += sizeof(u64);
1133 } 1378 }
1134 1379
1135 dprintf("%p [%p]: PERF_EVENT (IP, %d): %d: %p period: %Ld\n", 1380 dprintf("%p [%p]: PERF_EVENT_SAMPLE (IP, %d): %d: %p period: %Ld\n",
1136 (void *)(offset + head), 1381 (void *)(offset + head),
1137 (void *)(long)(event->header.size), 1382 (void *)(long)(event->header.size),
1138 event->header.misc, 1383 event->header.misc,
@@ -1140,8 +1385,8 @@ process_overflow_event(event_t *event, unsigned long offset, unsigned long head)
1140 (void *)(long)ip, 1385 (void *)(long)ip,
1141 (long long)period); 1386 (long long)period);
1142 1387
1143 if (event->header.type & PERF_SAMPLE_CALLCHAIN) { 1388 if (sample_type & PERF_SAMPLE_CALLCHAIN) {
1144 int i; 1389 unsigned int i;
1145 1390
1146 chain = (void *)more_data; 1391 chain = (void *)more_data;
1147 1392
@@ -1166,7 +1411,12 @@ process_overflow_event(event_t *event, unsigned long offset, unsigned long head)
1166 return -1; 1411 return -1;
1167 } 1412 }
1168 1413
1169 if (event->header.misc & PERF_EVENT_MISC_KERNEL) { 1414 if (comm_list && !strlist__has_entry(comm_list, thread->comm))
1415 return 0;
1416
1417 cpumode = event->header.misc & PERF_EVENT_MISC_CPUMODE_MASK;
1418
1419 if (cpumode == PERF_EVENT_MISC_KERNEL) {
1170 show = SHOW_KERNEL; 1420 show = SHOW_KERNEL;
1171 level = 'k'; 1421 level = 'k';
1172 1422
@@ -1174,7 +1424,7 @@ process_overflow_event(event_t *event, unsigned long offset, unsigned long head)
1174 1424
1175 dprintf(" ...... dso: %s\n", dso->name); 1425 dprintf(" ...... dso: %s\n", dso->name);
1176 1426
1177 } else if (event->header.misc & PERF_EVENT_MISC_USER) { 1427 } else if (cpumode == PERF_EVENT_MISC_USER) {
1178 1428
1179 show = SHOW_USER; 1429 show = SHOW_USER;
1180 level = '.'; 1430 level = '.';
@@ -1182,12 +1432,21 @@ process_overflow_event(event_t *event, unsigned long offset, unsigned long head)
1182 } else { 1432 } else {
1183 show = SHOW_HV; 1433 show = SHOW_HV;
1184 level = 'H'; 1434 level = 'H';
1435
1436 dso = hypervisor_dso;
1437
1185 dprintf(" ...... dso: [hypervisor]\n"); 1438 dprintf(" ...... dso: [hypervisor]\n");
1186 } 1439 }
1187 1440
1188 if (show & show_mask) { 1441 if (show & show_mask) {
1189 struct symbol *sym = resolve_symbol(thread, &map, &dso, &ip); 1442 struct symbol *sym = resolve_symbol(thread, &map, &dso, &ip);
1190 1443
1444 if (dso_list && dso && dso->name && !strlist__has_entry(dso_list, dso->name))
1445 return 0;
1446
1447 if (sym_list && sym && !strlist__has_entry(sym_list, sym->name))
1448 return 0;
1449
1191 if (hist_entry__add(thread, map, dso, sym, ip, chain, level, period)) { 1450 if (hist_entry__add(thread, map, dso, sym, ip, chain, level, period)) {
1192 eprintf("problem incrementing symbol count, skipping event\n"); 1451 eprintf("problem incrementing symbol count, skipping event\n");
1193 return -1; 1452 return -1;
@@ -1328,14 +1587,27 @@ static void trace_event(event_t *event)
1328} 1587}
1329 1588
1330static int 1589static int
1590process_read_event(event_t *event, unsigned long offset, unsigned long head)
1591{
1592 dprintf("%p [%p]: PERF_EVENT_READ: %d %d %Lu\n",
1593 (void *)(offset + head),
1594 (void *)(long)(event->header.size),
1595 event->read.pid,
1596 event->read.tid,
1597 event->read.value);
1598
1599 return 0;
1600}
1601
1602static int
1331process_event(event_t *event, unsigned long offset, unsigned long head) 1603process_event(event_t *event, unsigned long offset, unsigned long head)
1332{ 1604{
1333 trace_event(event); 1605 trace_event(event);
1334 1606
1335 if (event->header.misc & PERF_EVENT_MISC_OVERFLOW)
1336 return process_overflow_event(event, offset, head);
1337
1338 switch (event->header.type) { 1607 switch (event->header.type) {
1608 case PERF_EVENT_SAMPLE:
1609 return process_sample_event(event, offset, head);
1610
1339 case PERF_EVENT_MMAP: 1611 case PERF_EVENT_MMAP:
1340 return process_mmap_event(event, offset, head); 1612 return process_mmap_event(event, offset, head);
1341 1613
@@ -1351,6 +1623,9 @@ process_event(event_t *event, unsigned long offset, unsigned long head)
1351 case PERF_EVENT_LOST: 1623 case PERF_EVENT_LOST:
1352 return process_lost_event(event, offset, head); 1624 return process_lost_event(event, offset, head);
1353 1625
1626 case PERF_EVENT_READ:
1627 return process_read_event(event, offset, head);
1628
1354 /* 1629 /*
1355 * We dont process them right now but they are fine: 1630 * We dont process them right now but they are fine:
1356 */ 1631 */
@@ -1366,13 +1641,30 @@ process_event(event_t *event, unsigned long offset, unsigned long head)
1366 return 0; 1641 return 0;
1367} 1642}
1368 1643
1369static struct perf_file_header file_header; 1644static struct perf_header *header;
1645
1646static u64 perf_header__sample_type(void)
1647{
1648 u64 sample_type = 0;
1649 int i;
1650
1651 for (i = 0; i < header->attrs; i++) {
1652 struct perf_header_attr *attr = header->attr[i];
1653
1654 if (!sample_type)
1655 sample_type = attr->attr.sample_type;
1656 else if (sample_type != attr->attr.sample_type)
1657 die("non matching sample_type");
1658 }
1659
1660 return sample_type;
1661}
1370 1662
1371static int __cmd_report(void) 1663static int __cmd_report(void)
1372{ 1664{
1373 int ret, rc = EXIT_FAILURE; 1665 int ret, rc = EXIT_FAILURE;
1374 unsigned long offset = 0; 1666 unsigned long offset = 0;
1375 unsigned long head = sizeof(file_header); 1667 unsigned long head, shift;
1376 struct stat stat; 1668 struct stat stat;
1377 event_t *event; 1669 event_t *event;
1378 uint32_t size; 1670 uint32_t size;
@@ -1400,15 +1692,24 @@ static int __cmd_report(void)
1400 exit(0); 1692 exit(0);
1401 } 1693 }
1402 1694
1403 if (read(input, &file_header, sizeof(file_header)) == -1) { 1695 header = perf_header__read(input);
1404 perror("failed to read file headers"); 1696 head = header->data_offset;
1405 exit(-1);
1406 }
1407 1697
1408 if (sort__has_parent && 1698 sample_type = perf_header__sample_type();
1409 !(file_header.sample_type & PERF_SAMPLE_CALLCHAIN)) { 1699
1410 fprintf(stderr, "selected --sort parent, but no callchain data\n"); 1700 if (!(sample_type & PERF_SAMPLE_CALLCHAIN)) {
1411 exit(-1); 1701 if (sort__has_parent) {
1702 fprintf(stderr, "selected --sort parent, but no"
1703 " callchain data. Did you call"
1704 " perf record without -g?\n");
1705 exit(-1);
1706 }
1707 if (callchain) {
1708 fprintf(stderr, "selected -c but no callchain data."
1709 " Did you call perf record without"
1710 " -g?\n");
1711 exit(-1);
1712 }
1412 } 1713 }
1413 1714
1414 if (load_kernel() < 0) { 1715 if (load_kernel() < 0) {
@@ -1426,6 +1727,11 @@ static int __cmd_report(void)
1426 cwd = NULL; 1727 cwd = NULL;
1427 cwdlen = 0; 1728 cwdlen = 0;
1428 } 1729 }
1730
1731 shift = page_size * (head / page_size);
1732 offset += shift;
1733 head -= shift;
1734
1429remap: 1735remap:
1430 buf = (char *)mmap(NULL, page_size * mmap_window, PROT_READ, 1736 buf = (char *)mmap(NULL, page_size * mmap_window, PROT_READ,
1431 MAP_SHARED, input, offset); 1737 MAP_SHARED, input, offset);
@@ -1442,9 +1748,10 @@ more:
1442 size = 8; 1748 size = 8;
1443 1749
1444 if (head + event->header.size >= page_size * mmap_window) { 1750 if (head + event->header.size >= page_size * mmap_window) {
1445 unsigned long shift = page_size * (head / page_size);
1446 int ret; 1751 int ret;
1447 1752
1753 shift = page_size * (head / page_size);
1754
1448 ret = munmap(buf, page_size * mmap_window); 1755 ret = munmap(buf, page_size * mmap_window);
1449 assert(ret == 0); 1756 assert(ret == 0);
1450 1757
@@ -1482,10 +1789,10 @@ more:
1482 1789
1483 head += size; 1790 head += size;
1484 1791
1485 if (offset + head >= sizeof(file_header) + file_header.data_size) 1792 if (offset + head >= header->data_offset + header->data_size)
1486 goto done; 1793 goto done;
1487 1794
1488 if (offset + head < stat.st_size) 1795 if (offset + head < (unsigned long)stat.st_size)
1489 goto more; 1796 goto more;
1490 1797
1491done: 1798done:
@@ -1509,12 +1816,58 @@ done:
1509 dsos__fprintf(stdout); 1816 dsos__fprintf(stdout);
1510 1817
1511 collapse__resort(); 1818 collapse__resort();
1512 output__resort(); 1819 output__resort(total);
1513 output__fprintf(stdout, total); 1820 output__fprintf(stdout, total);
1514 1821
1515 return rc; 1822 return rc;
1516} 1823}
1517 1824
1825static int
1826parse_callchain_opt(const struct option *opt __used, const char *arg,
1827 int unset __used)
1828{
1829 char *tok;
1830 char *endptr;
1831
1832 callchain = 1;
1833
1834 if (!arg)
1835 return 0;
1836
1837 tok = strtok((char *)arg, ",");
1838 if (!tok)
1839 return -1;
1840
1841 /* get the output mode */
1842 if (!strncmp(tok, "graph", strlen(arg)))
1843 callchain_param.mode = CHAIN_GRAPH_ABS;
1844
1845 else if (!strncmp(tok, "flat", strlen(arg)))
1846 callchain_param.mode = CHAIN_FLAT;
1847
1848 else if (!strncmp(tok, "fractal", strlen(arg)))
1849 callchain_param.mode = CHAIN_GRAPH_REL;
1850
1851 else
1852 return -1;
1853
1854 /* get the min percentage */
1855 tok = strtok(NULL, ",");
1856 if (!tok)
1857 goto setup;
1858
1859 callchain_param.min_percent = strtod(tok, &endptr);
1860 if (tok == endptr)
1861 return -1;
1862
1863setup:
1864 if (register_callchain_param(&callchain_param) < 0) {
1865 fprintf(stderr, "Can't register callchain params\n");
1866 return -1;
1867 }
1868 return 0;
1869}
1870
1518static const char * const report_usage[] = { 1871static const char * const report_usage[] = {
1519 "perf report [<options>] <command>", 1872 "perf report [<options>] <command>",
1520 NULL 1873 NULL
@@ -1528,6 +1881,8 @@ static const struct option options[] = {
1528 OPT_BOOLEAN('D', "dump-raw-trace", &dump_trace, 1881 OPT_BOOLEAN('D', "dump-raw-trace", &dump_trace,
1529 "dump raw trace in ASCII"), 1882 "dump raw trace in ASCII"),
1530 OPT_STRING('k', "vmlinux", &vmlinux, "file", "vmlinux pathname"), 1883 OPT_STRING('k', "vmlinux", &vmlinux, "file", "vmlinux pathname"),
1884 OPT_BOOLEAN('m', "modules", &modules,
1885 "load module symbols - WARNING: use only with -k and LIVE kernel"),
1531 OPT_STRING('s', "sort", &sort_order, "key[,key2...]", 1886 OPT_STRING('s', "sort", &sort_order, "key[,key2...]",
1532 "sort by key(s): pid, comm, dso, symbol, parent"), 1887 "sort by key(s): pid, comm, dso, symbol, parent"),
1533 OPT_BOOLEAN('P', "full-paths", &full_paths, 1888 OPT_BOOLEAN('P', "full-paths", &full_paths,
@@ -1536,6 +1891,15 @@ static const struct option options[] = {
1536 "regex filter to identify parent, see: '--sort parent'"), 1891 "regex filter to identify parent, see: '--sort parent'"),
1537 OPT_BOOLEAN('x', "exclude-other", &exclude_other, 1892 OPT_BOOLEAN('x', "exclude-other", &exclude_other,
1538 "Only display entries with parent-match"), 1893 "Only display entries with parent-match"),
1894 OPT_CALLBACK_DEFAULT('c', "callchain", NULL, "output_type,min_percent",
1895 "Display callchains using output_type and min percent threshold. "
1896 "Default: flat,0", &parse_callchain_opt, callchain_default_opt),
1897 OPT_STRING('d', "dsos", &dso_list_str, "dso[,dso...]",
1898 "only consider symbols in these dsos"),
1899 OPT_STRING('C', "comms", &comm_list_str, "comm[,comm...]",
1900 "only consider symbols in these comms"),
1901 OPT_STRING('S', "symbols", &sym_list_str, "symbol[,symbol...]",
1902 "only consider these symbols"),
1539 OPT_END() 1903 OPT_END()
1540}; 1904};
1541 1905
@@ -1554,7 +1918,20 @@ static void setup_sorting(void)
1554 free(str); 1918 free(str);
1555} 1919}
1556 1920
1557int cmd_report(int argc, const char **argv, const char *prefix) 1921static void setup_list(struct strlist **list, const char *list_str,
1922 const char *list_name)
1923{
1924 if (list_str) {
1925 *list = strlist__new(true, list_str);
1926 if (!*list) {
1927 fprintf(stderr, "problems parsing %s list\n",
1928 list_name);
1929 exit(129);
1930 }
1931 }
1932}
1933
1934int cmd_report(int argc, const char **argv, const char *prefix __used)
1558{ 1935{
1559 symbol__init(); 1936 symbol__init();
1560 1937
@@ -1575,6 +1952,10 @@ int cmd_report(int argc, const char **argv, const char *prefix)
1575 if (argc) 1952 if (argc)
1576 usage_with_options(report_usage, options); 1953 usage_with_options(report_usage, options);
1577 1954
1955 setup_list(&dso_list, dso_list_str, "dso");
1956 setup_list(&comm_list, comm_list_str, "comm");
1957 setup_list(&sym_list, sym_list_str, "symbol");
1958
1578 setup_pager(); 1959 setup_pager();
1579 1960
1580 return __cmd_report(); 1961 return __cmd_report();