1 #include "../../util/util.h"
2 #include "../browser.h"
3 #include "../helpline.h"
4 #include "../libslang.h"
7 #include "../../util/annotate.h"
8 #include "../../util/hist.h"
9 #include "../../util/sort.h"
10 #include "../../util/symbol.h"
14 struct browser_disasm_line
{
15 struct rb_node rb_node
;
22 static struct annotate_browser_opt
{
27 } annotate_browser__opts
= {
32 struct annotate_browser
{
34 struct rb_root entries
;
35 struct rb_node
*curr_hot
;
36 struct disasm_line
*selection
;
37 struct disasm_line
**offsets
;
43 bool searching_backwards
;
52 static inline struct browser_disasm_line
*disasm_line__browser(struct disasm_line
*dl
)
54 return (struct browser_disasm_line
*)(dl
+ 1);
57 static bool disasm_line__filter(struct ui_browser
*browser __maybe_unused
,
60 if (annotate_browser__opts
.hide_src_code
) {
61 struct disasm_line
*dl
= list_entry(entry
, struct disasm_line
, node
);
62 return dl
->offset
== -1;
68 static int annotate_browser__jumps_percent_color(struct annotate_browser
*browser
,
71 if (current
&& (!browser
->b
.use_navkeypressed
|| browser
->b
.navkeypressed
))
72 return HE_COLORSET_SELECTED
;
73 if (nr
== browser
->max_jump_sources
)
74 return HE_COLORSET_TOP
;
76 return HE_COLORSET_MEDIUM
;
77 return HE_COLORSET_NORMAL
;
80 static int annotate_browser__set_jumps_percent_color(struct annotate_browser
*browser
,
83 int color
= annotate_browser__jumps_percent_color(browser
, nr
, current
);
84 return ui_browser__set_color(&browser
->b
, color
);
87 static void annotate_browser__write(struct ui_browser
*browser
, void *entry
, int row
)
89 struct annotate_browser
*ab
= container_of(browser
, struct annotate_browser
, b
);
90 struct disasm_line
*dl
= list_entry(entry
, struct disasm_line
, node
);
91 struct browser_disasm_line
*bdl
= disasm_line__browser(dl
);
92 bool current_entry
= ui_browser__is_current_entry(browser
, row
);
93 bool change_color
= (!annotate_browser__opts
.hide_src_code
&&
94 (!current_entry
|| (browser
->use_navkeypressed
&&
95 !browser
->navkeypressed
)));
96 int width
= browser
->width
, printed
;
99 if (dl
->offset
!= -1 && bdl
->percent
!= 0.0) {
100 ui_browser__set_percent_color(browser
, bdl
->percent
, current_entry
);
101 slsmg_printf("%6.2f ", bdl
->percent
);
103 ui_browser__set_percent_color(browser
, 0, current_entry
);
104 slsmg_write_nstring(" ", 7);
107 SLsmg_write_char(' ');
109 /* The scroll bar isn't being used */
110 if (!browser
->navkeypressed
)
114 slsmg_write_nstring(" ", width
- 7);
115 else if (dl
->offset
== -1) {
116 printed
= scnprintf(bf
, sizeof(bf
), "%*s ",
117 ab
->addr_width
, " ");
118 slsmg_write_nstring(bf
, printed
);
119 slsmg_write_nstring(dl
->line
, width
- printed
- 6);
121 u64 addr
= dl
->offset
;
124 if (!annotate_browser__opts
.use_offset
)
127 if (!annotate_browser__opts
.use_offset
) {
128 printed
= scnprintf(bf
, sizeof(bf
), "%" PRIx64
": ", addr
);
130 if (bdl
->jump_sources
) {
131 if (annotate_browser__opts
.show_nr_jumps
) {
133 printed
= scnprintf(bf
, sizeof(bf
), "%*d ",
136 prev
= annotate_browser__set_jumps_percent_color(ab
, bdl
->jump_sources
,
138 slsmg_write_nstring(bf
, printed
);
139 ui_browser__set_color(browser
, prev
);
142 printed
= scnprintf(bf
, sizeof(bf
), "%*" PRIx64
": ",
143 ab
->target_width
, addr
);
145 printed
= scnprintf(bf
, sizeof(bf
), "%*s ",
146 ab
->addr_width
, " ");
151 color
= ui_browser__set_color(browser
, HE_COLORSET_ADDR
);
152 slsmg_write_nstring(bf
, printed
);
154 ui_browser__set_color(browser
, color
);
155 if (dl
->ins
&& dl
->ins
->ops
->scnprintf
) {
156 if (ins__is_jump(dl
->ins
)) {
157 bool fwd
= dl
->ops
.target
.offset
> (u64
)dl
->offset
;
159 ui_browser__write_graph(browser
, fwd
? SLSMG_DARROW_CHAR
:
161 SLsmg_write_char(' ');
162 } else if (ins__is_call(dl
->ins
)) {
163 ui_browser__write_graph(browser
, SLSMG_RARROW_CHAR
);
164 SLsmg_write_char(' ');
166 slsmg_write_nstring(" ", 2);
169 if (strcmp(dl
->name
, "retq")) {
170 slsmg_write_nstring(" ", 2);
172 ui_browser__write_graph(browser
, SLSMG_LARROW_CHAR
);
173 SLsmg_write_char(' ');
177 disasm_line__scnprintf(dl
, bf
, sizeof(bf
), !annotate_browser__opts
.use_offset
);
178 slsmg_write_nstring(bf
, width
- 10 - printed
);
185 static void annotate_browser__draw_current_jump(struct ui_browser
*browser
)
187 struct annotate_browser
*ab
= container_of(browser
, struct annotate_browser
, b
);
188 struct disasm_line
*cursor
= ab
->selection
, *target
;
189 struct browser_disasm_line
*btarget
, *bcursor
;
190 unsigned int from
, to
;
192 if (!cursor
|| !cursor
->ins
|| !ins__is_jump(cursor
->ins
) ||
193 !disasm_line__has_offset(cursor
))
196 target
= ab
->offsets
[cursor
->ops
.target
.offset
];
200 bcursor
= disasm_line__browser(cursor
);
201 btarget
= disasm_line__browser(target
);
203 if (annotate_browser__opts
.hide_src_code
) {
204 from
= bcursor
->idx_asm
;
205 to
= btarget
->idx_asm
;
207 from
= (u64
)bcursor
->idx
;
208 to
= (u64
)btarget
->idx
;
211 ui_browser__set_color(browser
, HE_COLORSET_CODE
);
212 __ui_browser__line_arrow(browser
, 9 + ab
->addr_width
, from
, to
);
215 static unsigned int annotate_browser__refresh(struct ui_browser
*browser
)
217 int ret
= ui_browser__list_head_refresh(browser
);
219 if (annotate_browser__opts
.jump_arrows
)
220 annotate_browser__draw_current_jump(browser
);
222 ui_browser__set_color(browser
, HE_COLORSET_NORMAL
);
223 __ui_browser__vline(browser
, 7, 0, browser
->height
- 1);
227 static double disasm_line__calc_percent(struct disasm_line
*dl
, struct symbol
*sym
, int evidx
)
229 double percent
= 0.0;
231 if (dl
->offset
!= -1) {
232 int len
= sym
->end
- sym
->start
;
233 unsigned int hits
= 0;
234 struct annotation
*notes
= symbol__annotation(sym
);
235 struct source_line
*src_line
= notes
->src
->lines
;
236 struct sym_hist
*h
= annotation__histogram(notes
, evidx
);
237 s64 offset
= dl
->offset
;
238 struct disasm_line
*next
;
240 next
= disasm__get_next_ip_line(¬es
->src
->source
, dl
);
241 while (offset
< (s64
)len
&&
242 (next
== NULL
|| offset
< next
->offset
)) {
244 percent
+= src_line
[offset
].percent
;
246 hits
+= h
->addr
[offset
];
251 * If the percentage wasn't already calculated in
252 * symbol__get_source_line, do it now:
254 if (src_line
== NULL
&& h
->sum
)
255 percent
= 100.0 * hits
/ h
->sum
;
261 static void disasm_rb_tree__insert(struct rb_root
*root
, struct browser_disasm_line
*bdl
)
263 struct rb_node
**p
= &root
->rb_node
;
264 struct rb_node
*parent
= NULL
;
265 struct browser_disasm_line
*l
;
269 l
= rb_entry(parent
, struct browser_disasm_line
, rb_node
);
270 if (bdl
->percent
< l
->percent
)
275 rb_link_node(&bdl
->rb_node
, parent
, p
);
276 rb_insert_color(&bdl
->rb_node
, root
);
279 static void annotate_browser__set_top(struct annotate_browser
*browser
,
280 struct disasm_line
*pos
, u32 idx
)
284 ui_browser__refresh_dimensions(&browser
->b
);
285 back
= browser
->b
.height
/ 2;
286 browser
->b
.top_idx
= browser
->b
.index
= idx
;
288 while (browser
->b
.top_idx
!= 0 && back
!= 0) {
289 pos
= list_entry(pos
->node
.prev
, struct disasm_line
, node
);
291 if (disasm_line__filter(&browser
->b
, &pos
->node
))
294 --browser
->b
.top_idx
;
298 browser
->b
.top
= pos
;
299 browser
->b
.navkeypressed
= true;
302 static void annotate_browser__set_rb_top(struct annotate_browser
*browser
,
305 struct browser_disasm_line
*bpos
;
306 struct disasm_line
*pos
;
309 bpos
= rb_entry(nd
, struct browser_disasm_line
, rb_node
);
310 pos
= ((struct disasm_line
*)bpos
) - 1;
312 if (annotate_browser__opts
.hide_src_code
)
314 annotate_browser__set_top(browser
, pos
, idx
);
315 browser
->curr_hot
= nd
;
318 static void annotate_browser__calc_percent(struct annotate_browser
*browser
,
321 struct map_symbol
*ms
= browser
->b
.priv
;
322 struct symbol
*sym
= ms
->sym
;
323 struct annotation
*notes
= symbol__annotation(sym
);
324 struct disasm_line
*pos
;
326 browser
->entries
= RB_ROOT
;
328 pthread_mutex_lock(¬es
->lock
);
330 list_for_each_entry(pos
, ¬es
->src
->source
, node
) {
331 struct browser_disasm_line
*bpos
= disasm_line__browser(pos
);
332 bpos
->percent
= disasm_line__calc_percent(pos
, sym
, evidx
);
333 if (bpos
->percent
< 0.01) {
334 RB_CLEAR_NODE(&bpos
->rb_node
);
337 disasm_rb_tree__insert(&browser
->entries
, bpos
);
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 disasm_line
*dl
;
347 struct browser_disasm_line
*bdl
;
348 off_t offset
= browser
->b
.index
- browser
->b
.top_idx
;
350 browser
->b
.seek(&browser
->b
, offset
, SEEK_CUR
);
351 dl
= list_entry(browser
->b
.top
, struct disasm_line
, node
);
352 bdl
= disasm_line__browser(dl
);
354 if (annotate_browser__opts
.hide_src_code
) {
355 if (bdl
->idx_asm
< offset
)
358 browser
->b
.nr_entries
= browser
->nr_entries
;
359 annotate_browser__opts
.hide_src_code
= false;
360 browser
->b
.seek(&browser
->b
, -offset
, SEEK_CUR
);
361 browser
->b
.top_idx
= bdl
->idx
- offset
;
362 browser
->b
.index
= bdl
->idx
;
364 if (bdl
->idx_asm
< 0) {
365 ui_helpline__puts("Only available for assembly lines.");
366 browser
->b
.seek(&browser
->b
, -offset
, SEEK_CUR
);
370 if (bdl
->idx_asm
< offset
)
371 offset
= bdl
->idx_asm
;
373 browser
->b
.nr_entries
= browser
->nr_asm_entries
;
374 annotate_browser__opts
.hide_src_code
= true;
375 browser
->b
.seek(&browser
->b
, -offset
, SEEK_CUR
);
376 browser
->b
.top_idx
= bdl
->idx_asm
- offset
;
377 browser
->b
.index
= bdl
->idx_asm
;
383 static void annotate_browser__init_asm_mode(struct annotate_browser
*browser
)
385 ui_browser__reset_index(&browser
->b
);
386 browser
->b
.nr_entries
= browser
->nr_asm_entries
;
389 static bool annotate_browser__callq(struct annotate_browser
*browser
,
390 int evidx
, void (*timer
)(void *arg
),
391 void *arg
, int delay_secs
)
393 struct map_symbol
*ms
= browser
->b
.priv
;
394 struct disasm_line
*dl
= browser
->selection
;
395 struct symbol
*sym
= ms
->sym
;
396 struct annotation
*notes
;
397 struct symbol
*target
;
400 if (!ins__is_call(dl
->ins
))
403 ip
= ms
->map
->map_ip(ms
->map
, dl
->ops
.target
.addr
);
404 target
= map__find_symbol(ms
->map
, ip
, NULL
);
405 if (target
== NULL
) {
406 ui_helpline__puts("The called function was not found.");
410 notes
= symbol__annotation(target
);
411 pthread_mutex_lock(¬es
->lock
);
413 if (notes
->src
== NULL
&& symbol__alloc_hist(target
) < 0) {
414 pthread_mutex_unlock(¬es
->lock
);
415 ui__warning("Not enough memory for annotating '%s' symbol!\n",
420 pthread_mutex_unlock(¬es
->lock
);
421 symbol__tui_annotate(target
, ms
->map
, evidx
, timer
, arg
, delay_secs
);
422 ui_browser__show_title(&browser
->b
, sym
->name
);
427 struct disasm_line
*annotate_browser__find_offset(struct annotate_browser
*browser
,
428 s64 offset
, s64
*idx
)
430 struct map_symbol
*ms
= browser
->b
.priv
;
431 struct symbol
*sym
= ms
->sym
;
432 struct annotation
*notes
= symbol__annotation(sym
);
433 struct disasm_line
*pos
;
436 list_for_each_entry(pos
, ¬es
->src
->source
, node
) {
437 if (pos
->offset
== offset
)
439 if (!disasm_line__filter(&browser
->b
, &pos
->node
))
446 static bool annotate_browser__jump(struct annotate_browser
*browser
)
448 struct disasm_line
*dl
= browser
->selection
;
451 if (!ins__is_jump(dl
->ins
))
454 dl
= annotate_browser__find_offset(browser
, dl
->ops
.target
.offset
, &idx
);
456 ui_helpline__puts("Invallid jump offset");
460 annotate_browser__set_top(browser
, dl
, idx
);
466 struct disasm_line
*annotate_browser__find_string(struct annotate_browser
*browser
,
469 struct map_symbol
*ms
= browser
->b
.priv
;
470 struct symbol
*sym
= ms
->sym
;
471 struct annotation
*notes
= symbol__annotation(sym
);
472 struct disasm_line
*pos
= browser
->selection
;
474 *idx
= browser
->b
.index
;
475 list_for_each_entry_continue(pos
, ¬es
->src
->source
, node
) {
476 if (disasm_line__filter(&browser
->b
, &pos
->node
))
481 if (pos
->line
&& strstr(pos
->line
, s
) != NULL
)
488 static bool __annotate_browser__search(struct annotate_browser
*browser
)
490 struct disasm_line
*dl
;
493 dl
= annotate_browser__find_string(browser
, browser
->search_bf
, &idx
);
495 ui_helpline__puts("String not found!");
499 annotate_browser__set_top(browser
, dl
, idx
);
500 browser
->searching_backwards
= false;
505 struct disasm_line
*annotate_browser__find_string_reverse(struct annotate_browser
*browser
,
508 struct map_symbol
*ms
= browser
->b
.priv
;
509 struct symbol
*sym
= ms
->sym
;
510 struct annotation
*notes
= symbol__annotation(sym
);
511 struct disasm_line
*pos
= browser
->selection
;
513 *idx
= browser
->b
.index
;
514 list_for_each_entry_continue_reverse(pos
, ¬es
->src
->source
, node
) {
515 if (disasm_line__filter(&browser
->b
, &pos
->node
))
520 if (pos
->line
&& strstr(pos
->line
, s
) != NULL
)
527 static bool __annotate_browser__search_reverse(struct annotate_browser
*browser
)
529 struct disasm_line
*dl
;
532 dl
= annotate_browser__find_string_reverse(browser
, browser
->search_bf
, &idx
);
534 ui_helpline__puts("String not found!");
538 annotate_browser__set_top(browser
, dl
, idx
);
539 browser
->searching_backwards
= true;
543 static bool annotate_browser__search_window(struct annotate_browser
*browser
,
546 if (ui_browser__input_window("Search", "String: ", browser
->search_bf
,
547 "ENTER: OK, ESC: Cancel",
548 delay_secs
* 2) != K_ENTER
||
549 !*browser
->search_bf
)
555 static bool annotate_browser__search(struct annotate_browser
*browser
, int delay_secs
)
557 if (annotate_browser__search_window(browser
, delay_secs
))
558 return __annotate_browser__search(browser
);
563 static bool annotate_browser__continue_search(struct annotate_browser
*browser
,
566 if (!*browser
->search_bf
)
567 return annotate_browser__search(browser
, delay_secs
);
569 return __annotate_browser__search(browser
);
572 static bool annotate_browser__search_reverse(struct annotate_browser
*browser
,
575 if (annotate_browser__search_window(browser
, delay_secs
))
576 return __annotate_browser__search_reverse(browser
);
582 bool annotate_browser__continue_search_reverse(struct annotate_browser
*browser
,
585 if (!*browser
->search_bf
)
586 return annotate_browser__search_reverse(browser
, delay_secs
);
588 return __annotate_browser__search_reverse(browser
);
591 static void annotate_browser__update_addr_width(struct annotate_browser
*browser
)
593 if (annotate_browser__opts
.use_offset
)
594 browser
->target_width
= browser
->min_addr_width
;
596 browser
->target_width
= browser
->max_addr_width
;
598 browser
->addr_width
= browser
->target_width
;
600 if (annotate_browser__opts
.show_nr_jumps
)
601 browser
->addr_width
+= browser
->jumps_width
+ 1;
604 static int annotate_browser__run(struct annotate_browser
*browser
, int evidx
,
605 void(*timer
)(void *arg
),
606 void *arg
, int delay_secs
)
608 struct rb_node
*nd
= NULL
;
609 struct map_symbol
*ms
= browser
->b
.priv
;
610 struct symbol
*sym
= ms
->sym
;
611 const char *help
= "Press 'h' for help on key bindings";
614 if (ui_browser__show(&browser
->b
, sym
->name
, help
) < 0)
617 annotate_browser__calc_percent(browser
, evidx
);
619 if (browser
->curr_hot
) {
620 annotate_browser__set_rb_top(browser
, browser
->curr_hot
);
621 browser
->b
.navkeypressed
= false;
624 nd
= browser
->curr_hot
;
627 key
= ui_browser__run(&browser
->b
, delay_secs
);
629 if (delay_secs
!= 0) {
630 annotate_browser__calc_percent(browser
, evidx
);
632 * Current line focus got out of the list of most active
633 * lines, NULL it so that if TAB|UNTAB is pressed, we
634 * move to curr_hot (current hottest line).
636 if (nd
!= NULL
&& RB_EMPTY_NODE(nd
))
646 symbol__annotate_decay_histogram(sym
, evidx
);
652 nd
= rb_last(&browser
->entries
);
654 nd
= browser
->curr_hot
;
660 nd
= rb_first(&browser
->entries
);
662 nd
= browser
->curr_hot
;
666 ui_browser__help_window(&browser
->b
,
668 "PGDN/SPACE Navigate\n"
669 "q/ESC/CTRL+C Exit\n\n"
672 "H Cycle thru hottest instructions\n"
673 "j Toggle showing jump to target arrows\n"
674 "J Toggle showing number of jump sources on targets\n"
675 "n Search next string\n"
676 "o Toggle disassembler output/simplified view\n"
677 "s Toggle source code view\n"
679 "? Search previous string\n");
682 nd
= browser
->curr_hot
;
685 if (annotate_browser__toggle_source(browser
))
686 ui_helpline__puts(help
);
689 annotate_browser__opts
.use_offset
= !annotate_browser__opts
.use_offset
;
690 annotate_browser__update_addr_width(browser
);
693 annotate_browser__opts
.jump_arrows
= !annotate_browser__opts
.jump_arrows
;
696 annotate_browser__opts
.show_nr_jumps
= !annotate_browser__opts
.show_nr_jumps
;
697 annotate_browser__update_addr_width(browser
);
700 if (annotate_browser__search(browser
, delay_secs
)) {
702 ui_helpline__puts(help
);
706 if (browser
->searching_backwards
?
707 annotate_browser__continue_search_reverse(browser
, delay_secs
) :
708 annotate_browser__continue_search(browser
, delay_secs
))
712 if (annotate_browser__search_reverse(browser
, delay_secs
))
718 ui_helpline__fpush("%d: nr_ent=%d, height=%d, idx=%d, top_idx=%d, nr_asm_entries=%d",
719 seq
++, browser
->b
.nr_entries
,
723 browser
->nr_asm_entries
);
728 if (browser
->selection
== NULL
)
729 ui_helpline__puts("Huh? No selection. Report to linux-kernel@vger.kernel.org");
730 else if (browser
->selection
->offset
== -1)
731 ui_helpline__puts("Actions are only available for assembly lines.");
732 else if (!browser
->selection
->ins
) {
733 if (strcmp(browser
->selection
->name
, "retq"))
736 } else if (!(annotate_browser__jump(browser
) ||
737 annotate_browser__callq(browser
, evidx
, timer
, arg
, delay_secs
))) {
739 ui_helpline__puts("Actions are only available for 'callq', 'retq' & jump instructions.");
752 annotate_browser__set_rb_top(browser
, nd
);
755 ui_browser__hide(&browser
->b
);
759 int hist_entry__tui_annotate(struct hist_entry
*he
, int evidx
,
760 void(*timer
)(void *arg
), void *arg
, int delay_secs
)
762 return symbol__tui_annotate(he
->ms
.sym
, he
->ms
.map
, evidx
,
763 timer
, arg
, delay_secs
);
766 static void annotate_browser__mark_jump_targets(struct annotate_browser
*browser
,
771 for (offset
= 0; offset
< size
; ++offset
) {
772 struct disasm_line
*dl
= browser
->offsets
[offset
], *dlt
;
773 struct browser_disasm_line
*bdlt
;
775 if (!dl
|| !dl
->ins
|| !ins__is_jump(dl
->ins
) ||
776 !disasm_line__has_offset(dl
))
779 if (dl
->ops
.target
.offset
>= size
) {
780 ui__error("jump to after symbol!\n"
781 "size: %zx, jump target: %" PRIx64
,
782 size
, dl
->ops
.target
.offset
);
786 dlt
= browser
->offsets
[dl
->ops
.target
.offset
];
788 * FIXME: Oops, no jump target? Buggy disassembler? Or do we
789 * have to adjust to the previous offset?
794 bdlt
= disasm_line__browser(dlt
);
795 if (++bdlt
->jump_sources
> browser
->max_jump_sources
)
796 browser
->max_jump_sources
= bdlt
->jump_sources
;
803 static inline int width_jumps(int n
)
812 int symbol__tui_annotate(struct symbol
*sym
, struct map
*map
, int evidx
,
813 void(*timer
)(void *arg
), void *arg
,
816 struct disasm_line
*pos
, *n
;
817 struct annotation
*notes
;
819 struct map_symbol ms
= {
823 struct annotate_browser browser
= {
825 .refresh
= annotate_browser__refresh
,
826 .seek
= ui_browser__list_head_seek
,
827 .write
= annotate_browser__write
,
828 .filter
= disasm_line__filter
,
830 .use_navkeypressed
= true,
838 size
= symbol__size(sym
);
840 if (map
->dso
->annotate_warned
)
843 browser
.offsets
= zalloc(size
* sizeof(struct disasm_line
*));
844 if (browser
.offsets
== NULL
) {
845 ui__error("Not enough memory!");
849 if (symbol__annotate(sym
, map
, sizeof(struct browser_disasm_line
)) < 0) {
850 ui__error("%s", ui_helpline__last_msg
);
851 goto out_free_offsets
;
854 ui_helpline__push("Press <- or ESC to exit");
856 notes
= symbol__annotation(sym
);
857 browser
.start
= map__rip_2objdump(map
, sym
->start
);
859 list_for_each_entry(pos
, ¬es
->src
->source
, node
) {
860 struct browser_disasm_line
*bpos
;
861 size_t line_len
= strlen(pos
->line
);
863 if (browser
.b
.width
< line_len
)
864 browser
.b
.width
= line_len
;
865 bpos
= disasm_line__browser(pos
);
866 bpos
->idx
= browser
.nr_entries
++;
867 if (pos
->offset
!= -1) {
868 bpos
->idx_asm
= browser
.nr_asm_entries
++;
870 * FIXME: short term bandaid to cope with assembly
871 * routines that comes with labels in the same column
872 * as the address in objdump, sigh.
874 * E.g. copy_user_generic_unrolled
876 if (pos
->offset
< (s64
)size
)
877 browser
.offsets
[pos
->offset
] = pos
;
882 annotate_browser__mark_jump_targets(&browser
, size
);
884 browser
.addr_width
= browser
.target_width
= browser
.min_addr_width
= hex_width(size
);
885 browser
.max_addr_width
= hex_width(sym
->end
);
886 browser
.jumps_width
= width_jumps(browser
.max_jump_sources
);
887 browser
.b
.nr_entries
= browser
.nr_entries
;
888 browser
.b
.entries
= ¬es
->src
->source
,
889 browser
.b
.width
+= 18; /* Percentage */
891 if (annotate_browser__opts
.hide_src_code
)
892 annotate_browser__init_asm_mode(&browser
);
894 annotate_browser__update_addr_width(&browser
);
896 ret
= annotate_browser__run(&browser
, evidx
, timer
, arg
, delay_secs
);
897 list_for_each_entry_safe(pos
, n
, ¬es
->src
->source
, node
) {
898 list_del(&pos
->node
);
899 disasm_line__free(pos
);
903 free(browser
.offsets
);
907 #define ANNOTATE_CFG(n) \
908 { .name = #n, .value = &annotate_browser__opts.n, }
911 * Keep the entries sorted, they are bsearch'ed
913 static struct annotate__config
{
916 } annotate__configs
[] = {
917 ANNOTATE_CFG(hide_src_code
),
918 ANNOTATE_CFG(jump_arrows
),
919 ANNOTATE_CFG(show_nr_jumps
),
920 ANNOTATE_CFG(use_offset
),
925 static int annotate_config__cmp(const void *name
, const void *cfgp
)
927 const struct annotate__config
*cfg
= cfgp
;
929 return strcmp(name
, cfg
->name
);
932 static int annotate__config(const char *var
, const char *value
,
933 void *data __maybe_unused
)
935 struct annotate__config
*cfg
;
938 if (prefixcmp(var
, "annotate.") != 0)
942 cfg
= bsearch(name
, annotate__configs
, ARRAY_SIZE(annotate__configs
),
943 sizeof(struct annotate__config
), annotate_config__cmp
);
948 *cfg
->value
= perf_config_bool(name
, value
);
952 void annotate_browser__init(void)
954 perf_config(annotate__config
, NULL
);