diff options
Diffstat (limited to 'tools/perf/builtin-annotate.c')
-rw-r--r-- | tools/perf/builtin-annotate.c | 61 |
1 files changed, 45 insertions, 16 deletions
diff --git a/tools/perf/builtin-annotate.c b/tools/perf/builtin-annotate.c index 77bcc9b130f5..08278eda31a5 100644 --- a/tools/perf/builtin-annotate.c +++ b/tools/perf/builtin-annotate.c | |||
@@ -277,7 +277,7 @@ static void hist_entry__print_hits(struct hist_entry *self) | |||
277 | printf("%*s: %Lu\n", BITS_PER_LONG / 2, "h->sum", h->sum); | 277 | printf("%*s: %Lu\n", BITS_PER_LONG / 2, "h->sum", h->sum); |
278 | } | 278 | } |
279 | 279 | ||
280 | static void annotate_sym(struct hist_entry *he) | 280 | static int hist_entry__tty_annotate(struct hist_entry *he) |
281 | { | 281 | { |
282 | struct map *map = he->ms.map; | 282 | struct map *map = he->ms.map; |
283 | struct dso *dso = map->dso; | 283 | struct dso *dso = map->dso; |
@@ -288,7 +288,7 @@ static void annotate_sym(struct hist_entry *he) | |||
288 | struct objdump_line *pos, *n; | 288 | struct objdump_line *pos, *n; |
289 | 289 | ||
290 | if (hist_entry__annotate(he, &head) < 0) | 290 | if (hist_entry__annotate(he, &head) < 0) |
291 | return; | 291 | return -1; |
292 | 292 | ||
293 | if (full_paths) | 293 | if (full_paths) |
294 | d_filename = filename; | 294 | d_filename = filename; |
@@ -317,30 +317,59 @@ static void annotate_sym(struct hist_entry *he) | |||
317 | 317 | ||
318 | if (print_line) | 318 | if (print_line) |
319 | free_source_line(he, len); | 319 | free_source_line(he, len); |
320 | |||
321 | return 0; | ||
320 | } | 322 | } |
321 | 323 | ||
322 | static void hists__find_annotations(struct hists *self) | 324 | static void hists__find_annotations(struct hists *self) |
323 | { | 325 | { |
324 | struct rb_node *nd; | 326 | struct rb_node *first = rb_first(&self->entries), *nd = first; |
327 | int key = KEY_RIGHT; | ||
325 | 328 | ||
326 | for (nd = rb_first(&self->entries); nd; nd = rb_next(nd)) { | 329 | while (nd) { |
327 | struct hist_entry *he = rb_entry(nd, struct hist_entry, rb_node); | 330 | struct hist_entry *he = rb_entry(nd, struct hist_entry, rb_node); |
328 | struct sym_priv *priv; | 331 | struct sym_priv *priv; |
329 | 332 | ||
330 | if (he->ms.sym == NULL) | 333 | if (he->ms.sym == NULL || he->ms.map->dso->annotate_warned) |
331 | continue; | 334 | goto find_next; |
332 | 335 | ||
333 | priv = symbol__priv(he->ms.sym); | 336 | priv = symbol__priv(he->ms.sym); |
334 | if (priv->hist == NULL) | 337 | if (priv->hist == NULL) { |
338 | find_next: | ||
339 | if (key == KEY_LEFT) | ||
340 | nd = rb_prev(nd); | ||
341 | else | ||
342 | nd = rb_next(nd); | ||
335 | continue; | 343 | continue; |
344 | } | ||
336 | 345 | ||
337 | annotate_sym(he); | 346 | if (use_browser) { |
338 | /* | 347 | key = hist_entry__tui_annotate(he); |
339 | * Since we have a hist_entry per IP for the same symbol, free | 348 | if (is_exit_key(key)) |
340 | * he->ms.sym->hist to signal we already processed this symbol. | 349 | break; |
341 | */ | 350 | switch (key) { |
342 | free(priv->hist); | 351 | case KEY_RIGHT: |
343 | priv->hist = NULL; | 352 | case '\t': |
353 | nd = rb_next(nd); | ||
354 | break; | ||
355 | case KEY_LEFT: | ||
356 | if (nd == first) | ||
357 | continue; | ||
358 | nd = rb_prev(nd); | ||
359 | default: | ||
360 | break; | ||
361 | } | ||
362 | } else { | ||
363 | hist_entry__tty_annotate(he); | ||
364 | nd = rb_next(nd); | ||
365 | /* | ||
366 | * Since we have a hist_entry per IP for the same | ||
367 | * symbol, free he->ms.sym->hist to signal we already | ||
368 | * processed this symbol. | ||
369 | */ | ||
370 | free(priv->hist); | ||
371 | priv->hist = NULL; | ||
372 | } | ||
344 | } | 373 | } |
345 | } | 374 | } |
346 | 375 | ||
@@ -416,6 +445,8 @@ int cmd_annotate(int argc, const char **argv, const char *prefix __used) | |||
416 | { | 445 | { |
417 | argc = parse_options(argc, argv, options, annotate_usage, 0); | 446 | argc = parse_options(argc, argv, options, annotate_usage, 0); |
418 | 447 | ||
448 | setup_browser(); | ||
449 | |||
419 | symbol_conf.priv_size = sizeof(struct sym_priv); | 450 | symbol_conf.priv_size = sizeof(struct sym_priv); |
420 | symbol_conf.try_vmlinux_path = true; | 451 | symbol_conf.try_vmlinux_path = true; |
421 | 452 | ||
@@ -435,8 +466,6 @@ int cmd_annotate(int argc, const char **argv, const char *prefix __used) | |||
435 | sym_hist_filter = argv[0]; | 466 | sym_hist_filter = argv[0]; |
436 | } | 467 | } |
437 | 468 | ||
438 | setup_pager(); | ||
439 | |||
440 | if (field_sep && *field_sep == '.') { | 469 | if (field_sep && *field_sep == '.') { |
441 | pr_err("'.' is the only non valid --field-separator argument\n"); | 470 | pr_err("'.' is the only non valid --field-separator argument\n"); |
442 | return -1; | 471 | return -1; |