printf("%*s: %Lu\n", BITS_PER_LONG / 2, "h->sum", h->sum);
}
-static void annotate_sym(struct hist_entry *he)
+static int hist_entry__tty_annotate(struct hist_entry *he)
{
struct map *map = he->ms.map;
struct dso *dso = map->dso;
struct objdump_line *pos, *n;
if (hist_entry__annotate(he, &head) < 0)
- return;
+ return -1;
if (full_paths)
d_filename = filename;
if (print_line)
free_source_line(he, len);
+
+ return 0;
}
static void hists__find_annotations(struct hists *self)
{
- struct rb_node *nd;
+ struct rb_node *first = rb_first(&self->entries), *nd = first;
+ int key = KEY_RIGHT;
- for (nd = rb_first(&self->entries); nd; nd = rb_next(nd)) {
+ while (nd) {
struct hist_entry *he = rb_entry(nd, struct hist_entry, rb_node);
struct sym_priv *priv;
- if (he->ms.sym == NULL)
- continue;
+ if (he->ms.sym == NULL || he->ms.map->dso->annotate_warned)
+ goto find_next;
priv = symbol__priv(he->ms.sym);
- if (priv->hist == NULL)
+ if (priv->hist == NULL) {
+find_next:
+ if (key == KEY_LEFT)
+ nd = rb_prev(nd);
+ else
+ nd = rb_next(nd);
continue;
+ }
- annotate_sym(he);
- /*
- * Since we have a hist_entry per IP for the same symbol, free
- * he->ms.sym->hist to signal we already processed this symbol.
- */
- free(priv->hist);
- priv->hist = NULL;
+ if (use_browser) {
+ key = hist_entry__tui_annotate(he);
+ if (is_exit_key(key))
+ break;
+ switch (key) {
+ case KEY_RIGHT:
+ case '\t':
+ nd = rb_next(nd);
+ break;
+ case KEY_LEFT:
+ if (nd == first)
+ continue;
+ nd = rb_prev(nd);
+ default:
+ break;
+ }
+ } else {
+ hist_entry__tty_annotate(he);
+ nd = rb_next(nd);
+ /*
+ * Since we have a hist_entry per IP for the same
+ * symbol, free he->ms.sym->hist to signal we already
+ * processed this symbol.
+ */
+ free(priv->hist);
+ priv->hist = NULL;
+ }
}
}
{
argc = parse_options(argc, argv, options, annotate_usage, 0);
+ setup_browser();
+
symbol_conf.priv_size = sizeof(struct sym_priv);
symbol_conf.try_vmlinux_path = true;
sym_hist_filter = argv[0];
}
- setup_pager();
-
if (field_sep && *field_sep == '.') {
pr_err("'.' is the only non valid --field-separator argument\n");
return -1;
return newtWinChoice(NULL, yes, no, (char *)msg) == 1;
}
+static void ui__error_window(const char *fmt, ...)
+{
+ va_list ap;
+
+ va_start(ap, fmt);
+ newtWinMessagev((char *)"Error", (char *)"Ok", (char *)fmt, ap);
+ va_end(ap);
+}
+
#define HE_COLORSET_TOP 50
#define HE_COLORSET_MEDIUM 51
#define HE_COLORSET_NORMAL 52
newtFormAddHotKey(self->form, ' ');
newtFormAddHotKey(self->form, NEWT_KEY_HOME);
newtFormAddHotKey(self->form, NEWT_KEY_END);
+ newtFormAddHotKey(self->form, NEWT_KEY_TAB);
+ newtFormAddHotKey(self->form, NEWT_KEY_RIGHT);
if (ui_browser__refresh_entries(self) < 0)
return -1;
if (es->reason != NEWT_EXIT_HOTKEY)
break;
+ if (is_exit_key(es->u.key))
+ return es->u.key;
switch (es->u.key) {
case NEWT_KEY_DOWN:
if (self->index == self->nr_entries - 1)
}
}
break;
- case NEWT_KEY_ESCAPE:
+ case NEWT_KEY_RIGHT:
case NEWT_KEY_LEFT:
- case CTRL('c'):
- case 'Q':
- case 'q':
- return 0;
+ case NEWT_KEY_TAB:
+ return es->u.key;
default:
continue;
}
return ret;
}
-static void hist_entry__annotate_browser(struct hist_entry *self)
+int hist_entry__tui_annotate(struct hist_entry *self)
{
struct ui_browser browser;
struct newtExitStruct es;
struct objdump_line *pos, *n;
LIST_HEAD(head);
+ int ret;
if (self->ms.sym == NULL)
- return;
+ return -1;
- if (hist_entry__annotate(self, &head) < 0)
- return;
+ if (self->ms.map->dso->annotate_warned)
+ return -1;
+
+ if (hist_entry__annotate(self, &head) < 0) {
+ ui__error_window(browser__last_msg);
+ return -1;
+ }
ui_helpline__push("Press <- or ESC to exit");
}
browser.width += 18; /* Percentage */
- ui_browser__run(&browser, self->ms.sym->name, &es);
+ ret = ui_browser__run(&browser, self->ms.sym->name, &es);
newtFormDestroy(browser.form);
newtPopWindow();
list_for_each_entry_safe(pos, n, &head, node) {
objdump_line__free(pos);
}
ui_helpline__pop();
+ return ret;
}
static const void *newt__symbol_tree_get_current(newtComponent self)
switch (toupper(es.u.key)) {
case 'A':
+ if (browser->selection->map == NULL &&
+ browser->selection->map->dso->annotate_warned)
+ continue;
goto do_annotate;
case 'D':
goto zoom_dso;
continue;
default:;
}
- if (toupper(es.u.key) == 'Q' ||
- es.u.key == CTRL('c'))
- break;
- if (es.u.key == NEWT_KEY_ESCAPE) {
- if (dialog_yesno("Do you really want to exit?"))
+ if (is_exit_key(es.u.key)) {
+ if (es.u.key == NEWT_KEY_ESCAPE) {
+ if (dialog_yesno("Do you really want to exit?"))
+ break;
+ else
+ continue;
+ } else
break;
- else
- continue;
}
if (es.u.key == NEWT_KEY_LEFT) {
}
if (browser->selection->sym != NULL &&
+ !browser->selection->map->dso->annotate_warned &&
asprintf(&options[nr_options], "Annotate %s",
browser->selection->sym->name) > 0)
annotate = nr_options++;
struct hist_entry *he;
do_annotate:
if (browser->selection->map->dso->origin == DSO__ORIG_KERNEL) {
+ browser->selection->map->dso->annotate_warned = 1;
ui_helpline__puts("No vmlinux file found, can't "
"annotate with just a "
"kallsyms file");
if (he == NULL)
continue;
- hist_entry__annotate_browser(he);
+ hist_entry__tui_annotate(he);
} else if (choice == zoom_dso) {
zoom_dso:
if (dso_filter) {
{
struct newtPercentTreeColors *c = &defaultPercentTreeColors;
- if (!isatty(1) || !use_browser) {
+ if (!isatty(1) || !use_browser || dump_trace) {
setup_pager();
return;
}