1aca7a94dSNamhyung Kim #include "../../util/util.h" 2aca7a94dSNamhyung Kim #include "../browser.h" 3aca7a94dSNamhyung Kim #include "../helpline.h" 4aca7a94dSNamhyung Kim #include "../ui.h" 5aca7a94dSNamhyung Kim #include "../util.h" 6aca7a94dSNamhyung Kim #include "../../util/annotate.h" 7aca7a94dSNamhyung Kim #include "../../util/hist.h" 8aca7a94dSNamhyung Kim #include "../../util/sort.h" 9aca7a94dSNamhyung Kim #include "../../util/symbol.h" 10db8fd07aSNamhyung Kim #include "../../util/evsel.h" 11*41840d21STaeung Song #include "../../util/config.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 19f8f4aaeaSAndi Kleen #define IPC_WIDTH 6 20f8f4aaeaSAndi Kleen #define CYCLES_WIDTH 6 21f8f4aaeaSAndi 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 103f8f4aaeaSAndi Kleen static int annotate_browser__pcnt_width(struct annotate_browser *ab) 104f8f4aaeaSAndi Kleen { 105f8f4aaeaSAndi Kleen int w = 7 * ab->nr_events; 106f8f4aaeaSAndi Kleen 107f8f4aaeaSAndi Kleen if (ab->have_cycles) 108f8f4aaeaSAndi Kleen w += IPC_WIDTH + CYCLES_WIDTH; 109f8f4aaeaSAndi Kleen return w; 110f8f4aaeaSAndi Kleen } 111f8f4aaeaSAndi 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; 122f8f4aaeaSAndi 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) { 132f8f4aaeaSAndi 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); 137517dfdb3SArnaldo Carvalho de Melo if (annotate_browser__opts.show_total_period) { 138517dfdb3SArnaldo Carvalho de Melo ui_browser__printf(browser, "%6" PRIu64 " ", 1390c4a5bceSMartin Liška bdl->samples[i].nr); 140517dfdb3SArnaldo Carvalho de Melo } else { 141517dfdb3SArnaldo Carvalho de Melo ui_browser__printf(browser, "%6.2f ", 142517dfdb3SArnaldo Carvalho de Melo bdl->samples[i].percent); 143517dfdb3SArnaldo Carvalho de Melo } 144c7e7b610SNamhyung Kim } 145aca7a94dSNamhyung Kim } else { 14626270a00SArnaldo Carvalho de Melo ui_browser__write_nstring(browser, " ", 7 * ab->nr_events); 147f8f4aaeaSAndi Kleen } 148f8f4aaeaSAndi Kleen } else { 14905e8b080SArnaldo Carvalho de Melo ui_browser__set_percent_color(browser, 0, current_entry); 15026270a00SArnaldo Carvalho de Melo ui_browser__write_nstring(browser, " ", 7 * ab->nr_events); 151f8f4aaeaSAndi Kleen } 152f8f4aaeaSAndi Kleen if (ab->have_cycles) { 153f8f4aaeaSAndi Kleen if (dl->ipc) 154517dfdb3SArnaldo Carvalho de Melo ui_browser__printf(browser, "%*.2f ", IPC_WIDTH - 1, dl->ipc); 155f8f4aaeaSAndi Kleen else 15626270a00SArnaldo Carvalho de Melo ui_browser__write_nstring(browser, " ", IPC_WIDTH); 157f8f4aaeaSAndi Kleen if (dl->cycles) 158517dfdb3SArnaldo Carvalho de Melo ui_browser__printf(browser, "%*" PRIu64 " ", 159f8f4aaeaSAndi Kleen CYCLES_WIDTH - 1, dl->cycles); 160f8f4aaeaSAndi Kleen else 16126270a00SArnaldo Carvalho de Melo ui_browser__write_nstring(browser, " ", CYCLES_WIDTH); 162aca7a94dSNamhyung Kim } 163aca7a94dSNamhyung Kim 164cf2dacc5SArnaldo Carvalho de Melo SLsmg_write_char(' '); 165aca7a94dSNamhyung Kim 166aca7a94dSNamhyung Kim /* The scroll bar isn't being used */ 16705e8b080SArnaldo Carvalho de Melo if (!browser->navkeypressed) 168aca7a94dSNamhyung Kim width += 1; 169aca7a94dSNamhyung Kim 17029ed6e76SArnaldo Carvalho de Melo if (!*dl->line) 17126270a00SArnaldo Carvalho de Melo ui_browser__write_nstring(browser, " ", width - pcnt_width); 17283b1f2aaSArnaldo Carvalho de Melo else if (dl->offset == -1) { 173e592488cSAndi Kleen if (dl->line_nr && annotate_browser__opts.show_linenr) 174e592488cSAndi Kleen printed = scnprintf(bf, sizeof(bf), "%-*d ", 175e592488cSAndi Kleen ab->addr_width + 1, dl->line_nr); 176e592488cSAndi Kleen else 17783b1f2aaSArnaldo Carvalho de Melo printed = scnprintf(bf, sizeof(bf), "%*s ", 17883b1f2aaSArnaldo Carvalho de Melo ab->addr_width, " "); 17926270a00SArnaldo Carvalho de Melo ui_browser__write_nstring(browser, bf, printed); 18026270a00SArnaldo Carvalho de Melo ui_browser__write_nstring(browser, dl->line, width - printed - pcnt_width + 1); 18183b1f2aaSArnaldo Carvalho de Melo } else { 18229ed6e76SArnaldo Carvalho de Melo u64 addr = dl->offset; 18383b1f2aaSArnaldo Carvalho de Melo int color = -1; 184aca7a94dSNamhyung Kim 185e9823b21SArnaldo Carvalho de Melo if (!annotate_browser__opts.use_offset) 186aca7a94dSNamhyung Kim addr += ab->start; 187aca7a94dSNamhyung Kim 188e9823b21SArnaldo Carvalho de Melo if (!annotate_browser__opts.use_offset) { 189aca7a94dSNamhyung Kim printed = scnprintf(bf, sizeof(bf), "%" PRIx64 ": ", addr); 19061e04b33SArnaldo Carvalho de Melo } else { 1917d5b12f5SArnaldo Carvalho de Melo if (bdl->jump_sources) { 192e9823b21SArnaldo Carvalho de Melo if (annotate_browser__opts.show_nr_jumps) { 1932402e4a9SArnaldo Carvalho de Melo int prev; 1942402e4a9SArnaldo Carvalho de Melo printed = scnprintf(bf, sizeof(bf), "%*d ", 1952402e4a9SArnaldo Carvalho de Melo ab->jumps_width, 1962402e4a9SArnaldo Carvalho de Melo bdl->jump_sources); 1972402e4a9SArnaldo Carvalho de Melo prev = annotate_browser__set_jumps_percent_color(ab, bdl->jump_sources, 1982402e4a9SArnaldo Carvalho de Melo current_entry); 19926270a00SArnaldo Carvalho de Melo ui_browser__write_nstring(browser, bf, printed); 20005e8b080SArnaldo Carvalho de Melo ui_browser__set_color(browser, prev); 2012402e4a9SArnaldo Carvalho de Melo } 2022402e4a9SArnaldo Carvalho de Melo 20361e04b33SArnaldo Carvalho de Melo printed = scnprintf(bf, sizeof(bf), "%*" PRIx64 ": ", 2042402e4a9SArnaldo Carvalho de Melo ab->target_width, addr); 20561e04b33SArnaldo Carvalho de Melo } else { 20661e04b33SArnaldo Carvalho de Melo printed = scnprintf(bf, sizeof(bf), "%*s ", 20783b1f2aaSArnaldo Carvalho de Melo ab->addr_width, " "); 20861e04b33SArnaldo Carvalho de Melo } 20961e04b33SArnaldo Carvalho de Melo } 210b793a401SArnaldo Carvalho de Melo 211aca7a94dSNamhyung Kim if (change_color) 21205e8b080SArnaldo Carvalho de Melo color = ui_browser__set_color(browser, HE_COLORSET_ADDR); 21326270a00SArnaldo Carvalho de Melo ui_browser__write_nstring(browser, bf, printed); 214aca7a94dSNamhyung Kim if (change_color) 21505e8b080SArnaldo Carvalho de Melo ui_browser__set_color(browser, color); 21628548d78SArnaldo Carvalho de Melo if (dl->ins && dl->ins->ops->scnprintf) { 21751a0d455SArnaldo Carvalho de Melo if (ins__is_jump(dl->ins)) { 21844d1a3edSArnaldo Carvalho de Melo bool fwd = dl->ops.target.offset > (u64)dl->offset; 21951a0d455SArnaldo Carvalho de Melo 22005e8b080SArnaldo Carvalho de Melo ui_browser__write_graph(browser, fwd ? SLSMG_DARROW_CHAR : 22151a0d455SArnaldo Carvalho de Melo SLSMG_UARROW_CHAR); 22251a0d455SArnaldo Carvalho de Melo SLsmg_write_char(' '); 22388298f5aSArnaldo Carvalho de Melo } else if (ins__is_call(dl->ins)) { 22405e8b080SArnaldo Carvalho de Melo ui_browser__write_graph(browser, SLSMG_RARROW_CHAR); 22588298f5aSArnaldo Carvalho de Melo SLsmg_write_char(' '); 22651a0d455SArnaldo Carvalho de Melo } else { 22726270a00SArnaldo Carvalho de Melo ui_browser__write_nstring(browser, " ", 2); 22851a0d455SArnaldo Carvalho de Melo } 2294ea08b52SArnaldo Carvalho de Melo } else { 2304ea08b52SArnaldo Carvalho de Melo if (strcmp(dl->name, "retq")) { 23126270a00SArnaldo Carvalho de Melo ui_browser__write_nstring(browser, " ", 2); 2324ea08b52SArnaldo Carvalho de Melo } else { 23305e8b080SArnaldo Carvalho de Melo ui_browser__write_graph(browser, SLSMG_LARROW_CHAR); 2344ea08b52SArnaldo Carvalho de Melo SLsmg_write_char(' '); 2354ea08b52SArnaldo Carvalho de Melo } 2364ea08b52SArnaldo Carvalho de Melo } 2374ea08b52SArnaldo Carvalho de Melo 238e9823b21SArnaldo Carvalho de Melo disasm_line__scnprintf(dl, bf, sizeof(bf), !annotate_browser__opts.use_offset); 23926270a00SArnaldo Carvalho de Melo ui_browser__write_nstring(browser, bf, width - pcnt_width - 3 - printed); 240aca7a94dSNamhyung Kim } 241aca7a94dSNamhyung Kim 242aca7a94dSNamhyung Kim if (current_entry) 24329ed6e76SArnaldo Carvalho de Melo ab->selection = dl; 244aca7a94dSNamhyung Kim } 245aca7a94dSNamhyung Kim 246865c66c4SFrederik Deweerdt static bool disasm_line__is_valid_jump(struct disasm_line *dl, struct symbol *sym) 247865c66c4SFrederik Deweerdt { 248865c66c4SFrederik Deweerdt if (!dl || !dl->ins || !ins__is_jump(dl->ins) 249865c66c4SFrederik Deweerdt || !disasm_line__has_offset(dl) 250865c66c4SFrederik Deweerdt || dl->ops.target.offset >= symbol__size(sym)) 251865c66c4SFrederik Deweerdt return false; 252865c66c4SFrederik Deweerdt 253865c66c4SFrederik Deweerdt return true; 254865c66c4SFrederik Deweerdt } 255865c66c4SFrederik Deweerdt 2569d1ef56dSArnaldo Carvalho de Melo static void annotate_browser__draw_current_jump(struct ui_browser *browser) 257a3f895beSArnaldo Carvalho de Melo { 258a3f895beSArnaldo Carvalho de Melo struct annotate_browser *ab = container_of(browser, struct annotate_browser, b); 2599d1ef56dSArnaldo Carvalho de Melo struct disasm_line *cursor = ab->selection, *target; 2609d1ef56dSArnaldo Carvalho de Melo struct browser_disasm_line *btarget, *bcursor; 26183b1f2aaSArnaldo Carvalho de Melo unsigned int from, to; 26232ae1efdSNamhyung Kim struct map_symbol *ms = ab->b.priv; 26332ae1efdSNamhyung Kim struct symbol *sym = ms->sym; 264f8f4aaeaSAndi Kleen u8 pcnt_width = annotate_browser__pcnt_width(ab); 26532ae1efdSNamhyung Kim 26632ae1efdSNamhyung Kim /* PLT symbols contain external offsets */ 26732ae1efdSNamhyung Kim if (strstr(sym->name, "@plt")) 26832ae1efdSNamhyung Kim return; 269a3f895beSArnaldo Carvalho de Melo 270865c66c4SFrederik Deweerdt if (!disasm_line__is_valid_jump(cursor, sym)) 271a3f895beSArnaldo Carvalho de Melo return; 272a3f895beSArnaldo Carvalho de Melo 2739d1ef56dSArnaldo Carvalho de Melo target = ab->offsets[cursor->ops.target.offset]; 2749d1ef56dSArnaldo Carvalho de Melo if (!target) 2759d1ef56dSArnaldo Carvalho de Melo return; 2769d1ef56dSArnaldo Carvalho de Melo 2779d1ef56dSArnaldo Carvalho de Melo bcursor = disasm_line__browser(cursor); 2789d1ef56dSArnaldo Carvalho de Melo btarget = disasm_line__browser(target); 2799d1ef56dSArnaldo Carvalho de Melo 280e9823b21SArnaldo Carvalho de Melo if (annotate_browser__opts.hide_src_code) { 2819d1ef56dSArnaldo Carvalho de Melo from = bcursor->idx_asm; 282a3f895beSArnaldo Carvalho de Melo to = btarget->idx_asm; 283a3f895beSArnaldo Carvalho de Melo } else { 2849d1ef56dSArnaldo Carvalho de Melo from = (u64)bcursor->idx; 285a3f895beSArnaldo Carvalho de Melo to = (u64)btarget->idx; 286a3f895beSArnaldo Carvalho de Melo } 287a3f895beSArnaldo Carvalho de Melo 28878ce08dfSTaeung Song ui_browser__set_color(browser, HE_COLORSET_JUMP_ARROWS); 289c7e7b610SNamhyung Kim __ui_browser__line_arrow(browser, pcnt_width + 2 + ab->addr_width, 290c7e7b610SNamhyung Kim from, to); 291a3f895beSArnaldo Carvalho de Melo } 292a3f895beSArnaldo Carvalho de Melo 293a3f895beSArnaldo Carvalho de Melo static unsigned int annotate_browser__refresh(struct ui_browser *browser) 294a3f895beSArnaldo Carvalho de Melo { 295c7e7b610SNamhyung Kim struct annotate_browser *ab = container_of(browser, struct annotate_browser, b); 296a3f895beSArnaldo Carvalho de Melo int ret = ui_browser__list_head_refresh(browser); 297f8f4aaeaSAndi Kleen int pcnt_width = annotate_browser__pcnt_width(ab); 298a3f895beSArnaldo Carvalho de Melo 299e9823b21SArnaldo Carvalho de Melo if (annotate_browser__opts.jump_arrows) 3009d1ef56dSArnaldo Carvalho de Melo annotate_browser__draw_current_jump(browser); 301a3f895beSArnaldo Carvalho de Melo 30283b1f2aaSArnaldo Carvalho de Melo ui_browser__set_color(browser, HE_COLORSET_NORMAL); 303c7e7b610SNamhyung Kim __ui_browser__vline(browser, pcnt_width, 0, browser->height - 1); 304a3f895beSArnaldo Carvalho de Melo return ret; 305a3f895beSArnaldo Carvalho de Melo } 306a3f895beSArnaldo Carvalho de Melo 307c7e7b610SNamhyung Kim static int disasm__cmp(struct browser_disasm_line *a, 308c7e7b610SNamhyung Kim struct browser_disasm_line *b, int nr_pcnt) 309c7e7b610SNamhyung Kim { 310c7e7b610SNamhyung Kim int i; 311c7e7b610SNamhyung Kim 312c7e7b610SNamhyung Kim for (i = 0; i < nr_pcnt; i++) { 3130c4a5bceSMartin Liška if (a->samples[i].percent == b->samples[i].percent) 314c7e7b610SNamhyung Kim continue; 3150c4a5bceSMartin Liška return a->samples[i].percent < b->samples[i].percent; 316c7e7b610SNamhyung Kim } 317c7e7b610SNamhyung Kim return 0; 318c7e7b610SNamhyung Kim } 319c7e7b610SNamhyung Kim 320c7e7b610SNamhyung Kim static void disasm_rb_tree__insert(struct rb_root *root, struct browser_disasm_line *bdl, 321c7e7b610SNamhyung Kim int nr_events) 322aca7a94dSNamhyung Kim { 32329ed6e76SArnaldo Carvalho de Melo struct rb_node **p = &root->rb_node; 324aca7a94dSNamhyung Kim struct rb_node *parent = NULL; 325887c0066SArnaldo Carvalho de Melo struct browser_disasm_line *l; 326aca7a94dSNamhyung Kim 327aca7a94dSNamhyung Kim while (*p != NULL) { 328aca7a94dSNamhyung Kim parent = *p; 329887c0066SArnaldo Carvalho de Melo l = rb_entry(parent, struct browser_disasm_line, rb_node); 330c7e7b610SNamhyung Kim 331c7e7b610SNamhyung Kim if (disasm__cmp(bdl, l, nr_events)) 332aca7a94dSNamhyung Kim p = &(*p)->rb_left; 333aca7a94dSNamhyung Kim else 334aca7a94dSNamhyung Kim p = &(*p)->rb_right; 335aca7a94dSNamhyung Kim } 336887c0066SArnaldo Carvalho de Melo rb_link_node(&bdl->rb_node, parent, p); 337887c0066SArnaldo Carvalho de Melo rb_insert_color(&bdl->rb_node, root); 338aca7a94dSNamhyung Kim } 339aca7a94dSNamhyung Kim 34005e8b080SArnaldo Carvalho de Melo static void annotate_browser__set_top(struct annotate_browser *browser, 34129ed6e76SArnaldo Carvalho de Melo struct disasm_line *pos, u32 idx) 342aca7a94dSNamhyung Kim { 343aca7a94dSNamhyung Kim unsigned back; 344aca7a94dSNamhyung Kim 34505e8b080SArnaldo Carvalho de Melo ui_browser__refresh_dimensions(&browser->b); 34605e8b080SArnaldo Carvalho de Melo back = browser->b.height / 2; 34705e8b080SArnaldo Carvalho de Melo browser->b.top_idx = browser->b.index = idx; 348aca7a94dSNamhyung Kim 34905e8b080SArnaldo Carvalho de Melo while (browser->b.top_idx != 0 && back != 0) { 35029ed6e76SArnaldo Carvalho de Melo pos = list_entry(pos->node.prev, struct disasm_line, node); 351aca7a94dSNamhyung Kim 35205e8b080SArnaldo Carvalho de Melo if (disasm_line__filter(&browser->b, &pos->node)) 353aca7a94dSNamhyung Kim continue; 354aca7a94dSNamhyung Kim 35505e8b080SArnaldo Carvalho de Melo --browser->b.top_idx; 356aca7a94dSNamhyung Kim --back; 357aca7a94dSNamhyung Kim } 358aca7a94dSNamhyung Kim 35905e8b080SArnaldo Carvalho de Melo browser->b.top = pos; 36005e8b080SArnaldo Carvalho de Melo browser->b.navkeypressed = true; 361aca7a94dSNamhyung Kim } 362aca7a94dSNamhyung Kim 363aca7a94dSNamhyung Kim static void annotate_browser__set_rb_top(struct annotate_browser *browser, 364aca7a94dSNamhyung Kim struct rb_node *nd) 365aca7a94dSNamhyung Kim { 366887c0066SArnaldo Carvalho de Melo struct browser_disasm_line *bpos; 36729ed6e76SArnaldo Carvalho de Melo struct disasm_line *pos; 368a44b45f2SArnaldo Carvalho de Melo u32 idx; 369aca7a94dSNamhyung Kim 370887c0066SArnaldo Carvalho de Melo bpos = rb_entry(nd, struct browser_disasm_line, rb_node); 371887c0066SArnaldo Carvalho de Melo pos = ((struct disasm_line *)bpos) - 1; 372a44b45f2SArnaldo Carvalho de Melo idx = bpos->idx; 373e9823b21SArnaldo Carvalho de Melo if (annotate_browser__opts.hide_src_code) 374a44b45f2SArnaldo Carvalho de Melo idx = bpos->idx_asm; 375a44b45f2SArnaldo Carvalho de Melo annotate_browser__set_top(browser, pos, idx); 376aca7a94dSNamhyung Kim browser->curr_hot = nd; 377aca7a94dSNamhyung Kim } 378aca7a94dSNamhyung Kim 379aca7a94dSNamhyung Kim static void annotate_browser__calc_percent(struct annotate_browser *browser, 380db8fd07aSNamhyung Kim struct perf_evsel *evsel) 381aca7a94dSNamhyung Kim { 382aca7a94dSNamhyung Kim struct map_symbol *ms = browser->b.priv; 383aca7a94dSNamhyung Kim struct symbol *sym = ms->sym; 384aca7a94dSNamhyung Kim struct annotation *notes = symbol__annotation(sym); 385e64aa75bSNamhyung Kim struct disasm_line *pos, *next; 386e64aa75bSNamhyung Kim s64 len = symbol__size(sym); 387aca7a94dSNamhyung Kim 388aca7a94dSNamhyung Kim browser->entries = RB_ROOT; 389aca7a94dSNamhyung Kim 390aca7a94dSNamhyung Kim pthread_mutex_lock(¬es->lock); 391aca7a94dSNamhyung Kim 392aca7a94dSNamhyung Kim list_for_each_entry(pos, ¬es->src->source, node) { 393887c0066SArnaldo Carvalho de Melo struct browser_disasm_line *bpos = disasm_line__browser(pos); 394e64aa75bSNamhyung Kim const char *path = NULL; 395c7e7b610SNamhyung Kim double max_percent = 0.0; 396c7e7b610SNamhyung Kim int i; 397e64aa75bSNamhyung Kim 398e64aa75bSNamhyung Kim if (pos->offset == -1) { 399e64aa75bSNamhyung Kim RB_CLEAR_NODE(&bpos->rb_node); 400e64aa75bSNamhyung Kim continue; 401e64aa75bSNamhyung Kim } 402e64aa75bSNamhyung Kim 403e64aa75bSNamhyung Kim next = disasm__get_next_ip_line(¬es->src->source, pos); 404c7e7b610SNamhyung Kim 405c7e7b610SNamhyung Kim for (i = 0; i < browser->nr_events; i++) { 4060c4a5bceSMartin Liška u64 nr_samples; 4070c4a5bceSMartin Liška 4080c4a5bceSMartin Liška bpos->samples[i].percent = disasm__calc_percent(notes, 409c7e7b610SNamhyung Kim evsel->idx + i, 410c7e7b610SNamhyung Kim pos->offset, 411c7e7b610SNamhyung Kim next ? next->offset : len, 4120c4a5bceSMartin Liška &path, &nr_samples); 4130c4a5bceSMartin Liška bpos->samples[i].nr = nr_samples; 414e64aa75bSNamhyung Kim 4150c4a5bceSMartin Liška if (max_percent < bpos->samples[i].percent) 4160c4a5bceSMartin Liška max_percent = bpos->samples[i].percent; 417c7e7b610SNamhyung Kim } 418c7e7b610SNamhyung Kim 41930e863bbSAndi Kleen if (max_percent < 0.01 && pos->ipc == 0) { 420887c0066SArnaldo Carvalho de Melo RB_CLEAR_NODE(&bpos->rb_node); 421aca7a94dSNamhyung Kim continue; 422aca7a94dSNamhyung Kim } 423c7e7b610SNamhyung Kim disasm_rb_tree__insert(&browser->entries, bpos, 424c7e7b610SNamhyung Kim browser->nr_events); 425aca7a94dSNamhyung Kim } 426aca7a94dSNamhyung Kim pthread_mutex_unlock(¬es->lock); 427aca7a94dSNamhyung Kim 428aca7a94dSNamhyung Kim browser->curr_hot = rb_last(&browser->entries); 429aca7a94dSNamhyung Kim } 430aca7a94dSNamhyung Kim 431aca7a94dSNamhyung Kim static bool annotate_browser__toggle_source(struct annotate_browser *browser) 432aca7a94dSNamhyung Kim { 43329ed6e76SArnaldo Carvalho de Melo struct disasm_line *dl; 434887c0066SArnaldo Carvalho de Melo struct browser_disasm_line *bdl; 435aca7a94dSNamhyung Kim off_t offset = browser->b.index - browser->b.top_idx; 436aca7a94dSNamhyung Kim 437aca7a94dSNamhyung Kim browser->b.seek(&browser->b, offset, SEEK_CUR); 43829ed6e76SArnaldo Carvalho de Melo dl = list_entry(browser->b.top, struct disasm_line, node); 439887c0066SArnaldo Carvalho de Melo bdl = disasm_line__browser(dl); 440aca7a94dSNamhyung Kim 441e9823b21SArnaldo Carvalho de Melo if (annotate_browser__opts.hide_src_code) { 442887c0066SArnaldo Carvalho de Melo if (bdl->idx_asm < offset) 443887c0066SArnaldo Carvalho de Melo offset = bdl->idx; 444aca7a94dSNamhyung Kim 445aca7a94dSNamhyung Kim browser->b.nr_entries = browser->nr_entries; 446e9823b21SArnaldo Carvalho de Melo annotate_browser__opts.hide_src_code = false; 447aca7a94dSNamhyung Kim browser->b.seek(&browser->b, -offset, SEEK_CUR); 448887c0066SArnaldo Carvalho de Melo browser->b.top_idx = bdl->idx - offset; 449887c0066SArnaldo Carvalho de Melo browser->b.index = bdl->idx; 450aca7a94dSNamhyung Kim } else { 451887c0066SArnaldo Carvalho de Melo if (bdl->idx_asm < 0) { 452aca7a94dSNamhyung Kim ui_helpline__puts("Only available for assembly lines."); 453aca7a94dSNamhyung Kim browser->b.seek(&browser->b, -offset, SEEK_CUR); 454aca7a94dSNamhyung Kim return false; 455aca7a94dSNamhyung Kim } 456aca7a94dSNamhyung Kim 457887c0066SArnaldo Carvalho de Melo if (bdl->idx_asm < offset) 458887c0066SArnaldo Carvalho de Melo offset = bdl->idx_asm; 459aca7a94dSNamhyung Kim 460aca7a94dSNamhyung Kim browser->b.nr_entries = browser->nr_asm_entries; 461e9823b21SArnaldo Carvalho de Melo annotate_browser__opts.hide_src_code = true; 462aca7a94dSNamhyung Kim browser->b.seek(&browser->b, -offset, SEEK_CUR); 463887c0066SArnaldo Carvalho de Melo browser->b.top_idx = bdl->idx_asm - offset; 464887c0066SArnaldo Carvalho de Melo browser->b.index = bdl->idx_asm; 465aca7a94dSNamhyung Kim } 466aca7a94dSNamhyung Kim 467aca7a94dSNamhyung Kim return true; 468aca7a94dSNamhyung Kim } 469aca7a94dSNamhyung Kim 470e9823b21SArnaldo Carvalho de Melo static void annotate_browser__init_asm_mode(struct annotate_browser *browser) 471e9823b21SArnaldo Carvalho de Melo { 472e9823b21SArnaldo Carvalho de Melo ui_browser__reset_index(&browser->b); 473e9823b21SArnaldo Carvalho de Melo browser->b.nr_entries = browser->nr_asm_entries; 474e9823b21SArnaldo Carvalho de Melo } 475e9823b21SArnaldo Carvalho de Melo 47634f77abcSAdrian Hunter #define SYM_TITLE_MAX_SIZE (PATH_MAX + 64) 47734f77abcSAdrian Hunter 47834f77abcSAdrian Hunter static int sym_title(struct symbol *sym, struct map *map, char *title, 47934f77abcSAdrian Hunter size_t sz) 48034f77abcSAdrian Hunter { 48134f77abcSAdrian Hunter return snprintf(title, sz, "%s %s", sym->name, map->dso->long_name); 48234f77abcSAdrian Hunter } 48334f77abcSAdrian Hunter 484db8fd07aSNamhyung Kim static bool annotate_browser__callq(struct annotate_browser *browser, 485db8fd07aSNamhyung Kim struct perf_evsel *evsel, 4869783adf7SNamhyung Kim struct hist_browser_timer *hbt) 487aca7a94dSNamhyung Kim { 488aca7a94dSNamhyung Kim struct map_symbol *ms = browser->b.priv; 489657bcaf5SArnaldo Carvalho de Melo struct disasm_line *dl = browser->selection; 490aca7a94dSNamhyung Kim struct annotation *notes; 4911179e11bSAdrian Hunter struct addr_map_symbol target = { 4921179e11bSAdrian Hunter .map = ms->map, 4931d5077bdSAdrian Hunter .addr = map__objdump_2mem(ms->map, dl->ops.target.addr), 4941179e11bSAdrian Hunter }; 49534f77abcSAdrian Hunter char title[SYM_TITLE_MAX_SIZE]; 496aca7a94dSNamhyung Kim 497d86b0597SArnaldo Carvalho de Melo if (!ins__is_call(dl->ins)) 498aca7a94dSNamhyung Kim return false; 499aca7a94dSNamhyung Kim 5001d5077bdSAdrian Hunter if (map_groups__find_ams(&target, NULL) || 5011d5077bdSAdrian Hunter map__rip_2objdump(target.map, target.map->map_ip(target.map, 5021d5077bdSAdrian Hunter target.addr)) != 5031d5077bdSAdrian Hunter dl->ops.target.addr) { 504aca7a94dSNamhyung Kim ui_helpline__puts("The called function was not found."); 505aca7a94dSNamhyung Kim return true; 506aca7a94dSNamhyung Kim } 507aca7a94dSNamhyung Kim 5081179e11bSAdrian Hunter notes = symbol__annotation(target.sym); 509aca7a94dSNamhyung Kim pthread_mutex_lock(¬es->lock); 510aca7a94dSNamhyung Kim 5111179e11bSAdrian Hunter if (notes->src == NULL && symbol__alloc_hist(target.sym) < 0) { 512aca7a94dSNamhyung Kim pthread_mutex_unlock(¬es->lock); 513aca7a94dSNamhyung Kim ui__warning("Not enough memory for annotating '%s' symbol!\n", 5141179e11bSAdrian Hunter target.sym->name); 515aca7a94dSNamhyung Kim return true; 516aca7a94dSNamhyung Kim } 517aca7a94dSNamhyung Kim 518aca7a94dSNamhyung Kim pthread_mutex_unlock(¬es->lock); 5191179e11bSAdrian Hunter symbol__tui_annotate(target.sym, target.map, evsel, hbt); 5201179e11bSAdrian Hunter sym_title(ms->sym, ms->map, title, sizeof(title)); 52134f77abcSAdrian Hunter ui_browser__show_title(&browser->b, title); 522aca7a94dSNamhyung Kim return true; 523aca7a94dSNamhyung Kim } 524aca7a94dSNamhyung Kim 52529ed6e76SArnaldo Carvalho de Melo static 52629ed6e76SArnaldo Carvalho de Melo struct disasm_line *annotate_browser__find_offset(struct annotate_browser *browser, 527aca7a94dSNamhyung Kim s64 offset, s64 *idx) 528aca7a94dSNamhyung Kim { 529aca7a94dSNamhyung Kim struct map_symbol *ms = browser->b.priv; 530aca7a94dSNamhyung Kim struct symbol *sym = ms->sym; 531aca7a94dSNamhyung Kim struct annotation *notes = symbol__annotation(sym); 53229ed6e76SArnaldo Carvalho de Melo struct disasm_line *pos; 533aca7a94dSNamhyung Kim 534aca7a94dSNamhyung Kim *idx = 0; 535aca7a94dSNamhyung Kim list_for_each_entry(pos, ¬es->src->source, node) { 536aca7a94dSNamhyung Kim if (pos->offset == offset) 537aca7a94dSNamhyung Kim return pos; 53829ed6e76SArnaldo Carvalho de Melo if (!disasm_line__filter(&browser->b, &pos->node)) 539aca7a94dSNamhyung Kim ++*idx; 540aca7a94dSNamhyung Kim } 541aca7a94dSNamhyung Kim 542aca7a94dSNamhyung Kim return NULL; 543aca7a94dSNamhyung Kim } 544aca7a94dSNamhyung Kim 545aca7a94dSNamhyung Kim static bool annotate_browser__jump(struct annotate_browser *browser) 546aca7a94dSNamhyung Kim { 547657bcaf5SArnaldo Carvalho de Melo struct disasm_line *dl = browser->selection; 5484f9d0325SArnaldo Carvalho de Melo s64 idx; 549aca7a94dSNamhyung Kim 550d86b0597SArnaldo Carvalho de Melo if (!ins__is_jump(dl->ins)) 551aca7a94dSNamhyung Kim return false; 552aca7a94dSNamhyung Kim 55344d1a3edSArnaldo Carvalho de Melo dl = annotate_browser__find_offset(browser, dl->ops.target.offset, &idx); 55429ed6e76SArnaldo Carvalho de Melo if (dl == NULL) { 555e6f65388SIngo Molnar ui_helpline__puts("Invalid jump offset"); 556aca7a94dSNamhyung Kim return true; 557aca7a94dSNamhyung Kim } 558aca7a94dSNamhyung Kim 55929ed6e76SArnaldo Carvalho de Melo annotate_browser__set_top(browser, dl, idx); 560aca7a94dSNamhyung Kim 561aca7a94dSNamhyung Kim return true; 562aca7a94dSNamhyung Kim } 563aca7a94dSNamhyung Kim 56429ed6e76SArnaldo Carvalho de Melo static 56529ed6e76SArnaldo Carvalho de Melo struct disasm_line *annotate_browser__find_string(struct annotate_browser *browser, 566aca7a94dSNamhyung Kim char *s, s64 *idx) 567aca7a94dSNamhyung Kim { 568aca7a94dSNamhyung Kim struct map_symbol *ms = browser->b.priv; 569aca7a94dSNamhyung Kim struct symbol *sym = ms->sym; 570aca7a94dSNamhyung Kim struct annotation *notes = symbol__annotation(sym); 57129ed6e76SArnaldo Carvalho de Melo struct disasm_line *pos = browser->selection; 572aca7a94dSNamhyung Kim 573aca7a94dSNamhyung Kim *idx = browser->b.index; 574aca7a94dSNamhyung Kim list_for_each_entry_continue(pos, ¬es->src->source, node) { 57529ed6e76SArnaldo Carvalho de Melo if (disasm_line__filter(&browser->b, &pos->node)) 576aca7a94dSNamhyung Kim continue; 577aca7a94dSNamhyung Kim 578aca7a94dSNamhyung Kim ++*idx; 579aca7a94dSNamhyung Kim 580aca7a94dSNamhyung Kim if (pos->line && strstr(pos->line, s) != NULL) 581aca7a94dSNamhyung Kim return pos; 582aca7a94dSNamhyung Kim } 583aca7a94dSNamhyung Kim 584aca7a94dSNamhyung Kim return NULL; 585aca7a94dSNamhyung Kim } 586aca7a94dSNamhyung Kim 587aca7a94dSNamhyung Kim static bool __annotate_browser__search(struct annotate_browser *browser) 588aca7a94dSNamhyung Kim { 58929ed6e76SArnaldo Carvalho de Melo struct disasm_line *dl; 590aca7a94dSNamhyung Kim s64 idx; 591aca7a94dSNamhyung Kim 59229ed6e76SArnaldo Carvalho de Melo dl = annotate_browser__find_string(browser, browser->search_bf, &idx); 59329ed6e76SArnaldo Carvalho de Melo if (dl == NULL) { 594aca7a94dSNamhyung Kim ui_helpline__puts("String not found!"); 595aca7a94dSNamhyung Kim return false; 596aca7a94dSNamhyung Kim } 597aca7a94dSNamhyung Kim 59829ed6e76SArnaldo Carvalho de Melo annotate_browser__set_top(browser, dl, idx); 599aca7a94dSNamhyung Kim browser->searching_backwards = false; 600aca7a94dSNamhyung Kim return true; 601aca7a94dSNamhyung Kim } 602aca7a94dSNamhyung Kim 60329ed6e76SArnaldo Carvalho de Melo static 60429ed6e76SArnaldo Carvalho de Melo struct disasm_line *annotate_browser__find_string_reverse(struct annotate_browser *browser, 605aca7a94dSNamhyung Kim char *s, s64 *idx) 606aca7a94dSNamhyung Kim { 607aca7a94dSNamhyung Kim struct map_symbol *ms = browser->b.priv; 608aca7a94dSNamhyung Kim struct symbol *sym = ms->sym; 609aca7a94dSNamhyung Kim struct annotation *notes = symbol__annotation(sym); 61029ed6e76SArnaldo Carvalho de Melo struct disasm_line *pos = browser->selection; 611aca7a94dSNamhyung Kim 612aca7a94dSNamhyung Kim *idx = browser->b.index; 613aca7a94dSNamhyung Kim list_for_each_entry_continue_reverse(pos, ¬es->src->source, node) { 61429ed6e76SArnaldo Carvalho de Melo if (disasm_line__filter(&browser->b, &pos->node)) 615aca7a94dSNamhyung Kim continue; 616aca7a94dSNamhyung Kim 617aca7a94dSNamhyung Kim --*idx; 618aca7a94dSNamhyung Kim 619aca7a94dSNamhyung Kim if (pos->line && strstr(pos->line, s) != NULL) 620aca7a94dSNamhyung Kim return pos; 621aca7a94dSNamhyung Kim } 622aca7a94dSNamhyung Kim 623aca7a94dSNamhyung Kim return NULL; 624aca7a94dSNamhyung Kim } 625aca7a94dSNamhyung Kim 626aca7a94dSNamhyung Kim static bool __annotate_browser__search_reverse(struct annotate_browser *browser) 627aca7a94dSNamhyung Kim { 62829ed6e76SArnaldo Carvalho de Melo struct disasm_line *dl; 629aca7a94dSNamhyung Kim s64 idx; 630aca7a94dSNamhyung Kim 63129ed6e76SArnaldo Carvalho de Melo dl = annotate_browser__find_string_reverse(browser, browser->search_bf, &idx); 63229ed6e76SArnaldo Carvalho de Melo if (dl == NULL) { 633aca7a94dSNamhyung Kim ui_helpline__puts("String not found!"); 634aca7a94dSNamhyung Kim return false; 635aca7a94dSNamhyung Kim } 636aca7a94dSNamhyung Kim 63729ed6e76SArnaldo Carvalho de Melo annotate_browser__set_top(browser, dl, idx); 638aca7a94dSNamhyung Kim browser->searching_backwards = true; 639aca7a94dSNamhyung Kim return true; 640aca7a94dSNamhyung Kim } 641aca7a94dSNamhyung Kim 642aca7a94dSNamhyung Kim static bool annotate_browser__search_window(struct annotate_browser *browser, 643aca7a94dSNamhyung Kim int delay_secs) 644aca7a94dSNamhyung Kim { 645aca7a94dSNamhyung Kim if (ui_browser__input_window("Search", "String: ", browser->search_bf, 646aca7a94dSNamhyung Kim "ENTER: OK, ESC: Cancel", 647aca7a94dSNamhyung Kim delay_secs * 2) != K_ENTER || 648aca7a94dSNamhyung Kim !*browser->search_bf) 649aca7a94dSNamhyung Kim return false; 650aca7a94dSNamhyung Kim 651aca7a94dSNamhyung Kim return true; 652aca7a94dSNamhyung Kim } 653aca7a94dSNamhyung Kim 654aca7a94dSNamhyung Kim static bool annotate_browser__search(struct annotate_browser *browser, int delay_secs) 655aca7a94dSNamhyung Kim { 656aca7a94dSNamhyung Kim if (annotate_browser__search_window(browser, delay_secs)) 657aca7a94dSNamhyung Kim return __annotate_browser__search(browser); 658aca7a94dSNamhyung Kim 659aca7a94dSNamhyung Kim return false; 660aca7a94dSNamhyung Kim } 661aca7a94dSNamhyung Kim 662aca7a94dSNamhyung Kim static bool annotate_browser__continue_search(struct annotate_browser *browser, 663aca7a94dSNamhyung Kim int delay_secs) 664aca7a94dSNamhyung Kim { 665aca7a94dSNamhyung Kim if (!*browser->search_bf) 666aca7a94dSNamhyung Kim return annotate_browser__search(browser, delay_secs); 667aca7a94dSNamhyung Kim 668aca7a94dSNamhyung Kim return __annotate_browser__search(browser); 669aca7a94dSNamhyung Kim } 670aca7a94dSNamhyung Kim 671aca7a94dSNamhyung Kim static bool annotate_browser__search_reverse(struct annotate_browser *browser, 672aca7a94dSNamhyung Kim int delay_secs) 673aca7a94dSNamhyung Kim { 674aca7a94dSNamhyung Kim if (annotate_browser__search_window(browser, delay_secs)) 675aca7a94dSNamhyung Kim return __annotate_browser__search_reverse(browser); 676aca7a94dSNamhyung Kim 677aca7a94dSNamhyung Kim return false; 678aca7a94dSNamhyung Kim } 679aca7a94dSNamhyung Kim 680aca7a94dSNamhyung Kim static 681aca7a94dSNamhyung Kim bool annotate_browser__continue_search_reverse(struct annotate_browser *browser, 682aca7a94dSNamhyung Kim int delay_secs) 683aca7a94dSNamhyung Kim { 684aca7a94dSNamhyung Kim if (!*browser->search_bf) 685aca7a94dSNamhyung Kim return annotate_browser__search_reverse(browser, delay_secs); 686aca7a94dSNamhyung Kim 687aca7a94dSNamhyung Kim return __annotate_browser__search_reverse(browser); 688aca7a94dSNamhyung Kim } 689aca7a94dSNamhyung Kim 690e9823b21SArnaldo Carvalho de Melo static void annotate_browser__update_addr_width(struct annotate_browser *browser) 691e9823b21SArnaldo Carvalho de Melo { 692e9823b21SArnaldo Carvalho de Melo if (annotate_browser__opts.use_offset) 693e9823b21SArnaldo Carvalho de Melo browser->target_width = browser->min_addr_width; 694e9823b21SArnaldo Carvalho de Melo else 695e9823b21SArnaldo Carvalho de Melo browser->target_width = browser->max_addr_width; 696e9823b21SArnaldo Carvalho de Melo 697e9823b21SArnaldo Carvalho de Melo browser->addr_width = browser->target_width; 698e9823b21SArnaldo Carvalho de Melo 699e9823b21SArnaldo Carvalho de Melo if (annotate_browser__opts.show_nr_jumps) 700e9823b21SArnaldo Carvalho de Melo browser->addr_width += browser->jumps_width + 1; 701e9823b21SArnaldo Carvalho de Melo } 702e9823b21SArnaldo Carvalho de Melo 703db8fd07aSNamhyung Kim static int annotate_browser__run(struct annotate_browser *browser, 704db8fd07aSNamhyung Kim struct perf_evsel *evsel, 7059783adf7SNamhyung Kim struct hist_browser_timer *hbt) 706aca7a94dSNamhyung Kim { 707aca7a94dSNamhyung Kim struct rb_node *nd = NULL; 70805e8b080SArnaldo Carvalho de Melo struct map_symbol *ms = browser->b.priv; 709aca7a94dSNamhyung Kim struct symbol *sym = ms->sym; 71054e7a4e8SArnaldo Carvalho de Melo const char *help = "Press 'h' for help on key bindings"; 7119783adf7SNamhyung Kim int delay_secs = hbt ? hbt->refresh : 0; 712aca7a94dSNamhyung Kim int key; 71334f77abcSAdrian Hunter char title[SYM_TITLE_MAX_SIZE]; 714aca7a94dSNamhyung Kim 71534f77abcSAdrian Hunter sym_title(sym, ms->map, title, sizeof(title)); 71634f77abcSAdrian Hunter if (ui_browser__show(&browser->b, title, help) < 0) 717aca7a94dSNamhyung Kim return -1; 718aca7a94dSNamhyung Kim 719db8fd07aSNamhyung Kim annotate_browser__calc_percent(browser, evsel); 720aca7a94dSNamhyung Kim 72105e8b080SArnaldo Carvalho de Melo if (browser->curr_hot) { 72205e8b080SArnaldo Carvalho de Melo annotate_browser__set_rb_top(browser, browser->curr_hot); 72305e8b080SArnaldo Carvalho de Melo browser->b.navkeypressed = false; 724aca7a94dSNamhyung Kim } 725aca7a94dSNamhyung Kim 72605e8b080SArnaldo Carvalho de Melo nd = browser->curr_hot; 727aca7a94dSNamhyung Kim 728aca7a94dSNamhyung Kim while (1) { 72905e8b080SArnaldo Carvalho de Melo key = ui_browser__run(&browser->b, delay_secs); 730aca7a94dSNamhyung Kim 731aca7a94dSNamhyung Kim if (delay_secs != 0) { 732db8fd07aSNamhyung Kim annotate_browser__calc_percent(browser, evsel); 733aca7a94dSNamhyung Kim /* 734aca7a94dSNamhyung Kim * Current line focus got out of the list of most active 735aca7a94dSNamhyung Kim * lines, NULL it so that if TAB|UNTAB is pressed, we 736aca7a94dSNamhyung Kim * move to curr_hot (current hottest line). 737aca7a94dSNamhyung Kim */ 738aca7a94dSNamhyung Kim if (nd != NULL && RB_EMPTY_NODE(nd)) 739aca7a94dSNamhyung Kim nd = NULL; 740aca7a94dSNamhyung Kim } 741aca7a94dSNamhyung Kim 742aca7a94dSNamhyung Kim switch (key) { 743aca7a94dSNamhyung Kim case K_TIMER: 7449783adf7SNamhyung Kim if (hbt) 7459783adf7SNamhyung Kim hbt->timer(hbt->arg); 746aca7a94dSNamhyung Kim 747aca7a94dSNamhyung Kim if (delay_secs != 0) 748db8fd07aSNamhyung Kim symbol__annotate_decay_histogram(sym, evsel->idx); 749aca7a94dSNamhyung Kim continue; 750aca7a94dSNamhyung Kim case K_TAB: 751aca7a94dSNamhyung Kim if (nd != NULL) { 752aca7a94dSNamhyung Kim nd = rb_prev(nd); 753aca7a94dSNamhyung Kim if (nd == NULL) 75405e8b080SArnaldo Carvalho de Melo nd = rb_last(&browser->entries); 755aca7a94dSNamhyung Kim } else 75605e8b080SArnaldo Carvalho de Melo nd = browser->curr_hot; 757aca7a94dSNamhyung Kim break; 758aca7a94dSNamhyung Kim case K_UNTAB: 759d4913cbdSMarkus Trippelsdorf if (nd != NULL) { 760aca7a94dSNamhyung Kim nd = rb_next(nd); 761aca7a94dSNamhyung Kim if (nd == NULL) 76205e8b080SArnaldo Carvalho de Melo nd = rb_first(&browser->entries); 763d4913cbdSMarkus Trippelsdorf } else 76405e8b080SArnaldo Carvalho de Melo nd = browser->curr_hot; 765aca7a94dSNamhyung Kim break; 76654e7a4e8SArnaldo Carvalho de Melo case K_F1: 767aca7a94dSNamhyung Kim case 'h': 76805e8b080SArnaldo Carvalho de Melo ui_browser__help_window(&browser->b, 76954e7a4e8SArnaldo Carvalho de Melo "UP/DOWN/PGUP\n" 77054e7a4e8SArnaldo Carvalho de Melo "PGDN/SPACE Navigate\n" 77154e7a4e8SArnaldo Carvalho de Melo "q/ESC/CTRL+C Exit\n\n" 7727727a925SArnaldo Carvalho de Melo "ENTER Go to target\n" 7737727a925SArnaldo Carvalho de Melo "ESC Exit\n" 774107baecaSArnaldo Carvalho de Melo "H Cycle thru hottest instructions\n" 77554e7a4e8SArnaldo Carvalho de Melo "j Toggle showing jump to target arrows\n" 77654e7a4e8SArnaldo Carvalho de Melo "J Toggle showing number of jump sources on targets\n" 77754e7a4e8SArnaldo Carvalho de Melo "n Search next string\n" 77854e7a4e8SArnaldo Carvalho de Melo "o Toggle disassembler output/simplified view\n" 77954e7a4e8SArnaldo Carvalho de Melo "s Toggle source code view\n" 7800c4a5bceSMartin Liška "t Toggle total period view\n" 78154e7a4e8SArnaldo Carvalho de Melo "/ Search string\n" 782e592488cSAndi Kleen "k Toggle line numbers\n" 78379ee47faSFeng Tang "r Run available scripts\n" 784fcd9fef9SArnaldo Carvalho de Melo "? Search string backwards\n"); 78554e7a4e8SArnaldo Carvalho de Melo continue; 78679ee47faSFeng Tang case 'r': 78779ee47faSFeng Tang { 78879ee47faSFeng Tang script_browse(NULL); 78979ee47faSFeng Tang continue; 79079ee47faSFeng Tang } 791e592488cSAndi Kleen case 'k': 792e592488cSAndi Kleen annotate_browser__opts.show_linenr = 793e592488cSAndi Kleen !annotate_browser__opts.show_linenr; 794e592488cSAndi Kleen break; 79554e7a4e8SArnaldo Carvalho de Melo case 'H': 79605e8b080SArnaldo Carvalho de Melo nd = browser->curr_hot; 797aca7a94dSNamhyung Kim break; 798aca7a94dSNamhyung Kim case 's': 79905e8b080SArnaldo Carvalho de Melo if (annotate_browser__toggle_source(browser)) 800aca7a94dSNamhyung Kim ui_helpline__puts(help); 801aca7a94dSNamhyung Kim continue; 802aca7a94dSNamhyung Kim case 'o': 803e9823b21SArnaldo Carvalho de Melo annotate_browser__opts.use_offset = !annotate_browser__opts.use_offset; 80405e8b080SArnaldo Carvalho de Melo annotate_browser__update_addr_width(browser); 805aca7a94dSNamhyung Kim continue; 8069d1ef56dSArnaldo Carvalho de Melo case 'j': 807e9823b21SArnaldo Carvalho de Melo annotate_browser__opts.jump_arrows = !annotate_browser__opts.jump_arrows; 8089d1ef56dSArnaldo Carvalho de Melo continue; 8092402e4a9SArnaldo Carvalho de Melo case 'J': 810e9823b21SArnaldo Carvalho de Melo annotate_browser__opts.show_nr_jumps = !annotate_browser__opts.show_nr_jumps; 81105e8b080SArnaldo Carvalho de Melo annotate_browser__update_addr_width(browser); 812e9823b21SArnaldo Carvalho de Melo continue; 813aca7a94dSNamhyung Kim case '/': 81405e8b080SArnaldo Carvalho de Melo if (annotate_browser__search(browser, delay_secs)) { 815aca7a94dSNamhyung Kim show_help: 816aca7a94dSNamhyung Kim ui_helpline__puts(help); 817aca7a94dSNamhyung Kim } 818aca7a94dSNamhyung Kim continue; 819aca7a94dSNamhyung Kim case 'n': 82005e8b080SArnaldo Carvalho de Melo if (browser->searching_backwards ? 82105e8b080SArnaldo Carvalho de Melo annotate_browser__continue_search_reverse(browser, delay_secs) : 82205e8b080SArnaldo Carvalho de Melo annotate_browser__continue_search(browser, delay_secs)) 823aca7a94dSNamhyung Kim goto show_help; 824aca7a94dSNamhyung Kim continue; 825aca7a94dSNamhyung Kim case '?': 82605e8b080SArnaldo Carvalho de Melo if (annotate_browser__search_reverse(browser, delay_secs)) 827aca7a94dSNamhyung Kim goto show_help; 828aca7a94dSNamhyung Kim continue; 829e9823b21SArnaldo Carvalho de Melo case 'D': { 830e9823b21SArnaldo Carvalho de Melo static int seq; 831e9823b21SArnaldo Carvalho de Melo ui_helpline__pop(); 832e9823b21SArnaldo Carvalho de Melo ui_helpline__fpush("%d: nr_ent=%d, height=%d, idx=%d, top_idx=%d, nr_asm_entries=%d", 83305e8b080SArnaldo Carvalho de Melo seq++, browser->b.nr_entries, 83405e8b080SArnaldo Carvalho de Melo browser->b.height, 83505e8b080SArnaldo Carvalho de Melo browser->b.index, 83605e8b080SArnaldo Carvalho de Melo browser->b.top_idx, 83705e8b080SArnaldo Carvalho de Melo browser->nr_asm_entries); 838e9823b21SArnaldo Carvalho de Melo } 839e9823b21SArnaldo Carvalho de Melo continue; 840aca7a94dSNamhyung Kim case K_ENTER: 841aca7a94dSNamhyung Kim case K_RIGHT: 84205e8b080SArnaldo Carvalho de Melo if (browser->selection == NULL) 843aca7a94dSNamhyung Kim ui_helpline__puts("Huh? No selection. Report to linux-kernel@vger.kernel.org"); 84405e8b080SArnaldo Carvalho de Melo else if (browser->selection->offset == -1) 845aca7a94dSNamhyung Kim ui_helpline__puts("Actions are only available for assembly lines."); 84605e8b080SArnaldo Carvalho de Melo else if (!browser->selection->ins) { 84705e8b080SArnaldo Carvalho de Melo if (strcmp(browser->selection->name, "retq")) 848c4cceae3SArnaldo Carvalho de Melo goto show_sup_ins; 849c4cceae3SArnaldo Carvalho de Melo goto out; 85005e8b080SArnaldo Carvalho de Melo } else if (!(annotate_browser__jump(browser) || 851db8fd07aSNamhyung Kim annotate_browser__callq(browser, evsel, hbt))) { 852c4cceae3SArnaldo Carvalho de Melo show_sup_ins: 853c4cceae3SArnaldo Carvalho de Melo ui_helpline__puts("Actions are only available for 'callq', 'retq' & jump instructions."); 854c4cceae3SArnaldo Carvalho de Melo } 855aca7a94dSNamhyung Kim continue; 8560c4a5bceSMartin Liška case 't': 8570c4a5bceSMartin Liška annotate_browser__opts.show_total_period = 8580c4a5bceSMartin Liška !annotate_browser__opts.show_total_period; 8590c4a5bceSMartin Liška annotate_browser__update_addr_width(browser); 8600c4a5bceSMartin Liška continue; 861aca7a94dSNamhyung Kim case K_LEFT: 862aca7a94dSNamhyung Kim case K_ESC: 863aca7a94dSNamhyung Kim case 'q': 864aca7a94dSNamhyung Kim case CTRL('c'): 865aca7a94dSNamhyung Kim goto out; 866aca7a94dSNamhyung Kim default: 867aca7a94dSNamhyung Kim continue; 868aca7a94dSNamhyung Kim } 869aca7a94dSNamhyung Kim 870aca7a94dSNamhyung Kim if (nd != NULL) 87105e8b080SArnaldo Carvalho de Melo annotate_browser__set_rb_top(browser, nd); 872aca7a94dSNamhyung Kim } 873aca7a94dSNamhyung Kim out: 87405e8b080SArnaldo Carvalho de Melo ui_browser__hide(&browser->b); 875aca7a94dSNamhyung Kim return key; 876aca7a94dSNamhyung Kim } 877aca7a94dSNamhyung Kim 878d5dbc518SArnaldo Carvalho de Melo int map_symbol__tui_annotate(struct map_symbol *ms, struct perf_evsel *evsel, 879d5dbc518SArnaldo Carvalho de Melo struct hist_browser_timer *hbt) 880d5dbc518SArnaldo Carvalho de Melo { 8810c4a5bceSMartin Liška /* Set default value for show_total_period. */ 8820c4a5bceSMartin Liška annotate_browser__opts.show_total_period = 8830c4a5bceSMartin Liška symbol_conf.show_total_period; 8840c4a5bceSMartin Liška 885d5dbc518SArnaldo Carvalho de Melo return symbol__tui_annotate(ms->sym, ms->map, evsel, hbt); 886d5dbc518SArnaldo Carvalho de Melo } 887d5dbc518SArnaldo Carvalho de Melo 888db8fd07aSNamhyung Kim int hist_entry__tui_annotate(struct hist_entry *he, struct perf_evsel *evsel, 8899783adf7SNamhyung Kim struct hist_browser_timer *hbt) 890aca7a94dSNamhyung Kim { 891ed426915SNamhyung Kim /* reset abort key so that it can get Ctrl-C as a key */ 892ed426915SNamhyung Kim SLang_reset_tty(); 893ed426915SNamhyung Kim SLang_init_tty(0, 0, 0); 894ed426915SNamhyung Kim 895d5dbc518SArnaldo Carvalho de Melo return map_symbol__tui_annotate(&he->ms, evsel, hbt); 896aca7a94dSNamhyung Kim } 897aca7a94dSNamhyung Kim 89830e863bbSAndi Kleen 89930e863bbSAndi Kleen static unsigned count_insn(struct annotate_browser *browser, u64 start, u64 end) 90030e863bbSAndi Kleen { 90130e863bbSAndi Kleen unsigned n_insn = 0; 90230e863bbSAndi Kleen u64 offset; 90330e863bbSAndi Kleen 90430e863bbSAndi Kleen for (offset = start; offset <= end; offset++) { 90530e863bbSAndi Kleen if (browser->offsets[offset]) 90630e863bbSAndi Kleen n_insn++; 90730e863bbSAndi Kleen } 90830e863bbSAndi Kleen return n_insn; 90930e863bbSAndi Kleen } 91030e863bbSAndi Kleen 91130e863bbSAndi Kleen static void count_and_fill(struct annotate_browser *browser, u64 start, u64 end, 91230e863bbSAndi Kleen struct cyc_hist *ch) 91330e863bbSAndi Kleen { 91430e863bbSAndi Kleen unsigned n_insn; 91530e863bbSAndi Kleen u64 offset; 91630e863bbSAndi Kleen 91730e863bbSAndi Kleen n_insn = count_insn(browser, start, end); 91830e863bbSAndi Kleen if (n_insn && ch->num && ch->cycles) { 91930e863bbSAndi Kleen float ipc = n_insn / ((double)ch->cycles / (double)ch->num); 92030e863bbSAndi Kleen 92130e863bbSAndi Kleen /* Hide data when there are too many overlaps. */ 92230e863bbSAndi Kleen if (ch->reset >= 0x7fff || ch->reset >= ch->num / 2) 92330e863bbSAndi Kleen return; 92430e863bbSAndi Kleen 92530e863bbSAndi Kleen for (offset = start; offset <= end; offset++) { 92630e863bbSAndi Kleen struct disasm_line *dl = browser->offsets[offset]; 92730e863bbSAndi Kleen 92830e863bbSAndi Kleen if (dl) 92930e863bbSAndi Kleen dl->ipc = ipc; 93030e863bbSAndi Kleen } 93130e863bbSAndi Kleen } 93230e863bbSAndi Kleen } 93330e863bbSAndi Kleen 93430e863bbSAndi Kleen /* 93530e863bbSAndi Kleen * This should probably be in util/annotate.c to share with the tty 93630e863bbSAndi Kleen * annotate, but right now we need the per byte offsets arrays, 93730e863bbSAndi Kleen * which are only here. 93830e863bbSAndi Kleen */ 93930e863bbSAndi Kleen static void annotate__compute_ipc(struct annotate_browser *browser, size_t size, 94030e863bbSAndi Kleen struct symbol *sym) 94130e863bbSAndi Kleen { 94230e863bbSAndi Kleen u64 offset; 94330e863bbSAndi Kleen struct annotation *notes = symbol__annotation(sym); 94430e863bbSAndi Kleen 94530e863bbSAndi Kleen if (!notes->src || !notes->src->cycles_hist) 94630e863bbSAndi Kleen return; 94730e863bbSAndi Kleen 94830e863bbSAndi Kleen pthread_mutex_lock(¬es->lock); 94930e863bbSAndi Kleen for (offset = 0; offset < size; ++offset) { 95030e863bbSAndi Kleen struct cyc_hist *ch; 95130e863bbSAndi Kleen 95230e863bbSAndi Kleen ch = ¬es->src->cycles_hist[offset]; 95330e863bbSAndi Kleen if (ch && ch->cycles) { 95430e863bbSAndi Kleen struct disasm_line *dl; 95530e863bbSAndi Kleen 95630e863bbSAndi Kleen if (ch->have_start) 95730e863bbSAndi Kleen count_and_fill(browser, ch->start, offset, ch); 95830e863bbSAndi Kleen dl = browser->offsets[offset]; 95930e863bbSAndi Kleen if (dl && ch->num_aggr) 96030e863bbSAndi Kleen dl->cycles = ch->cycles_aggr / ch->num_aggr; 96130e863bbSAndi Kleen browser->have_cycles = true; 96230e863bbSAndi Kleen } 96330e863bbSAndi Kleen } 96430e863bbSAndi Kleen pthread_mutex_unlock(¬es->lock); 96530e863bbSAndi Kleen } 96630e863bbSAndi Kleen 967b793a401SArnaldo Carvalho de Melo static void annotate_browser__mark_jump_targets(struct annotate_browser *browser, 968b793a401SArnaldo Carvalho de Melo size_t size) 969b793a401SArnaldo Carvalho de Melo { 970b793a401SArnaldo Carvalho de Melo u64 offset; 97132ae1efdSNamhyung Kim struct map_symbol *ms = browser->b.priv; 97232ae1efdSNamhyung Kim struct symbol *sym = ms->sym; 97332ae1efdSNamhyung Kim 97432ae1efdSNamhyung Kim /* PLT symbols contain external offsets */ 97532ae1efdSNamhyung Kim if (strstr(sym->name, "@plt")) 97632ae1efdSNamhyung Kim return; 977b793a401SArnaldo Carvalho de Melo 978b793a401SArnaldo Carvalho de Melo for (offset = 0; offset < size; ++offset) { 979b793a401SArnaldo Carvalho de Melo struct disasm_line *dl = browser->offsets[offset], *dlt; 980b793a401SArnaldo Carvalho de Melo struct browser_disasm_line *bdlt; 981b793a401SArnaldo Carvalho de Melo 982865c66c4SFrederik Deweerdt if (!disasm_line__is_valid_jump(dl, sym)) 983b793a401SArnaldo Carvalho de Melo continue; 984b793a401SArnaldo Carvalho de Melo 98544d1a3edSArnaldo Carvalho de Melo dlt = browser->offsets[dl->ops.target.offset]; 9869481ede9SArnaldo Carvalho de Melo /* 9879481ede9SArnaldo Carvalho de Melo * FIXME: Oops, no jump target? Buggy disassembler? Or do we 9889481ede9SArnaldo Carvalho de Melo * have to adjust to the previous offset? 9899481ede9SArnaldo Carvalho de Melo */ 9909481ede9SArnaldo Carvalho de Melo if (dlt == NULL) 9919481ede9SArnaldo Carvalho de Melo continue; 9929481ede9SArnaldo Carvalho de Melo 993b793a401SArnaldo Carvalho de Melo bdlt = disasm_line__browser(dlt); 9942402e4a9SArnaldo Carvalho de Melo if (++bdlt->jump_sources > browser->max_jump_sources) 9952402e4a9SArnaldo Carvalho de Melo browser->max_jump_sources = bdlt->jump_sources; 9962402e4a9SArnaldo Carvalho de Melo 9972402e4a9SArnaldo Carvalho de Melo ++browser->nr_jumps; 998b793a401SArnaldo Carvalho de Melo } 999b793a401SArnaldo Carvalho de Melo } 1000b793a401SArnaldo Carvalho de Melo 10012402e4a9SArnaldo Carvalho de Melo static inline int width_jumps(int n) 10022402e4a9SArnaldo Carvalho de Melo { 10032402e4a9SArnaldo Carvalho de Melo if (n >= 100) 10042402e4a9SArnaldo Carvalho de Melo return 5; 10052402e4a9SArnaldo Carvalho de Melo if (n / 10) 10062402e4a9SArnaldo Carvalho de Melo return 2; 10072402e4a9SArnaldo Carvalho de Melo return 1; 10082402e4a9SArnaldo Carvalho de Melo } 10092402e4a9SArnaldo Carvalho de Melo 1010db8fd07aSNamhyung Kim int symbol__tui_annotate(struct symbol *sym, struct map *map, 1011db8fd07aSNamhyung Kim struct perf_evsel *evsel, 10129783adf7SNamhyung Kim struct hist_browser_timer *hbt) 1013aca7a94dSNamhyung Kim { 101429ed6e76SArnaldo Carvalho de Melo struct disasm_line *pos, *n; 1015aca7a94dSNamhyung Kim struct annotation *notes; 1016c0a58fb2SSamuel Liao size_t size; 1017aca7a94dSNamhyung Kim struct map_symbol ms = { 1018aca7a94dSNamhyung Kim .map = map, 1019aca7a94dSNamhyung Kim .sym = sym, 1020aca7a94dSNamhyung Kim }; 1021aca7a94dSNamhyung Kim struct annotate_browser browser = { 1022aca7a94dSNamhyung Kim .b = { 1023a3f895beSArnaldo Carvalho de Melo .refresh = annotate_browser__refresh, 1024aca7a94dSNamhyung Kim .seek = ui_browser__list_head_seek, 1025aca7a94dSNamhyung Kim .write = annotate_browser__write, 102629ed6e76SArnaldo Carvalho de Melo .filter = disasm_line__filter, 1027aca7a94dSNamhyung Kim .priv = &ms, 1028aca7a94dSNamhyung Kim .use_navkeypressed = true, 1029aca7a94dSNamhyung Kim }, 1030aca7a94dSNamhyung Kim }; 1031b793a401SArnaldo Carvalho de Melo int ret = -1; 1032c7e7b610SNamhyung Kim int nr_pcnt = 1; 1033c7e7b610SNamhyung Kim size_t sizeof_bdl = sizeof(struct browser_disasm_line); 1034aca7a94dSNamhyung Kim 1035aca7a94dSNamhyung Kim if (sym == NULL) 1036aca7a94dSNamhyung Kim return -1; 1037aca7a94dSNamhyung Kim 1038c0a58fb2SSamuel Liao size = symbol__size(sym); 1039c0a58fb2SSamuel Liao 1040aca7a94dSNamhyung Kim if (map->dso->annotate_warned) 1041aca7a94dSNamhyung Kim return -1; 1042aca7a94dSNamhyung Kim 1043b793a401SArnaldo Carvalho de Melo browser.offsets = zalloc(size * sizeof(struct disasm_line *)); 1044b793a401SArnaldo Carvalho de Melo if (browser.offsets == NULL) { 1045b793a401SArnaldo Carvalho de Melo ui__error("Not enough memory!"); 1046b793a401SArnaldo Carvalho de Melo return -1; 1047b793a401SArnaldo Carvalho de Melo } 1048b793a401SArnaldo Carvalho de Melo 1049c7e7b610SNamhyung Kim if (perf_evsel__is_group_event(evsel)) { 1050c7e7b610SNamhyung Kim nr_pcnt = evsel->nr_members; 10510c4a5bceSMartin Liška sizeof_bdl += sizeof(struct disasm_line_samples) * 10520c4a5bceSMartin Liška (nr_pcnt - 1); 1053c7e7b610SNamhyung Kim } 1054c7e7b610SNamhyung Kim 1055c7e7b610SNamhyung Kim if (symbol__annotate(sym, map, sizeof_bdl) < 0) { 1056aca7a94dSNamhyung Kim ui__error("%s", ui_helpline__last_msg); 1057b793a401SArnaldo Carvalho de Melo goto out_free_offsets; 1058aca7a94dSNamhyung Kim } 1059aca7a94dSNamhyung Kim 10607727a925SArnaldo Carvalho de Melo ui_helpline__push("Press ESC to exit"); 1061aca7a94dSNamhyung Kim 1062aca7a94dSNamhyung Kim notes = symbol__annotation(sym); 1063aca7a94dSNamhyung Kim browser.start = map__rip_2objdump(map, sym->start); 1064aca7a94dSNamhyung Kim 1065aca7a94dSNamhyung Kim list_for_each_entry(pos, ¬es->src->source, node) { 1066887c0066SArnaldo Carvalho de Melo struct browser_disasm_line *bpos; 1067aca7a94dSNamhyung Kim size_t line_len = strlen(pos->line); 1068aca7a94dSNamhyung Kim 1069aca7a94dSNamhyung Kim if (browser.b.width < line_len) 1070aca7a94dSNamhyung Kim browser.b.width = line_len; 1071887c0066SArnaldo Carvalho de Melo bpos = disasm_line__browser(pos); 1072887c0066SArnaldo Carvalho de Melo bpos->idx = browser.nr_entries++; 1073b793a401SArnaldo Carvalho de Melo if (pos->offset != -1) { 1074887c0066SArnaldo Carvalho de Melo bpos->idx_asm = browser.nr_asm_entries++; 107597148a97SArnaldo Carvalho de Melo /* 107697148a97SArnaldo Carvalho de Melo * FIXME: short term bandaid to cope with assembly 107797148a97SArnaldo Carvalho de Melo * routines that comes with labels in the same column 107897148a97SArnaldo Carvalho de Melo * as the address in objdump, sigh. 107997148a97SArnaldo Carvalho de Melo * 108097148a97SArnaldo Carvalho de Melo * E.g. copy_user_generic_unrolled 108197148a97SArnaldo Carvalho de Melo */ 108297148a97SArnaldo Carvalho de Melo if (pos->offset < (s64)size) 1083b793a401SArnaldo Carvalho de Melo browser.offsets[pos->offset] = pos; 1084b793a401SArnaldo Carvalho de Melo } else 1085887c0066SArnaldo Carvalho de Melo bpos->idx_asm = -1; 1086aca7a94dSNamhyung Kim } 1087aca7a94dSNamhyung Kim 1088b793a401SArnaldo Carvalho de Melo annotate_browser__mark_jump_targets(&browser, size); 108930e863bbSAndi Kleen annotate__compute_ipc(&browser, size, sym); 1090b793a401SArnaldo Carvalho de Melo 10912402e4a9SArnaldo Carvalho de Melo browser.addr_width = browser.target_width = browser.min_addr_width = hex_width(size); 109283b1f2aaSArnaldo Carvalho de Melo browser.max_addr_width = hex_width(sym->end); 10932402e4a9SArnaldo Carvalho de Melo browser.jumps_width = width_jumps(browser.max_jump_sources); 1094c7e7b610SNamhyung Kim browser.nr_events = nr_pcnt; 1095aca7a94dSNamhyung Kim browser.b.nr_entries = browser.nr_entries; 1096aca7a94dSNamhyung Kim browser.b.entries = ¬es->src->source, 1097aca7a94dSNamhyung Kim browser.b.width += 18; /* Percentage */ 1098e9823b21SArnaldo Carvalho de Melo 1099e9823b21SArnaldo Carvalho de Melo if (annotate_browser__opts.hide_src_code) 1100e9823b21SArnaldo Carvalho de Melo annotate_browser__init_asm_mode(&browser); 1101e9823b21SArnaldo Carvalho de Melo 1102e9823b21SArnaldo Carvalho de Melo annotate_browser__update_addr_width(&browser); 1103e9823b21SArnaldo Carvalho de Melo 1104db8fd07aSNamhyung Kim ret = annotate_browser__run(&browser, evsel, hbt); 1105aca7a94dSNamhyung Kim list_for_each_entry_safe(pos, n, ¬es->src->source, node) { 1106aca7a94dSNamhyung Kim list_del(&pos->node); 110729ed6e76SArnaldo Carvalho de Melo disasm_line__free(pos); 1108aca7a94dSNamhyung Kim } 1109b793a401SArnaldo Carvalho de Melo 1110b793a401SArnaldo Carvalho de Melo out_free_offsets: 1111b793a401SArnaldo Carvalho de Melo free(browser.offsets); 1112aca7a94dSNamhyung Kim return ret; 1113aca7a94dSNamhyung Kim } 1114c323cf04SArnaldo Carvalho de Melo 1115c323cf04SArnaldo Carvalho de Melo #define ANNOTATE_CFG(n) \ 1116c323cf04SArnaldo Carvalho de Melo { .name = #n, .value = &annotate_browser__opts.n, } 1117c323cf04SArnaldo Carvalho de Melo 1118c323cf04SArnaldo Carvalho de Melo /* 1119c323cf04SArnaldo Carvalho de Melo * Keep the entries sorted, they are bsearch'ed 1120c323cf04SArnaldo Carvalho de Melo */ 11217c3102b8SArnaldo Carvalho de Melo static struct annotate_config { 1122c323cf04SArnaldo Carvalho de Melo const char *name; 1123c323cf04SArnaldo Carvalho de Melo bool *value; 1124c323cf04SArnaldo Carvalho de Melo } annotate__configs[] = { 1125c323cf04SArnaldo Carvalho de Melo ANNOTATE_CFG(hide_src_code), 1126c323cf04SArnaldo Carvalho de Melo ANNOTATE_CFG(jump_arrows), 1127e592488cSAndi Kleen ANNOTATE_CFG(show_linenr), 1128c323cf04SArnaldo Carvalho de Melo ANNOTATE_CFG(show_nr_jumps), 11290c4a5bceSMartin Liška ANNOTATE_CFG(show_total_period), 113039ff7cdbSNamhyung Kim ANNOTATE_CFG(use_offset), 1131c323cf04SArnaldo Carvalho de Melo }; 1132c323cf04SArnaldo Carvalho de Melo 1133c323cf04SArnaldo Carvalho de Melo #undef ANNOTATE_CFG 1134c323cf04SArnaldo Carvalho de Melo 1135c323cf04SArnaldo Carvalho de Melo static int annotate_config__cmp(const void *name, const void *cfgp) 1136c323cf04SArnaldo Carvalho de Melo { 11377c3102b8SArnaldo Carvalho de Melo const struct annotate_config *cfg = cfgp; 1138c323cf04SArnaldo Carvalho de Melo 1139c323cf04SArnaldo Carvalho de Melo return strcmp(name, cfg->name); 1140c323cf04SArnaldo Carvalho de Melo } 1141c323cf04SArnaldo Carvalho de Melo 11421d037ca1SIrina Tirdea static int annotate__config(const char *var, const char *value, 11431d037ca1SIrina Tirdea void *data __maybe_unused) 1144c323cf04SArnaldo Carvalho de Melo { 11457c3102b8SArnaldo Carvalho de Melo struct annotate_config *cfg; 1146c323cf04SArnaldo Carvalho de Melo const char *name; 1147c323cf04SArnaldo Carvalho de Melo 1148c323cf04SArnaldo Carvalho de Melo if (prefixcmp(var, "annotate.") != 0) 1149c323cf04SArnaldo Carvalho de Melo return 0; 1150c323cf04SArnaldo Carvalho de Melo 1151c323cf04SArnaldo Carvalho de Melo name = var + 9; 1152c323cf04SArnaldo Carvalho de Melo cfg = bsearch(name, annotate__configs, ARRAY_SIZE(annotate__configs), 11537c3102b8SArnaldo Carvalho de Melo sizeof(struct annotate_config), annotate_config__cmp); 1154c323cf04SArnaldo Carvalho de Melo 1155c323cf04SArnaldo Carvalho de Melo if (cfg == NULL) 1156f06cff7cSArnaldo Carvalho de Melo ui__warning("%s variable unknown, ignoring...", var); 1157f06cff7cSArnaldo Carvalho de Melo else 1158c323cf04SArnaldo Carvalho de Melo *cfg->value = perf_config_bool(name, value); 1159c323cf04SArnaldo Carvalho de Melo return 0; 1160c323cf04SArnaldo Carvalho de Melo } 1161c323cf04SArnaldo Carvalho de Melo 1162c323cf04SArnaldo Carvalho de Melo void annotate_browser__init(void) 1163c323cf04SArnaldo Carvalho de Melo { 1164c323cf04SArnaldo Carvalho de Melo perf_config(annotate__config, NULL); 1165c323cf04SArnaldo Carvalho de Melo } 1166