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"
22 static struct annotate_browser_opt {
27 } annotate_browser__opts = {
60 if (annotate_browser__opts.hide_src_code) {
68 static int annotate_browser__jumps_percent_color(
struct annotate_browser *browser,
71 if (current && (!browser->
b.use_navkeypressed || browser->
b.navkeypressed))
80 static int annotate_browser__set_jumps_percent_color(
struct annotate_browser *browser,
83 int color = annotate_browser__jumps_percent_color(browser, nr, current);
87 static void annotate_browser__write(
struct ui_browser *browser,
void *entry,
int row)
93 bool change_color = (!annotate_browser__opts.hide_src_code &&
107 SLsmg_write_char(
' ');
115 else if (dl->
offset == -1) {
116 printed =
scnprintf(bf,
sizeof(bf),
"%*s ",
124 if (!annotate_browser__opts.use_offset)
127 if (!annotate_browser__opts.use_offset) {
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,
145 printed =
scnprintf(bf,
sizeof(bf),
"%*s ",
155 if (dl->
ins && dl->
ins->ops->scnprintf) {
161 SLsmg_write_char(
' ');
164 SLsmg_write_char(
' ');
173 SLsmg_write_char(
' ');
185 static void annotate_browser__draw_current_jump(
struct ui_browser *browser)
190 unsigned int from, to;
193 !disasm_line__has_offset(cursor))
200 bcursor = disasm_line__browser(cursor);
201 btarget = disasm_line__browser(
target);
203 if (annotate_browser__opts.hide_src_code) {
215 static unsigned int annotate_browser__refresh(
struct ui_browser *browser)
219 if (annotate_browser__opts.jump_arrows)
220 annotate_browser__draw_current_jump(browser);
227 static double disasm_line__calc_percent(
struct disasm_line *dl,
struct symbol *sym,
int evidx)
233 unsigned int hits = 0;
234 struct annotation *notes = symbol__annotation(sym);
236 struct sym_hist *
h = annotation__histogram(notes, evidx);
241 while (offset < (
s64)len &&
254 if (src_line ==
NULL && h->
sum)
255 percent = 100.0 * hits / h->
sum;
275 rb_link_node(&bdl->
rb_node, parent, p);
285 back = browser->
b.height / 2;
286 browser->
b.top_idx = browser->
b.index =
idx;
288 while (browser->
b.top_idx != 0 && back != 0) {
291 if (disasm_line__filter(&browser->
b, &pos->
node))
294 --browser->
b.top_idx;
298 browser->
b.top =
pos;
299 browser->
b.navkeypressed =
true;
312 if (annotate_browser__opts.hide_src_code)
314 annotate_browser__set_top(browser, pos, idx);
318 static void annotate_browser__calc_percent(
struct annotate_browser *browser,
323 struct annotation *notes = symbol__annotation(sym);
328 pthread_mutex_lock(¬es->
lock);
332 bpos->
percent = disasm_line__calc_percent(pos, sym, evidx);
337 disasm_rb_tree__insert(&browser->
entries, bpos);
339 pthread_mutex_unlock(¬es->
lock);
344 static bool annotate_browser__toggle_source(
struct annotate_browser *browser)
348 off_t offset = browser->
b.index - browser->
b.top_idx;
350 browser->
b.seek(&browser->
b, offset,
SEEK_CUR);
352 bdl = disasm_line__browser(dl);
354 if (annotate_browser__opts.hide_src_code) {
359 annotate_browser__opts.hide_src_code =
false;
360 browser->
b.seek(&browser->
b, -offset,
SEEK_CUR);
362 browser->
b.index = bdl->
idx;
366 browser->
b.seek(&browser->
b, -offset,
SEEK_CUR);
374 annotate_browser__opts.hide_src_code =
true;
375 browser->
b.seek(&browser->
b, -offset,
SEEK_CUR);
383 static void annotate_browser__init_asm_mode(
struct annotate_browser *browser)
390 int evidx,
void (*
timer)(
void *
arg),
391 void *arg,
int delay_secs)
403 ip = ms->
map->map_ip(ms->
map, dl->
ops.target.addr);
405 if (target ==
NULL) {
410 notes = symbol__annotation(target);
411 pthread_mutex_lock(¬es->
lock);
414 pthread_mutex_unlock(¬es->
lock);
415 ui__warning(
"Not enough memory for annotating '%s' symbol!\n",
420 pthread_mutex_unlock(¬es->
lock);
432 struct annotation *notes = symbol__annotation(sym);
437 if (pos->
offset == offset)
439 if (!disasm_line__filter(&browser->
b, &pos->
node))
454 dl = annotate_browser__find_offset(browser, dl->
ops.target.offset, &idx);
460 annotate_browser__set_top(browser, dl, idx);
471 struct annotation *notes = symbol__annotation(sym);
474 *idx = browser->
b.index;
476 if (disasm_line__filter(&browser->
b, &pos->
node))
493 dl = annotate_browser__find_string(browser, browser->
search_bf, &idx);
499 annotate_browser__set_top(browser, dl, idx);
510 struct annotation *notes = symbol__annotation(sym);
513 *idx = browser->
b.index;
515 if (disasm_line__filter(&browser->
b, &pos->
node))
527 static bool __annotate_browser__search_reverse(
struct annotate_browser *browser)
532 dl = annotate_browser__find_string_reverse(browser, browser->
search_bf, &idx);
538 annotate_browser__set_top(browser, dl, idx);
543 static bool annotate_browser__search_window(
struct annotate_browser *browser,
547 "ENTER: OK, ESC: Cancel",
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,
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,
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)
600 if (annotate_browser__opts.show_nr_jumps)
604 static int annotate_browser__run(
struct annotate_browser *browser,
int evidx,
605 void(*
timer)(
void *arg),
606 void *arg,
int delay_secs)
611 const char *help =
"Press 'h' for help on key bindings";
617 annotate_browser__calc_percent(browser, evidx);
620 annotate_browser__set_rb_top(browser, browser->
curr_hot);
621 browser->
b.navkeypressed =
false;
629 if (delay_secs != 0) {
630 annotate_browser__calc_percent(browser, evidx);
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");
685 if (annotate_browser__toggle_source(browser))
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)) {
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))
719 seq++, browser->
b.nr_entries,
730 else if (browser->
selection->offset == -1)
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);
760 void(*
timer)(
void *arg),
void *arg,
int delay_secs)
763 timer, arg, delay_secs);
766 static void annotate_browser__mark_jump_targets(
struct annotate_browser *browser,
776 !disasm_line__has_offset(dl))
779 if (dl->
ops.target.offset >= size) {
781 "size: %zx, jump target: %" PRIx64,
782 size, dl->
ops.target.offset);
786 dlt = browser->
offsets[dl->
ops.target.offset];
794 bdlt = disasm_line__browser(dlt);
803 static inline int width_jumps(
int n)
813 void(*
timer)(
void *arg),
void *arg,
825 .refresh = annotate_browser__refresh,
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)
851 goto out_free_offsets;
856 notes = symbol__annotation(sym);
863 if (browser.
b.width < line_len)
864 browser.
b.width = line_len;
865 bpos = disasm_line__browser(pos);
882 annotate_browser__mark_jump_targets(&browser, size);
888 browser.
b.entries = ¬es->
src->source,
889 browser.
b.width += 18;
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);
907 #define ANNOTATE_CFG(n) \
908 { .name = #n, .value = &annotate_browser__opts.n, }
913 static struct annotate__config {
916 } annotate__configs[] = {
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;
943 sizeof(
struct annotate__config), annotate_config__cmp);