xref: /linux/tools/perf/ui/browsers/annotate.c (revision 9761e86e36c0957e76c1b7c328953687a1a38655)
1b2441318SGreg Kroah-Hartman // SPDX-License-Identifier: GPL-2.0
2aca7a94dSNamhyung Kim #include "../../util/util.h"
3aca7a94dSNamhyung Kim #include "../browser.h"
4aca7a94dSNamhyung Kim #include "../helpline.h"
5aca7a94dSNamhyung Kim #include "../ui.h"
6aca7a94dSNamhyung Kim #include "../util.h"
7aca7a94dSNamhyung Kim #include "../../util/annotate.h"
8aca7a94dSNamhyung Kim #include "../../util/hist.h"
9aca7a94dSNamhyung Kim #include "../../util/sort.h"
10aca7a94dSNamhyung Kim #include "../../util/symbol.h"
11db8fd07aSNamhyung Kim #include "../../util/evsel.h"
1241840d21STaeung Song #include "../../util/config.h"
1369fb09f6SJin Yao #include "../../util/evlist.h"
14fd20e811SArnaldo Carvalho de Melo #include <inttypes.h>
15aca7a94dSNamhyung Kim #include <pthread.h>
16877a7a11SArnaldo Carvalho de Melo #include <linux/kernel.h>
178e99b6d4SArnaldo Carvalho de Melo #include <linux/string.h>
18b0742e90SArnaldo Carvalho de Melo #include <sys/ttydefaults.h>
19aca7a94dSNamhyung Kim 
200c4a5bceSMartin Liška struct disasm_line_samples {
210c4a5bceSMartin Liška 	double		      percent;
22bb79a232SArnaldo Carvalho de Melo 	struct sym_hist_entry he;
230c4a5bceSMartin Liška };
240c4a5bceSMartin Liška 
2598bc80b0SArnaldo Carvalho de Melo static struct annotation_options annotate_browser__opts = {
26e9823b21SArnaldo Carvalho de Melo 	.use_offset	= true,
27e9823b21SArnaldo Carvalho de Melo 	.jump_arrows	= true,
28e9823b21SArnaldo Carvalho de Melo };
29e9823b21SArnaldo Carvalho de Melo 
30dcaa3948SJin Yao struct arch;
31dcaa3948SJin Yao 
32aca7a94dSNamhyung Kim struct annotate_browser {
33aca7a94dSNamhyung Kim 	struct ui_browser	    b;
34aca7a94dSNamhyung Kim 	struct rb_root		    entries;
35aca7a94dSNamhyung Kim 	struct rb_node		   *curr_hot;
367bcbcd58SJiri Olsa 	struct annotation_line	   *selection;
37dcaa3948SJin Yao 	struct arch		   *arch;
38aca7a94dSNamhyung Kim 	bool			    searching_backwards;
39aca7a94dSNamhyung Kim 	char			    search_bf[128];
40aca7a94dSNamhyung Kim };
41aca7a94dSNamhyung Kim 
4295aa89d9SArnaldo Carvalho de Melo static inline struct annotation *browser__annotation(struct ui_browser *browser)
4395aa89d9SArnaldo Carvalho de Melo {
4495aa89d9SArnaldo Carvalho de Melo 	struct map_symbol *ms = browser->priv;
4595aa89d9SArnaldo Carvalho de Melo 	return symbol__annotation(ms->sym);
4695aa89d9SArnaldo Carvalho de Melo }
4795aa89d9SArnaldo Carvalho de Melo 
4816932d77SArnaldo Carvalho de Melo static bool disasm_line__filter(struct ui_browser *browser, void *entry)
49aca7a94dSNamhyung Kim {
5095aa89d9SArnaldo Carvalho de Melo 	struct annotation *notes = browser__annotation(browser);
5116932d77SArnaldo Carvalho de Melo 
5216932d77SArnaldo Carvalho de Melo 	if (notes->options->hide_src_code) {
53d5490b96SJiri Olsa 		struct annotation_line *al = list_entry(entry, struct annotation_line, node);
54d5490b96SJiri Olsa 
55d5490b96SJiri Olsa 		return al->offset == -1;
56aca7a94dSNamhyung Kim 	}
57aca7a94dSNamhyung Kim 
58aca7a94dSNamhyung Kim 	return false;
59aca7a94dSNamhyung Kim }
60aca7a94dSNamhyung Kim 
6127feb761SArnaldo Carvalho de Melo static int ui_browser__jumps_percent_color(struct ui_browser *browser, int nr, bool current)
622402e4a9SArnaldo Carvalho de Melo {
6327feb761SArnaldo Carvalho de Melo 	struct annotation *notes = browser__annotation(browser);
64bc1c0f3dSArnaldo Carvalho de Melo 
6527feb761SArnaldo Carvalho de Melo 	if (current && (!browser->use_navkeypressed || browser->navkeypressed))
662402e4a9SArnaldo Carvalho de Melo 		return HE_COLORSET_SELECTED;
67bc1c0f3dSArnaldo Carvalho de Melo 	if (nr == notes->max_jump_sources)
682402e4a9SArnaldo Carvalho de Melo 		return HE_COLORSET_TOP;
692402e4a9SArnaldo Carvalho de Melo 	if (nr > 1)
702402e4a9SArnaldo Carvalho de Melo 		return HE_COLORSET_MEDIUM;
712402e4a9SArnaldo Carvalho de Melo 	return HE_COLORSET_NORMAL;
722402e4a9SArnaldo Carvalho de Melo }
732402e4a9SArnaldo Carvalho de Melo 
7427feb761SArnaldo Carvalho de Melo static int ui_browser__set_jumps_percent_color(struct ui_browser *browser, int nr, bool current)
752402e4a9SArnaldo Carvalho de Melo {
7627feb761SArnaldo Carvalho de Melo 	 int color = ui_browser__jumps_percent_color(browser, nr, current);
7727feb761SArnaldo Carvalho de Melo 	 return ui_browser__set_color(browser, color);
782402e4a9SArnaldo Carvalho de Melo }
792402e4a9SArnaldo Carvalho de Melo 
80a5433b3eSJiri Olsa static void disasm_line__write(struct disasm_line *dl, struct ui_browser *browser,
81a5433b3eSJiri Olsa 			       char *bf, size_t size)
82aca7a94dSNamhyung Kim {
8395aa89d9SArnaldo Carvalho de Melo 	struct annotation *notes = browser__annotation(browser);
8416932d77SArnaldo Carvalho de Melo 
8575b49202SArnaldo Carvalho de Melo 	if (dl->ins.ops && dl->ins.ops->scnprintf) {
8675b49202SArnaldo Carvalho de Melo 		if (ins__is_jump(&dl->ins)) {
87d5490b96SJiri Olsa 			bool fwd = dl->ops.target.offset > dl->al.offset;
8851a0d455SArnaldo Carvalho de Melo 
8905e8b080SArnaldo Carvalho de Melo 			ui_browser__write_graph(browser, fwd ? SLSMG_DARROW_CHAR :
9051a0d455SArnaldo Carvalho de Melo 							    SLSMG_UARROW_CHAR);
9151a0d455SArnaldo Carvalho de Melo 			SLsmg_write_char(' ');
9275b49202SArnaldo Carvalho de Melo 		} else if (ins__is_call(&dl->ins)) {
9305e8b080SArnaldo Carvalho de Melo 			ui_browser__write_graph(browser, SLSMG_RARROW_CHAR);
9488298f5aSArnaldo Carvalho de Melo 			SLsmg_write_char(' ');
9575b49202SArnaldo Carvalho de Melo 		} else if (ins__is_ret(&dl->ins)) {
9605e8b080SArnaldo Carvalho de Melo 			ui_browser__write_graph(browser, SLSMG_LARROW_CHAR);
974ea08b52SArnaldo Carvalho de Melo 			SLsmg_write_char(' ');
986ef94929SNaveen N. Rao 		} else {
996ef94929SNaveen N. Rao 			ui_browser__write_nstring(browser, " ", 2);
1004ea08b52SArnaldo Carvalho de Melo 		}
1016ef94929SNaveen N. Rao 	} else {
1026ef94929SNaveen N. Rao 		ui_browser__write_nstring(browser, " ", 2);
1034ea08b52SArnaldo Carvalho de Melo 	}
1044ea08b52SArnaldo Carvalho de Melo 
10516932d77SArnaldo Carvalho de Melo 	disasm_line__scnprintf(dl, bf, size, !notes->options->use_offset);
106a5433b3eSJiri Olsa }
107a5433b3eSJiri Olsa 
108a5433b3eSJiri Olsa static void annotate_browser__write(struct ui_browser *browser, void *entry, int row)
109a5433b3eSJiri Olsa {
110a5433b3eSJiri Olsa 	struct annotate_browser *ab = container_of(browser, struct annotate_browser, b);
11195aa89d9SArnaldo Carvalho de Melo 	struct annotation *notes = browser__annotation(browser);
112a5433b3eSJiri Olsa 	struct annotation_line *al = list_entry(entry, struct annotation_line, node);
113a5433b3eSJiri Olsa 	bool current_entry = ui_browser__is_current_entry(browser, row);
11416932d77SArnaldo Carvalho de Melo 	bool change_color = (!notes->options->hide_src_code &&
115a5433b3eSJiri Olsa 			     (!current_entry || (browser->use_navkeypressed &&
116a5433b3eSJiri Olsa 					         !browser->navkeypressed)));
117a5433b3eSJiri Olsa 	int width = browser->width, printed;
1186af612d2SArnaldo Carvalho de Melo 	int i, pcnt_width = annotation__pcnt_width(notes),
1190e83a7e9SArnaldo Carvalho de Melo 	       cycles_width = annotation__cycles_width(notes);
120a5433b3eSJiri Olsa 	double percent_max = 0.0;
121a5433b3eSJiri Olsa 	char bf[256];
122a5433b3eSJiri Olsa 	bool show_title = false;
123a5433b3eSJiri Olsa 
1240553e83dSArnaldo Carvalho de Melo 	for (i = 0; i < notes->nr_events; i++) {
125a5433b3eSJiri Olsa 		if (al->samples[i].percent > percent_max)
126a5433b3eSJiri Olsa 			percent_max = al->samples[i].percent;
127a5433b3eSJiri Olsa 	}
128a5433b3eSJiri Olsa 
129a5433b3eSJiri Olsa 	if ((row == 0) && (al->offset == -1 || percent_max == 0.0)) {
1300e83a7e9SArnaldo Carvalho de Melo 		if (notes->have_cycles) {
131a5433b3eSJiri Olsa 			if (al->ipc == 0.0 && al->cycles == 0)
132a5433b3eSJiri Olsa 				show_title = true;
133a5433b3eSJiri Olsa 		} else
134a5433b3eSJiri Olsa 			show_title = true;
135a5433b3eSJiri Olsa 	}
136a5433b3eSJiri Olsa 
137a5433b3eSJiri Olsa 	if (al->offset != -1 && percent_max != 0.0) {
1380553e83dSArnaldo Carvalho de Melo 		for (i = 0; i < notes->nr_events; i++) {
139a5433b3eSJiri Olsa 			ui_browser__set_percent_color(browser,
140a5433b3eSJiri Olsa 						al->samples[i].percent,
141a5433b3eSJiri Olsa 						current_entry);
14216932d77SArnaldo Carvalho de Melo 			if (notes->options->show_total_period) {
143a5433b3eSJiri Olsa 				ui_browser__printf(browser, "%11" PRIu64 " ",
144a5433b3eSJiri Olsa 						   al->samples[i].he.period);
14516932d77SArnaldo Carvalho de Melo 			} else if (notes->options->show_nr_samples) {
146a5433b3eSJiri Olsa 				ui_browser__printf(browser, "%6" PRIu64 " ",
147a5433b3eSJiri Olsa 						   al->samples[i].he.nr_samples);
148a5433b3eSJiri Olsa 			} else {
149a5433b3eSJiri Olsa 				ui_browser__printf(browser, "%6.2f ",
150a5433b3eSJiri Olsa 						   al->samples[i].percent);
151a5433b3eSJiri Olsa 			}
152a5433b3eSJiri Olsa 		}
153a5433b3eSJiri Olsa 	} else {
154a5433b3eSJiri Olsa 		ui_browser__set_percent_color(browser, 0, current_entry);
155a5433b3eSJiri Olsa 
156a5433b3eSJiri Olsa 		if (!show_title)
157a5433b3eSJiri Olsa 			ui_browser__write_nstring(browser, " ", pcnt_width);
158a5433b3eSJiri Olsa 		else {
159a5433b3eSJiri Olsa 			ui_browser__printf(browser, "%*s", pcnt_width,
16016932d77SArnaldo Carvalho de Melo 					   notes->options->show_total_period ? "Period" :
16116932d77SArnaldo Carvalho de Melo 					   notes->options->show_nr_samples ? "Samples" : "Percent");
162a5433b3eSJiri Olsa 		}
163a5433b3eSJiri Olsa 	}
1640e83a7e9SArnaldo Carvalho de Melo 	if (notes->have_cycles) {
165a5433b3eSJiri Olsa 		if (al->ipc)
166c426e584SArnaldo Carvalho de Melo 			ui_browser__printf(browser, "%*.2f ", ANNOTATION__IPC_WIDTH - 1, al->ipc);
167a5433b3eSJiri Olsa 		else if (!show_title)
168c426e584SArnaldo Carvalho de Melo 			ui_browser__write_nstring(browser, " ", ANNOTATION__IPC_WIDTH);
169a5433b3eSJiri Olsa 		else
170c426e584SArnaldo Carvalho de Melo 			ui_browser__printf(browser, "%*s ", ANNOTATION__IPC_WIDTH - 1, "IPC");
171a5433b3eSJiri Olsa 
172a5433b3eSJiri Olsa 		if (al->cycles)
173a5433b3eSJiri Olsa 			ui_browser__printf(browser, "%*" PRIu64 " ",
174c426e584SArnaldo Carvalho de Melo 					   ANNOTATION__CYCLES_WIDTH - 1, al->cycles);
175a5433b3eSJiri Olsa 		else if (!show_title)
176c426e584SArnaldo Carvalho de Melo 			ui_browser__write_nstring(browser, " ", ANNOTATION__CYCLES_WIDTH);
177a5433b3eSJiri Olsa 		else
178c426e584SArnaldo Carvalho de Melo 			ui_browser__printf(browser, "%*s ", ANNOTATION__CYCLES_WIDTH - 1, "Cycle");
179a5433b3eSJiri Olsa 	}
180a5433b3eSJiri Olsa 
181a5433b3eSJiri Olsa 	SLsmg_write_char(' ');
182a5433b3eSJiri Olsa 
183a5433b3eSJiri Olsa 	/* The scroll bar isn't being used */
184a5433b3eSJiri Olsa 	if (!browser->navkeypressed)
185a5433b3eSJiri Olsa 		width += 1;
186a5433b3eSJiri Olsa 
187a5433b3eSJiri Olsa 	if (!*al->line)
188a5433b3eSJiri Olsa 		ui_browser__write_nstring(browser, " ", width - pcnt_width - cycles_width);
189a5433b3eSJiri Olsa 	else if (al->offset == -1) {
19016932d77SArnaldo Carvalho de Melo 		if (al->line_nr && notes->options->show_linenr)
191a5433b3eSJiri Olsa 			printed = scnprintf(bf, sizeof(bf), "%-*d ",
192*9761e86eSArnaldo Carvalho de Melo 					notes->widths.addr + 1, al->line_nr);
193a5433b3eSJiri Olsa 		else
194a5433b3eSJiri Olsa 			printed = scnprintf(bf, sizeof(bf), "%*s  ",
195*9761e86eSArnaldo Carvalho de Melo 				    notes->widths.addr, " ");
196a5433b3eSJiri Olsa 		ui_browser__write_nstring(browser, bf, printed);
197a5433b3eSJiri Olsa 		ui_browser__write_nstring(browser, al->line, width - printed - pcnt_width - cycles_width + 1);
198a5433b3eSJiri Olsa 	} else {
199a5433b3eSJiri Olsa 		u64 addr = al->offset;
200a5433b3eSJiri Olsa 		int color = -1;
201a5433b3eSJiri Olsa 
20216932d77SArnaldo Carvalho de Melo 		if (!notes->options->use_offset)
2030ca693b3SArnaldo Carvalho de Melo 			addr += notes->start;
204a5433b3eSJiri Olsa 
20516932d77SArnaldo Carvalho de Melo 		if (!notes->options->use_offset) {
206a5433b3eSJiri Olsa 			printed = scnprintf(bf, sizeof(bf), "%" PRIx64 ": ", addr);
207a5433b3eSJiri Olsa 		} else {
2080db45bcfSArnaldo Carvalho de Melo 			if (al->jump_sources) {
20916932d77SArnaldo Carvalho de Melo 				if (notes->options->show_nr_jumps) {
210a5433b3eSJiri Olsa 					int prev;
211a5433b3eSJiri Olsa 					printed = scnprintf(bf, sizeof(bf), "%*d ",
212*9761e86eSArnaldo Carvalho de Melo 							    notes->widths.jumps,
2130db45bcfSArnaldo Carvalho de Melo 							    al->jump_sources);
2140db45bcfSArnaldo Carvalho de Melo 					prev = ui_browser__set_jumps_percent_color(browser, al->jump_sources,
215a5433b3eSJiri Olsa 										   current_entry);
216a5433b3eSJiri Olsa 					ui_browser__write_nstring(browser, bf, printed);
217a5433b3eSJiri Olsa 					ui_browser__set_color(browser, prev);
218a5433b3eSJiri Olsa 				}
219a5433b3eSJiri Olsa 
220a5433b3eSJiri Olsa 				printed = scnprintf(bf, sizeof(bf), "%*" PRIx64 ": ",
221*9761e86eSArnaldo Carvalho de Melo 						    notes->widths.target, addr);
222a5433b3eSJiri Olsa 			} else {
223a5433b3eSJiri Olsa 				printed = scnprintf(bf, sizeof(bf), "%*s  ",
224*9761e86eSArnaldo Carvalho de Melo 						    notes->widths.addr, " ");
225a5433b3eSJiri Olsa 			}
226a5433b3eSJiri Olsa 		}
227a5433b3eSJiri Olsa 
228a5433b3eSJiri Olsa 		if (change_color)
229a5433b3eSJiri Olsa 			color = ui_browser__set_color(browser, HE_COLORSET_ADDR);
230a5433b3eSJiri Olsa 		ui_browser__write_nstring(browser, bf, printed);
231a5433b3eSJiri Olsa 		if (change_color)
232a5433b3eSJiri Olsa 			ui_browser__set_color(browser, color);
233a5433b3eSJiri Olsa 
234a5433b3eSJiri Olsa 		disasm_line__write(disasm_line(al), browser, bf, sizeof(bf));
235a5433b3eSJiri Olsa 
236bc1e5d60SArnaldo Carvalho de Melo 		ui_browser__write_nstring(browser, bf, width - pcnt_width - cycles_width - 3 - printed);
237aca7a94dSNamhyung Kim 	}
238aca7a94dSNamhyung Kim 
239aca7a94dSNamhyung Kim 	if (current_entry)
240a5433b3eSJiri Olsa 		ab->selection = al;
241aca7a94dSNamhyung Kim }
242aca7a94dSNamhyung Kim 
2437e63a13aSJin Yao static bool is_fused(struct annotate_browser *ab, struct disasm_line *cursor)
2447e63a13aSJin Yao {
245a17c4ca0SJiri Olsa 	struct disasm_line *pos = list_prev_entry(cursor, al.node);
2467e63a13aSJin Yao 	const char *name;
2477e63a13aSJin Yao 
2487e63a13aSJin Yao 	if (!pos)
2497e63a13aSJin Yao 		return false;
2507e63a13aSJin Yao 
2517e63a13aSJin Yao 	if (ins__is_lock(&pos->ins))
2527e63a13aSJin Yao 		name = pos->ops.locked.ins.name;
2537e63a13aSJin Yao 	else
2547e63a13aSJin Yao 		name = pos->ins.name;
2557e63a13aSJin Yao 
2567e63a13aSJin Yao 	if (!name || !cursor->ins.name)
2577e63a13aSJin Yao 		return false;
2587e63a13aSJin Yao 
2597e63a13aSJin Yao 	return ins__is_fused(ab->arch, name, cursor->ins.name);
2607e63a13aSJin Yao }
2617e63a13aSJin Yao 
2629d1ef56dSArnaldo Carvalho de Melo static void annotate_browser__draw_current_jump(struct ui_browser *browser)
263a3f895beSArnaldo Carvalho de Melo {
264a3f895beSArnaldo Carvalho de Melo 	struct annotate_browser *ab = container_of(browser, struct annotate_browser, b);
2657bcbcd58SJiri Olsa 	struct disasm_line *cursor = disasm_line(ab->selection);
266a5ef2702SJiri Olsa 	struct annotation_line *target;
26783b1f2aaSArnaldo Carvalho de Melo 	unsigned int from, to;
26832ae1efdSNamhyung Kim 	struct map_symbol *ms = ab->b.priv;
26932ae1efdSNamhyung Kim 	struct symbol *sym = ms->sym;
2700e83a7e9SArnaldo Carvalho de Melo 	struct annotation *notes = symbol__annotation(sym);
2716af612d2SArnaldo Carvalho de Melo 	u8 pcnt_width = annotation__pcnt_width(notes);
27200ea0eb2SArnaldo Carvalho de Melo 	int width;
27332ae1efdSNamhyung Kim 
27432ae1efdSNamhyung Kim 	/* PLT symbols contain external offsets */
27532ae1efdSNamhyung Kim 	if (strstr(sym->name, "@plt"))
27632ae1efdSNamhyung Kim 		return;
277a3f895beSArnaldo Carvalho de Melo 
278865c66c4SFrederik Deweerdt 	if (!disasm_line__is_valid_jump(cursor, sym))
279a3f895beSArnaldo Carvalho de Melo 		return;
280a3f895beSArnaldo Carvalho de Melo 
2819c04409dSArnaldo Carvalho de Melo 	/*
2829c04409dSArnaldo Carvalho de Melo 	 * This first was seen with a gcc function, _cpp_lex_token, that
2839c04409dSArnaldo Carvalho de Melo 	 * has the usual jumps:
2849c04409dSArnaldo Carvalho de Melo 	 *
2859c04409dSArnaldo Carvalho de Melo 	 *  │1159e6c: ↓ jne    115aa32 <_cpp_lex_token@@Base+0xf92>
2869c04409dSArnaldo Carvalho de Melo 	 *
2879c04409dSArnaldo Carvalho de Melo 	 * I.e. jumps to a label inside that function (_cpp_lex_token), and
2889c04409dSArnaldo Carvalho de Melo 	 * those works, but also this kind:
2899c04409dSArnaldo Carvalho de Melo 	 *
2909c04409dSArnaldo Carvalho de Melo 	 *  │1159e8b: ↓ jne    c469be <cpp_named_operator2name@@Base+0xa72>
2919c04409dSArnaldo Carvalho de Melo 	 *
2929c04409dSArnaldo Carvalho de Melo 	 *  I.e. jumps to another function, outside _cpp_lex_token, which
2939c04409dSArnaldo Carvalho de Melo 	 *  are not being correctly handled generating as a side effect references
2949c04409dSArnaldo Carvalho de Melo 	 *  to ab->offset[] entries that are set to NULL, so to make this code
2959c04409dSArnaldo Carvalho de Melo 	 *  more robust, check that here.
2969c04409dSArnaldo Carvalho de Melo 	 *
2979c04409dSArnaldo Carvalho de Melo 	 *  A proper fix for will be put in place, looking at the function
2989c04409dSArnaldo Carvalho de Melo 	 *  name right after the '<' token and probably treating this like a
2999c04409dSArnaldo Carvalho de Melo 	 *  'call' instruction.
3009c04409dSArnaldo Carvalho de Melo 	 */
3019d6bb41dSArnaldo Carvalho de Melo 	target = notes->offsets[cursor->ops.target.offset];
3029c04409dSArnaldo Carvalho de Melo 	if (target == NULL) {
3039d6bb41dSArnaldo Carvalho de Melo 		ui_helpline__printf("WARN: jump target inconsistency, press 'o', notes->offsets[%#x] = NULL\n",
3049c04409dSArnaldo Carvalho de Melo 				    cursor->ops.target.offset);
3059c04409dSArnaldo Carvalho de Melo 		return;
3069c04409dSArnaldo Carvalho de Melo 	}
3079d1ef56dSArnaldo Carvalho de Melo 
30816932d77SArnaldo Carvalho de Melo 	if (notes->options->hide_src_code) {
3094850c92eSArnaldo Carvalho de Melo 		from = cursor->al.idx_asm;
3104850c92eSArnaldo Carvalho de Melo 		to = target->idx_asm;
311a3f895beSArnaldo Carvalho de Melo 	} else {
3124850c92eSArnaldo Carvalho de Melo 		from = (u64)cursor->al.idx;
3134850c92eSArnaldo Carvalho de Melo 		to = (u64)target->idx;
314a3f895beSArnaldo Carvalho de Melo 	}
315a3f895beSArnaldo Carvalho de Melo 
3160e83a7e9SArnaldo Carvalho de Melo 	width = annotation__cycles_width(notes);
317b40982e8SJin Yao 
31878ce08dfSTaeung Song 	ui_browser__set_color(browser, HE_COLORSET_JUMP_ARROWS);
319b40982e8SJin Yao 	__ui_browser__line_arrow(browser,
320*9761e86eSArnaldo Carvalho de Melo 				 pcnt_width + 2 + notes->widths.addr + width,
321c7e7b610SNamhyung Kim 				 from, to);
3227e63a13aSJin Yao 
3237e63a13aSJin Yao 	if (is_fused(ab, cursor)) {
3247e63a13aSJin Yao 		ui_browser__mark_fused(browser,
325*9761e86eSArnaldo Carvalho de Melo 				       pcnt_width + 3 + notes->widths.addr + width,
3267e63a13aSJin Yao 				       from - 1,
3277e63a13aSJin Yao 				       to > from ? true : false);
3287e63a13aSJin Yao 	}
329a3f895beSArnaldo Carvalho de Melo }
330a3f895beSArnaldo Carvalho de Melo 
331a3f895beSArnaldo Carvalho de Melo static unsigned int annotate_browser__refresh(struct ui_browser *browser)
332a3f895beSArnaldo Carvalho de Melo {
33395aa89d9SArnaldo Carvalho de Melo 	struct annotation *notes = browser__annotation(browser);
334a3f895beSArnaldo Carvalho de Melo 	int ret = ui_browser__list_head_refresh(browser);
3356af612d2SArnaldo Carvalho de Melo 	int pcnt_width = annotation__pcnt_width(notes);
336a3f895beSArnaldo Carvalho de Melo 
33716932d77SArnaldo Carvalho de Melo 	if (notes->options->jump_arrows)
3389d1ef56dSArnaldo Carvalho de Melo 		annotate_browser__draw_current_jump(browser);
339a3f895beSArnaldo Carvalho de Melo 
34083b1f2aaSArnaldo Carvalho de Melo 	ui_browser__set_color(browser, HE_COLORSET_NORMAL);
341c7e7b610SNamhyung Kim 	__ui_browser__vline(browser, pcnt_width, 0, browser->height - 1);
342a3f895beSArnaldo Carvalho de Melo 	return ret;
343a3f895beSArnaldo Carvalho de Melo }
344a3f895beSArnaldo Carvalho de Melo 
345b15636c6SJiri Olsa static int disasm__cmp(struct annotation_line *a, struct annotation_line *b)
346c7e7b610SNamhyung Kim {
347c7e7b610SNamhyung Kim 	int i;
348c7e7b610SNamhyung Kim 
349b15636c6SJiri Olsa 	for (i = 0; i < a->samples_nr; i++) {
3500c4a5bceSMartin Liška 		if (a->samples[i].percent == b->samples[i].percent)
351c7e7b610SNamhyung Kim 			continue;
3520c4a5bceSMartin Liška 		return a->samples[i].percent < b->samples[i].percent;
353c7e7b610SNamhyung Kim 	}
354c7e7b610SNamhyung Kim 	return 0;
355c7e7b610SNamhyung Kim }
356c7e7b610SNamhyung Kim 
357b15636c6SJiri Olsa static void disasm_rb_tree__insert(struct rb_root *root, struct annotation_line *al)
358aca7a94dSNamhyung Kim {
35929ed6e76SArnaldo Carvalho de Melo 	struct rb_node **p = &root->rb_node;
360aca7a94dSNamhyung Kim 	struct rb_node *parent = NULL;
3613ab6db8dSJiri Olsa 	struct annotation_line *l;
362aca7a94dSNamhyung Kim 
363aca7a94dSNamhyung Kim 	while (*p != NULL) {
364aca7a94dSNamhyung Kim 		parent = *p;
3653ab6db8dSJiri Olsa 		l = rb_entry(parent, struct annotation_line, rb_node);
366c7e7b610SNamhyung Kim 
367b15636c6SJiri Olsa 		if (disasm__cmp(al, l))
368aca7a94dSNamhyung Kim 			p = &(*p)->rb_left;
369aca7a94dSNamhyung Kim 		else
370aca7a94dSNamhyung Kim 			p = &(*p)->rb_right;
371aca7a94dSNamhyung Kim 	}
3723ab6db8dSJiri Olsa 	rb_link_node(&al->rb_node, parent, p);
3733ab6db8dSJiri Olsa 	rb_insert_color(&al->rb_node, root);
374aca7a94dSNamhyung Kim }
375aca7a94dSNamhyung Kim 
37605e8b080SArnaldo Carvalho de Melo static void annotate_browser__set_top(struct annotate_browser *browser,
377ec03a77dSJiri Olsa 				      struct annotation_line *pos, u32 idx)
378aca7a94dSNamhyung Kim {
379aca7a94dSNamhyung Kim 	unsigned back;
380aca7a94dSNamhyung Kim 
38105e8b080SArnaldo Carvalho de Melo 	ui_browser__refresh_dimensions(&browser->b);
38205e8b080SArnaldo Carvalho de Melo 	back = browser->b.height / 2;
38305e8b080SArnaldo Carvalho de Melo 	browser->b.top_idx = browser->b.index = idx;
384aca7a94dSNamhyung Kim 
38505e8b080SArnaldo Carvalho de Melo 	while (browser->b.top_idx != 0 && back != 0) {
386ec03a77dSJiri Olsa 		pos = list_entry(pos->node.prev, struct annotation_line, node);
387aca7a94dSNamhyung Kim 
388ec03a77dSJiri Olsa 		if (disasm_line__filter(&browser->b, &pos->node))
389aca7a94dSNamhyung Kim 			continue;
390aca7a94dSNamhyung Kim 
39105e8b080SArnaldo Carvalho de Melo 		--browser->b.top_idx;
392aca7a94dSNamhyung Kim 		--back;
393aca7a94dSNamhyung Kim 	}
394aca7a94dSNamhyung Kim 
395ec03a77dSJiri Olsa 	browser->b.top = pos;
39605e8b080SArnaldo Carvalho de Melo 	browser->b.navkeypressed = true;
397aca7a94dSNamhyung Kim }
398aca7a94dSNamhyung Kim 
399aca7a94dSNamhyung Kim static void annotate_browser__set_rb_top(struct annotate_browser *browser,
400aca7a94dSNamhyung Kim 					 struct rb_node *nd)
401aca7a94dSNamhyung Kim {
40295aa89d9SArnaldo Carvalho de Melo 	struct annotation *notes = browser__annotation(&browser->b);
4034850c92eSArnaldo Carvalho de Melo 	struct annotation_line * pos = rb_entry(nd, struct annotation_line, rb_node);
4044850c92eSArnaldo Carvalho de Melo 	u32 idx = pos->idx;
405aca7a94dSNamhyung Kim 
40616932d77SArnaldo Carvalho de Melo 	if (notes->options->hide_src_code)
4074850c92eSArnaldo Carvalho de Melo 		idx = pos->idx_asm;
408a44b45f2SArnaldo Carvalho de Melo 	annotate_browser__set_top(browser, pos, idx);
409aca7a94dSNamhyung Kim 	browser->curr_hot = nd;
410aca7a94dSNamhyung Kim }
411aca7a94dSNamhyung Kim 
412aca7a94dSNamhyung Kim static void annotate_browser__calc_percent(struct annotate_browser *browser,
413db8fd07aSNamhyung Kim 					   struct perf_evsel *evsel)
414aca7a94dSNamhyung Kim {
415aca7a94dSNamhyung Kim 	struct map_symbol *ms = browser->b.priv;
416aca7a94dSNamhyung Kim 	struct symbol *sym = ms->sym;
417aca7a94dSNamhyung Kim 	struct annotation *notes = symbol__annotation(sym);
418c4c72436SJiri Olsa 	struct disasm_line *pos;
419aca7a94dSNamhyung Kim 
420aca7a94dSNamhyung Kim 	browser->entries = RB_ROOT;
421aca7a94dSNamhyung Kim 
422aca7a94dSNamhyung Kim 	pthread_mutex_lock(&notes->lock);
423aca7a94dSNamhyung Kim 
424e425da6cSJiri Olsa 	symbol__calc_percent(sym, evsel);
425e425da6cSJiri Olsa 
426a17c4ca0SJiri Olsa 	list_for_each_entry(pos, &notes->src->source, al.node) {
427c7e7b610SNamhyung Kim 		double max_percent = 0.0;
428c7e7b610SNamhyung Kim 		int i;
429e64aa75bSNamhyung Kim 
430d5490b96SJiri Olsa 		if (pos->al.offset == -1) {
4315b12adc8SJiri Olsa 			RB_CLEAR_NODE(&pos->al.rb_node);
432e64aa75bSNamhyung Kim 			continue;
433e64aa75bSNamhyung Kim 		}
434e64aa75bSNamhyung Kim 
435b15636c6SJiri Olsa 		for (i = 0; i < pos->al.samples_nr; i++) {
436e425da6cSJiri Olsa 			struct annotation_data *sample = &pos->al.samples[i];
4370c4a5bceSMartin Liška 
4383ab6db8dSJiri Olsa 			if (max_percent < sample->percent)
4393ab6db8dSJiri Olsa 				max_percent = sample->percent;
440c7e7b610SNamhyung Kim 		}
441c7e7b610SNamhyung Kim 
44237236d5eSJiri Olsa 		if (max_percent < 0.01 && pos->al.ipc == 0) {
4435b12adc8SJiri Olsa 			RB_CLEAR_NODE(&pos->al.rb_node);
444aca7a94dSNamhyung Kim 			continue;
445aca7a94dSNamhyung Kim 		}
446b15636c6SJiri Olsa 		disasm_rb_tree__insert(&browser->entries, &pos->al);
447aca7a94dSNamhyung Kim 	}
448aca7a94dSNamhyung Kim 	pthread_mutex_unlock(&notes->lock);
449aca7a94dSNamhyung Kim 
450aca7a94dSNamhyung Kim 	browser->curr_hot = rb_last(&browser->entries);
451aca7a94dSNamhyung Kim }
452aca7a94dSNamhyung Kim 
453aca7a94dSNamhyung Kim static bool annotate_browser__toggle_source(struct annotate_browser *browser)
454aca7a94dSNamhyung Kim {
45595aa89d9SArnaldo Carvalho de Melo 	struct annotation *notes = browser__annotation(&browser->b);
456ec03a77dSJiri Olsa 	struct annotation_line *al;
457aca7a94dSNamhyung Kim 	off_t offset = browser->b.index - browser->b.top_idx;
458aca7a94dSNamhyung Kim 
459aca7a94dSNamhyung Kim 	browser->b.seek(&browser->b, offset, SEEK_CUR);
460ec03a77dSJiri Olsa 	al = list_entry(browser->b.top, struct annotation_line, node);
461aca7a94dSNamhyung Kim 
46216932d77SArnaldo Carvalho de Melo 	if (notes->options->hide_src_code) {
4634850c92eSArnaldo Carvalho de Melo 		if (al->idx_asm < offset)
4644850c92eSArnaldo Carvalho de Melo 			offset = al->idx;
465aca7a94dSNamhyung Kim 
4661cf5f98aSArnaldo Carvalho de Melo 		browser->b.nr_entries = notes->nr_entries;
46716932d77SArnaldo Carvalho de Melo 		notes->options->hide_src_code = false;
468aca7a94dSNamhyung Kim 		browser->b.seek(&browser->b, -offset, SEEK_CUR);
4694850c92eSArnaldo Carvalho de Melo 		browser->b.top_idx = al->idx - offset;
4704850c92eSArnaldo Carvalho de Melo 		browser->b.index = al->idx;
471aca7a94dSNamhyung Kim 	} else {
4724850c92eSArnaldo Carvalho de Melo 		if (al->idx_asm < 0) {
473aca7a94dSNamhyung Kim 			ui_helpline__puts("Only available for assembly lines.");
474aca7a94dSNamhyung Kim 			browser->b.seek(&browser->b, -offset, SEEK_CUR);
475aca7a94dSNamhyung Kim 			return false;
476aca7a94dSNamhyung Kim 		}
477aca7a94dSNamhyung Kim 
4784850c92eSArnaldo Carvalho de Melo 		if (al->idx_asm < offset)
4794850c92eSArnaldo Carvalho de Melo 			offset = al->idx_asm;
480aca7a94dSNamhyung Kim 
4811cf5f98aSArnaldo Carvalho de Melo 		browser->b.nr_entries = notes->nr_asm_entries;
48216932d77SArnaldo Carvalho de Melo 		notes->options->hide_src_code = true;
483aca7a94dSNamhyung Kim 		browser->b.seek(&browser->b, -offset, SEEK_CUR);
4844850c92eSArnaldo Carvalho de Melo 		browser->b.top_idx = al->idx_asm - offset;
4854850c92eSArnaldo Carvalho de Melo 		browser->b.index = al->idx_asm;
486aca7a94dSNamhyung Kim 	}
487aca7a94dSNamhyung Kim 
488aca7a94dSNamhyung Kim 	return true;
489aca7a94dSNamhyung Kim }
490aca7a94dSNamhyung Kim 
4911cf5f98aSArnaldo Carvalho de Melo static void ui_browser__init_asm_mode(struct ui_browser *browser)
492e9823b21SArnaldo Carvalho de Melo {
4931cf5f98aSArnaldo Carvalho de Melo 	struct annotation *notes = browser__annotation(browser);
4941cf5f98aSArnaldo Carvalho de Melo 	ui_browser__reset_index(browser);
4951cf5f98aSArnaldo Carvalho de Melo 	browser->nr_entries = notes->nr_asm_entries;
496e9823b21SArnaldo Carvalho de Melo }
497e9823b21SArnaldo Carvalho de Melo 
49834f77abcSAdrian Hunter #define SYM_TITLE_MAX_SIZE (PATH_MAX + 64)
49934f77abcSAdrian Hunter 
50034f77abcSAdrian Hunter static int sym_title(struct symbol *sym, struct map *map, char *title,
50134f77abcSAdrian Hunter 		     size_t sz)
50234f77abcSAdrian Hunter {
50334f77abcSAdrian Hunter 	return snprintf(title, sz, "%s  %s", sym->name, map->dso->long_name);
50434f77abcSAdrian Hunter }
50534f77abcSAdrian Hunter 
506db8fd07aSNamhyung Kim static bool annotate_browser__callq(struct annotate_browser *browser,
507db8fd07aSNamhyung Kim 				    struct perf_evsel *evsel,
5089783adf7SNamhyung Kim 				    struct hist_browser_timer *hbt)
509aca7a94dSNamhyung Kim {
510aca7a94dSNamhyung Kim 	struct map_symbol *ms = browser->b.priv;
5117bcbcd58SJiri Olsa 	struct disasm_line *dl = disasm_line(browser->selection);
512aca7a94dSNamhyung Kim 	struct annotation *notes;
51334f77abcSAdrian Hunter 	char title[SYM_TITLE_MAX_SIZE];
514aca7a94dSNamhyung Kim 
51575b49202SArnaldo Carvalho de Melo 	if (!ins__is_call(&dl->ins))
516aca7a94dSNamhyung Kim 		return false;
517aca7a94dSNamhyung Kim 
518696703afSArnaldo Carvalho de Melo 	if (!dl->ops.target.sym) {
519aca7a94dSNamhyung Kim 		ui_helpline__puts("The called function was not found.");
520aca7a94dSNamhyung Kim 		return true;
521aca7a94dSNamhyung Kim 	}
522aca7a94dSNamhyung Kim 
523696703afSArnaldo Carvalho de Melo 	notes = symbol__annotation(dl->ops.target.sym);
524aca7a94dSNamhyung Kim 	pthread_mutex_lock(&notes->lock);
525aca7a94dSNamhyung Kim 
526696703afSArnaldo Carvalho de Melo 	if (notes->src == NULL && symbol__alloc_hist(dl->ops.target.sym) < 0) {
527aca7a94dSNamhyung Kim 		pthread_mutex_unlock(&notes->lock);
528aca7a94dSNamhyung Kim 		ui__warning("Not enough memory for annotating '%s' symbol!\n",
529696703afSArnaldo Carvalho de Melo 			    dl->ops.target.sym->name);
530aca7a94dSNamhyung Kim 		return true;
531aca7a94dSNamhyung Kim 	}
532aca7a94dSNamhyung Kim 
533aca7a94dSNamhyung Kim 	pthread_mutex_unlock(&notes->lock);
534696703afSArnaldo Carvalho de Melo 	symbol__tui_annotate(dl->ops.target.sym, ms->map, evsel, hbt);
5351179e11bSAdrian Hunter 	sym_title(ms->sym, ms->map, title, sizeof(title));
53634f77abcSAdrian Hunter 	ui_browser__show_title(&browser->b, title);
537aca7a94dSNamhyung Kim 	return true;
538aca7a94dSNamhyung Kim }
539aca7a94dSNamhyung Kim 
54029ed6e76SArnaldo Carvalho de Melo static
54129ed6e76SArnaldo Carvalho de Melo struct disasm_line *annotate_browser__find_offset(struct annotate_browser *browser,
542aca7a94dSNamhyung Kim 					  s64 offset, s64 *idx)
543aca7a94dSNamhyung Kim {
54495aa89d9SArnaldo Carvalho de Melo 	struct annotation *notes = browser__annotation(&browser->b);
54529ed6e76SArnaldo Carvalho de Melo 	struct disasm_line *pos;
546aca7a94dSNamhyung Kim 
547aca7a94dSNamhyung Kim 	*idx = 0;
548a17c4ca0SJiri Olsa 	list_for_each_entry(pos, &notes->src->source, al.node) {
549d5490b96SJiri Olsa 		if (pos->al.offset == offset)
550aca7a94dSNamhyung Kim 			return pos;
551a17c4ca0SJiri Olsa 		if (!disasm_line__filter(&browser->b, &pos->al.node))
552aca7a94dSNamhyung Kim 			++*idx;
553aca7a94dSNamhyung Kim 	}
554aca7a94dSNamhyung Kim 
555aca7a94dSNamhyung Kim 	return NULL;
556aca7a94dSNamhyung Kim }
557aca7a94dSNamhyung Kim 
558aca7a94dSNamhyung Kim static bool annotate_browser__jump(struct annotate_browser *browser)
559aca7a94dSNamhyung Kim {
5607bcbcd58SJiri Olsa 	struct disasm_line *dl = disasm_line(browser->selection);
5615252b1aeSArnaldo Carvalho de Melo 	u64 offset;
5624f9d0325SArnaldo Carvalho de Melo 	s64 idx;
563aca7a94dSNamhyung Kim 
56475b49202SArnaldo Carvalho de Melo 	if (!ins__is_jump(&dl->ins))
565aca7a94dSNamhyung Kim 		return false;
566aca7a94dSNamhyung Kim 
5675252b1aeSArnaldo Carvalho de Melo 	offset = dl->ops.target.offset;
5685252b1aeSArnaldo Carvalho de Melo 	dl = annotate_browser__find_offset(browser, offset, &idx);
56929ed6e76SArnaldo Carvalho de Melo 	if (dl == NULL) {
5705252b1aeSArnaldo Carvalho de Melo 		ui_helpline__printf("Invalid jump offset: %" PRIx64, offset);
571aca7a94dSNamhyung Kim 		return true;
572aca7a94dSNamhyung Kim 	}
573aca7a94dSNamhyung Kim 
574ec03a77dSJiri Olsa 	annotate_browser__set_top(browser, &dl->al, idx);
575aca7a94dSNamhyung Kim 
576aca7a94dSNamhyung Kim 	return true;
577aca7a94dSNamhyung Kim }
578aca7a94dSNamhyung Kim 
57929ed6e76SArnaldo Carvalho de Melo static
5809213afbdSJiri Olsa struct annotation_line *annotate_browser__find_string(struct annotate_browser *browser,
581aca7a94dSNamhyung Kim 					  char *s, s64 *idx)
582aca7a94dSNamhyung Kim {
58395aa89d9SArnaldo Carvalho de Melo 	struct annotation *notes = browser__annotation(&browser->b);
5849213afbdSJiri Olsa 	struct annotation_line *al = browser->selection;
585aca7a94dSNamhyung Kim 
586aca7a94dSNamhyung Kim 	*idx = browser->b.index;
5879213afbdSJiri Olsa 	list_for_each_entry_continue(al, &notes->src->source, node) {
5889213afbdSJiri Olsa 		if (disasm_line__filter(&browser->b, &al->node))
589aca7a94dSNamhyung Kim 			continue;
590aca7a94dSNamhyung Kim 
591aca7a94dSNamhyung Kim 		++*idx;
592aca7a94dSNamhyung Kim 
5939213afbdSJiri Olsa 		if (al->line && strstr(al->line, s) != NULL)
5949213afbdSJiri Olsa 			return al;
595aca7a94dSNamhyung Kim 	}
596aca7a94dSNamhyung Kim 
597aca7a94dSNamhyung Kim 	return NULL;
598aca7a94dSNamhyung Kim }
599aca7a94dSNamhyung Kim 
600aca7a94dSNamhyung Kim static bool __annotate_browser__search(struct annotate_browser *browser)
601aca7a94dSNamhyung Kim {
6029213afbdSJiri Olsa 	struct annotation_line *al;
603aca7a94dSNamhyung Kim 	s64 idx;
604aca7a94dSNamhyung Kim 
6059213afbdSJiri Olsa 	al = annotate_browser__find_string(browser, browser->search_bf, &idx);
6069213afbdSJiri Olsa 	if (al == NULL) {
607aca7a94dSNamhyung Kim 		ui_helpline__puts("String not found!");
608aca7a94dSNamhyung Kim 		return false;
609aca7a94dSNamhyung Kim 	}
610aca7a94dSNamhyung Kim 
611ec03a77dSJiri Olsa 	annotate_browser__set_top(browser, al, idx);
612aca7a94dSNamhyung Kim 	browser->searching_backwards = false;
613aca7a94dSNamhyung Kim 	return true;
614aca7a94dSNamhyung Kim }
615aca7a94dSNamhyung Kim 
61629ed6e76SArnaldo Carvalho de Melo static
6179213afbdSJiri Olsa struct annotation_line *annotate_browser__find_string_reverse(struct annotate_browser *browser,
618aca7a94dSNamhyung Kim 						  char *s, s64 *idx)
619aca7a94dSNamhyung Kim {
62095aa89d9SArnaldo Carvalho de Melo 	struct annotation *notes = browser__annotation(&browser->b);
6219213afbdSJiri Olsa 	struct annotation_line *al = browser->selection;
622aca7a94dSNamhyung Kim 
623aca7a94dSNamhyung Kim 	*idx = browser->b.index;
6249213afbdSJiri Olsa 	list_for_each_entry_continue_reverse(al, &notes->src->source, node) {
6259213afbdSJiri Olsa 		if (disasm_line__filter(&browser->b, &al->node))
626aca7a94dSNamhyung Kim 			continue;
627aca7a94dSNamhyung Kim 
628aca7a94dSNamhyung Kim 		--*idx;
629aca7a94dSNamhyung Kim 
6309213afbdSJiri Olsa 		if (al->line && strstr(al->line, s) != NULL)
6319213afbdSJiri Olsa 			return al;
632aca7a94dSNamhyung Kim 	}
633aca7a94dSNamhyung Kim 
634aca7a94dSNamhyung Kim 	return NULL;
635aca7a94dSNamhyung Kim }
636aca7a94dSNamhyung Kim 
637aca7a94dSNamhyung Kim static bool __annotate_browser__search_reverse(struct annotate_browser *browser)
638aca7a94dSNamhyung Kim {
6399213afbdSJiri Olsa 	struct annotation_line *al;
640aca7a94dSNamhyung Kim 	s64 idx;
641aca7a94dSNamhyung Kim 
6429213afbdSJiri Olsa 	al = annotate_browser__find_string_reverse(browser, browser->search_bf, &idx);
6439213afbdSJiri Olsa 	if (al == NULL) {
644aca7a94dSNamhyung Kim 		ui_helpline__puts("String not found!");
645aca7a94dSNamhyung Kim 		return false;
646aca7a94dSNamhyung Kim 	}
647aca7a94dSNamhyung Kim 
648ec03a77dSJiri Olsa 	annotate_browser__set_top(browser, al, idx);
649aca7a94dSNamhyung Kim 	browser->searching_backwards = true;
650aca7a94dSNamhyung Kim 	return true;
651aca7a94dSNamhyung Kim }
652aca7a94dSNamhyung Kim 
653aca7a94dSNamhyung Kim static bool annotate_browser__search_window(struct annotate_browser *browser,
654aca7a94dSNamhyung Kim 					    int delay_secs)
655aca7a94dSNamhyung Kim {
656aca7a94dSNamhyung Kim 	if (ui_browser__input_window("Search", "String: ", browser->search_bf,
657aca7a94dSNamhyung Kim 				     "ENTER: OK, ESC: Cancel",
658aca7a94dSNamhyung Kim 				     delay_secs * 2) != K_ENTER ||
659aca7a94dSNamhyung Kim 	    !*browser->search_bf)
660aca7a94dSNamhyung Kim 		return false;
661aca7a94dSNamhyung Kim 
662aca7a94dSNamhyung Kim 	return true;
663aca7a94dSNamhyung Kim }
664aca7a94dSNamhyung Kim 
665aca7a94dSNamhyung Kim static bool annotate_browser__search(struct annotate_browser *browser, int delay_secs)
666aca7a94dSNamhyung Kim {
667aca7a94dSNamhyung Kim 	if (annotate_browser__search_window(browser, delay_secs))
668aca7a94dSNamhyung Kim 		return __annotate_browser__search(browser);
669aca7a94dSNamhyung Kim 
670aca7a94dSNamhyung Kim 	return false;
671aca7a94dSNamhyung Kim }
672aca7a94dSNamhyung Kim 
673aca7a94dSNamhyung Kim static bool annotate_browser__continue_search(struct annotate_browser *browser,
674aca7a94dSNamhyung Kim 					      int delay_secs)
675aca7a94dSNamhyung Kim {
676aca7a94dSNamhyung Kim 	if (!*browser->search_bf)
677aca7a94dSNamhyung Kim 		return annotate_browser__search(browser, delay_secs);
678aca7a94dSNamhyung Kim 
679aca7a94dSNamhyung Kim 	return __annotate_browser__search(browser);
680aca7a94dSNamhyung Kim }
681aca7a94dSNamhyung Kim 
682aca7a94dSNamhyung Kim static bool annotate_browser__search_reverse(struct annotate_browser *browser,
683aca7a94dSNamhyung Kim 					   int delay_secs)
684aca7a94dSNamhyung Kim {
685aca7a94dSNamhyung Kim 	if (annotate_browser__search_window(browser, delay_secs))
686aca7a94dSNamhyung Kim 		return __annotate_browser__search_reverse(browser);
687aca7a94dSNamhyung Kim 
688aca7a94dSNamhyung Kim 	return false;
689aca7a94dSNamhyung Kim }
690aca7a94dSNamhyung Kim 
691aca7a94dSNamhyung Kim static
692aca7a94dSNamhyung Kim bool annotate_browser__continue_search_reverse(struct annotate_browser *browser,
693aca7a94dSNamhyung Kim 					       int delay_secs)
694aca7a94dSNamhyung Kim {
695aca7a94dSNamhyung Kim 	if (!*browser->search_bf)
696aca7a94dSNamhyung Kim 		return annotate_browser__search_reverse(browser, delay_secs);
697aca7a94dSNamhyung Kim 
698aca7a94dSNamhyung Kim 	return __annotate_browser__search_reverse(browser);
699aca7a94dSNamhyung Kim }
700aca7a94dSNamhyung Kim 
701*9761e86eSArnaldo Carvalho de Melo static void annotation__update_column_widths(struct annotation *notes)
702e9823b21SArnaldo Carvalho de Melo {
70316932d77SArnaldo Carvalho de Melo 	if (notes->options->use_offset)
704*9761e86eSArnaldo Carvalho de Melo 		notes->widths.target = notes->widths.min_addr;
705e9823b21SArnaldo Carvalho de Melo 	else
706*9761e86eSArnaldo Carvalho de Melo 		notes->widths.target = notes->widths.max_addr;
707e9823b21SArnaldo Carvalho de Melo 
708*9761e86eSArnaldo Carvalho de Melo 	notes->widths.addr = notes->widths.target;
709e9823b21SArnaldo Carvalho de Melo 
71016932d77SArnaldo Carvalho de Melo 	if (notes->options->show_nr_jumps)
711*9761e86eSArnaldo Carvalho de Melo 		notes->widths.addr += notes->widths.jumps + 1;
712e9823b21SArnaldo Carvalho de Melo }
713e9823b21SArnaldo Carvalho de Melo 
714db8fd07aSNamhyung Kim static int annotate_browser__run(struct annotate_browser *browser,
715db8fd07aSNamhyung Kim 				 struct perf_evsel *evsel,
7169783adf7SNamhyung Kim 				 struct hist_browser_timer *hbt)
717aca7a94dSNamhyung Kim {
718aca7a94dSNamhyung Kim 	struct rb_node *nd = NULL;
71905e8b080SArnaldo Carvalho de Melo 	struct map_symbol *ms = browser->b.priv;
720aca7a94dSNamhyung Kim 	struct symbol *sym = ms->sym;
72116932d77SArnaldo Carvalho de Melo 	struct annotation *notes = symbol__annotation(ms->sym);
72254e7a4e8SArnaldo Carvalho de Melo 	const char *help = "Press 'h' for help on key bindings";
7239783adf7SNamhyung Kim 	int delay_secs = hbt ? hbt->refresh : 0;
724aca7a94dSNamhyung Kim 	int key;
72534f77abcSAdrian Hunter 	char title[SYM_TITLE_MAX_SIZE];
726aca7a94dSNamhyung Kim 
72734f77abcSAdrian Hunter 	sym_title(sym, ms->map, title, sizeof(title));
72834f77abcSAdrian Hunter 	if (ui_browser__show(&browser->b, title, help) < 0)
729aca7a94dSNamhyung Kim 		return -1;
730aca7a94dSNamhyung Kim 
731db8fd07aSNamhyung Kim 	annotate_browser__calc_percent(browser, evsel);
732aca7a94dSNamhyung Kim 
73305e8b080SArnaldo Carvalho de Melo 	if (browser->curr_hot) {
73405e8b080SArnaldo Carvalho de Melo 		annotate_browser__set_rb_top(browser, browser->curr_hot);
73505e8b080SArnaldo Carvalho de Melo 		browser->b.navkeypressed = false;
736aca7a94dSNamhyung Kim 	}
737aca7a94dSNamhyung Kim 
73805e8b080SArnaldo Carvalho de Melo 	nd = browser->curr_hot;
739aca7a94dSNamhyung Kim 
740aca7a94dSNamhyung Kim 	while (1) {
74105e8b080SArnaldo Carvalho de Melo 		key = ui_browser__run(&browser->b, delay_secs);
742aca7a94dSNamhyung Kim 
743aca7a94dSNamhyung Kim 		if (delay_secs != 0) {
744db8fd07aSNamhyung Kim 			annotate_browser__calc_percent(browser, evsel);
745aca7a94dSNamhyung Kim 			/*
746aca7a94dSNamhyung Kim 			 * Current line focus got out of the list of most active
747aca7a94dSNamhyung Kim 			 * lines, NULL it so that if TAB|UNTAB is pressed, we
748aca7a94dSNamhyung Kim 			 * move to curr_hot (current hottest line).
749aca7a94dSNamhyung Kim 			 */
750aca7a94dSNamhyung Kim 			if (nd != NULL && RB_EMPTY_NODE(nd))
751aca7a94dSNamhyung Kim 				nd = NULL;
752aca7a94dSNamhyung Kim 		}
753aca7a94dSNamhyung Kim 
754aca7a94dSNamhyung Kim 		switch (key) {
755aca7a94dSNamhyung Kim 		case K_TIMER:
7569783adf7SNamhyung Kim 			if (hbt)
7579783adf7SNamhyung Kim 				hbt->timer(hbt->arg);
758aca7a94dSNamhyung Kim 
759aca7a94dSNamhyung Kim 			if (delay_secs != 0)
760db8fd07aSNamhyung Kim 				symbol__annotate_decay_histogram(sym, evsel->idx);
761aca7a94dSNamhyung Kim 			continue;
762aca7a94dSNamhyung Kim 		case K_TAB:
763aca7a94dSNamhyung Kim 			if (nd != NULL) {
764aca7a94dSNamhyung Kim 				nd = rb_prev(nd);
765aca7a94dSNamhyung Kim 				if (nd == NULL)
76605e8b080SArnaldo Carvalho de Melo 					nd = rb_last(&browser->entries);
767aca7a94dSNamhyung Kim 			} else
76805e8b080SArnaldo Carvalho de Melo 				nd = browser->curr_hot;
769aca7a94dSNamhyung Kim 			break;
770aca7a94dSNamhyung Kim 		case K_UNTAB:
771d4913cbdSMarkus Trippelsdorf 			if (nd != NULL) {
772aca7a94dSNamhyung Kim 				nd = rb_next(nd);
773aca7a94dSNamhyung Kim 				if (nd == NULL)
77405e8b080SArnaldo Carvalho de Melo 					nd = rb_first(&browser->entries);
775d4913cbdSMarkus Trippelsdorf 			} else
77605e8b080SArnaldo Carvalho de Melo 				nd = browser->curr_hot;
777aca7a94dSNamhyung Kim 			break;
77854e7a4e8SArnaldo Carvalho de Melo 		case K_F1:
779aca7a94dSNamhyung Kim 		case 'h':
78005e8b080SArnaldo Carvalho de Melo 			ui_browser__help_window(&browser->b,
78154e7a4e8SArnaldo Carvalho de Melo 		"UP/DOWN/PGUP\n"
78254e7a4e8SArnaldo Carvalho de Melo 		"PGDN/SPACE    Navigate\n"
78354e7a4e8SArnaldo Carvalho de Melo 		"q/ESC/CTRL+C  Exit\n\n"
7847727a925SArnaldo Carvalho de Melo 		"ENTER         Go to target\n"
7857727a925SArnaldo Carvalho de Melo 		"ESC           Exit\n"
786eba9fac0SArnaldo Carvalho de Melo 		"H             Go to hottest instruction\n"
787eba9fac0SArnaldo Carvalho de Melo 		"TAB/shift+TAB Cycle thru hottest instructions\n"
78854e7a4e8SArnaldo Carvalho de Melo 		"j             Toggle showing jump to target arrows\n"
78954e7a4e8SArnaldo Carvalho de Melo 		"J             Toggle showing number of jump sources on targets\n"
79054e7a4e8SArnaldo Carvalho de Melo 		"n             Search next string\n"
79154e7a4e8SArnaldo Carvalho de Melo 		"o             Toggle disassembler output/simplified view\n"
79254e7a4e8SArnaldo Carvalho de Melo 		"s             Toggle source code view\n"
7933a555c77STaeung Song 		"t             Circulate percent, total period, samples view\n"
79454e7a4e8SArnaldo Carvalho de Melo 		"/             Search string\n"
795e592488cSAndi Kleen 		"k             Toggle line numbers\n"
79679ee47faSFeng Tang 		"r             Run available scripts\n"
797fcd9fef9SArnaldo Carvalho de Melo 		"?             Search string backwards\n");
79854e7a4e8SArnaldo Carvalho de Melo 			continue;
79979ee47faSFeng Tang 		case 'r':
80079ee47faSFeng Tang 			{
80179ee47faSFeng Tang 				script_browse(NULL);
80279ee47faSFeng Tang 				continue;
80379ee47faSFeng Tang 			}
804e592488cSAndi Kleen 		case 'k':
80516932d77SArnaldo Carvalho de Melo 			notes->options->show_linenr = !notes->options->show_linenr;
806e592488cSAndi Kleen 			break;
80754e7a4e8SArnaldo Carvalho de Melo 		case 'H':
80805e8b080SArnaldo Carvalho de Melo 			nd = browser->curr_hot;
809aca7a94dSNamhyung Kim 			break;
810aca7a94dSNamhyung Kim 		case 's':
81105e8b080SArnaldo Carvalho de Melo 			if (annotate_browser__toggle_source(browser))
812aca7a94dSNamhyung Kim 				ui_helpline__puts(help);
813aca7a94dSNamhyung Kim 			continue;
814aca7a94dSNamhyung Kim 		case 'o':
81516932d77SArnaldo Carvalho de Melo 			notes->options->use_offset = !notes->options->use_offset;
816*9761e86eSArnaldo Carvalho de Melo 			annotation__update_column_widths(notes);
817aca7a94dSNamhyung Kim 			continue;
8189d1ef56dSArnaldo Carvalho de Melo 		case 'j':
81916932d77SArnaldo Carvalho de Melo 			notes->options->jump_arrows = !notes->options->jump_arrows;
8209d1ef56dSArnaldo Carvalho de Melo 			continue;
8212402e4a9SArnaldo Carvalho de Melo 		case 'J':
82216932d77SArnaldo Carvalho de Melo 			notes->options->show_nr_jumps = !notes->options->show_nr_jumps;
823*9761e86eSArnaldo Carvalho de Melo 			annotation__update_column_widths(notes);
824e9823b21SArnaldo Carvalho de Melo 			continue;
825aca7a94dSNamhyung Kim 		case '/':
82605e8b080SArnaldo Carvalho de Melo 			if (annotate_browser__search(browser, delay_secs)) {
827aca7a94dSNamhyung Kim show_help:
828aca7a94dSNamhyung Kim 				ui_helpline__puts(help);
829aca7a94dSNamhyung Kim 			}
830aca7a94dSNamhyung Kim 			continue;
831aca7a94dSNamhyung Kim 		case 'n':
83205e8b080SArnaldo Carvalho de Melo 			if (browser->searching_backwards ?
83305e8b080SArnaldo Carvalho de Melo 			    annotate_browser__continue_search_reverse(browser, delay_secs) :
83405e8b080SArnaldo Carvalho de Melo 			    annotate_browser__continue_search(browser, delay_secs))
835aca7a94dSNamhyung Kim 				goto show_help;
836aca7a94dSNamhyung Kim 			continue;
837aca7a94dSNamhyung Kim 		case '?':
83805e8b080SArnaldo Carvalho de Melo 			if (annotate_browser__search_reverse(browser, delay_secs))
839aca7a94dSNamhyung Kim 				goto show_help;
840aca7a94dSNamhyung Kim 			continue;
841e9823b21SArnaldo Carvalho de Melo 		case 'D': {
842e9823b21SArnaldo Carvalho de Melo 			static int seq;
843e9823b21SArnaldo Carvalho de Melo 			ui_helpline__pop();
844e9823b21SArnaldo Carvalho de Melo 			ui_helpline__fpush("%d: nr_ent=%d, height=%d, idx=%d, top_idx=%d, nr_asm_entries=%d",
84505e8b080SArnaldo Carvalho de Melo 					   seq++, browser->b.nr_entries,
84605e8b080SArnaldo Carvalho de Melo 					   browser->b.height,
84705e8b080SArnaldo Carvalho de Melo 					   browser->b.index,
84805e8b080SArnaldo Carvalho de Melo 					   browser->b.top_idx,
8491cf5f98aSArnaldo Carvalho de Melo 					   notes->nr_asm_entries);
850e9823b21SArnaldo Carvalho de Melo 		}
851e9823b21SArnaldo Carvalho de Melo 			continue;
852aca7a94dSNamhyung Kim 		case K_ENTER:
853aca7a94dSNamhyung Kim 		case K_RIGHT:
8547bcbcd58SJiri Olsa 		{
8557bcbcd58SJiri Olsa 			struct disasm_line *dl = disasm_line(browser->selection);
8567bcbcd58SJiri Olsa 
85705e8b080SArnaldo Carvalho de Melo 			if (browser->selection == NULL)
858aca7a94dSNamhyung Kim 				ui_helpline__puts("Huh? No selection. Report to linux-kernel@vger.kernel.org");
8597bcbcd58SJiri Olsa 			else if (browser->selection->offset == -1)
860aca7a94dSNamhyung Kim 				ui_helpline__puts("Actions are only available for assembly lines.");
8617bcbcd58SJiri Olsa 			else if (!dl->ins.ops)
862c4cceae3SArnaldo Carvalho de Melo 				goto show_sup_ins;
8637bcbcd58SJiri Olsa 			else if (ins__is_ret(&dl->ins))
864c4cceae3SArnaldo Carvalho de Melo 				goto out;
8656ef94929SNaveen N. Rao 			else if (!(annotate_browser__jump(browser) ||
866db8fd07aSNamhyung Kim 				     annotate_browser__callq(browser, evsel, hbt))) {
867c4cceae3SArnaldo Carvalho de Melo show_sup_ins:
8686ef94929SNaveen N. Rao 				ui_helpline__puts("Actions are only available for function call/return & jump/branch instructions.");
869c4cceae3SArnaldo Carvalho de Melo 			}
870aca7a94dSNamhyung Kim 			continue;
8717bcbcd58SJiri Olsa 		}
8720c4a5bceSMartin Liška 		case 't':
87316932d77SArnaldo Carvalho de Melo 			if (notes->options->show_total_period) {
87416932d77SArnaldo Carvalho de Melo 				notes->options->show_total_period = false;
87516932d77SArnaldo Carvalho de Melo 				notes->options->show_nr_samples = true;
87616932d77SArnaldo Carvalho de Melo 			} else if (notes->options->show_nr_samples)
87716932d77SArnaldo Carvalho de Melo 				notes->options->show_nr_samples = false;
8783a555c77STaeung Song 			else
87916932d77SArnaldo Carvalho de Melo 				notes->options->show_total_period = true;
880*9761e86eSArnaldo Carvalho de Melo 			annotation__update_column_widths(notes);
8810c4a5bceSMartin Liška 			continue;
882aca7a94dSNamhyung Kim 		case K_LEFT:
883aca7a94dSNamhyung Kim 		case K_ESC:
884aca7a94dSNamhyung Kim 		case 'q':
885aca7a94dSNamhyung Kim 		case CTRL('c'):
886aca7a94dSNamhyung Kim 			goto out;
887aca7a94dSNamhyung Kim 		default:
888aca7a94dSNamhyung Kim 			continue;
889aca7a94dSNamhyung Kim 		}
890aca7a94dSNamhyung Kim 
891aca7a94dSNamhyung Kim 		if (nd != NULL)
89205e8b080SArnaldo Carvalho de Melo 			annotate_browser__set_rb_top(browser, nd);
893aca7a94dSNamhyung Kim 	}
894aca7a94dSNamhyung Kim out:
89505e8b080SArnaldo Carvalho de Melo 	ui_browser__hide(&browser->b);
896aca7a94dSNamhyung Kim 	return key;
897aca7a94dSNamhyung Kim }
898aca7a94dSNamhyung Kim 
899d5dbc518SArnaldo Carvalho de Melo int map_symbol__tui_annotate(struct map_symbol *ms, struct perf_evsel *evsel,
900d5dbc518SArnaldo Carvalho de Melo 			     struct hist_browser_timer *hbt)
901d5dbc518SArnaldo Carvalho de Melo {
9029cef4b0bSTaeung Song 	/* Set default value for show_total_period and show_nr_samples  */
9030c4a5bceSMartin Liška 	annotate_browser__opts.show_total_period =
9040c4a5bceSMartin Liška 		symbol_conf.show_total_period;
9059cef4b0bSTaeung Song 	annotate_browser__opts.show_nr_samples =
9069cef4b0bSTaeung Song 		symbol_conf.show_nr_samples;
9070c4a5bceSMartin Liška 
908d5dbc518SArnaldo Carvalho de Melo 	return symbol__tui_annotate(ms->sym, ms->map, evsel, hbt);
909d5dbc518SArnaldo Carvalho de Melo }
910d5dbc518SArnaldo Carvalho de Melo 
911db8fd07aSNamhyung Kim int hist_entry__tui_annotate(struct hist_entry *he, struct perf_evsel *evsel,
9129783adf7SNamhyung Kim 			     struct hist_browser_timer *hbt)
913aca7a94dSNamhyung Kim {
914ed426915SNamhyung Kim 	/* reset abort key so that it can get Ctrl-C as a key */
915ed426915SNamhyung Kim 	SLang_reset_tty();
916ed426915SNamhyung Kim 	SLang_init_tty(0, 0, 0);
917ed426915SNamhyung Kim 
918d5dbc518SArnaldo Carvalho de Melo 	return map_symbol__tui_annotate(&he->ms, evsel, hbt);
919aca7a94dSNamhyung Kim }
920aca7a94dSNamhyung Kim 
9212402e4a9SArnaldo Carvalho de Melo static inline int width_jumps(int n)
9222402e4a9SArnaldo Carvalho de Melo {
9232402e4a9SArnaldo Carvalho de Melo 	if (n >= 100)
9242402e4a9SArnaldo Carvalho de Melo 		return 5;
9252402e4a9SArnaldo Carvalho de Melo 	if (n / 10)
9262402e4a9SArnaldo Carvalho de Melo 		return 2;
9272402e4a9SArnaldo Carvalho de Melo 	return 1;
9282402e4a9SArnaldo Carvalho de Melo }
9292402e4a9SArnaldo Carvalho de Melo 
930db8fd07aSNamhyung Kim int symbol__tui_annotate(struct symbol *sym, struct map *map,
931db8fd07aSNamhyung Kim 			 struct perf_evsel *evsel,
9329783adf7SNamhyung Kim 			 struct hist_browser_timer *hbt)
933aca7a94dSNamhyung Kim {
9349d6bb41dSArnaldo Carvalho de Melo 	struct annotation *notes = symbol__annotation(sym);
935c0a58fb2SSamuel Liao 	size_t size;
936aca7a94dSNamhyung Kim 	struct map_symbol ms = {
937aca7a94dSNamhyung Kim 		.map = map,
938aca7a94dSNamhyung Kim 		.sym = sym,
939aca7a94dSNamhyung Kim 	};
940aca7a94dSNamhyung Kim 	struct annotate_browser browser = {
941aca7a94dSNamhyung Kim 		.b = {
942a3f895beSArnaldo Carvalho de Melo 			.refresh = annotate_browser__refresh,
943aca7a94dSNamhyung Kim 			.seek	 = ui_browser__list_head_seek,
944aca7a94dSNamhyung Kim 			.write	 = annotate_browser__write,
94529ed6e76SArnaldo Carvalho de Melo 			.filter  = disasm_line__filter,
946aca7a94dSNamhyung Kim 			.priv	 = &ms,
947aca7a94dSNamhyung Kim 			.use_navkeypressed = true,
948aca7a94dSNamhyung Kim 		},
949aca7a94dSNamhyung Kim 	};
950ee51d851SArnaldo Carvalho de Melo 	int ret = -1, err;
951c7e7b610SNamhyung Kim 	int nr_pcnt = 1;
952aca7a94dSNamhyung Kim 
953aca7a94dSNamhyung Kim 	if (sym == NULL)
954aca7a94dSNamhyung Kim 		return -1;
955aca7a94dSNamhyung Kim 
956c0a58fb2SSamuel Liao 	size = symbol__size(sym);
957c0a58fb2SSamuel Liao 
958aca7a94dSNamhyung Kim 	if (map->dso->annotate_warned)
959aca7a94dSNamhyung Kim 		return -1;
960aca7a94dSNamhyung Kim 
96116932d77SArnaldo Carvalho de Melo 	notes->options = &annotate_browser__opts;
96216932d77SArnaldo Carvalho de Melo 
9639d6bb41dSArnaldo Carvalho de Melo 	notes->offsets = zalloc(size * sizeof(struct annotation_line *));
9649d6bb41dSArnaldo Carvalho de Melo 	if (notes->offsets == NULL) {
965b793a401SArnaldo Carvalho de Melo 		ui__error("Not enough memory!");
966b793a401SArnaldo Carvalho de Melo 		return -1;
967b793a401SArnaldo Carvalho de Melo 	}
968b793a401SArnaldo Carvalho de Melo 
9693ab6db8dSJiri Olsa 	if (perf_evsel__is_group_event(evsel))
970c7e7b610SNamhyung Kim 		nr_pcnt = evsel->nr_members;
971c7e7b610SNamhyung Kim 
9724850c92eSArnaldo Carvalho de Melo 	err = symbol__annotate(sym, map, evsel, 0, &browser.arch);
973ee51d851SArnaldo Carvalho de Melo 	if (err) {
974ee51d851SArnaldo Carvalho de Melo 		char msg[BUFSIZ];
975ee51d851SArnaldo Carvalho de Melo 		symbol__strerror_disassemble(sym, map, err, msg, sizeof(msg));
976ee51d851SArnaldo Carvalho de Melo 		ui__error("Couldn't annotate %s:\n%s", sym->name, msg);
977b793a401SArnaldo Carvalho de Melo 		goto out_free_offsets;
978aca7a94dSNamhyung Kim 	}
979aca7a94dSNamhyung Kim 
98005d3f1a1SJiri Olsa 	symbol__calc_percent(sym, evsel);
98105d3f1a1SJiri Olsa 
9827727a925SArnaldo Carvalho de Melo 	ui_helpline__push("Press ESC to exit");
983aca7a94dSNamhyung Kim 
9840ca693b3SArnaldo Carvalho de Melo 	notes->start = map__rip_2objdump(map, sym->start);
985aca7a94dSNamhyung Kim 
9865bc49f61SArnaldo Carvalho de Melo 	annotation__set_offsets(notes, size);
9875bc49f61SArnaldo Carvalho de Melo 	browser.b.width = notes->max_line_len;
9886dcd57e8SArnaldo Carvalho de Melo 	annotation__mark_jump_targets(notes, sym);
989f56c083bSArnaldo Carvalho de Melo 	annotation__compute_ipc(notes, size);
990b793a401SArnaldo Carvalho de Melo 
991*9761e86eSArnaldo Carvalho de Melo 	notes->widths.addr = notes->widths.target = notes->widths.min_addr = hex_width(size);
992*9761e86eSArnaldo Carvalho de Melo 	notes->widths.max_addr = hex_width(sym->end);
993*9761e86eSArnaldo Carvalho de Melo 	notes->widths.jumps = width_jumps(notes->max_jump_sources);
9940553e83dSArnaldo Carvalho de Melo 	notes->nr_events = nr_pcnt;
9951cf5f98aSArnaldo Carvalho de Melo 	browser.b.nr_entries = notes->nr_entries;
996aca7a94dSNamhyung Kim 	browser.b.entries = &notes->src->source,
997aca7a94dSNamhyung Kim 	browser.b.width += 18; /* Percentage */
998e9823b21SArnaldo Carvalho de Melo 
99916932d77SArnaldo Carvalho de Melo 	if (notes->options->hide_src_code)
10001cf5f98aSArnaldo Carvalho de Melo 		ui_browser__init_asm_mode(&browser.b);
1001e9823b21SArnaldo Carvalho de Melo 
1002*9761e86eSArnaldo Carvalho de Melo 	annotation__update_column_widths(notes);
1003e9823b21SArnaldo Carvalho de Melo 
1004db8fd07aSNamhyung Kim 	ret = annotate_browser__run(&browser, evsel, hbt);
1005f8eb37bdSJiri Olsa 
1006f8eb37bdSJiri Olsa 	annotated_source__purge(notes->src);
1007b793a401SArnaldo Carvalho de Melo 
1008b793a401SArnaldo Carvalho de Melo out_free_offsets:
10099d6bb41dSArnaldo Carvalho de Melo 	zfree(&notes->offsets);
1010aca7a94dSNamhyung Kim 	return ret;
1011aca7a94dSNamhyung Kim }
1012c323cf04SArnaldo Carvalho de Melo 
1013c323cf04SArnaldo Carvalho de Melo #define ANNOTATE_CFG(n) \
1014c323cf04SArnaldo Carvalho de Melo 	{ .name = #n, .value = &annotate_browser__opts.n, }
1015c323cf04SArnaldo Carvalho de Melo 
1016c323cf04SArnaldo Carvalho de Melo /*
1017c323cf04SArnaldo Carvalho de Melo  * Keep the entries sorted, they are bsearch'ed
1018c323cf04SArnaldo Carvalho de Melo  */
10197c3102b8SArnaldo Carvalho de Melo static struct annotate_config {
1020c323cf04SArnaldo Carvalho de Melo 	const char *name;
1021c323cf04SArnaldo Carvalho de Melo 	bool *value;
1022c323cf04SArnaldo Carvalho de Melo } annotate__configs[] = {
1023c323cf04SArnaldo Carvalho de Melo 	ANNOTATE_CFG(hide_src_code),
1024c323cf04SArnaldo Carvalho de Melo 	ANNOTATE_CFG(jump_arrows),
1025e592488cSAndi Kleen 	ANNOTATE_CFG(show_linenr),
1026c323cf04SArnaldo Carvalho de Melo 	ANNOTATE_CFG(show_nr_jumps),
10279cef4b0bSTaeung Song 	ANNOTATE_CFG(show_nr_samples),
10280c4a5bceSMartin Liška 	ANNOTATE_CFG(show_total_period),
102939ff7cdbSNamhyung Kim 	ANNOTATE_CFG(use_offset),
1030c323cf04SArnaldo Carvalho de Melo };
1031c323cf04SArnaldo Carvalho de Melo 
1032c323cf04SArnaldo Carvalho de Melo #undef ANNOTATE_CFG
1033c323cf04SArnaldo Carvalho de Melo 
1034c323cf04SArnaldo Carvalho de Melo static int annotate_config__cmp(const void *name, const void *cfgp)
1035c323cf04SArnaldo Carvalho de Melo {
10367c3102b8SArnaldo Carvalho de Melo 	const struct annotate_config *cfg = cfgp;
1037c323cf04SArnaldo Carvalho de Melo 
1038c323cf04SArnaldo Carvalho de Melo 	return strcmp(name, cfg->name);
1039c323cf04SArnaldo Carvalho de Melo }
1040c323cf04SArnaldo Carvalho de Melo 
10411d037ca1SIrina Tirdea static int annotate__config(const char *var, const char *value,
10421d037ca1SIrina Tirdea 			    void *data __maybe_unused)
1043c323cf04SArnaldo Carvalho de Melo {
10447c3102b8SArnaldo Carvalho de Melo 	struct annotate_config *cfg;
1045c323cf04SArnaldo Carvalho de Melo 	const char *name;
1046c323cf04SArnaldo Carvalho de Melo 
10478e99b6d4SArnaldo Carvalho de Melo 	if (!strstarts(var, "annotate."))
1048c323cf04SArnaldo Carvalho de Melo 		return 0;
1049c323cf04SArnaldo Carvalho de Melo 
1050c323cf04SArnaldo Carvalho de Melo 	name = var + 9;
1051c323cf04SArnaldo Carvalho de Melo 	cfg = bsearch(name, annotate__configs, ARRAY_SIZE(annotate__configs),
10527c3102b8SArnaldo Carvalho de Melo 		      sizeof(struct annotate_config), annotate_config__cmp);
1053c323cf04SArnaldo Carvalho de Melo 
1054c323cf04SArnaldo Carvalho de Melo 	if (cfg == NULL)
1055f06cff7cSArnaldo Carvalho de Melo 		ui__warning("%s variable unknown, ignoring...", var);
1056f06cff7cSArnaldo Carvalho de Melo 	else
1057c323cf04SArnaldo Carvalho de Melo 		*cfg->value = perf_config_bool(name, value);
1058c323cf04SArnaldo Carvalho de Melo 	return 0;
1059c323cf04SArnaldo Carvalho de Melo }
1060c323cf04SArnaldo Carvalho de Melo 
1061c323cf04SArnaldo Carvalho de Melo void annotate_browser__init(void)
1062c323cf04SArnaldo Carvalho de Melo {
1063c323cf04SArnaldo Carvalho de Melo 	perf_config(annotate__config, NULL);
1064c323cf04SArnaldo Carvalho de Melo }
1065