aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf/builtin-annotate.c
diff options
context:
space:
mode:
authorArnaldo Carvalho de Melo <acme@redhat.com>2010-05-11 22:18:06 -0400
committerArnaldo Carvalho de Melo <acme@redhat.com>2010-05-11 22:23:20 -0400
commitef7b93a11904c6ba10604233d318d9e8ec88cddc (patch)
tree7ae6fa9cbe19be8fbbc18c8fdeb7edfdb7bdab60 /tools/perf/builtin-annotate.c
parent3798ed7bc7ade26d3f59506cd06288615dfc7585 (diff)
perf report: Librarize the annotation code and use it in the newt browser
Now we don't anymore use popen to run 'perf annotate' for the selected symbol, instead we collect per address samplings when processing samples in 'perf report' if we're using the newt browser, then we use this data directly to do annotation. Done this way we can actually traverse the objdump_line objects directly, matching the addresses to the collected samples and colouring them appropriately using lower level slang routines. The new ui_browser class will be reused for the main, callchain aware, histogram browser, when it will be made generic and don't assume that the objects are always instances of the objdump_line class maintained using list_heads. Cc: Frédéric Weisbecker <fweisbec@gmail.com> Cc: Mike Galbraith <efault@gmx.de> Cc: Paul Mackerras <paulus@samba.org> Cc: Peter Zijlstra <a.p.zijlstra@chello.nl> Cc: Tom Zanussi <tzanussi@gmail.com> LKML-Reference: <new-submission> Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Diffstat (limited to 'tools/perf/builtin-annotate.c')
-rw-r--r--tools/perf/builtin-annotate.c198
1 files changed, 2 insertions, 196 deletions
diff --git a/tools/perf/builtin-annotate.c b/tools/perf/builtin-annotate.c
index 3940964161b3..fd1b786c8f35 100644
--- a/tools/perf/builtin-annotate.c
+++ b/tools/perf/builtin-annotate.c
@@ -34,68 +34,8 @@ static bool full_paths;
34 34
35static bool print_line; 35static bool print_line;
36 36
37struct sym_hist {
38 u64 sum;
39 u64 ip[0];
40};
41
42struct sym_ext {
43 struct rb_node node;
44 double percent;
45 char *path;
46};
47
48struct sym_priv {
49 struct sym_hist *hist;
50 struct sym_ext *ext;
51};
52
53static const char *sym_hist_filter; 37static const char *sym_hist_filter;
54 38
55static int sym__alloc_hist(struct symbol *self)
56{
57 struct sym_priv *priv = symbol__priv(self);
58 const int size = (sizeof(*priv->hist) +
59 (self->end - self->start) * sizeof(u64));
60
61 priv->hist = zalloc(size);
62 return priv->hist == NULL ? -1 : 0;
63}
64
65/*
66 * collect histogram counts
67 */
68static int annotate__hist_hit(struct hist_entry *he, u64 ip)
69{
70 unsigned int sym_size, offset;
71 struct symbol *sym = he->ms.sym;
72 struct sym_priv *priv;
73 struct sym_hist *h;
74
75 if (!sym || !he->ms.map)
76 return 0;
77
78 priv = symbol__priv(sym);
79 if (priv->hist == NULL && sym__alloc_hist(sym) < 0)
80 return -ENOMEM;
81
82 sym_size = sym->end - sym->start;
83 offset = ip - sym->start;
84
85 pr_debug3("%s: ip=%#Lx\n", __func__, he->ms.map->unmap_ip(he->ms.map, ip));
86
87 if (offset >= sym_size)
88 return 0;
89
90 h = priv->hist;
91 h->sum++;
92 h->ip[offset]++;
93
94 pr_debug3("%#Lx %s: count++ [ip: %#Lx, %#Lx] => %Ld\n", he->ms.sym->start,
95 he->ms.sym->name, ip, ip - he->ms.sym->start, h->ip[offset]);
96 return 0;
97}
98
99static int hists__add_entry(struct hists *self, struct addr_location *al) 39static int hists__add_entry(struct hists *self, struct addr_location *al)
100{ 40{
101 struct hist_entry *he; 41 struct hist_entry *he;
@@ -115,7 +55,7 @@ static int hists__add_entry(struct hists *self, struct addr_location *al)
115 if (he == NULL) 55 if (he == NULL)
116 return -ENOMEM; 56 return -ENOMEM;
117 57
118 return annotate__hist_hit(he, al->addr); 58 return hist_entry__inc_addr_samples(he, al->addr);
119} 59}
120 60
121static int process_sample_event(event_t *event, struct perf_session *session) 61static int process_sample_event(event_t *event, struct perf_session *session)
@@ -140,101 +80,6 @@ static int process_sample_event(event_t *event, struct perf_session *session)
140 return 0; 80 return 0;
141} 81}
142 82
143struct objdump_line {
144 struct list_head node;
145 s64 offset;
146 char *line;
147};
148
149static struct objdump_line *objdump_line__new(s64 offset, char *line)
150{
151 struct objdump_line *self = malloc(sizeof(*self));
152
153 if (self != NULL) {
154 self->offset = offset;
155 self->line = line;
156 }
157
158 return self;
159}
160
161static void objdump_line__free(struct objdump_line *self)
162{
163 free(self->line);
164 free(self);
165}
166
167static void objdump__add_line(struct list_head *head, struct objdump_line *line)
168{
169 list_add_tail(&line->node, head);
170}
171
172static struct objdump_line *objdump__get_next_ip_line(struct list_head *head,
173 struct objdump_line *pos)
174{
175 list_for_each_entry_continue(pos, head, node)
176 if (pos->offset >= 0)
177 return pos;
178
179 return NULL;
180}
181
182static int parse_line(FILE *file, struct hist_entry *he,
183 struct list_head *head)
184{
185 struct symbol *sym = he->ms.sym;
186 struct objdump_line *objdump_line;
187 char *line = NULL, *tmp, *tmp2;
188 size_t line_len;
189 s64 line_ip, offset = -1;
190 char *c;
191
192 if (getline(&line, &line_len, file) < 0)
193 return -1;
194
195 if (!line)
196 return -1;
197
198 c = strchr(line, '\n');
199 if (c)
200 *c = 0;
201
202 line_ip = -1;
203
204 /*
205 * Strip leading spaces:
206 */
207 tmp = line;
208 while (*tmp) {
209 if (*tmp != ' ')
210 break;
211 tmp++;
212 }
213
214 if (*tmp) {
215 /*
216 * Parse hexa addresses followed by ':'
217 */
218 line_ip = strtoull(tmp, &tmp2, 16);
219 if (*tmp2 != ':')
220 line_ip = -1;
221 }
222
223 if (line_ip != -1) {
224 u64 start = map__rip_2objdump(he->ms.map, sym->start);
225 offset = line_ip - start;
226 }
227
228 objdump_line = objdump_line__new(offset, line);
229 if (objdump_line == NULL) {
230 free(line);
231 return -1;
232 }
233 objdump__add_line(head, objdump_line);
234
235 return 0;
236}
237
238static int objdump_line__print(struct objdump_line *self, 83static int objdump_line__print(struct objdump_line *self,
239 struct list_head *head, 84 struct list_head *head,
240 struct hist_entry *he, u64 len) 85 struct hist_entry *he, u64 len)
@@ -439,27 +284,11 @@ static void annotate_sym(struct hist_entry *he)
439 struct symbol *sym = he->ms.sym; 284 struct symbol *sym = he->ms.sym;
440 const char *filename = dso->long_name, *d_filename; 285 const char *filename = dso->long_name, *d_filename;
441 u64 len; 286 u64 len;
442 char command[PATH_MAX*2];
443 FILE *file;
444 LIST_HEAD(head); 287 LIST_HEAD(head);
445 struct objdump_line *pos, *n; 288 struct objdump_line *pos, *n;
446 289
447 if (!filename) 290 if (hist_entry__annotate(he, &head) < 0)
448 return;
449
450 if (dso->origin == DSO__ORIG_KERNEL) {
451 if (dso->annotate_warned)
452 return;
453 dso->annotate_warned = 1;
454 pr_err("Can't annotate %s: No vmlinux file was found in the "
455 "path:\n", sym->name);
456 vmlinux_path__fprintf(stderr);
457 return; 291 return;
458 }
459
460 pr_debug("%s: filename=%s, sym=%s, start=%#Lx, end=%#Lx\n", __func__,
461 filename, sym->name, map->unmap_ip(map, sym->start),
462 map->unmap_ip(map, sym->end));
463 292
464 if (full_paths) 293 if (full_paths)
465 d_filename = filename; 294 d_filename = filename;
@@ -477,29 +306,6 @@ static void annotate_sym(struct hist_entry *he)
477 printf(" Percent | Source code & Disassembly of %s\n", d_filename); 306 printf(" Percent | Source code & Disassembly of %s\n", d_filename);
478 printf("------------------------------------------------\n"); 307 printf("------------------------------------------------\n");
479 308
480 if (verbose >= 2)
481 printf("annotating [%p] %30s : [%p] %30s\n",
482 dso, dso->long_name, sym, sym->name);
483
484 sprintf(command, "objdump --start-address=0x%016Lx --stop-address=0x%016Lx -dS %s|grep -v %s",
485 map__rip_2objdump(map, sym->start),
486 map__rip_2objdump(map, sym->end),
487 filename, filename);
488
489 if (verbose >= 3)
490 printf("doing: %s\n", command);
491
492 file = popen(command, "r");
493 if (!file)
494 return;
495
496 while (!feof(file)) {
497 if (parse_line(file, he, &head) < 0)
498 break;
499 }
500
501 pclose(file);
502
503 if (verbose) 309 if (verbose)
504 hist_entry__print_hits(he); 310 hist_entry__print_hits(he);
505 311