1e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#include "../browser.h"
2e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#include "../helpline.h"
3e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#include "../libslang.h"
4e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#include "../../annotate.h"
5e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#include "../../hist.h"
6e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#include "../../sort.h"
7e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#include "../../symbol.h"
8e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#include <pthread.h>
9e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
10e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengstatic void ui__error_window(const char *fmt, ...)
11e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{
12e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	va_list ap;
13e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
14e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	va_start(ap, fmt);
15e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	newtWinMessagev((char *)"Error", (char *)"Ok", (char *)fmt, ap);
16e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	va_end(ap);
17e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng}
18e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
19e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengstruct annotate_browser {
20e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	struct ui_browser b;
21e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	struct rb_root	  entries;
22e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	struct rb_node	  *curr_hot;
23e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng};
24e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
25e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengstruct objdump_line_rb_node {
26e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	struct rb_node	rb_node;
27e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	double		percent;
28e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	u32		idx;
29e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng};
30e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
31e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengstatic inline
32e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengstruct objdump_line_rb_node *objdump_line__rb(struct objdump_line *self)
33e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{
34e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	return (struct objdump_line_rb_node *)(self + 1);
35e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng}
36e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
37e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengstatic void annotate_browser__write(struct ui_browser *self, void *entry, int row)
38e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{
39e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	struct objdump_line *ol = rb_entry(entry, struct objdump_line, node);
40e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	bool current_entry = ui_browser__is_current_entry(self, row);
41e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	int width = self->width;
42e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
43e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	if (ol->offset != -1) {
44e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		struct objdump_line_rb_node *olrb = objdump_line__rb(ol);
45e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		ui_browser__set_percent_color(self, olrb->percent, current_entry);
46e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		slsmg_printf(" %7.2f ", olrb->percent);
47e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	} else {
48e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		ui_browser__set_percent_color(self, 0, current_entry);
49e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		slsmg_write_nstring(" ", 9);
50e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	}
51e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
52e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	SLsmg_write_char(':');
53e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	slsmg_write_nstring(" ", 8);
54e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	if (!*ol->line)
55e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		slsmg_write_nstring(" ", width - 18);
56e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	else
57e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		slsmg_write_nstring(ol->line, width - 18);
58e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
59e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	if (!current_entry)
60e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		ui_browser__set_color(self, HE_COLORSET_CODE);
61e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng}
62e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
63e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengstatic double objdump_line__calc_percent(struct objdump_line *self,
64e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng					 struct symbol *sym, int evidx)
65e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{
66e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	double percent = 0.0;
67e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
68e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	if (self->offset != -1) {
69e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		int len = sym->end - sym->start;
70e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		unsigned int hits = 0;
71e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		struct annotation *notes = symbol__annotation(sym);
72e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		struct source_line *src_line = notes->src->lines;
73e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		struct sym_hist *h = annotation__histogram(notes, evidx);
74e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		s64 offset = self->offset;
75e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		struct objdump_line *next;
76e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
77e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		next = objdump__get_next_ip_line(&notes->src->source, self);
78e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		while (offset < (s64)len &&
79e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		       (next == NULL || offset < next->offset)) {
80e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			if (src_line) {
81e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng				percent += src_line[offset].percent;
82e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			} else
83e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng				hits += h->addr[offset];
84e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
85e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			++offset;
86e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		}
87e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		/*
88e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 		 * If the percentage wasn't already calculated in
89e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 		 * symbol__get_source_line, do it now:
90e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 		 */
91e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		if (src_line == NULL && h->sum)
92e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			percent = 100.0 * hits / h->sum;
93e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	}
94e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
95e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	return percent;
96e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng}
97e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
98e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengstatic void objdump__insert_line(struct rb_root *self,
99e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng				 struct objdump_line_rb_node *line)
100e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{
101e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	struct rb_node **p = &self->rb_node;
102e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	struct rb_node *parent = NULL;
103e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	struct objdump_line_rb_node *l;
104e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
105e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	while (*p != NULL) {
106e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		parent = *p;
107e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		l = rb_entry(parent, struct objdump_line_rb_node, rb_node);
108e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		if (line->percent < l->percent)
109e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			p = &(*p)->rb_left;
110e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		else
111e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			p = &(*p)->rb_right;
112e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	}
113e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	rb_link_node(&line->rb_node, parent, p);
114e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	rb_insert_color(&line->rb_node, self);
115e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng}
116e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
117e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengstatic void annotate_browser__set_top(struct annotate_browser *self,
118e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng				      struct rb_node *nd)
119e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{
120e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	struct objdump_line_rb_node *rbpos;
121e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	struct objdump_line *pos;
122e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	unsigned back;
123e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
124e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	ui_browser__refresh_dimensions(&self->b);
125e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	back = self->b.height / 2;
126e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	rbpos = rb_entry(nd, struct objdump_line_rb_node, rb_node);
127e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	pos = ((struct objdump_line *)rbpos) - 1;
128e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	self->b.top_idx = self->b.index = rbpos->idx;
129e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
130e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	while (self->b.top_idx != 0 && back != 0) {
131e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		pos = list_entry(pos->node.prev, struct objdump_line, node);
132e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
133e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		--self->b.top_idx;
134e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		--back;
135e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	}
136e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
137e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	self->b.top = pos;
138e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	self->curr_hot = nd;
139e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng}
140e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
141e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengstatic void annotate_browser__calc_percent(struct annotate_browser *browser,
142e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng					   int evidx)
143e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{
144e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	struct symbol *sym = browser->b.priv;
145e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	struct annotation *notes = symbol__annotation(sym);
146e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	struct objdump_line *pos;
147e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
148e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	browser->entries = RB_ROOT;
149e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
150e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	pthread_mutex_lock(&notes->lock);
151e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
152e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	list_for_each_entry(pos, &notes->src->source, node) {
153e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		struct objdump_line_rb_node *rbpos = objdump_line__rb(pos);
154e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		rbpos->percent = objdump_line__calc_percent(pos, sym, evidx);
155e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		if (rbpos->percent < 0.01) {
156e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			RB_CLEAR_NODE(&rbpos->rb_node);
157e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			continue;
158e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		}
159e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		objdump__insert_line(&browser->entries, rbpos);
160e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	}
161e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	pthread_mutex_unlock(&notes->lock);
162e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
163e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	browser->curr_hot = rb_last(&browser->entries);
164e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng}
165e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
166e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengstatic int annotate_browser__run(struct annotate_browser *self, int evidx,
167e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng				 int refresh)
168e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{
169e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	struct rb_node *nd = NULL;
170e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	struct symbol *sym = self->b.priv;
171e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	/*
172e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	 * RIGHT To allow builtin-annotate to cycle thru multiple symbols by
173e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	 * examining the exit key for this function.
174e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	 */
175e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	int exit_keys[] = { 'H', NEWT_KEY_TAB, NEWT_KEY_UNTAB,
176e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			    NEWT_KEY_RIGHT, 0 };
177e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	int key;
178e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
179e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	if (ui_browser__show(&self->b, sym->name,
180e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			     "<-, -> or ESC: exit, TAB/shift+TAB: "
181e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			     "cycle hottest lines, H: Hottest") < 0)
182e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		return -1;
183e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
184e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	ui_browser__add_exit_keys(&self->b, exit_keys);
185e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	annotate_browser__calc_percent(self, evidx);
186e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
187e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	if (self->curr_hot)
188e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		annotate_browser__set_top(self, self->curr_hot);
189e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
190e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	nd = self->curr_hot;
191e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
192e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	if (refresh != 0)
193e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		newtFormSetTimer(self->b.form, refresh);
194e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
195e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	while (1) {
196e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		key = ui_browser__run(&self->b);
197e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
198e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		if (refresh != 0) {
199e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			annotate_browser__calc_percent(self, evidx);
200e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			/*
201e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			 * Current line focus got out of the list of most active
202e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			 * lines, NULL it so that if TAB|UNTAB is pressed, we
203e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			 * move to curr_hot (current hottest line).
204e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			 */
205e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			if (nd != NULL && RB_EMPTY_NODE(nd))
206e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng				nd = NULL;
207e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		}
208e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
209e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		switch (key) {
210e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		case -1:
211e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			/*
212e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 			 * FIXME we need to check if it was
213e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 			 * es.reason == NEWT_EXIT_TIMER
214e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 			 */
215e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			if (refresh != 0)
216e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng				symbol__annotate_decay_histogram(sym, evidx);
217e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			continue;
218e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		case NEWT_KEY_TAB:
219e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			if (nd != NULL) {
220e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng				nd = rb_prev(nd);
221e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng				if (nd == NULL)
222e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng					nd = rb_last(&self->entries);
223e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			} else
224e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng				nd = self->curr_hot;
225e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			break;
226e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		case NEWT_KEY_UNTAB:
227e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			if (nd != NULL)
228e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng				nd = rb_next(nd);
229e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng				if (nd == NULL)
230e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng					nd = rb_first(&self->entries);
231e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			else
232e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng				nd = self->curr_hot;
233e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			break;
234e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		case 'H':
235e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			nd = self->curr_hot;
236e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			break;
237e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		default:
238e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			goto out;
239e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		}
240e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
241e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		if (nd != NULL)
242e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			annotate_browser__set_top(self, nd);
243e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	}
244e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengout:
245e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	ui_browser__hide(&self->b);
246e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	return key;
247e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng}
248e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
249e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengint hist_entry__tui_annotate(struct hist_entry *he, int evidx)
250e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{
251e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	return symbol__tui_annotate(he->ms.sym, he->ms.map, evidx, 0);
252e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng}
253e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
254e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengint symbol__tui_annotate(struct symbol *sym, struct map *map, int evidx,
255e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			 int refresh)
256e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{
257e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	struct objdump_line *pos, *n;
258e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	struct annotation *notes;
259e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	struct annotate_browser browser = {
260e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		.b = {
261e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			.refresh = ui_browser__list_head_refresh,
262e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			.seek	 = ui_browser__list_head_seek,
263e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			.write	 = annotate_browser__write,
264e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			.priv	 = sym,
265e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		},
266e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	};
267e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	int ret;
268e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
269e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	if (sym == NULL)
270e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		return -1;
271e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
272e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	if (map->dso->annotate_warned)
273e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		return -1;
274e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
275e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	if (symbol__annotate(sym, map, sizeof(struct objdump_line_rb_node)) < 0) {
276e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		ui__error_window(ui_helpline__last_msg);
277e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		return -1;
278e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	}
279e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
280e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	ui_helpline__push("Press <- or ESC to exit");
281e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
282e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	notes = symbol__annotation(sym);
283e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
284e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	list_for_each_entry(pos, &notes->src->source, node) {
285e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		struct objdump_line_rb_node *rbpos;
286e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		size_t line_len = strlen(pos->line);
287e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
288e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		if (browser.b.width < line_len)
289e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			browser.b.width = line_len;
290e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		rbpos = objdump_line__rb(pos);
291e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		rbpos->idx = browser.b.nr_entries++;
292e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	}
293e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
294e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	browser.b.entries = &notes->src->source,
295e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	browser.b.width += 18; /* Percentage */
296e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	ret = annotate_browser__run(&browser, evidx, refresh);
297e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	list_for_each_entry_safe(pos, n, &notes->src->source, node) {
298e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		list_del(&pos->node);
299e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		objdump_line__free(pos);
300e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	}
301e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	return ret;
302e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng}
303