1aca7a94dSNamhyung Kim #include "../../util/util.h" 2aca7a94dSNamhyung Kim #include "../browser.h" 3aca7a94dSNamhyung Kim #include "../helpline.h" 4aca7a94dSNamhyung Kim #include "../libslang.h" 5aca7a94dSNamhyung Kim #include "../ui.h" 6aca7a94dSNamhyung Kim #include "../util.h" 7aca7a94dSNamhyung Kim #include "../../util/annotate.h" 8aca7a94dSNamhyung Kim #include "../../util/hist.h" 9aca7a94dSNamhyung Kim #include "../../util/sort.h" 10aca7a94dSNamhyung Kim #include "../../util/symbol.h" 11db8fd07aSNamhyung Kim #include "../../util/evsel.h" 12aca7a94dSNamhyung Kim #include <pthread.h> 13aca7a94dSNamhyung Kim 140c4a5bceSMartin Liška struct disasm_line_samples { 150c4a5bceSMartin Liška double percent; 160c4a5bceSMartin Liška u64 nr; 170c4a5bceSMartin Liška }; 180c4a5bceSMartin Liška 19b793a401SArnaldo Carvalho de Melo struct browser_disasm_line { 20b793a401SArnaldo Carvalho de Melo struct rb_node rb_node; 21b793a401SArnaldo Carvalho de Melo u32 idx; 22b793a401SArnaldo Carvalho de Melo int idx_asm; 237d5b12f5SArnaldo Carvalho de Melo int jump_sources; 24c7e7b610SNamhyung Kim /* 25c7e7b610SNamhyung Kim * actual length of this array is saved on the nr_events field 26c7e7b610SNamhyung Kim * of the struct annotate_browser 27c7e7b610SNamhyung Kim */ 280c4a5bceSMartin Liška struct disasm_line_samples samples[1]; 29b793a401SArnaldo Carvalho de Melo }; 30b793a401SArnaldo Carvalho de Melo 31e9823b21SArnaldo Carvalho de Melo static struct annotate_browser_opt { 32e9823b21SArnaldo Carvalho de Melo bool hide_src_code, 33e9823b21SArnaldo Carvalho de Melo use_offset, 34e9823b21SArnaldo Carvalho de Melo jump_arrows, 35e592488cSAndi Kleen show_linenr, 360c4a5bceSMartin Liška show_nr_jumps, 370c4a5bceSMartin Liška show_total_period; 38e9823b21SArnaldo Carvalho de Melo } annotate_browser__opts = { 39e9823b21SArnaldo Carvalho de Melo .use_offset = true, 40e9823b21SArnaldo Carvalho de Melo .jump_arrows = true, 41e9823b21SArnaldo Carvalho de Melo }; 42e9823b21SArnaldo Carvalho de Melo 43aca7a94dSNamhyung Kim struct annotate_browser { 44aca7a94dSNamhyung Kim struct ui_browser b; 45aca7a94dSNamhyung Kim struct rb_root entries; 46aca7a94dSNamhyung Kim struct rb_node *curr_hot; 4729ed6e76SArnaldo Carvalho de Melo struct disasm_line *selection; 48b793a401SArnaldo Carvalho de Melo struct disasm_line **offsets; 49c7e7b610SNamhyung Kim int nr_events; 50aca7a94dSNamhyung Kim u64 start; 51aca7a94dSNamhyung Kim int nr_asm_entries; 52aca7a94dSNamhyung Kim int nr_entries; 532402e4a9SArnaldo Carvalho de Melo int max_jump_sources; 542402e4a9SArnaldo Carvalho de Melo int nr_jumps; 55aca7a94dSNamhyung Kim bool searching_backwards; 56*30e863bbSAndi Kleen bool have_cycles; 5783b1f2aaSArnaldo Carvalho de Melo u8 addr_width; 582402e4a9SArnaldo Carvalho de Melo u8 jumps_width; 592402e4a9SArnaldo Carvalho de Melo u8 target_width; 6083b1f2aaSArnaldo Carvalho de Melo u8 min_addr_width; 6183b1f2aaSArnaldo Carvalho de Melo u8 max_addr_width; 62aca7a94dSNamhyung Kim char search_bf[128]; 63aca7a94dSNamhyung Kim }; 64aca7a94dSNamhyung Kim 65887c0066SArnaldo Carvalho de Melo static inline struct browser_disasm_line *disasm_line__browser(struct disasm_line *dl) 66aca7a94dSNamhyung Kim { 67887c0066SArnaldo Carvalho de Melo return (struct browser_disasm_line *)(dl + 1); 68aca7a94dSNamhyung Kim } 69aca7a94dSNamhyung Kim 701d037ca1SIrina Tirdea static bool disasm_line__filter(struct ui_browser *browser __maybe_unused, 711d037ca1SIrina Tirdea void *entry) 72aca7a94dSNamhyung Kim { 73e9823b21SArnaldo Carvalho de Melo if (annotate_browser__opts.hide_src_code) { 7429ed6e76SArnaldo Carvalho de Melo struct disasm_line *dl = list_entry(entry, struct disasm_line, node); 7529ed6e76SArnaldo Carvalho de Melo return dl->offset == -1; 76aca7a94dSNamhyung Kim } 77aca7a94dSNamhyung Kim 78aca7a94dSNamhyung Kim return false; 79aca7a94dSNamhyung Kim } 80aca7a94dSNamhyung Kim 812402e4a9SArnaldo Carvalho de Melo static int annotate_browser__jumps_percent_color(struct annotate_browser *browser, 822402e4a9SArnaldo Carvalho de Melo int nr, bool current) 832402e4a9SArnaldo Carvalho de Melo { 842402e4a9SArnaldo Carvalho de Melo if (current && (!browser->b.use_navkeypressed || browser->b.navkeypressed)) 852402e4a9SArnaldo Carvalho de Melo return HE_COLORSET_SELECTED; 862402e4a9SArnaldo Carvalho de Melo if (nr == browser->max_jump_sources) 872402e4a9SArnaldo Carvalho de Melo return HE_COLORSET_TOP; 882402e4a9SArnaldo Carvalho de Melo if (nr > 1) 892402e4a9SArnaldo Carvalho de Melo return HE_COLORSET_MEDIUM; 902402e4a9SArnaldo Carvalho de Melo return HE_COLORSET_NORMAL; 912402e4a9SArnaldo Carvalho de Melo } 922402e4a9SArnaldo Carvalho de Melo 932402e4a9SArnaldo Carvalho de Melo static int annotate_browser__set_jumps_percent_color(struct annotate_browser *browser, 942402e4a9SArnaldo Carvalho de Melo int nr, bool current) 952402e4a9SArnaldo Carvalho de Melo { 962402e4a9SArnaldo Carvalho de Melo int color = annotate_browser__jumps_percent_color(browser, nr, current); 972402e4a9SArnaldo Carvalho de Melo return ui_browser__set_color(&browser->b, color); 982402e4a9SArnaldo Carvalho de Melo } 992402e4a9SArnaldo Carvalho de Melo 10005e8b080SArnaldo Carvalho de Melo static void annotate_browser__write(struct ui_browser *browser, void *entry, int row) 101aca7a94dSNamhyung Kim { 10205e8b080SArnaldo Carvalho de Melo struct annotate_browser *ab = container_of(browser, struct annotate_browser, b); 10329ed6e76SArnaldo Carvalho de Melo struct disasm_line *dl = list_entry(entry, struct disasm_line, node); 104b793a401SArnaldo Carvalho de Melo struct browser_disasm_line *bdl = disasm_line__browser(dl); 10505e8b080SArnaldo Carvalho de Melo bool current_entry = ui_browser__is_current_entry(browser, row); 106e9823b21SArnaldo Carvalho de Melo bool change_color = (!annotate_browser__opts.hide_src_code && 10705e8b080SArnaldo Carvalho de Melo (!current_entry || (browser->use_navkeypressed && 10805e8b080SArnaldo Carvalho de Melo !browser->navkeypressed))); 10905e8b080SArnaldo Carvalho de Melo int width = browser->width, printed; 110c7e7b610SNamhyung Kim int i, pcnt_width = 7 * ab->nr_events; 111c7e7b610SNamhyung Kim double percent_max = 0.0; 11283b1f2aaSArnaldo Carvalho de Melo char bf[256]; 113aca7a94dSNamhyung Kim 114c7e7b610SNamhyung Kim for (i = 0; i < ab->nr_events; i++) { 1150c4a5bceSMartin Liška if (bdl->samples[i].percent > percent_max) 1160c4a5bceSMartin Liška percent_max = bdl->samples[i].percent; 117c7e7b610SNamhyung Kim } 118c7e7b610SNamhyung Kim 119c7e7b610SNamhyung Kim if (dl->offset != -1 && percent_max != 0.0) { 120c7e7b610SNamhyung Kim for (i = 0; i < ab->nr_events; i++) { 1210c4a5bceSMartin Liška ui_browser__set_percent_color(browser, 1220c4a5bceSMartin Liška bdl->samples[i].percent, 123c7e7b610SNamhyung Kim current_entry); 1240c4a5bceSMartin Liška if (annotate_browser__opts.show_total_period) 1250c4a5bceSMartin Liška slsmg_printf("%6" PRIu64 " ", 1260c4a5bceSMartin Liška bdl->samples[i].nr); 1270c4a5bceSMartin Liška else 1280c4a5bceSMartin Liška slsmg_printf("%6.2f ", bdl->samples[i].percent); 129c7e7b610SNamhyung Kim } 130aca7a94dSNamhyung Kim } else { 13105e8b080SArnaldo Carvalho de Melo ui_browser__set_percent_color(browser, 0, current_entry); 132c7e7b610SNamhyung Kim slsmg_write_nstring(" ", pcnt_width); 133aca7a94dSNamhyung Kim } 134aca7a94dSNamhyung Kim 135cf2dacc5SArnaldo Carvalho de Melo SLsmg_write_char(' '); 136aca7a94dSNamhyung Kim 137aca7a94dSNamhyung Kim /* The scroll bar isn't being used */ 13805e8b080SArnaldo Carvalho de Melo if (!browser->navkeypressed) 139aca7a94dSNamhyung Kim width += 1; 140aca7a94dSNamhyung Kim 14129ed6e76SArnaldo Carvalho de Melo if (!*dl->line) 142c7e7b610SNamhyung Kim slsmg_write_nstring(" ", width - pcnt_width); 14383b1f2aaSArnaldo Carvalho de Melo else if (dl->offset == -1) { 144e592488cSAndi Kleen if (dl->line_nr && annotate_browser__opts.show_linenr) 145e592488cSAndi Kleen printed = scnprintf(bf, sizeof(bf), "%-*d ", 146e592488cSAndi Kleen ab->addr_width + 1, dl->line_nr); 147e592488cSAndi Kleen else 14883b1f2aaSArnaldo Carvalho de Melo printed = scnprintf(bf, sizeof(bf), "%*s ", 14983b1f2aaSArnaldo Carvalho de Melo ab->addr_width, " "); 15083b1f2aaSArnaldo Carvalho de Melo slsmg_write_nstring(bf, printed); 151c7e7b610SNamhyung Kim slsmg_write_nstring(dl->line, width - printed - pcnt_width + 1); 15283b1f2aaSArnaldo Carvalho de Melo } else { 15329ed6e76SArnaldo Carvalho de Melo u64 addr = dl->offset; 15483b1f2aaSArnaldo Carvalho de Melo int color = -1; 155aca7a94dSNamhyung Kim 156e9823b21SArnaldo Carvalho de Melo if (!annotate_browser__opts.use_offset) 157aca7a94dSNamhyung Kim addr += ab->start; 158aca7a94dSNamhyung Kim 159e9823b21SArnaldo Carvalho de Melo if (!annotate_browser__opts.use_offset) { 160aca7a94dSNamhyung Kim printed = scnprintf(bf, sizeof(bf), "%" PRIx64 ": ", addr); 16161e04b33SArnaldo Carvalho de Melo } else { 1627d5b12f5SArnaldo Carvalho de Melo if (bdl->jump_sources) { 163e9823b21SArnaldo Carvalho de Melo if (annotate_browser__opts.show_nr_jumps) { 1642402e4a9SArnaldo Carvalho de Melo int prev; 1652402e4a9SArnaldo Carvalho de Melo printed = scnprintf(bf, sizeof(bf), "%*d ", 1662402e4a9SArnaldo Carvalho de Melo ab->jumps_width, 1672402e4a9SArnaldo Carvalho de Melo bdl->jump_sources); 1682402e4a9SArnaldo Carvalho de Melo prev = annotate_browser__set_jumps_percent_color(ab, bdl->jump_sources, 1692402e4a9SArnaldo Carvalho de Melo current_entry); 1702402e4a9SArnaldo Carvalho de Melo slsmg_write_nstring(bf, printed); 17105e8b080SArnaldo Carvalho de Melo ui_browser__set_color(browser, prev); 1722402e4a9SArnaldo Carvalho de Melo } 1732402e4a9SArnaldo Carvalho de Melo 17461e04b33SArnaldo Carvalho de Melo printed = scnprintf(bf, sizeof(bf), "%*" PRIx64 ": ", 1752402e4a9SArnaldo Carvalho de Melo ab->target_width, addr); 17661e04b33SArnaldo Carvalho de Melo } else { 17761e04b33SArnaldo Carvalho de Melo printed = scnprintf(bf, sizeof(bf), "%*s ", 17883b1f2aaSArnaldo Carvalho de Melo ab->addr_width, " "); 17961e04b33SArnaldo Carvalho de Melo } 18061e04b33SArnaldo Carvalho de Melo } 181b793a401SArnaldo Carvalho de Melo 182aca7a94dSNamhyung Kim if (change_color) 18305e8b080SArnaldo Carvalho de Melo color = ui_browser__set_color(browser, HE_COLORSET_ADDR); 184aca7a94dSNamhyung Kim slsmg_write_nstring(bf, printed); 185aca7a94dSNamhyung Kim if (change_color) 18605e8b080SArnaldo Carvalho de Melo ui_browser__set_color(browser, color); 18728548d78SArnaldo Carvalho de Melo if (dl->ins && dl->ins->ops->scnprintf) { 18851a0d455SArnaldo Carvalho de Melo if (ins__is_jump(dl->ins)) { 18944d1a3edSArnaldo Carvalho de Melo bool fwd = dl->ops.target.offset > (u64)dl->offset; 19051a0d455SArnaldo Carvalho de Melo 19105e8b080SArnaldo Carvalho de Melo ui_browser__write_graph(browser, fwd ? SLSMG_DARROW_CHAR : 19251a0d455SArnaldo Carvalho de Melo SLSMG_UARROW_CHAR); 19351a0d455SArnaldo Carvalho de Melo SLsmg_write_char(' '); 19488298f5aSArnaldo Carvalho de Melo } else if (ins__is_call(dl->ins)) { 19505e8b080SArnaldo Carvalho de Melo ui_browser__write_graph(browser, SLSMG_RARROW_CHAR); 19688298f5aSArnaldo Carvalho de Melo SLsmg_write_char(' '); 19751a0d455SArnaldo Carvalho de Melo } else { 19851a0d455SArnaldo Carvalho de Melo slsmg_write_nstring(" ", 2); 19951a0d455SArnaldo Carvalho de Melo } 2004ea08b52SArnaldo Carvalho de Melo } else { 2014ea08b52SArnaldo Carvalho de Melo if (strcmp(dl->name, "retq")) { 2024ea08b52SArnaldo Carvalho de Melo slsmg_write_nstring(" ", 2); 2034ea08b52SArnaldo Carvalho de Melo } else { 20405e8b080SArnaldo Carvalho de Melo ui_browser__write_graph(browser, SLSMG_LARROW_CHAR); 2054ea08b52SArnaldo Carvalho de Melo SLsmg_write_char(' '); 2064ea08b52SArnaldo Carvalho de Melo } 2074ea08b52SArnaldo Carvalho de Melo } 2084ea08b52SArnaldo Carvalho de Melo 209e9823b21SArnaldo Carvalho de Melo disasm_line__scnprintf(dl, bf, sizeof(bf), !annotate_browser__opts.use_offset); 210c7e7b610SNamhyung Kim slsmg_write_nstring(bf, width - pcnt_width - 3 - printed); 211aca7a94dSNamhyung Kim } 212aca7a94dSNamhyung Kim 213aca7a94dSNamhyung Kim if (current_entry) 21429ed6e76SArnaldo Carvalho de Melo ab->selection = dl; 215aca7a94dSNamhyung Kim } 216aca7a94dSNamhyung Kim 217865c66c4SFrederik Deweerdt static bool disasm_line__is_valid_jump(struct disasm_line *dl, struct symbol *sym) 218865c66c4SFrederik Deweerdt { 219865c66c4SFrederik Deweerdt if (!dl || !dl->ins || !ins__is_jump(dl->ins) 220865c66c4SFrederik Deweerdt || !disasm_line__has_offset(dl) 221865c66c4SFrederik Deweerdt || dl->ops.target.offset >= symbol__size(sym)) 222865c66c4SFrederik Deweerdt return false; 223865c66c4SFrederik Deweerdt 224865c66c4SFrederik Deweerdt return true; 225865c66c4SFrederik Deweerdt } 226865c66c4SFrederik Deweerdt 2279d1ef56dSArnaldo Carvalho de Melo static void annotate_browser__draw_current_jump(struct ui_browser *browser) 228a3f895beSArnaldo Carvalho de Melo { 229a3f895beSArnaldo Carvalho de Melo struct annotate_browser *ab = container_of(browser, struct annotate_browser, b); 2309d1ef56dSArnaldo Carvalho de Melo struct disasm_line *cursor = ab->selection, *target; 2319d1ef56dSArnaldo Carvalho de Melo struct browser_disasm_line *btarget, *bcursor; 23283b1f2aaSArnaldo Carvalho de Melo unsigned int from, to; 23332ae1efdSNamhyung Kim struct map_symbol *ms = ab->b.priv; 23432ae1efdSNamhyung Kim struct symbol *sym = ms->sym; 235c7e7b610SNamhyung Kim u8 pcnt_width = 7; 23632ae1efdSNamhyung Kim 23732ae1efdSNamhyung Kim /* PLT symbols contain external offsets */ 23832ae1efdSNamhyung Kim if (strstr(sym->name, "@plt")) 23932ae1efdSNamhyung Kim return; 240a3f895beSArnaldo Carvalho de Melo 241865c66c4SFrederik Deweerdt if (!disasm_line__is_valid_jump(cursor, sym)) 242a3f895beSArnaldo Carvalho de Melo return; 243a3f895beSArnaldo Carvalho de Melo 2449d1ef56dSArnaldo Carvalho de Melo target = ab->offsets[cursor->ops.target.offset]; 2459d1ef56dSArnaldo Carvalho de Melo if (!target) 2469d1ef56dSArnaldo Carvalho de Melo return; 2479d1ef56dSArnaldo Carvalho de Melo 2489d1ef56dSArnaldo Carvalho de Melo bcursor = disasm_line__browser(cursor); 2499d1ef56dSArnaldo Carvalho de Melo btarget = disasm_line__browser(target); 2509d1ef56dSArnaldo Carvalho de Melo 251e9823b21SArnaldo Carvalho de Melo if (annotate_browser__opts.hide_src_code) { 2529d1ef56dSArnaldo Carvalho de Melo from = bcursor->idx_asm; 253a3f895beSArnaldo Carvalho de Melo to = btarget->idx_asm; 254a3f895beSArnaldo Carvalho de Melo } else { 2559d1ef56dSArnaldo Carvalho de Melo from = (u64)bcursor->idx; 256a3f895beSArnaldo Carvalho de Melo to = (u64)btarget->idx; 257a3f895beSArnaldo Carvalho de Melo } 258a3f895beSArnaldo Carvalho de Melo 259c7e7b610SNamhyung Kim pcnt_width *= ab->nr_events; 260c7e7b610SNamhyung Kim 261a3f895beSArnaldo Carvalho de Melo ui_browser__set_color(browser, HE_COLORSET_CODE); 262c7e7b610SNamhyung Kim __ui_browser__line_arrow(browser, pcnt_width + 2 + ab->addr_width, 263c7e7b610SNamhyung Kim from, to); 264a3f895beSArnaldo Carvalho de Melo } 265a3f895beSArnaldo Carvalho de Melo 266a3f895beSArnaldo Carvalho de Melo static unsigned int annotate_browser__refresh(struct ui_browser *browser) 267a3f895beSArnaldo Carvalho de Melo { 268c7e7b610SNamhyung Kim struct annotate_browser *ab = container_of(browser, struct annotate_browser, b); 269a3f895beSArnaldo Carvalho de Melo int ret = ui_browser__list_head_refresh(browser); 270c7e7b610SNamhyung Kim int pcnt_width; 271c7e7b610SNamhyung Kim 272c7e7b610SNamhyung Kim pcnt_width = 7 * ab->nr_events; 273a3f895beSArnaldo Carvalho de Melo 274e9823b21SArnaldo Carvalho de Melo if (annotate_browser__opts.jump_arrows) 2759d1ef56dSArnaldo Carvalho de Melo annotate_browser__draw_current_jump(browser); 276a3f895beSArnaldo Carvalho de Melo 27783b1f2aaSArnaldo Carvalho de Melo ui_browser__set_color(browser, HE_COLORSET_NORMAL); 278c7e7b610SNamhyung Kim __ui_browser__vline(browser, pcnt_width, 0, browser->height - 1); 279a3f895beSArnaldo Carvalho de Melo return ret; 280a3f895beSArnaldo Carvalho de Melo } 281a3f895beSArnaldo Carvalho de Melo 282c7e7b610SNamhyung Kim static int disasm__cmp(struct browser_disasm_line *a, 283c7e7b610SNamhyung Kim struct browser_disasm_line *b, int nr_pcnt) 284c7e7b610SNamhyung Kim { 285c7e7b610SNamhyung Kim int i; 286c7e7b610SNamhyung Kim 287c7e7b610SNamhyung Kim for (i = 0; i < nr_pcnt; i++) { 2880c4a5bceSMartin Liška if (a->samples[i].percent == b->samples[i].percent) 289c7e7b610SNamhyung Kim continue; 2900c4a5bceSMartin Liška return a->samples[i].percent < b->samples[i].percent; 291c7e7b610SNamhyung Kim } 292c7e7b610SNamhyung Kim return 0; 293c7e7b610SNamhyung Kim } 294c7e7b610SNamhyung Kim 295c7e7b610SNamhyung Kim static void disasm_rb_tree__insert(struct rb_root *root, struct browser_disasm_line *bdl, 296c7e7b610SNamhyung Kim int nr_events) 297aca7a94dSNamhyung Kim { 29829ed6e76SArnaldo Carvalho de Melo struct rb_node **p = &root->rb_node; 299aca7a94dSNamhyung Kim struct rb_node *parent = NULL; 300887c0066SArnaldo Carvalho de Melo struct browser_disasm_line *l; 301aca7a94dSNamhyung Kim 302aca7a94dSNamhyung Kim while (*p != NULL) { 303aca7a94dSNamhyung Kim parent = *p; 304887c0066SArnaldo Carvalho de Melo l = rb_entry(parent, struct browser_disasm_line, rb_node); 305c7e7b610SNamhyung Kim 306c7e7b610SNamhyung Kim if (disasm__cmp(bdl, l, nr_events)) 307aca7a94dSNamhyung Kim p = &(*p)->rb_left; 308aca7a94dSNamhyung Kim else 309aca7a94dSNamhyung Kim p = &(*p)->rb_right; 310aca7a94dSNamhyung Kim } 311887c0066SArnaldo Carvalho de Melo rb_link_node(&bdl->rb_node, parent, p); 312887c0066SArnaldo Carvalho de Melo rb_insert_color(&bdl->rb_node, root); 313aca7a94dSNamhyung Kim } 314aca7a94dSNamhyung Kim 31505e8b080SArnaldo Carvalho de Melo static void annotate_browser__set_top(struct annotate_browser *browser, 31629ed6e76SArnaldo Carvalho de Melo struct disasm_line *pos, u32 idx) 317aca7a94dSNamhyung Kim { 318aca7a94dSNamhyung Kim unsigned back; 319aca7a94dSNamhyung Kim 32005e8b080SArnaldo Carvalho de Melo ui_browser__refresh_dimensions(&browser->b); 32105e8b080SArnaldo Carvalho de Melo back = browser->b.height / 2; 32205e8b080SArnaldo Carvalho de Melo browser->b.top_idx = browser->b.index = idx; 323aca7a94dSNamhyung Kim 32405e8b080SArnaldo Carvalho de Melo while (browser->b.top_idx != 0 && back != 0) { 32529ed6e76SArnaldo Carvalho de Melo pos = list_entry(pos->node.prev, struct disasm_line, node); 326aca7a94dSNamhyung Kim 32705e8b080SArnaldo Carvalho de Melo if (disasm_line__filter(&browser->b, &pos->node)) 328aca7a94dSNamhyung Kim continue; 329aca7a94dSNamhyung Kim 33005e8b080SArnaldo Carvalho de Melo --browser->b.top_idx; 331aca7a94dSNamhyung Kim --back; 332aca7a94dSNamhyung Kim } 333aca7a94dSNamhyung Kim 33405e8b080SArnaldo Carvalho de Melo browser->b.top = pos; 33505e8b080SArnaldo Carvalho de Melo browser->b.navkeypressed = true; 336aca7a94dSNamhyung Kim } 337aca7a94dSNamhyung Kim 338aca7a94dSNamhyung Kim static void annotate_browser__set_rb_top(struct annotate_browser *browser, 339aca7a94dSNamhyung Kim struct rb_node *nd) 340aca7a94dSNamhyung Kim { 341887c0066SArnaldo Carvalho de Melo struct browser_disasm_line *bpos; 34229ed6e76SArnaldo Carvalho de Melo struct disasm_line *pos; 343a44b45f2SArnaldo Carvalho de Melo u32 idx; 344aca7a94dSNamhyung Kim 345887c0066SArnaldo Carvalho de Melo bpos = rb_entry(nd, struct browser_disasm_line, rb_node); 346887c0066SArnaldo Carvalho de Melo pos = ((struct disasm_line *)bpos) - 1; 347a44b45f2SArnaldo Carvalho de Melo idx = bpos->idx; 348e9823b21SArnaldo Carvalho de Melo if (annotate_browser__opts.hide_src_code) 349a44b45f2SArnaldo Carvalho de Melo idx = bpos->idx_asm; 350a44b45f2SArnaldo Carvalho de Melo annotate_browser__set_top(browser, pos, idx); 351aca7a94dSNamhyung Kim browser->curr_hot = nd; 352aca7a94dSNamhyung Kim } 353aca7a94dSNamhyung Kim 354aca7a94dSNamhyung Kim static void annotate_browser__calc_percent(struct annotate_browser *browser, 355db8fd07aSNamhyung Kim struct perf_evsel *evsel) 356aca7a94dSNamhyung Kim { 357aca7a94dSNamhyung Kim struct map_symbol *ms = browser->b.priv; 358aca7a94dSNamhyung Kim struct symbol *sym = ms->sym; 359aca7a94dSNamhyung Kim struct annotation *notes = symbol__annotation(sym); 360e64aa75bSNamhyung Kim struct disasm_line *pos, *next; 361e64aa75bSNamhyung Kim s64 len = symbol__size(sym); 362aca7a94dSNamhyung Kim 363aca7a94dSNamhyung Kim browser->entries = RB_ROOT; 364aca7a94dSNamhyung Kim 365aca7a94dSNamhyung Kim pthread_mutex_lock(¬es->lock); 366aca7a94dSNamhyung Kim 367aca7a94dSNamhyung Kim list_for_each_entry(pos, ¬es->src->source, node) { 368887c0066SArnaldo Carvalho de Melo struct browser_disasm_line *bpos = disasm_line__browser(pos); 369e64aa75bSNamhyung Kim const char *path = NULL; 370c7e7b610SNamhyung Kim double max_percent = 0.0; 371c7e7b610SNamhyung Kim int i; 372e64aa75bSNamhyung Kim 373e64aa75bSNamhyung Kim if (pos->offset == -1) { 374e64aa75bSNamhyung Kim RB_CLEAR_NODE(&bpos->rb_node); 375e64aa75bSNamhyung Kim continue; 376e64aa75bSNamhyung Kim } 377e64aa75bSNamhyung Kim 378e64aa75bSNamhyung Kim next = disasm__get_next_ip_line(¬es->src->source, pos); 379c7e7b610SNamhyung Kim 380c7e7b610SNamhyung Kim for (i = 0; i < browser->nr_events; i++) { 3810c4a5bceSMartin Liška u64 nr_samples; 3820c4a5bceSMartin Liška 3830c4a5bceSMartin Liška bpos->samples[i].percent = disasm__calc_percent(notes, 384c7e7b610SNamhyung Kim evsel->idx + i, 385c7e7b610SNamhyung Kim pos->offset, 386c7e7b610SNamhyung Kim next ? next->offset : len, 3870c4a5bceSMartin Liška &path, &nr_samples); 3880c4a5bceSMartin Liška bpos->samples[i].nr = nr_samples; 389e64aa75bSNamhyung Kim 3900c4a5bceSMartin Liška if (max_percent < bpos->samples[i].percent) 3910c4a5bceSMartin Liška max_percent = bpos->samples[i].percent; 392c7e7b610SNamhyung Kim } 393c7e7b610SNamhyung Kim 394*30e863bbSAndi Kleen if (max_percent < 0.01 && pos->ipc == 0) { 395887c0066SArnaldo Carvalho de Melo RB_CLEAR_NODE(&bpos->rb_node); 396aca7a94dSNamhyung Kim continue; 397aca7a94dSNamhyung Kim } 398c7e7b610SNamhyung Kim disasm_rb_tree__insert(&browser->entries, bpos, 399c7e7b610SNamhyung Kim browser->nr_events); 400aca7a94dSNamhyung Kim } 401aca7a94dSNamhyung Kim pthread_mutex_unlock(¬es->lock); 402aca7a94dSNamhyung Kim 403aca7a94dSNamhyung Kim browser->curr_hot = rb_last(&browser->entries); 404aca7a94dSNamhyung Kim } 405aca7a94dSNamhyung Kim 406aca7a94dSNamhyung Kim static bool annotate_browser__toggle_source(struct annotate_browser *browser) 407aca7a94dSNamhyung Kim { 40829ed6e76SArnaldo Carvalho de Melo struct disasm_line *dl; 409887c0066SArnaldo Carvalho de Melo struct browser_disasm_line *bdl; 410aca7a94dSNamhyung Kim off_t offset = browser->b.index - browser->b.top_idx; 411aca7a94dSNamhyung Kim 412aca7a94dSNamhyung Kim browser->b.seek(&browser->b, offset, SEEK_CUR); 41329ed6e76SArnaldo Carvalho de Melo dl = list_entry(browser->b.top, struct disasm_line, node); 414887c0066SArnaldo Carvalho de Melo bdl = disasm_line__browser(dl); 415aca7a94dSNamhyung Kim 416e9823b21SArnaldo Carvalho de Melo if (annotate_browser__opts.hide_src_code) { 417887c0066SArnaldo Carvalho de Melo if (bdl->idx_asm < offset) 418887c0066SArnaldo Carvalho de Melo offset = bdl->idx; 419aca7a94dSNamhyung Kim 420aca7a94dSNamhyung Kim browser->b.nr_entries = browser->nr_entries; 421e9823b21SArnaldo Carvalho de Melo annotate_browser__opts.hide_src_code = false; 422aca7a94dSNamhyung Kim browser->b.seek(&browser->b, -offset, SEEK_CUR); 423887c0066SArnaldo Carvalho de Melo browser->b.top_idx = bdl->idx - offset; 424887c0066SArnaldo Carvalho de Melo browser->b.index = bdl->idx; 425aca7a94dSNamhyung Kim } else { 426887c0066SArnaldo Carvalho de Melo if (bdl->idx_asm < 0) { 427aca7a94dSNamhyung Kim ui_helpline__puts("Only available for assembly lines."); 428aca7a94dSNamhyung Kim browser->b.seek(&browser->b, -offset, SEEK_CUR); 429aca7a94dSNamhyung Kim return false; 430aca7a94dSNamhyung Kim } 431aca7a94dSNamhyung Kim 432887c0066SArnaldo Carvalho de Melo if (bdl->idx_asm < offset) 433887c0066SArnaldo Carvalho de Melo offset = bdl->idx_asm; 434aca7a94dSNamhyung Kim 435aca7a94dSNamhyung Kim browser->b.nr_entries = browser->nr_asm_entries; 436e9823b21SArnaldo Carvalho de Melo annotate_browser__opts.hide_src_code = true; 437aca7a94dSNamhyung Kim browser->b.seek(&browser->b, -offset, SEEK_CUR); 438887c0066SArnaldo Carvalho de Melo browser->b.top_idx = bdl->idx_asm - offset; 439887c0066SArnaldo Carvalho de Melo browser->b.index = bdl->idx_asm; 440aca7a94dSNamhyung Kim } 441aca7a94dSNamhyung Kim 442aca7a94dSNamhyung Kim return true; 443aca7a94dSNamhyung Kim } 444aca7a94dSNamhyung Kim 445e9823b21SArnaldo Carvalho de Melo static void annotate_browser__init_asm_mode(struct annotate_browser *browser) 446e9823b21SArnaldo Carvalho de Melo { 447e9823b21SArnaldo Carvalho de Melo ui_browser__reset_index(&browser->b); 448e9823b21SArnaldo Carvalho de Melo browser->b.nr_entries = browser->nr_asm_entries; 449e9823b21SArnaldo Carvalho de Melo } 450e9823b21SArnaldo Carvalho de Melo 45134f77abcSAdrian Hunter #define SYM_TITLE_MAX_SIZE (PATH_MAX + 64) 45234f77abcSAdrian Hunter 45334f77abcSAdrian Hunter static int sym_title(struct symbol *sym, struct map *map, char *title, 45434f77abcSAdrian Hunter size_t sz) 45534f77abcSAdrian Hunter { 45634f77abcSAdrian Hunter return snprintf(title, sz, "%s %s", sym->name, map->dso->long_name); 45734f77abcSAdrian Hunter } 45834f77abcSAdrian Hunter 459db8fd07aSNamhyung Kim static bool annotate_browser__callq(struct annotate_browser *browser, 460db8fd07aSNamhyung Kim struct perf_evsel *evsel, 4619783adf7SNamhyung Kim struct hist_browser_timer *hbt) 462aca7a94dSNamhyung Kim { 463aca7a94dSNamhyung Kim struct map_symbol *ms = browser->b.priv; 464657bcaf5SArnaldo Carvalho de Melo struct disasm_line *dl = browser->selection; 465aca7a94dSNamhyung Kim struct annotation *notes; 4661179e11bSAdrian Hunter struct addr_map_symbol target = { 4671179e11bSAdrian Hunter .map = ms->map, 4681d5077bdSAdrian Hunter .addr = map__objdump_2mem(ms->map, dl->ops.target.addr), 4691179e11bSAdrian Hunter }; 47034f77abcSAdrian Hunter char title[SYM_TITLE_MAX_SIZE]; 471aca7a94dSNamhyung Kim 472d86b0597SArnaldo Carvalho de Melo if (!ins__is_call(dl->ins)) 473aca7a94dSNamhyung Kim return false; 474aca7a94dSNamhyung Kim 4751d5077bdSAdrian Hunter if (map_groups__find_ams(&target, NULL) || 4761d5077bdSAdrian Hunter map__rip_2objdump(target.map, target.map->map_ip(target.map, 4771d5077bdSAdrian Hunter target.addr)) != 4781d5077bdSAdrian Hunter dl->ops.target.addr) { 479aca7a94dSNamhyung Kim ui_helpline__puts("The called function was not found."); 480aca7a94dSNamhyung Kim return true; 481aca7a94dSNamhyung Kim } 482aca7a94dSNamhyung Kim 4831179e11bSAdrian Hunter notes = symbol__annotation(target.sym); 484aca7a94dSNamhyung Kim pthread_mutex_lock(¬es->lock); 485aca7a94dSNamhyung Kim 4861179e11bSAdrian Hunter if (notes->src == NULL && symbol__alloc_hist(target.sym) < 0) { 487aca7a94dSNamhyung Kim pthread_mutex_unlock(¬es->lock); 488aca7a94dSNamhyung Kim ui__warning("Not enough memory for annotating '%s' symbol!\n", 4891179e11bSAdrian Hunter target.sym->name); 490aca7a94dSNamhyung Kim return true; 491aca7a94dSNamhyung Kim } 492aca7a94dSNamhyung Kim 493aca7a94dSNamhyung Kim pthread_mutex_unlock(¬es->lock); 4941179e11bSAdrian Hunter symbol__tui_annotate(target.sym, target.map, evsel, hbt); 4951179e11bSAdrian Hunter sym_title(ms->sym, ms->map, title, sizeof(title)); 49634f77abcSAdrian Hunter ui_browser__show_title(&browser->b, title); 497aca7a94dSNamhyung Kim return true; 498aca7a94dSNamhyung Kim } 499aca7a94dSNamhyung Kim 50029ed6e76SArnaldo Carvalho de Melo static 50129ed6e76SArnaldo Carvalho de Melo struct disasm_line *annotate_browser__find_offset(struct annotate_browser *browser, 502aca7a94dSNamhyung Kim s64 offset, s64 *idx) 503aca7a94dSNamhyung Kim { 504aca7a94dSNamhyung Kim struct map_symbol *ms = browser->b.priv; 505aca7a94dSNamhyung Kim struct symbol *sym = ms->sym; 506aca7a94dSNamhyung Kim struct annotation *notes = symbol__annotation(sym); 50729ed6e76SArnaldo Carvalho de Melo struct disasm_line *pos; 508aca7a94dSNamhyung Kim 509aca7a94dSNamhyung Kim *idx = 0; 510aca7a94dSNamhyung Kim list_for_each_entry(pos, ¬es->src->source, node) { 511aca7a94dSNamhyung Kim if (pos->offset == offset) 512aca7a94dSNamhyung Kim return pos; 51329ed6e76SArnaldo Carvalho de Melo if (!disasm_line__filter(&browser->b, &pos->node)) 514aca7a94dSNamhyung Kim ++*idx; 515aca7a94dSNamhyung Kim } 516aca7a94dSNamhyung Kim 517aca7a94dSNamhyung Kim return NULL; 518aca7a94dSNamhyung Kim } 519aca7a94dSNamhyung Kim 520aca7a94dSNamhyung Kim static bool annotate_browser__jump(struct annotate_browser *browser) 521aca7a94dSNamhyung Kim { 522657bcaf5SArnaldo Carvalho de Melo struct disasm_line *dl = browser->selection; 5234f9d0325SArnaldo Carvalho de Melo s64 idx; 524aca7a94dSNamhyung Kim 525d86b0597SArnaldo Carvalho de Melo if (!ins__is_jump(dl->ins)) 526aca7a94dSNamhyung Kim return false; 527aca7a94dSNamhyung Kim 52844d1a3edSArnaldo Carvalho de Melo dl = annotate_browser__find_offset(browser, dl->ops.target.offset, &idx); 52929ed6e76SArnaldo Carvalho de Melo if (dl == NULL) { 530e6f65388SIngo Molnar ui_helpline__puts("Invalid jump offset"); 531aca7a94dSNamhyung Kim return true; 532aca7a94dSNamhyung Kim } 533aca7a94dSNamhyung Kim 53429ed6e76SArnaldo Carvalho de Melo annotate_browser__set_top(browser, dl, idx); 535aca7a94dSNamhyung Kim 536aca7a94dSNamhyung Kim return true; 537aca7a94dSNamhyung Kim } 538aca7a94dSNamhyung Kim 53929ed6e76SArnaldo Carvalho de Melo static 54029ed6e76SArnaldo Carvalho de Melo struct disasm_line *annotate_browser__find_string(struct annotate_browser *browser, 541aca7a94dSNamhyung Kim char *s, s64 *idx) 542aca7a94dSNamhyung Kim { 543aca7a94dSNamhyung Kim struct map_symbol *ms = browser->b.priv; 544aca7a94dSNamhyung Kim struct symbol *sym = ms->sym; 545aca7a94dSNamhyung Kim struct annotation *notes = symbol__annotation(sym); 54629ed6e76SArnaldo Carvalho de Melo struct disasm_line *pos = browser->selection; 547aca7a94dSNamhyung Kim 548aca7a94dSNamhyung Kim *idx = browser->b.index; 549aca7a94dSNamhyung Kim list_for_each_entry_continue(pos, ¬es->src->source, node) { 55029ed6e76SArnaldo Carvalho de Melo if (disasm_line__filter(&browser->b, &pos->node)) 551aca7a94dSNamhyung Kim continue; 552aca7a94dSNamhyung Kim 553aca7a94dSNamhyung Kim ++*idx; 554aca7a94dSNamhyung Kim 555aca7a94dSNamhyung Kim if (pos->line && strstr(pos->line, s) != NULL) 556aca7a94dSNamhyung Kim return pos; 557aca7a94dSNamhyung Kim } 558aca7a94dSNamhyung Kim 559aca7a94dSNamhyung Kim return NULL; 560aca7a94dSNamhyung Kim } 561aca7a94dSNamhyung Kim 562aca7a94dSNamhyung Kim static bool __annotate_browser__search(struct annotate_browser *browser) 563aca7a94dSNamhyung Kim { 56429ed6e76SArnaldo Carvalho de Melo struct disasm_line *dl; 565aca7a94dSNamhyung Kim s64 idx; 566aca7a94dSNamhyung Kim 56729ed6e76SArnaldo Carvalho de Melo dl = annotate_browser__find_string(browser, browser->search_bf, &idx); 56829ed6e76SArnaldo Carvalho de Melo if (dl == NULL) { 569aca7a94dSNamhyung Kim ui_helpline__puts("String not found!"); 570aca7a94dSNamhyung Kim return false; 571aca7a94dSNamhyung Kim } 572aca7a94dSNamhyung Kim 57329ed6e76SArnaldo Carvalho de Melo annotate_browser__set_top(browser, dl, idx); 574aca7a94dSNamhyung Kim browser->searching_backwards = false; 575aca7a94dSNamhyung Kim return true; 576aca7a94dSNamhyung Kim } 577aca7a94dSNamhyung Kim 57829ed6e76SArnaldo Carvalho de Melo static 57929ed6e76SArnaldo Carvalho de Melo struct disasm_line *annotate_browser__find_string_reverse(struct annotate_browser *browser, 580aca7a94dSNamhyung Kim char *s, s64 *idx) 581aca7a94dSNamhyung Kim { 582aca7a94dSNamhyung Kim struct map_symbol *ms = browser->b.priv; 583aca7a94dSNamhyung Kim struct symbol *sym = ms->sym; 584aca7a94dSNamhyung Kim struct annotation *notes = symbol__annotation(sym); 58529ed6e76SArnaldo Carvalho de Melo struct disasm_line *pos = browser->selection; 586aca7a94dSNamhyung Kim 587aca7a94dSNamhyung Kim *idx = browser->b.index; 588aca7a94dSNamhyung Kim list_for_each_entry_continue_reverse(pos, ¬es->src->source, node) { 58929ed6e76SArnaldo Carvalho de Melo if (disasm_line__filter(&browser->b, &pos->node)) 590aca7a94dSNamhyung Kim continue; 591aca7a94dSNamhyung Kim 592aca7a94dSNamhyung Kim --*idx; 593aca7a94dSNamhyung Kim 594aca7a94dSNamhyung Kim if (pos->line && strstr(pos->line, s) != NULL) 595aca7a94dSNamhyung Kim return pos; 596aca7a94dSNamhyung Kim } 597aca7a94dSNamhyung Kim 598aca7a94dSNamhyung Kim return NULL; 599aca7a94dSNamhyung Kim } 600aca7a94dSNamhyung Kim 601aca7a94dSNamhyung Kim static bool __annotate_browser__search_reverse(struct annotate_browser *browser) 602aca7a94dSNamhyung Kim { 60329ed6e76SArnaldo Carvalho de Melo struct disasm_line *dl; 604aca7a94dSNamhyung Kim s64 idx; 605aca7a94dSNamhyung Kim 60629ed6e76SArnaldo Carvalho de Melo dl = annotate_browser__find_string_reverse(browser, browser->search_bf, &idx); 60729ed6e76SArnaldo Carvalho de Melo if (dl == NULL) { 608aca7a94dSNamhyung Kim ui_helpline__puts("String not found!"); 609aca7a94dSNamhyung Kim return false; 610aca7a94dSNamhyung Kim } 611aca7a94dSNamhyung Kim 61229ed6e76SArnaldo Carvalho de Melo annotate_browser__set_top(browser, dl, idx); 613aca7a94dSNamhyung Kim browser->searching_backwards = true; 614aca7a94dSNamhyung Kim return true; 615aca7a94dSNamhyung Kim } 616aca7a94dSNamhyung Kim 617aca7a94dSNamhyung Kim static bool annotate_browser__search_window(struct annotate_browser *browser, 618aca7a94dSNamhyung Kim int delay_secs) 619aca7a94dSNamhyung Kim { 620aca7a94dSNamhyung Kim if (ui_browser__input_window("Search", "String: ", browser->search_bf, 621aca7a94dSNamhyung Kim "ENTER: OK, ESC: Cancel", 622aca7a94dSNamhyung Kim delay_secs * 2) != K_ENTER || 623aca7a94dSNamhyung Kim !*browser->search_bf) 624aca7a94dSNamhyung Kim return false; 625aca7a94dSNamhyung Kim 626aca7a94dSNamhyung Kim return true; 627aca7a94dSNamhyung Kim } 628aca7a94dSNamhyung Kim 629aca7a94dSNamhyung Kim static bool annotate_browser__search(struct annotate_browser *browser, int delay_secs) 630aca7a94dSNamhyung Kim { 631aca7a94dSNamhyung Kim if (annotate_browser__search_window(browser, delay_secs)) 632aca7a94dSNamhyung Kim return __annotate_browser__search(browser); 633aca7a94dSNamhyung Kim 634aca7a94dSNamhyung Kim return false; 635aca7a94dSNamhyung Kim } 636aca7a94dSNamhyung Kim 637aca7a94dSNamhyung Kim static bool annotate_browser__continue_search(struct annotate_browser *browser, 638aca7a94dSNamhyung Kim int delay_secs) 639aca7a94dSNamhyung Kim { 640aca7a94dSNamhyung Kim if (!*browser->search_bf) 641aca7a94dSNamhyung Kim return annotate_browser__search(browser, delay_secs); 642aca7a94dSNamhyung Kim 643aca7a94dSNamhyung Kim return __annotate_browser__search(browser); 644aca7a94dSNamhyung Kim } 645aca7a94dSNamhyung Kim 646aca7a94dSNamhyung Kim static bool annotate_browser__search_reverse(struct annotate_browser *browser, 647aca7a94dSNamhyung Kim int delay_secs) 648aca7a94dSNamhyung Kim { 649aca7a94dSNamhyung Kim if (annotate_browser__search_window(browser, delay_secs)) 650aca7a94dSNamhyung Kim return __annotate_browser__search_reverse(browser); 651aca7a94dSNamhyung Kim 652aca7a94dSNamhyung Kim return false; 653aca7a94dSNamhyung Kim } 654aca7a94dSNamhyung Kim 655aca7a94dSNamhyung Kim static 656aca7a94dSNamhyung Kim bool annotate_browser__continue_search_reverse(struct annotate_browser *browser, 657aca7a94dSNamhyung Kim int delay_secs) 658aca7a94dSNamhyung Kim { 659aca7a94dSNamhyung Kim if (!*browser->search_bf) 660aca7a94dSNamhyung Kim return annotate_browser__search_reverse(browser, delay_secs); 661aca7a94dSNamhyung Kim 662aca7a94dSNamhyung Kim return __annotate_browser__search_reverse(browser); 663aca7a94dSNamhyung Kim } 664aca7a94dSNamhyung Kim 665e9823b21SArnaldo Carvalho de Melo static void annotate_browser__update_addr_width(struct annotate_browser *browser) 666e9823b21SArnaldo Carvalho de Melo { 667e9823b21SArnaldo Carvalho de Melo if (annotate_browser__opts.use_offset) 668e9823b21SArnaldo Carvalho de Melo browser->target_width = browser->min_addr_width; 669e9823b21SArnaldo Carvalho de Melo else 670e9823b21SArnaldo Carvalho de Melo browser->target_width = browser->max_addr_width; 671e9823b21SArnaldo Carvalho de Melo 672e9823b21SArnaldo Carvalho de Melo browser->addr_width = browser->target_width; 673e9823b21SArnaldo Carvalho de Melo 674e9823b21SArnaldo Carvalho de Melo if (annotate_browser__opts.show_nr_jumps) 675e9823b21SArnaldo Carvalho de Melo browser->addr_width += browser->jumps_width + 1; 676e9823b21SArnaldo Carvalho de Melo } 677e9823b21SArnaldo Carvalho de Melo 678db8fd07aSNamhyung Kim static int annotate_browser__run(struct annotate_browser *browser, 679db8fd07aSNamhyung Kim struct perf_evsel *evsel, 6809783adf7SNamhyung Kim struct hist_browser_timer *hbt) 681aca7a94dSNamhyung Kim { 682aca7a94dSNamhyung Kim struct rb_node *nd = NULL; 68305e8b080SArnaldo Carvalho de Melo struct map_symbol *ms = browser->b.priv; 684aca7a94dSNamhyung Kim struct symbol *sym = ms->sym; 68554e7a4e8SArnaldo Carvalho de Melo const char *help = "Press 'h' for help on key bindings"; 6869783adf7SNamhyung Kim int delay_secs = hbt ? hbt->refresh : 0; 687aca7a94dSNamhyung Kim int key; 68834f77abcSAdrian Hunter char title[SYM_TITLE_MAX_SIZE]; 689aca7a94dSNamhyung Kim 69034f77abcSAdrian Hunter sym_title(sym, ms->map, title, sizeof(title)); 69134f77abcSAdrian Hunter if (ui_browser__show(&browser->b, title, help) < 0) 692aca7a94dSNamhyung Kim return -1; 693aca7a94dSNamhyung Kim 694db8fd07aSNamhyung Kim annotate_browser__calc_percent(browser, evsel); 695aca7a94dSNamhyung Kim 69605e8b080SArnaldo Carvalho de Melo if (browser->curr_hot) { 69705e8b080SArnaldo Carvalho de Melo annotate_browser__set_rb_top(browser, browser->curr_hot); 69805e8b080SArnaldo Carvalho de Melo browser->b.navkeypressed = false; 699aca7a94dSNamhyung Kim } 700aca7a94dSNamhyung Kim 70105e8b080SArnaldo Carvalho de Melo nd = browser->curr_hot; 702aca7a94dSNamhyung Kim 703aca7a94dSNamhyung Kim while (1) { 70405e8b080SArnaldo Carvalho de Melo key = ui_browser__run(&browser->b, delay_secs); 705aca7a94dSNamhyung Kim 706aca7a94dSNamhyung Kim if (delay_secs != 0) { 707db8fd07aSNamhyung Kim annotate_browser__calc_percent(browser, evsel); 708aca7a94dSNamhyung Kim /* 709aca7a94dSNamhyung Kim * Current line focus got out of the list of most active 710aca7a94dSNamhyung Kim * lines, NULL it so that if TAB|UNTAB is pressed, we 711aca7a94dSNamhyung Kim * move to curr_hot (current hottest line). 712aca7a94dSNamhyung Kim */ 713aca7a94dSNamhyung Kim if (nd != NULL && RB_EMPTY_NODE(nd)) 714aca7a94dSNamhyung Kim nd = NULL; 715aca7a94dSNamhyung Kim } 716aca7a94dSNamhyung Kim 717aca7a94dSNamhyung Kim switch (key) { 718aca7a94dSNamhyung Kim case K_TIMER: 7199783adf7SNamhyung Kim if (hbt) 7209783adf7SNamhyung Kim hbt->timer(hbt->arg); 721aca7a94dSNamhyung Kim 722aca7a94dSNamhyung Kim if (delay_secs != 0) 723db8fd07aSNamhyung Kim symbol__annotate_decay_histogram(sym, evsel->idx); 724aca7a94dSNamhyung Kim continue; 725aca7a94dSNamhyung Kim case K_TAB: 726aca7a94dSNamhyung Kim if (nd != NULL) { 727aca7a94dSNamhyung Kim nd = rb_prev(nd); 728aca7a94dSNamhyung Kim if (nd == NULL) 72905e8b080SArnaldo Carvalho de Melo nd = rb_last(&browser->entries); 730aca7a94dSNamhyung Kim } else 73105e8b080SArnaldo Carvalho de Melo nd = browser->curr_hot; 732aca7a94dSNamhyung Kim break; 733aca7a94dSNamhyung Kim case K_UNTAB: 734aca7a94dSNamhyung Kim if (nd != NULL) 735aca7a94dSNamhyung Kim nd = rb_next(nd); 736aca7a94dSNamhyung Kim if (nd == NULL) 73705e8b080SArnaldo Carvalho de Melo nd = rb_first(&browser->entries); 738aca7a94dSNamhyung Kim else 73905e8b080SArnaldo Carvalho de Melo nd = browser->curr_hot; 740aca7a94dSNamhyung Kim break; 74154e7a4e8SArnaldo Carvalho de Melo case K_F1: 742aca7a94dSNamhyung Kim case 'h': 74305e8b080SArnaldo Carvalho de Melo ui_browser__help_window(&browser->b, 74454e7a4e8SArnaldo Carvalho de Melo "UP/DOWN/PGUP\n" 74554e7a4e8SArnaldo Carvalho de Melo "PGDN/SPACE Navigate\n" 74654e7a4e8SArnaldo Carvalho de Melo "q/ESC/CTRL+C Exit\n\n" 74754e7a4e8SArnaldo Carvalho de Melo "-> Go to target\n" 74854e7a4e8SArnaldo Carvalho de Melo "<- Exit\n" 749107baecaSArnaldo Carvalho de Melo "H Cycle thru hottest instructions\n" 75054e7a4e8SArnaldo Carvalho de Melo "j Toggle showing jump to target arrows\n" 75154e7a4e8SArnaldo Carvalho de Melo "J Toggle showing number of jump sources on targets\n" 75254e7a4e8SArnaldo Carvalho de Melo "n Search next string\n" 75354e7a4e8SArnaldo Carvalho de Melo "o Toggle disassembler output/simplified view\n" 75454e7a4e8SArnaldo Carvalho de Melo "s Toggle source code view\n" 7550c4a5bceSMartin Liška "t Toggle total period view\n" 75654e7a4e8SArnaldo Carvalho de Melo "/ Search string\n" 757e592488cSAndi Kleen "k Toggle line numbers\n" 75879ee47faSFeng Tang "r Run available scripts\n" 759fcd9fef9SArnaldo Carvalho de Melo "? Search string backwards\n"); 76054e7a4e8SArnaldo Carvalho de Melo continue; 76179ee47faSFeng Tang case 'r': 76279ee47faSFeng Tang { 76379ee47faSFeng Tang script_browse(NULL); 76479ee47faSFeng Tang continue; 76579ee47faSFeng Tang } 766e592488cSAndi Kleen case 'k': 767e592488cSAndi Kleen annotate_browser__opts.show_linenr = 768e592488cSAndi Kleen !annotate_browser__opts.show_linenr; 769e592488cSAndi Kleen break; 77054e7a4e8SArnaldo Carvalho de Melo case 'H': 77105e8b080SArnaldo Carvalho de Melo nd = browser->curr_hot; 772aca7a94dSNamhyung Kim break; 773aca7a94dSNamhyung Kim case 's': 77405e8b080SArnaldo Carvalho de Melo if (annotate_browser__toggle_source(browser)) 775aca7a94dSNamhyung Kim ui_helpline__puts(help); 776aca7a94dSNamhyung Kim continue; 777aca7a94dSNamhyung Kim case 'o': 778e9823b21SArnaldo Carvalho de Melo annotate_browser__opts.use_offset = !annotate_browser__opts.use_offset; 77905e8b080SArnaldo Carvalho de Melo annotate_browser__update_addr_width(browser); 780aca7a94dSNamhyung Kim continue; 7819d1ef56dSArnaldo Carvalho de Melo case 'j': 782e9823b21SArnaldo Carvalho de Melo annotate_browser__opts.jump_arrows = !annotate_browser__opts.jump_arrows; 7839d1ef56dSArnaldo Carvalho de Melo continue; 7842402e4a9SArnaldo Carvalho de Melo case 'J': 785e9823b21SArnaldo Carvalho de Melo annotate_browser__opts.show_nr_jumps = !annotate_browser__opts.show_nr_jumps; 78605e8b080SArnaldo Carvalho de Melo annotate_browser__update_addr_width(browser); 787e9823b21SArnaldo Carvalho de Melo continue; 788aca7a94dSNamhyung Kim case '/': 78905e8b080SArnaldo Carvalho de Melo if (annotate_browser__search(browser, delay_secs)) { 790aca7a94dSNamhyung Kim show_help: 791aca7a94dSNamhyung Kim ui_helpline__puts(help); 792aca7a94dSNamhyung Kim } 793aca7a94dSNamhyung Kim continue; 794aca7a94dSNamhyung Kim case 'n': 79505e8b080SArnaldo Carvalho de Melo if (browser->searching_backwards ? 79605e8b080SArnaldo Carvalho de Melo annotate_browser__continue_search_reverse(browser, delay_secs) : 79705e8b080SArnaldo Carvalho de Melo annotate_browser__continue_search(browser, delay_secs)) 798aca7a94dSNamhyung Kim goto show_help; 799aca7a94dSNamhyung Kim continue; 800aca7a94dSNamhyung Kim case '?': 80105e8b080SArnaldo Carvalho de Melo if (annotate_browser__search_reverse(browser, delay_secs)) 802aca7a94dSNamhyung Kim goto show_help; 803aca7a94dSNamhyung Kim continue; 804e9823b21SArnaldo Carvalho de Melo case 'D': { 805e9823b21SArnaldo Carvalho de Melo static int seq; 806e9823b21SArnaldo Carvalho de Melo ui_helpline__pop(); 807e9823b21SArnaldo Carvalho de Melo ui_helpline__fpush("%d: nr_ent=%d, height=%d, idx=%d, top_idx=%d, nr_asm_entries=%d", 80805e8b080SArnaldo Carvalho de Melo seq++, browser->b.nr_entries, 80905e8b080SArnaldo Carvalho de Melo browser->b.height, 81005e8b080SArnaldo Carvalho de Melo browser->b.index, 81105e8b080SArnaldo Carvalho de Melo browser->b.top_idx, 81205e8b080SArnaldo Carvalho de Melo browser->nr_asm_entries); 813e9823b21SArnaldo Carvalho de Melo } 814e9823b21SArnaldo Carvalho de Melo continue; 815aca7a94dSNamhyung Kim case K_ENTER: 816aca7a94dSNamhyung Kim case K_RIGHT: 81705e8b080SArnaldo Carvalho de Melo if (browser->selection == NULL) 818aca7a94dSNamhyung Kim ui_helpline__puts("Huh? No selection. Report to linux-kernel@vger.kernel.org"); 81905e8b080SArnaldo Carvalho de Melo else if (browser->selection->offset == -1) 820aca7a94dSNamhyung Kim ui_helpline__puts("Actions are only available for assembly lines."); 82105e8b080SArnaldo Carvalho de Melo else if (!browser->selection->ins) { 82205e8b080SArnaldo Carvalho de Melo if (strcmp(browser->selection->name, "retq")) 823c4cceae3SArnaldo Carvalho de Melo goto show_sup_ins; 824c4cceae3SArnaldo Carvalho de Melo goto out; 82505e8b080SArnaldo Carvalho de Melo } else if (!(annotate_browser__jump(browser) || 826db8fd07aSNamhyung Kim annotate_browser__callq(browser, evsel, hbt))) { 827c4cceae3SArnaldo Carvalho de Melo show_sup_ins: 828c4cceae3SArnaldo Carvalho de Melo ui_helpline__puts("Actions are only available for 'callq', 'retq' & jump instructions."); 829c4cceae3SArnaldo Carvalho de Melo } 830aca7a94dSNamhyung Kim continue; 8310c4a5bceSMartin Liška case 't': 8320c4a5bceSMartin Liška annotate_browser__opts.show_total_period = 8330c4a5bceSMartin Liška !annotate_browser__opts.show_total_period; 8340c4a5bceSMartin Liška annotate_browser__update_addr_width(browser); 8350c4a5bceSMartin Liška continue; 836aca7a94dSNamhyung Kim case K_LEFT: 837aca7a94dSNamhyung Kim case K_ESC: 838aca7a94dSNamhyung Kim case 'q': 839aca7a94dSNamhyung Kim case CTRL('c'): 840aca7a94dSNamhyung Kim goto out; 841aca7a94dSNamhyung Kim default: 842aca7a94dSNamhyung Kim continue; 843aca7a94dSNamhyung Kim } 844aca7a94dSNamhyung Kim 845aca7a94dSNamhyung Kim if (nd != NULL) 84605e8b080SArnaldo Carvalho de Melo annotate_browser__set_rb_top(browser, nd); 847aca7a94dSNamhyung Kim } 848aca7a94dSNamhyung Kim out: 84905e8b080SArnaldo Carvalho de Melo ui_browser__hide(&browser->b); 850aca7a94dSNamhyung Kim return key; 851aca7a94dSNamhyung Kim } 852aca7a94dSNamhyung Kim 853d5dbc518SArnaldo Carvalho de Melo int map_symbol__tui_annotate(struct map_symbol *ms, struct perf_evsel *evsel, 854d5dbc518SArnaldo Carvalho de Melo struct hist_browser_timer *hbt) 855d5dbc518SArnaldo Carvalho de Melo { 8560c4a5bceSMartin Liška /* Set default value for show_total_period. */ 8570c4a5bceSMartin Liška annotate_browser__opts.show_total_period = 8580c4a5bceSMartin Liška symbol_conf.show_total_period; 8590c4a5bceSMartin Liška 860d5dbc518SArnaldo Carvalho de Melo return symbol__tui_annotate(ms->sym, ms->map, evsel, hbt); 861d5dbc518SArnaldo Carvalho de Melo } 862d5dbc518SArnaldo Carvalho de Melo 863db8fd07aSNamhyung Kim int hist_entry__tui_annotate(struct hist_entry *he, struct perf_evsel *evsel, 8649783adf7SNamhyung Kim struct hist_browser_timer *hbt) 865aca7a94dSNamhyung Kim { 866ed426915SNamhyung Kim /* reset abort key so that it can get Ctrl-C as a key */ 867ed426915SNamhyung Kim SLang_reset_tty(); 868ed426915SNamhyung Kim SLang_init_tty(0, 0, 0); 869ed426915SNamhyung Kim 870d5dbc518SArnaldo Carvalho de Melo return map_symbol__tui_annotate(&he->ms, evsel, hbt); 871aca7a94dSNamhyung Kim } 872aca7a94dSNamhyung Kim 873*30e863bbSAndi Kleen 874*30e863bbSAndi Kleen static unsigned count_insn(struct annotate_browser *browser, u64 start, u64 end) 875*30e863bbSAndi Kleen { 876*30e863bbSAndi Kleen unsigned n_insn = 0; 877*30e863bbSAndi Kleen u64 offset; 878*30e863bbSAndi Kleen 879*30e863bbSAndi Kleen for (offset = start; offset <= end; offset++) { 880*30e863bbSAndi Kleen if (browser->offsets[offset]) 881*30e863bbSAndi Kleen n_insn++; 882*30e863bbSAndi Kleen } 883*30e863bbSAndi Kleen return n_insn; 884*30e863bbSAndi Kleen } 885*30e863bbSAndi Kleen 886*30e863bbSAndi Kleen static void count_and_fill(struct annotate_browser *browser, u64 start, u64 end, 887*30e863bbSAndi Kleen struct cyc_hist *ch) 888*30e863bbSAndi Kleen { 889*30e863bbSAndi Kleen unsigned n_insn; 890*30e863bbSAndi Kleen u64 offset; 891*30e863bbSAndi Kleen 892*30e863bbSAndi Kleen n_insn = count_insn(browser, start, end); 893*30e863bbSAndi Kleen if (n_insn && ch->num && ch->cycles) { 894*30e863bbSAndi Kleen float ipc = n_insn / ((double)ch->cycles / (double)ch->num); 895*30e863bbSAndi Kleen 896*30e863bbSAndi Kleen /* Hide data when there are too many overlaps. */ 897*30e863bbSAndi Kleen if (ch->reset >= 0x7fff || ch->reset >= ch->num / 2) 898*30e863bbSAndi Kleen return; 899*30e863bbSAndi Kleen 900*30e863bbSAndi Kleen for (offset = start; offset <= end; offset++) { 901*30e863bbSAndi Kleen struct disasm_line *dl = browser->offsets[offset]; 902*30e863bbSAndi Kleen 903*30e863bbSAndi Kleen if (dl) 904*30e863bbSAndi Kleen dl->ipc = ipc; 905*30e863bbSAndi Kleen } 906*30e863bbSAndi Kleen } 907*30e863bbSAndi Kleen } 908*30e863bbSAndi Kleen 909*30e863bbSAndi Kleen /* 910*30e863bbSAndi Kleen * This should probably be in util/annotate.c to share with the tty 911*30e863bbSAndi Kleen * annotate, but right now we need the per byte offsets arrays, 912*30e863bbSAndi Kleen * which are only here. 913*30e863bbSAndi Kleen */ 914*30e863bbSAndi Kleen static void annotate__compute_ipc(struct annotate_browser *browser, size_t size, 915*30e863bbSAndi Kleen struct symbol *sym) 916*30e863bbSAndi Kleen { 917*30e863bbSAndi Kleen u64 offset; 918*30e863bbSAndi Kleen struct annotation *notes = symbol__annotation(sym); 919*30e863bbSAndi Kleen 920*30e863bbSAndi Kleen if (!notes->src || !notes->src->cycles_hist) 921*30e863bbSAndi Kleen return; 922*30e863bbSAndi Kleen 923*30e863bbSAndi Kleen pthread_mutex_lock(¬es->lock); 924*30e863bbSAndi Kleen for (offset = 0; offset < size; ++offset) { 925*30e863bbSAndi Kleen struct cyc_hist *ch; 926*30e863bbSAndi Kleen 927*30e863bbSAndi Kleen ch = ¬es->src->cycles_hist[offset]; 928*30e863bbSAndi Kleen if (ch && ch->cycles) { 929*30e863bbSAndi Kleen struct disasm_line *dl; 930*30e863bbSAndi Kleen 931*30e863bbSAndi Kleen if (ch->have_start) 932*30e863bbSAndi Kleen count_and_fill(browser, ch->start, offset, ch); 933*30e863bbSAndi Kleen dl = browser->offsets[offset]; 934*30e863bbSAndi Kleen if (dl && ch->num_aggr) 935*30e863bbSAndi Kleen dl->cycles = ch->cycles_aggr / ch->num_aggr; 936*30e863bbSAndi Kleen browser->have_cycles = true; 937*30e863bbSAndi Kleen } 938*30e863bbSAndi Kleen } 939*30e863bbSAndi Kleen pthread_mutex_unlock(¬es->lock); 940*30e863bbSAndi Kleen } 941*30e863bbSAndi Kleen 942b793a401SArnaldo Carvalho de Melo static void annotate_browser__mark_jump_targets(struct annotate_browser *browser, 943b793a401SArnaldo Carvalho de Melo size_t size) 944b793a401SArnaldo Carvalho de Melo { 945b793a401SArnaldo Carvalho de Melo u64 offset; 94632ae1efdSNamhyung Kim struct map_symbol *ms = browser->b.priv; 94732ae1efdSNamhyung Kim struct symbol *sym = ms->sym; 94832ae1efdSNamhyung Kim 94932ae1efdSNamhyung Kim /* PLT symbols contain external offsets */ 95032ae1efdSNamhyung Kim if (strstr(sym->name, "@plt")) 95132ae1efdSNamhyung Kim return; 952b793a401SArnaldo Carvalho de Melo 953b793a401SArnaldo Carvalho de Melo for (offset = 0; offset < size; ++offset) { 954b793a401SArnaldo Carvalho de Melo struct disasm_line *dl = browser->offsets[offset], *dlt; 955b793a401SArnaldo Carvalho de Melo struct browser_disasm_line *bdlt; 956b793a401SArnaldo Carvalho de Melo 957865c66c4SFrederik Deweerdt if (!disasm_line__is_valid_jump(dl, sym)) 958b793a401SArnaldo Carvalho de Melo continue; 959b793a401SArnaldo Carvalho de Melo 96044d1a3edSArnaldo Carvalho de Melo dlt = browser->offsets[dl->ops.target.offset]; 9619481ede9SArnaldo Carvalho de Melo /* 9629481ede9SArnaldo Carvalho de Melo * FIXME: Oops, no jump target? Buggy disassembler? Or do we 9639481ede9SArnaldo Carvalho de Melo * have to adjust to the previous offset? 9649481ede9SArnaldo Carvalho de Melo */ 9659481ede9SArnaldo Carvalho de Melo if (dlt == NULL) 9669481ede9SArnaldo Carvalho de Melo continue; 9679481ede9SArnaldo Carvalho de Melo 968b793a401SArnaldo Carvalho de Melo bdlt = disasm_line__browser(dlt); 9692402e4a9SArnaldo Carvalho de Melo if (++bdlt->jump_sources > browser->max_jump_sources) 9702402e4a9SArnaldo Carvalho de Melo browser->max_jump_sources = bdlt->jump_sources; 9712402e4a9SArnaldo Carvalho de Melo 9722402e4a9SArnaldo Carvalho de Melo ++browser->nr_jumps; 973b793a401SArnaldo Carvalho de Melo } 974b793a401SArnaldo Carvalho de Melo } 975b793a401SArnaldo Carvalho de Melo 9762402e4a9SArnaldo Carvalho de Melo static inline int width_jumps(int n) 9772402e4a9SArnaldo Carvalho de Melo { 9782402e4a9SArnaldo Carvalho de Melo if (n >= 100) 9792402e4a9SArnaldo Carvalho de Melo return 5; 9802402e4a9SArnaldo Carvalho de Melo if (n / 10) 9812402e4a9SArnaldo Carvalho de Melo return 2; 9822402e4a9SArnaldo Carvalho de Melo return 1; 9832402e4a9SArnaldo Carvalho de Melo } 9842402e4a9SArnaldo Carvalho de Melo 985db8fd07aSNamhyung Kim int symbol__tui_annotate(struct symbol *sym, struct map *map, 986db8fd07aSNamhyung Kim struct perf_evsel *evsel, 9879783adf7SNamhyung Kim struct hist_browser_timer *hbt) 988aca7a94dSNamhyung Kim { 98929ed6e76SArnaldo Carvalho de Melo struct disasm_line *pos, *n; 990aca7a94dSNamhyung Kim struct annotation *notes; 991c0a58fb2SSamuel Liao size_t size; 992aca7a94dSNamhyung Kim struct map_symbol ms = { 993aca7a94dSNamhyung Kim .map = map, 994aca7a94dSNamhyung Kim .sym = sym, 995aca7a94dSNamhyung Kim }; 996aca7a94dSNamhyung Kim struct annotate_browser browser = { 997aca7a94dSNamhyung Kim .b = { 998a3f895beSArnaldo Carvalho de Melo .refresh = annotate_browser__refresh, 999aca7a94dSNamhyung Kim .seek = ui_browser__list_head_seek, 1000aca7a94dSNamhyung Kim .write = annotate_browser__write, 100129ed6e76SArnaldo Carvalho de Melo .filter = disasm_line__filter, 1002aca7a94dSNamhyung Kim .priv = &ms, 1003aca7a94dSNamhyung Kim .use_navkeypressed = true, 1004aca7a94dSNamhyung Kim }, 1005aca7a94dSNamhyung Kim }; 1006b793a401SArnaldo Carvalho de Melo int ret = -1; 1007c7e7b610SNamhyung Kim int nr_pcnt = 1; 1008c7e7b610SNamhyung Kim size_t sizeof_bdl = sizeof(struct browser_disasm_line); 1009aca7a94dSNamhyung Kim 1010aca7a94dSNamhyung Kim if (sym == NULL) 1011aca7a94dSNamhyung Kim return -1; 1012aca7a94dSNamhyung Kim 1013c0a58fb2SSamuel Liao size = symbol__size(sym); 1014c0a58fb2SSamuel Liao 1015aca7a94dSNamhyung Kim if (map->dso->annotate_warned) 1016aca7a94dSNamhyung Kim return -1; 1017aca7a94dSNamhyung Kim 1018b793a401SArnaldo Carvalho de Melo browser.offsets = zalloc(size * sizeof(struct disasm_line *)); 1019b793a401SArnaldo Carvalho de Melo if (browser.offsets == NULL) { 1020b793a401SArnaldo Carvalho de Melo ui__error("Not enough memory!"); 1021b793a401SArnaldo Carvalho de Melo return -1; 1022b793a401SArnaldo Carvalho de Melo } 1023b793a401SArnaldo Carvalho de Melo 1024c7e7b610SNamhyung Kim if (perf_evsel__is_group_event(evsel)) { 1025c7e7b610SNamhyung Kim nr_pcnt = evsel->nr_members; 10260c4a5bceSMartin Liška sizeof_bdl += sizeof(struct disasm_line_samples) * 10270c4a5bceSMartin Liška (nr_pcnt - 1); 1028c7e7b610SNamhyung Kim } 1029c7e7b610SNamhyung Kim 1030c7e7b610SNamhyung Kim if (symbol__annotate(sym, map, sizeof_bdl) < 0) { 1031aca7a94dSNamhyung Kim ui__error("%s", ui_helpline__last_msg); 1032b793a401SArnaldo Carvalho de Melo goto out_free_offsets; 1033aca7a94dSNamhyung Kim } 1034aca7a94dSNamhyung Kim 1035aca7a94dSNamhyung Kim ui_helpline__push("Press <- or ESC to exit"); 1036aca7a94dSNamhyung Kim 1037aca7a94dSNamhyung Kim notes = symbol__annotation(sym); 1038aca7a94dSNamhyung Kim browser.start = map__rip_2objdump(map, sym->start); 1039aca7a94dSNamhyung Kim 1040aca7a94dSNamhyung Kim list_for_each_entry(pos, ¬es->src->source, node) { 1041887c0066SArnaldo Carvalho de Melo struct browser_disasm_line *bpos; 1042aca7a94dSNamhyung Kim size_t line_len = strlen(pos->line); 1043aca7a94dSNamhyung Kim 1044aca7a94dSNamhyung Kim if (browser.b.width < line_len) 1045aca7a94dSNamhyung Kim browser.b.width = line_len; 1046887c0066SArnaldo Carvalho de Melo bpos = disasm_line__browser(pos); 1047887c0066SArnaldo Carvalho de Melo bpos->idx = browser.nr_entries++; 1048b793a401SArnaldo Carvalho de Melo if (pos->offset != -1) { 1049887c0066SArnaldo Carvalho de Melo bpos->idx_asm = browser.nr_asm_entries++; 105097148a97SArnaldo Carvalho de Melo /* 105197148a97SArnaldo Carvalho de Melo * FIXME: short term bandaid to cope with assembly 105297148a97SArnaldo Carvalho de Melo * routines that comes with labels in the same column 105397148a97SArnaldo Carvalho de Melo * as the address in objdump, sigh. 105497148a97SArnaldo Carvalho de Melo * 105597148a97SArnaldo Carvalho de Melo * E.g. copy_user_generic_unrolled 105697148a97SArnaldo Carvalho de Melo */ 105797148a97SArnaldo Carvalho de Melo if (pos->offset < (s64)size) 1058b793a401SArnaldo Carvalho de Melo browser.offsets[pos->offset] = pos; 1059b793a401SArnaldo Carvalho de Melo } else 1060887c0066SArnaldo Carvalho de Melo bpos->idx_asm = -1; 1061aca7a94dSNamhyung Kim } 1062aca7a94dSNamhyung Kim 1063b793a401SArnaldo Carvalho de Melo annotate_browser__mark_jump_targets(&browser, size); 1064*30e863bbSAndi Kleen annotate__compute_ipc(&browser, size, sym); 1065b793a401SArnaldo Carvalho de Melo 10662402e4a9SArnaldo Carvalho de Melo browser.addr_width = browser.target_width = browser.min_addr_width = hex_width(size); 106783b1f2aaSArnaldo Carvalho de Melo browser.max_addr_width = hex_width(sym->end); 10682402e4a9SArnaldo Carvalho de Melo browser.jumps_width = width_jumps(browser.max_jump_sources); 1069c7e7b610SNamhyung Kim browser.nr_events = nr_pcnt; 1070aca7a94dSNamhyung Kim browser.b.nr_entries = browser.nr_entries; 1071aca7a94dSNamhyung Kim browser.b.entries = ¬es->src->source, 1072aca7a94dSNamhyung Kim browser.b.width += 18; /* Percentage */ 1073e9823b21SArnaldo Carvalho de Melo 1074e9823b21SArnaldo Carvalho de Melo if (annotate_browser__opts.hide_src_code) 1075e9823b21SArnaldo Carvalho de Melo annotate_browser__init_asm_mode(&browser); 1076e9823b21SArnaldo Carvalho de Melo 1077e9823b21SArnaldo Carvalho de Melo annotate_browser__update_addr_width(&browser); 1078e9823b21SArnaldo Carvalho de Melo 1079db8fd07aSNamhyung Kim ret = annotate_browser__run(&browser, evsel, hbt); 1080aca7a94dSNamhyung Kim list_for_each_entry_safe(pos, n, ¬es->src->source, node) { 1081aca7a94dSNamhyung Kim list_del(&pos->node); 108229ed6e76SArnaldo Carvalho de Melo disasm_line__free(pos); 1083aca7a94dSNamhyung Kim } 1084b793a401SArnaldo Carvalho de Melo 1085b793a401SArnaldo Carvalho de Melo out_free_offsets: 1086b793a401SArnaldo Carvalho de Melo free(browser.offsets); 1087aca7a94dSNamhyung Kim return ret; 1088aca7a94dSNamhyung Kim } 1089c323cf04SArnaldo Carvalho de Melo 1090c323cf04SArnaldo Carvalho de Melo #define ANNOTATE_CFG(n) \ 1091c323cf04SArnaldo Carvalho de Melo { .name = #n, .value = &annotate_browser__opts.n, } 1092c323cf04SArnaldo Carvalho de Melo 1093c323cf04SArnaldo Carvalho de Melo /* 1094c323cf04SArnaldo Carvalho de Melo * Keep the entries sorted, they are bsearch'ed 1095c323cf04SArnaldo Carvalho de Melo */ 10967c3102b8SArnaldo Carvalho de Melo static struct annotate_config { 1097c323cf04SArnaldo Carvalho de Melo const char *name; 1098c323cf04SArnaldo Carvalho de Melo bool *value; 1099c323cf04SArnaldo Carvalho de Melo } annotate__configs[] = { 1100c323cf04SArnaldo Carvalho de Melo ANNOTATE_CFG(hide_src_code), 1101c323cf04SArnaldo Carvalho de Melo ANNOTATE_CFG(jump_arrows), 1102e592488cSAndi Kleen ANNOTATE_CFG(show_linenr), 1103c323cf04SArnaldo Carvalho de Melo ANNOTATE_CFG(show_nr_jumps), 1104c323cf04SArnaldo Carvalho de Melo ANNOTATE_CFG(use_offset), 11050c4a5bceSMartin Liška ANNOTATE_CFG(show_total_period), 1106c323cf04SArnaldo Carvalho de Melo }; 1107c323cf04SArnaldo Carvalho de Melo 1108c323cf04SArnaldo Carvalho de Melo #undef ANNOTATE_CFG 1109c323cf04SArnaldo Carvalho de Melo 1110c323cf04SArnaldo Carvalho de Melo static int annotate_config__cmp(const void *name, const void *cfgp) 1111c323cf04SArnaldo Carvalho de Melo { 11127c3102b8SArnaldo Carvalho de Melo const struct annotate_config *cfg = cfgp; 1113c323cf04SArnaldo Carvalho de Melo 1114c323cf04SArnaldo Carvalho de Melo return strcmp(name, cfg->name); 1115c323cf04SArnaldo Carvalho de Melo } 1116c323cf04SArnaldo Carvalho de Melo 11171d037ca1SIrina Tirdea static int annotate__config(const char *var, const char *value, 11181d037ca1SIrina Tirdea void *data __maybe_unused) 1119c323cf04SArnaldo Carvalho de Melo { 11207c3102b8SArnaldo Carvalho de Melo struct annotate_config *cfg; 1121c323cf04SArnaldo Carvalho de Melo const char *name; 1122c323cf04SArnaldo Carvalho de Melo 1123c323cf04SArnaldo Carvalho de Melo if (prefixcmp(var, "annotate.") != 0) 1124c323cf04SArnaldo Carvalho de Melo return 0; 1125c323cf04SArnaldo Carvalho de Melo 1126c323cf04SArnaldo Carvalho de Melo name = var + 9; 1127c323cf04SArnaldo Carvalho de Melo cfg = bsearch(name, annotate__configs, ARRAY_SIZE(annotate__configs), 11287c3102b8SArnaldo Carvalho de Melo sizeof(struct annotate_config), annotate_config__cmp); 1129c323cf04SArnaldo Carvalho de Melo 1130c323cf04SArnaldo Carvalho de Melo if (cfg == NULL) 1131c323cf04SArnaldo Carvalho de Melo return -1; 1132c323cf04SArnaldo Carvalho de Melo 1133c323cf04SArnaldo Carvalho de Melo *cfg->value = perf_config_bool(name, value); 1134c323cf04SArnaldo Carvalho de Melo return 0; 1135c323cf04SArnaldo Carvalho de Melo } 1136c323cf04SArnaldo Carvalho de Melo 1137c323cf04SArnaldo Carvalho de Melo void annotate_browser__init(void) 1138c323cf04SArnaldo Carvalho de Melo { 1139c323cf04SArnaldo Carvalho de Melo perf_config(annotate__config, NULL); 1140c323cf04SArnaldo Carvalho de Melo } 1141