xref: /linux/tools/perf/ui/browsers/annotate.c (revision 63df0e4bc368adbd12ed70ed4789d8d52d65661d)
1b2441318SGreg Kroah-Hartman // SPDX-License-Identifier: GPL-2.0
2aca7a94dSNamhyung Kim #include "../browser.h"
3aca7a94dSNamhyung Kim #include "../helpline.h"
4aca7a94dSNamhyung Kim #include "../ui.h"
5aca7a94dSNamhyung Kim #include "../../util/annotate.h"
6b4209025SArnaldo Carvalho de Melo #include "../../util/debug.h"
74a3cec84SArnaldo Carvalho de Melo #include "../../util/dso.h"
8aca7a94dSNamhyung Kim #include "../../util/hist.h"
9aca7a94dSNamhyung Kim #include "../../util/sort.h"
101101f69aSArnaldo Carvalho de Melo #include "../../util/map.h"
1182aff6ccSIan Rogers #include "../../util/mutex.h"
12aca7a94dSNamhyung Kim #include "../../util/symbol.h"
13db8fd07aSNamhyung Kim #include "../../util/evsel.h"
1469fb09f6SJin Yao #include "../../util/evlist.h"
15fd20e811SArnaldo Carvalho de Melo #include <inttypes.h>
16877a7a11SArnaldo Carvalho de Melo #include <linux/kernel.h>
178e99b6d4SArnaldo Carvalho de Melo #include <linux/string.h>
187f7c536fSArnaldo Carvalho de Melo #include <linux/zalloc.h>
19b0742e90SArnaldo Carvalho de Melo #include <sys/ttydefaults.h>
203e0d7953SJiri Olsa #include <asm/bug.h>
21aca7a94dSNamhyung Kim 
22dcaa3948SJin Yao struct arch;
23dcaa3948SJin Yao 
24aca7a94dSNamhyung Kim struct annotate_browser {
25aca7a94dSNamhyung Kim 	struct ui_browser	    b;
26aca7a94dSNamhyung Kim 	struct rb_root		    entries;
27aca7a94dSNamhyung Kim 	struct rb_node		   *curr_hot;
287bcbcd58SJiri Olsa 	struct annotation_line	   *selection;
29dcaa3948SJin Yao 	struct arch		   *arch;
30cd0cccbaSArnaldo Carvalho de Melo 	struct annotation_options  *opts;
31aca7a94dSNamhyung Kim 	bool			    searching_backwards;
32aca7a94dSNamhyung Kim 	char			    search_bf[128];
33aca7a94dSNamhyung Kim };
34aca7a94dSNamhyung Kim 
3595aa89d9SArnaldo Carvalho de Melo static inline struct annotation *browser__annotation(struct ui_browser *browser)
3695aa89d9SArnaldo Carvalho de Melo {
3795aa89d9SArnaldo Carvalho de Melo 	struct map_symbol *ms = browser->priv;
3895aa89d9SArnaldo Carvalho de Melo 	return symbol__annotation(ms->sym);
3995aa89d9SArnaldo Carvalho de Melo }
4095aa89d9SArnaldo Carvalho de Melo 
4116932d77SArnaldo Carvalho de Melo static bool disasm_line__filter(struct ui_browser *browser, void *entry)
42aca7a94dSNamhyung Kim {
4395aa89d9SArnaldo Carvalho de Melo 	struct annotation *notes = browser__annotation(browser);
44d5490b96SJiri Olsa 	struct annotation_line *al = list_entry(entry, struct annotation_line, node);
459b80d1f9SArnaldo Carvalho de Melo 	return annotation_line__filter(al, notes);
46aca7a94dSNamhyung Kim }
47aca7a94dSNamhyung Kim 
4827feb761SArnaldo Carvalho de Melo static int ui_browser__jumps_percent_color(struct ui_browser *browser, int nr, bool current)
492402e4a9SArnaldo Carvalho de Melo {
5027feb761SArnaldo Carvalho de Melo 	struct annotation *notes = browser__annotation(browser);
51bc1c0f3dSArnaldo Carvalho de Melo 
5227feb761SArnaldo Carvalho de Melo 	if (current && (!browser->use_navkeypressed || browser->navkeypressed))
532402e4a9SArnaldo Carvalho de Melo 		return HE_COLORSET_SELECTED;
54bc1c0f3dSArnaldo Carvalho de Melo 	if (nr == notes->max_jump_sources)
552402e4a9SArnaldo Carvalho de Melo 		return HE_COLORSET_TOP;
562402e4a9SArnaldo Carvalho de Melo 	if (nr > 1)
572402e4a9SArnaldo Carvalho de Melo 		return HE_COLORSET_MEDIUM;
582402e4a9SArnaldo Carvalho de Melo 	return HE_COLORSET_NORMAL;
592402e4a9SArnaldo Carvalho de Melo }
602402e4a9SArnaldo Carvalho de Melo 
61a1e9b74cSArnaldo Carvalho de Melo static int ui_browser__set_jumps_percent_color(void *browser, int nr, bool current)
622402e4a9SArnaldo Carvalho de Melo {
6327feb761SArnaldo Carvalho de Melo 	 int color = ui_browser__jumps_percent_color(browser, nr, current);
6427feb761SArnaldo Carvalho de Melo 	 return ui_browser__set_color(browser, color);
652402e4a9SArnaldo Carvalho de Melo }
662402e4a9SArnaldo Carvalho de Melo 
67a1e9b74cSArnaldo Carvalho de Melo static int annotate_browser__set_color(void *browser, int color)
68aca7a94dSNamhyung Kim {
69a1e9b74cSArnaldo Carvalho de Melo 	return ui_browser__set_color(browser, color);
704ea08b52SArnaldo Carvalho de Melo }
714ea08b52SArnaldo Carvalho de Melo 
72a1e9b74cSArnaldo Carvalho de Melo static void annotate_browser__write_graph(void *browser, int graph)
73a1e9b74cSArnaldo Carvalho de Melo {
74a1e9b74cSArnaldo Carvalho de Melo 	ui_browser__write_graph(browser, graph);
75a5433b3eSJiri Olsa }
76a5433b3eSJiri Olsa 
772ba5eca1SArnaldo Carvalho de Melo static void annotate_browser__set_percent_color(void *browser, double percent, bool current)
782ba5eca1SArnaldo Carvalho de Melo {
792ba5eca1SArnaldo Carvalho de Melo 	ui_browser__set_percent_color(browser, percent, current);
802ba5eca1SArnaldo Carvalho de Melo }
812ba5eca1SArnaldo Carvalho de Melo 
822ba5eca1SArnaldo Carvalho de Melo static void annotate_browser__printf(void *browser, const char *fmt, ...)
832ba5eca1SArnaldo Carvalho de Melo {
842ba5eca1SArnaldo Carvalho de Melo 	va_list args;
852ba5eca1SArnaldo Carvalho de Melo 
862ba5eca1SArnaldo Carvalho de Melo 	va_start(args, fmt);
872ba5eca1SArnaldo Carvalho de Melo 	ui_browser__vprintf(browser, fmt, args);
882ba5eca1SArnaldo Carvalho de Melo 	va_end(args);
892ba5eca1SArnaldo Carvalho de Melo }
902ba5eca1SArnaldo Carvalho de Melo 
91a5433b3eSJiri Olsa static void annotate_browser__write(struct ui_browser *browser, void *entry, int row)
92a5433b3eSJiri Olsa {
93a5433b3eSJiri Olsa 	struct annotate_browser *ab = container_of(browser, struct annotate_browser, b);
9495aa89d9SArnaldo Carvalho de Melo 	struct annotation *notes = browser__annotation(browser);
95a5433b3eSJiri Olsa 	struct annotation_line *al = list_entry(entry, struct annotation_line, node);
96da201963SArnaldo Carvalho de Melo 	const bool is_current_entry = ui_browser__is_current_entry(browser, row);
97c298304bSArnaldo Carvalho de Melo 	struct annotation_write_ops ops = {
98c298304bSArnaldo Carvalho de Melo 		.first_line		 = row == 0,
99da201963SArnaldo Carvalho de Melo 		.current_entry		 = is_current_entry,
100c298304bSArnaldo Carvalho de Melo 		.change_color		 = (!notes->options->hide_src_code &&
101da201963SArnaldo Carvalho de Melo 					    (!is_current_entry ||
102c298304bSArnaldo Carvalho de Melo 					     (browser->use_navkeypressed &&
103c298304bSArnaldo Carvalho de Melo 					      !browser->navkeypressed))),
104c298304bSArnaldo Carvalho de Melo 		.width			 = browser->width,
105c298304bSArnaldo Carvalho de Melo 		.obj			 = browser,
106c298304bSArnaldo Carvalho de Melo 		.set_color		 = annotate_browser__set_color,
107c298304bSArnaldo Carvalho de Melo 		.set_percent_color	 = annotate_browser__set_percent_color,
108c298304bSArnaldo Carvalho de Melo 		.set_jumps_percent_color = ui_browser__set_jumps_percent_color,
109c298304bSArnaldo Carvalho de Melo 		.printf			 = annotate_browser__printf,
110c298304bSArnaldo Carvalho de Melo 		.write_graph		 = annotate_browser__write_graph,
111c298304bSArnaldo Carvalho de Melo 	};
112a5433b3eSJiri Olsa 
113a5433b3eSJiri Olsa 	/* The scroll bar isn't being used */
114a5433b3eSJiri Olsa 	if (!browser->navkeypressed)
115c298304bSArnaldo Carvalho de Melo 		ops.width += 1;
116a5433b3eSJiri Olsa 
1174c650ddcSJiri Olsa 	annotation_line__write(al, notes, &ops, ab->opts);
118aca7a94dSNamhyung Kim 
119c298304bSArnaldo Carvalho de Melo 	if (ops.current_entry)
120a5433b3eSJiri Olsa 		ab->selection = al;
121aca7a94dSNamhyung Kim }
122aca7a94dSNamhyung Kim 
1237efbcc8cSRavi Bangoria static int is_fused(struct annotate_browser *ab, struct disasm_line *cursor)
1247e63a13aSJin Yao {
125a17c4ca0SJiri Olsa 	struct disasm_line *pos = list_prev_entry(cursor, al.node);
1267e63a13aSJin Yao 	const char *name;
1277efbcc8cSRavi Bangoria 	int diff = 1;
1287efbcc8cSRavi Bangoria 
1297efbcc8cSRavi Bangoria 	while (pos && pos->al.offset == -1) {
1307efbcc8cSRavi Bangoria 		pos = list_prev_entry(pos, al.node);
1317efbcc8cSRavi Bangoria 		if (!ab->opts->hide_src_code)
1327efbcc8cSRavi Bangoria 			diff++;
1337efbcc8cSRavi Bangoria 	}
1347e63a13aSJin Yao 
1357e63a13aSJin Yao 	if (!pos)
1367efbcc8cSRavi Bangoria 		return 0;
1377e63a13aSJin Yao 
1387e63a13aSJin Yao 	if (ins__is_lock(&pos->ins))
1397e63a13aSJin Yao 		name = pos->ops.locked.ins.name;
1407e63a13aSJin Yao 	else
1417e63a13aSJin Yao 		name = pos->ins.name;
1427e63a13aSJin Yao 
1437e63a13aSJin Yao 	if (!name || !cursor->ins.name)
1447efbcc8cSRavi Bangoria 		return 0;
1457e63a13aSJin Yao 
1467efbcc8cSRavi Bangoria 	if (ins__is_fused(ab->arch, name, cursor->ins.name))
1477efbcc8cSRavi Bangoria 		return diff;
1487efbcc8cSRavi Bangoria 	return 0;
1497e63a13aSJin Yao }
1507e63a13aSJin Yao 
1519d1ef56dSArnaldo Carvalho de Melo static void annotate_browser__draw_current_jump(struct ui_browser *browser)
152a3f895beSArnaldo Carvalho de Melo {
153a3f895beSArnaldo Carvalho de Melo 	struct annotate_browser *ab = container_of(browser, struct annotate_browser, b);
1547bcbcd58SJiri Olsa 	struct disasm_line *cursor = disasm_line(ab->selection);
155a5ef2702SJiri Olsa 	struct annotation_line *target;
15683b1f2aaSArnaldo Carvalho de Melo 	unsigned int from, to;
15732ae1efdSNamhyung Kim 	struct map_symbol *ms = ab->b.priv;
15832ae1efdSNamhyung Kim 	struct symbol *sym = ms->sym;
1590e83a7e9SArnaldo Carvalho de Melo 	struct annotation *notes = symbol__annotation(sym);
1606af612d2SArnaldo Carvalho de Melo 	u8 pcnt_width = annotation__pcnt_width(notes);
16100ea0eb2SArnaldo Carvalho de Melo 	int width;
1627efbcc8cSRavi Bangoria 	int diff = 0;
16332ae1efdSNamhyung Kim 
16432ae1efdSNamhyung Kim 	/* PLT symbols contain external offsets */
16532ae1efdSNamhyung Kim 	if (strstr(sym->name, "@plt"))
16632ae1efdSNamhyung Kim 		return;
167a3f895beSArnaldo Carvalho de Melo 
1682eff0611SArnaldo Carvalho de Melo 	if (!disasm_line__is_valid_local_jump(cursor, sym))
169a3f895beSArnaldo Carvalho de Melo 		return;
170a3f895beSArnaldo Carvalho de Melo 
1719c04409dSArnaldo Carvalho de Melo 	/*
1729c04409dSArnaldo Carvalho de Melo 	 * This first was seen with a gcc function, _cpp_lex_token, that
1739c04409dSArnaldo Carvalho de Melo 	 * has the usual jumps:
1749c04409dSArnaldo Carvalho de Melo 	 *
1759c04409dSArnaldo Carvalho de Melo 	 *  │1159e6c: ↓ jne    115aa32 <_cpp_lex_token@@Base+0xf92>
1769c04409dSArnaldo Carvalho de Melo 	 *
1779c04409dSArnaldo Carvalho de Melo 	 * I.e. jumps to a label inside that function (_cpp_lex_token), and
1789c04409dSArnaldo Carvalho de Melo 	 * those works, but also this kind:
1799c04409dSArnaldo Carvalho de Melo 	 *
1809c04409dSArnaldo Carvalho de Melo 	 *  │1159e8b: ↓ jne    c469be <cpp_named_operator2name@@Base+0xa72>
1819c04409dSArnaldo Carvalho de Melo 	 *
1829c04409dSArnaldo Carvalho de Melo 	 *  I.e. jumps to another function, outside _cpp_lex_token, which
1839c04409dSArnaldo Carvalho de Melo 	 *  are not being correctly handled generating as a side effect references
1849c04409dSArnaldo Carvalho de Melo 	 *  to ab->offset[] entries that are set to NULL, so to make this code
1859c04409dSArnaldo Carvalho de Melo 	 *  more robust, check that here.
1869c04409dSArnaldo Carvalho de Melo 	 *
1879c04409dSArnaldo Carvalho de Melo 	 *  A proper fix for will be put in place, looking at the function
1889c04409dSArnaldo Carvalho de Melo 	 *  name right after the '<' token and probably treating this like a
1899c04409dSArnaldo Carvalho de Melo 	 *  'call' instruction.
1909c04409dSArnaldo Carvalho de Melo 	 */
1919d6bb41dSArnaldo Carvalho de Melo 	target = notes->offsets[cursor->ops.target.offset];
1929c04409dSArnaldo Carvalho de Melo 	if (target == NULL) {
1939d6bb41dSArnaldo Carvalho de Melo 		ui_helpline__printf("WARN: jump target inconsistency, press 'o', notes->offsets[%#x] = NULL\n",
1949c04409dSArnaldo Carvalho de Melo 				    cursor->ops.target.offset);
1959c04409dSArnaldo Carvalho de Melo 		return;
1969c04409dSArnaldo Carvalho de Melo 	}
1979d1ef56dSArnaldo Carvalho de Melo 
19816932d77SArnaldo Carvalho de Melo 	if (notes->options->hide_src_code) {
1994850c92eSArnaldo Carvalho de Melo 		from = cursor->al.idx_asm;
2004850c92eSArnaldo Carvalho de Melo 		to = target->idx_asm;
201a3f895beSArnaldo Carvalho de Melo 	} else {
2024850c92eSArnaldo Carvalho de Melo 		from = (u64)cursor->al.idx;
2034850c92eSArnaldo Carvalho de Melo 		to = (u64)target->idx;
204a3f895beSArnaldo Carvalho de Melo 	}
205a3f895beSArnaldo Carvalho de Melo 
2060e83a7e9SArnaldo Carvalho de Melo 	width = annotation__cycles_width(notes);
207b40982e8SJin Yao 
20878ce08dfSTaeung Song 	ui_browser__set_color(browser, HE_COLORSET_JUMP_ARROWS);
209b40982e8SJin Yao 	__ui_browser__line_arrow(browser,
2109761e86eSArnaldo Carvalho de Melo 				 pcnt_width + 2 + notes->widths.addr + width,
211c7e7b610SNamhyung Kim 				 from, to);
2127e63a13aSJin Yao 
2137efbcc8cSRavi Bangoria 	diff = is_fused(ab, cursor);
2147efbcc8cSRavi Bangoria 	if (diff > 0) {
2157e63a13aSJin Yao 		ui_browser__mark_fused(browser,
2169761e86eSArnaldo Carvalho de Melo 				       pcnt_width + 3 + notes->widths.addr + width,
2177efbcc8cSRavi Bangoria 				       from - diff, diff, to > from);
2187e63a13aSJin Yao 	}
219a3f895beSArnaldo Carvalho de Melo }
220a3f895beSArnaldo Carvalho de Melo 
221a3f895beSArnaldo Carvalho de Melo static unsigned int annotate_browser__refresh(struct ui_browser *browser)
222a3f895beSArnaldo Carvalho de Melo {
22395aa89d9SArnaldo Carvalho de Melo 	struct annotation *notes = browser__annotation(browser);
224a3f895beSArnaldo Carvalho de Melo 	int ret = ui_browser__list_head_refresh(browser);
2256af612d2SArnaldo Carvalho de Melo 	int pcnt_width = annotation__pcnt_width(notes);
226a3f895beSArnaldo Carvalho de Melo 
22716932d77SArnaldo Carvalho de Melo 	if (notes->options->jump_arrows)
2289d1ef56dSArnaldo Carvalho de Melo 		annotate_browser__draw_current_jump(browser);
229a3f895beSArnaldo Carvalho de Melo 
23083b1f2aaSArnaldo Carvalho de Melo 	ui_browser__set_color(browser, HE_COLORSET_NORMAL);
231e726c851SArnaldo Carvalho de Melo 	__ui_browser__vline(browser, pcnt_width, 0, browser->rows - 1);
232a3f895beSArnaldo Carvalho de Melo 	return ret;
233a3f895beSArnaldo Carvalho de Melo }
234a3f895beSArnaldo Carvalho de Melo 
235da06d568SHe Kuang static double disasm__cmp(struct annotation_line *a, struct annotation_line *b,
236da06d568SHe Kuang 						  int percent_type)
237c7e7b610SNamhyung Kim {
238c7e7b610SNamhyung Kim 	int i;
239c7e7b610SNamhyung Kim 
240c2f938baSJiri Olsa 	for (i = 0; i < a->data_nr; i++) {
241da06d568SHe Kuang 		if (a->data[i].percent[percent_type] == b->data[i].percent[percent_type])
242c7e7b610SNamhyung Kim 			continue;
243da06d568SHe Kuang 		return a->data[i].percent[percent_type] -
244da06d568SHe Kuang 			   b->data[i].percent[percent_type];
245c7e7b610SNamhyung Kim 	}
246c7e7b610SNamhyung Kim 	return 0;
247c7e7b610SNamhyung Kim }
248c7e7b610SNamhyung Kim 
249da06d568SHe Kuang static void disasm_rb_tree__insert(struct annotate_browser *browser,
250da06d568SHe Kuang 				struct annotation_line *al)
251aca7a94dSNamhyung Kim {
252da06d568SHe Kuang 	struct rb_root *root = &browser->entries;
25329ed6e76SArnaldo Carvalho de Melo 	struct rb_node **p = &root->rb_node;
254aca7a94dSNamhyung Kim 	struct rb_node *parent = NULL;
2553ab6db8dSJiri Olsa 	struct annotation_line *l;
256aca7a94dSNamhyung Kim 
257aca7a94dSNamhyung Kim 	while (*p != NULL) {
258aca7a94dSNamhyung Kim 		parent = *p;
2593ab6db8dSJiri Olsa 		l = rb_entry(parent, struct annotation_line, rb_node);
260c7e7b610SNamhyung Kim 
261da06d568SHe Kuang 		if (disasm__cmp(al, l, browser->opts->percent_type) < 0)
262aca7a94dSNamhyung Kim 			p = &(*p)->rb_left;
263aca7a94dSNamhyung Kim 		else
264aca7a94dSNamhyung Kim 			p = &(*p)->rb_right;
265aca7a94dSNamhyung Kim 	}
2663ab6db8dSJiri Olsa 	rb_link_node(&al->rb_node, parent, p);
2673ab6db8dSJiri Olsa 	rb_insert_color(&al->rb_node, root);
268aca7a94dSNamhyung Kim }
269aca7a94dSNamhyung Kim 
27005e8b080SArnaldo Carvalho de Melo static void annotate_browser__set_top(struct annotate_browser *browser,
271ec03a77dSJiri Olsa 				      struct annotation_line *pos, u32 idx)
272aca7a94dSNamhyung Kim {
2739b80d1f9SArnaldo Carvalho de Melo 	struct annotation *notes = browser__annotation(&browser->b);
274aca7a94dSNamhyung Kim 	unsigned back;
275aca7a94dSNamhyung Kim 
27605e8b080SArnaldo Carvalho de Melo 	ui_browser__refresh_dimensions(&browser->b);
27705e8b080SArnaldo Carvalho de Melo 	back = browser->b.height / 2;
27805e8b080SArnaldo Carvalho de Melo 	browser->b.top_idx = browser->b.index = idx;
279aca7a94dSNamhyung Kim 
28005e8b080SArnaldo Carvalho de Melo 	while (browser->b.top_idx != 0 && back != 0) {
281ec03a77dSJiri Olsa 		pos = list_entry(pos->node.prev, struct annotation_line, node);
282aca7a94dSNamhyung Kim 
2839b80d1f9SArnaldo Carvalho de Melo 		if (annotation_line__filter(pos, notes))
284aca7a94dSNamhyung Kim 			continue;
285aca7a94dSNamhyung Kim 
28605e8b080SArnaldo Carvalho de Melo 		--browser->b.top_idx;
287aca7a94dSNamhyung Kim 		--back;
288aca7a94dSNamhyung Kim 	}
289aca7a94dSNamhyung Kim 
290ec03a77dSJiri Olsa 	browser->b.top = pos;
29105e8b080SArnaldo Carvalho de Melo 	browser->b.navkeypressed = true;
292aca7a94dSNamhyung Kim }
293aca7a94dSNamhyung Kim 
294aca7a94dSNamhyung Kim static void annotate_browser__set_rb_top(struct annotate_browser *browser,
295aca7a94dSNamhyung Kim 					 struct rb_node *nd)
296aca7a94dSNamhyung Kim {
29795aa89d9SArnaldo Carvalho de Melo 	struct annotation *notes = browser__annotation(&browser->b);
2984850c92eSArnaldo Carvalho de Melo 	struct annotation_line * pos = rb_entry(nd, struct annotation_line, rb_node);
2994850c92eSArnaldo Carvalho de Melo 	u32 idx = pos->idx;
300aca7a94dSNamhyung Kim 
30116932d77SArnaldo Carvalho de Melo 	if (notes->options->hide_src_code)
3024850c92eSArnaldo Carvalho de Melo 		idx = pos->idx_asm;
303a44b45f2SArnaldo Carvalho de Melo 	annotate_browser__set_top(browser, pos, idx);
304aca7a94dSNamhyung Kim 	browser->curr_hot = nd;
305aca7a94dSNamhyung Kim }
306aca7a94dSNamhyung Kim 
307aca7a94dSNamhyung Kim static void annotate_browser__calc_percent(struct annotate_browser *browser,
30832dcd021SJiri Olsa 					   struct evsel *evsel)
309aca7a94dSNamhyung Kim {
310aca7a94dSNamhyung Kim 	struct map_symbol *ms = browser->b.priv;
311aca7a94dSNamhyung Kim 	struct symbol *sym = ms->sym;
312aca7a94dSNamhyung Kim 	struct annotation *notes = symbol__annotation(sym);
313c4c72436SJiri Olsa 	struct disasm_line *pos;
314aca7a94dSNamhyung Kim 
315aca7a94dSNamhyung Kim 	browser->entries = RB_ROOT;
316aca7a94dSNamhyung Kim 
3179b3726efSIan Rogers 	mutex_lock(&notes->lock);
318aca7a94dSNamhyung Kim 
319e425da6cSJiri Olsa 	symbol__calc_percent(sym, evsel);
320e425da6cSJiri Olsa 
321a17c4ca0SJiri Olsa 	list_for_each_entry(pos, &notes->src->source, al.node) {
322c7e7b610SNamhyung Kim 		double max_percent = 0.0;
323c7e7b610SNamhyung Kim 		int i;
324e64aa75bSNamhyung Kim 
325d5490b96SJiri Olsa 		if (pos->al.offset == -1) {
3265b12adc8SJiri Olsa 			RB_CLEAR_NODE(&pos->al.rb_node);
327e64aa75bSNamhyung Kim 			continue;
328e64aa75bSNamhyung Kim 		}
329e64aa75bSNamhyung Kim 
330c2f938baSJiri Olsa 		for (i = 0; i < pos->al.data_nr; i++) {
3316d9f0c2dSJiri Olsa 			double percent;
3320c4a5bceSMartin Liška 
3336d9f0c2dSJiri Olsa 			percent = annotation_data__percent(&pos->al.data[i],
334d4265b1aSJiri Olsa 							   browser->opts->percent_type);
3356d9f0c2dSJiri Olsa 
3366d9f0c2dSJiri Olsa 			if (max_percent < percent)
3376d9f0c2dSJiri Olsa 				max_percent = percent;
338c7e7b610SNamhyung Kim 		}
339c7e7b610SNamhyung Kim 
34037236d5eSJiri Olsa 		if (max_percent < 0.01 && pos->al.ipc == 0) {
3415b12adc8SJiri Olsa 			RB_CLEAR_NODE(&pos->al.rb_node);
342aca7a94dSNamhyung Kim 			continue;
343aca7a94dSNamhyung Kim 		}
344da06d568SHe Kuang 		disasm_rb_tree__insert(browser, &pos->al);
345aca7a94dSNamhyung Kim 	}
3469b3726efSIan Rogers 	mutex_unlock(&notes->lock);
347aca7a94dSNamhyung Kim 
348aca7a94dSNamhyung Kim 	browser->curr_hot = rb_last(&browser->entries);
349aca7a94dSNamhyung Kim }
350aca7a94dSNamhyung Kim 
3516de249d6SRiccardo Mancini static struct annotation_line *annotate_browser__find_next_asm_line(
3526de249d6SRiccardo Mancini 					struct annotate_browser *browser,
3536de249d6SRiccardo Mancini 					struct annotation_line *al)
3546de249d6SRiccardo Mancini {
3556de249d6SRiccardo Mancini 	struct annotation_line *it = al;
3566de249d6SRiccardo Mancini 
3576de249d6SRiccardo Mancini 	/* find next asm line */
3585a4451e4SRiccardo Mancini 	list_for_each_entry_continue(it, browser->b.entries, node) {
3596de249d6SRiccardo Mancini 		if (it->idx_asm >= 0)
3606de249d6SRiccardo Mancini 			return it;
3616de249d6SRiccardo Mancini 	}
3626de249d6SRiccardo Mancini 
3636de249d6SRiccardo Mancini 	/* no asm line found forwards, try backwards */
3646de249d6SRiccardo Mancini 	it = al;
3655a4451e4SRiccardo Mancini 	list_for_each_entry_continue_reverse(it, browser->b.entries, node) {
3666de249d6SRiccardo Mancini 		if (it->idx_asm >= 0)
3676de249d6SRiccardo Mancini 			return it;
3686de249d6SRiccardo Mancini 	}
3696de249d6SRiccardo Mancini 
3706de249d6SRiccardo Mancini 	/* There are no asm lines */
3716de249d6SRiccardo Mancini 	return NULL;
3726de249d6SRiccardo Mancini }
3736de249d6SRiccardo Mancini 
374aca7a94dSNamhyung Kim static bool annotate_browser__toggle_source(struct annotate_browser *browser)
375aca7a94dSNamhyung Kim {
37695aa89d9SArnaldo Carvalho de Melo 	struct annotation *notes = browser__annotation(&browser->b);
377ec03a77dSJiri Olsa 	struct annotation_line *al;
378aca7a94dSNamhyung Kim 	off_t offset = browser->b.index - browser->b.top_idx;
379aca7a94dSNamhyung Kim 
380aca7a94dSNamhyung Kim 	browser->b.seek(&browser->b, offset, SEEK_CUR);
381ec03a77dSJiri Olsa 	al = list_entry(browser->b.top, struct annotation_line, node);
382aca7a94dSNamhyung Kim 
38316932d77SArnaldo Carvalho de Melo 	if (notes->options->hide_src_code) {
3844850c92eSArnaldo Carvalho de Melo 		if (al->idx_asm < offset)
3854850c92eSArnaldo Carvalho de Melo 			offset = al->idx;
386aca7a94dSNamhyung Kim 
3871cf5f98aSArnaldo Carvalho de Melo 		browser->b.nr_entries = notes->nr_entries;
38816932d77SArnaldo Carvalho de Melo 		notes->options->hide_src_code = false;
389aca7a94dSNamhyung Kim 		browser->b.seek(&browser->b, -offset, SEEK_CUR);
3904850c92eSArnaldo Carvalho de Melo 		browser->b.top_idx = al->idx - offset;
3914850c92eSArnaldo Carvalho de Melo 		browser->b.index = al->idx;
392aca7a94dSNamhyung Kim 	} else {
3934850c92eSArnaldo Carvalho de Melo 		if (al->idx_asm < 0) {
3946de249d6SRiccardo Mancini 			/* move cursor to next asm line */
3956de249d6SRiccardo Mancini 			al = annotate_browser__find_next_asm_line(browser, al);
3966de249d6SRiccardo Mancini 			if (!al) {
397aca7a94dSNamhyung Kim 				browser->b.seek(&browser->b, -offset, SEEK_CUR);
398aca7a94dSNamhyung Kim 				return false;
399aca7a94dSNamhyung Kim 			}
4006de249d6SRiccardo Mancini 		}
401aca7a94dSNamhyung Kim 
4024850c92eSArnaldo Carvalho de Melo 		if (al->idx_asm < offset)
4034850c92eSArnaldo Carvalho de Melo 			offset = al->idx_asm;
404aca7a94dSNamhyung Kim 
4051cf5f98aSArnaldo Carvalho de Melo 		browser->b.nr_entries = notes->nr_asm_entries;
40616932d77SArnaldo Carvalho de Melo 		notes->options->hide_src_code = true;
407aca7a94dSNamhyung Kim 		browser->b.seek(&browser->b, -offset, SEEK_CUR);
4084850c92eSArnaldo Carvalho de Melo 		browser->b.top_idx = al->idx_asm - offset;
4094850c92eSArnaldo Carvalho de Melo 		browser->b.index = al->idx_asm;
410aca7a94dSNamhyung Kim 	}
411aca7a94dSNamhyung Kim 
412aca7a94dSNamhyung Kim 	return true;
413aca7a94dSNamhyung Kim }
414aca7a94dSNamhyung Kim 
4152777b81bSMartin Liska #define SYM_TITLE_MAX_SIZE (PATH_MAX + 64)
4162777b81bSMartin Liska 
4172777b81bSMartin Liska static void annotate_browser__show_full_location(struct ui_browser *browser)
4182777b81bSMartin Liska {
4192777b81bSMartin Liska 	struct annotate_browser *ab = container_of(browser, struct annotate_browser, b);
4202777b81bSMartin Liska 	struct disasm_line *cursor = disasm_line(ab->selection);
4212777b81bSMartin Liska 	struct annotation_line *al = &cursor->al;
4222777b81bSMartin Liska 
4232777b81bSMartin Liska 	if (al->offset != -1)
4242777b81bSMartin Liska 		ui_helpline__puts("Only available for source code lines.");
4252777b81bSMartin Liska 	else if (al->fileloc == NULL)
4262777b81bSMartin Liska 		ui_helpline__puts("No source file location.");
4272777b81bSMartin Liska 	else {
4282777b81bSMartin Liska 		char help_line[SYM_TITLE_MAX_SIZE];
4292777b81bSMartin Liska 		sprintf (help_line, "Source file location: %s", al->fileloc);
4302777b81bSMartin Liska 		ui_helpline__puts(help_line);
4312777b81bSMartin Liska 	}
4322777b81bSMartin Liska }
4332777b81bSMartin Liska 
4341cf5f98aSArnaldo Carvalho de Melo static void ui_browser__init_asm_mode(struct ui_browser *browser)
435e9823b21SArnaldo Carvalho de Melo {
4361cf5f98aSArnaldo Carvalho de Melo 	struct annotation *notes = browser__annotation(browser);
4371cf5f98aSArnaldo Carvalho de Melo 	ui_browser__reset_index(browser);
4381cf5f98aSArnaldo Carvalho de Melo 	browser->nr_entries = notes->nr_asm_entries;
439e9823b21SArnaldo Carvalho de Melo }
440e9823b21SArnaldo Carvalho de Melo 
44134f77abcSAdrian Hunter static int sym_title(struct symbol *sym, struct map *map, char *title,
4423e0d7953SJiri Olsa 		     size_t sz, int percent_type)
44334f77abcSAdrian Hunter {
444*63df0e4bSIan Rogers 	return snprintf(title, sz, "%s  %s [Percent: %s]", sym->name,
445*63df0e4bSIan Rogers 			map__dso(map)->long_name,
4463e0d7953SJiri Olsa 			percent_type_str(percent_type));
44734f77abcSAdrian Hunter }
44834f77abcSAdrian Hunter 
449e4cc91b8SArnaldo Carvalho de Melo /*
4504d39c89fSIngo Molnar  * This can be called from external jumps, i.e. jumps from one function
451e4cc91b8SArnaldo Carvalho de Melo  * to another, like from the kernel's entry_SYSCALL_64 function to the
452e4cc91b8SArnaldo Carvalho de Melo  * swapgs_restore_regs_and_return_to_usermode() function.
453e4cc91b8SArnaldo Carvalho de Melo  *
454e4cc91b8SArnaldo Carvalho de Melo  * So all we check here is that dl->ops.target.sym is set, if it is, just
455e4cc91b8SArnaldo Carvalho de Melo  * go to that function and when exiting from its disassembly, come back
456e4cc91b8SArnaldo Carvalho de Melo  * to the calling function.
457e4cc91b8SArnaldo Carvalho de Melo  */
458db8fd07aSNamhyung Kim static bool annotate_browser__callq(struct annotate_browser *browser,
45932dcd021SJiri Olsa 				    struct evsel *evsel,
4609783adf7SNamhyung Kim 				    struct hist_browser_timer *hbt)
461aca7a94dSNamhyung Kim {
46229754894SArnaldo Carvalho de Melo 	struct map_symbol *ms = browser->b.priv, target_ms;
4637bcbcd58SJiri Olsa 	struct disasm_line *dl = disasm_line(browser->selection);
464aca7a94dSNamhyung Kim 	struct annotation *notes;
46534f77abcSAdrian Hunter 	char title[SYM_TITLE_MAX_SIZE];
466aca7a94dSNamhyung Kim 
467696703afSArnaldo Carvalho de Melo 	if (!dl->ops.target.sym) {
468aca7a94dSNamhyung Kim 		ui_helpline__puts("The called function was not found.");
469aca7a94dSNamhyung Kim 		return true;
470aca7a94dSNamhyung Kim 	}
471aca7a94dSNamhyung Kim 
472696703afSArnaldo Carvalho de Melo 	notes = symbol__annotation(dl->ops.target.sym);
4739b3726efSIan Rogers 	mutex_lock(&notes->lock);
474aca7a94dSNamhyung Kim 
4756484d2f9SJiri Olsa 	if (!symbol__hists(dl->ops.target.sym, evsel->evlist->core.nr_entries)) {
4769b3726efSIan Rogers 		mutex_unlock(&notes->lock);
477aca7a94dSNamhyung Kim 		ui__warning("Not enough memory for annotating '%s' symbol!\n",
478696703afSArnaldo Carvalho de Melo 			    dl->ops.target.sym->name);
479aca7a94dSNamhyung Kim 		return true;
480aca7a94dSNamhyung Kim 	}
481aca7a94dSNamhyung Kim 
482f2eaea09SArnaldo Carvalho de Melo 	target_ms.maps = ms->maps;
48329754894SArnaldo Carvalho de Melo 	target_ms.map = ms->map;
48429754894SArnaldo Carvalho de Melo 	target_ms.sym = dl->ops.target.sym;
4859b3726efSIan Rogers 	mutex_unlock(&notes->lock);
48629754894SArnaldo Carvalho de Melo 	symbol__tui_annotate(&target_ms, evsel, hbt, browser->opts);
4873e0d7953SJiri Olsa 	sym_title(ms->sym, ms->map, title, sizeof(title), browser->opts->percent_type);
48834f77abcSAdrian Hunter 	ui_browser__show_title(&browser->b, title);
489aca7a94dSNamhyung Kim 	return true;
490aca7a94dSNamhyung Kim }
491aca7a94dSNamhyung Kim 
49229ed6e76SArnaldo Carvalho de Melo static
49329ed6e76SArnaldo Carvalho de Melo struct disasm_line *annotate_browser__find_offset(struct annotate_browser *browser,
494aca7a94dSNamhyung Kim 					  s64 offset, s64 *idx)
495aca7a94dSNamhyung Kim {
49695aa89d9SArnaldo Carvalho de Melo 	struct annotation *notes = browser__annotation(&browser->b);
49729ed6e76SArnaldo Carvalho de Melo 	struct disasm_line *pos;
498aca7a94dSNamhyung Kim 
499aca7a94dSNamhyung Kim 	*idx = 0;
500a17c4ca0SJiri Olsa 	list_for_each_entry(pos, &notes->src->source, al.node) {
501d5490b96SJiri Olsa 		if (pos->al.offset == offset)
502aca7a94dSNamhyung Kim 			return pos;
5039b80d1f9SArnaldo Carvalho de Melo 		if (!annotation_line__filter(&pos->al, notes))
504aca7a94dSNamhyung Kim 			++*idx;
505aca7a94dSNamhyung Kim 	}
506aca7a94dSNamhyung Kim 
507aca7a94dSNamhyung Kim 	return NULL;
508aca7a94dSNamhyung Kim }
509aca7a94dSNamhyung Kim 
510e4cc91b8SArnaldo Carvalho de Melo static bool annotate_browser__jump(struct annotate_browser *browser,
51132dcd021SJiri Olsa 				   struct evsel *evsel,
512e4cc91b8SArnaldo Carvalho de Melo 				   struct hist_browser_timer *hbt)
513aca7a94dSNamhyung Kim {
5147bcbcd58SJiri Olsa 	struct disasm_line *dl = disasm_line(browser->selection);
5155252b1aeSArnaldo Carvalho de Melo 	u64 offset;
5164f9d0325SArnaldo Carvalho de Melo 	s64 idx;
517aca7a94dSNamhyung Kim 
51875b49202SArnaldo Carvalho de Melo 	if (!ins__is_jump(&dl->ins))
519aca7a94dSNamhyung Kim 		return false;
520aca7a94dSNamhyung Kim 
521e4cc91b8SArnaldo Carvalho de Melo 	if (dl->ops.target.outside) {
522e4cc91b8SArnaldo Carvalho de Melo 		annotate_browser__callq(browser, evsel, hbt);
523e4cc91b8SArnaldo Carvalho de Melo 		return true;
524e4cc91b8SArnaldo Carvalho de Melo 	}
525e4cc91b8SArnaldo Carvalho de Melo 
5265252b1aeSArnaldo Carvalho de Melo 	offset = dl->ops.target.offset;
5275252b1aeSArnaldo Carvalho de Melo 	dl = annotate_browser__find_offset(browser, offset, &idx);
52829ed6e76SArnaldo Carvalho de Melo 	if (dl == NULL) {
5295252b1aeSArnaldo Carvalho de Melo 		ui_helpline__printf("Invalid jump offset: %" PRIx64, offset);
530aca7a94dSNamhyung Kim 		return true;
531aca7a94dSNamhyung Kim 	}
532aca7a94dSNamhyung Kim 
533ec03a77dSJiri Olsa 	annotate_browser__set_top(browser, &dl->al, idx);
534aca7a94dSNamhyung Kim 
535aca7a94dSNamhyung Kim 	return true;
536aca7a94dSNamhyung Kim }
537aca7a94dSNamhyung Kim 
53829ed6e76SArnaldo Carvalho de Melo static
5399213afbdSJiri Olsa struct annotation_line *annotate_browser__find_string(struct annotate_browser *browser,
540aca7a94dSNamhyung Kim 					  char *s, s64 *idx)
541aca7a94dSNamhyung Kim {
54295aa89d9SArnaldo Carvalho de Melo 	struct annotation *notes = browser__annotation(&browser->b);
5439213afbdSJiri Olsa 	struct annotation_line *al = browser->selection;
544aca7a94dSNamhyung Kim 
545aca7a94dSNamhyung Kim 	*idx = browser->b.index;
5469213afbdSJiri Olsa 	list_for_each_entry_continue(al, &notes->src->source, node) {
5479b80d1f9SArnaldo Carvalho de Melo 		if (annotation_line__filter(al, notes))
548aca7a94dSNamhyung Kim 			continue;
549aca7a94dSNamhyung Kim 
550aca7a94dSNamhyung Kim 		++*idx;
551aca7a94dSNamhyung Kim 
5529213afbdSJiri Olsa 		if (al->line && strstr(al->line, s) != NULL)
5539213afbdSJiri Olsa 			return al;
554aca7a94dSNamhyung Kim 	}
555aca7a94dSNamhyung Kim 
556aca7a94dSNamhyung Kim 	return NULL;
557aca7a94dSNamhyung Kim }
558aca7a94dSNamhyung Kim 
559aca7a94dSNamhyung Kim static bool __annotate_browser__search(struct annotate_browser *browser)
560aca7a94dSNamhyung Kim {
5619213afbdSJiri Olsa 	struct annotation_line *al;
562aca7a94dSNamhyung Kim 	s64 idx;
563aca7a94dSNamhyung Kim 
5649213afbdSJiri Olsa 	al = annotate_browser__find_string(browser, browser->search_bf, &idx);
5659213afbdSJiri Olsa 	if (al == NULL) {
566aca7a94dSNamhyung Kim 		ui_helpline__puts("String not found!");
567aca7a94dSNamhyung Kim 		return false;
568aca7a94dSNamhyung Kim 	}
569aca7a94dSNamhyung Kim 
570ec03a77dSJiri Olsa 	annotate_browser__set_top(browser, al, idx);
571aca7a94dSNamhyung Kim 	browser->searching_backwards = false;
572aca7a94dSNamhyung Kim 	return true;
573aca7a94dSNamhyung Kim }
574aca7a94dSNamhyung Kim 
57529ed6e76SArnaldo Carvalho de Melo static
5769213afbdSJiri Olsa struct annotation_line *annotate_browser__find_string_reverse(struct annotate_browser *browser,
577aca7a94dSNamhyung Kim 						  char *s, s64 *idx)
578aca7a94dSNamhyung Kim {
57995aa89d9SArnaldo Carvalho de Melo 	struct annotation *notes = browser__annotation(&browser->b);
5809213afbdSJiri Olsa 	struct annotation_line *al = browser->selection;
581aca7a94dSNamhyung Kim 
582aca7a94dSNamhyung Kim 	*idx = browser->b.index;
5839213afbdSJiri Olsa 	list_for_each_entry_continue_reverse(al, &notes->src->source, node) {
5849b80d1f9SArnaldo Carvalho de Melo 		if (annotation_line__filter(al, notes))
585aca7a94dSNamhyung Kim 			continue;
586aca7a94dSNamhyung Kim 
587aca7a94dSNamhyung Kim 		--*idx;
588aca7a94dSNamhyung Kim 
5899213afbdSJiri Olsa 		if (al->line && strstr(al->line, s) != NULL)
5909213afbdSJiri Olsa 			return al;
591aca7a94dSNamhyung Kim 	}
592aca7a94dSNamhyung Kim 
593aca7a94dSNamhyung Kim 	return NULL;
594aca7a94dSNamhyung Kim }
595aca7a94dSNamhyung Kim 
596aca7a94dSNamhyung Kim static bool __annotate_browser__search_reverse(struct annotate_browser *browser)
597aca7a94dSNamhyung Kim {
5989213afbdSJiri Olsa 	struct annotation_line *al;
599aca7a94dSNamhyung Kim 	s64 idx;
600aca7a94dSNamhyung Kim 
6019213afbdSJiri Olsa 	al = annotate_browser__find_string_reverse(browser, browser->search_bf, &idx);
6029213afbdSJiri Olsa 	if (al == NULL) {
603aca7a94dSNamhyung Kim 		ui_helpline__puts("String not found!");
604aca7a94dSNamhyung Kim 		return false;
605aca7a94dSNamhyung Kim 	}
606aca7a94dSNamhyung Kim 
607ec03a77dSJiri Olsa 	annotate_browser__set_top(browser, al, idx);
608aca7a94dSNamhyung Kim 	browser->searching_backwards = true;
609aca7a94dSNamhyung Kim 	return true;
610aca7a94dSNamhyung Kim }
611aca7a94dSNamhyung Kim 
612aca7a94dSNamhyung Kim static bool annotate_browser__search_window(struct annotate_browser *browser,
613aca7a94dSNamhyung Kim 					    int delay_secs)
614aca7a94dSNamhyung Kim {
615aca7a94dSNamhyung Kim 	if (ui_browser__input_window("Search", "String: ", browser->search_bf,
616aca7a94dSNamhyung Kim 				     "ENTER: OK, ESC: Cancel",
617aca7a94dSNamhyung Kim 				     delay_secs * 2) != K_ENTER ||
618aca7a94dSNamhyung Kim 	    !*browser->search_bf)
619aca7a94dSNamhyung Kim 		return false;
620aca7a94dSNamhyung Kim 
621aca7a94dSNamhyung Kim 	return true;
622aca7a94dSNamhyung Kim }
623aca7a94dSNamhyung Kim 
624aca7a94dSNamhyung Kim static bool annotate_browser__search(struct annotate_browser *browser, int delay_secs)
625aca7a94dSNamhyung Kim {
626aca7a94dSNamhyung Kim 	if (annotate_browser__search_window(browser, delay_secs))
627aca7a94dSNamhyung Kim 		return __annotate_browser__search(browser);
628aca7a94dSNamhyung Kim 
629aca7a94dSNamhyung Kim 	return false;
630aca7a94dSNamhyung Kim }
631aca7a94dSNamhyung Kim 
632aca7a94dSNamhyung Kim static bool annotate_browser__continue_search(struct annotate_browser *browser,
633aca7a94dSNamhyung Kim 					      int delay_secs)
634aca7a94dSNamhyung Kim {
635aca7a94dSNamhyung Kim 	if (!*browser->search_bf)
636aca7a94dSNamhyung Kim 		return annotate_browser__search(browser, delay_secs);
637aca7a94dSNamhyung Kim 
638aca7a94dSNamhyung Kim 	return __annotate_browser__search(browser);
639aca7a94dSNamhyung Kim }
640aca7a94dSNamhyung Kim 
641aca7a94dSNamhyung Kim static bool annotate_browser__search_reverse(struct annotate_browser *browser,
642aca7a94dSNamhyung Kim 					   int delay_secs)
643aca7a94dSNamhyung Kim {
644aca7a94dSNamhyung Kim 	if (annotate_browser__search_window(browser, delay_secs))
645aca7a94dSNamhyung Kim 		return __annotate_browser__search_reverse(browser);
646aca7a94dSNamhyung Kim 
647aca7a94dSNamhyung Kim 	return false;
648aca7a94dSNamhyung Kim }
649aca7a94dSNamhyung Kim 
650aca7a94dSNamhyung Kim static
651aca7a94dSNamhyung Kim bool annotate_browser__continue_search_reverse(struct annotate_browser *browser,
652aca7a94dSNamhyung Kim 					       int delay_secs)
653aca7a94dSNamhyung Kim {
654aca7a94dSNamhyung Kim 	if (!*browser->search_bf)
655aca7a94dSNamhyung Kim 		return annotate_browser__search_reverse(browser, delay_secs);
656aca7a94dSNamhyung Kim 
657aca7a94dSNamhyung Kim 	return __annotate_browser__search_reverse(browser);
658aca7a94dSNamhyung Kim }
659aca7a94dSNamhyung Kim 
6606920e285SArnaldo Carvalho de Melo static int annotate_browser__show(struct ui_browser *browser, char *title, const char *help)
6616920e285SArnaldo Carvalho de Melo {
6623e0d7953SJiri Olsa 	struct annotate_browser *ab = container_of(browser, struct annotate_browser, b);
6636920e285SArnaldo Carvalho de Melo 	struct map_symbol *ms = browser->priv;
6646920e285SArnaldo Carvalho de Melo 	struct symbol *sym = ms->sym;
6656920e285SArnaldo Carvalho de Melo 	char symbol_dso[SYM_TITLE_MAX_SIZE];
6666920e285SArnaldo Carvalho de Melo 
6676920e285SArnaldo Carvalho de Melo 	if (ui_browser__show(browser, title, help) < 0)
6686920e285SArnaldo Carvalho de Melo 		return -1;
6696920e285SArnaldo Carvalho de Melo 
6703e0d7953SJiri Olsa 	sym_title(sym, ms->map, symbol_dso, sizeof(symbol_dso), ab->opts->percent_type);
6716920e285SArnaldo Carvalho de Melo 
6726920e285SArnaldo Carvalho de Melo 	ui_browser__gotorc_title(browser, 0, 0);
6736920e285SArnaldo Carvalho de Melo 	ui_browser__set_color(browser, HE_COLORSET_ROOT);
6746920e285SArnaldo Carvalho de Melo 	ui_browser__write_nstring(browser, symbol_dso, browser->width + 1);
6756920e285SArnaldo Carvalho de Melo 	return 0;
6766920e285SArnaldo Carvalho de Melo }
6776920e285SArnaldo Carvalho de Melo 
6783e0d7953SJiri Olsa static void
6793e0d7953SJiri Olsa switch_percent_type(struct annotation_options *opts, bool base)
6803e0d7953SJiri Olsa {
6813e0d7953SJiri Olsa 	switch (opts->percent_type) {
6823e0d7953SJiri Olsa 	case PERCENT_HITS_LOCAL:
6833e0d7953SJiri Olsa 		if (base)
6843e0d7953SJiri Olsa 			opts->percent_type = PERCENT_PERIOD_LOCAL;
6853e0d7953SJiri Olsa 		else
6863e0d7953SJiri Olsa 			opts->percent_type = PERCENT_HITS_GLOBAL;
6873e0d7953SJiri Olsa 		break;
6883e0d7953SJiri Olsa 	case PERCENT_HITS_GLOBAL:
6893e0d7953SJiri Olsa 		if (base)
6903e0d7953SJiri Olsa 			opts->percent_type = PERCENT_PERIOD_GLOBAL;
6913e0d7953SJiri Olsa 		else
6923e0d7953SJiri Olsa 			opts->percent_type = PERCENT_HITS_LOCAL;
6933e0d7953SJiri Olsa 		break;
6943e0d7953SJiri Olsa 	case PERCENT_PERIOD_LOCAL:
6953e0d7953SJiri Olsa 		if (base)
6963e0d7953SJiri Olsa 			opts->percent_type = PERCENT_HITS_LOCAL;
6973e0d7953SJiri Olsa 		else
6983e0d7953SJiri Olsa 			opts->percent_type = PERCENT_PERIOD_GLOBAL;
6993e0d7953SJiri Olsa 		break;
7003e0d7953SJiri Olsa 	case PERCENT_PERIOD_GLOBAL:
7013e0d7953SJiri Olsa 		if (base)
7023e0d7953SJiri Olsa 			opts->percent_type = PERCENT_HITS_GLOBAL;
7033e0d7953SJiri Olsa 		else
7043e0d7953SJiri Olsa 			opts->percent_type = PERCENT_PERIOD_LOCAL;
7053e0d7953SJiri Olsa 		break;
7063e0d7953SJiri Olsa 	default:
7073e0d7953SJiri Olsa 		WARN_ON(1);
7083e0d7953SJiri Olsa 	}
7093e0d7953SJiri Olsa }
7103e0d7953SJiri Olsa 
711db8fd07aSNamhyung Kim static int annotate_browser__run(struct annotate_browser *browser,
71232dcd021SJiri Olsa 				 struct evsel *evsel,
7139783adf7SNamhyung Kim 				 struct hist_browser_timer *hbt)
714aca7a94dSNamhyung Kim {
715aca7a94dSNamhyung Kim 	struct rb_node *nd = NULL;
7166920e285SArnaldo Carvalho de Melo 	struct hists *hists = evsel__hists(evsel);
71705e8b080SArnaldo Carvalho de Melo 	struct map_symbol *ms = browser->b.priv;
718aca7a94dSNamhyung Kim 	struct symbol *sym = ms->sym;
71916932d77SArnaldo Carvalho de Melo 	struct annotation *notes = symbol__annotation(ms->sym);
72054e7a4e8SArnaldo Carvalho de Melo 	const char *help = "Press 'h' for help on key bindings";
7219783adf7SNamhyung Kim 	int delay_secs = hbt ? hbt->refresh : 0;
7226920e285SArnaldo Carvalho de Melo 	char title[256];
723aca7a94dSNamhyung Kim 	int key;
724aca7a94dSNamhyung Kim 
7250683d13cSJiri Olsa 	hists__scnprintf_title(hists, title, sizeof(title));
7266920e285SArnaldo Carvalho de Melo 	if (annotate_browser__show(&browser->b, title, help) < 0)
727aca7a94dSNamhyung Kim 		return -1;
728aca7a94dSNamhyung Kim 
729db8fd07aSNamhyung Kim 	annotate_browser__calc_percent(browser, evsel);
730aca7a94dSNamhyung Kim 
73105e8b080SArnaldo Carvalho de Melo 	if (browser->curr_hot) {
73205e8b080SArnaldo Carvalho de Melo 		annotate_browser__set_rb_top(browser, browser->curr_hot);
73305e8b080SArnaldo Carvalho de Melo 		browser->b.navkeypressed = false;
734aca7a94dSNamhyung Kim 	}
735aca7a94dSNamhyung Kim 
73605e8b080SArnaldo Carvalho de Melo 	nd = browser->curr_hot;
737aca7a94dSNamhyung Kim 
738aca7a94dSNamhyung Kim 	while (1) {
73905e8b080SArnaldo Carvalho de Melo 		key = ui_browser__run(&browser->b, delay_secs);
740aca7a94dSNamhyung Kim 
741aca7a94dSNamhyung Kim 		if (delay_secs != 0) {
742db8fd07aSNamhyung Kim 			annotate_browser__calc_percent(browser, evsel);
743aca7a94dSNamhyung Kim 			/*
744aca7a94dSNamhyung Kim 			 * Current line focus got out of the list of most active
745aca7a94dSNamhyung Kim 			 * lines, NULL it so that if TAB|UNTAB is pressed, we
746aca7a94dSNamhyung Kim 			 * move to curr_hot (current hottest line).
747aca7a94dSNamhyung Kim 			 */
748aca7a94dSNamhyung Kim 			if (nd != NULL && RB_EMPTY_NODE(nd))
749aca7a94dSNamhyung Kim 				nd = NULL;
750aca7a94dSNamhyung Kim 		}
751aca7a94dSNamhyung Kim 
752aca7a94dSNamhyung Kim 		switch (key) {
753aca7a94dSNamhyung Kim 		case K_TIMER:
7549783adf7SNamhyung Kim 			if (hbt)
7559783adf7SNamhyung Kim 				hbt->timer(hbt->arg);
756aca7a94dSNamhyung Kim 
7576920e285SArnaldo Carvalho de Melo 			if (delay_secs != 0) {
75838fe0e01SJiri Olsa 				symbol__annotate_decay_histogram(sym, evsel->core.idx);
7596920e285SArnaldo Carvalho de Melo 				hists__scnprintf_title(hists, title, sizeof(title));
7606920e285SArnaldo Carvalho de Melo 				annotate_browser__show(&browser->b, title, help);
7616920e285SArnaldo Carvalho de Melo 			}
762aca7a94dSNamhyung Kim 			continue;
763aca7a94dSNamhyung Kim 		case K_TAB:
764aca7a94dSNamhyung Kim 			if (nd != NULL) {
765aca7a94dSNamhyung Kim 				nd = rb_prev(nd);
766aca7a94dSNamhyung Kim 				if (nd == NULL)
76705e8b080SArnaldo Carvalho de Melo 					nd = rb_last(&browser->entries);
768aca7a94dSNamhyung Kim 			} else
76905e8b080SArnaldo Carvalho de Melo 				nd = browser->curr_hot;
770aca7a94dSNamhyung Kim 			break;
771aca7a94dSNamhyung Kim 		case K_UNTAB:
772d4913cbdSMarkus Trippelsdorf 			if (nd != NULL) {
773aca7a94dSNamhyung Kim 				nd = rb_next(nd);
774aca7a94dSNamhyung Kim 				if (nd == NULL)
77505e8b080SArnaldo Carvalho de Melo 					nd = rb_first(&browser->entries);
776d4913cbdSMarkus Trippelsdorf 			} else
77705e8b080SArnaldo Carvalho de Melo 				nd = browser->curr_hot;
778aca7a94dSNamhyung Kim 			break;
77954e7a4e8SArnaldo Carvalho de Melo 		case K_F1:
780aca7a94dSNamhyung Kim 		case 'h':
78105e8b080SArnaldo Carvalho de Melo 			ui_browser__help_window(&browser->b,
78254e7a4e8SArnaldo Carvalho de Melo 		"UP/DOWN/PGUP\n"
78354e7a4e8SArnaldo Carvalho de Melo 		"PGDN/SPACE    Navigate\n"
78454e7a4e8SArnaldo Carvalho de Melo 		"q/ESC/CTRL+C  Exit\n\n"
7857727a925SArnaldo Carvalho de Melo 		"ENTER         Go to target\n"
7867727a925SArnaldo Carvalho de Melo 		"ESC           Exit\n"
787eba9fac0SArnaldo Carvalho de Melo 		"H             Go to hottest instruction\n"
788eba9fac0SArnaldo Carvalho de Melo 		"TAB/shift+TAB Cycle thru hottest instructions\n"
78954e7a4e8SArnaldo Carvalho de Melo 		"j             Toggle showing jump to target arrows\n"
79054e7a4e8SArnaldo Carvalho de Melo 		"J             Toggle showing number of jump sources on targets\n"
79154e7a4e8SArnaldo Carvalho de Melo 		"n             Search next string\n"
79254e7a4e8SArnaldo Carvalho de Melo 		"o             Toggle disassembler output/simplified view\n"
79351f39603SArnaldo Carvalho de Melo 		"O             Bump offset level (jump targets -> +call -> all -> cycle thru)\n"
79454e7a4e8SArnaldo Carvalho de Melo 		"s             Toggle source code view\n"
7953a555c77STaeung Song 		"t             Circulate percent, total period, samples view\n"
7963e71fc03SJin Yao 		"c             Show min/max cycle\n"
79754e7a4e8SArnaldo Carvalho de Melo 		"/             Search string\n"
798e592488cSAndi Kleen 		"k             Toggle line numbers\n"
7992777b81bSMartin Liska 		"l             Show full source file location\n"
800d9bd7665SArnaldo Carvalho de Melo 		"P             Print to [symbol_name].annotation file.\n"
80179ee47faSFeng Tang 		"r             Run available scripts\n"
8023e0d7953SJiri Olsa 		"p             Toggle percent type [local/global]\n"
8033e0d7953SJiri Olsa 		"b             Toggle percent base [period/hits]\n"
8047d18a824SNamhyung Kim 		"?             Search string backwards\n"
8057d18a824SNamhyung Kim 		"f             Toggle showing offsets to full address\n");
80654e7a4e8SArnaldo Carvalho de Melo 			continue;
80779ee47faSFeng Tang 		case 'r':
8086f3da20eSAndi Kleen 			script_browse(NULL, NULL);
80954cf752cSRavi Bangoria 			annotate_browser__show(&browser->b, title, help);
81079ee47faSFeng Tang 			continue;
811e592488cSAndi Kleen 		case 'k':
81216932d77SArnaldo Carvalho de Melo 			notes->options->show_linenr = !notes->options->show_linenr;
8134fd00847SMartin Liška 			continue;
8142777b81bSMartin Liska 		case 'l':
8152777b81bSMartin Liska 			annotate_browser__show_full_location (&browser->b);
8162777b81bSMartin Liska 			continue;
81754e7a4e8SArnaldo Carvalho de Melo 		case 'H':
81805e8b080SArnaldo Carvalho de Melo 			nd = browser->curr_hot;
819aca7a94dSNamhyung Kim 			break;
820aca7a94dSNamhyung Kim 		case 's':
82105e8b080SArnaldo Carvalho de Melo 			if (annotate_browser__toggle_source(browser))
822aca7a94dSNamhyung Kim 				ui_helpline__puts(help);
823aca7a94dSNamhyung Kim 			continue;
824aca7a94dSNamhyung Kim 		case 'o':
82516932d77SArnaldo Carvalho de Melo 			notes->options->use_offset = !notes->options->use_offset;
8269761e86eSArnaldo Carvalho de Melo 			annotation__update_column_widths(notes);
827aca7a94dSNamhyung Kim 			continue;
82851f39603SArnaldo Carvalho de Melo 		case 'O':
82951f39603SArnaldo Carvalho de Melo 			if (++notes->options->offset_level > ANNOTATION__MAX_OFFSET_LEVEL)
83051f39603SArnaldo Carvalho de Melo 				notes->options->offset_level = ANNOTATION__MIN_OFFSET_LEVEL;
83151f39603SArnaldo Carvalho de Melo 			continue;
8329d1ef56dSArnaldo Carvalho de Melo 		case 'j':
83316932d77SArnaldo Carvalho de Melo 			notes->options->jump_arrows = !notes->options->jump_arrows;
8349d1ef56dSArnaldo Carvalho de Melo 			continue;
8352402e4a9SArnaldo Carvalho de Melo 		case 'J':
83616932d77SArnaldo Carvalho de Melo 			notes->options->show_nr_jumps = !notes->options->show_nr_jumps;
8379761e86eSArnaldo Carvalho de Melo 			annotation__update_column_widths(notes);
838e9823b21SArnaldo Carvalho de Melo 			continue;
839aca7a94dSNamhyung Kim 		case '/':
84005e8b080SArnaldo Carvalho de Melo 			if (annotate_browser__search(browser, delay_secs)) {
841aca7a94dSNamhyung Kim show_help:
842aca7a94dSNamhyung Kim 				ui_helpline__puts(help);
843aca7a94dSNamhyung Kim 			}
844aca7a94dSNamhyung Kim 			continue;
845aca7a94dSNamhyung Kim 		case 'n':
84605e8b080SArnaldo Carvalho de Melo 			if (browser->searching_backwards ?
84705e8b080SArnaldo Carvalho de Melo 			    annotate_browser__continue_search_reverse(browser, delay_secs) :
84805e8b080SArnaldo Carvalho de Melo 			    annotate_browser__continue_search(browser, delay_secs))
849aca7a94dSNamhyung Kim 				goto show_help;
850aca7a94dSNamhyung Kim 			continue;
851aca7a94dSNamhyung Kim 		case '?':
85205e8b080SArnaldo Carvalho de Melo 			if (annotate_browser__search_reverse(browser, delay_secs))
853aca7a94dSNamhyung Kim 				goto show_help;
854aca7a94dSNamhyung Kim 			continue;
855e9823b21SArnaldo Carvalho de Melo 		case 'D': {
856e9823b21SArnaldo Carvalho de Melo 			static int seq;
857e9823b21SArnaldo Carvalho de Melo 			ui_helpline__pop();
858e9823b21SArnaldo Carvalho de Melo 			ui_helpline__fpush("%d: nr_ent=%d, height=%d, idx=%d, top_idx=%d, nr_asm_entries=%d",
85905e8b080SArnaldo Carvalho de Melo 					   seq++, browser->b.nr_entries,
86005e8b080SArnaldo Carvalho de Melo 					   browser->b.height,
86105e8b080SArnaldo Carvalho de Melo 					   browser->b.index,
86205e8b080SArnaldo Carvalho de Melo 					   browser->b.top_idx,
8631cf5f98aSArnaldo Carvalho de Melo 					   notes->nr_asm_entries);
864e9823b21SArnaldo Carvalho de Melo 		}
865e9823b21SArnaldo Carvalho de Melo 			continue;
866aca7a94dSNamhyung Kim 		case K_ENTER:
867aca7a94dSNamhyung Kim 		case K_RIGHT:
8687bcbcd58SJiri Olsa 		{
8697bcbcd58SJiri Olsa 			struct disasm_line *dl = disasm_line(browser->selection);
8707bcbcd58SJiri Olsa 
87105e8b080SArnaldo Carvalho de Melo 			if (browser->selection == NULL)
872aca7a94dSNamhyung Kim 				ui_helpline__puts("Huh? No selection. Report to linux-kernel@vger.kernel.org");
8737bcbcd58SJiri Olsa 			else if (browser->selection->offset == -1)
874aca7a94dSNamhyung Kim 				ui_helpline__puts("Actions are only available for assembly lines.");
8757bcbcd58SJiri Olsa 			else if (!dl->ins.ops)
876c4cceae3SArnaldo Carvalho de Melo 				goto show_sup_ins;
8777bcbcd58SJiri Olsa 			else if (ins__is_ret(&dl->ins))
878c4cceae3SArnaldo Carvalho de Melo 				goto out;
879e4cc91b8SArnaldo Carvalho de Melo 			else if (!(annotate_browser__jump(browser, evsel, hbt) ||
880db8fd07aSNamhyung Kim 				     annotate_browser__callq(browser, evsel, hbt))) {
881c4cceae3SArnaldo Carvalho de Melo show_sup_ins:
8826ef94929SNaveen N. Rao 				ui_helpline__puts("Actions are only available for function call/return & jump/branch instructions.");
883c4cceae3SArnaldo Carvalho de Melo 			}
884aca7a94dSNamhyung Kim 			continue;
8857bcbcd58SJiri Olsa 		}
886d9bd7665SArnaldo Carvalho de Melo 		case 'P':
8874c650ddcSJiri Olsa 			map_symbol__annotation_dump(ms, evsel, browser->opts);
888d9bd7665SArnaldo Carvalho de Melo 			continue;
8890c4a5bceSMartin Liška 		case 't':
89068aac855SRavi Bangoria 			if (symbol_conf.show_total_period) {
89168aac855SRavi Bangoria 				symbol_conf.show_total_period = false;
89246ccb442SRavi Bangoria 				symbol_conf.show_nr_samples = true;
89346ccb442SRavi Bangoria 			} else if (symbol_conf.show_nr_samples)
89446ccb442SRavi Bangoria 				symbol_conf.show_nr_samples = false;
8953a555c77STaeung Song 			else
89668aac855SRavi Bangoria 				symbol_conf.show_total_period = true;
8979761e86eSArnaldo Carvalho de Melo 			annotation__update_column_widths(notes);
8980c4a5bceSMartin Liška 			continue;
8993e71fc03SJin Yao 		case 'c':
9003e71fc03SJin Yao 			if (notes->options->show_minmax_cycle)
9013e71fc03SJin Yao 				notes->options->show_minmax_cycle = false;
9023e71fc03SJin Yao 			else
9033e71fc03SJin Yao 				notes->options->show_minmax_cycle = true;
9043e71fc03SJin Yao 			annotation__update_column_widths(notes);
9053e71fc03SJin Yao 			continue;
9063e0d7953SJiri Olsa 		case 'p':
9073e0d7953SJiri Olsa 		case 'b':
9083e0d7953SJiri Olsa 			switch_percent_type(browser->opts, key == 'b');
9093e0d7953SJiri Olsa 			hists__scnprintf_title(hists, title, sizeof(title));
9103e0d7953SJiri Olsa 			annotate_browser__show(&browser->b, title, help);
9113e0d7953SJiri Olsa 			continue;
9127d18a824SNamhyung Kim 		case 'f':
9137d18a824SNamhyung Kim 			annotation__toggle_full_addr(notes, ms);
9147d18a824SNamhyung Kim 			continue;
915aca7a94dSNamhyung Kim 		case K_LEFT:
916aca7a94dSNamhyung Kim 		case K_ESC:
917aca7a94dSNamhyung Kim 		case 'q':
918aca7a94dSNamhyung Kim 		case CTRL('c'):
919aca7a94dSNamhyung Kim 			goto out;
920aca7a94dSNamhyung Kim 		default:
921aca7a94dSNamhyung Kim 			continue;
922aca7a94dSNamhyung Kim 		}
923aca7a94dSNamhyung Kim 
924aca7a94dSNamhyung Kim 		if (nd != NULL)
92505e8b080SArnaldo Carvalho de Melo 			annotate_browser__set_rb_top(browser, nd);
926aca7a94dSNamhyung Kim 	}
927aca7a94dSNamhyung Kim out:
92805e8b080SArnaldo Carvalho de Melo 	ui_browser__hide(&browser->b);
929aca7a94dSNamhyung Kim 	return key;
930aca7a94dSNamhyung Kim }
931aca7a94dSNamhyung Kim 
93232dcd021SJiri Olsa int map_symbol__tui_annotate(struct map_symbol *ms, struct evsel *evsel,
933cd0cccbaSArnaldo Carvalho de Melo 			     struct hist_browser_timer *hbt,
934cd0cccbaSArnaldo Carvalho de Melo 			     struct annotation_options *opts)
935d5dbc518SArnaldo Carvalho de Melo {
93629754894SArnaldo Carvalho de Melo 	return symbol__tui_annotate(ms, evsel, hbt, opts);
937d5dbc518SArnaldo Carvalho de Melo }
938d5dbc518SArnaldo Carvalho de Melo 
93932dcd021SJiri Olsa int hist_entry__tui_annotate(struct hist_entry *he, struct evsel *evsel,
940cd0cccbaSArnaldo Carvalho de Melo 			     struct hist_browser_timer *hbt,
941cd0cccbaSArnaldo Carvalho de Melo 			     struct annotation_options *opts)
942aca7a94dSNamhyung Kim {
943ed426915SNamhyung Kim 	/* reset abort key so that it can get Ctrl-C as a key */
944ed426915SNamhyung Kim 	SLang_reset_tty();
945ed426915SNamhyung Kim 	SLang_init_tty(0, 0, 0);
946ed426915SNamhyung Kim 
947cd0cccbaSArnaldo Carvalho de Melo 	return map_symbol__tui_annotate(&he->ms, evsel, hbt, opts);
948aca7a94dSNamhyung Kim }
949aca7a94dSNamhyung Kim 
95029754894SArnaldo Carvalho de Melo int symbol__tui_annotate(struct map_symbol *ms, struct evsel *evsel,
951cd0cccbaSArnaldo Carvalho de Melo 			 struct hist_browser_timer *hbt,
952cd0cccbaSArnaldo Carvalho de Melo 			 struct annotation_options *opts)
953aca7a94dSNamhyung Kim {
95429754894SArnaldo Carvalho de Melo 	struct symbol *sym = ms->sym;
9559d6bb41dSArnaldo Carvalho de Melo 	struct annotation *notes = symbol__annotation(sym);
956aca7a94dSNamhyung Kim 	struct annotate_browser browser = {
957aca7a94dSNamhyung Kim 		.b = {
958a3f895beSArnaldo Carvalho de Melo 			.refresh = annotate_browser__refresh,
959aca7a94dSNamhyung Kim 			.seek	 = ui_browser__list_head_seek,
960aca7a94dSNamhyung Kim 			.write	 = annotate_browser__write,
96129ed6e76SArnaldo Carvalho de Melo 			.filter  = disasm_line__filter,
9626920e285SArnaldo Carvalho de Melo 			.extra_title_lines = 1, /* for hists__scnprintf_title() */
96329754894SArnaldo Carvalho de Melo 			.priv	 = ms,
964aca7a94dSNamhyung Kim 			.use_navkeypressed = true,
965aca7a94dSNamhyung Kim 		},
966cd0cccbaSArnaldo Carvalho de Melo 		.opts = opts,
967aca7a94dSNamhyung Kim 	};
968*63df0e4bSIan Rogers 	struct dso *dso;
969ee51d851SArnaldo Carvalho de Melo 	int ret = -1, err;
970d5962fb7SDario Petrillo 	int not_annotated = list_empty(&notes->src->source);
971aca7a94dSNamhyung Kim 
972aca7a94dSNamhyung Kim 	if (sym == NULL)
973aca7a94dSNamhyung Kim 		return -1;
974aca7a94dSNamhyung Kim 
975*63df0e4bSIan Rogers 	dso = map__dso(ms->map);
976*63df0e4bSIan Rogers 	if (dso->annotate_warned)
977aca7a94dSNamhyung Kim 		return -1;
978aca7a94dSNamhyung Kim 
979d5962fb7SDario Petrillo 	if (not_annotated) {
98029754894SArnaldo Carvalho de Melo 		err = symbol__annotate2(ms, evsel, opts, &browser.arch);
981ee51d851SArnaldo Carvalho de Melo 		if (err) {
982ee51d851SArnaldo Carvalho de Melo 			char msg[BUFSIZ];
983*63df0e4bSIan Rogers 			dso->annotate_warned = true;
98429754894SArnaldo Carvalho de Melo 			symbol__strerror_disassemble(ms, err, msg, sizeof(msg));
985ee51d851SArnaldo Carvalho de Melo 			ui__error("Couldn't annotate %s:\n%s", sym->name, msg);
986b793a401SArnaldo Carvalho de Melo 			goto out_free_offsets;
987aca7a94dSNamhyung Kim 		}
988d5962fb7SDario Petrillo 	}
989aca7a94dSNamhyung Kim 
9907727a925SArnaldo Carvalho de Melo 	ui_helpline__push("Press ESC to exit");
991aca7a94dSNamhyung Kim 
9925bc49f61SArnaldo Carvalho de Melo 	browser.b.width = notes->max_line_len;
9931cf5f98aSArnaldo Carvalho de Melo 	browser.b.nr_entries = notes->nr_entries;
994aca7a94dSNamhyung Kim 	browser.b.entries = &notes->src->source,
995aca7a94dSNamhyung Kim 	browser.b.width += 18; /* Percentage */
996e9823b21SArnaldo Carvalho de Melo 
99716932d77SArnaldo Carvalho de Melo 	if (notes->options->hide_src_code)
9981cf5f98aSArnaldo Carvalho de Melo 		ui_browser__init_asm_mode(&browser.b);
999e9823b21SArnaldo Carvalho de Melo 
1000db8fd07aSNamhyung Kim 	ret = annotate_browser__run(&browser, evsel, hbt);
1001f8eb37bdSJiri Olsa 
1002d5962fb7SDario Petrillo 	if(not_annotated)
1003f8eb37bdSJiri Olsa 		annotated_source__purge(notes->src);
1004b793a401SArnaldo Carvalho de Melo 
1005b793a401SArnaldo Carvalho de Melo out_free_offsets:
1006d5962fb7SDario Petrillo 	if(not_annotated)
10079d6bb41dSArnaldo Carvalho de Melo 		zfree(&notes->offsets);
1008aca7a94dSNamhyung Kim 	return ret;
1009aca7a94dSNamhyung Kim }
1010