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 19*f8f4aaeaSAndi Kleen #define IPC_WIDTH 6 20*f8f4aaeaSAndi Kleen #define CYCLES_WIDTH 6 21*f8f4aaeaSAndi Kleen 22b793a401SArnaldo Carvalho de Melo struct browser_disasm_line { 23b793a401SArnaldo Carvalho de Melo struct rb_node rb_node; 24b793a401SArnaldo Carvalho de Melo u32 idx; 25b793a401SArnaldo Carvalho de Melo int idx_asm; 267d5b12f5SArnaldo Carvalho de Melo int jump_sources; 27c7e7b610SNamhyung Kim /* 28c7e7b610SNamhyung Kim * actual length of this array is saved on the nr_events field 29c7e7b610SNamhyung Kim * of the struct annotate_browser 30c7e7b610SNamhyung Kim */ 310c4a5bceSMartin Liška struct disasm_line_samples samples[1]; 32b793a401SArnaldo Carvalho de Melo }; 33b793a401SArnaldo Carvalho de Melo 34e9823b21SArnaldo Carvalho de Melo static struct annotate_browser_opt { 35e9823b21SArnaldo Carvalho de Melo bool hide_src_code, 36e9823b21SArnaldo Carvalho de Melo use_offset, 37e9823b21SArnaldo Carvalho de Melo jump_arrows, 38e592488cSAndi Kleen show_linenr, 390c4a5bceSMartin Liška show_nr_jumps, 400c4a5bceSMartin Liška show_total_period; 41e9823b21SArnaldo Carvalho de Melo } annotate_browser__opts = { 42e9823b21SArnaldo Carvalho de Melo .use_offset = true, 43e9823b21SArnaldo Carvalho de Melo .jump_arrows = true, 44e9823b21SArnaldo Carvalho de Melo }; 45e9823b21SArnaldo Carvalho de Melo 46aca7a94dSNamhyung Kim struct annotate_browser { 47aca7a94dSNamhyung Kim struct ui_browser b; 48aca7a94dSNamhyung Kim struct rb_root entries; 49aca7a94dSNamhyung Kim struct rb_node *curr_hot; 5029ed6e76SArnaldo Carvalho de Melo struct disasm_line *selection; 51b793a401SArnaldo Carvalho de Melo struct disasm_line **offsets; 52c7e7b610SNamhyung Kim int nr_events; 53aca7a94dSNamhyung Kim u64 start; 54aca7a94dSNamhyung Kim int nr_asm_entries; 55aca7a94dSNamhyung Kim int nr_entries; 562402e4a9SArnaldo Carvalho de Melo int max_jump_sources; 572402e4a9SArnaldo Carvalho de Melo int nr_jumps; 58aca7a94dSNamhyung Kim bool searching_backwards; 5930e863bbSAndi Kleen bool have_cycles; 6083b1f2aaSArnaldo Carvalho de Melo u8 addr_width; 612402e4a9SArnaldo Carvalho de Melo u8 jumps_width; 622402e4a9SArnaldo Carvalho de Melo u8 target_width; 6383b1f2aaSArnaldo Carvalho de Melo u8 min_addr_width; 6483b1f2aaSArnaldo Carvalho de Melo u8 max_addr_width; 65aca7a94dSNamhyung Kim char search_bf[128]; 66aca7a94dSNamhyung Kim }; 67aca7a94dSNamhyung Kim 68887c0066SArnaldo Carvalho de Melo static inline struct browser_disasm_line *disasm_line__browser(struct disasm_line *dl) 69aca7a94dSNamhyung Kim { 70887c0066SArnaldo Carvalho de Melo return (struct browser_disasm_line *)(dl + 1); 71aca7a94dSNamhyung Kim } 72aca7a94dSNamhyung Kim 731d037ca1SIrina Tirdea static bool disasm_line__filter(struct ui_browser *browser __maybe_unused, 741d037ca1SIrina Tirdea void *entry) 75aca7a94dSNamhyung Kim { 76e9823b21SArnaldo Carvalho de Melo if (annotate_browser__opts.hide_src_code) { 7729ed6e76SArnaldo Carvalho de Melo struct disasm_line *dl = list_entry(entry, struct disasm_line, node); 7829ed6e76SArnaldo Carvalho de Melo return dl->offset == -1; 79aca7a94dSNamhyung Kim } 80aca7a94dSNamhyung Kim 81aca7a94dSNamhyung Kim return false; 82aca7a94dSNamhyung Kim } 83aca7a94dSNamhyung Kim 842402e4a9SArnaldo Carvalho de Melo static int annotate_browser__jumps_percent_color(struct annotate_browser *browser, 852402e4a9SArnaldo Carvalho de Melo int nr, bool current) 862402e4a9SArnaldo Carvalho de Melo { 872402e4a9SArnaldo Carvalho de Melo if (current && (!browser->b.use_navkeypressed || browser->b.navkeypressed)) 882402e4a9SArnaldo Carvalho de Melo return HE_COLORSET_SELECTED; 892402e4a9SArnaldo Carvalho de Melo if (nr == browser->max_jump_sources) 902402e4a9SArnaldo Carvalho de Melo return HE_COLORSET_TOP; 912402e4a9SArnaldo Carvalho de Melo if (nr > 1) 922402e4a9SArnaldo Carvalho de Melo return HE_COLORSET_MEDIUM; 932402e4a9SArnaldo Carvalho de Melo return HE_COLORSET_NORMAL; 942402e4a9SArnaldo Carvalho de Melo } 952402e4a9SArnaldo Carvalho de Melo 962402e4a9SArnaldo Carvalho de Melo static int annotate_browser__set_jumps_percent_color(struct annotate_browser *browser, 972402e4a9SArnaldo Carvalho de Melo int nr, bool current) 982402e4a9SArnaldo Carvalho de Melo { 992402e4a9SArnaldo Carvalho de Melo int color = annotate_browser__jumps_percent_color(browser, nr, current); 1002402e4a9SArnaldo Carvalho de Melo return ui_browser__set_color(&browser->b, color); 1012402e4a9SArnaldo Carvalho de Melo } 1022402e4a9SArnaldo Carvalho de Melo 103*f8f4aaeaSAndi Kleen static int annotate_browser__pcnt_width(struct annotate_browser *ab) 104*f8f4aaeaSAndi Kleen { 105*f8f4aaeaSAndi Kleen int w = 7 * ab->nr_events; 106*f8f4aaeaSAndi Kleen 107*f8f4aaeaSAndi Kleen if (ab->have_cycles) 108*f8f4aaeaSAndi Kleen w += IPC_WIDTH + CYCLES_WIDTH; 109*f8f4aaeaSAndi Kleen return w; 110*f8f4aaeaSAndi Kleen } 111*f8f4aaeaSAndi Kleen 11205e8b080SArnaldo Carvalho de Melo static void annotate_browser__write(struct ui_browser *browser, void *entry, int row) 113aca7a94dSNamhyung Kim { 11405e8b080SArnaldo Carvalho de Melo struct annotate_browser *ab = container_of(browser, struct annotate_browser, b); 11529ed6e76SArnaldo Carvalho de Melo struct disasm_line *dl = list_entry(entry, struct disasm_line, node); 116b793a401SArnaldo Carvalho de Melo struct browser_disasm_line *bdl = disasm_line__browser(dl); 11705e8b080SArnaldo Carvalho de Melo bool current_entry = ui_browser__is_current_entry(browser, row); 118e9823b21SArnaldo Carvalho de Melo bool change_color = (!annotate_browser__opts.hide_src_code && 11905e8b080SArnaldo Carvalho de Melo (!current_entry || (browser->use_navkeypressed && 12005e8b080SArnaldo Carvalho de Melo !browser->navkeypressed))); 12105e8b080SArnaldo Carvalho de Melo int width = browser->width, printed; 122*f8f4aaeaSAndi Kleen int i, pcnt_width = annotate_browser__pcnt_width(ab); 123c7e7b610SNamhyung Kim double percent_max = 0.0; 12483b1f2aaSArnaldo Carvalho de Melo char bf[256]; 125aca7a94dSNamhyung Kim 126c7e7b610SNamhyung Kim for (i = 0; i < ab->nr_events; i++) { 1270c4a5bceSMartin Liška if (bdl->samples[i].percent > percent_max) 1280c4a5bceSMartin Liška percent_max = bdl->samples[i].percent; 129c7e7b610SNamhyung Kim } 130c7e7b610SNamhyung Kim 131c7e7b610SNamhyung Kim if (dl->offset != -1 && percent_max != 0.0) { 132*f8f4aaeaSAndi Kleen if (percent_max != 0.0) { 133c7e7b610SNamhyung Kim for (i = 0; i < ab->nr_events; i++) { 1340c4a5bceSMartin Liška ui_browser__set_percent_color(browser, 1350c4a5bceSMartin Liška bdl->samples[i].percent, 136c7e7b610SNamhyung Kim current_entry); 1370c4a5bceSMartin Liška if (annotate_browser__opts.show_total_period) 1380c4a5bceSMartin Liška slsmg_printf("%6" PRIu64 " ", 1390c4a5bceSMartin Liška bdl->samples[i].nr); 1400c4a5bceSMartin Liška else 1410c4a5bceSMartin Liška slsmg_printf("%6.2f ", bdl->samples[i].percent); 142c7e7b610SNamhyung Kim } 143aca7a94dSNamhyung Kim } else { 144*f8f4aaeaSAndi Kleen slsmg_write_nstring(" ", 7 * ab->nr_events); 145*f8f4aaeaSAndi Kleen } 146*f8f4aaeaSAndi Kleen } else { 14705e8b080SArnaldo Carvalho de Melo ui_browser__set_percent_color(browser, 0, current_entry); 148*f8f4aaeaSAndi Kleen slsmg_write_nstring(" ", 7 * ab->nr_events); 149*f8f4aaeaSAndi Kleen } 150*f8f4aaeaSAndi Kleen if (ab->have_cycles) { 151*f8f4aaeaSAndi Kleen if (dl->ipc) 152*f8f4aaeaSAndi Kleen slsmg_printf("%*.2f ", IPC_WIDTH - 1, dl->ipc); 153*f8f4aaeaSAndi Kleen else 154*f8f4aaeaSAndi Kleen slsmg_write_nstring(" ", IPC_WIDTH); 155*f8f4aaeaSAndi Kleen if (dl->cycles) 156*f8f4aaeaSAndi Kleen slsmg_printf("%*" PRIu64 " ", 157*f8f4aaeaSAndi Kleen CYCLES_WIDTH - 1, dl->cycles); 158*f8f4aaeaSAndi Kleen else 159*f8f4aaeaSAndi Kleen slsmg_write_nstring(" ", CYCLES_WIDTH); 160aca7a94dSNamhyung Kim } 161aca7a94dSNamhyung Kim 162cf2dacc5SArnaldo Carvalho de Melo SLsmg_write_char(' '); 163aca7a94dSNamhyung Kim 164aca7a94dSNamhyung Kim /* The scroll bar isn't being used */ 16505e8b080SArnaldo Carvalho de Melo if (!browser->navkeypressed) 166aca7a94dSNamhyung Kim width += 1; 167aca7a94dSNamhyung Kim 16829ed6e76SArnaldo Carvalho de Melo if (!*dl->line) 169c7e7b610SNamhyung Kim slsmg_write_nstring(" ", width - pcnt_width); 17083b1f2aaSArnaldo Carvalho de Melo else if (dl->offset == -1) { 171e592488cSAndi Kleen if (dl->line_nr && annotate_browser__opts.show_linenr) 172e592488cSAndi Kleen printed = scnprintf(bf, sizeof(bf), "%-*d ", 173e592488cSAndi Kleen ab->addr_width + 1, dl->line_nr); 174e592488cSAndi Kleen else 17583b1f2aaSArnaldo Carvalho de Melo printed = scnprintf(bf, sizeof(bf), "%*s ", 17683b1f2aaSArnaldo Carvalho de Melo ab->addr_width, " "); 17783b1f2aaSArnaldo Carvalho de Melo slsmg_write_nstring(bf, printed); 178c7e7b610SNamhyung Kim slsmg_write_nstring(dl->line, width - printed - pcnt_width + 1); 17983b1f2aaSArnaldo Carvalho de Melo } else { 18029ed6e76SArnaldo Carvalho de Melo u64 addr = dl->offset; 18183b1f2aaSArnaldo Carvalho de Melo int color = -1; 182aca7a94dSNamhyung Kim 183e9823b21SArnaldo Carvalho de Melo if (!annotate_browser__opts.use_offset) 184aca7a94dSNamhyung Kim addr += ab->start; 185aca7a94dSNamhyung Kim 186e9823b21SArnaldo Carvalho de Melo if (!annotate_browser__opts.use_offset) { 187aca7a94dSNamhyung Kim printed = scnprintf(bf, sizeof(bf), "%" PRIx64 ": ", addr); 18861e04b33SArnaldo Carvalho de Melo } else { 1897d5b12f5SArnaldo Carvalho de Melo if (bdl->jump_sources) { 190e9823b21SArnaldo Carvalho de Melo if (annotate_browser__opts.show_nr_jumps) { 1912402e4a9SArnaldo Carvalho de Melo int prev; 1922402e4a9SArnaldo Carvalho de Melo printed = scnprintf(bf, sizeof(bf), "%*d ", 1932402e4a9SArnaldo Carvalho de Melo ab->jumps_width, 1942402e4a9SArnaldo Carvalho de Melo bdl->jump_sources); 1952402e4a9SArnaldo Carvalho de Melo prev = annotate_browser__set_jumps_percent_color(ab, bdl->jump_sources, 1962402e4a9SArnaldo Carvalho de Melo current_entry); 1972402e4a9SArnaldo Carvalho de Melo slsmg_write_nstring(bf, printed); 19805e8b080SArnaldo Carvalho de Melo ui_browser__set_color(browser, prev); 1992402e4a9SArnaldo Carvalho de Melo } 2002402e4a9SArnaldo Carvalho de Melo 20161e04b33SArnaldo Carvalho de Melo printed = scnprintf(bf, sizeof(bf), "%*" PRIx64 ": ", 2022402e4a9SArnaldo Carvalho de Melo ab->target_width, addr); 20361e04b33SArnaldo Carvalho de Melo } else { 20461e04b33SArnaldo Carvalho de Melo printed = scnprintf(bf, sizeof(bf), "%*s ", 20583b1f2aaSArnaldo Carvalho de Melo ab->addr_width, " "); 20661e04b33SArnaldo Carvalho de Melo } 20761e04b33SArnaldo Carvalho de Melo } 208b793a401SArnaldo Carvalho de Melo 209aca7a94dSNamhyung Kim if (change_color) 21005e8b080SArnaldo Carvalho de Melo color = ui_browser__set_color(browser, HE_COLORSET_ADDR); 211aca7a94dSNamhyung Kim slsmg_write_nstring(bf, printed); 212aca7a94dSNamhyung Kim if (change_color) 21305e8b080SArnaldo Carvalho de Melo ui_browser__set_color(browser, color); 21428548d78SArnaldo Carvalho de Melo if (dl->ins && dl->ins->ops->scnprintf) { 21551a0d455SArnaldo Carvalho de Melo if (ins__is_jump(dl->ins)) { 21644d1a3edSArnaldo Carvalho de Melo bool fwd = dl->ops.target.offset > (u64)dl->offset; 21751a0d455SArnaldo Carvalho de Melo 21805e8b080SArnaldo Carvalho de Melo ui_browser__write_graph(browser, fwd ? SLSMG_DARROW_CHAR : 21951a0d455SArnaldo Carvalho de Melo SLSMG_UARROW_CHAR); 22051a0d455SArnaldo Carvalho de Melo SLsmg_write_char(' '); 22188298f5aSArnaldo Carvalho de Melo } else if (ins__is_call(dl->ins)) { 22205e8b080SArnaldo Carvalho de Melo ui_browser__write_graph(browser, SLSMG_RARROW_CHAR); 22388298f5aSArnaldo Carvalho de Melo SLsmg_write_char(' '); 22451a0d455SArnaldo Carvalho de Melo } else { 22551a0d455SArnaldo Carvalho de Melo slsmg_write_nstring(" ", 2); 22651a0d455SArnaldo Carvalho de Melo } 2274ea08b52SArnaldo Carvalho de Melo } else { 2284ea08b52SArnaldo Carvalho de Melo if (strcmp(dl->name, "retq")) { 2294ea08b52SArnaldo Carvalho de Melo slsmg_write_nstring(" ", 2); 2304ea08b52SArnaldo Carvalho de Melo } else { 23105e8b080SArnaldo Carvalho de Melo ui_browser__write_graph(browser, SLSMG_LARROW_CHAR); 2324ea08b52SArnaldo Carvalho de Melo SLsmg_write_char(' '); 2334ea08b52SArnaldo Carvalho de Melo } 2344ea08b52SArnaldo Carvalho de Melo } 2354ea08b52SArnaldo Carvalho de Melo 236e9823b21SArnaldo Carvalho de Melo disasm_line__scnprintf(dl, bf, sizeof(bf), !annotate_browser__opts.use_offset); 237c7e7b610SNamhyung Kim slsmg_write_nstring(bf, width - pcnt_width - 3 - printed); 238aca7a94dSNamhyung Kim } 239aca7a94dSNamhyung Kim 240aca7a94dSNamhyung Kim if (current_entry) 24129ed6e76SArnaldo Carvalho de Melo ab->selection = dl; 242aca7a94dSNamhyung Kim } 243aca7a94dSNamhyung Kim 244865c66c4SFrederik Deweerdt static bool disasm_line__is_valid_jump(struct disasm_line *dl, struct symbol *sym) 245865c66c4SFrederik Deweerdt { 246865c66c4SFrederik Deweerdt if (!dl || !dl->ins || !ins__is_jump(dl->ins) 247865c66c4SFrederik Deweerdt || !disasm_line__has_offset(dl) 248865c66c4SFrederik Deweerdt || dl->ops.target.offset >= symbol__size(sym)) 249865c66c4SFrederik Deweerdt return false; 250865c66c4SFrederik Deweerdt 251865c66c4SFrederik Deweerdt return true; 252865c66c4SFrederik Deweerdt } 253865c66c4SFrederik Deweerdt 2549d1ef56dSArnaldo Carvalho de Melo static void annotate_browser__draw_current_jump(struct ui_browser *browser) 255a3f895beSArnaldo Carvalho de Melo { 256a3f895beSArnaldo Carvalho de Melo struct annotate_browser *ab = container_of(browser, struct annotate_browser, b); 2579d1ef56dSArnaldo Carvalho de Melo struct disasm_line *cursor = ab->selection, *target; 2589d1ef56dSArnaldo Carvalho de Melo struct browser_disasm_line *btarget, *bcursor; 25983b1f2aaSArnaldo Carvalho de Melo unsigned int from, to; 26032ae1efdSNamhyung Kim struct map_symbol *ms = ab->b.priv; 26132ae1efdSNamhyung Kim struct symbol *sym = ms->sym; 262*f8f4aaeaSAndi Kleen u8 pcnt_width = annotate_browser__pcnt_width(ab); 26332ae1efdSNamhyung Kim 26432ae1efdSNamhyung Kim /* PLT symbols contain external offsets */ 26532ae1efdSNamhyung Kim if (strstr(sym->name, "@plt")) 26632ae1efdSNamhyung Kim return; 267a3f895beSArnaldo Carvalho de Melo 268865c66c4SFrederik Deweerdt if (!disasm_line__is_valid_jump(cursor, sym)) 269a3f895beSArnaldo Carvalho de Melo return; 270a3f895beSArnaldo Carvalho de Melo 2719d1ef56dSArnaldo Carvalho de Melo target = ab->offsets[cursor->ops.target.offset]; 2729d1ef56dSArnaldo Carvalho de Melo if (!target) 2739d1ef56dSArnaldo Carvalho de Melo return; 2749d1ef56dSArnaldo Carvalho de Melo 2759d1ef56dSArnaldo Carvalho de Melo bcursor = disasm_line__browser(cursor); 2769d1ef56dSArnaldo Carvalho de Melo btarget = disasm_line__browser(target); 2779d1ef56dSArnaldo Carvalho de Melo 278e9823b21SArnaldo Carvalho de Melo if (annotate_browser__opts.hide_src_code) { 2799d1ef56dSArnaldo Carvalho de Melo from = bcursor->idx_asm; 280a3f895beSArnaldo Carvalho de Melo to = btarget->idx_asm; 281a3f895beSArnaldo Carvalho de Melo } else { 2829d1ef56dSArnaldo Carvalho de Melo from = (u64)bcursor->idx; 283a3f895beSArnaldo Carvalho de Melo to = (u64)btarget->idx; 284a3f895beSArnaldo Carvalho de Melo } 285a3f895beSArnaldo Carvalho de Melo 286a3f895beSArnaldo Carvalho de Melo ui_browser__set_color(browser, HE_COLORSET_CODE); 287c7e7b610SNamhyung Kim __ui_browser__line_arrow(browser, pcnt_width + 2 + ab->addr_width, 288c7e7b610SNamhyung Kim from, to); 289a3f895beSArnaldo Carvalho de Melo } 290a3f895beSArnaldo Carvalho de Melo 291a3f895beSArnaldo Carvalho de Melo static unsigned int annotate_browser__refresh(struct ui_browser *browser) 292a3f895beSArnaldo Carvalho de Melo { 293c7e7b610SNamhyung Kim struct annotate_browser *ab = container_of(browser, struct annotate_browser, b); 294a3f895beSArnaldo Carvalho de Melo int ret = ui_browser__list_head_refresh(browser); 295*f8f4aaeaSAndi Kleen int pcnt_width = annotate_browser__pcnt_width(ab); 296a3f895beSArnaldo Carvalho de Melo 297e9823b21SArnaldo Carvalho de Melo if (annotate_browser__opts.jump_arrows) 2989d1ef56dSArnaldo Carvalho de Melo annotate_browser__draw_current_jump(browser); 299a3f895beSArnaldo Carvalho de Melo 30083b1f2aaSArnaldo Carvalho de Melo ui_browser__set_color(browser, HE_COLORSET_NORMAL); 301c7e7b610SNamhyung Kim __ui_browser__vline(browser, pcnt_width, 0, browser->height - 1); 302a3f895beSArnaldo Carvalho de Melo return ret; 303a3f895beSArnaldo Carvalho de Melo } 304a3f895beSArnaldo Carvalho de Melo 305c7e7b610SNamhyung Kim static int disasm__cmp(struct browser_disasm_line *a, 306c7e7b610SNamhyung Kim struct browser_disasm_line *b, int nr_pcnt) 307c7e7b610SNamhyung Kim { 308c7e7b610SNamhyung Kim int i; 309c7e7b610SNamhyung Kim 310c7e7b610SNamhyung Kim for (i = 0; i < nr_pcnt; i++) { 3110c4a5bceSMartin Liška if (a->samples[i].percent == b->samples[i].percent) 312c7e7b610SNamhyung Kim continue; 3130c4a5bceSMartin Liška return a->samples[i].percent < b->samples[i].percent; 314c7e7b610SNamhyung Kim } 315c7e7b610SNamhyung Kim return 0; 316c7e7b610SNamhyung Kim } 317c7e7b610SNamhyung Kim 318c7e7b610SNamhyung Kim static void disasm_rb_tree__insert(struct rb_root *root, struct browser_disasm_line *bdl, 319c7e7b610SNamhyung Kim int nr_events) 320aca7a94dSNamhyung Kim { 32129ed6e76SArnaldo Carvalho de Melo struct rb_node **p = &root->rb_node; 322aca7a94dSNamhyung Kim struct rb_node *parent = NULL; 323887c0066SArnaldo Carvalho de Melo struct browser_disasm_line *l; 324aca7a94dSNamhyung Kim 325aca7a94dSNamhyung Kim while (*p != NULL) { 326aca7a94dSNamhyung Kim parent = *p; 327887c0066SArnaldo Carvalho de Melo l = rb_entry(parent, struct browser_disasm_line, rb_node); 328c7e7b610SNamhyung Kim 329c7e7b610SNamhyung Kim if (disasm__cmp(bdl, l, nr_events)) 330aca7a94dSNamhyung Kim p = &(*p)->rb_left; 331aca7a94dSNamhyung Kim else 332aca7a94dSNamhyung Kim p = &(*p)->rb_right; 333aca7a94dSNamhyung Kim } 334887c0066SArnaldo Carvalho de Melo rb_link_node(&bdl->rb_node, parent, p); 335887c0066SArnaldo Carvalho de Melo rb_insert_color(&bdl->rb_node, root); 336aca7a94dSNamhyung Kim } 337aca7a94dSNamhyung Kim 33805e8b080SArnaldo Carvalho de Melo static void annotate_browser__set_top(struct annotate_browser *browser, 33929ed6e76SArnaldo Carvalho de Melo struct disasm_line *pos, u32 idx) 340aca7a94dSNamhyung Kim { 341aca7a94dSNamhyung Kim unsigned back; 342aca7a94dSNamhyung Kim 34305e8b080SArnaldo Carvalho de Melo ui_browser__refresh_dimensions(&browser->b); 34405e8b080SArnaldo Carvalho de Melo back = browser->b.height / 2; 34505e8b080SArnaldo Carvalho de Melo browser->b.top_idx = browser->b.index = idx; 346aca7a94dSNamhyung Kim 34705e8b080SArnaldo Carvalho de Melo while (browser->b.top_idx != 0 && back != 0) { 34829ed6e76SArnaldo Carvalho de Melo pos = list_entry(pos->node.prev, struct disasm_line, node); 349aca7a94dSNamhyung Kim 35005e8b080SArnaldo Carvalho de Melo if (disasm_line__filter(&browser->b, &pos->node)) 351aca7a94dSNamhyung Kim continue; 352aca7a94dSNamhyung Kim 35305e8b080SArnaldo Carvalho de Melo --browser->b.top_idx; 354aca7a94dSNamhyung Kim --back; 355aca7a94dSNamhyung Kim } 356aca7a94dSNamhyung Kim 35705e8b080SArnaldo Carvalho de Melo browser->b.top = pos; 35805e8b080SArnaldo Carvalho de Melo browser->b.navkeypressed = true; 359aca7a94dSNamhyung Kim } 360aca7a94dSNamhyung Kim 361aca7a94dSNamhyung Kim static void annotate_browser__set_rb_top(struct annotate_browser *browser, 362aca7a94dSNamhyung Kim struct rb_node *nd) 363aca7a94dSNamhyung Kim { 364887c0066SArnaldo Carvalho de Melo struct browser_disasm_line *bpos; 36529ed6e76SArnaldo Carvalho de Melo struct disasm_line *pos; 366a44b45f2SArnaldo Carvalho de Melo u32 idx; 367aca7a94dSNamhyung Kim 368887c0066SArnaldo Carvalho de Melo bpos = rb_entry(nd, struct browser_disasm_line, rb_node); 369887c0066SArnaldo Carvalho de Melo pos = ((struct disasm_line *)bpos) - 1; 370a44b45f2SArnaldo Carvalho de Melo idx = bpos->idx; 371e9823b21SArnaldo Carvalho de Melo if (annotate_browser__opts.hide_src_code) 372a44b45f2SArnaldo Carvalho de Melo idx = bpos->idx_asm; 373a44b45f2SArnaldo Carvalho de Melo annotate_browser__set_top(browser, pos, idx); 374aca7a94dSNamhyung Kim browser->curr_hot = nd; 375aca7a94dSNamhyung Kim } 376aca7a94dSNamhyung Kim 377aca7a94dSNamhyung Kim static void annotate_browser__calc_percent(struct annotate_browser *browser, 378db8fd07aSNamhyung Kim struct perf_evsel *evsel) 379aca7a94dSNamhyung Kim { 380aca7a94dSNamhyung Kim struct map_symbol *ms = browser->b.priv; 381aca7a94dSNamhyung Kim struct symbol *sym = ms->sym; 382aca7a94dSNamhyung Kim struct annotation *notes = symbol__annotation(sym); 383e64aa75bSNamhyung Kim struct disasm_line *pos, *next; 384e64aa75bSNamhyung Kim s64 len = symbol__size(sym); 385aca7a94dSNamhyung Kim 386aca7a94dSNamhyung Kim browser->entries = RB_ROOT; 387aca7a94dSNamhyung Kim 388aca7a94dSNamhyung Kim pthread_mutex_lock(¬es->lock); 389aca7a94dSNamhyung Kim 390aca7a94dSNamhyung Kim list_for_each_entry(pos, ¬es->src->source, node) { 391887c0066SArnaldo Carvalho de Melo struct browser_disasm_line *bpos = disasm_line__browser(pos); 392e64aa75bSNamhyung Kim const char *path = NULL; 393c7e7b610SNamhyung Kim double max_percent = 0.0; 394c7e7b610SNamhyung Kim int i; 395e64aa75bSNamhyung Kim 396e64aa75bSNamhyung Kim if (pos->offset == -1) { 397e64aa75bSNamhyung Kim RB_CLEAR_NODE(&bpos->rb_node); 398e64aa75bSNamhyung Kim continue; 399e64aa75bSNamhyung Kim } 400e64aa75bSNamhyung Kim 401e64aa75bSNamhyung Kim next = disasm__get_next_ip_line(¬es->src->source, pos); 402c7e7b610SNamhyung Kim 403c7e7b610SNamhyung Kim for (i = 0; i < browser->nr_events; i++) { 4040c4a5bceSMartin Liška u64 nr_samples; 4050c4a5bceSMartin Liška 4060c4a5bceSMartin Liška bpos->samples[i].percent = disasm__calc_percent(notes, 407c7e7b610SNamhyung Kim evsel->idx + i, 408c7e7b610SNamhyung Kim pos->offset, 409c7e7b610SNamhyung Kim next ? next->offset : len, 4100c4a5bceSMartin Liška &path, &nr_samples); 4110c4a5bceSMartin Liška bpos->samples[i].nr = nr_samples; 412e64aa75bSNamhyung Kim 4130c4a5bceSMartin Liška if (max_percent < bpos->samples[i].percent) 4140c4a5bceSMartin Liška max_percent = bpos->samples[i].percent; 415c7e7b610SNamhyung Kim } 416c7e7b610SNamhyung Kim 41730e863bbSAndi Kleen if (max_percent < 0.01 && pos->ipc == 0) { 418887c0066SArnaldo Carvalho de Melo RB_CLEAR_NODE(&bpos->rb_node); 419aca7a94dSNamhyung Kim continue; 420aca7a94dSNamhyung Kim } 421c7e7b610SNamhyung Kim disasm_rb_tree__insert(&browser->entries, bpos, 422c7e7b610SNamhyung Kim browser->nr_events); 423aca7a94dSNamhyung Kim } 424aca7a94dSNamhyung Kim pthread_mutex_unlock(¬es->lock); 425aca7a94dSNamhyung Kim 426aca7a94dSNamhyung Kim browser->curr_hot = rb_last(&browser->entries); 427aca7a94dSNamhyung Kim } 428aca7a94dSNamhyung Kim 429aca7a94dSNamhyung Kim static bool annotate_browser__toggle_source(struct annotate_browser *browser) 430aca7a94dSNamhyung Kim { 43129ed6e76SArnaldo Carvalho de Melo struct disasm_line *dl; 432887c0066SArnaldo Carvalho de Melo struct browser_disasm_line *bdl; 433aca7a94dSNamhyung Kim off_t offset = browser->b.index - browser->b.top_idx; 434aca7a94dSNamhyung Kim 435aca7a94dSNamhyung Kim browser->b.seek(&browser->b, offset, SEEK_CUR); 43629ed6e76SArnaldo Carvalho de Melo dl = list_entry(browser->b.top, struct disasm_line, node); 437887c0066SArnaldo Carvalho de Melo bdl = disasm_line__browser(dl); 438aca7a94dSNamhyung Kim 439e9823b21SArnaldo Carvalho de Melo if (annotate_browser__opts.hide_src_code) { 440887c0066SArnaldo Carvalho de Melo if (bdl->idx_asm < offset) 441887c0066SArnaldo Carvalho de Melo offset = bdl->idx; 442aca7a94dSNamhyung Kim 443aca7a94dSNamhyung Kim browser->b.nr_entries = browser->nr_entries; 444e9823b21SArnaldo Carvalho de Melo annotate_browser__opts.hide_src_code = false; 445aca7a94dSNamhyung Kim browser->b.seek(&browser->b, -offset, SEEK_CUR); 446887c0066SArnaldo Carvalho de Melo browser->b.top_idx = bdl->idx - offset; 447887c0066SArnaldo Carvalho de Melo browser->b.index = bdl->idx; 448aca7a94dSNamhyung Kim } else { 449887c0066SArnaldo Carvalho de Melo if (bdl->idx_asm < 0) { 450aca7a94dSNamhyung Kim ui_helpline__puts("Only available for assembly lines."); 451aca7a94dSNamhyung Kim browser->b.seek(&browser->b, -offset, SEEK_CUR); 452aca7a94dSNamhyung Kim return false; 453aca7a94dSNamhyung Kim } 454aca7a94dSNamhyung Kim 455887c0066SArnaldo Carvalho de Melo if (bdl->idx_asm < offset) 456887c0066SArnaldo Carvalho de Melo offset = bdl->idx_asm; 457aca7a94dSNamhyung Kim 458aca7a94dSNamhyung Kim browser->b.nr_entries = browser->nr_asm_entries; 459e9823b21SArnaldo Carvalho de Melo annotate_browser__opts.hide_src_code = true; 460aca7a94dSNamhyung Kim browser->b.seek(&browser->b, -offset, SEEK_CUR); 461887c0066SArnaldo Carvalho de Melo browser->b.top_idx = bdl->idx_asm - offset; 462887c0066SArnaldo Carvalho de Melo browser->b.index = bdl->idx_asm; 463aca7a94dSNamhyung Kim } 464aca7a94dSNamhyung Kim 465aca7a94dSNamhyung Kim return true; 466aca7a94dSNamhyung Kim } 467aca7a94dSNamhyung Kim 468e9823b21SArnaldo Carvalho de Melo static void annotate_browser__init_asm_mode(struct annotate_browser *browser) 469e9823b21SArnaldo Carvalho de Melo { 470e9823b21SArnaldo Carvalho de Melo ui_browser__reset_index(&browser->b); 471e9823b21SArnaldo Carvalho de Melo browser->b.nr_entries = browser->nr_asm_entries; 472e9823b21SArnaldo Carvalho de Melo } 473e9823b21SArnaldo Carvalho de Melo 47434f77abcSAdrian Hunter #define SYM_TITLE_MAX_SIZE (PATH_MAX + 64) 47534f77abcSAdrian Hunter 47634f77abcSAdrian Hunter static int sym_title(struct symbol *sym, struct map *map, char *title, 47734f77abcSAdrian Hunter size_t sz) 47834f77abcSAdrian Hunter { 47934f77abcSAdrian Hunter return snprintf(title, sz, "%s %s", sym->name, map->dso->long_name); 48034f77abcSAdrian Hunter } 48134f77abcSAdrian Hunter 482db8fd07aSNamhyung Kim static bool annotate_browser__callq(struct annotate_browser *browser, 483db8fd07aSNamhyung Kim struct perf_evsel *evsel, 4849783adf7SNamhyung Kim struct hist_browser_timer *hbt) 485aca7a94dSNamhyung Kim { 486aca7a94dSNamhyung Kim struct map_symbol *ms = browser->b.priv; 487657bcaf5SArnaldo Carvalho de Melo struct disasm_line *dl = browser->selection; 488aca7a94dSNamhyung Kim struct annotation *notes; 4891179e11bSAdrian Hunter struct addr_map_symbol target = { 4901179e11bSAdrian Hunter .map = ms->map, 4911d5077bdSAdrian Hunter .addr = map__objdump_2mem(ms->map, dl->ops.target.addr), 4921179e11bSAdrian Hunter }; 49334f77abcSAdrian Hunter char title[SYM_TITLE_MAX_SIZE]; 494aca7a94dSNamhyung Kim 495d86b0597SArnaldo Carvalho de Melo if (!ins__is_call(dl->ins)) 496aca7a94dSNamhyung Kim return false; 497aca7a94dSNamhyung Kim 4981d5077bdSAdrian Hunter if (map_groups__find_ams(&target, NULL) || 4991d5077bdSAdrian Hunter map__rip_2objdump(target.map, target.map->map_ip(target.map, 5001d5077bdSAdrian Hunter target.addr)) != 5011d5077bdSAdrian Hunter dl->ops.target.addr) { 502aca7a94dSNamhyung Kim ui_helpline__puts("The called function was not found."); 503aca7a94dSNamhyung Kim return true; 504aca7a94dSNamhyung Kim } 505aca7a94dSNamhyung Kim 5061179e11bSAdrian Hunter notes = symbol__annotation(target.sym); 507aca7a94dSNamhyung Kim pthread_mutex_lock(¬es->lock); 508aca7a94dSNamhyung Kim 5091179e11bSAdrian Hunter if (notes->src == NULL && symbol__alloc_hist(target.sym) < 0) { 510aca7a94dSNamhyung Kim pthread_mutex_unlock(¬es->lock); 511aca7a94dSNamhyung Kim ui__warning("Not enough memory for annotating '%s' symbol!\n", 5121179e11bSAdrian Hunter target.sym->name); 513aca7a94dSNamhyung Kim return true; 514aca7a94dSNamhyung Kim } 515aca7a94dSNamhyung Kim 516aca7a94dSNamhyung Kim pthread_mutex_unlock(¬es->lock); 5171179e11bSAdrian Hunter symbol__tui_annotate(target.sym, target.map, evsel, hbt); 5181179e11bSAdrian Hunter sym_title(ms->sym, ms->map, title, sizeof(title)); 51934f77abcSAdrian Hunter ui_browser__show_title(&browser->b, title); 520aca7a94dSNamhyung Kim return true; 521aca7a94dSNamhyung Kim } 522aca7a94dSNamhyung Kim 52329ed6e76SArnaldo Carvalho de Melo static 52429ed6e76SArnaldo Carvalho de Melo struct disasm_line *annotate_browser__find_offset(struct annotate_browser *browser, 525aca7a94dSNamhyung Kim s64 offset, s64 *idx) 526aca7a94dSNamhyung Kim { 527aca7a94dSNamhyung Kim struct map_symbol *ms = browser->b.priv; 528aca7a94dSNamhyung Kim struct symbol *sym = ms->sym; 529aca7a94dSNamhyung Kim struct annotation *notes = symbol__annotation(sym); 53029ed6e76SArnaldo Carvalho de Melo struct disasm_line *pos; 531aca7a94dSNamhyung Kim 532aca7a94dSNamhyung Kim *idx = 0; 533aca7a94dSNamhyung Kim list_for_each_entry(pos, ¬es->src->source, node) { 534aca7a94dSNamhyung Kim if (pos->offset == offset) 535aca7a94dSNamhyung Kim return pos; 53629ed6e76SArnaldo Carvalho de Melo if (!disasm_line__filter(&browser->b, &pos->node)) 537aca7a94dSNamhyung Kim ++*idx; 538aca7a94dSNamhyung Kim } 539aca7a94dSNamhyung Kim 540aca7a94dSNamhyung Kim return NULL; 541aca7a94dSNamhyung Kim } 542aca7a94dSNamhyung Kim 543aca7a94dSNamhyung Kim static bool annotate_browser__jump(struct annotate_browser *browser) 544aca7a94dSNamhyung Kim { 545657bcaf5SArnaldo Carvalho de Melo struct disasm_line *dl = browser->selection; 5464f9d0325SArnaldo Carvalho de Melo s64 idx; 547aca7a94dSNamhyung Kim 548d86b0597SArnaldo Carvalho de Melo if (!ins__is_jump(dl->ins)) 549aca7a94dSNamhyung Kim return false; 550aca7a94dSNamhyung Kim 55144d1a3edSArnaldo Carvalho de Melo dl = annotate_browser__find_offset(browser, dl->ops.target.offset, &idx); 55229ed6e76SArnaldo Carvalho de Melo if (dl == NULL) { 553e6f65388SIngo Molnar ui_helpline__puts("Invalid jump offset"); 554aca7a94dSNamhyung Kim return true; 555aca7a94dSNamhyung Kim } 556aca7a94dSNamhyung Kim 55729ed6e76SArnaldo Carvalho de Melo annotate_browser__set_top(browser, dl, idx); 558aca7a94dSNamhyung Kim 559aca7a94dSNamhyung Kim return true; 560aca7a94dSNamhyung Kim } 561aca7a94dSNamhyung Kim 56229ed6e76SArnaldo Carvalho de Melo static 56329ed6e76SArnaldo Carvalho de Melo struct disasm_line *annotate_browser__find_string(struct annotate_browser *browser, 564aca7a94dSNamhyung Kim char *s, s64 *idx) 565aca7a94dSNamhyung Kim { 566aca7a94dSNamhyung Kim struct map_symbol *ms = browser->b.priv; 567aca7a94dSNamhyung Kim struct symbol *sym = ms->sym; 568aca7a94dSNamhyung Kim struct annotation *notes = symbol__annotation(sym); 56929ed6e76SArnaldo Carvalho de Melo struct disasm_line *pos = browser->selection; 570aca7a94dSNamhyung Kim 571aca7a94dSNamhyung Kim *idx = browser->b.index; 572aca7a94dSNamhyung Kim list_for_each_entry_continue(pos, ¬es->src->source, node) { 57329ed6e76SArnaldo Carvalho de Melo if (disasm_line__filter(&browser->b, &pos->node)) 574aca7a94dSNamhyung Kim continue; 575aca7a94dSNamhyung Kim 576aca7a94dSNamhyung Kim ++*idx; 577aca7a94dSNamhyung Kim 578aca7a94dSNamhyung Kim if (pos->line && strstr(pos->line, s) != NULL) 579aca7a94dSNamhyung Kim return pos; 580aca7a94dSNamhyung Kim } 581aca7a94dSNamhyung Kim 582aca7a94dSNamhyung Kim return NULL; 583aca7a94dSNamhyung Kim } 584aca7a94dSNamhyung Kim 585aca7a94dSNamhyung Kim static bool __annotate_browser__search(struct annotate_browser *browser) 586aca7a94dSNamhyung Kim { 58729ed6e76SArnaldo Carvalho de Melo struct disasm_line *dl; 588aca7a94dSNamhyung Kim s64 idx; 589aca7a94dSNamhyung Kim 59029ed6e76SArnaldo Carvalho de Melo dl = annotate_browser__find_string(browser, browser->search_bf, &idx); 59129ed6e76SArnaldo Carvalho de Melo if (dl == NULL) { 592aca7a94dSNamhyung Kim ui_helpline__puts("String not found!"); 593aca7a94dSNamhyung Kim return false; 594aca7a94dSNamhyung Kim } 595aca7a94dSNamhyung Kim 59629ed6e76SArnaldo Carvalho de Melo annotate_browser__set_top(browser, dl, idx); 597aca7a94dSNamhyung Kim browser->searching_backwards = false; 598aca7a94dSNamhyung Kim return true; 599aca7a94dSNamhyung Kim } 600aca7a94dSNamhyung Kim 60129ed6e76SArnaldo Carvalho de Melo static 60229ed6e76SArnaldo Carvalho de Melo struct disasm_line *annotate_browser__find_string_reverse(struct annotate_browser *browser, 603aca7a94dSNamhyung Kim char *s, s64 *idx) 604aca7a94dSNamhyung Kim { 605aca7a94dSNamhyung Kim struct map_symbol *ms = browser->b.priv; 606aca7a94dSNamhyung Kim struct symbol *sym = ms->sym; 607aca7a94dSNamhyung Kim struct annotation *notes = symbol__annotation(sym); 60829ed6e76SArnaldo Carvalho de Melo struct disasm_line *pos = browser->selection; 609aca7a94dSNamhyung Kim 610aca7a94dSNamhyung Kim *idx = browser->b.index; 611aca7a94dSNamhyung Kim list_for_each_entry_continue_reverse(pos, ¬es->src->source, node) { 61229ed6e76SArnaldo Carvalho de Melo if (disasm_line__filter(&browser->b, &pos->node)) 613aca7a94dSNamhyung Kim continue; 614aca7a94dSNamhyung Kim 615aca7a94dSNamhyung Kim --*idx; 616aca7a94dSNamhyung Kim 617aca7a94dSNamhyung Kim if (pos->line && strstr(pos->line, s) != NULL) 618aca7a94dSNamhyung Kim return pos; 619aca7a94dSNamhyung Kim } 620aca7a94dSNamhyung Kim 621aca7a94dSNamhyung Kim return NULL; 622aca7a94dSNamhyung Kim } 623aca7a94dSNamhyung Kim 624aca7a94dSNamhyung Kim static bool __annotate_browser__search_reverse(struct annotate_browser *browser) 625aca7a94dSNamhyung Kim { 62629ed6e76SArnaldo Carvalho de Melo struct disasm_line *dl; 627aca7a94dSNamhyung Kim s64 idx; 628aca7a94dSNamhyung Kim 62929ed6e76SArnaldo Carvalho de Melo dl = annotate_browser__find_string_reverse(browser, browser->search_bf, &idx); 63029ed6e76SArnaldo Carvalho de Melo if (dl == NULL) { 631aca7a94dSNamhyung Kim ui_helpline__puts("String not found!"); 632aca7a94dSNamhyung Kim return false; 633aca7a94dSNamhyung Kim } 634aca7a94dSNamhyung Kim 63529ed6e76SArnaldo Carvalho de Melo annotate_browser__set_top(browser, dl, idx); 636aca7a94dSNamhyung Kim browser->searching_backwards = true; 637aca7a94dSNamhyung Kim return true; 638aca7a94dSNamhyung Kim } 639aca7a94dSNamhyung Kim 640aca7a94dSNamhyung Kim static bool annotate_browser__search_window(struct annotate_browser *browser, 641aca7a94dSNamhyung Kim int delay_secs) 642aca7a94dSNamhyung Kim { 643aca7a94dSNamhyung Kim if (ui_browser__input_window("Search", "String: ", browser->search_bf, 644aca7a94dSNamhyung Kim "ENTER: OK, ESC: Cancel", 645aca7a94dSNamhyung Kim delay_secs * 2) != K_ENTER || 646aca7a94dSNamhyung Kim !*browser->search_bf) 647aca7a94dSNamhyung Kim return false; 648aca7a94dSNamhyung Kim 649aca7a94dSNamhyung Kim return true; 650aca7a94dSNamhyung Kim } 651aca7a94dSNamhyung Kim 652aca7a94dSNamhyung Kim static bool annotate_browser__search(struct annotate_browser *browser, int delay_secs) 653aca7a94dSNamhyung Kim { 654aca7a94dSNamhyung Kim if (annotate_browser__search_window(browser, delay_secs)) 655aca7a94dSNamhyung Kim return __annotate_browser__search(browser); 656aca7a94dSNamhyung Kim 657aca7a94dSNamhyung Kim return false; 658aca7a94dSNamhyung Kim } 659aca7a94dSNamhyung Kim 660aca7a94dSNamhyung Kim static bool annotate_browser__continue_search(struct annotate_browser *browser, 661aca7a94dSNamhyung Kim int delay_secs) 662aca7a94dSNamhyung Kim { 663aca7a94dSNamhyung Kim if (!*browser->search_bf) 664aca7a94dSNamhyung Kim return annotate_browser__search(browser, delay_secs); 665aca7a94dSNamhyung Kim 666aca7a94dSNamhyung Kim return __annotate_browser__search(browser); 667aca7a94dSNamhyung Kim } 668aca7a94dSNamhyung Kim 669aca7a94dSNamhyung Kim static bool annotate_browser__search_reverse(struct annotate_browser *browser, 670aca7a94dSNamhyung Kim int delay_secs) 671aca7a94dSNamhyung Kim { 672aca7a94dSNamhyung Kim if (annotate_browser__search_window(browser, delay_secs)) 673aca7a94dSNamhyung Kim return __annotate_browser__search_reverse(browser); 674aca7a94dSNamhyung Kim 675aca7a94dSNamhyung Kim return false; 676aca7a94dSNamhyung Kim } 677aca7a94dSNamhyung Kim 678aca7a94dSNamhyung Kim static 679aca7a94dSNamhyung Kim bool annotate_browser__continue_search_reverse(struct annotate_browser *browser, 680aca7a94dSNamhyung Kim int delay_secs) 681aca7a94dSNamhyung Kim { 682aca7a94dSNamhyung Kim if (!*browser->search_bf) 683aca7a94dSNamhyung Kim return annotate_browser__search_reverse(browser, delay_secs); 684aca7a94dSNamhyung Kim 685aca7a94dSNamhyung Kim return __annotate_browser__search_reverse(browser); 686aca7a94dSNamhyung Kim } 687aca7a94dSNamhyung Kim 688e9823b21SArnaldo Carvalho de Melo static void annotate_browser__update_addr_width(struct annotate_browser *browser) 689e9823b21SArnaldo Carvalho de Melo { 690e9823b21SArnaldo Carvalho de Melo if (annotate_browser__opts.use_offset) 691e9823b21SArnaldo Carvalho de Melo browser->target_width = browser->min_addr_width; 692e9823b21SArnaldo Carvalho de Melo else 693e9823b21SArnaldo Carvalho de Melo browser->target_width = browser->max_addr_width; 694e9823b21SArnaldo Carvalho de Melo 695e9823b21SArnaldo Carvalho de Melo browser->addr_width = browser->target_width; 696e9823b21SArnaldo Carvalho de Melo 697e9823b21SArnaldo Carvalho de Melo if (annotate_browser__opts.show_nr_jumps) 698e9823b21SArnaldo Carvalho de Melo browser->addr_width += browser->jumps_width + 1; 699e9823b21SArnaldo Carvalho de Melo } 700e9823b21SArnaldo Carvalho de Melo 701db8fd07aSNamhyung Kim static int annotate_browser__run(struct annotate_browser *browser, 702db8fd07aSNamhyung Kim struct perf_evsel *evsel, 7039783adf7SNamhyung Kim struct hist_browser_timer *hbt) 704aca7a94dSNamhyung Kim { 705aca7a94dSNamhyung Kim struct rb_node *nd = NULL; 70605e8b080SArnaldo Carvalho de Melo struct map_symbol *ms = browser->b.priv; 707aca7a94dSNamhyung Kim struct symbol *sym = ms->sym; 70854e7a4e8SArnaldo Carvalho de Melo const char *help = "Press 'h' for help on key bindings"; 7099783adf7SNamhyung Kim int delay_secs = hbt ? hbt->refresh : 0; 710aca7a94dSNamhyung Kim int key; 71134f77abcSAdrian Hunter char title[SYM_TITLE_MAX_SIZE]; 712aca7a94dSNamhyung Kim 71334f77abcSAdrian Hunter sym_title(sym, ms->map, title, sizeof(title)); 71434f77abcSAdrian Hunter if (ui_browser__show(&browser->b, title, help) < 0) 715aca7a94dSNamhyung Kim return -1; 716aca7a94dSNamhyung Kim 717db8fd07aSNamhyung Kim annotate_browser__calc_percent(browser, evsel); 718aca7a94dSNamhyung Kim 71905e8b080SArnaldo Carvalho de Melo if (browser->curr_hot) { 72005e8b080SArnaldo Carvalho de Melo annotate_browser__set_rb_top(browser, browser->curr_hot); 72105e8b080SArnaldo Carvalho de Melo browser->b.navkeypressed = false; 722aca7a94dSNamhyung Kim } 723aca7a94dSNamhyung Kim 72405e8b080SArnaldo Carvalho de Melo nd = browser->curr_hot; 725aca7a94dSNamhyung Kim 726aca7a94dSNamhyung Kim while (1) { 72705e8b080SArnaldo Carvalho de Melo key = ui_browser__run(&browser->b, delay_secs); 728aca7a94dSNamhyung Kim 729aca7a94dSNamhyung Kim if (delay_secs != 0) { 730db8fd07aSNamhyung Kim annotate_browser__calc_percent(browser, evsel); 731aca7a94dSNamhyung Kim /* 732aca7a94dSNamhyung Kim * Current line focus got out of the list of most active 733aca7a94dSNamhyung Kim * lines, NULL it so that if TAB|UNTAB is pressed, we 734aca7a94dSNamhyung Kim * move to curr_hot (current hottest line). 735aca7a94dSNamhyung Kim */ 736aca7a94dSNamhyung Kim if (nd != NULL && RB_EMPTY_NODE(nd)) 737aca7a94dSNamhyung Kim nd = NULL; 738aca7a94dSNamhyung Kim } 739aca7a94dSNamhyung Kim 740aca7a94dSNamhyung Kim switch (key) { 741aca7a94dSNamhyung Kim case K_TIMER: 7429783adf7SNamhyung Kim if (hbt) 7439783adf7SNamhyung Kim hbt->timer(hbt->arg); 744aca7a94dSNamhyung Kim 745aca7a94dSNamhyung Kim if (delay_secs != 0) 746db8fd07aSNamhyung Kim symbol__annotate_decay_histogram(sym, evsel->idx); 747aca7a94dSNamhyung Kim continue; 748aca7a94dSNamhyung Kim case K_TAB: 749aca7a94dSNamhyung Kim if (nd != NULL) { 750aca7a94dSNamhyung Kim nd = rb_prev(nd); 751aca7a94dSNamhyung Kim if (nd == NULL) 75205e8b080SArnaldo Carvalho de Melo nd = rb_last(&browser->entries); 753aca7a94dSNamhyung Kim } else 75405e8b080SArnaldo Carvalho de Melo nd = browser->curr_hot; 755aca7a94dSNamhyung Kim break; 756aca7a94dSNamhyung Kim case K_UNTAB: 757aca7a94dSNamhyung Kim if (nd != NULL) 758aca7a94dSNamhyung Kim nd = rb_next(nd); 759aca7a94dSNamhyung Kim if (nd == NULL) 76005e8b080SArnaldo Carvalho de Melo nd = rb_first(&browser->entries); 761aca7a94dSNamhyung Kim else 76205e8b080SArnaldo Carvalho de Melo nd = browser->curr_hot; 763aca7a94dSNamhyung Kim break; 76454e7a4e8SArnaldo Carvalho de Melo case K_F1: 765aca7a94dSNamhyung Kim case 'h': 76605e8b080SArnaldo Carvalho de Melo ui_browser__help_window(&browser->b, 76754e7a4e8SArnaldo Carvalho de Melo "UP/DOWN/PGUP\n" 76854e7a4e8SArnaldo Carvalho de Melo "PGDN/SPACE Navigate\n" 76954e7a4e8SArnaldo Carvalho de Melo "q/ESC/CTRL+C Exit\n\n" 77054e7a4e8SArnaldo Carvalho de Melo "-> Go to target\n" 77154e7a4e8SArnaldo Carvalho de Melo "<- Exit\n" 772107baecaSArnaldo Carvalho de Melo "H Cycle thru hottest instructions\n" 77354e7a4e8SArnaldo Carvalho de Melo "j Toggle showing jump to target arrows\n" 77454e7a4e8SArnaldo Carvalho de Melo "J Toggle showing number of jump sources on targets\n" 77554e7a4e8SArnaldo Carvalho de Melo "n Search next string\n" 77654e7a4e8SArnaldo Carvalho de Melo "o Toggle disassembler output/simplified view\n" 77754e7a4e8SArnaldo Carvalho de Melo "s Toggle source code view\n" 7780c4a5bceSMartin Liška "t Toggle total period view\n" 77954e7a4e8SArnaldo Carvalho de Melo "/ Search string\n" 780e592488cSAndi Kleen "k Toggle line numbers\n" 78179ee47faSFeng Tang "r Run available scripts\n" 782fcd9fef9SArnaldo Carvalho de Melo "? Search string backwards\n"); 78354e7a4e8SArnaldo Carvalho de Melo continue; 78479ee47faSFeng Tang case 'r': 78579ee47faSFeng Tang { 78679ee47faSFeng Tang script_browse(NULL); 78779ee47faSFeng Tang continue; 78879ee47faSFeng Tang } 789e592488cSAndi Kleen case 'k': 790e592488cSAndi Kleen annotate_browser__opts.show_linenr = 791e592488cSAndi Kleen !annotate_browser__opts.show_linenr; 792e592488cSAndi Kleen break; 79354e7a4e8SArnaldo Carvalho de Melo case 'H': 79405e8b080SArnaldo Carvalho de Melo nd = browser->curr_hot; 795aca7a94dSNamhyung Kim break; 796aca7a94dSNamhyung Kim case 's': 79705e8b080SArnaldo Carvalho de Melo if (annotate_browser__toggle_source(browser)) 798aca7a94dSNamhyung Kim ui_helpline__puts(help); 799aca7a94dSNamhyung Kim continue; 800aca7a94dSNamhyung Kim case 'o': 801e9823b21SArnaldo Carvalho de Melo annotate_browser__opts.use_offset = !annotate_browser__opts.use_offset; 80205e8b080SArnaldo Carvalho de Melo annotate_browser__update_addr_width(browser); 803aca7a94dSNamhyung Kim continue; 8049d1ef56dSArnaldo Carvalho de Melo case 'j': 805e9823b21SArnaldo Carvalho de Melo annotate_browser__opts.jump_arrows = !annotate_browser__opts.jump_arrows; 8069d1ef56dSArnaldo Carvalho de Melo continue; 8072402e4a9SArnaldo Carvalho de Melo case 'J': 808e9823b21SArnaldo Carvalho de Melo annotate_browser__opts.show_nr_jumps = !annotate_browser__opts.show_nr_jumps; 80905e8b080SArnaldo Carvalho de Melo annotate_browser__update_addr_width(browser); 810e9823b21SArnaldo Carvalho de Melo continue; 811aca7a94dSNamhyung Kim case '/': 81205e8b080SArnaldo Carvalho de Melo if (annotate_browser__search(browser, delay_secs)) { 813aca7a94dSNamhyung Kim show_help: 814aca7a94dSNamhyung Kim ui_helpline__puts(help); 815aca7a94dSNamhyung Kim } 816aca7a94dSNamhyung Kim continue; 817aca7a94dSNamhyung Kim case 'n': 81805e8b080SArnaldo Carvalho de Melo if (browser->searching_backwards ? 81905e8b080SArnaldo Carvalho de Melo annotate_browser__continue_search_reverse(browser, delay_secs) : 82005e8b080SArnaldo Carvalho de Melo annotate_browser__continue_search(browser, delay_secs)) 821aca7a94dSNamhyung Kim goto show_help; 822aca7a94dSNamhyung Kim continue; 823aca7a94dSNamhyung Kim case '?': 82405e8b080SArnaldo Carvalho de Melo if (annotate_browser__search_reverse(browser, delay_secs)) 825aca7a94dSNamhyung Kim goto show_help; 826aca7a94dSNamhyung Kim continue; 827e9823b21SArnaldo Carvalho de Melo case 'D': { 828e9823b21SArnaldo Carvalho de Melo static int seq; 829e9823b21SArnaldo Carvalho de Melo ui_helpline__pop(); 830e9823b21SArnaldo Carvalho de Melo ui_helpline__fpush("%d: nr_ent=%d, height=%d, idx=%d, top_idx=%d, nr_asm_entries=%d", 83105e8b080SArnaldo Carvalho de Melo seq++, browser->b.nr_entries, 83205e8b080SArnaldo Carvalho de Melo browser->b.height, 83305e8b080SArnaldo Carvalho de Melo browser->b.index, 83405e8b080SArnaldo Carvalho de Melo browser->b.top_idx, 83505e8b080SArnaldo Carvalho de Melo browser->nr_asm_entries); 836e9823b21SArnaldo Carvalho de Melo } 837e9823b21SArnaldo Carvalho de Melo continue; 838aca7a94dSNamhyung Kim case K_ENTER: 839aca7a94dSNamhyung Kim case K_RIGHT: 84005e8b080SArnaldo Carvalho de Melo if (browser->selection == NULL) 841aca7a94dSNamhyung Kim ui_helpline__puts("Huh? No selection. Report to linux-kernel@vger.kernel.org"); 84205e8b080SArnaldo Carvalho de Melo else if (browser->selection->offset == -1) 843aca7a94dSNamhyung Kim ui_helpline__puts("Actions are only available for assembly lines."); 84405e8b080SArnaldo Carvalho de Melo else if (!browser->selection->ins) { 84505e8b080SArnaldo Carvalho de Melo if (strcmp(browser->selection->name, "retq")) 846c4cceae3SArnaldo Carvalho de Melo goto show_sup_ins; 847c4cceae3SArnaldo Carvalho de Melo goto out; 84805e8b080SArnaldo Carvalho de Melo } else if (!(annotate_browser__jump(browser) || 849db8fd07aSNamhyung Kim annotate_browser__callq(browser, evsel, hbt))) { 850c4cceae3SArnaldo Carvalho de Melo show_sup_ins: 851c4cceae3SArnaldo Carvalho de Melo ui_helpline__puts("Actions are only available for 'callq', 'retq' & jump instructions."); 852c4cceae3SArnaldo Carvalho de Melo } 853aca7a94dSNamhyung Kim continue; 8540c4a5bceSMartin Liška case 't': 8550c4a5bceSMartin Liška annotate_browser__opts.show_total_period = 8560c4a5bceSMartin Liška !annotate_browser__opts.show_total_period; 8570c4a5bceSMartin Liška annotate_browser__update_addr_width(browser); 8580c4a5bceSMartin Liška continue; 859aca7a94dSNamhyung Kim case K_LEFT: 860aca7a94dSNamhyung Kim case K_ESC: 861aca7a94dSNamhyung Kim case 'q': 862aca7a94dSNamhyung Kim case CTRL('c'): 863aca7a94dSNamhyung Kim goto out; 864aca7a94dSNamhyung Kim default: 865aca7a94dSNamhyung Kim continue; 866aca7a94dSNamhyung Kim } 867aca7a94dSNamhyung Kim 868aca7a94dSNamhyung Kim if (nd != NULL) 86905e8b080SArnaldo Carvalho de Melo annotate_browser__set_rb_top(browser, nd); 870aca7a94dSNamhyung Kim } 871aca7a94dSNamhyung Kim out: 87205e8b080SArnaldo Carvalho de Melo ui_browser__hide(&browser->b); 873aca7a94dSNamhyung Kim return key; 874aca7a94dSNamhyung Kim } 875aca7a94dSNamhyung Kim 876d5dbc518SArnaldo Carvalho de Melo int map_symbol__tui_annotate(struct map_symbol *ms, struct perf_evsel *evsel, 877d5dbc518SArnaldo Carvalho de Melo struct hist_browser_timer *hbt) 878d5dbc518SArnaldo Carvalho de Melo { 8790c4a5bceSMartin Liška /* Set default value for show_total_period. */ 8800c4a5bceSMartin Liška annotate_browser__opts.show_total_period = 8810c4a5bceSMartin Liška symbol_conf.show_total_period; 8820c4a5bceSMartin Liška 883d5dbc518SArnaldo Carvalho de Melo return symbol__tui_annotate(ms->sym, ms->map, evsel, hbt); 884d5dbc518SArnaldo Carvalho de Melo } 885d5dbc518SArnaldo Carvalho de Melo 886db8fd07aSNamhyung Kim int hist_entry__tui_annotate(struct hist_entry *he, struct perf_evsel *evsel, 8879783adf7SNamhyung Kim struct hist_browser_timer *hbt) 888aca7a94dSNamhyung Kim { 889ed426915SNamhyung Kim /* reset abort key so that it can get Ctrl-C as a key */ 890ed426915SNamhyung Kim SLang_reset_tty(); 891ed426915SNamhyung Kim SLang_init_tty(0, 0, 0); 892ed426915SNamhyung Kim 893d5dbc518SArnaldo Carvalho de Melo return map_symbol__tui_annotate(&he->ms, evsel, hbt); 894aca7a94dSNamhyung Kim } 895aca7a94dSNamhyung Kim 89630e863bbSAndi Kleen 89730e863bbSAndi Kleen static unsigned count_insn(struct annotate_browser *browser, u64 start, u64 end) 89830e863bbSAndi Kleen { 89930e863bbSAndi Kleen unsigned n_insn = 0; 90030e863bbSAndi Kleen u64 offset; 90130e863bbSAndi Kleen 90230e863bbSAndi Kleen for (offset = start; offset <= end; offset++) { 90330e863bbSAndi Kleen if (browser->offsets[offset]) 90430e863bbSAndi Kleen n_insn++; 90530e863bbSAndi Kleen } 90630e863bbSAndi Kleen return n_insn; 90730e863bbSAndi Kleen } 90830e863bbSAndi Kleen 90930e863bbSAndi Kleen static void count_and_fill(struct annotate_browser *browser, u64 start, u64 end, 91030e863bbSAndi Kleen struct cyc_hist *ch) 91130e863bbSAndi Kleen { 91230e863bbSAndi Kleen unsigned n_insn; 91330e863bbSAndi Kleen u64 offset; 91430e863bbSAndi Kleen 91530e863bbSAndi Kleen n_insn = count_insn(browser, start, end); 91630e863bbSAndi Kleen if (n_insn && ch->num && ch->cycles) { 91730e863bbSAndi Kleen float ipc = n_insn / ((double)ch->cycles / (double)ch->num); 91830e863bbSAndi Kleen 91930e863bbSAndi Kleen /* Hide data when there are too many overlaps. */ 92030e863bbSAndi Kleen if (ch->reset >= 0x7fff || ch->reset >= ch->num / 2) 92130e863bbSAndi Kleen return; 92230e863bbSAndi Kleen 92330e863bbSAndi Kleen for (offset = start; offset <= end; offset++) { 92430e863bbSAndi Kleen struct disasm_line *dl = browser->offsets[offset]; 92530e863bbSAndi Kleen 92630e863bbSAndi Kleen if (dl) 92730e863bbSAndi Kleen dl->ipc = ipc; 92830e863bbSAndi Kleen } 92930e863bbSAndi Kleen } 93030e863bbSAndi Kleen } 93130e863bbSAndi Kleen 93230e863bbSAndi Kleen /* 93330e863bbSAndi Kleen * This should probably be in util/annotate.c to share with the tty 93430e863bbSAndi Kleen * annotate, but right now we need the per byte offsets arrays, 93530e863bbSAndi Kleen * which are only here. 93630e863bbSAndi Kleen */ 93730e863bbSAndi Kleen static void annotate__compute_ipc(struct annotate_browser *browser, size_t size, 93830e863bbSAndi Kleen struct symbol *sym) 93930e863bbSAndi Kleen { 94030e863bbSAndi Kleen u64 offset; 94130e863bbSAndi Kleen struct annotation *notes = symbol__annotation(sym); 94230e863bbSAndi Kleen 94330e863bbSAndi Kleen if (!notes->src || !notes->src->cycles_hist) 94430e863bbSAndi Kleen return; 94530e863bbSAndi Kleen 94630e863bbSAndi Kleen pthread_mutex_lock(¬es->lock); 94730e863bbSAndi Kleen for (offset = 0; offset < size; ++offset) { 94830e863bbSAndi Kleen struct cyc_hist *ch; 94930e863bbSAndi Kleen 95030e863bbSAndi Kleen ch = ¬es->src->cycles_hist[offset]; 95130e863bbSAndi Kleen if (ch && ch->cycles) { 95230e863bbSAndi Kleen struct disasm_line *dl; 95330e863bbSAndi Kleen 95430e863bbSAndi Kleen if (ch->have_start) 95530e863bbSAndi Kleen count_and_fill(browser, ch->start, offset, ch); 95630e863bbSAndi Kleen dl = browser->offsets[offset]; 95730e863bbSAndi Kleen if (dl && ch->num_aggr) 95830e863bbSAndi Kleen dl->cycles = ch->cycles_aggr / ch->num_aggr; 95930e863bbSAndi Kleen browser->have_cycles = true; 96030e863bbSAndi Kleen } 96130e863bbSAndi Kleen } 96230e863bbSAndi Kleen pthread_mutex_unlock(¬es->lock); 96330e863bbSAndi Kleen } 96430e863bbSAndi Kleen 965b793a401SArnaldo Carvalho de Melo static void annotate_browser__mark_jump_targets(struct annotate_browser *browser, 966b793a401SArnaldo Carvalho de Melo size_t size) 967b793a401SArnaldo Carvalho de Melo { 968b793a401SArnaldo Carvalho de Melo u64 offset; 96932ae1efdSNamhyung Kim struct map_symbol *ms = browser->b.priv; 97032ae1efdSNamhyung Kim struct symbol *sym = ms->sym; 97132ae1efdSNamhyung Kim 97232ae1efdSNamhyung Kim /* PLT symbols contain external offsets */ 97332ae1efdSNamhyung Kim if (strstr(sym->name, "@plt")) 97432ae1efdSNamhyung Kim return; 975b793a401SArnaldo Carvalho de Melo 976b793a401SArnaldo Carvalho de Melo for (offset = 0; offset < size; ++offset) { 977b793a401SArnaldo Carvalho de Melo struct disasm_line *dl = browser->offsets[offset], *dlt; 978b793a401SArnaldo Carvalho de Melo struct browser_disasm_line *bdlt; 979b793a401SArnaldo Carvalho de Melo 980865c66c4SFrederik Deweerdt if (!disasm_line__is_valid_jump(dl, sym)) 981b793a401SArnaldo Carvalho de Melo continue; 982b793a401SArnaldo Carvalho de Melo 98344d1a3edSArnaldo Carvalho de Melo dlt = browser->offsets[dl->ops.target.offset]; 9849481ede9SArnaldo Carvalho de Melo /* 9859481ede9SArnaldo Carvalho de Melo * FIXME: Oops, no jump target? Buggy disassembler? Or do we 9869481ede9SArnaldo Carvalho de Melo * have to adjust to the previous offset? 9879481ede9SArnaldo Carvalho de Melo */ 9889481ede9SArnaldo Carvalho de Melo if (dlt == NULL) 9899481ede9SArnaldo Carvalho de Melo continue; 9909481ede9SArnaldo Carvalho de Melo 991b793a401SArnaldo Carvalho de Melo bdlt = disasm_line__browser(dlt); 9922402e4a9SArnaldo Carvalho de Melo if (++bdlt->jump_sources > browser->max_jump_sources) 9932402e4a9SArnaldo Carvalho de Melo browser->max_jump_sources = bdlt->jump_sources; 9942402e4a9SArnaldo Carvalho de Melo 9952402e4a9SArnaldo Carvalho de Melo ++browser->nr_jumps; 996b793a401SArnaldo Carvalho de Melo } 997b793a401SArnaldo Carvalho de Melo } 998b793a401SArnaldo Carvalho de Melo 9992402e4a9SArnaldo Carvalho de Melo static inline int width_jumps(int n) 10002402e4a9SArnaldo Carvalho de Melo { 10012402e4a9SArnaldo Carvalho de Melo if (n >= 100) 10022402e4a9SArnaldo Carvalho de Melo return 5; 10032402e4a9SArnaldo Carvalho de Melo if (n / 10) 10042402e4a9SArnaldo Carvalho de Melo return 2; 10052402e4a9SArnaldo Carvalho de Melo return 1; 10062402e4a9SArnaldo Carvalho de Melo } 10072402e4a9SArnaldo Carvalho de Melo 1008db8fd07aSNamhyung Kim int symbol__tui_annotate(struct symbol *sym, struct map *map, 1009db8fd07aSNamhyung Kim struct perf_evsel *evsel, 10109783adf7SNamhyung Kim struct hist_browser_timer *hbt) 1011aca7a94dSNamhyung Kim { 101229ed6e76SArnaldo Carvalho de Melo struct disasm_line *pos, *n; 1013aca7a94dSNamhyung Kim struct annotation *notes; 1014c0a58fb2SSamuel Liao size_t size; 1015aca7a94dSNamhyung Kim struct map_symbol ms = { 1016aca7a94dSNamhyung Kim .map = map, 1017aca7a94dSNamhyung Kim .sym = sym, 1018aca7a94dSNamhyung Kim }; 1019aca7a94dSNamhyung Kim struct annotate_browser browser = { 1020aca7a94dSNamhyung Kim .b = { 1021a3f895beSArnaldo Carvalho de Melo .refresh = annotate_browser__refresh, 1022aca7a94dSNamhyung Kim .seek = ui_browser__list_head_seek, 1023aca7a94dSNamhyung Kim .write = annotate_browser__write, 102429ed6e76SArnaldo Carvalho de Melo .filter = disasm_line__filter, 1025aca7a94dSNamhyung Kim .priv = &ms, 1026aca7a94dSNamhyung Kim .use_navkeypressed = true, 1027aca7a94dSNamhyung Kim }, 1028aca7a94dSNamhyung Kim }; 1029b793a401SArnaldo Carvalho de Melo int ret = -1; 1030c7e7b610SNamhyung Kim int nr_pcnt = 1; 1031c7e7b610SNamhyung Kim size_t sizeof_bdl = sizeof(struct browser_disasm_line); 1032aca7a94dSNamhyung Kim 1033aca7a94dSNamhyung Kim if (sym == NULL) 1034aca7a94dSNamhyung Kim return -1; 1035aca7a94dSNamhyung Kim 1036c0a58fb2SSamuel Liao size = symbol__size(sym); 1037c0a58fb2SSamuel Liao 1038aca7a94dSNamhyung Kim if (map->dso->annotate_warned) 1039aca7a94dSNamhyung Kim return -1; 1040aca7a94dSNamhyung Kim 1041b793a401SArnaldo Carvalho de Melo browser.offsets = zalloc(size * sizeof(struct disasm_line *)); 1042b793a401SArnaldo Carvalho de Melo if (browser.offsets == NULL) { 1043b793a401SArnaldo Carvalho de Melo ui__error("Not enough memory!"); 1044b793a401SArnaldo Carvalho de Melo return -1; 1045b793a401SArnaldo Carvalho de Melo } 1046b793a401SArnaldo Carvalho de Melo 1047c7e7b610SNamhyung Kim if (perf_evsel__is_group_event(evsel)) { 1048c7e7b610SNamhyung Kim nr_pcnt = evsel->nr_members; 10490c4a5bceSMartin Liška sizeof_bdl += sizeof(struct disasm_line_samples) * 10500c4a5bceSMartin Liška (nr_pcnt - 1); 1051c7e7b610SNamhyung Kim } 1052c7e7b610SNamhyung Kim 1053c7e7b610SNamhyung Kim if (symbol__annotate(sym, map, sizeof_bdl) < 0) { 1054aca7a94dSNamhyung Kim ui__error("%s", ui_helpline__last_msg); 1055b793a401SArnaldo Carvalho de Melo goto out_free_offsets; 1056aca7a94dSNamhyung Kim } 1057aca7a94dSNamhyung Kim 1058aca7a94dSNamhyung Kim ui_helpline__push("Press <- or ESC to exit"); 1059aca7a94dSNamhyung Kim 1060aca7a94dSNamhyung Kim notes = symbol__annotation(sym); 1061aca7a94dSNamhyung Kim browser.start = map__rip_2objdump(map, sym->start); 1062aca7a94dSNamhyung Kim 1063aca7a94dSNamhyung Kim list_for_each_entry(pos, ¬es->src->source, node) { 1064887c0066SArnaldo Carvalho de Melo struct browser_disasm_line *bpos; 1065aca7a94dSNamhyung Kim size_t line_len = strlen(pos->line); 1066aca7a94dSNamhyung Kim 1067aca7a94dSNamhyung Kim if (browser.b.width < line_len) 1068aca7a94dSNamhyung Kim browser.b.width = line_len; 1069887c0066SArnaldo Carvalho de Melo bpos = disasm_line__browser(pos); 1070887c0066SArnaldo Carvalho de Melo bpos->idx = browser.nr_entries++; 1071b793a401SArnaldo Carvalho de Melo if (pos->offset != -1) { 1072887c0066SArnaldo Carvalho de Melo bpos->idx_asm = browser.nr_asm_entries++; 107397148a97SArnaldo Carvalho de Melo /* 107497148a97SArnaldo Carvalho de Melo * FIXME: short term bandaid to cope with assembly 107597148a97SArnaldo Carvalho de Melo * routines that comes with labels in the same column 107697148a97SArnaldo Carvalho de Melo * as the address in objdump, sigh. 107797148a97SArnaldo Carvalho de Melo * 107897148a97SArnaldo Carvalho de Melo * E.g. copy_user_generic_unrolled 107997148a97SArnaldo Carvalho de Melo */ 108097148a97SArnaldo Carvalho de Melo if (pos->offset < (s64)size) 1081b793a401SArnaldo Carvalho de Melo browser.offsets[pos->offset] = pos; 1082b793a401SArnaldo Carvalho de Melo } else 1083887c0066SArnaldo Carvalho de Melo bpos->idx_asm = -1; 1084aca7a94dSNamhyung Kim } 1085aca7a94dSNamhyung Kim 1086b793a401SArnaldo Carvalho de Melo annotate_browser__mark_jump_targets(&browser, size); 108730e863bbSAndi Kleen annotate__compute_ipc(&browser, size, sym); 1088b793a401SArnaldo Carvalho de Melo 10892402e4a9SArnaldo Carvalho de Melo browser.addr_width = browser.target_width = browser.min_addr_width = hex_width(size); 109083b1f2aaSArnaldo Carvalho de Melo browser.max_addr_width = hex_width(sym->end); 10912402e4a9SArnaldo Carvalho de Melo browser.jumps_width = width_jumps(browser.max_jump_sources); 1092c7e7b610SNamhyung Kim browser.nr_events = nr_pcnt; 1093aca7a94dSNamhyung Kim browser.b.nr_entries = browser.nr_entries; 1094aca7a94dSNamhyung Kim browser.b.entries = ¬es->src->source, 1095aca7a94dSNamhyung Kim browser.b.width += 18; /* Percentage */ 1096e9823b21SArnaldo Carvalho de Melo 1097e9823b21SArnaldo Carvalho de Melo if (annotate_browser__opts.hide_src_code) 1098e9823b21SArnaldo Carvalho de Melo annotate_browser__init_asm_mode(&browser); 1099e9823b21SArnaldo Carvalho de Melo 1100e9823b21SArnaldo Carvalho de Melo annotate_browser__update_addr_width(&browser); 1101e9823b21SArnaldo Carvalho de Melo 1102db8fd07aSNamhyung Kim ret = annotate_browser__run(&browser, evsel, hbt); 1103aca7a94dSNamhyung Kim list_for_each_entry_safe(pos, n, ¬es->src->source, node) { 1104aca7a94dSNamhyung Kim list_del(&pos->node); 110529ed6e76SArnaldo Carvalho de Melo disasm_line__free(pos); 1106aca7a94dSNamhyung Kim } 1107b793a401SArnaldo Carvalho de Melo 1108b793a401SArnaldo Carvalho de Melo out_free_offsets: 1109b793a401SArnaldo Carvalho de Melo free(browser.offsets); 1110aca7a94dSNamhyung Kim return ret; 1111aca7a94dSNamhyung Kim } 1112c323cf04SArnaldo Carvalho de Melo 1113c323cf04SArnaldo Carvalho de Melo #define ANNOTATE_CFG(n) \ 1114c323cf04SArnaldo Carvalho de Melo { .name = #n, .value = &annotate_browser__opts.n, } 1115c323cf04SArnaldo Carvalho de Melo 1116c323cf04SArnaldo Carvalho de Melo /* 1117c323cf04SArnaldo Carvalho de Melo * Keep the entries sorted, they are bsearch'ed 1118c323cf04SArnaldo Carvalho de Melo */ 11197c3102b8SArnaldo Carvalho de Melo static struct annotate_config { 1120c323cf04SArnaldo Carvalho de Melo const char *name; 1121c323cf04SArnaldo Carvalho de Melo bool *value; 1122c323cf04SArnaldo Carvalho de Melo } annotate__configs[] = { 1123c323cf04SArnaldo Carvalho de Melo ANNOTATE_CFG(hide_src_code), 1124c323cf04SArnaldo Carvalho de Melo ANNOTATE_CFG(jump_arrows), 1125e592488cSAndi Kleen ANNOTATE_CFG(show_linenr), 1126c323cf04SArnaldo Carvalho de Melo ANNOTATE_CFG(show_nr_jumps), 1127c323cf04SArnaldo Carvalho de Melo ANNOTATE_CFG(use_offset), 11280c4a5bceSMartin Liška ANNOTATE_CFG(show_total_period), 1129c323cf04SArnaldo Carvalho de Melo }; 1130c323cf04SArnaldo Carvalho de Melo 1131c323cf04SArnaldo Carvalho de Melo #undef ANNOTATE_CFG 1132c323cf04SArnaldo Carvalho de Melo 1133c323cf04SArnaldo Carvalho de Melo static int annotate_config__cmp(const void *name, const void *cfgp) 1134c323cf04SArnaldo Carvalho de Melo { 11357c3102b8SArnaldo Carvalho de Melo const struct annotate_config *cfg = cfgp; 1136c323cf04SArnaldo Carvalho de Melo 1137c323cf04SArnaldo Carvalho de Melo return strcmp(name, cfg->name); 1138c323cf04SArnaldo Carvalho de Melo } 1139c323cf04SArnaldo Carvalho de Melo 11401d037ca1SIrina Tirdea static int annotate__config(const char *var, const char *value, 11411d037ca1SIrina Tirdea void *data __maybe_unused) 1142c323cf04SArnaldo Carvalho de Melo { 11437c3102b8SArnaldo Carvalho de Melo struct annotate_config *cfg; 1144c323cf04SArnaldo Carvalho de Melo const char *name; 1145c323cf04SArnaldo Carvalho de Melo 1146c323cf04SArnaldo Carvalho de Melo if (prefixcmp(var, "annotate.") != 0) 1147c323cf04SArnaldo Carvalho de Melo return 0; 1148c323cf04SArnaldo Carvalho de Melo 1149c323cf04SArnaldo Carvalho de Melo name = var + 9; 1150c323cf04SArnaldo Carvalho de Melo cfg = bsearch(name, annotate__configs, ARRAY_SIZE(annotate__configs), 11517c3102b8SArnaldo Carvalho de Melo sizeof(struct annotate_config), annotate_config__cmp); 1152c323cf04SArnaldo Carvalho de Melo 1153c323cf04SArnaldo Carvalho de Melo if (cfg == NULL) 1154c323cf04SArnaldo Carvalho de Melo return -1; 1155c323cf04SArnaldo Carvalho de Melo 1156c323cf04SArnaldo Carvalho de Melo *cfg->value = perf_config_bool(name, value); 1157c323cf04SArnaldo Carvalho de Melo return 0; 1158c323cf04SArnaldo Carvalho de Melo } 1159c323cf04SArnaldo Carvalho de Melo 1160c323cf04SArnaldo Carvalho de Melo void annotate_browser__init(void) 1161c323cf04SArnaldo Carvalho de Melo { 1162c323cf04SArnaldo Carvalho de Melo perf_config(annotate__config, NULL); 1163c323cf04SArnaldo Carvalho de Melo } 1164