aboutsummaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
authorArnaldo Carvalho de Melo <acme@redhat.com>2010-08-05 16:00:42 -0400
committerArnaldo Carvalho de Melo <acme@redhat.com>2010-08-05 18:38:01 -0400
commit9a725995e88fd3fd79daf99819c51d676ba37ad9 (patch)
treeb50c8a1ff31d94a1c3691236885f87088fcc3507 /tools
parentc408fedfc4a1fa16e611ffd6f3280301b38614be (diff)
perf ui: Add a map browser
Press -> and then "Browse map details" to see the DSO long name as the title and the list of symbols in the DSO used by the map where the current symbol is. Cc: Frederic Weisbecker <fweisbec@gmail.com> Cc: Mike Galbraith <efault@gmx.de> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Srikar Dronamraju <srikar@linux.vnet.ibm.com> Cc: Stephane Eranian <eranian@google.com> LKML-Reference: <new-submission> Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Diffstat (limited to 'tools')
-rw-r--r--tools/perf/util/newt.c129
1 files changed, 127 insertions, 2 deletions
diff --git a/tools/perf/util/newt.c b/tools/perf/util/newt.c
index 91de99b58445..fc4a2b3aa65e 100644
--- a/tools/perf/util/newt.c
+++ b/tools/perf/util/newt.c
@@ -13,6 +13,7 @@
13#include <slang.h> 13#include <slang.h>
14#include <signal.h> 14#include <signal.h>
15#include <stdlib.h> 15#include <stdlib.h>
16#include <elf.h>
16#include <newt.h> 17#include <newt.h>
17#include <sys/ttydefaults.h> 18#include <sys/ttydefaults.h>
18 19
@@ -280,6 +281,7 @@ struct ui_browser {
280 u16 top, left, width, height; 281 u16 top, left, width, height;
281 void *priv; 282 void *priv;
282 unsigned int (*refresh_entries)(struct ui_browser *self); 283 unsigned int (*refresh_entries)(struct ui_browser *self);
284 void (*write)(struct ui_browser *self, void *entry, int row);
283 void (*seek)(struct ui_browser *self, 285 void (*seek)(struct ui_browser *self,
284 off_t offset, int whence); 286 off_t offset, int whence);
285 u32 nr_entries; 287 u32 nr_entries;
@@ -316,6 +318,58 @@ static void ui_browser__list_head_seek(struct ui_browser *self,
316 self->first_visible_entry = pos; 318 self->first_visible_entry = pos;
317} 319}
318 320
321static void ui_browser__rb_tree_seek(struct ui_browser *self,
322 off_t offset, int whence)
323{
324 struct rb_root *root = self->entries;
325 struct rb_node *nd;
326
327 switch (whence) {
328 case SEEK_SET:
329 nd = rb_first(root);
330 break;
331 case SEEK_CUR:
332 nd = self->first_visible_entry;
333 break;
334 case SEEK_END:
335 nd = rb_last(root);
336 break;
337 default:
338 return;
339 }
340
341 if (offset > 0) {
342 while (offset-- != 0)
343 nd = rb_next(nd);
344 } else {
345 while (offset++ != 0)
346 nd = rb_prev(nd);
347 }
348
349 self->first_visible_entry = nd;
350}
351
352static unsigned int ui_browser__rb_tree_refresh(struct ui_browser *self)
353{
354 struct rb_node *nd;
355 int row = 0;
356
357 if (self->first_visible_entry == NULL)
358 self->first_visible_entry = rb_first(self->entries);
359
360 nd = self->first_visible_entry;
361
362 while (nd != NULL) {
363 SLsmg_gotorc(self->top + row, self->left);
364 self->write(self, nd, row);
365 if (++row == self->height)
366 break;
367 nd = rb_next(nd);
368 }
369
370 return row;
371}
372
319static bool ui_browser__is_current_entry(struct ui_browser *self, unsigned row) 373static bool ui_browser__is_current_entry(struct ui_browser *self, unsigned row)
320{ 374{
321 return (self->first_visible_entry_idx + row) == self->index; 375 return (self->first_visible_entry_idx + row) == self->index;
@@ -592,6 +646,70 @@ int hist_entry__tui_annotate(struct hist_entry *self)
592 return ret; 646 return ret;
593} 647}
594 648
649/* -------------------------------------------------------------------- */
650
651struct map_browser {
652 struct ui_browser b;
653 struct map *map;
654 u16 namelen;
655 u8 addrlen;
656};
657
658static void map_browser__write(struct ui_browser *self, void *nd, int row)
659{
660 struct symbol *sym = rb_entry(nd, struct symbol, rb_node);
661 struct map_browser *mb = container_of(self, struct map_browser, b);
662 bool current_entry = ui_browser__is_current_entry(self, row);
663 int color = ui_browser__percent_color(0, current_entry);
664
665 SLsmg_set_color(color);
666 slsmg_printf("%*llx %*llx %c ",
667 mb->addrlen, sym->start, mb->addrlen, sym->end,
668 sym->binding == STB_GLOBAL ? 'g' :
669 sym->binding == STB_LOCAL ? 'l' : 'w');
670 slsmg_write_nstring(sym->name, mb->namelen);
671}
672
673static int map__browse(struct map *self)
674{
675 struct map_browser mb = {
676 .b = {
677 .entries = &self->dso->symbols[self->type],
678 .refresh_entries = ui_browser__rb_tree_refresh,
679 .seek = ui_browser__rb_tree_seek,
680 .write = map_browser__write,
681 },
682 };
683 struct newtExitStruct es;
684 struct rb_node *nd;
685 char tmp[BITS_PER_LONG / 4];
686 u64 maxaddr = 0;
687 int ret;
688
689 ui_helpline__push("Press <- or ESC to exit");
690
691 for (nd = rb_first(mb.b.entries); nd; nd = rb_next(nd)) {
692 struct symbol *pos = rb_entry(nd, struct symbol, rb_node);
693
694 if (mb.namelen < pos->namelen)
695 mb.namelen = pos->namelen;
696 if (maxaddr < pos->end)
697 maxaddr = pos->end;
698 ++mb.b.nr_entries;
699 }
700
701 mb.addrlen = snprintf(tmp, sizeof(tmp), "%llx", maxaddr);
702 mb.b.width += mb.addrlen * 2 + 4 + mb.namelen;
703 ui_browser__show(&mb.b, self->dso->long_name);
704 ret = ui_browser__run(&mb.b, &es);
705 newtFormDestroy(mb.b.form);
706 newtPopWindow();
707 ui_helpline__pop();
708 return ret;
709}
710
711/* -------------------------------------------------------------------- */
712
595struct hist_browser { 713struct hist_browser {
596 struct ui_browser b; 714 struct ui_browser b;
597 struct hists *hists; 715 struct hists *hists;
@@ -680,7 +798,8 @@ int hists__browse(struct hists *self, const char *helpline, const char *ev_name)
680 const struct dso *dso; 798 const struct dso *dso;
681 char *options[16]; 799 char *options[16];
682 int nr_options = 0, choice = 0, i, 800 int nr_options = 0, choice = 0, i,
683 annotate = -2, zoom_dso = -2, zoom_thread = -2; 801 annotate = -2, zoom_dso = -2, zoom_thread = -2,
802 browse_map = -2;
684 803
685 if (hist_browser__run(browser, msg, &es)) 804 if (hist_browser__run(browser, msg, &es))
686 break; 805 break;
@@ -771,6 +890,10 @@ do_help:
771 (dso->kernel ? "the Kernel" : dso->short_name)) > 0) 890 (dso->kernel ? "the Kernel" : dso->short_name)) > 0)
772 zoom_dso = nr_options++; 891 zoom_dso = nr_options++;
773 892
893 if (browser->selection->map != NULL &&
894 asprintf(&options[nr_options], "Browse map details") > 0)
895 browse_map = nr_options++;
896
774 options[nr_options++] = (char *)"Exit"; 897 options[nr_options++] = (char *)"Exit";
775 898
776 choice = popup_menu(nr_options, options); 899 choice = popup_menu(nr_options, options);
@@ -800,7 +923,9 @@ do_annotate:
800 continue; 923 continue;
801 924
802 hist_entry__tui_annotate(he); 925 hist_entry__tui_annotate(he);
803 } else if (choice == zoom_dso) { 926 } else if (choice == browse_map)
927 map__browse(browser->selection->map);
928 else if (choice == zoom_dso) {
804zoom_dso: 929zoom_dso:
805 if (dso_filter) { 930 if (dso_filter) {
806 pstack__remove(fstack, &dso_filter); 931 pstack__remove(fstack, &dso_filter);