xref: /linux/tools/perf/ui/browsers/annotate.c (revision a23e1966932464e1c5226cb9ac4ce1d5fc10ba22)
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;
30aca7a94dSNamhyung Kim 	bool			    searching_backwards;
31aca7a94dSNamhyung Kim 	char			    search_bf[128];
32aca7a94dSNamhyung Kim };
33aca7a94dSNamhyung Kim 
3495aa89d9SArnaldo Carvalho de Melo static inline struct annotation *browser__annotation(struct ui_browser *browser)
3595aa89d9SArnaldo Carvalho de Melo {
3695aa89d9SArnaldo Carvalho de Melo 	struct map_symbol *ms = browser->priv;
3795aa89d9SArnaldo Carvalho de Melo 	return symbol__annotation(ms->sym);
3895aa89d9SArnaldo Carvalho de Melo }
3995aa89d9SArnaldo Carvalho de Melo 
402fa21d69SNamhyung Kim static bool disasm_line__filter(struct ui_browser *browser __maybe_unused, void *entry)
41aca7a94dSNamhyung Kim {
42d5490b96SJiri Olsa 	struct annotation_line *al = list_entry(entry, struct annotation_line, node);
432fa21d69SNamhyung Kim 	return annotation_line__filter(al);
44aca7a94dSNamhyung Kim }
45aca7a94dSNamhyung Kim 
4627feb761SArnaldo Carvalho de Melo static int ui_browser__jumps_percent_color(struct ui_browser *browser, int nr, bool current)
472402e4a9SArnaldo Carvalho de Melo {
4827feb761SArnaldo Carvalho de Melo 	struct annotation *notes = browser__annotation(browser);
49bc1c0f3dSArnaldo Carvalho de Melo 
5027feb761SArnaldo Carvalho de Melo 	if (current && (!browser->use_navkeypressed || browser->navkeypressed))
512402e4a9SArnaldo Carvalho de Melo 		return HE_COLORSET_SELECTED;
52bc1c0f3dSArnaldo Carvalho de Melo 	if (nr == notes->max_jump_sources)
532402e4a9SArnaldo Carvalho de Melo 		return HE_COLORSET_TOP;
542402e4a9SArnaldo Carvalho de Melo 	if (nr > 1)
552402e4a9SArnaldo Carvalho de Melo 		return HE_COLORSET_MEDIUM;
562402e4a9SArnaldo Carvalho de Melo 	return HE_COLORSET_NORMAL;
572402e4a9SArnaldo Carvalho de Melo }
582402e4a9SArnaldo Carvalho de Melo 
59a1e9b74cSArnaldo Carvalho de Melo static int ui_browser__set_jumps_percent_color(void *browser, int nr, bool current)
602402e4a9SArnaldo Carvalho de Melo {
6127feb761SArnaldo Carvalho de Melo 	 int color = ui_browser__jumps_percent_color(browser, nr, current);
6227feb761SArnaldo Carvalho de Melo 	 return ui_browser__set_color(browser, color);
632402e4a9SArnaldo Carvalho de Melo }
642402e4a9SArnaldo Carvalho de Melo 
65a1e9b74cSArnaldo Carvalho de Melo static int annotate_browser__set_color(void *browser, int color)
66aca7a94dSNamhyung Kim {
67a1e9b74cSArnaldo Carvalho de Melo 	return ui_browser__set_color(browser, color);
684ea08b52SArnaldo Carvalho de Melo }
694ea08b52SArnaldo Carvalho de Melo 
70a1e9b74cSArnaldo Carvalho de Melo static void annotate_browser__write_graph(void *browser, int graph)
71a1e9b74cSArnaldo Carvalho de Melo {
72a1e9b74cSArnaldo Carvalho de Melo 	ui_browser__write_graph(browser, graph);
73a5433b3eSJiri Olsa }
74a5433b3eSJiri Olsa 
752ba5eca1SArnaldo Carvalho de Melo static void annotate_browser__set_percent_color(void *browser, double percent, bool current)
762ba5eca1SArnaldo Carvalho de Melo {
772ba5eca1SArnaldo Carvalho de Melo 	ui_browser__set_percent_color(browser, percent, current);
782ba5eca1SArnaldo Carvalho de Melo }
792ba5eca1SArnaldo Carvalho de Melo 
802ba5eca1SArnaldo Carvalho de Melo static void annotate_browser__printf(void *browser, const char *fmt, ...)
812ba5eca1SArnaldo Carvalho de Melo {
822ba5eca1SArnaldo Carvalho de Melo 	va_list args;
832ba5eca1SArnaldo Carvalho de Melo 
842ba5eca1SArnaldo Carvalho de Melo 	va_start(args, fmt);
852ba5eca1SArnaldo Carvalho de Melo 	ui_browser__vprintf(browser, fmt, args);
862ba5eca1SArnaldo Carvalho de Melo 	va_end(args);
872ba5eca1SArnaldo Carvalho de Melo }
882ba5eca1SArnaldo Carvalho de Melo 
89a5433b3eSJiri Olsa static void annotate_browser__write(struct ui_browser *browser, void *entry, int row)
90a5433b3eSJiri Olsa {
91a5433b3eSJiri Olsa 	struct annotate_browser *ab = container_of(browser, struct annotate_browser, b);
9295aa89d9SArnaldo Carvalho de Melo 	struct annotation *notes = browser__annotation(browser);
93a5433b3eSJiri Olsa 	struct annotation_line *al = list_entry(entry, struct annotation_line, node);
94da201963SArnaldo Carvalho de Melo 	const bool is_current_entry = ui_browser__is_current_entry(browser, row);
95c298304bSArnaldo Carvalho de Melo 	struct annotation_write_ops ops = {
96c298304bSArnaldo Carvalho de Melo 		.first_line		 = row == 0,
97da201963SArnaldo Carvalho de Melo 		.current_entry		 = is_current_entry,
9822197fb2SNamhyung Kim 		.change_color		 = (!annotate_opts.hide_src_code &&
99da201963SArnaldo Carvalho de Melo 					    (!is_current_entry ||
100c298304bSArnaldo Carvalho de Melo 					     (browser->use_navkeypressed &&
101c298304bSArnaldo Carvalho de Melo 					      !browser->navkeypressed))),
102c298304bSArnaldo Carvalho de Melo 		.width			 = browser->width,
103c298304bSArnaldo Carvalho de Melo 		.obj			 = browser,
104c298304bSArnaldo Carvalho de Melo 		.set_color		 = annotate_browser__set_color,
105c298304bSArnaldo Carvalho de Melo 		.set_percent_color	 = annotate_browser__set_percent_color,
106c298304bSArnaldo Carvalho de Melo 		.set_jumps_percent_color = ui_browser__set_jumps_percent_color,
107c298304bSArnaldo Carvalho de Melo 		.printf			 = annotate_browser__printf,
108c298304bSArnaldo Carvalho de Melo 		.write_graph		 = annotate_browser__write_graph,
109c298304bSArnaldo Carvalho de Melo 	};
110a5433b3eSJiri Olsa 
111a5433b3eSJiri Olsa 	/* The scroll bar isn't being used */
112a5433b3eSJiri Olsa 	if (!browser->navkeypressed)
113c298304bSArnaldo Carvalho de Melo 		ops.width += 1;
114a5433b3eSJiri Olsa 
11541fd3cacSNamhyung Kim 	annotation_line__write(al, notes, &ops);
116aca7a94dSNamhyung Kim 
117c298304bSArnaldo Carvalho de Melo 	if (ops.current_entry)
118a5433b3eSJiri Olsa 		ab->selection = al;
119aca7a94dSNamhyung Kim }
120aca7a94dSNamhyung Kim 
1217efbcc8cSRavi Bangoria static int is_fused(struct annotate_browser *ab, struct disasm_line *cursor)
1227e63a13aSJin Yao {
123a17c4ca0SJiri Olsa 	struct disasm_line *pos = list_prev_entry(cursor, al.node);
1247e63a13aSJin Yao 	const char *name;
1257efbcc8cSRavi Bangoria 	int diff = 1;
1267efbcc8cSRavi Bangoria 
1277efbcc8cSRavi Bangoria 	while (pos && pos->al.offset == -1) {
1287efbcc8cSRavi Bangoria 		pos = list_prev_entry(pos, al.node);
12922197fb2SNamhyung Kim 		if (!annotate_opts.hide_src_code)
1307efbcc8cSRavi Bangoria 			diff++;
1317efbcc8cSRavi Bangoria 	}
1327e63a13aSJin Yao 
1337e63a13aSJin Yao 	if (!pos)
1347efbcc8cSRavi Bangoria 		return 0;
1357e63a13aSJin Yao 
1367e63a13aSJin Yao 	if (ins__is_lock(&pos->ins))
1377e63a13aSJin Yao 		name = pos->ops.locked.ins.name;
1387e63a13aSJin Yao 	else
1397e63a13aSJin Yao 		name = pos->ins.name;
1407e63a13aSJin Yao 
1417e63a13aSJin Yao 	if (!name || !cursor->ins.name)
1427efbcc8cSRavi Bangoria 		return 0;
1437e63a13aSJin Yao 
1447efbcc8cSRavi Bangoria 	if (ins__is_fused(ab->arch, name, cursor->ins.name))
1457efbcc8cSRavi Bangoria 		return diff;
1467efbcc8cSRavi Bangoria 	return 0;
1477e63a13aSJin Yao }
1487e63a13aSJin Yao 
1499d1ef56dSArnaldo Carvalho de Melo static void annotate_browser__draw_current_jump(struct ui_browser *browser)
150a3f895beSArnaldo Carvalho de Melo {
151a3f895beSArnaldo Carvalho de Melo 	struct annotate_browser *ab = container_of(browser, struct annotate_browser, b);
1527bcbcd58SJiri Olsa 	struct disasm_line *cursor = disasm_line(ab->selection);
153a5ef2702SJiri Olsa 	struct annotation_line *target;
15483b1f2aaSArnaldo Carvalho de Melo 	unsigned int from, to;
15532ae1efdSNamhyung Kim 	struct map_symbol *ms = ab->b.priv;
15632ae1efdSNamhyung Kim 	struct symbol *sym = ms->sym;
1570e83a7e9SArnaldo Carvalho de Melo 	struct annotation *notes = symbol__annotation(sym);
1586af612d2SArnaldo Carvalho de Melo 	u8 pcnt_width = annotation__pcnt_width(notes);
15900ea0eb2SArnaldo Carvalho de Melo 	int width;
1607efbcc8cSRavi Bangoria 	int diff = 0;
16132ae1efdSNamhyung Kim 
16232ae1efdSNamhyung Kim 	/* PLT symbols contain external offsets */
16332ae1efdSNamhyung Kim 	if (strstr(sym->name, "@plt"))
16432ae1efdSNamhyung Kim 		return;
165a3f895beSArnaldo Carvalho de Melo 
1662eff0611SArnaldo Carvalho de Melo 	if (!disasm_line__is_valid_local_jump(cursor, sym))
167a3f895beSArnaldo Carvalho de Melo 		return;
168a3f895beSArnaldo Carvalho de Melo 
1699c04409dSArnaldo Carvalho de Melo 	/*
1709c04409dSArnaldo Carvalho de Melo 	 * This first was seen with a gcc function, _cpp_lex_token, that
1719c04409dSArnaldo Carvalho de Melo 	 * has the usual jumps:
1729c04409dSArnaldo Carvalho de Melo 	 *
1739c04409dSArnaldo Carvalho de Melo 	 *  │1159e6c: ↓ jne    115aa32 <_cpp_lex_token@@Base+0xf92>
1749c04409dSArnaldo Carvalho de Melo 	 *
1759c04409dSArnaldo Carvalho de Melo 	 * I.e. jumps to a label inside that function (_cpp_lex_token), and
1769c04409dSArnaldo Carvalho de Melo 	 * those works, but also this kind:
1779c04409dSArnaldo Carvalho de Melo 	 *
1789c04409dSArnaldo Carvalho de Melo 	 *  │1159e8b: ↓ jne    c469be <cpp_named_operator2name@@Base+0xa72>
1799c04409dSArnaldo Carvalho de Melo 	 *
1809c04409dSArnaldo Carvalho de Melo 	 *  I.e. jumps to another function, outside _cpp_lex_token, which
1819c04409dSArnaldo Carvalho de Melo 	 *  are not being correctly handled generating as a side effect references
1829c04409dSArnaldo Carvalho de Melo 	 *  to ab->offset[] entries that are set to NULL, so to make this code
1839c04409dSArnaldo Carvalho de Melo 	 *  more robust, check that here.
1849c04409dSArnaldo Carvalho de Melo 	 *
1859c04409dSArnaldo Carvalho de Melo 	 *  A proper fix for will be put in place, looking at the function
1869c04409dSArnaldo Carvalho de Melo 	 *  name right after the '<' token and probably treating this like a
1879c04409dSArnaldo Carvalho de Melo 	 *  'call' instruction.
1889c04409dSArnaldo Carvalho de Melo 	 */
189b753d48fSNamhyung Kim 	target = notes->src->offsets[cursor->ops.target.offset];
1909c04409dSArnaldo Carvalho de Melo 	if (target == NULL) {
1919d6bb41dSArnaldo Carvalho de Melo 		ui_helpline__printf("WARN: jump target inconsistency, press 'o', notes->offsets[%#x] = NULL\n",
1929c04409dSArnaldo Carvalho de Melo 				    cursor->ops.target.offset);
1939c04409dSArnaldo Carvalho de Melo 		return;
1949c04409dSArnaldo Carvalho de Melo 	}
1959d1ef56dSArnaldo Carvalho de Melo 
19622197fb2SNamhyung Kim 	if (annotate_opts.hide_src_code) {
1974850c92eSArnaldo Carvalho de Melo 		from = cursor->al.idx_asm;
1984850c92eSArnaldo Carvalho de Melo 		to = target->idx_asm;
199a3f895beSArnaldo Carvalho de Melo 	} else {
2004850c92eSArnaldo Carvalho de Melo 		from = (u64)cursor->al.idx;
2014850c92eSArnaldo Carvalho de Melo 		to = (u64)target->idx;
202a3f895beSArnaldo Carvalho de Melo 	}
203a3f895beSArnaldo Carvalho de Melo 
2040e83a7e9SArnaldo Carvalho de Melo 	width = annotation__cycles_width(notes);
205b40982e8SJin Yao 
20678ce08dfSTaeung Song 	ui_browser__set_color(browser, HE_COLORSET_JUMP_ARROWS);
207b40982e8SJin Yao 	__ui_browser__line_arrow(browser,
2089761e86eSArnaldo Carvalho de Melo 				 pcnt_width + 2 + notes->widths.addr + width,
209c7e7b610SNamhyung Kim 				 from, to);
2107e63a13aSJin Yao 
2117efbcc8cSRavi Bangoria 	diff = is_fused(ab, cursor);
2127efbcc8cSRavi Bangoria 	if (diff > 0) {
2137e63a13aSJin Yao 		ui_browser__mark_fused(browser,
2149761e86eSArnaldo Carvalho de Melo 				       pcnt_width + 3 + notes->widths.addr + width,
2157efbcc8cSRavi Bangoria 				       from - diff, diff, to > from);
2167e63a13aSJin Yao 	}
217a3f895beSArnaldo Carvalho de Melo }
218a3f895beSArnaldo Carvalho de Melo 
219a3f895beSArnaldo Carvalho de Melo static unsigned int annotate_browser__refresh(struct ui_browser *browser)
220a3f895beSArnaldo Carvalho de Melo {
22195aa89d9SArnaldo Carvalho de Melo 	struct annotation *notes = browser__annotation(browser);
222a3f895beSArnaldo Carvalho de Melo 	int ret = ui_browser__list_head_refresh(browser);
2236af612d2SArnaldo Carvalho de Melo 	int pcnt_width = annotation__pcnt_width(notes);
224a3f895beSArnaldo Carvalho de Melo 
22522197fb2SNamhyung Kim 	if (annotate_opts.jump_arrows)
2269d1ef56dSArnaldo Carvalho de Melo 		annotate_browser__draw_current_jump(browser);
227a3f895beSArnaldo Carvalho de Melo 
22883b1f2aaSArnaldo Carvalho de Melo 	ui_browser__set_color(browser, HE_COLORSET_NORMAL);
229e726c851SArnaldo Carvalho de Melo 	__ui_browser__vline(browser, pcnt_width, 0, browser->rows - 1);
230a3f895beSArnaldo Carvalho de Melo 	return ret;
231a3f895beSArnaldo Carvalho de Melo }
232a3f895beSArnaldo Carvalho de Melo 
233da06d568SHe Kuang static double disasm__cmp(struct annotation_line *a, struct annotation_line *b,
234da06d568SHe Kuang 						  int percent_type)
235c7e7b610SNamhyung Kim {
236c7e7b610SNamhyung Kim 	int i;
237c7e7b610SNamhyung Kim 
238c2f938baSJiri Olsa 	for (i = 0; i < a->data_nr; i++) {
239da06d568SHe Kuang 		if (a->data[i].percent[percent_type] == b->data[i].percent[percent_type])
240c7e7b610SNamhyung Kim 			continue;
241da06d568SHe Kuang 		return a->data[i].percent[percent_type] -
242da06d568SHe Kuang 			   b->data[i].percent[percent_type];
243c7e7b610SNamhyung Kim 	}
244c7e7b610SNamhyung Kim 	return 0;
245c7e7b610SNamhyung Kim }
246c7e7b610SNamhyung Kim 
247da06d568SHe Kuang static void disasm_rb_tree__insert(struct annotate_browser *browser,
248da06d568SHe Kuang 				struct annotation_line *al)
249aca7a94dSNamhyung Kim {
250da06d568SHe Kuang 	struct rb_root *root = &browser->entries;
25129ed6e76SArnaldo Carvalho de Melo 	struct rb_node **p = &root->rb_node;
252aca7a94dSNamhyung Kim 	struct rb_node *parent = NULL;
2533ab6db8dSJiri Olsa 	struct annotation_line *l;
254aca7a94dSNamhyung Kim 
255aca7a94dSNamhyung Kim 	while (*p != NULL) {
256aca7a94dSNamhyung Kim 		parent = *p;
2573ab6db8dSJiri Olsa 		l = rb_entry(parent, struct annotation_line, rb_node);
258c7e7b610SNamhyung Kim 
25922197fb2SNamhyung Kim 		if (disasm__cmp(al, l, annotate_opts.percent_type) < 0)
260aca7a94dSNamhyung Kim 			p = &(*p)->rb_left;
261aca7a94dSNamhyung Kim 		else
262aca7a94dSNamhyung Kim 			p = &(*p)->rb_right;
263aca7a94dSNamhyung Kim 	}
2643ab6db8dSJiri Olsa 	rb_link_node(&al->rb_node, parent, p);
2653ab6db8dSJiri Olsa 	rb_insert_color(&al->rb_node, root);
266aca7a94dSNamhyung Kim }
267aca7a94dSNamhyung Kim 
26805e8b080SArnaldo Carvalho de Melo static void annotate_browser__set_top(struct annotate_browser *browser,
269ec03a77dSJiri Olsa 				      struct annotation_line *pos, u32 idx)
270aca7a94dSNamhyung Kim {
271aca7a94dSNamhyung Kim 	unsigned back;
272aca7a94dSNamhyung Kim 
27305e8b080SArnaldo Carvalho de Melo 	ui_browser__refresh_dimensions(&browser->b);
27405e8b080SArnaldo Carvalho de Melo 	back = browser->b.height / 2;
27505e8b080SArnaldo Carvalho de Melo 	browser->b.top_idx = browser->b.index = idx;
276aca7a94dSNamhyung Kim 
27705e8b080SArnaldo Carvalho de Melo 	while (browser->b.top_idx != 0 && back != 0) {
278ec03a77dSJiri Olsa 		pos = list_entry(pos->node.prev, struct annotation_line, node);
279aca7a94dSNamhyung Kim 
2802fa21d69SNamhyung Kim 		if (annotation_line__filter(pos))
281aca7a94dSNamhyung Kim 			continue;
282aca7a94dSNamhyung Kim 
28305e8b080SArnaldo Carvalho de Melo 		--browser->b.top_idx;
284aca7a94dSNamhyung Kim 		--back;
285aca7a94dSNamhyung Kim 	}
286aca7a94dSNamhyung Kim 
287ec03a77dSJiri Olsa 	browser->b.top = pos;
28805e8b080SArnaldo Carvalho de Melo 	browser->b.navkeypressed = true;
289aca7a94dSNamhyung Kim }
290aca7a94dSNamhyung Kim 
291aca7a94dSNamhyung Kim static void annotate_browser__set_rb_top(struct annotate_browser *browser,
292aca7a94dSNamhyung Kim 					 struct rb_node *nd)
293aca7a94dSNamhyung Kim {
2944850c92eSArnaldo Carvalho de Melo 	struct annotation_line * pos = rb_entry(nd, struct annotation_line, rb_node);
2954850c92eSArnaldo Carvalho de Melo 	u32 idx = pos->idx;
296aca7a94dSNamhyung Kim 
29722197fb2SNamhyung Kim 	if (annotate_opts.hide_src_code)
2984850c92eSArnaldo Carvalho de Melo 		idx = pos->idx_asm;
299a44b45f2SArnaldo Carvalho de Melo 	annotate_browser__set_top(browser, pos, idx);
300aca7a94dSNamhyung Kim 	browser->curr_hot = nd;
301aca7a94dSNamhyung Kim }
302aca7a94dSNamhyung Kim 
303aca7a94dSNamhyung Kim static void annotate_browser__calc_percent(struct annotate_browser *browser,
30432dcd021SJiri Olsa 					   struct evsel *evsel)
305aca7a94dSNamhyung Kim {
306aca7a94dSNamhyung Kim 	struct map_symbol *ms = browser->b.priv;
307aca7a94dSNamhyung Kim 	struct symbol *sym = ms->sym;
308aca7a94dSNamhyung Kim 	struct annotation *notes = symbol__annotation(sym);
309c4c72436SJiri Olsa 	struct disasm_line *pos;
310aca7a94dSNamhyung Kim 
311aca7a94dSNamhyung Kim 	browser->entries = RB_ROOT;
312aca7a94dSNamhyung Kim 
3132e9f9d4aSIan Rogers 	annotation__lock(notes);
314aca7a94dSNamhyung Kim 
315e425da6cSJiri Olsa 	symbol__calc_percent(sym, evsel);
316e425da6cSJiri Olsa 
317a17c4ca0SJiri Olsa 	list_for_each_entry(pos, &notes->src->source, al.node) {
318c7e7b610SNamhyung Kim 		double max_percent = 0.0;
319c7e7b610SNamhyung Kim 		int i;
320e64aa75bSNamhyung Kim 
321d5490b96SJiri Olsa 		if (pos->al.offset == -1) {
3225b12adc8SJiri Olsa 			RB_CLEAR_NODE(&pos->al.rb_node);
323e64aa75bSNamhyung Kim 			continue;
324e64aa75bSNamhyung Kim 		}
325e64aa75bSNamhyung Kim 
326c2f938baSJiri Olsa 		for (i = 0; i < pos->al.data_nr; i++) {
3276d9f0c2dSJiri Olsa 			double percent;
3280c4a5bceSMartin Liška 
3296d9f0c2dSJiri Olsa 			percent = annotation_data__percent(&pos->al.data[i],
33022197fb2SNamhyung Kim 							   annotate_opts.percent_type);
3316d9f0c2dSJiri Olsa 
3326d9f0c2dSJiri Olsa 			if (max_percent < percent)
3336d9f0c2dSJiri Olsa 				max_percent = percent;
334c7e7b610SNamhyung Kim 		}
335c7e7b610SNamhyung Kim 
336de2c7eb5SNamhyung Kim 		if (max_percent < 0.01 && (!pos->al.cycles || pos->al.cycles->ipc == 0)) {
3375b12adc8SJiri Olsa 			RB_CLEAR_NODE(&pos->al.rb_node);
338aca7a94dSNamhyung Kim 			continue;
339aca7a94dSNamhyung Kim 		}
340da06d568SHe Kuang 		disasm_rb_tree__insert(browser, &pos->al);
341aca7a94dSNamhyung Kim 	}
3422e9f9d4aSIan Rogers 	annotation__unlock(notes);
343aca7a94dSNamhyung Kim 
344aca7a94dSNamhyung Kim 	browser->curr_hot = rb_last(&browser->entries);
345aca7a94dSNamhyung Kim }
346aca7a94dSNamhyung Kim 
3476de249d6SRiccardo Mancini static struct annotation_line *annotate_browser__find_next_asm_line(
3486de249d6SRiccardo Mancini 					struct annotate_browser *browser,
3496de249d6SRiccardo Mancini 					struct annotation_line *al)
3506de249d6SRiccardo Mancini {
3516de249d6SRiccardo Mancini 	struct annotation_line *it = al;
3526de249d6SRiccardo Mancini 
3536de249d6SRiccardo Mancini 	/* find next asm line */
3545a4451e4SRiccardo Mancini 	list_for_each_entry_continue(it, browser->b.entries, node) {
3556de249d6SRiccardo Mancini 		if (it->idx_asm >= 0)
3566de249d6SRiccardo Mancini 			return it;
3576de249d6SRiccardo Mancini 	}
3586de249d6SRiccardo Mancini 
3596de249d6SRiccardo Mancini 	/* no asm line found forwards, try backwards */
3606de249d6SRiccardo Mancini 	it = al;
3615a4451e4SRiccardo Mancini 	list_for_each_entry_continue_reverse(it, browser->b.entries, node) {
3626de249d6SRiccardo Mancini 		if (it->idx_asm >= 0)
3636de249d6SRiccardo Mancini 			return it;
3646de249d6SRiccardo Mancini 	}
3656de249d6SRiccardo Mancini 
3666de249d6SRiccardo Mancini 	/* There are no asm lines */
3676de249d6SRiccardo Mancini 	return NULL;
3686de249d6SRiccardo Mancini }
3696de249d6SRiccardo Mancini 
370aca7a94dSNamhyung Kim static bool annotate_browser__toggle_source(struct annotate_browser *browser)
371aca7a94dSNamhyung Kim {
37295aa89d9SArnaldo Carvalho de Melo 	struct annotation *notes = browser__annotation(&browser->b);
373ec03a77dSJiri Olsa 	struct annotation_line *al;
374aca7a94dSNamhyung Kim 	off_t offset = browser->b.index - browser->b.top_idx;
375aca7a94dSNamhyung Kim 
376aca7a94dSNamhyung Kim 	browser->b.seek(&browser->b, offset, SEEK_CUR);
377ec03a77dSJiri Olsa 	al = list_entry(browser->b.top, struct annotation_line, node);
378aca7a94dSNamhyung Kim 
37922197fb2SNamhyung Kim 	if (annotate_opts.hide_src_code) {
3804850c92eSArnaldo Carvalho de Melo 		if (al->idx_asm < offset)
3814850c92eSArnaldo Carvalho de Melo 			offset = al->idx;
382aca7a94dSNamhyung Kim 
3830aae4c99SNamhyung Kim 		browser->b.nr_entries = notes->src->nr_entries;
38422197fb2SNamhyung Kim 		annotate_opts.hide_src_code = false;
385aca7a94dSNamhyung Kim 		browser->b.seek(&browser->b, -offset, SEEK_CUR);
3864850c92eSArnaldo Carvalho de Melo 		browser->b.top_idx = al->idx - offset;
3874850c92eSArnaldo Carvalho de Melo 		browser->b.index = al->idx;
388aca7a94dSNamhyung Kim 	} else {
3894850c92eSArnaldo Carvalho de Melo 		if (al->idx_asm < 0) {
3906de249d6SRiccardo Mancini 			/* move cursor to next asm line */
3916de249d6SRiccardo Mancini 			al = annotate_browser__find_next_asm_line(browser, al);
3926de249d6SRiccardo Mancini 			if (!al) {
393aca7a94dSNamhyung Kim 				browser->b.seek(&browser->b, -offset, SEEK_CUR);
394aca7a94dSNamhyung Kim 				return false;
395aca7a94dSNamhyung Kim 			}
3966de249d6SRiccardo Mancini 		}
397aca7a94dSNamhyung Kim 
3984850c92eSArnaldo Carvalho de Melo 		if (al->idx_asm < offset)
3994850c92eSArnaldo Carvalho de Melo 			offset = al->idx_asm;
400aca7a94dSNamhyung Kim 
4010aae4c99SNamhyung Kim 		browser->b.nr_entries = notes->src->nr_asm_entries;
40222197fb2SNamhyung Kim 		annotate_opts.hide_src_code = true;
403aca7a94dSNamhyung Kim 		browser->b.seek(&browser->b, -offset, SEEK_CUR);
4044850c92eSArnaldo Carvalho de Melo 		browser->b.top_idx = al->idx_asm - offset;
4054850c92eSArnaldo Carvalho de Melo 		browser->b.index = al->idx_asm;
406aca7a94dSNamhyung Kim 	}
407aca7a94dSNamhyung Kim 
408aca7a94dSNamhyung Kim 	return true;
409aca7a94dSNamhyung Kim }
410aca7a94dSNamhyung Kim 
4112777b81bSMartin Liska #define SYM_TITLE_MAX_SIZE (PATH_MAX + 64)
4122777b81bSMartin Liska 
4132777b81bSMartin Liska static void annotate_browser__show_full_location(struct ui_browser *browser)
4142777b81bSMartin Liska {
4152777b81bSMartin Liska 	struct annotate_browser *ab = container_of(browser, struct annotate_browser, b);
4162777b81bSMartin Liska 	struct disasm_line *cursor = disasm_line(ab->selection);
4172777b81bSMartin Liska 	struct annotation_line *al = &cursor->al;
4182777b81bSMartin Liska 
4192777b81bSMartin Liska 	if (al->offset != -1)
4202777b81bSMartin Liska 		ui_helpline__puts("Only available for source code lines.");
4212777b81bSMartin Liska 	else if (al->fileloc == NULL)
4222777b81bSMartin Liska 		ui_helpline__puts("No source file location.");
4232777b81bSMartin Liska 	else {
4242777b81bSMartin Liska 		char help_line[SYM_TITLE_MAX_SIZE];
4252777b81bSMartin Liska 		sprintf (help_line, "Source file location: %s", al->fileloc);
4262777b81bSMartin Liska 		ui_helpline__puts(help_line);
4272777b81bSMartin Liska 	}
4282777b81bSMartin Liska }
4292777b81bSMartin Liska 
4301cf5f98aSArnaldo Carvalho de Melo static void ui_browser__init_asm_mode(struct ui_browser *browser)
431e9823b21SArnaldo Carvalho de Melo {
4321cf5f98aSArnaldo Carvalho de Melo 	struct annotation *notes = browser__annotation(browser);
4331cf5f98aSArnaldo Carvalho de Melo 	ui_browser__reset_index(browser);
4340aae4c99SNamhyung Kim 	browser->nr_entries = notes->src->nr_asm_entries;
435e9823b21SArnaldo Carvalho de Melo }
436e9823b21SArnaldo Carvalho de Melo 
43734f77abcSAdrian Hunter static int sym_title(struct symbol *sym, struct map *map, char *title,
4383e0d7953SJiri Olsa 		     size_t sz, int percent_type)
43934f77abcSAdrian Hunter {
44063df0e4bSIan Rogers 	return snprintf(title, sz, "%s  %s [Percent: %s]", sym->name,
44163df0e4bSIan Rogers 			map__dso(map)->long_name,
4423e0d7953SJiri Olsa 			percent_type_str(percent_type));
44334f77abcSAdrian Hunter }
44434f77abcSAdrian Hunter 
445e4cc91b8SArnaldo Carvalho de Melo /*
4464d39c89fSIngo Molnar  * This can be called from external jumps, i.e. jumps from one function
447e4cc91b8SArnaldo Carvalho de Melo  * to another, like from the kernel's entry_SYSCALL_64 function to the
448e4cc91b8SArnaldo Carvalho de Melo  * swapgs_restore_regs_and_return_to_usermode() function.
449e4cc91b8SArnaldo Carvalho de Melo  *
450e4cc91b8SArnaldo Carvalho de Melo  * So all we check here is that dl->ops.target.sym is set, if it is, just
451e4cc91b8SArnaldo Carvalho de Melo  * go to that function and when exiting from its disassembly, come back
452e4cc91b8SArnaldo Carvalho de Melo  * to the calling function.
453e4cc91b8SArnaldo Carvalho de Melo  */
454db8fd07aSNamhyung Kim static bool annotate_browser__callq(struct annotate_browser *browser,
45532dcd021SJiri Olsa 				    struct evsel *evsel,
4569783adf7SNamhyung Kim 				    struct hist_browser_timer *hbt)
457aca7a94dSNamhyung Kim {
45829754894SArnaldo Carvalho de Melo 	struct map_symbol *ms = browser->b.priv, target_ms;
4597bcbcd58SJiri Olsa 	struct disasm_line *dl = disasm_line(browser->selection);
460aca7a94dSNamhyung Kim 	struct annotation *notes;
46134f77abcSAdrian Hunter 	char title[SYM_TITLE_MAX_SIZE];
462aca7a94dSNamhyung Kim 
463696703afSArnaldo Carvalho de Melo 	if (!dl->ops.target.sym) {
464aca7a94dSNamhyung Kim 		ui_helpline__puts("The called function was not found.");
465aca7a94dSNamhyung Kim 		return true;
466aca7a94dSNamhyung Kim 	}
467aca7a94dSNamhyung Kim 
468696703afSArnaldo Carvalho de Melo 	notes = symbol__annotation(dl->ops.target.sym);
4692e9f9d4aSIan Rogers 	annotation__lock(notes);
470aca7a94dSNamhyung Kim 
4716484d2f9SJiri Olsa 	if (!symbol__hists(dl->ops.target.sym, evsel->evlist->core.nr_entries)) {
4722e9f9d4aSIan Rogers 		annotation__unlock(notes);
473aca7a94dSNamhyung Kim 		ui__warning("Not enough memory for annotating '%s' symbol!\n",
474696703afSArnaldo Carvalho de Melo 			    dl->ops.target.sym->name);
475aca7a94dSNamhyung Kim 		return true;
476aca7a94dSNamhyung Kim 	}
477aca7a94dSNamhyung Kim 
478f2eaea09SArnaldo Carvalho de Melo 	target_ms.maps = ms->maps;
47929754894SArnaldo Carvalho de Melo 	target_ms.map = ms->map;
48029754894SArnaldo Carvalho de Melo 	target_ms.sym = dl->ops.target.sym;
4812e9f9d4aSIan Rogers 	annotation__unlock(notes);
48222197fb2SNamhyung Kim 	symbol__tui_annotate(&target_ms, evsel, hbt);
48322197fb2SNamhyung Kim 	sym_title(ms->sym, ms->map, title, sizeof(title), annotate_opts.percent_type);
48434f77abcSAdrian Hunter 	ui_browser__show_title(&browser->b, title);
485aca7a94dSNamhyung Kim 	return true;
486aca7a94dSNamhyung Kim }
487aca7a94dSNamhyung Kim 
48829ed6e76SArnaldo Carvalho de Melo static
48929ed6e76SArnaldo Carvalho de Melo struct disasm_line *annotate_browser__find_offset(struct annotate_browser *browser,
490aca7a94dSNamhyung Kim 					  s64 offset, s64 *idx)
491aca7a94dSNamhyung Kim {
49295aa89d9SArnaldo Carvalho de Melo 	struct annotation *notes = browser__annotation(&browser->b);
49329ed6e76SArnaldo Carvalho de Melo 	struct disasm_line *pos;
494aca7a94dSNamhyung Kim 
495aca7a94dSNamhyung Kim 	*idx = 0;
496a17c4ca0SJiri Olsa 	list_for_each_entry(pos, &notes->src->source, al.node) {
497d5490b96SJiri Olsa 		if (pos->al.offset == offset)
498aca7a94dSNamhyung Kim 			return pos;
4992fa21d69SNamhyung Kim 		if (!annotation_line__filter(&pos->al))
500aca7a94dSNamhyung Kim 			++*idx;
501aca7a94dSNamhyung Kim 	}
502aca7a94dSNamhyung Kim 
503aca7a94dSNamhyung Kim 	return NULL;
504aca7a94dSNamhyung Kim }
505aca7a94dSNamhyung Kim 
506e4cc91b8SArnaldo Carvalho de Melo static bool annotate_browser__jump(struct annotate_browser *browser,
50732dcd021SJiri Olsa 				   struct evsel *evsel,
508e4cc91b8SArnaldo Carvalho de Melo 				   struct hist_browser_timer *hbt)
509aca7a94dSNamhyung Kim {
5107bcbcd58SJiri Olsa 	struct disasm_line *dl = disasm_line(browser->selection);
5115252b1aeSArnaldo Carvalho de Melo 	u64 offset;
5124f9d0325SArnaldo Carvalho de Melo 	s64 idx;
513aca7a94dSNamhyung Kim 
51475b49202SArnaldo Carvalho de Melo 	if (!ins__is_jump(&dl->ins))
515aca7a94dSNamhyung Kim 		return false;
516aca7a94dSNamhyung Kim 
517e4cc91b8SArnaldo Carvalho de Melo 	if (dl->ops.target.outside) {
518e4cc91b8SArnaldo Carvalho de Melo 		annotate_browser__callq(browser, evsel, hbt);
519e4cc91b8SArnaldo Carvalho de Melo 		return true;
520e4cc91b8SArnaldo Carvalho de Melo 	}
521e4cc91b8SArnaldo Carvalho de Melo 
5225252b1aeSArnaldo Carvalho de Melo 	offset = dl->ops.target.offset;
5235252b1aeSArnaldo Carvalho de Melo 	dl = annotate_browser__find_offset(browser, offset, &idx);
52429ed6e76SArnaldo Carvalho de Melo 	if (dl == NULL) {
5255252b1aeSArnaldo Carvalho de Melo 		ui_helpline__printf("Invalid jump offset: %" PRIx64, offset);
526aca7a94dSNamhyung Kim 		return true;
527aca7a94dSNamhyung Kim 	}
528aca7a94dSNamhyung Kim 
529ec03a77dSJiri Olsa 	annotate_browser__set_top(browser, &dl->al, idx);
530aca7a94dSNamhyung Kim 
531aca7a94dSNamhyung Kim 	return true;
532aca7a94dSNamhyung Kim }
533aca7a94dSNamhyung Kim 
53429ed6e76SArnaldo Carvalho de Melo static
5359213afbdSJiri Olsa struct annotation_line *annotate_browser__find_string(struct annotate_browser *browser,
536aca7a94dSNamhyung Kim 					  char *s, s64 *idx)
537aca7a94dSNamhyung Kim {
53895aa89d9SArnaldo Carvalho de Melo 	struct annotation *notes = browser__annotation(&browser->b);
5399213afbdSJiri Olsa 	struct annotation_line *al = browser->selection;
540aca7a94dSNamhyung Kim 
541aca7a94dSNamhyung Kim 	*idx = browser->b.index;
5429213afbdSJiri Olsa 	list_for_each_entry_continue(al, &notes->src->source, node) {
5432fa21d69SNamhyung Kim 		if (annotation_line__filter(al))
544aca7a94dSNamhyung Kim 			continue;
545aca7a94dSNamhyung Kim 
546aca7a94dSNamhyung Kim 		++*idx;
547aca7a94dSNamhyung Kim 
5489213afbdSJiri Olsa 		if (al->line && strstr(al->line, s) != NULL)
5499213afbdSJiri Olsa 			return al;
550aca7a94dSNamhyung Kim 	}
551aca7a94dSNamhyung Kim 
552aca7a94dSNamhyung Kim 	return NULL;
553aca7a94dSNamhyung Kim }
554aca7a94dSNamhyung Kim 
555aca7a94dSNamhyung Kim static bool __annotate_browser__search(struct annotate_browser *browser)
556aca7a94dSNamhyung Kim {
5579213afbdSJiri Olsa 	struct annotation_line *al;
558aca7a94dSNamhyung Kim 	s64 idx;
559aca7a94dSNamhyung Kim 
5609213afbdSJiri Olsa 	al = annotate_browser__find_string(browser, browser->search_bf, &idx);
5619213afbdSJiri Olsa 	if (al == NULL) {
562aca7a94dSNamhyung Kim 		ui_helpline__puts("String not found!");
563aca7a94dSNamhyung Kim 		return false;
564aca7a94dSNamhyung Kim 	}
565aca7a94dSNamhyung Kim 
566ec03a77dSJiri Olsa 	annotate_browser__set_top(browser, al, idx);
567aca7a94dSNamhyung Kim 	browser->searching_backwards = false;
568aca7a94dSNamhyung Kim 	return true;
569aca7a94dSNamhyung Kim }
570aca7a94dSNamhyung Kim 
57129ed6e76SArnaldo Carvalho de Melo static
5729213afbdSJiri Olsa struct annotation_line *annotate_browser__find_string_reverse(struct annotate_browser *browser,
573aca7a94dSNamhyung Kim 						  char *s, s64 *idx)
574aca7a94dSNamhyung Kim {
57595aa89d9SArnaldo Carvalho de Melo 	struct annotation *notes = browser__annotation(&browser->b);
5769213afbdSJiri Olsa 	struct annotation_line *al = browser->selection;
577aca7a94dSNamhyung Kim 
578aca7a94dSNamhyung Kim 	*idx = browser->b.index;
5799213afbdSJiri Olsa 	list_for_each_entry_continue_reverse(al, &notes->src->source, node) {
5802fa21d69SNamhyung Kim 		if (annotation_line__filter(al))
581aca7a94dSNamhyung Kim 			continue;
582aca7a94dSNamhyung Kim 
583aca7a94dSNamhyung Kim 		--*idx;
584aca7a94dSNamhyung Kim 
5859213afbdSJiri Olsa 		if (al->line && strstr(al->line, s) != NULL)
5869213afbdSJiri Olsa 			return al;
587aca7a94dSNamhyung Kim 	}
588aca7a94dSNamhyung Kim 
589aca7a94dSNamhyung Kim 	return NULL;
590aca7a94dSNamhyung Kim }
591aca7a94dSNamhyung Kim 
592aca7a94dSNamhyung Kim static bool __annotate_browser__search_reverse(struct annotate_browser *browser)
593aca7a94dSNamhyung Kim {
5949213afbdSJiri Olsa 	struct annotation_line *al;
595aca7a94dSNamhyung Kim 	s64 idx;
596aca7a94dSNamhyung Kim 
5979213afbdSJiri Olsa 	al = annotate_browser__find_string_reverse(browser, browser->search_bf, &idx);
5989213afbdSJiri Olsa 	if (al == NULL) {
599aca7a94dSNamhyung Kim 		ui_helpline__puts("String not found!");
600aca7a94dSNamhyung Kim 		return false;
601aca7a94dSNamhyung Kim 	}
602aca7a94dSNamhyung Kim 
603ec03a77dSJiri Olsa 	annotate_browser__set_top(browser, al, idx);
604aca7a94dSNamhyung Kim 	browser->searching_backwards = true;
605aca7a94dSNamhyung Kim 	return true;
606aca7a94dSNamhyung Kim }
607aca7a94dSNamhyung Kim 
608aca7a94dSNamhyung Kim static bool annotate_browser__search_window(struct annotate_browser *browser,
609aca7a94dSNamhyung Kim 					    int delay_secs)
610aca7a94dSNamhyung Kim {
611aca7a94dSNamhyung Kim 	if (ui_browser__input_window("Search", "String: ", browser->search_bf,
612aca7a94dSNamhyung Kim 				     "ENTER: OK, ESC: Cancel",
613aca7a94dSNamhyung Kim 				     delay_secs * 2) != K_ENTER ||
614aca7a94dSNamhyung Kim 	    !*browser->search_bf)
615aca7a94dSNamhyung Kim 		return false;
616aca7a94dSNamhyung Kim 
617aca7a94dSNamhyung Kim 	return true;
618aca7a94dSNamhyung Kim }
619aca7a94dSNamhyung Kim 
620aca7a94dSNamhyung Kim static bool annotate_browser__search(struct annotate_browser *browser, int delay_secs)
621aca7a94dSNamhyung Kim {
622aca7a94dSNamhyung Kim 	if (annotate_browser__search_window(browser, delay_secs))
623aca7a94dSNamhyung Kim 		return __annotate_browser__search(browser);
624aca7a94dSNamhyung Kim 
625aca7a94dSNamhyung Kim 	return false;
626aca7a94dSNamhyung Kim }
627aca7a94dSNamhyung Kim 
628aca7a94dSNamhyung Kim static bool annotate_browser__continue_search(struct annotate_browser *browser,
629aca7a94dSNamhyung Kim 					      int delay_secs)
630aca7a94dSNamhyung Kim {
631aca7a94dSNamhyung Kim 	if (!*browser->search_bf)
632aca7a94dSNamhyung Kim 		return annotate_browser__search(browser, delay_secs);
633aca7a94dSNamhyung Kim 
634aca7a94dSNamhyung Kim 	return __annotate_browser__search(browser);
635aca7a94dSNamhyung Kim }
636aca7a94dSNamhyung Kim 
637aca7a94dSNamhyung Kim static bool annotate_browser__search_reverse(struct annotate_browser *browser,
638aca7a94dSNamhyung Kim 					   int delay_secs)
639aca7a94dSNamhyung Kim {
640aca7a94dSNamhyung Kim 	if (annotate_browser__search_window(browser, delay_secs))
641aca7a94dSNamhyung Kim 		return __annotate_browser__search_reverse(browser);
642aca7a94dSNamhyung Kim 
643aca7a94dSNamhyung Kim 	return false;
644aca7a94dSNamhyung Kim }
645aca7a94dSNamhyung Kim 
646aca7a94dSNamhyung Kim static
647aca7a94dSNamhyung Kim bool annotate_browser__continue_search_reverse(struct annotate_browser *browser,
648aca7a94dSNamhyung Kim 					       int delay_secs)
649aca7a94dSNamhyung Kim {
650aca7a94dSNamhyung Kim 	if (!*browser->search_bf)
651aca7a94dSNamhyung Kim 		return annotate_browser__search_reverse(browser, delay_secs);
652aca7a94dSNamhyung Kim 
653aca7a94dSNamhyung Kim 	return __annotate_browser__search_reverse(browser);
654aca7a94dSNamhyung Kim }
655aca7a94dSNamhyung Kim 
6566920e285SArnaldo Carvalho de Melo static int annotate_browser__show(struct ui_browser *browser, char *title, const char *help)
6576920e285SArnaldo Carvalho de Melo {
6586920e285SArnaldo Carvalho de Melo 	struct map_symbol *ms = browser->priv;
6596920e285SArnaldo Carvalho de Melo 	struct symbol *sym = ms->sym;
6606920e285SArnaldo Carvalho de Melo 	char symbol_dso[SYM_TITLE_MAX_SIZE];
6616920e285SArnaldo Carvalho de Melo 
6626920e285SArnaldo Carvalho de Melo 	if (ui_browser__show(browser, title, help) < 0)
6636920e285SArnaldo Carvalho de Melo 		return -1;
6646920e285SArnaldo Carvalho de Melo 
66522197fb2SNamhyung Kim 	sym_title(sym, ms->map, symbol_dso, sizeof(symbol_dso), annotate_opts.percent_type);
6666920e285SArnaldo Carvalho de Melo 
6676920e285SArnaldo Carvalho de Melo 	ui_browser__gotorc_title(browser, 0, 0);
6686920e285SArnaldo Carvalho de Melo 	ui_browser__set_color(browser, HE_COLORSET_ROOT);
6696920e285SArnaldo Carvalho de Melo 	ui_browser__write_nstring(browser, symbol_dso, browser->width + 1);
6706920e285SArnaldo Carvalho de Melo 	return 0;
6716920e285SArnaldo Carvalho de Melo }
6726920e285SArnaldo Carvalho de Melo 
6733e0d7953SJiri Olsa static void
6743e0d7953SJiri Olsa switch_percent_type(struct annotation_options *opts, bool base)
6753e0d7953SJiri Olsa {
6763e0d7953SJiri Olsa 	switch (opts->percent_type) {
6773e0d7953SJiri Olsa 	case PERCENT_HITS_LOCAL:
6783e0d7953SJiri Olsa 		if (base)
6793e0d7953SJiri Olsa 			opts->percent_type = PERCENT_PERIOD_LOCAL;
6803e0d7953SJiri Olsa 		else
6813e0d7953SJiri Olsa 			opts->percent_type = PERCENT_HITS_GLOBAL;
6823e0d7953SJiri Olsa 		break;
6833e0d7953SJiri Olsa 	case PERCENT_HITS_GLOBAL:
6843e0d7953SJiri Olsa 		if (base)
6853e0d7953SJiri Olsa 			opts->percent_type = PERCENT_PERIOD_GLOBAL;
6863e0d7953SJiri Olsa 		else
6873e0d7953SJiri Olsa 			opts->percent_type = PERCENT_HITS_LOCAL;
6883e0d7953SJiri Olsa 		break;
6893e0d7953SJiri Olsa 	case PERCENT_PERIOD_LOCAL:
6903e0d7953SJiri Olsa 		if (base)
6913e0d7953SJiri Olsa 			opts->percent_type = PERCENT_HITS_LOCAL;
6923e0d7953SJiri Olsa 		else
6933e0d7953SJiri Olsa 			opts->percent_type = PERCENT_PERIOD_GLOBAL;
6943e0d7953SJiri Olsa 		break;
6953e0d7953SJiri Olsa 	case PERCENT_PERIOD_GLOBAL:
6963e0d7953SJiri Olsa 		if (base)
6973e0d7953SJiri Olsa 			opts->percent_type = PERCENT_HITS_GLOBAL;
6983e0d7953SJiri Olsa 		else
6993e0d7953SJiri Olsa 			opts->percent_type = PERCENT_PERIOD_LOCAL;
7003e0d7953SJiri Olsa 		break;
7013e0d7953SJiri Olsa 	default:
7023e0d7953SJiri Olsa 		WARN_ON(1);
7033e0d7953SJiri Olsa 	}
7043e0d7953SJiri Olsa }
7053e0d7953SJiri Olsa 
706db8fd07aSNamhyung Kim static int annotate_browser__run(struct annotate_browser *browser,
70732dcd021SJiri Olsa 				 struct evsel *evsel,
7089783adf7SNamhyung Kim 				 struct hist_browser_timer *hbt)
709aca7a94dSNamhyung Kim {
710aca7a94dSNamhyung Kim 	struct rb_node *nd = NULL;
7116920e285SArnaldo Carvalho de Melo 	struct hists *hists = evsel__hists(evsel);
71205e8b080SArnaldo Carvalho de Melo 	struct map_symbol *ms = browser->b.priv;
713aca7a94dSNamhyung Kim 	struct symbol *sym = ms->sym;
71416932d77SArnaldo Carvalho de Melo 	struct annotation *notes = symbol__annotation(ms->sym);
71554e7a4e8SArnaldo Carvalho de Melo 	const char *help = "Press 'h' for help on key bindings";
7169783adf7SNamhyung Kim 	int delay_secs = hbt ? hbt->refresh : 0;
7176920e285SArnaldo Carvalho de Melo 	char title[256];
718aca7a94dSNamhyung Kim 	int key;
719aca7a94dSNamhyung Kim 
7200683d13cSJiri Olsa 	hists__scnprintf_title(hists, title, sizeof(title));
7216920e285SArnaldo Carvalho de Melo 	if (annotate_browser__show(&browser->b, title, help) < 0)
722aca7a94dSNamhyung Kim 		return -1;
723aca7a94dSNamhyung Kim 
724db8fd07aSNamhyung Kim 	annotate_browser__calc_percent(browser, evsel);
725aca7a94dSNamhyung Kim 
72605e8b080SArnaldo Carvalho de Melo 	if (browser->curr_hot) {
72705e8b080SArnaldo Carvalho de Melo 		annotate_browser__set_rb_top(browser, browser->curr_hot);
72805e8b080SArnaldo Carvalho de Melo 		browser->b.navkeypressed = false;
729aca7a94dSNamhyung Kim 	}
730aca7a94dSNamhyung Kim 
73105e8b080SArnaldo Carvalho de Melo 	nd = browser->curr_hot;
732aca7a94dSNamhyung Kim 
733aca7a94dSNamhyung Kim 	while (1) {
73405e8b080SArnaldo Carvalho de Melo 		key = ui_browser__run(&browser->b, delay_secs);
735aca7a94dSNamhyung Kim 
736aca7a94dSNamhyung Kim 		if (delay_secs != 0) {
737db8fd07aSNamhyung Kim 			annotate_browser__calc_percent(browser, evsel);
738aca7a94dSNamhyung Kim 			/*
739aca7a94dSNamhyung Kim 			 * Current line focus got out of the list of most active
740aca7a94dSNamhyung Kim 			 * lines, NULL it so that if TAB|UNTAB is pressed, we
741aca7a94dSNamhyung Kim 			 * move to curr_hot (current hottest line).
742aca7a94dSNamhyung Kim 			 */
743aca7a94dSNamhyung Kim 			if (nd != NULL && RB_EMPTY_NODE(nd))
744aca7a94dSNamhyung Kim 				nd = NULL;
745aca7a94dSNamhyung Kim 		}
746aca7a94dSNamhyung Kim 
747aca7a94dSNamhyung Kim 		switch (key) {
748aca7a94dSNamhyung Kim 		case K_TIMER:
7499783adf7SNamhyung Kim 			if (hbt)
7509783adf7SNamhyung Kim 				hbt->timer(hbt->arg);
751aca7a94dSNamhyung Kim 
7526920e285SArnaldo Carvalho de Melo 			if (delay_secs != 0) {
75338fe0e01SJiri Olsa 				symbol__annotate_decay_histogram(sym, evsel->core.idx);
7546920e285SArnaldo Carvalho de Melo 				hists__scnprintf_title(hists, title, sizeof(title));
7556920e285SArnaldo Carvalho de Melo 				annotate_browser__show(&browser->b, title, help);
7566920e285SArnaldo Carvalho de Melo 			}
757aca7a94dSNamhyung Kim 			continue;
758aca7a94dSNamhyung Kim 		case K_TAB:
759aca7a94dSNamhyung Kim 			if (nd != NULL) {
760aca7a94dSNamhyung Kim 				nd = rb_prev(nd);
761aca7a94dSNamhyung Kim 				if (nd == NULL)
76205e8b080SArnaldo Carvalho de Melo 					nd = rb_last(&browser->entries);
763aca7a94dSNamhyung Kim 			} else
76405e8b080SArnaldo Carvalho de Melo 				nd = browser->curr_hot;
765aca7a94dSNamhyung Kim 			break;
766aca7a94dSNamhyung Kim 		case K_UNTAB:
767d4913cbdSMarkus Trippelsdorf 			if (nd != NULL) {
768aca7a94dSNamhyung Kim 				nd = rb_next(nd);
769aca7a94dSNamhyung Kim 				if (nd == NULL)
77005e8b080SArnaldo Carvalho de Melo 					nd = rb_first(&browser->entries);
771d4913cbdSMarkus Trippelsdorf 			} else
77205e8b080SArnaldo Carvalho de Melo 				nd = browser->curr_hot;
773aca7a94dSNamhyung Kim 			break;
77454e7a4e8SArnaldo Carvalho de Melo 		case K_F1:
775aca7a94dSNamhyung Kim 		case 'h':
77605e8b080SArnaldo Carvalho de Melo 			ui_browser__help_window(&browser->b,
77754e7a4e8SArnaldo Carvalho de Melo 		"UP/DOWN/PGUP\n"
77854e7a4e8SArnaldo Carvalho de Melo 		"PGDN/SPACE    Navigate\n"
7796d491b37SNamhyung Kim 		"</>           Move to prev/next symbol\n"
78054e7a4e8SArnaldo Carvalho de Melo 		"q/ESC/CTRL+C  Exit\n\n"
7817727a925SArnaldo Carvalho de Melo 		"ENTER         Go to target\n"
782eba9fac0SArnaldo Carvalho de Melo 		"H             Go to hottest instruction\n"
783eba9fac0SArnaldo Carvalho de Melo 		"TAB/shift+TAB Cycle thru hottest instructions\n"
78454e7a4e8SArnaldo Carvalho de Melo 		"j             Toggle showing jump to target arrows\n"
78554e7a4e8SArnaldo Carvalho de Melo 		"J             Toggle showing number of jump sources on targets\n"
78654e7a4e8SArnaldo Carvalho de Melo 		"n             Search next string\n"
78754e7a4e8SArnaldo Carvalho de Melo 		"o             Toggle disassembler output/simplified view\n"
78851f39603SArnaldo Carvalho de Melo 		"O             Bump offset level (jump targets -> +call -> all -> cycle thru)\n"
78954e7a4e8SArnaldo Carvalho de Melo 		"s             Toggle source code view\n"
7903a555c77STaeung Song 		"t             Circulate percent, total period, samples view\n"
7913e71fc03SJin Yao 		"c             Show min/max cycle\n"
79254e7a4e8SArnaldo Carvalho de Melo 		"/             Search string\n"
793e592488cSAndi Kleen 		"k             Toggle line numbers\n"
7942777b81bSMartin Liska 		"l             Show full source file location\n"
795d9bd7665SArnaldo Carvalho de Melo 		"P             Print to [symbol_name].annotation file.\n"
79679ee47faSFeng Tang 		"r             Run available scripts\n"
7973e0d7953SJiri Olsa 		"p             Toggle percent type [local/global]\n"
7983e0d7953SJiri Olsa 		"b             Toggle percent base [period/hits]\n"
7997d18a824SNamhyung Kim 		"?             Search string backwards\n"
8007d18a824SNamhyung Kim 		"f             Toggle showing offsets to full address\n");
80154e7a4e8SArnaldo Carvalho de Melo 			continue;
80279ee47faSFeng Tang 		case 'r':
8036f3da20eSAndi Kleen 			script_browse(NULL, NULL);
80454cf752cSRavi Bangoria 			annotate_browser__show(&browser->b, title, help);
80579ee47faSFeng Tang 			continue;
806e592488cSAndi Kleen 		case 'k':
80722197fb2SNamhyung Kim 			annotate_opts.show_linenr = !annotate_opts.show_linenr;
8084fd00847SMartin Liška 			continue;
8092777b81bSMartin Liska 		case 'l':
8102777b81bSMartin Liska 			annotate_browser__show_full_location (&browser->b);
8112777b81bSMartin Liska 			continue;
81254e7a4e8SArnaldo Carvalho de Melo 		case 'H':
81305e8b080SArnaldo Carvalho de Melo 			nd = browser->curr_hot;
814aca7a94dSNamhyung Kim 			break;
815aca7a94dSNamhyung Kim 		case 's':
81605e8b080SArnaldo Carvalho de Melo 			if (annotate_browser__toggle_source(browser))
817aca7a94dSNamhyung Kim 				ui_helpline__puts(help);
818aca7a94dSNamhyung Kim 			continue;
819aca7a94dSNamhyung Kim 		case 'o':
82022197fb2SNamhyung Kim 			annotate_opts.use_offset = !annotate_opts.use_offset;
8219761e86eSArnaldo Carvalho de Melo 			annotation__update_column_widths(notes);
822aca7a94dSNamhyung Kim 			continue;
82351f39603SArnaldo Carvalho de Melo 		case 'O':
82422197fb2SNamhyung Kim 			if (++annotate_opts.offset_level > ANNOTATION__MAX_OFFSET_LEVEL)
82522197fb2SNamhyung Kim 				annotate_opts.offset_level = ANNOTATION__MIN_OFFSET_LEVEL;
82651f39603SArnaldo Carvalho de Melo 			continue;
8279d1ef56dSArnaldo Carvalho de Melo 		case 'j':
82822197fb2SNamhyung Kim 			annotate_opts.jump_arrows = !annotate_opts.jump_arrows;
8299d1ef56dSArnaldo Carvalho de Melo 			continue;
8302402e4a9SArnaldo Carvalho de Melo 		case 'J':
83122197fb2SNamhyung Kim 			annotate_opts.show_nr_jumps = !annotate_opts.show_nr_jumps;
8329761e86eSArnaldo Carvalho de Melo 			annotation__update_column_widths(notes);
833e9823b21SArnaldo Carvalho de Melo 			continue;
834aca7a94dSNamhyung Kim 		case '/':
83505e8b080SArnaldo Carvalho de Melo 			if (annotate_browser__search(browser, delay_secs)) {
836aca7a94dSNamhyung Kim show_help:
837aca7a94dSNamhyung Kim 				ui_helpline__puts(help);
838aca7a94dSNamhyung Kim 			}
839aca7a94dSNamhyung Kim 			continue;
840aca7a94dSNamhyung Kim 		case 'n':
84105e8b080SArnaldo Carvalho de Melo 			if (browser->searching_backwards ?
84205e8b080SArnaldo Carvalho de Melo 			    annotate_browser__continue_search_reverse(browser, delay_secs) :
84305e8b080SArnaldo Carvalho de Melo 			    annotate_browser__continue_search(browser, delay_secs))
844aca7a94dSNamhyung Kim 				goto show_help;
845aca7a94dSNamhyung Kim 			continue;
846aca7a94dSNamhyung Kim 		case '?':
84705e8b080SArnaldo Carvalho de Melo 			if (annotate_browser__search_reverse(browser, delay_secs))
848aca7a94dSNamhyung Kim 				goto show_help;
849aca7a94dSNamhyung Kim 			continue;
850e9823b21SArnaldo Carvalho de Melo 		case 'D': {
851e9823b21SArnaldo Carvalho de Melo 			static int seq;
852e9823b21SArnaldo Carvalho de Melo 			ui_helpline__pop();
853e9823b21SArnaldo Carvalho de Melo 			ui_helpline__fpush("%d: nr_ent=%d, height=%d, idx=%d, top_idx=%d, nr_asm_entries=%d",
85405e8b080SArnaldo Carvalho de Melo 					   seq++, browser->b.nr_entries,
85505e8b080SArnaldo Carvalho de Melo 					   browser->b.height,
85605e8b080SArnaldo Carvalho de Melo 					   browser->b.index,
85705e8b080SArnaldo Carvalho de Melo 					   browser->b.top_idx,
8580aae4c99SNamhyung Kim 					   notes->src->nr_asm_entries);
859e9823b21SArnaldo Carvalho de Melo 		}
860e9823b21SArnaldo Carvalho de Melo 			continue;
861aca7a94dSNamhyung Kim 		case K_ENTER:
862aca7a94dSNamhyung Kim 		case K_RIGHT:
8637bcbcd58SJiri Olsa 		{
8647bcbcd58SJiri Olsa 			struct disasm_line *dl = disasm_line(browser->selection);
8657bcbcd58SJiri Olsa 
86605e8b080SArnaldo Carvalho de Melo 			if (browser->selection == NULL)
867aca7a94dSNamhyung Kim 				ui_helpline__puts("Huh? No selection. Report to linux-kernel@vger.kernel.org");
8687bcbcd58SJiri Olsa 			else if (browser->selection->offset == -1)
869aca7a94dSNamhyung Kim 				ui_helpline__puts("Actions are only available for assembly lines.");
8707bcbcd58SJiri Olsa 			else if (!dl->ins.ops)
871c4cceae3SArnaldo Carvalho de Melo 				goto show_sup_ins;
8727bcbcd58SJiri Olsa 			else if (ins__is_ret(&dl->ins))
873c4cceae3SArnaldo Carvalho de Melo 				goto out;
874e4cc91b8SArnaldo Carvalho de Melo 			else if (!(annotate_browser__jump(browser, evsel, hbt) ||
875db8fd07aSNamhyung Kim 				     annotate_browser__callq(browser, evsel, hbt))) {
876c4cceae3SArnaldo Carvalho de Melo show_sup_ins:
8776ef94929SNaveen N. Rao 				ui_helpline__puts("Actions are only available for function call/return & jump/branch instructions.");
878c4cceae3SArnaldo Carvalho de Melo 			}
879aca7a94dSNamhyung Kim 			continue;
8807bcbcd58SJiri Olsa 		}
881d9bd7665SArnaldo Carvalho de Melo 		case 'P':
88241fd3cacSNamhyung Kim 			map_symbol__annotation_dump(ms, evsel);
883d9bd7665SArnaldo Carvalho de Melo 			continue;
8840c4a5bceSMartin Liška 		case 't':
88568aac855SRavi Bangoria 			if (symbol_conf.show_total_period) {
88668aac855SRavi Bangoria 				symbol_conf.show_total_period = false;
88746ccb442SRavi Bangoria 				symbol_conf.show_nr_samples = true;
88846ccb442SRavi Bangoria 			} else if (symbol_conf.show_nr_samples)
88946ccb442SRavi Bangoria 				symbol_conf.show_nr_samples = false;
8903a555c77STaeung Song 			else
89168aac855SRavi Bangoria 				symbol_conf.show_total_period = true;
8929761e86eSArnaldo Carvalho de Melo 			annotation__update_column_widths(notes);
8930c4a5bceSMartin Liška 			continue;
8943e71fc03SJin Yao 		case 'c':
89522197fb2SNamhyung Kim 			if (annotate_opts.show_minmax_cycle)
89622197fb2SNamhyung Kim 				annotate_opts.show_minmax_cycle = false;
8973e71fc03SJin Yao 			else
89822197fb2SNamhyung Kim 				annotate_opts.show_minmax_cycle = true;
8993e71fc03SJin Yao 			annotation__update_column_widths(notes);
9003e71fc03SJin Yao 			continue;
9013e0d7953SJiri Olsa 		case 'p':
9023e0d7953SJiri Olsa 		case 'b':
90322197fb2SNamhyung Kim 			switch_percent_type(&annotate_opts, key == 'b');
9043e0d7953SJiri Olsa 			hists__scnprintf_title(hists, title, sizeof(title));
9053e0d7953SJiri Olsa 			annotate_browser__show(&browser->b, title, help);
9063e0d7953SJiri Olsa 			continue;
9077d18a824SNamhyung Kim 		case 'f':
9087d18a824SNamhyung Kim 			annotation__toggle_full_addr(notes, ms);
9097d18a824SNamhyung Kim 			continue;
910aca7a94dSNamhyung Kim 		case K_LEFT:
9116d491b37SNamhyung Kim 		case '<':
9126d491b37SNamhyung Kim 		case '>':
913aca7a94dSNamhyung Kim 		case K_ESC:
914aca7a94dSNamhyung Kim 		case 'q':
915aca7a94dSNamhyung Kim 		case CTRL('c'):
916aca7a94dSNamhyung Kim 			goto out;
917aca7a94dSNamhyung Kim 		default:
918aca7a94dSNamhyung Kim 			continue;
919aca7a94dSNamhyung Kim 		}
920aca7a94dSNamhyung Kim 
921aca7a94dSNamhyung Kim 		if (nd != NULL)
92205e8b080SArnaldo Carvalho de Melo 			annotate_browser__set_rb_top(browser, nd);
923aca7a94dSNamhyung Kim 	}
924aca7a94dSNamhyung Kim out:
92505e8b080SArnaldo Carvalho de Melo 	ui_browser__hide(&browser->b);
926aca7a94dSNamhyung Kim 	return key;
927aca7a94dSNamhyung Kim }
928aca7a94dSNamhyung Kim 
92932dcd021SJiri Olsa int map_symbol__tui_annotate(struct map_symbol *ms, struct evsel *evsel,
93022197fb2SNamhyung Kim 			     struct hist_browser_timer *hbt)
931d5dbc518SArnaldo Carvalho de Melo {
93222197fb2SNamhyung Kim 	return symbol__tui_annotate(ms, evsel, hbt);
933d5dbc518SArnaldo Carvalho de Melo }
934d5dbc518SArnaldo Carvalho de Melo 
93532dcd021SJiri Olsa int hist_entry__tui_annotate(struct hist_entry *he, struct evsel *evsel,
93622197fb2SNamhyung Kim 			     struct hist_browser_timer *hbt)
937aca7a94dSNamhyung Kim {
938ed426915SNamhyung Kim 	/* reset abort key so that it can get Ctrl-C as a key */
939ed426915SNamhyung Kim 	SLang_reset_tty();
940ed426915SNamhyung Kim 	SLang_init_tty(0, 0, 0);
9416af6d224SAhelenia Ziemiańska 	SLtty_set_suspend_state(true);
942ed426915SNamhyung Kim 
94322197fb2SNamhyung Kim 	return map_symbol__tui_annotate(&he->ms, evsel, hbt);
944aca7a94dSNamhyung Kim }
945aca7a94dSNamhyung Kim 
94629754894SArnaldo Carvalho de Melo int symbol__tui_annotate(struct map_symbol *ms, struct evsel *evsel,
94722197fb2SNamhyung Kim 			 struct hist_browser_timer *hbt)
948aca7a94dSNamhyung Kim {
94929754894SArnaldo Carvalho de Melo 	struct symbol *sym = ms->sym;
9509d6bb41dSArnaldo Carvalho de Melo 	struct annotation *notes = symbol__annotation(sym);
951aca7a94dSNamhyung Kim 	struct annotate_browser browser = {
952aca7a94dSNamhyung Kim 		.b = {
953a3f895beSArnaldo Carvalho de Melo 			.refresh = annotate_browser__refresh,
954aca7a94dSNamhyung Kim 			.seek	 = ui_browser__list_head_seek,
955aca7a94dSNamhyung Kim 			.write	 = annotate_browser__write,
95629ed6e76SArnaldo Carvalho de Melo 			.filter  = disasm_line__filter,
9576920e285SArnaldo Carvalho de Melo 			.extra_title_lines = 1, /* for hists__scnprintf_title() */
95829754894SArnaldo Carvalho de Melo 			.priv	 = ms,
959aca7a94dSNamhyung Kim 			.use_navkeypressed = true,
960aca7a94dSNamhyung Kim 		},
961aca7a94dSNamhyung Kim 	};
96263df0e4bSIan Rogers 	struct dso *dso;
963ee51d851SArnaldo Carvalho de Melo 	int ret = -1, err;
964d5962fb7SDario Petrillo 	int not_annotated = list_empty(&notes->src->source);
965aca7a94dSNamhyung Kim 
966aca7a94dSNamhyung Kim 	if (sym == NULL)
967aca7a94dSNamhyung Kim 		return -1;
968aca7a94dSNamhyung Kim 
96963df0e4bSIan Rogers 	dso = map__dso(ms->map);
97063df0e4bSIan Rogers 	if (dso->annotate_warned)
971aca7a94dSNamhyung Kim 		return -1;
972aca7a94dSNamhyung Kim 
973*2b8dbf69SNamhyung Kim 	if (not_annotated || !sym->annotate2) {
97441fd3cacSNamhyung Kim 		err = symbol__annotate2(ms, evsel, &browser.arch);
975ee51d851SArnaldo Carvalho de Melo 		if (err) {
976ee51d851SArnaldo Carvalho de Melo 			char msg[BUFSIZ];
97763df0e4bSIan Rogers 			dso->annotate_warned = true;
97829754894SArnaldo Carvalho de Melo 			symbol__strerror_disassemble(ms, err, msg, sizeof(msg));
979ee51d851SArnaldo Carvalho de Melo 			ui__error("Couldn't annotate %s:\n%s", sym->name, msg);
980b793a401SArnaldo Carvalho de Melo 			goto out_free_offsets;
981aca7a94dSNamhyung Kim 		}
982d5962fb7SDario Petrillo 	}
983aca7a94dSNamhyung Kim 
9847727a925SArnaldo Carvalho de Melo 	ui_helpline__push("Press ESC to exit");
985aca7a94dSNamhyung Kim 
9860aae4c99SNamhyung Kim 	browser.b.width = notes->src->max_line_len;
9870aae4c99SNamhyung Kim 	browser.b.nr_entries = notes->src->nr_entries;
988aca7a94dSNamhyung Kim 	browser.b.entries = &notes->src->source,
989aca7a94dSNamhyung Kim 	browser.b.width += 18; /* Percentage */
990e9823b21SArnaldo Carvalho de Melo 
99122197fb2SNamhyung Kim 	if (annotate_opts.hide_src_code)
9921cf5f98aSArnaldo Carvalho de Melo 		ui_browser__init_asm_mode(&browser.b);
993e9823b21SArnaldo Carvalho de Melo 
994db8fd07aSNamhyung Kim 	ret = annotate_browser__run(&browser, evsel, hbt);
995f8eb37bdSJiri Olsa 
996d5962fb7SDario Petrillo 	if(not_annotated)
997f8eb37bdSJiri Olsa 		annotated_source__purge(notes->src);
998b793a401SArnaldo Carvalho de Melo 
999b793a401SArnaldo Carvalho de Melo out_free_offsets:
1000d5962fb7SDario Petrillo 	if(not_annotated)
1001b753d48fSNamhyung Kim 		zfree(&notes->src->offsets);
1002aca7a94dSNamhyung Kim 	return ret;
1003aca7a94dSNamhyung Kim }
1004