diff options
Diffstat (limited to 'tools/perf/builtin-annotate.c')
-rw-r--r-- | tools/perf/builtin-annotate.c | 62 |
1 files changed, 34 insertions, 28 deletions
diff --git a/tools/perf/builtin-annotate.c b/tools/perf/builtin-annotate.c index 4f0c3d98352..483cb946644 100644 --- a/tools/perf/builtin-annotate.c +++ b/tools/perf/builtin-annotate.c | |||
@@ -30,7 +30,8 @@ | |||
30 | 30 | ||
31 | #include <linux/bitmap.h> | 31 | #include <linux/bitmap.h> |
32 | 32 | ||
33 | static struct perf_annotate { | 33 | struct perf_annotate { |
34 | struct perf_event_ops ops; | ||
34 | char const *input_name; | 35 | char const *input_name; |
35 | bool force, use_tui, use_stdio; | 36 | bool force, use_tui, use_stdio; |
36 | bool full_paths; | 37 | bool full_paths; |
@@ -38,13 +39,12 @@ static struct perf_annotate { | |||
38 | const char *sym_hist_filter; | 39 | const char *sym_hist_filter; |
39 | const char *cpu_list; | 40 | const char *cpu_list; |
40 | DECLARE_BITMAP(cpu_bitmap, MAX_NR_CPUS); | 41 | DECLARE_BITMAP(cpu_bitmap, MAX_NR_CPUS); |
41 | } annotate = { | 42 | }; |
42 | .input_name = "perf.data", | ||
43 | }, *ann = &annotate; | ||
44 | 43 | ||
45 | static int perf_evsel__add_sample(struct perf_evsel *evsel, | 44 | static int perf_evsel__add_sample(struct perf_evsel *evsel, |
46 | struct perf_sample *sample, | 45 | struct perf_sample *sample, |
47 | struct addr_location *al) | 46 | struct addr_location *al, |
47 | struct perf_annotate *ann) | ||
48 | { | 48 | { |
49 | struct hist_entry *he; | 49 | struct hist_entry *he; |
50 | int ret; | 50 | int ret; |
@@ -79,11 +79,13 @@ static int perf_evsel__add_sample(struct perf_evsel *evsel, | |||
79 | return ret; | 79 | return ret; |
80 | } | 80 | } |
81 | 81 | ||
82 | static int process_sample_event(union perf_event *event, | 82 | static int process_sample_event(struct perf_event_ops *ops, |
83 | union perf_event *event, | ||
83 | struct perf_sample *sample, | 84 | struct perf_sample *sample, |
84 | struct perf_evsel *evsel, | 85 | struct perf_evsel *evsel, |
85 | struct perf_session *session) | 86 | struct perf_session *session) |
86 | { | 87 | { |
88 | struct perf_annotate *ann = container_of(ops, struct perf_annotate, ops); | ||
87 | struct addr_location al; | 89 | struct addr_location al; |
88 | 90 | ||
89 | if (perf_event__preprocess_sample(event, session, &al, sample, | 91 | if (perf_event__preprocess_sample(event, session, &al, sample, |
@@ -96,7 +98,7 @@ static int process_sample_event(union perf_event *event, | |||
96 | if (ann->cpu_list && !test_bit(sample->cpu, ann->cpu_bitmap)) | 98 | if (ann->cpu_list && !test_bit(sample->cpu, ann->cpu_bitmap)) |
97 | return 0; | 99 | return 0; |
98 | 100 | ||
99 | if (!al.filtered && perf_evsel__add_sample(evsel, sample, &al)) { | 101 | if (!al.filtered && perf_evsel__add_sample(evsel, sample, &al, ann)) { |
100 | pr_warning("problem incrementing symbol count, " | 102 | pr_warning("problem incrementing symbol count, " |
101 | "skipping event\n"); | 103 | "skipping event\n"); |
102 | return -1; | 104 | return -1; |
@@ -105,13 +107,15 @@ static int process_sample_event(union perf_event *event, | |||
105 | return 0; | 107 | return 0; |
106 | } | 108 | } |
107 | 109 | ||
108 | static int hist_entry__tty_annotate(struct hist_entry *he, int evidx) | 110 | static int hist_entry__tty_annotate(struct hist_entry *he, int evidx, |
111 | struct perf_annotate *ann) | ||
109 | { | 112 | { |
110 | return symbol__tty_annotate(he->ms.sym, he->ms.map, evidx, | 113 | return symbol__tty_annotate(he->ms.sym, he->ms.map, evidx, |
111 | ann->print_line, ann->full_paths, 0, 0); | 114 | ann->print_line, ann->full_paths, 0, 0); |
112 | } | 115 | } |
113 | 116 | ||
114 | static void hists__find_annotations(struct hists *self, int evidx) | 117 | static void hists__find_annotations(struct hists *self, int evidx, |
118 | struct perf_annotate *ann) | ||
115 | { | 119 | { |
116 | struct rb_node *nd = rb_first(&self->entries), *next; | 120 | struct rb_node *nd = rb_first(&self->entries), *next; |
117 | int key = K_RIGHT; | 121 | int key = K_RIGHT; |
@@ -149,7 +153,7 @@ find_next: | |||
149 | if (next != NULL) | 153 | if (next != NULL) |
150 | nd = next; | 154 | nd = next; |
151 | } else { | 155 | } else { |
152 | hist_entry__tty_annotate(he, evidx); | 156 | hist_entry__tty_annotate(he, evidx, ann); |
153 | nd = rb_next(nd); | 157 | nd = rb_next(nd); |
154 | /* | 158 | /* |
155 | * Since we have a hist_entry per IP for the same | 159 | * Since we have a hist_entry per IP for the same |
@@ -162,16 +166,7 @@ find_next: | |||
162 | } | 166 | } |
163 | } | 167 | } |
164 | 168 | ||
165 | static struct perf_event_ops event_ops = { | 169 | static int __cmd_annotate(struct perf_annotate *ann) |
166 | .sample = process_sample_event, | ||
167 | .mmap = perf_event__process_mmap, | ||
168 | .comm = perf_event__process_comm, | ||
169 | .fork = perf_event__process_task, | ||
170 | .ordered_samples = true, | ||
171 | .ordering_requires_timestamps = true, | ||
172 | }; | ||
173 | |||
174 | static int __cmd_annotate(void) | ||
175 | { | 170 | { |
176 | int ret; | 171 | int ret; |
177 | struct perf_session *session; | 172 | struct perf_session *session; |
@@ -179,7 +174,7 @@ static int __cmd_annotate(void) | |||
179 | u64 total_nr_samples; | 174 | u64 total_nr_samples; |
180 | 175 | ||
181 | session = perf_session__new(ann->input_name, O_RDONLY, | 176 | session = perf_session__new(ann->input_name, O_RDONLY, |
182 | ann->force, false, &event_ops); | 177 | ann->force, false, &ann->ops); |
183 | if (session == NULL) | 178 | if (session == NULL) |
184 | return -ENOMEM; | 179 | return -ENOMEM; |
185 | 180 | ||
@@ -190,7 +185,7 @@ static int __cmd_annotate(void) | |||
190 | goto out_delete; | 185 | goto out_delete; |
191 | } | 186 | } |
192 | 187 | ||
193 | ret = perf_session__process_events(session, &event_ops); | 188 | ret = perf_session__process_events(session, &ann->ops); |
194 | if (ret) | 189 | if (ret) |
195 | goto out_delete; | 190 | goto out_delete; |
196 | 191 | ||
@@ -214,7 +209,7 @@ static int __cmd_annotate(void) | |||
214 | total_nr_samples += nr_samples; | 209 | total_nr_samples += nr_samples; |
215 | hists__collapse_resort(hists); | 210 | hists__collapse_resort(hists); |
216 | hists__output_resort(hists); | 211 | hists__output_resort(hists); |
217 | hists__find_annotations(hists, pos->idx); | 212 | hists__find_annotations(hists, pos->idx, ann); |
218 | } | 213 | } |
219 | } | 214 | } |
220 | 215 | ||
@@ -243,7 +238,20 @@ static const char * const annotate_usage[] = { | |||
243 | NULL | 238 | NULL |
244 | }; | 239 | }; |
245 | 240 | ||
246 | static const struct option options[] = { | 241 | int cmd_annotate(int argc, const char **argv, const char *prefix __used) |
242 | { | ||
243 | struct perf_annotate annotate = { | ||
244 | .ops = { | ||
245 | .sample = process_sample_event, | ||
246 | .mmap = perf_event__process_mmap, | ||
247 | .comm = perf_event__process_comm, | ||
248 | .fork = perf_event__process_task, | ||
249 | .ordered_samples = true, | ||
250 | .ordering_requires_timestamps = true, | ||
251 | }, | ||
252 | .input_name = "perf.data", | ||
253 | }; | ||
254 | const struct option options[] = { | ||
247 | OPT_STRING('i', "input", &annotate.input_name, "file", | 255 | OPT_STRING('i', "input", &annotate.input_name, "file", |
248 | "input file name"), | 256 | "input file name"), |
249 | OPT_STRING('d', "dsos", &symbol_conf.dso_list_str, "dso[,dso...]", | 257 | OPT_STRING('d', "dsos", &symbol_conf.dso_list_str, "dso[,dso...]", |
@@ -275,10 +283,8 @@ static const struct option options[] = { | |||
275 | OPT_STRING('M', "disassembler-style", &disassembler_style, "disassembler style", | 283 | OPT_STRING('M', "disassembler-style", &disassembler_style, "disassembler style", |
276 | "Specify disassembler style (e.g. -M intel for intel syntax)"), | 284 | "Specify disassembler style (e.g. -M intel for intel syntax)"), |
277 | OPT_END() | 285 | OPT_END() |
278 | }; | 286 | }; |
279 | 287 | ||
280 | int cmd_annotate(int argc, const char **argv, const char *prefix __used) | ||
281 | { | ||
282 | argc = parse_options(argc, argv, options, annotate_usage, 0); | 288 | argc = parse_options(argc, argv, options, annotate_usage, 0); |
283 | 289 | ||
284 | if (annotate.use_stdio) | 290 | if (annotate.use_stdio) |
@@ -312,5 +318,5 @@ int cmd_annotate(int argc, const char **argv, const char *prefix __used) | |||
312 | return -1; | 318 | return -1; |
313 | } | 319 | } |
314 | 320 | ||
315 | return __cmd_annotate(); | 321 | return __cmd_annotate(&annotate); |
316 | } | 322 | } |