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/map.h"
11 #include "../../util/symbol.h"
12 #include "../../util/evsel.h"
13 #include "../../util/evlist.h"
16 #include <linux/kernel.h>
17 #include <linux/string.h>
18 #include <sys/ttydefaults.h>
21 struct disasm_line_samples {
23 struct sym_hist_entry he;
28 struct annotate_browser {
30 struct rb_root entries;
31 struct rb_node *curr_hot;
32 struct annotation_line *selection;
34 struct annotation_options *opts;
35 bool searching_backwards;
39 static inline struct annotation *browser__annotation(struct ui_browser *browser)
41 struct map_symbol *ms = browser->priv;
42 return symbol__annotation(ms->sym);
45 static bool disasm_line__filter(struct ui_browser *browser, void *entry)
47 struct annotation *notes = browser__annotation(browser);
48 struct annotation_line *al = list_entry(entry, struct annotation_line, node);
49 return annotation_line__filter(al, notes);
52 static int ui_browser__jumps_percent_color(struct ui_browser *browser, int nr, bool current)
54 struct annotation *notes = browser__annotation(browser);
56 if (current && (!browser->use_navkeypressed || browser->navkeypressed))
57 return HE_COLORSET_SELECTED;
58 if (nr == notes->max_jump_sources)
59 return HE_COLORSET_TOP;
61 return HE_COLORSET_MEDIUM;
62 return HE_COLORSET_NORMAL;
65 static int ui_browser__set_jumps_percent_color(void *browser, int nr, bool current)
67 int color = ui_browser__jumps_percent_color(browser, nr, current);
68 return ui_browser__set_color(browser, color);
71 static int annotate_browser__set_color(void *browser, int color)
73 return ui_browser__set_color(browser, color);
76 static void annotate_browser__write_graph(void *browser, int graph)
78 ui_browser__write_graph(browser, graph);
81 static void annotate_browser__set_percent_color(void *browser, double percent, bool current)
83 ui_browser__set_percent_color(browser, percent, current);
86 static void annotate_browser__printf(void *browser, const char *fmt, ...)
91 ui_browser__vprintf(browser, fmt, args);
95 static void annotate_browser__write(struct ui_browser *browser, void *entry, int row)
97 struct annotate_browser *ab = container_of(browser, struct annotate_browser, b);
98 struct annotation *notes = browser__annotation(browser);
99 struct annotation_line *al = list_entry(entry, struct annotation_line, node);
100 struct annotation_write_ops ops = {
101 .first_line = row == 0,
102 .current_entry = ui_browser__is_current_entry(browser, row),
103 .change_color = (!notes->options->hide_src_code &&
104 (!ops.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 double disasm__cmp(struct annotation_line *a, struct annotation_line *b,
233 for (i = 0; i < a->data_nr; i++) {
234 if (a->data[i].percent[percent_type] == b->data[i].percent[percent_type])
236 return a->data[i].percent[percent_type] -
237 b->data[i].percent[percent_type];
242 static void disasm_rb_tree__insert(struct annotate_browser *browser,
243 struct annotation_line *al)
245 struct rb_root *root = &browser->entries;
246 struct rb_node **p = &root->rb_node;
247 struct rb_node *parent = NULL;
248 struct annotation_line *l;
252 l = rb_entry(parent, struct annotation_line, rb_node);
254 if (disasm__cmp(al, l, browser->opts->percent_type) < 0)
259 rb_link_node(&al->rb_node, parent, p);
260 rb_insert_color(&al->rb_node, root);
263 static void annotate_browser__set_top(struct annotate_browser *browser,
264 struct annotation_line *pos, u32 idx)
266 struct annotation *notes = browser__annotation(&browser->b);
269 ui_browser__refresh_dimensions(&browser->b);
270 back = browser->b.height / 2;
271 browser->b.top_idx = browser->b.index = idx;
273 while (browser->b.top_idx != 0 && back != 0) {
274 pos = list_entry(pos->node.prev, struct annotation_line, node);
276 if (annotation_line__filter(pos, notes))
279 --browser->b.top_idx;
283 browser->b.top = pos;
284 browser->b.navkeypressed = true;
287 static void annotate_browser__set_rb_top(struct annotate_browser *browser,
290 struct annotation *notes = browser__annotation(&browser->b);
291 struct annotation_line * pos = rb_entry(nd, struct annotation_line, rb_node);
294 if (notes->options->hide_src_code)
296 annotate_browser__set_top(browser, pos, idx);
297 browser->curr_hot = nd;
300 static void annotate_browser__calc_percent(struct annotate_browser *browser,
301 struct perf_evsel *evsel)
303 struct map_symbol *ms = browser->b.priv;
304 struct symbol *sym = ms->sym;
305 struct annotation *notes = symbol__annotation(sym);
306 struct disasm_line *pos;
308 browser->entries = RB_ROOT;
310 pthread_mutex_lock(¬es->lock);
312 symbol__calc_percent(sym, evsel);
314 list_for_each_entry(pos, ¬es->src->source, al.node) {
315 double max_percent = 0.0;
318 if (pos->al.offset == -1) {
319 RB_CLEAR_NODE(&pos->al.rb_node);
323 for (i = 0; i < pos->al.data_nr; i++) {
326 percent = annotation_data__percent(&pos->al.data[i],
327 browser->opts->percent_type);
329 if (max_percent < percent)
330 max_percent = percent;
333 if (max_percent < 0.01 && pos->al.ipc == 0) {
334 RB_CLEAR_NODE(&pos->al.rb_node);
337 disasm_rb_tree__insert(browser, &pos->al);
339 pthread_mutex_unlock(¬es->lock);
341 browser->curr_hot = rb_last(&browser->entries);
344 static bool annotate_browser__toggle_source(struct annotate_browser *browser)
346 struct annotation *notes = browser__annotation(&browser->b);
347 struct annotation_line *al;
348 off_t offset = browser->b.index - browser->b.top_idx;
350 browser->b.seek(&browser->b, offset, SEEK_CUR);
351 al = list_entry(browser->b.top, struct annotation_line, node);
353 if (notes->options->hide_src_code) {
354 if (al->idx_asm < offset)
357 browser->b.nr_entries = notes->nr_entries;
358 notes->options->hide_src_code = false;
359 browser->b.seek(&browser->b, -offset, SEEK_CUR);
360 browser->b.top_idx = al->idx - offset;
361 browser->b.index = al->idx;
363 if (al->idx_asm < 0) {
364 ui_helpline__puts("Only available for assembly lines.");
365 browser->b.seek(&browser->b, -offset, SEEK_CUR);
369 if (al->idx_asm < offset)
370 offset = al->idx_asm;
372 browser->b.nr_entries = notes->nr_asm_entries;
373 notes->options->hide_src_code = true;
374 browser->b.seek(&browser->b, -offset, SEEK_CUR);
375 browser->b.top_idx = al->idx_asm - offset;
376 browser->b.index = al->idx_asm;
382 static void ui_browser__init_asm_mode(struct ui_browser *browser)
384 struct annotation *notes = browser__annotation(browser);
385 ui_browser__reset_index(browser);
386 browser->nr_entries = notes->nr_asm_entries;
389 #define SYM_TITLE_MAX_SIZE (PATH_MAX + 64)
391 static int sym_title(struct symbol *sym, struct map *map, char *title,
392 size_t sz, int percent_type)
394 return snprintf(title, sz, "%s %s [Percent: %s]", sym->name, map->dso->long_name,
395 percent_type_str(percent_type));
399 * This can be called from external jumps, i.e. jumps from one functon
400 * to another, like from the kernel's entry_SYSCALL_64 function to the
401 * swapgs_restore_regs_and_return_to_usermode() function.
403 * So all we check here is that dl->ops.target.sym is set, if it is, just
404 * go to that function and when exiting from its disassembly, come back
405 * to the calling function.
407 static bool annotate_browser__callq(struct annotate_browser *browser,
408 struct perf_evsel *evsel,
409 struct hist_browser_timer *hbt)
411 struct map_symbol *ms = browser->b.priv;
412 struct disasm_line *dl = disasm_line(browser->selection);
413 struct annotation *notes;
414 char title[SYM_TITLE_MAX_SIZE];
416 if (!dl->ops.target.sym) {
417 ui_helpline__puts("The called function was not found.");
421 notes = symbol__annotation(dl->ops.target.sym);
422 pthread_mutex_lock(¬es->lock);
424 if (!symbol__hists(dl->ops.target.sym, evsel->evlist->nr_entries)) {
425 pthread_mutex_unlock(¬es->lock);
426 ui__warning("Not enough memory for annotating '%s' symbol!\n",
427 dl->ops.target.sym->name);
431 pthread_mutex_unlock(¬es->lock);
432 symbol__tui_annotate(dl->ops.target.sym, ms->map, evsel, hbt, browser->opts);
433 sym_title(ms->sym, ms->map, title, sizeof(title), browser->opts->percent_type);
434 ui_browser__show_title(&browser->b, title);
439 struct disasm_line *annotate_browser__find_offset(struct annotate_browser *browser,
440 s64 offset, s64 *idx)
442 struct annotation *notes = browser__annotation(&browser->b);
443 struct disasm_line *pos;
446 list_for_each_entry(pos, ¬es->src->source, al.node) {
447 if (pos->al.offset == offset)
449 if (!annotation_line__filter(&pos->al, notes))
456 static bool annotate_browser__jump(struct annotate_browser *browser,
457 struct perf_evsel *evsel,
458 struct hist_browser_timer *hbt)
460 struct disasm_line *dl = disasm_line(browser->selection);
464 if (!ins__is_jump(&dl->ins))
467 if (dl->ops.target.outside) {
468 annotate_browser__callq(browser, evsel, hbt);
472 offset = dl->ops.target.offset;
473 dl = annotate_browser__find_offset(browser, offset, &idx);
475 ui_helpline__printf("Invalid jump offset: %" PRIx64, offset);
479 annotate_browser__set_top(browser, &dl->al, idx);
485 struct annotation_line *annotate_browser__find_string(struct annotate_browser *browser,
488 struct annotation *notes = browser__annotation(&browser->b);
489 struct annotation_line *al = browser->selection;
491 *idx = browser->b.index;
492 list_for_each_entry_continue(al, ¬es->src->source, node) {
493 if (annotation_line__filter(al, notes))
498 if (al->line && strstr(al->line, s) != NULL)
505 static bool __annotate_browser__search(struct annotate_browser *browser)
507 struct annotation_line *al;
510 al = annotate_browser__find_string(browser, browser->search_bf, &idx);
512 ui_helpline__puts("String not found!");
516 annotate_browser__set_top(browser, al, idx);
517 browser->searching_backwards = false;
522 struct annotation_line *annotate_browser__find_string_reverse(struct annotate_browser *browser,
525 struct annotation *notes = browser__annotation(&browser->b);
526 struct annotation_line *al = browser->selection;
528 *idx = browser->b.index;
529 list_for_each_entry_continue_reverse(al, ¬es->src->source, node) {
530 if (annotation_line__filter(al, notes))
535 if (al->line && strstr(al->line, s) != NULL)
542 static bool __annotate_browser__search_reverse(struct annotate_browser *browser)
544 struct annotation_line *al;
547 al = annotate_browser__find_string_reverse(browser, browser->search_bf, &idx);
549 ui_helpline__puts("String not found!");
553 annotate_browser__set_top(browser, al, idx);
554 browser->searching_backwards = true;
558 static bool annotate_browser__search_window(struct annotate_browser *browser,
561 if (ui_browser__input_window("Search", "String: ", browser->search_bf,
562 "ENTER: OK, ESC: Cancel",
563 delay_secs * 2) != K_ENTER ||
564 !*browser->search_bf)
570 static bool annotate_browser__search(struct annotate_browser *browser, int delay_secs)
572 if (annotate_browser__search_window(browser, delay_secs))
573 return __annotate_browser__search(browser);
578 static bool annotate_browser__continue_search(struct annotate_browser *browser,
581 if (!*browser->search_bf)
582 return annotate_browser__search(browser, delay_secs);
584 return __annotate_browser__search(browser);
587 static bool annotate_browser__search_reverse(struct annotate_browser *browser,
590 if (annotate_browser__search_window(browser, delay_secs))
591 return __annotate_browser__search_reverse(browser);
597 bool annotate_browser__continue_search_reverse(struct annotate_browser *browser,
600 if (!*browser->search_bf)
601 return annotate_browser__search_reverse(browser, delay_secs);
603 return __annotate_browser__search_reverse(browser);
606 static int annotate_browser__show(struct ui_browser *browser, char *title, const char *help)
608 struct annotate_browser *ab = container_of(browser, struct annotate_browser, b);
609 struct map_symbol *ms = browser->priv;
610 struct symbol *sym = ms->sym;
611 char symbol_dso[SYM_TITLE_MAX_SIZE];
613 if (ui_browser__show(browser, title, help) < 0)
616 sym_title(sym, ms->map, symbol_dso, sizeof(symbol_dso), ab->opts->percent_type);
618 ui_browser__gotorc_title(browser, 0, 0);
619 ui_browser__set_color(browser, HE_COLORSET_ROOT);
620 ui_browser__write_nstring(browser, symbol_dso, browser->width + 1);
625 switch_percent_type(struct annotation_options *opts, bool base)
627 switch (opts->percent_type) {
628 case PERCENT_HITS_LOCAL:
630 opts->percent_type = PERCENT_PERIOD_LOCAL;
632 opts->percent_type = PERCENT_HITS_GLOBAL;
634 case PERCENT_HITS_GLOBAL:
636 opts->percent_type = PERCENT_PERIOD_GLOBAL;
638 opts->percent_type = PERCENT_HITS_LOCAL;
640 case PERCENT_PERIOD_LOCAL:
642 opts->percent_type = PERCENT_HITS_LOCAL;
644 opts->percent_type = PERCENT_PERIOD_GLOBAL;
646 case PERCENT_PERIOD_GLOBAL:
648 opts->percent_type = PERCENT_HITS_GLOBAL;
650 opts->percent_type = PERCENT_PERIOD_LOCAL;
657 static int annotate_browser__run(struct annotate_browser *browser,
658 struct perf_evsel *evsel,
659 struct hist_browser_timer *hbt)
661 struct rb_node *nd = NULL;
662 struct hists *hists = evsel__hists(evsel);
663 struct map_symbol *ms = browser->b.priv;
664 struct symbol *sym = ms->sym;
665 struct annotation *notes = symbol__annotation(ms->sym);
666 const char *help = "Press 'h' for help on key bindings";
667 int delay_secs = hbt ? hbt->refresh : 0;
671 hists__scnprintf_title(hists, title, sizeof(title));
672 if (annotate_browser__show(&browser->b, title, help) < 0)
675 annotate_browser__calc_percent(browser, evsel);
677 if (browser->curr_hot) {
678 annotate_browser__set_rb_top(browser, browser->curr_hot);
679 browser->b.navkeypressed = false;
682 nd = browser->curr_hot;
685 key = ui_browser__run(&browser->b, delay_secs);
687 if (delay_secs != 0) {
688 annotate_browser__calc_percent(browser, evsel);
690 * Current line focus got out of the list of most active
691 * lines, NULL it so that if TAB|UNTAB is pressed, we
692 * move to curr_hot (current hottest line).
694 if (nd != NULL && RB_EMPTY_NODE(nd))
701 hbt->timer(hbt->arg);
703 if (delay_secs != 0) {
704 symbol__annotate_decay_histogram(sym, evsel->idx);
705 hists__scnprintf_title(hists, title, sizeof(title));
706 annotate_browser__show(&browser->b, title, help);
713 nd = rb_last(&browser->entries);
715 nd = browser->curr_hot;
721 nd = rb_first(&browser->entries);
723 nd = browser->curr_hot;
727 ui_browser__help_window(&browser->b,
729 "PGDN/SPACE Navigate\n"
730 "q/ESC/CTRL+C Exit\n\n"
731 "ENTER Go to target\n"
733 "H Go to hottest instruction\n"
734 "TAB/shift+TAB Cycle thru hottest instructions\n"
735 "j Toggle showing jump to target arrows\n"
736 "J Toggle showing number of jump sources on targets\n"
737 "n Search next string\n"
738 "o Toggle disassembler output/simplified view\n"
739 "O Bump offset level (jump targets -> +call -> all -> cycle thru)\n"
740 "s Toggle source code view\n"
741 "t Circulate percent, total period, samples view\n"
742 "c Show min/max cycle\n"
744 "k Toggle line numbers\n"
745 "P Print to [symbol_name].annotation file.\n"
746 "r Run available scripts\n"
747 "p Toggle percent type [local/global]\n"
748 "b Toggle percent base [period/hits]\n"
749 "? Search string backwards\n");
753 script_browse(NULL, NULL);
757 notes->options->show_linenr = !notes->options->show_linenr;
760 nd = browser->curr_hot;
763 if (annotate_browser__toggle_source(browser))
764 ui_helpline__puts(help);
767 notes->options->use_offset = !notes->options->use_offset;
768 annotation__update_column_widths(notes);
771 if (++notes->options->offset_level > ANNOTATION__MAX_OFFSET_LEVEL)
772 notes->options->offset_level = ANNOTATION__MIN_OFFSET_LEVEL;
775 notes->options->jump_arrows = !notes->options->jump_arrows;
778 notes->options->show_nr_jumps = !notes->options->show_nr_jumps;
779 annotation__update_column_widths(notes);
782 if (annotate_browser__search(browser, delay_secs)) {
784 ui_helpline__puts(help);
788 if (browser->searching_backwards ?
789 annotate_browser__continue_search_reverse(browser, delay_secs) :
790 annotate_browser__continue_search(browser, delay_secs))
794 if (annotate_browser__search_reverse(browser, delay_secs))
800 ui_helpline__fpush("%d: nr_ent=%d, height=%d, idx=%d, top_idx=%d, nr_asm_entries=%d",
801 seq++, browser->b.nr_entries,
805 notes->nr_asm_entries);
811 struct disasm_line *dl = disasm_line(browser->selection);
813 if (browser->selection == NULL)
814 ui_helpline__puts("Huh? No selection. Report to linux-kernel@vger.kernel.org");
815 else if (browser->selection->offset == -1)
816 ui_helpline__puts("Actions are only available for assembly lines.");
817 else if (!dl->ins.ops)
819 else if (ins__is_ret(&dl->ins))
821 else if (!(annotate_browser__jump(browser, evsel, hbt) ||
822 annotate_browser__callq(browser, evsel, hbt))) {
824 ui_helpline__puts("Actions are only available for function call/return & jump/branch instructions.");
829 map_symbol__annotation_dump(ms, evsel, browser->opts);
832 if (notes->options->show_total_period) {
833 notes->options->show_total_period = false;
834 notes->options->show_nr_samples = true;
835 } else if (notes->options->show_nr_samples)
836 notes->options->show_nr_samples = false;
838 notes->options->show_total_period = true;
839 annotation__update_column_widths(notes);
842 if (notes->options->show_minmax_cycle)
843 notes->options->show_minmax_cycle = false;
845 notes->options->show_minmax_cycle = true;
846 annotation__update_column_widths(notes);
850 switch_percent_type(browser->opts, key == 'b');
851 hists__scnprintf_title(hists, title, sizeof(title));
852 annotate_browser__show(&browser->b, title, help);
864 annotate_browser__set_rb_top(browser, nd);
867 ui_browser__hide(&browser->b);
871 int map_symbol__tui_annotate(struct map_symbol *ms, struct perf_evsel *evsel,
872 struct hist_browser_timer *hbt,
873 struct annotation_options *opts)
875 return symbol__tui_annotate(ms->sym, ms->map, evsel, hbt, opts);
878 int hist_entry__tui_annotate(struct hist_entry *he, struct perf_evsel *evsel,
879 struct hist_browser_timer *hbt,
880 struct annotation_options *opts)
882 /* reset abort key so that it can get Ctrl-C as a key */
884 SLang_init_tty(0, 0, 0);
886 return map_symbol__tui_annotate(&he->ms, evsel, hbt, opts);
889 int symbol__tui_annotate(struct symbol *sym, struct map *map,
890 struct perf_evsel *evsel,
891 struct hist_browser_timer *hbt,
892 struct annotation_options *opts)
894 struct annotation *notes = symbol__annotation(sym);
895 struct map_symbol ms = {
899 struct annotate_browser browser = {
901 .refresh = annotate_browser__refresh,
902 .seek = ui_browser__list_head_seek,
903 .write = annotate_browser__write,
904 .filter = disasm_line__filter,
905 .extra_title_lines = 1, /* for hists__scnprintf_title() */
907 .use_navkeypressed = true,
916 if (map->dso->annotate_warned)
919 err = symbol__annotate2(sym, map, evsel, opts, &browser.arch);
922 symbol__strerror_disassemble(sym, map, err, msg, sizeof(msg));
923 ui__error("Couldn't annotate %s:\n%s", sym->name, msg);
924 goto out_free_offsets;
927 ui_helpline__push("Press ESC to exit");
929 browser.b.width = notes->max_line_len;
930 browser.b.nr_entries = notes->nr_entries;
931 browser.b.entries = ¬es->src->source,
932 browser.b.width += 18; /* Percentage */
934 if (notes->options->hide_src_code)
935 ui_browser__init_asm_mode(&browser.b);
937 ret = annotate_browser__run(&browser, evsel, hbt);
939 annotated_source__purge(notes->src);
942 zfree(¬es->offsets);