1 // SPDX-License-Identifier: GPL-2.0
2 #include "../../util/util.h"
3 #include "../browser.h"
4 #include "../helpline.h"
7 #include "../../util/annotate.h"
8 #include "../../util/hist.h"
9 #include "../../util/sort.h"
10 #include "../../util/symbol.h"
11 #include "../../util/evsel.h"
12 #include "../../util/evlist.h"
15 #include <linux/kernel.h>
16 #include <linux/string.h>
17 #include <sys/ttydefaults.h>
20 struct disasm_line_samples {
22 struct sym_hist_entry he;
27 struct annotate_browser {
29 struct rb_root entries;
30 struct rb_node *curr_hot;
31 struct annotation_line *selection;
33 struct annotation_options *opts;
34 bool searching_backwards;
38 static inline struct annotation *browser__annotation(struct ui_browser *browser)
40 struct map_symbol *ms = browser->priv;
41 return symbol__annotation(ms->sym);
44 static bool disasm_line__filter(struct ui_browser *browser, void *entry)
46 struct annotation *notes = browser__annotation(browser);
47 struct annotation_line *al = list_entry(entry, struct annotation_line, node);
48 return annotation_line__filter(al, notes);
51 static int ui_browser__jumps_percent_color(struct ui_browser *browser, int nr, bool current)
53 struct annotation *notes = browser__annotation(browser);
55 if (current && (!browser->use_navkeypressed || browser->navkeypressed))
56 return HE_COLORSET_SELECTED;
57 if (nr == notes->max_jump_sources)
58 return HE_COLORSET_TOP;
60 return HE_COLORSET_MEDIUM;
61 return HE_COLORSET_NORMAL;
64 static int ui_browser__set_jumps_percent_color(void *browser, int nr, bool current)
66 int color = ui_browser__jumps_percent_color(browser, nr, current);
67 return ui_browser__set_color(browser, color);
70 static int annotate_browser__set_color(void *browser, int color)
72 return ui_browser__set_color(browser, color);
75 static void annotate_browser__write_graph(void *browser, int graph)
77 ui_browser__write_graph(browser, graph);
80 static void annotate_browser__set_percent_color(void *browser, double percent, bool current)
82 ui_browser__set_percent_color(browser, percent, current);
85 static void annotate_browser__printf(void *browser, const char *fmt, ...)
90 ui_browser__vprintf(browser, fmt, args);
94 static void annotate_browser__write(struct ui_browser *browser, void *entry, int row)
96 struct annotate_browser *ab = container_of(browser, struct annotate_browser, b);
97 struct annotation *notes = browser__annotation(browser);
98 struct annotation_line *al = list_entry(entry, struct annotation_line, node);
99 const bool is_current_entry = ui_browser__is_current_entry(browser, row);
100 struct annotation_write_ops ops = {
101 .first_line = row == 0,
102 .current_entry = is_current_entry,
103 .change_color = (!notes->options->hide_src_code &&
104 (!is_current_entry ||
105 (browser->use_navkeypressed &&
106 !browser->navkeypressed))),
107 .width = browser->width,
109 .set_color = annotate_browser__set_color,
110 .set_percent_color = annotate_browser__set_percent_color,
111 .set_jumps_percent_color = ui_browser__set_jumps_percent_color,
112 .printf = annotate_browser__printf,
113 .write_graph = annotate_browser__write_graph,
116 /* The scroll bar isn't being used */
117 if (!browser->navkeypressed)
120 annotation_line__write(al, notes, &ops, ab->opts);
122 if (ops.current_entry)
126 static bool is_fused(struct annotate_browser *ab, struct disasm_line *cursor)
128 struct disasm_line *pos = list_prev_entry(cursor, al.node);
134 if (ins__is_lock(&pos->ins))
135 name = pos->ops.locked.ins.name;
137 name = pos->ins.name;
139 if (!name || !cursor->ins.name)
142 return ins__is_fused(ab->arch, name, cursor->ins.name);
145 static void annotate_browser__draw_current_jump(struct ui_browser *browser)
147 struct annotate_browser *ab = container_of(browser, struct annotate_browser, b);
148 struct disasm_line *cursor = disasm_line(ab->selection);
149 struct annotation_line *target;
150 unsigned int from, to;
151 struct map_symbol *ms = ab->b.priv;
152 struct symbol *sym = ms->sym;
153 struct annotation *notes = symbol__annotation(sym);
154 u8 pcnt_width = annotation__pcnt_width(notes);
157 /* PLT symbols contain external offsets */
158 if (strstr(sym->name, "@plt"))
161 if (!disasm_line__is_valid_local_jump(cursor, sym))
165 * This first was seen with a gcc function, _cpp_lex_token, that
166 * has the usual jumps:
168 * │1159e6c: ↓ jne 115aa32 <_cpp_lex_token@@Base+0xf92>
170 * I.e. jumps to a label inside that function (_cpp_lex_token), and
171 * those works, but also this kind:
173 * │1159e8b: ↓ jne c469be <cpp_named_operator2name@@Base+0xa72>
175 * I.e. jumps to another function, outside _cpp_lex_token, which
176 * are not being correctly handled generating as a side effect references
177 * to ab->offset[] entries that are set to NULL, so to make this code
178 * more robust, check that here.
180 * A proper fix for will be put in place, looking at the function
181 * name right after the '<' token and probably treating this like a
182 * 'call' instruction.
184 target = notes->offsets[cursor->ops.target.offset];
185 if (target == NULL) {
186 ui_helpline__printf("WARN: jump target inconsistency, press 'o', notes->offsets[%#x] = NULL\n",
187 cursor->ops.target.offset);
191 if (notes->options->hide_src_code) {
192 from = cursor->al.idx_asm;
193 to = target->idx_asm;
195 from = (u64)cursor->al.idx;
196 to = (u64)target->idx;
199 width = annotation__cycles_width(notes);
201 ui_browser__set_color(browser, HE_COLORSET_JUMP_ARROWS);
202 __ui_browser__line_arrow(browser,
203 pcnt_width + 2 + notes->widths.addr + width,
206 if (is_fused(ab, cursor)) {
207 ui_browser__mark_fused(browser,
208 pcnt_width + 3 + notes->widths.addr + width,
210 to > from ? true : false);
214 static unsigned int annotate_browser__refresh(struct ui_browser *browser)
216 struct annotation *notes = browser__annotation(browser);
217 int ret = ui_browser__list_head_refresh(browser);
218 int pcnt_width = annotation__pcnt_width(notes);
220 if (notes->options->jump_arrows)
221 annotate_browser__draw_current_jump(browser);
223 ui_browser__set_color(browser, HE_COLORSET_NORMAL);
224 __ui_browser__vline(browser, pcnt_width, 0, browser->rows - 1);
228 static int disasm__cmp(struct annotation_line *a, struct annotation_line *b)
232 for (i = 0; i < a->data_nr; i++) {
233 if (a->data[i].percent == b->data[i].percent)
235 return a->data[i].percent < b->data[i].percent;
240 static void disasm_rb_tree__insert(struct rb_root *root, struct annotation_line *al)
242 struct rb_node **p = &root->rb_node;
243 struct rb_node *parent = NULL;
244 struct annotation_line *l;
248 l = rb_entry(parent, struct annotation_line, rb_node);
250 if (disasm__cmp(al, l))
255 rb_link_node(&al->rb_node, parent, p);
256 rb_insert_color(&al->rb_node, root);
259 static void annotate_browser__set_top(struct annotate_browser *browser,
260 struct annotation_line *pos, u32 idx)
262 struct annotation *notes = browser__annotation(&browser->b);
265 ui_browser__refresh_dimensions(&browser->b);
266 back = browser->b.height / 2;
267 browser->b.top_idx = browser->b.index = idx;
269 while (browser->b.top_idx != 0 && back != 0) {
270 pos = list_entry(pos->node.prev, struct annotation_line, node);
272 if (annotation_line__filter(pos, notes))
275 --browser->b.top_idx;
279 browser->b.top = pos;
280 browser->b.navkeypressed = true;
283 static void annotate_browser__set_rb_top(struct annotate_browser *browser,
286 struct annotation *notes = browser__annotation(&browser->b);
287 struct annotation_line * pos = rb_entry(nd, struct annotation_line, rb_node);
290 if (notes->options->hide_src_code)
292 annotate_browser__set_top(browser, pos, idx);
293 browser->curr_hot = nd;
296 static void annotate_browser__calc_percent(struct annotate_browser *browser,
297 struct perf_evsel *evsel)
299 struct map_symbol *ms = browser->b.priv;
300 struct symbol *sym = ms->sym;
301 struct annotation *notes = symbol__annotation(sym);
302 struct disasm_line *pos;
304 browser->entries = RB_ROOT;
306 pthread_mutex_lock(¬es->lock);
308 symbol__calc_percent(sym, evsel);
310 list_for_each_entry(pos, ¬es->src->source, al.node) {
311 double max_percent = 0.0;
314 if (pos->al.offset == -1) {
315 RB_CLEAR_NODE(&pos->al.rb_node);
319 for (i = 0; i < pos->al.data_nr; i++) {
322 percent = annotation_data__percent(&pos->al.data[i],
323 browser->opts->percent_type);
325 if (max_percent < percent)
326 max_percent = percent;
329 if (max_percent < 0.01 && pos->al.ipc == 0) {
330 RB_CLEAR_NODE(&pos->al.rb_node);
333 disasm_rb_tree__insert(&browser->entries, &pos->al);
335 pthread_mutex_unlock(¬es->lock);
337 browser->curr_hot = rb_last(&browser->entries);
340 static bool annotate_browser__toggle_source(struct annotate_browser *browser)
342 struct annotation *notes = browser__annotation(&browser->b);
343 struct annotation_line *al;
344 off_t offset = browser->b.index - browser->b.top_idx;
346 browser->b.seek(&browser->b, offset, SEEK_CUR);
347 al = list_entry(browser->b.top, struct annotation_line, node);
349 if (notes->options->hide_src_code) {
350 if (al->idx_asm < offset)
353 browser->b.nr_entries = notes->nr_entries;
354 notes->options->hide_src_code = false;
355 browser->b.seek(&browser->b, -offset, SEEK_CUR);
356 browser->b.top_idx = al->idx - offset;
357 browser->b.index = al->idx;
359 if (al->idx_asm < 0) {
360 ui_helpline__puts("Only available for assembly lines.");
361 browser->b.seek(&browser->b, -offset, SEEK_CUR);
365 if (al->idx_asm < offset)
366 offset = al->idx_asm;
368 browser->b.nr_entries = notes->nr_asm_entries;
369 notes->options->hide_src_code = true;
370 browser->b.seek(&browser->b, -offset, SEEK_CUR);
371 browser->b.top_idx = al->idx_asm - offset;
372 browser->b.index = al->idx_asm;
378 static void ui_browser__init_asm_mode(struct ui_browser *browser)
380 struct annotation *notes = browser__annotation(browser);
381 ui_browser__reset_index(browser);
382 browser->nr_entries = notes->nr_asm_entries;
385 #define SYM_TITLE_MAX_SIZE (PATH_MAX + 64)
387 static int sym_title(struct symbol *sym, struct map *map, char *title,
388 size_t sz, int percent_type)
390 return snprintf(title, sz, "%s %s [Percent: %s]", sym->name, map->dso->long_name,
391 percent_type_str(percent_type));
395 * This can be called from external jumps, i.e. jumps from one functon
396 * to another, like from the kernel's entry_SYSCALL_64 function to the
397 * swapgs_restore_regs_and_return_to_usermode() function.
399 * So all we check here is that dl->ops.target.sym is set, if it is, just
400 * go to that function and when exiting from its disassembly, come back
401 * to the calling function.
403 static bool annotate_browser__callq(struct annotate_browser *browser,
404 struct perf_evsel *evsel,
405 struct hist_browser_timer *hbt)
407 struct map_symbol *ms = browser->b.priv;
408 struct disasm_line *dl = disasm_line(browser->selection);
409 struct annotation *notes;
410 char title[SYM_TITLE_MAX_SIZE];
412 if (!dl->ops.target.sym) {
413 ui_helpline__puts("The called function was not found.");
417 notes = symbol__annotation(dl->ops.target.sym);
418 pthread_mutex_lock(¬es->lock);
420 if (!symbol__hists(dl->ops.target.sym, evsel->evlist->nr_entries)) {
421 pthread_mutex_unlock(¬es->lock);
422 ui__warning("Not enough memory for annotating '%s' symbol!\n",
423 dl->ops.target.sym->name);
427 pthread_mutex_unlock(¬es->lock);
428 symbol__tui_annotate(dl->ops.target.sym, ms->map, evsel, hbt, browser->opts);
429 sym_title(ms->sym, ms->map, title, sizeof(title), browser->opts->percent_type);
430 ui_browser__show_title(&browser->b, title);
435 struct disasm_line *annotate_browser__find_offset(struct annotate_browser *browser,
436 s64 offset, s64 *idx)
438 struct annotation *notes = browser__annotation(&browser->b);
439 struct disasm_line *pos;
442 list_for_each_entry(pos, ¬es->src->source, al.node) {
443 if (pos->al.offset == offset)
445 if (!annotation_line__filter(&pos->al, notes))
452 static bool annotate_browser__jump(struct annotate_browser *browser,
453 struct perf_evsel *evsel,
454 struct hist_browser_timer *hbt)
456 struct disasm_line *dl = disasm_line(browser->selection);
460 if (!ins__is_jump(&dl->ins))
463 if (dl->ops.target.outside) {
464 annotate_browser__callq(browser, evsel, hbt);
468 offset = dl->ops.target.offset;
469 dl = annotate_browser__find_offset(browser, offset, &idx);
471 ui_helpline__printf("Invalid jump offset: %" PRIx64, offset);
475 annotate_browser__set_top(browser, &dl->al, idx);
481 struct annotation_line *annotate_browser__find_string(struct annotate_browser *browser,
484 struct annotation *notes = browser__annotation(&browser->b);
485 struct annotation_line *al = browser->selection;
487 *idx = browser->b.index;
488 list_for_each_entry_continue(al, ¬es->src->source, node) {
489 if (annotation_line__filter(al, notes))
494 if (al->line && strstr(al->line, s) != NULL)
501 static bool __annotate_browser__search(struct annotate_browser *browser)
503 struct annotation_line *al;
506 al = annotate_browser__find_string(browser, browser->search_bf, &idx);
508 ui_helpline__puts("String not found!");
512 annotate_browser__set_top(browser, al, idx);
513 browser->searching_backwards = false;
518 struct annotation_line *annotate_browser__find_string_reverse(struct annotate_browser *browser,
521 struct annotation *notes = browser__annotation(&browser->b);
522 struct annotation_line *al = browser->selection;
524 *idx = browser->b.index;
525 list_for_each_entry_continue_reverse(al, ¬es->src->source, node) {
526 if (annotation_line__filter(al, notes))
531 if (al->line && strstr(al->line, s) != NULL)
538 static bool __annotate_browser__search_reverse(struct annotate_browser *browser)
540 struct annotation_line *al;
543 al = annotate_browser__find_string_reverse(browser, browser->search_bf, &idx);
545 ui_helpline__puts("String not found!");
549 annotate_browser__set_top(browser, al, idx);
550 browser->searching_backwards = true;
554 static bool annotate_browser__search_window(struct annotate_browser *browser,
557 if (ui_browser__input_window("Search", "String: ", browser->search_bf,
558 "ENTER: OK, ESC: Cancel",
559 delay_secs * 2) != K_ENTER ||
560 !*browser->search_bf)
566 static bool annotate_browser__search(struct annotate_browser *browser, int delay_secs)
568 if (annotate_browser__search_window(browser, delay_secs))
569 return __annotate_browser__search(browser);
574 static bool annotate_browser__continue_search(struct annotate_browser *browser,
577 if (!*browser->search_bf)
578 return annotate_browser__search(browser, delay_secs);
580 return __annotate_browser__search(browser);
583 static bool annotate_browser__search_reverse(struct annotate_browser *browser,
586 if (annotate_browser__search_window(browser, delay_secs))
587 return __annotate_browser__search_reverse(browser);
593 bool annotate_browser__continue_search_reverse(struct annotate_browser *browser,
596 if (!*browser->search_bf)
597 return annotate_browser__search_reverse(browser, delay_secs);
599 return __annotate_browser__search_reverse(browser);
602 static int annotate_browser__show(struct ui_browser *browser, char *title, const char *help)
604 struct annotate_browser *ab = container_of(browser, struct annotate_browser, b);
605 struct map_symbol *ms = browser->priv;
606 struct symbol *sym = ms->sym;
607 char symbol_dso[SYM_TITLE_MAX_SIZE];
609 if (ui_browser__show(browser, title, help) < 0)
612 sym_title(sym, ms->map, symbol_dso, sizeof(symbol_dso), ab->opts->percent_type);
614 ui_browser__gotorc_title(browser, 0, 0);
615 ui_browser__set_color(browser, HE_COLORSET_ROOT);
616 ui_browser__write_nstring(browser, symbol_dso, browser->width + 1);
621 switch_percent_type(struct annotation_options *opts, bool base)
623 switch (opts->percent_type) {
624 case PERCENT_HITS_LOCAL:
626 opts->percent_type = PERCENT_PERIOD_LOCAL;
628 opts->percent_type = PERCENT_HITS_GLOBAL;
630 case PERCENT_HITS_GLOBAL:
632 opts->percent_type = PERCENT_PERIOD_GLOBAL;
634 opts->percent_type = PERCENT_HITS_LOCAL;
636 case PERCENT_PERIOD_LOCAL:
638 opts->percent_type = PERCENT_HITS_LOCAL;
640 opts->percent_type = PERCENT_PERIOD_GLOBAL;
642 case PERCENT_PERIOD_GLOBAL:
644 opts->percent_type = PERCENT_HITS_GLOBAL;
646 opts->percent_type = PERCENT_PERIOD_LOCAL;
653 static int annotate_browser__run(struct annotate_browser *browser,
654 struct perf_evsel *evsel,
655 struct hist_browser_timer *hbt)
657 struct rb_node *nd = NULL;
658 struct hists *hists = evsel__hists(evsel);
659 struct map_symbol *ms = browser->b.priv;
660 struct symbol *sym = ms->sym;
661 struct annotation *notes = symbol__annotation(ms->sym);
662 const char *help = "Press 'h' for help on key bindings";
663 int delay_secs = hbt ? hbt->refresh : 0;
667 hists__scnprintf_title(hists, title, sizeof(title));
668 if (annotate_browser__show(&browser->b, title, help) < 0)
671 annotate_browser__calc_percent(browser, evsel);
673 if (browser->curr_hot) {
674 annotate_browser__set_rb_top(browser, browser->curr_hot);
675 browser->b.navkeypressed = false;
678 nd = browser->curr_hot;
681 key = ui_browser__run(&browser->b, delay_secs);
683 if (delay_secs != 0) {
684 annotate_browser__calc_percent(browser, evsel);
686 * Current line focus got out of the list of most active
687 * lines, NULL it so that if TAB|UNTAB is pressed, we
688 * move to curr_hot (current hottest line).
690 if (nd != NULL && RB_EMPTY_NODE(nd))
697 hbt->timer(hbt->arg);
699 if (delay_secs != 0) {
700 symbol__annotate_decay_histogram(sym, evsel->idx);
701 hists__scnprintf_title(hists, title, sizeof(title));
702 annotate_browser__show(&browser->b, title, help);
709 nd = rb_last(&browser->entries);
711 nd = browser->curr_hot;
717 nd = rb_first(&browser->entries);
719 nd = browser->curr_hot;
723 ui_browser__help_window(&browser->b,
725 "PGDN/SPACE Navigate\n"
726 "q/ESC/CTRL+C Exit\n\n"
727 "ENTER Go to target\n"
729 "H Go to hottest instruction\n"
730 "TAB/shift+TAB Cycle thru hottest instructions\n"
731 "j Toggle showing jump to target arrows\n"
732 "J Toggle showing number of jump sources on targets\n"
733 "n Search next string\n"
734 "o Toggle disassembler output/simplified view\n"
735 "O Bump offset level (jump targets -> +call -> all -> cycle thru)\n"
736 "s Toggle source code view\n"
737 "t Circulate percent, total period, samples view\n"
738 "c Show min/max cycle\n"
740 "k Toggle line numbers\n"
741 "P Print to [symbol_name].annotation file.\n"
742 "r Run available scripts\n"
743 "p Toggle percent type [local/global]\n"
744 "b Toggle percent base [period/hits]\n"
745 "? Search string backwards\n");
753 notes->options->show_linenr = !notes->options->show_linenr;
756 nd = browser->curr_hot;
759 if (annotate_browser__toggle_source(browser))
760 ui_helpline__puts(help);
763 notes->options->use_offset = !notes->options->use_offset;
764 annotation__update_column_widths(notes);
767 if (++notes->options->offset_level > ANNOTATION__MAX_OFFSET_LEVEL)
768 notes->options->offset_level = ANNOTATION__MIN_OFFSET_LEVEL;
771 notes->options->jump_arrows = !notes->options->jump_arrows;
774 notes->options->show_nr_jumps = !notes->options->show_nr_jumps;
775 annotation__update_column_widths(notes);
778 if (annotate_browser__search(browser, delay_secs)) {
780 ui_helpline__puts(help);
784 if (browser->searching_backwards ?
785 annotate_browser__continue_search_reverse(browser, delay_secs) :
786 annotate_browser__continue_search(browser, delay_secs))
790 if (annotate_browser__search_reverse(browser, delay_secs))
796 ui_helpline__fpush("%d: nr_ent=%d, height=%d, idx=%d, top_idx=%d, nr_asm_entries=%d",
797 seq++, browser->b.nr_entries,
801 notes->nr_asm_entries);
807 struct disasm_line *dl = disasm_line(browser->selection);
809 if (browser->selection == NULL)
810 ui_helpline__puts("Huh? No selection. Report to linux-kernel@vger.kernel.org");
811 else if (browser->selection->offset == -1)
812 ui_helpline__puts("Actions are only available for assembly lines.");
813 else if (!dl->ins.ops)
815 else if (ins__is_ret(&dl->ins))
817 else if (!(annotate_browser__jump(browser, evsel, hbt) ||
818 annotate_browser__callq(browser, evsel, hbt))) {
820 ui_helpline__puts("Actions are only available for function call/return & jump/branch instructions.");
825 map_symbol__annotation_dump(ms, evsel, browser->opts);
828 if (notes->options->show_total_period) {
829 notes->options->show_total_period = false;
830 notes->options->show_nr_samples = true;
831 } else if (notes->options->show_nr_samples)
832 notes->options->show_nr_samples = false;
834 notes->options->show_total_period = true;
835 annotation__update_column_widths(notes);
838 if (notes->options->show_minmax_cycle)
839 notes->options->show_minmax_cycle = false;
841 notes->options->show_minmax_cycle = true;
842 annotation__update_column_widths(notes);
846 switch_percent_type(browser->opts, key == 'b');
847 hists__scnprintf_title(hists, title, sizeof(title));
848 annotate_browser__show(&browser->b, title, help);
860 annotate_browser__set_rb_top(browser, nd);
863 ui_browser__hide(&browser->b);
867 int map_symbol__tui_annotate(struct map_symbol *ms, struct perf_evsel *evsel,
868 struct hist_browser_timer *hbt,
869 struct annotation_options *opts)
871 return symbol__tui_annotate(ms->sym, ms->map, evsel, hbt, opts);
874 int hist_entry__tui_annotate(struct hist_entry *he, struct perf_evsel *evsel,
875 struct hist_browser_timer *hbt,
876 struct annotation_options *opts)
878 /* reset abort key so that it can get Ctrl-C as a key */
880 SLang_init_tty(0, 0, 0);
882 return map_symbol__tui_annotate(&he->ms, evsel, hbt, opts);
885 int symbol__tui_annotate(struct symbol *sym, struct map *map,
886 struct perf_evsel *evsel,
887 struct hist_browser_timer *hbt,
888 struct annotation_options *opts)
890 struct annotation *notes = symbol__annotation(sym);
891 struct map_symbol ms = {
895 struct annotate_browser browser = {
897 .refresh = annotate_browser__refresh,
898 .seek = ui_browser__list_head_seek,
899 .write = annotate_browser__write,
900 .filter = disasm_line__filter,
901 .extra_title_lines = 1, /* for hists__scnprintf_title() */
903 .use_navkeypressed = true,
912 if (map->dso->annotate_warned)
915 err = symbol__annotate2(sym, map, evsel, opts, &browser.arch);
918 symbol__strerror_disassemble(sym, map, err, msg, sizeof(msg));
919 ui__error("Couldn't annotate %s:\n%s", sym->name, msg);
920 goto out_free_offsets;
923 ui_helpline__push("Press ESC to exit");
925 browser.b.width = notes->max_line_len;
926 browser.b.nr_entries = notes->nr_entries;
927 browser.b.entries = ¬es->src->source,
928 browser.b.width += 18; /* Percentage */
930 if (notes->options->hide_src_code)
931 ui_browser__init_asm_mode(&browser.b);
933 ret = annotate_browser__run(&browser, evsel, hbt);
935 annotated_source__purge(notes->src);
938 zfree(¬es->offsets);