aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--tools/perf/builtin-report.c86
1 files changed, 39 insertions, 47 deletions
diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c
index 86981bd08f65..7a6577bf9a41 100644
--- a/tools/perf/builtin-report.c
+++ b/tools/perf/builtin-report.c
@@ -59,6 +59,11 @@ struct ip_event {
59 unsigned char __more_data[]; 59 unsigned char __more_data[];
60}; 60};
61 61
62struct ip_callchain {
63 __u64 nr;
64 __u64 ips[0];
65};
66
62struct mmap_event { 67struct mmap_event {
63 struct perf_event_header header; 68 struct perf_event_header header;
64 __u32 pid, tid; 69 __u32 pid, tid;
@@ -833,15 +838,12 @@ got_dso:
833 return dso->find_symbol(dso, ip); 838 return dso->find_symbol(dso, ip);
834} 839}
835 840
836static struct symbol *call__match(struct symbol *sym) 841static int call__match(struct symbol *sym)
837{ 842{
838 if (!sym)
839 return NULL;
840
841 if (sym->name && !regexec(&parent_regex, sym->name, 0, NULL, 0)) 843 if (sym->name && !regexec(&parent_regex, sym->name, 0, NULL, 0))
842 return sym; 844 return 1;
843 845
844 return NULL; 846 return 0;
845} 847}
846 848
847/* 849/*
@@ -850,7 +852,7 @@ static struct symbol *call__match(struct symbol *sym)
850 852
851static int 853static int
852hist_entry__add(struct thread *thread, struct map *map, struct dso *dso, 854hist_entry__add(struct thread *thread, struct map *map, struct dso *dso,
853 struct symbol *sym, __u64 ip, struct perf_callchain_entry *chain, 855 struct symbol *sym, __u64 ip, struct ip_callchain *chain,
854 char level, __u64 count) 856 char level, __u64 count)
855{ 857{
856 struct rb_node **p = &hist.rb_node; 858 struct rb_node **p = &hist.rb_node;
@@ -869,31 +871,35 @@ hist_entry__add(struct thread *thread, struct map *map, struct dso *dso,
869 int cmp; 871 int cmp;
870 872
871 if (sort__has_parent && chain) { 873 if (sort__has_parent && chain) {
872 int i, nr = chain->hv; 874 __u64 context = PERF_CONTEXT_MAX;
873 struct symbol *sym; 875 int i;
874 struct dso *dso; 876
875 __u64 ip; 877 for (i = 0; i < chain->nr; i++) {
876 878 __u64 ip = chain->ips[i];
877 for (i = 0; i < chain->kernel; i++) { 879 struct dso *dso = NULL;
878 ip = chain->ip[nr + i]; 880 struct symbol *sym;
879 dso = kernel_dso; 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
880 sym = resolve_symbol(thread, NULL, &dso, &ip); 895 sym = resolve_symbol(thread, NULL, &dso, &ip);
881 entry.parent = call__match(sym); 896
882 if (entry.parent) 897 if (sym && call__match(sym)) {
883 goto got_parent; 898 entry.parent = sym;
884 } 899 break;
885 nr += i; 900 }
886
887 for (i = 0; i < chain->user; i++) {
888 ip = chain->ip[nr + i];
889 sym = resolve_symbol(thread, NULL, NULL, &ip);
890 entry.parent = call__match(sym);
891 if (entry.parent)
892 goto got_parent;
893 } 901 }
894 nr += i;
895 } 902 }
896got_parent:
897 903
898 while (*p != NULL) { 904 while (*p != NULL) {
899 parent = *p; 905 parent = *p;
@@ -1095,21 +1101,10 @@ static unsigned long total = 0,
1095 total_unknown = 0, 1101 total_unknown = 0,
1096 total_lost = 0; 1102 total_lost = 0;
1097 1103
1098static int validate_chain(struct perf_callchain_entry *chain, event_t *event) 1104static int validate_chain(struct ip_callchain *chain, event_t *event)
1099{ 1105{
1100 unsigned int chain_size; 1106 unsigned int chain_size;
1101 1107
1102 if (chain->nr > MAX_STACK_DEPTH)
1103 return -1;
1104 if (chain->hv > MAX_STACK_DEPTH)
1105 return -1;
1106 if (chain->kernel > MAX_STACK_DEPTH)
1107 return -1;
1108 if (chain->user > MAX_STACK_DEPTH)
1109 return -1;
1110 if (chain->hv + chain->kernel + chain->user != chain->nr)
1111 return -1;
1112
1113 chain_size = event->header.size; 1108 chain_size = event->header.size;
1114 chain_size -= (unsigned long)&event->ip.__more_data - (unsigned long)event; 1109 chain_size -= (unsigned long)&event->ip.__more_data - (unsigned long)event;
1115 1110
@@ -1130,7 +1125,7 @@ process_overflow_event(event_t *event, unsigned long offset, unsigned long head)
1130 __u64 period = 1; 1125 __u64 period = 1;
1131 struct map *map = NULL; 1126 struct map *map = NULL;
1132 void *more_data = event->ip.__more_data; 1127 void *more_data = event->ip.__more_data;
1133 struct perf_callchain_entry *chain = NULL; 1128 struct ip_callchain *chain = NULL;
1134 1129
1135 if (event->header.type & PERF_SAMPLE_PERIOD) { 1130 if (event->header.type & PERF_SAMPLE_PERIOD) {
1136 period = *(__u64 *)more_data; 1131 period = *(__u64 *)more_data;
@@ -1150,10 +1145,7 @@ process_overflow_event(event_t *event, unsigned long offset, unsigned long head)
1150 1145
1151 chain = (void *)more_data; 1146 chain = (void *)more_data;
1152 1147
1153 dprintf("... chain: u:%d, k:%d, nr:%d\n", 1148 dprintf("... chain: nr:%Lu\n", chain->nr);
1154 chain->user,
1155 chain->kernel,
1156 chain->nr);
1157 1149
1158 if (validate_chain(chain, event) < 0) { 1150 if (validate_chain(chain, event) < 0) {
1159 eprintf("call-chain problem with event, skipping it.\n"); 1151 eprintf("call-chain problem with event, skipping it.\n");
@@ -1162,7 +1154,7 @@ process_overflow_event(event_t *event, unsigned long offset, unsigned long head)
1162 1154
1163 if (dump_trace) { 1155 if (dump_trace) {
1164 for (i = 0; i < chain->nr; i++) 1156 for (i = 0; i < chain->nr; i++)
1165 dprintf("..... %2d: %016Lx\n", i, chain->ip[i]); 1157 dprintf("..... %2d: %016Lx\n", i, chain->ips[i]);
1166 } 1158 }
1167 } 1159 }
1168 1160