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" 1141840d21STaeung Song #include "../../util/config.h" 12fd20e811SArnaldo Carvalho de Melo #include <inttypes.h> 13aca7a94dSNamhyung Kim #include <pthread.h> 14877a7a11SArnaldo Carvalho de Melo #include <linux/kernel.h> 15b0742e90SArnaldo Carvalho de Melo #include <sys/ttydefaults.h> 16aca7a94dSNamhyung Kim 170c4a5bceSMartin Liška struct disasm_line_samples { 180c4a5bceSMartin Liška double percent; 190c4a5bceSMartin Liška u64 nr; 200c4a5bceSMartin Liška }; 210c4a5bceSMartin Liška 22f8f4aaeaSAndi Kleen #define IPC_WIDTH 6 23f8f4aaeaSAndi Kleen #define CYCLES_WIDTH 6 24f8f4aaeaSAndi Kleen 25b793a401SArnaldo Carvalho de Melo struct browser_disasm_line { 26b793a401SArnaldo Carvalho de Melo struct rb_node rb_node; 27b793a401SArnaldo Carvalho de Melo u32 idx; 28b793a401SArnaldo Carvalho de Melo int idx_asm; 297d5b12f5SArnaldo Carvalho de Melo int jump_sources; 30c7e7b610SNamhyung Kim /* 31c7e7b610SNamhyung Kim * actual length of this array is saved on the nr_events field 32c7e7b610SNamhyung Kim * of the struct annotate_browser 33c7e7b610SNamhyung Kim */ 340c4a5bceSMartin Liška struct disasm_line_samples samples[1]; 35b793a401SArnaldo Carvalho de Melo }; 36b793a401SArnaldo Carvalho de Melo 37e9823b21SArnaldo Carvalho de Melo static struct annotate_browser_opt { 38e9823b21SArnaldo Carvalho de Melo bool hide_src_code, 39e9823b21SArnaldo Carvalho de Melo use_offset, 40e9823b21SArnaldo Carvalho de Melo jump_arrows, 41e592488cSAndi Kleen show_linenr, 420c4a5bceSMartin Liška show_nr_jumps, 430c4a5bceSMartin Liška show_total_period; 44e9823b21SArnaldo Carvalho de Melo } annotate_browser__opts = { 45e9823b21SArnaldo Carvalho de Melo .use_offset = true, 46e9823b21SArnaldo Carvalho de Melo .jump_arrows = true, 47e9823b21SArnaldo Carvalho de Melo }; 48e9823b21SArnaldo Carvalho de Melo 49aca7a94dSNamhyung Kim struct annotate_browser { 50aca7a94dSNamhyung Kim struct ui_browser b; 51aca7a94dSNamhyung Kim struct rb_root entries; 52aca7a94dSNamhyung Kim struct rb_node *curr_hot; 5329ed6e76SArnaldo Carvalho de Melo struct disasm_line *selection; 54b793a401SArnaldo Carvalho de Melo struct disasm_line **offsets; 55c7e7b610SNamhyung Kim int nr_events; 56aca7a94dSNamhyung Kim u64 start; 57aca7a94dSNamhyung Kim int nr_asm_entries; 58aca7a94dSNamhyung Kim int nr_entries; 592402e4a9SArnaldo Carvalho de Melo int max_jump_sources; 602402e4a9SArnaldo Carvalho de Melo int nr_jumps; 61aca7a94dSNamhyung Kim bool searching_backwards; 6230e863bbSAndi Kleen bool have_cycles; 6383b1f2aaSArnaldo Carvalho de Melo u8 addr_width; 642402e4a9SArnaldo Carvalho de Melo u8 jumps_width; 652402e4a9SArnaldo Carvalho de Melo u8 target_width; 6683b1f2aaSArnaldo Carvalho de Melo u8 min_addr_width; 6783b1f2aaSArnaldo Carvalho de Melo u8 max_addr_width; 68aca7a94dSNamhyung Kim char search_bf[128]; 69aca7a94dSNamhyung Kim }; 70aca7a94dSNamhyung Kim 71887c0066SArnaldo Carvalho de Melo static inline struct browser_disasm_line *disasm_line__browser(struct disasm_line *dl) 72aca7a94dSNamhyung Kim { 73887c0066SArnaldo Carvalho de Melo return (struct browser_disasm_line *)(dl + 1); 74aca7a94dSNamhyung Kim } 75aca7a94dSNamhyung Kim 761d037ca1SIrina Tirdea static bool disasm_line__filter(struct ui_browser *browser __maybe_unused, 771d037ca1SIrina Tirdea void *entry) 78aca7a94dSNamhyung Kim { 79e9823b21SArnaldo Carvalho de Melo if (annotate_browser__opts.hide_src_code) { 8029ed6e76SArnaldo Carvalho de Melo struct disasm_line *dl = list_entry(entry, struct disasm_line, node); 8129ed6e76SArnaldo Carvalho de Melo return dl->offset == -1; 82aca7a94dSNamhyung Kim } 83aca7a94dSNamhyung Kim 84aca7a94dSNamhyung Kim return false; 85aca7a94dSNamhyung Kim } 86aca7a94dSNamhyung Kim 872402e4a9SArnaldo Carvalho de Melo static int annotate_browser__jumps_percent_color(struct annotate_browser *browser, 882402e4a9SArnaldo Carvalho de Melo int nr, bool current) 892402e4a9SArnaldo Carvalho de Melo { 902402e4a9SArnaldo Carvalho de Melo if (current && (!browser->b.use_navkeypressed || browser->b.navkeypressed)) 912402e4a9SArnaldo Carvalho de Melo return HE_COLORSET_SELECTED; 922402e4a9SArnaldo Carvalho de Melo if (nr == browser->max_jump_sources) 932402e4a9SArnaldo Carvalho de Melo return HE_COLORSET_TOP; 942402e4a9SArnaldo Carvalho de Melo if (nr > 1) 952402e4a9SArnaldo Carvalho de Melo return HE_COLORSET_MEDIUM; 962402e4a9SArnaldo Carvalho de Melo return HE_COLORSET_NORMAL; 972402e4a9SArnaldo Carvalho de Melo } 982402e4a9SArnaldo Carvalho de Melo 992402e4a9SArnaldo Carvalho de Melo static int annotate_browser__set_jumps_percent_color(struct annotate_browser *browser, 1002402e4a9SArnaldo Carvalho de Melo int nr, bool current) 1012402e4a9SArnaldo Carvalho de Melo { 1022402e4a9SArnaldo Carvalho de Melo int color = annotate_browser__jumps_percent_color(browser, nr, current); 1032402e4a9SArnaldo Carvalho de Melo return ui_browser__set_color(&browser->b, color); 1042402e4a9SArnaldo Carvalho de Melo } 1052402e4a9SArnaldo Carvalho de Melo 106f8f4aaeaSAndi Kleen static int annotate_browser__pcnt_width(struct annotate_browser *ab) 107f8f4aaeaSAndi Kleen { 108f8f4aaeaSAndi Kleen int w = 7 * ab->nr_events; 109f8f4aaeaSAndi Kleen 110f8f4aaeaSAndi Kleen if (ab->have_cycles) 111f8f4aaeaSAndi Kleen w += IPC_WIDTH + CYCLES_WIDTH; 112f8f4aaeaSAndi Kleen return w; 113f8f4aaeaSAndi Kleen } 114f8f4aaeaSAndi Kleen 11505e8b080SArnaldo Carvalho de Melo static void annotate_browser__write(struct ui_browser *browser, void *entry, int row) 116aca7a94dSNamhyung Kim { 11705e8b080SArnaldo Carvalho de Melo struct annotate_browser *ab = container_of(browser, struct annotate_browser, b); 11829ed6e76SArnaldo Carvalho de Melo struct disasm_line *dl = list_entry(entry, struct disasm_line, node); 119b793a401SArnaldo Carvalho de Melo struct browser_disasm_line *bdl = disasm_line__browser(dl); 12005e8b080SArnaldo Carvalho de Melo bool current_entry = ui_browser__is_current_entry(browser, row); 121e9823b21SArnaldo Carvalho de Melo bool change_color = (!annotate_browser__opts.hide_src_code && 12205e8b080SArnaldo Carvalho de Melo (!current_entry || (browser->use_navkeypressed && 12305e8b080SArnaldo Carvalho de Melo !browser->navkeypressed))); 12405e8b080SArnaldo Carvalho de Melo int width = browser->width, printed; 125f8f4aaeaSAndi Kleen int i, pcnt_width = annotate_browser__pcnt_width(ab); 126c7e7b610SNamhyung Kim double percent_max = 0.0; 12783b1f2aaSArnaldo Carvalho de Melo char bf[256]; 128*ec27ae18SJin Yao bool show_title = false; 129aca7a94dSNamhyung Kim 130c7e7b610SNamhyung Kim for (i = 0; i < ab->nr_events; i++) { 1310c4a5bceSMartin Liška if (bdl->samples[i].percent > percent_max) 1320c4a5bceSMartin Liška percent_max = bdl->samples[i].percent; 133c7e7b610SNamhyung Kim } 134c7e7b610SNamhyung Kim 135*ec27ae18SJin Yao if ((row == 0) && (dl->offset == -1 || percent_max == 0.0)) { 136*ec27ae18SJin Yao if (ab->have_cycles) { 137*ec27ae18SJin Yao if (dl->ipc == 0.0 && dl->cycles == 0) 138*ec27ae18SJin Yao show_title = true; 139*ec27ae18SJin Yao } else 140*ec27ae18SJin Yao show_title = true; 141*ec27ae18SJin Yao } 142*ec27ae18SJin Yao 143c7e7b610SNamhyung Kim if (dl->offset != -1 && percent_max != 0.0) { 144c7e7b610SNamhyung Kim for (i = 0; i < ab->nr_events; i++) { 1450c4a5bceSMartin Liška ui_browser__set_percent_color(browser, 1460c4a5bceSMartin Liška bdl->samples[i].percent, 147c7e7b610SNamhyung Kim current_entry); 148517dfdb3SArnaldo Carvalho de Melo if (annotate_browser__opts.show_total_period) { 149517dfdb3SArnaldo Carvalho de Melo ui_browser__printf(browser, "%6" PRIu64 " ", 1500c4a5bceSMartin Liška bdl->samples[i].nr); 151517dfdb3SArnaldo Carvalho de Melo } else { 152517dfdb3SArnaldo Carvalho de Melo ui_browser__printf(browser, "%6.2f ", 153517dfdb3SArnaldo Carvalho de Melo bdl->samples[i].percent); 154517dfdb3SArnaldo Carvalho de Melo } 155c7e7b610SNamhyung Kim } 156aca7a94dSNamhyung Kim } else { 15705e8b080SArnaldo Carvalho de Melo ui_browser__set_percent_color(browser, 0, current_entry); 158*ec27ae18SJin Yao 159*ec27ae18SJin Yao if (!show_title) 16026270a00SArnaldo Carvalho de Melo ui_browser__write_nstring(browser, " ", 7 * ab->nr_events); 161*ec27ae18SJin Yao else 162*ec27ae18SJin Yao ui_browser__printf(browser, "%*s", 7, "Percent"); 163f8f4aaeaSAndi Kleen } 164f8f4aaeaSAndi Kleen if (ab->have_cycles) { 165f8f4aaeaSAndi Kleen if (dl->ipc) 166517dfdb3SArnaldo Carvalho de Melo ui_browser__printf(browser, "%*.2f ", IPC_WIDTH - 1, dl->ipc); 167*ec27ae18SJin Yao else if (!show_title) 16826270a00SArnaldo Carvalho de Melo ui_browser__write_nstring(browser, " ", IPC_WIDTH); 169*ec27ae18SJin Yao else 170*ec27ae18SJin Yao ui_browser__printf(browser, "%*s ", IPC_WIDTH - 1, "IPC"); 171*ec27ae18SJin Yao 172f8f4aaeaSAndi Kleen if (dl->cycles) 173517dfdb3SArnaldo Carvalho de Melo ui_browser__printf(browser, "%*" PRIu64 " ", 174f8f4aaeaSAndi Kleen CYCLES_WIDTH - 1, dl->cycles); 175*ec27ae18SJin Yao else if (!show_title) 17626270a00SArnaldo Carvalho de Melo ui_browser__write_nstring(browser, " ", CYCLES_WIDTH); 177*ec27ae18SJin Yao else 178*ec27ae18SJin Yao ui_browser__printf(browser, "%*s ", CYCLES_WIDTH - 1, "Cycle"); 179aca7a94dSNamhyung Kim } 180aca7a94dSNamhyung Kim 181cf2dacc5SArnaldo Carvalho de Melo SLsmg_write_char(' '); 182aca7a94dSNamhyung Kim 183aca7a94dSNamhyung Kim /* The scroll bar isn't being used */ 18405e8b080SArnaldo Carvalho de Melo if (!browser->navkeypressed) 185aca7a94dSNamhyung Kim width += 1; 186aca7a94dSNamhyung Kim 18729ed6e76SArnaldo Carvalho de Melo if (!*dl->line) 18826270a00SArnaldo Carvalho de Melo ui_browser__write_nstring(browser, " ", width - pcnt_width); 18983b1f2aaSArnaldo Carvalho de Melo else if (dl->offset == -1) { 190e592488cSAndi Kleen if (dl->line_nr && annotate_browser__opts.show_linenr) 191e592488cSAndi Kleen printed = scnprintf(bf, sizeof(bf), "%-*d ", 192e592488cSAndi Kleen ab->addr_width + 1, dl->line_nr); 193e592488cSAndi Kleen else 19483b1f2aaSArnaldo Carvalho de Melo printed = scnprintf(bf, sizeof(bf), "%*s ", 19583b1f2aaSArnaldo Carvalho de Melo ab->addr_width, " "); 19626270a00SArnaldo Carvalho de Melo ui_browser__write_nstring(browser, bf, printed); 19726270a00SArnaldo Carvalho de Melo ui_browser__write_nstring(browser, dl->line, width - printed - pcnt_width + 1); 19883b1f2aaSArnaldo Carvalho de Melo } else { 19929ed6e76SArnaldo Carvalho de Melo u64 addr = dl->offset; 20083b1f2aaSArnaldo Carvalho de Melo int color = -1; 201aca7a94dSNamhyung Kim 202e9823b21SArnaldo Carvalho de Melo if (!annotate_browser__opts.use_offset) 203aca7a94dSNamhyung Kim addr += ab->start; 204aca7a94dSNamhyung Kim 205e9823b21SArnaldo Carvalho de Melo if (!annotate_browser__opts.use_offset) { 206aca7a94dSNamhyung Kim printed = scnprintf(bf, sizeof(bf), "%" PRIx64 ": ", addr); 20761e04b33SArnaldo Carvalho de Melo } else { 2087d5b12f5SArnaldo Carvalho de Melo if (bdl->jump_sources) { 209e9823b21SArnaldo Carvalho de Melo if (annotate_browser__opts.show_nr_jumps) { 2102402e4a9SArnaldo Carvalho de Melo int prev; 2112402e4a9SArnaldo Carvalho de Melo printed = scnprintf(bf, sizeof(bf), "%*d ", 2122402e4a9SArnaldo Carvalho de Melo ab->jumps_width, 2132402e4a9SArnaldo Carvalho de Melo bdl->jump_sources); 2142402e4a9SArnaldo Carvalho de Melo prev = annotate_browser__set_jumps_percent_color(ab, bdl->jump_sources, 2152402e4a9SArnaldo Carvalho de Melo current_entry); 21626270a00SArnaldo Carvalho de Melo ui_browser__write_nstring(browser, bf, printed); 21705e8b080SArnaldo Carvalho de Melo ui_browser__set_color(browser, prev); 2182402e4a9SArnaldo Carvalho de Melo } 2192402e4a9SArnaldo Carvalho de Melo 22061e04b33SArnaldo Carvalho de Melo printed = scnprintf(bf, sizeof(bf), "%*" PRIx64 ": ", 2212402e4a9SArnaldo Carvalho de Melo ab->target_width, addr); 22261e04b33SArnaldo Carvalho de Melo } else { 22361e04b33SArnaldo Carvalho de Melo printed = scnprintf(bf, sizeof(bf), "%*s ", 22483b1f2aaSArnaldo Carvalho de Melo ab->addr_width, " "); 22561e04b33SArnaldo Carvalho de Melo } 22661e04b33SArnaldo Carvalho de Melo } 227b793a401SArnaldo Carvalho de Melo 228aca7a94dSNamhyung Kim if (change_color) 22905e8b080SArnaldo Carvalho de Melo color = ui_browser__set_color(browser, HE_COLORSET_ADDR); 23026270a00SArnaldo Carvalho de Melo ui_browser__write_nstring(browser, bf, printed); 231aca7a94dSNamhyung Kim if (change_color) 23205e8b080SArnaldo Carvalho de Melo ui_browser__set_color(browser, color); 23375b49202SArnaldo Carvalho de Melo if (dl->ins.ops && dl->ins.ops->scnprintf) { 23475b49202SArnaldo Carvalho de Melo if (ins__is_jump(&dl->ins)) { 235e216874cSRavi Bangoria bool fwd = dl->ops.target.offset > dl->offset; 23651a0d455SArnaldo Carvalho de Melo 23705e8b080SArnaldo Carvalho de Melo ui_browser__write_graph(browser, fwd ? SLSMG_DARROW_CHAR : 23851a0d455SArnaldo Carvalho de Melo SLSMG_UARROW_CHAR); 23951a0d455SArnaldo Carvalho de Melo SLsmg_write_char(' '); 24075b49202SArnaldo Carvalho de Melo } else if (ins__is_call(&dl->ins)) { 24105e8b080SArnaldo Carvalho de Melo ui_browser__write_graph(browser, SLSMG_RARROW_CHAR); 24288298f5aSArnaldo Carvalho de Melo SLsmg_write_char(' '); 24375b49202SArnaldo Carvalho de Melo } else if (ins__is_ret(&dl->ins)) { 24405e8b080SArnaldo Carvalho de Melo ui_browser__write_graph(browser, SLSMG_LARROW_CHAR); 2454ea08b52SArnaldo Carvalho de Melo SLsmg_write_char(' '); 2466ef94929SNaveen N. Rao } else { 2476ef94929SNaveen N. Rao ui_browser__write_nstring(browser, " ", 2); 2484ea08b52SArnaldo Carvalho de Melo } 2496ef94929SNaveen N. Rao } else { 2506ef94929SNaveen N. Rao ui_browser__write_nstring(browser, " ", 2); 2514ea08b52SArnaldo Carvalho de Melo } 2524ea08b52SArnaldo Carvalho de Melo 253e9823b21SArnaldo Carvalho de Melo disasm_line__scnprintf(dl, bf, sizeof(bf), !annotate_browser__opts.use_offset); 25426270a00SArnaldo Carvalho de Melo ui_browser__write_nstring(browser, bf, width - pcnt_width - 3 - printed); 255aca7a94dSNamhyung Kim } 256aca7a94dSNamhyung Kim 257aca7a94dSNamhyung Kim if (current_entry) 25829ed6e76SArnaldo Carvalho de Melo ab->selection = dl; 259aca7a94dSNamhyung Kim } 260aca7a94dSNamhyung Kim 261865c66c4SFrederik Deweerdt static bool disasm_line__is_valid_jump(struct disasm_line *dl, struct symbol *sym) 262865c66c4SFrederik Deweerdt { 26375b49202SArnaldo Carvalho de Melo if (!dl || !dl->ins.ops || !ins__is_jump(&dl->ins) 264865c66c4SFrederik Deweerdt || !disasm_line__has_offset(dl) 265e216874cSRavi Bangoria || dl->ops.target.offset < 0 266e216874cSRavi Bangoria || dl->ops.target.offset >= (s64)symbol__size(sym)) 267865c66c4SFrederik Deweerdt return false; 268865c66c4SFrederik Deweerdt 269865c66c4SFrederik Deweerdt return true; 270865c66c4SFrederik Deweerdt } 271865c66c4SFrederik Deweerdt 2729d1ef56dSArnaldo Carvalho de Melo static void annotate_browser__draw_current_jump(struct ui_browser *browser) 273a3f895beSArnaldo Carvalho de Melo { 274a3f895beSArnaldo Carvalho de Melo struct annotate_browser *ab = container_of(browser, struct annotate_browser, b); 2759d1ef56dSArnaldo Carvalho de Melo struct disasm_line *cursor = ab->selection, *target; 2769d1ef56dSArnaldo Carvalho de Melo struct browser_disasm_line *btarget, *bcursor; 27783b1f2aaSArnaldo Carvalho de Melo unsigned int from, to; 27832ae1efdSNamhyung Kim struct map_symbol *ms = ab->b.priv; 27932ae1efdSNamhyung Kim struct symbol *sym = ms->sym; 280f8f4aaeaSAndi Kleen u8 pcnt_width = annotate_browser__pcnt_width(ab); 28132ae1efdSNamhyung Kim 28232ae1efdSNamhyung Kim /* PLT symbols contain external offsets */ 28332ae1efdSNamhyung Kim if (strstr(sym->name, "@plt")) 28432ae1efdSNamhyung Kim return; 285a3f895beSArnaldo Carvalho de Melo 286865c66c4SFrederik Deweerdt if (!disasm_line__is_valid_jump(cursor, sym)) 287a3f895beSArnaldo Carvalho de Melo return; 288a3f895beSArnaldo Carvalho de Melo 2899d1ef56dSArnaldo Carvalho de Melo target = ab->offsets[cursor->ops.target.offset]; 2909d1ef56dSArnaldo Carvalho de Melo if (!target) 2919d1ef56dSArnaldo Carvalho de Melo return; 2929d1ef56dSArnaldo Carvalho de Melo 2939d1ef56dSArnaldo Carvalho de Melo bcursor = disasm_line__browser(cursor); 2949d1ef56dSArnaldo Carvalho de Melo btarget = disasm_line__browser(target); 2959d1ef56dSArnaldo Carvalho de Melo 296e9823b21SArnaldo Carvalho de Melo if (annotate_browser__opts.hide_src_code) { 2979d1ef56dSArnaldo Carvalho de Melo from = bcursor->idx_asm; 298a3f895beSArnaldo Carvalho de Melo to = btarget->idx_asm; 299a3f895beSArnaldo Carvalho de Melo } else { 3009d1ef56dSArnaldo Carvalho de Melo from = (u64)bcursor->idx; 301a3f895beSArnaldo Carvalho de Melo to = (u64)btarget->idx; 302a3f895beSArnaldo Carvalho de Melo } 303a3f895beSArnaldo Carvalho de Melo 30478ce08dfSTaeung Song ui_browser__set_color(browser, HE_COLORSET_JUMP_ARROWS); 305c7e7b610SNamhyung Kim __ui_browser__line_arrow(browser, pcnt_width + 2 + ab->addr_width, 306c7e7b610SNamhyung Kim from, to); 307a3f895beSArnaldo Carvalho de Melo } 308a3f895beSArnaldo Carvalho de Melo 309a3f895beSArnaldo Carvalho de Melo static unsigned int annotate_browser__refresh(struct ui_browser *browser) 310a3f895beSArnaldo Carvalho de Melo { 311c7e7b610SNamhyung Kim struct annotate_browser *ab = container_of(browser, struct annotate_browser, b); 312a3f895beSArnaldo Carvalho de Melo int ret = ui_browser__list_head_refresh(browser); 313f8f4aaeaSAndi Kleen int pcnt_width = annotate_browser__pcnt_width(ab); 314a3f895beSArnaldo Carvalho de Melo 315e9823b21SArnaldo Carvalho de Melo if (annotate_browser__opts.jump_arrows) 3169d1ef56dSArnaldo Carvalho de Melo annotate_browser__draw_current_jump(browser); 317a3f895beSArnaldo Carvalho de Melo 31883b1f2aaSArnaldo Carvalho de Melo ui_browser__set_color(browser, HE_COLORSET_NORMAL); 319c7e7b610SNamhyung Kim __ui_browser__vline(browser, pcnt_width, 0, browser->height - 1); 320a3f895beSArnaldo Carvalho de Melo return ret; 321a3f895beSArnaldo Carvalho de Melo } 322a3f895beSArnaldo Carvalho de Melo 323c7e7b610SNamhyung Kim static int disasm__cmp(struct browser_disasm_line *a, 324c7e7b610SNamhyung Kim struct browser_disasm_line *b, int nr_pcnt) 325c7e7b610SNamhyung Kim { 326c7e7b610SNamhyung Kim int i; 327c7e7b610SNamhyung Kim 328c7e7b610SNamhyung Kim for (i = 0; i < nr_pcnt; i++) { 3290c4a5bceSMartin Liška if (a->samples[i].percent == b->samples[i].percent) 330c7e7b610SNamhyung Kim continue; 3310c4a5bceSMartin Liška return a->samples[i].percent < b->samples[i].percent; 332c7e7b610SNamhyung Kim } 333c7e7b610SNamhyung Kim return 0; 334c7e7b610SNamhyung Kim } 335c7e7b610SNamhyung Kim 336c7e7b610SNamhyung Kim static void disasm_rb_tree__insert(struct rb_root *root, struct browser_disasm_line *bdl, 337c7e7b610SNamhyung Kim int nr_events) 338aca7a94dSNamhyung Kim { 33929ed6e76SArnaldo Carvalho de Melo struct rb_node **p = &root->rb_node; 340aca7a94dSNamhyung Kim struct rb_node *parent = NULL; 341887c0066SArnaldo Carvalho de Melo struct browser_disasm_line *l; 342aca7a94dSNamhyung Kim 343aca7a94dSNamhyung Kim while (*p != NULL) { 344aca7a94dSNamhyung Kim parent = *p; 345887c0066SArnaldo Carvalho de Melo l = rb_entry(parent, struct browser_disasm_line, rb_node); 346c7e7b610SNamhyung Kim 347c7e7b610SNamhyung Kim if (disasm__cmp(bdl, l, nr_events)) 348aca7a94dSNamhyung Kim p = &(*p)->rb_left; 349aca7a94dSNamhyung Kim else 350aca7a94dSNamhyung Kim p = &(*p)->rb_right; 351aca7a94dSNamhyung Kim } 352887c0066SArnaldo Carvalho de Melo rb_link_node(&bdl->rb_node, parent, p); 353887c0066SArnaldo Carvalho de Melo rb_insert_color(&bdl->rb_node, root); 354aca7a94dSNamhyung Kim } 355aca7a94dSNamhyung Kim 35605e8b080SArnaldo Carvalho de Melo static void annotate_browser__set_top(struct annotate_browser *browser, 35729ed6e76SArnaldo Carvalho de Melo struct disasm_line *pos, u32 idx) 358aca7a94dSNamhyung Kim { 359aca7a94dSNamhyung Kim unsigned back; 360aca7a94dSNamhyung Kim 36105e8b080SArnaldo Carvalho de Melo ui_browser__refresh_dimensions(&browser->b); 36205e8b080SArnaldo Carvalho de Melo back = browser->b.height / 2; 36305e8b080SArnaldo Carvalho de Melo browser->b.top_idx = browser->b.index = idx; 364aca7a94dSNamhyung Kim 36505e8b080SArnaldo Carvalho de Melo while (browser->b.top_idx != 0 && back != 0) { 36629ed6e76SArnaldo Carvalho de Melo pos = list_entry(pos->node.prev, struct disasm_line, node); 367aca7a94dSNamhyung Kim 36805e8b080SArnaldo Carvalho de Melo if (disasm_line__filter(&browser->b, &pos->node)) 369aca7a94dSNamhyung Kim continue; 370aca7a94dSNamhyung Kim 37105e8b080SArnaldo Carvalho de Melo --browser->b.top_idx; 372aca7a94dSNamhyung Kim --back; 373aca7a94dSNamhyung Kim } 374aca7a94dSNamhyung Kim 37505e8b080SArnaldo Carvalho de Melo browser->b.top = pos; 37605e8b080SArnaldo Carvalho de Melo browser->b.navkeypressed = true; 377aca7a94dSNamhyung Kim } 378aca7a94dSNamhyung Kim 379aca7a94dSNamhyung Kim static void annotate_browser__set_rb_top(struct annotate_browser *browser, 380aca7a94dSNamhyung Kim struct rb_node *nd) 381aca7a94dSNamhyung Kim { 382887c0066SArnaldo Carvalho de Melo struct browser_disasm_line *bpos; 38329ed6e76SArnaldo Carvalho de Melo struct disasm_line *pos; 384a44b45f2SArnaldo Carvalho de Melo u32 idx; 385aca7a94dSNamhyung Kim 386887c0066SArnaldo Carvalho de Melo bpos = rb_entry(nd, struct browser_disasm_line, rb_node); 387887c0066SArnaldo Carvalho de Melo pos = ((struct disasm_line *)bpos) - 1; 388a44b45f2SArnaldo Carvalho de Melo idx = bpos->idx; 389e9823b21SArnaldo Carvalho de Melo if (annotate_browser__opts.hide_src_code) 390a44b45f2SArnaldo Carvalho de Melo idx = bpos->idx_asm; 391a44b45f2SArnaldo Carvalho de Melo annotate_browser__set_top(browser, pos, idx); 392aca7a94dSNamhyung Kim browser->curr_hot = nd; 393aca7a94dSNamhyung Kim } 394aca7a94dSNamhyung Kim 395aca7a94dSNamhyung Kim static void annotate_browser__calc_percent(struct annotate_browser *browser, 396db8fd07aSNamhyung Kim struct perf_evsel *evsel) 397aca7a94dSNamhyung Kim { 398aca7a94dSNamhyung Kim struct map_symbol *ms = browser->b.priv; 399aca7a94dSNamhyung Kim struct symbol *sym = ms->sym; 400aca7a94dSNamhyung Kim struct annotation *notes = symbol__annotation(sym); 401e64aa75bSNamhyung Kim struct disasm_line *pos, *next; 402e64aa75bSNamhyung Kim s64 len = symbol__size(sym); 403aca7a94dSNamhyung Kim 404aca7a94dSNamhyung Kim browser->entries = RB_ROOT; 405aca7a94dSNamhyung Kim 406aca7a94dSNamhyung Kim pthread_mutex_lock(¬es->lock); 407aca7a94dSNamhyung Kim 408aca7a94dSNamhyung Kim list_for_each_entry(pos, ¬es->src->source, node) { 409887c0066SArnaldo Carvalho de Melo struct browser_disasm_line *bpos = disasm_line__browser(pos); 410e64aa75bSNamhyung Kim const char *path = NULL; 411c7e7b610SNamhyung Kim double max_percent = 0.0; 412c7e7b610SNamhyung Kim int i; 413e64aa75bSNamhyung Kim 414e64aa75bSNamhyung Kim if (pos->offset == -1) { 415e64aa75bSNamhyung Kim RB_CLEAR_NODE(&bpos->rb_node); 416e64aa75bSNamhyung Kim continue; 417e64aa75bSNamhyung Kim } 418e64aa75bSNamhyung Kim 419e64aa75bSNamhyung Kim next = disasm__get_next_ip_line(¬es->src->source, pos); 420c7e7b610SNamhyung Kim 421c7e7b610SNamhyung Kim for (i = 0; i < browser->nr_events; i++) { 4220c4a5bceSMartin Liška u64 nr_samples; 4230c4a5bceSMartin Liška 4240c4a5bceSMartin Liška bpos->samples[i].percent = disasm__calc_percent(notes, 425c7e7b610SNamhyung Kim evsel->idx + i, 426c7e7b610SNamhyung Kim pos->offset, 427c7e7b610SNamhyung Kim next ? next->offset : len, 4280c4a5bceSMartin Liška &path, &nr_samples); 4290c4a5bceSMartin Liška bpos->samples[i].nr = nr_samples; 430e64aa75bSNamhyung Kim 4310c4a5bceSMartin Liška if (max_percent < bpos->samples[i].percent) 4320c4a5bceSMartin Liška max_percent = bpos->samples[i].percent; 433c7e7b610SNamhyung Kim } 434c7e7b610SNamhyung Kim 43530e863bbSAndi Kleen if (max_percent < 0.01 && pos->ipc == 0) { 436887c0066SArnaldo Carvalho de Melo RB_CLEAR_NODE(&bpos->rb_node); 437aca7a94dSNamhyung Kim continue; 438aca7a94dSNamhyung Kim } 439c7e7b610SNamhyung Kim disasm_rb_tree__insert(&browser->entries, bpos, 440c7e7b610SNamhyung Kim browser->nr_events); 441aca7a94dSNamhyung Kim } 442aca7a94dSNamhyung Kim pthread_mutex_unlock(¬es->lock); 443aca7a94dSNamhyung Kim 444aca7a94dSNamhyung Kim browser->curr_hot = rb_last(&browser->entries); 445aca7a94dSNamhyung Kim } 446aca7a94dSNamhyung Kim 447aca7a94dSNamhyung Kim static bool annotate_browser__toggle_source(struct annotate_browser *browser) 448aca7a94dSNamhyung Kim { 44929ed6e76SArnaldo Carvalho de Melo struct disasm_line *dl; 450887c0066SArnaldo Carvalho de Melo struct browser_disasm_line *bdl; 451aca7a94dSNamhyung Kim off_t offset = browser->b.index - browser->b.top_idx; 452aca7a94dSNamhyung Kim 453aca7a94dSNamhyung Kim browser->b.seek(&browser->b, offset, SEEK_CUR); 45429ed6e76SArnaldo Carvalho de Melo dl = list_entry(browser->b.top, struct disasm_line, node); 455887c0066SArnaldo Carvalho de Melo bdl = disasm_line__browser(dl); 456aca7a94dSNamhyung Kim 457e9823b21SArnaldo Carvalho de Melo if (annotate_browser__opts.hide_src_code) { 458887c0066SArnaldo Carvalho de Melo if (bdl->idx_asm < offset) 459887c0066SArnaldo Carvalho de Melo offset = bdl->idx; 460aca7a94dSNamhyung Kim 461aca7a94dSNamhyung Kim browser->b.nr_entries = browser->nr_entries; 462e9823b21SArnaldo Carvalho de Melo annotate_browser__opts.hide_src_code = false; 463aca7a94dSNamhyung Kim browser->b.seek(&browser->b, -offset, SEEK_CUR); 464887c0066SArnaldo Carvalho de Melo browser->b.top_idx = bdl->idx - offset; 465887c0066SArnaldo Carvalho de Melo browser->b.index = bdl->idx; 466aca7a94dSNamhyung Kim } else { 467887c0066SArnaldo Carvalho de Melo if (bdl->idx_asm < 0) { 468aca7a94dSNamhyung Kim ui_helpline__puts("Only available for assembly lines."); 469aca7a94dSNamhyung Kim browser->b.seek(&browser->b, -offset, SEEK_CUR); 470aca7a94dSNamhyung Kim return false; 471aca7a94dSNamhyung Kim } 472aca7a94dSNamhyung Kim 473887c0066SArnaldo Carvalho de Melo if (bdl->idx_asm < offset) 474887c0066SArnaldo Carvalho de Melo offset = bdl->idx_asm; 475aca7a94dSNamhyung Kim 476aca7a94dSNamhyung Kim browser->b.nr_entries = browser->nr_asm_entries; 477e9823b21SArnaldo Carvalho de Melo annotate_browser__opts.hide_src_code = true; 478aca7a94dSNamhyung Kim browser->b.seek(&browser->b, -offset, SEEK_CUR); 479887c0066SArnaldo Carvalho de Melo browser->b.top_idx = bdl->idx_asm - offset; 480887c0066SArnaldo Carvalho de Melo browser->b.index = bdl->idx_asm; 481aca7a94dSNamhyung Kim } 482aca7a94dSNamhyung Kim 483aca7a94dSNamhyung Kim return true; 484aca7a94dSNamhyung Kim } 485aca7a94dSNamhyung Kim 486e9823b21SArnaldo Carvalho de Melo static void annotate_browser__init_asm_mode(struct annotate_browser *browser) 487e9823b21SArnaldo Carvalho de Melo { 488e9823b21SArnaldo Carvalho de Melo ui_browser__reset_index(&browser->b); 489e9823b21SArnaldo Carvalho de Melo browser->b.nr_entries = browser->nr_asm_entries; 490e9823b21SArnaldo Carvalho de Melo } 491e9823b21SArnaldo Carvalho de Melo 49234f77abcSAdrian Hunter #define SYM_TITLE_MAX_SIZE (PATH_MAX + 64) 49334f77abcSAdrian Hunter 49434f77abcSAdrian Hunter static int sym_title(struct symbol *sym, struct map *map, char *title, 49534f77abcSAdrian Hunter size_t sz) 49634f77abcSAdrian Hunter { 49734f77abcSAdrian Hunter return snprintf(title, sz, "%s %s", sym->name, map->dso->long_name); 49834f77abcSAdrian Hunter } 49934f77abcSAdrian Hunter 500db8fd07aSNamhyung Kim static bool annotate_browser__callq(struct annotate_browser *browser, 501db8fd07aSNamhyung Kim struct perf_evsel *evsel, 5029783adf7SNamhyung Kim struct hist_browser_timer *hbt) 503aca7a94dSNamhyung Kim { 504aca7a94dSNamhyung Kim struct map_symbol *ms = browser->b.priv; 505657bcaf5SArnaldo Carvalho de Melo struct disasm_line *dl = browser->selection; 506aca7a94dSNamhyung Kim struct annotation *notes; 5071179e11bSAdrian Hunter struct addr_map_symbol target = { 5081179e11bSAdrian Hunter .map = ms->map, 5091d5077bdSAdrian Hunter .addr = map__objdump_2mem(ms->map, dl->ops.target.addr), 5101179e11bSAdrian Hunter }; 51134f77abcSAdrian Hunter char title[SYM_TITLE_MAX_SIZE]; 512aca7a94dSNamhyung Kim 51375b49202SArnaldo Carvalho de Melo if (!ins__is_call(&dl->ins)) 514aca7a94dSNamhyung Kim return false; 515aca7a94dSNamhyung Kim 516be39db9fSArnaldo Carvalho de Melo if (map_groups__find_ams(&target) || 5171d5077bdSAdrian Hunter map__rip_2objdump(target.map, target.map->map_ip(target.map, 5181d5077bdSAdrian Hunter target.addr)) != 5191d5077bdSAdrian Hunter dl->ops.target.addr) { 520aca7a94dSNamhyung Kim ui_helpline__puts("The called function was not found."); 521aca7a94dSNamhyung Kim return true; 522aca7a94dSNamhyung Kim } 523aca7a94dSNamhyung Kim 5241179e11bSAdrian Hunter notes = symbol__annotation(target.sym); 525aca7a94dSNamhyung Kim pthread_mutex_lock(¬es->lock); 526aca7a94dSNamhyung Kim 5271179e11bSAdrian Hunter if (notes->src == NULL && symbol__alloc_hist(target.sym) < 0) { 528aca7a94dSNamhyung Kim pthread_mutex_unlock(¬es->lock); 529aca7a94dSNamhyung Kim ui__warning("Not enough memory for annotating '%s' symbol!\n", 5301179e11bSAdrian Hunter target.sym->name); 531aca7a94dSNamhyung Kim return true; 532aca7a94dSNamhyung Kim } 533aca7a94dSNamhyung Kim 534aca7a94dSNamhyung Kim pthread_mutex_unlock(¬es->lock); 5351179e11bSAdrian Hunter symbol__tui_annotate(target.sym, target.map, evsel, hbt); 5361179e11bSAdrian Hunter sym_title(ms->sym, ms->map, title, sizeof(title)); 53734f77abcSAdrian Hunter ui_browser__show_title(&browser->b, title); 538aca7a94dSNamhyung Kim return true; 539aca7a94dSNamhyung Kim } 540aca7a94dSNamhyung Kim 54129ed6e76SArnaldo Carvalho de Melo static 54229ed6e76SArnaldo Carvalho de Melo struct disasm_line *annotate_browser__find_offset(struct annotate_browser *browser, 543aca7a94dSNamhyung Kim s64 offset, s64 *idx) 544aca7a94dSNamhyung Kim { 545aca7a94dSNamhyung Kim struct map_symbol *ms = browser->b.priv; 546aca7a94dSNamhyung Kim struct symbol *sym = ms->sym; 547aca7a94dSNamhyung Kim struct annotation *notes = symbol__annotation(sym); 54829ed6e76SArnaldo Carvalho de Melo struct disasm_line *pos; 549aca7a94dSNamhyung Kim 550aca7a94dSNamhyung Kim *idx = 0; 551aca7a94dSNamhyung Kim list_for_each_entry(pos, ¬es->src->source, node) { 552aca7a94dSNamhyung Kim if (pos->offset == offset) 553aca7a94dSNamhyung Kim return pos; 55429ed6e76SArnaldo Carvalho de Melo if (!disasm_line__filter(&browser->b, &pos->node)) 555aca7a94dSNamhyung Kim ++*idx; 556aca7a94dSNamhyung Kim } 557aca7a94dSNamhyung Kim 558aca7a94dSNamhyung Kim return NULL; 559aca7a94dSNamhyung Kim } 560aca7a94dSNamhyung Kim 561aca7a94dSNamhyung Kim static bool annotate_browser__jump(struct annotate_browser *browser) 562aca7a94dSNamhyung Kim { 563657bcaf5SArnaldo Carvalho de Melo struct disasm_line *dl = browser->selection; 5645252b1aeSArnaldo Carvalho de Melo u64 offset; 5654f9d0325SArnaldo Carvalho de Melo s64 idx; 566aca7a94dSNamhyung Kim 56775b49202SArnaldo Carvalho de Melo if (!ins__is_jump(&dl->ins)) 568aca7a94dSNamhyung Kim return false; 569aca7a94dSNamhyung Kim 5705252b1aeSArnaldo Carvalho de Melo offset = dl->ops.target.offset; 5715252b1aeSArnaldo Carvalho de Melo dl = annotate_browser__find_offset(browser, offset, &idx); 57229ed6e76SArnaldo Carvalho de Melo if (dl == NULL) { 5735252b1aeSArnaldo Carvalho de Melo ui_helpline__printf("Invalid jump offset: %" PRIx64, offset); 574aca7a94dSNamhyung Kim return true; 575aca7a94dSNamhyung Kim } 576aca7a94dSNamhyung Kim 57729ed6e76SArnaldo Carvalho de Melo annotate_browser__set_top(browser, dl, idx); 578aca7a94dSNamhyung Kim 579aca7a94dSNamhyung Kim return true; 580aca7a94dSNamhyung Kim } 581aca7a94dSNamhyung Kim 58229ed6e76SArnaldo Carvalho de Melo static 58329ed6e76SArnaldo Carvalho de Melo struct disasm_line *annotate_browser__find_string(struct annotate_browser *browser, 584aca7a94dSNamhyung Kim char *s, s64 *idx) 585aca7a94dSNamhyung Kim { 586aca7a94dSNamhyung Kim struct map_symbol *ms = browser->b.priv; 587aca7a94dSNamhyung Kim struct symbol *sym = ms->sym; 588aca7a94dSNamhyung Kim struct annotation *notes = symbol__annotation(sym); 58929ed6e76SArnaldo Carvalho de Melo struct disasm_line *pos = browser->selection; 590aca7a94dSNamhyung Kim 591aca7a94dSNamhyung Kim *idx = browser->b.index; 592aca7a94dSNamhyung Kim list_for_each_entry_continue(pos, ¬es->src->source, node) { 59329ed6e76SArnaldo Carvalho de Melo if (disasm_line__filter(&browser->b, &pos->node)) 594aca7a94dSNamhyung Kim continue; 595aca7a94dSNamhyung Kim 596aca7a94dSNamhyung Kim ++*idx; 597aca7a94dSNamhyung Kim 598aca7a94dSNamhyung Kim if (pos->line && strstr(pos->line, s) != NULL) 599aca7a94dSNamhyung Kim return pos; 600aca7a94dSNamhyung Kim } 601aca7a94dSNamhyung Kim 602aca7a94dSNamhyung Kim return NULL; 603aca7a94dSNamhyung Kim } 604aca7a94dSNamhyung Kim 605aca7a94dSNamhyung Kim static bool __annotate_browser__search(struct annotate_browser *browser) 606aca7a94dSNamhyung Kim { 60729ed6e76SArnaldo Carvalho de Melo struct disasm_line *dl; 608aca7a94dSNamhyung Kim s64 idx; 609aca7a94dSNamhyung Kim 61029ed6e76SArnaldo Carvalho de Melo dl = annotate_browser__find_string(browser, browser->search_bf, &idx); 61129ed6e76SArnaldo Carvalho de Melo if (dl == NULL) { 612aca7a94dSNamhyung Kim ui_helpline__puts("String not found!"); 613aca7a94dSNamhyung Kim return false; 614aca7a94dSNamhyung Kim } 615aca7a94dSNamhyung Kim 61629ed6e76SArnaldo Carvalho de Melo annotate_browser__set_top(browser, dl, idx); 617aca7a94dSNamhyung Kim browser->searching_backwards = false; 618aca7a94dSNamhyung Kim return true; 619aca7a94dSNamhyung Kim } 620aca7a94dSNamhyung Kim 62129ed6e76SArnaldo Carvalho de Melo static 62229ed6e76SArnaldo Carvalho de Melo struct disasm_line *annotate_browser__find_string_reverse(struct annotate_browser *browser, 623aca7a94dSNamhyung Kim char *s, s64 *idx) 624aca7a94dSNamhyung Kim { 625aca7a94dSNamhyung Kim struct map_symbol *ms = browser->b.priv; 626aca7a94dSNamhyung Kim struct symbol *sym = ms->sym; 627aca7a94dSNamhyung Kim struct annotation *notes = symbol__annotation(sym); 62829ed6e76SArnaldo Carvalho de Melo struct disasm_line *pos = browser->selection; 629aca7a94dSNamhyung Kim 630aca7a94dSNamhyung Kim *idx = browser->b.index; 631aca7a94dSNamhyung Kim list_for_each_entry_continue_reverse(pos, ¬es->src->source, node) { 63229ed6e76SArnaldo Carvalho de Melo if (disasm_line__filter(&browser->b, &pos->node)) 633aca7a94dSNamhyung Kim continue; 634aca7a94dSNamhyung Kim 635aca7a94dSNamhyung Kim --*idx; 636aca7a94dSNamhyung Kim 637aca7a94dSNamhyung Kim if (pos->line && strstr(pos->line, s) != NULL) 638aca7a94dSNamhyung Kim return pos; 639aca7a94dSNamhyung Kim } 640aca7a94dSNamhyung Kim 641aca7a94dSNamhyung Kim return NULL; 642aca7a94dSNamhyung Kim } 643aca7a94dSNamhyung Kim 644aca7a94dSNamhyung Kim static bool __annotate_browser__search_reverse(struct annotate_browser *browser) 645aca7a94dSNamhyung Kim { 64629ed6e76SArnaldo Carvalho de Melo struct disasm_line *dl; 647aca7a94dSNamhyung Kim s64 idx; 648aca7a94dSNamhyung Kim 64929ed6e76SArnaldo Carvalho de Melo dl = annotate_browser__find_string_reverse(browser, browser->search_bf, &idx); 65029ed6e76SArnaldo Carvalho de Melo if (dl == NULL) { 651aca7a94dSNamhyung Kim ui_helpline__puts("String not found!"); 652aca7a94dSNamhyung Kim return false; 653aca7a94dSNamhyung Kim } 654aca7a94dSNamhyung Kim 65529ed6e76SArnaldo Carvalho de Melo annotate_browser__set_top(browser, dl, idx); 656aca7a94dSNamhyung Kim browser->searching_backwards = true; 657aca7a94dSNamhyung Kim return true; 658aca7a94dSNamhyung Kim } 659aca7a94dSNamhyung Kim 660aca7a94dSNamhyung Kim static bool annotate_browser__search_window(struct annotate_browser *browser, 661aca7a94dSNamhyung Kim int delay_secs) 662aca7a94dSNamhyung Kim { 663aca7a94dSNamhyung Kim if (ui_browser__input_window("Search", "String: ", browser->search_bf, 664aca7a94dSNamhyung Kim "ENTER: OK, ESC: Cancel", 665aca7a94dSNamhyung Kim delay_secs * 2) != K_ENTER || 666aca7a94dSNamhyung Kim !*browser->search_bf) 667aca7a94dSNamhyung Kim return false; 668aca7a94dSNamhyung Kim 669aca7a94dSNamhyung Kim return true; 670aca7a94dSNamhyung Kim } 671aca7a94dSNamhyung Kim 672aca7a94dSNamhyung Kim static bool annotate_browser__search(struct annotate_browser *browser, int delay_secs) 673aca7a94dSNamhyung Kim { 674aca7a94dSNamhyung Kim if (annotate_browser__search_window(browser, delay_secs)) 675aca7a94dSNamhyung Kim return __annotate_browser__search(browser); 676aca7a94dSNamhyung Kim 677aca7a94dSNamhyung Kim return false; 678aca7a94dSNamhyung Kim } 679aca7a94dSNamhyung Kim 680aca7a94dSNamhyung Kim static bool annotate_browser__continue_search(struct annotate_browser *browser, 681aca7a94dSNamhyung Kim int delay_secs) 682aca7a94dSNamhyung Kim { 683aca7a94dSNamhyung Kim if (!*browser->search_bf) 684aca7a94dSNamhyung Kim return annotate_browser__search(browser, delay_secs); 685aca7a94dSNamhyung Kim 686aca7a94dSNamhyung Kim return __annotate_browser__search(browser); 687aca7a94dSNamhyung Kim } 688aca7a94dSNamhyung Kim 689aca7a94dSNamhyung Kim static bool annotate_browser__search_reverse(struct annotate_browser *browser, 690aca7a94dSNamhyung Kim int delay_secs) 691aca7a94dSNamhyung Kim { 692aca7a94dSNamhyung Kim if (annotate_browser__search_window(browser, delay_secs)) 693aca7a94dSNamhyung Kim return __annotate_browser__search_reverse(browser); 694aca7a94dSNamhyung Kim 695aca7a94dSNamhyung Kim return false; 696aca7a94dSNamhyung Kim } 697aca7a94dSNamhyung Kim 698aca7a94dSNamhyung Kim static 699aca7a94dSNamhyung Kim bool annotate_browser__continue_search_reverse(struct annotate_browser *browser, 700aca7a94dSNamhyung Kim int delay_secs) 701aca7a94dSNamhyung Kim { 702aca7a94dSNamhyung Kim if (!*browser->search_bf) 703aca7a94dSNamhyung Kim return annotate_browser__search_reverse(browser, delay_secs); 704aca7a94dSNamhyung Kim 705aca7a94dSNamhyung Kim return __annotate_browser__search_reverse(browser); 706aca7a94dSNamhyung Kim } 707aca7a94dSNamhyung Kim 708e9823b21SArnaldo Carvalho de Melo static void annotate_browser__update_addr_width(struct annotate_browser *browser) 709e9823b21SArnaldo Carvalho de Melo { 710e9823b21SArnaldo Carvalho de Melo if (annotate_browser__opts.use_offset) 711e9823b21SArnaldo Carvalho de Melo browser->target_width = browser->min_addr_width; 712e9823b21SArnaldo Carvalho de Melo else 713e9823b21SArnaldo Carvalho de Melo browser->target_width = browser->max_addr_width; 714e9823b21SArnaldo Carvalho de Melo 715e9823b21SArnaldo Carvalho de Melo browser->addr_width = browser->target_width; 716e9823b21SArnaldo Carvalho de Melo 717e9823b21SArnaldo Carvalho de Melo if (annotate_browser__opts.show_nr_jumps) 718e9823b21SArnaldo Carvalho de Melo browser->addr_width += browser->jumps_width + 1; 719e9823b21SArnaldo Carvalho de Melo } 720e9823b21SArnaldo Carvalho de Melo 721db8fd07aSNamhyung Kim static int annotate_browser__run(struct annotate_browser *browser, 722db8fd07aSNamhyung Kim struct perf_evsel *evsel, 7239783adf7SNamhyung Kim struct hist_browser_timer *hbt) 724aca7a94dSNamhyung Kim { 725aca7a94dSNamhyung Kim struct rb_node *nd = NULL; 72605e8b080SArnaldo Carvalho de Melo struct map_symbol *ms = browser->b.priv; 727aca7a94dSNamhyung Kim struct symbol *sym = ms->sym; 72854e7a4e8SArnaldo Carvalho de Melo const char *help = "Press 'h' for help on key bindings"; 7299783adf7SNamhyung Kim int delay_secs = hbt ? hbt->refresh : 0; 730aca7a94dSNamhyung Kim int key; 73134f77abcSAdrian Hunter char title[SYM_TITLE_MAX_SIZE]; 732aca7a94dSNamhyung Kim 73334f77abcSAdrian Hunter sym_title(sym, ms->map, title, sizeof(title)); 73434f77abcSAdrian Hunter if (ui_browser__show(&browser->b, title, help) < 0) 735aca7a94dSNamhyung Kim return -1; 736aca7a94dSNamhyung Kim 737db8fd07aSNamhyung Kim annotate_browser__calc_percent(browser, evsel); 738aca7a94dSNamhyung Kim 73905e8b080SArnaldo Carvalho de Melo if (browser->curr_hot) { 74005e8b080SArnaldo Carvalho de Melo annotate_browser__set_rb_top(browser, browser->curr_hot); 74105e8b080SArnaldo Carvalho de Melo browser->b.navkeypressed = false; 742aca7a94dSNamhyung Kim } 743aca7a94dSNamhyung Kim 74405e8b080SArnaldo Carvalho de Melo nd = browser->curr_hot; 745aca7a94dSNamhyung Kim 746aca7a94dSNamhyung Kim while (1) { 74705e8b080SArnaldo Carvalho de Melo key = ui_browser__run(&browser->b, delay_secs); 748aca7a94dSNamhyung Kim 749aca7a94dSNamhyung Kim if (delay_secs != 0) { 750db8fd07aSNamhyung Kim annotate_browser__calc_percent(browser, evsel); 751aca7a94dSNamhyung Kim /* 752aca7a94dSNamhyung Kim * Current line focus got out of the list of most active 753aca7a94dSNamhyung Kim * lines, NULL it so that if TAB|UNTAB is pressed, we 754aca7a94dSNamhyung Kim * move to curr_hot (current hottest line). 755aca7a94dSNamhyung Kim */ 756aca7a94dSNamhyung Kim if (nd != NULL && RB_EMPTY_NODE(nd)) 757aca7a94dSNamhyung Kim nd = NULL; 758aca7a94dSNamhyung Kim } 759aca7a94dSNamhyung Kim 760aca7a94dSNamhyung Kim switch (key) { 761aca7a94dSNamhyung Kim case K_TIMER: 7629783adf7SNamhyung Kim if (hbt) 7639783adf7SNamhyung Kim hbt->timer(hbt->arg); 764aca7a94dSNamhyung Kim 765aca7a94dSNamhyung Kim if (delay_secs != 0) 766db8fd07aSNamhyung Kim symbol__annotate_decay_histogram(sym, evsel->idx); 767aca7a94dSNamhyung Kim continue; 768aca7a94dSNamhyung Kim case K_TAB: 769aca7a94dSNamhyung Kim if (nd != NULL) { 770aca7a94dSNamhyung Kim nd = rb_prev(nd); 771aca7a94dSNamhyung Kim if (nd == NULL) 77205e8b080SArnaldo Carvalho de Melo nd = rb_last(&browser->entries); 773aca7a94dSNamhyung Kim } else 77405e8b080SArnaldo Carvalho de Melo nd = browser->curr_hot; 775aca7a94dSNamhyung Kim break; 776aca7a94dSNamhyung Kim case K_UNTAB: 777d4913cbdSMarkus Trippelsdorf if (nd != NULL) { 778aca7a94dSNamhyung Kim nd = rb_next(nd); 779aca7a94dSNamhyung Kim if (nd == NULL) 78005e8b080SArnaldo Carvalho de Melo nd = rb_first(&browser->entries); 781d4913cbdSMarkus Trippelsdorf } else 78205e8b080SArnaldo Carvalho de Melo nd = browser->curr_hot; 783aca7a94dSNamhyung Kim break; 78454e7a4e8SArnaldo Carvalho de Melo case K_F1: 785aca7a94dSNamhyung Kim case 'h': 78605e8b080SArnaldo Carvalho de Melo ui_browser__help_window(&browser->b, 78754e7a4e8SArnaldo Carvalho de Melo "UP/DOWN/PGUP\n" 78854e7a4e8SArnaldo Carvalho de Melo "PGDN/SPACE Navigate\n" 78954e7a4e8SArnaldo Carvalho de Melo "q/ESC/CTRL+C Exit\n\n" 7907727a925SArnaldo Carvalho de Melo "ENTER Go to target\n" 7917727a925SArnaldo Carvalho de Melo "ESC Exit\n" 792107baecaSArnaldo Carvalho de Melo "H Cycle thru hottest instructions\n" 79354e7a4e8SArnaldo Carvalho de Melo "j Toggle showing jump to target arrows\n" 79454e7a4e8SArnaldo Carvalho de Melo "J Toggle showing number of jump sources on targets\n" 79554e7a4e8SArnaldo Carvalho de Melo "n Search next string\n" 79654e7a4e8SArnaldo Carvalho de Melo "o Toggle disassembler output/simplified view\n" 79754e7a4e8SArnaldo Carvalho de Melo "s Toggle source code view\n" 7980c4a5bceSMartin Liška "t Toggle total period view\n" 79954e7a4e8SArnaldo Carvalho de Melo "/ Search string\n" 800e592488cSAndi Kleen "k Toggle line numbers\n" 80179ee47faSFeng Tang "r Run available scripts\n" 802fcd9fef9SArnaldo Carvalho de Melo "? Search string backwards\n"); 80354e7a4e8SArnaldo Carvalho de Melo continue; 80479ee47faSFeng Tang case 'r': 80579ee47faSFeng Tang { 80679ee47faSFeng Tang script_browse(NULL); 80779ee47faSFeng Tang continue; 80879ee47faSFeng Tang } 809e592488cSAndi Kleen case 'k': 810e592488cSAndi Kleen annotate_browser__opts.show_linenr = 811e592488cSAndi Kleen !annotate_browser__opts.show_linenr; 812e592488cSAndi Kleen break; 81354e7a4e8SArnaldo Carvalho de Melo case 'H': 81405e8b080SArnaldo Carvalho de Melo nd = browser->curr_hot; 815aca7a94dSNamhyung Kim break; 816aca7a94dSNamhyung Kim case 's': 81705e8b080SArnaldo Carvalho de Melo if (annotate_browser__toggle_source(browser)) 818aca7a94dSNamhyung Kim ui_helpline__puts(help); 819aca7a94dSNamhyung Kim continue; 820aca7a94dSNamhyung Kim case 'o': 821e9823b21SArnaldo Carvalho de Melo annotate_browser__opts.use_offset = !annotate_browser__opts.use_offset; 82205e8b080SArnaldo Carvalho de Melo annotate_browser__update_addr_width(browser); 823aca7a94dSNamhyung Kim continue; 8249d1ef56dSArnaldo Carvalho de Melo case 'j': 825e9823b21SArnaldo Carvalho de Melo annotate_browser__opts.jump_arrows = !annotate_browser__opts.jump_arrows; 8269d1ef56dSArnaldo Carvalho de Melo continue; 8272402e4a9SArnaldo Carvalho de Melo case 'J': 828e9823b21SArnaldo Carvalho de Melo annotate_browser__opts.show_nr_jumps = !annotate_browser__opts.show_nr_jumps; 82905e8b080SArnaldo Carvalho de Melo annotate_browser__update_addr_width(browser); 830e9823b21SArnaldo Carvalho de Melo continue; 831aca7a94dSNamhyung Kim case '/': 83205e8b080SArnaldo Carvalho de Melo if (annotate_browser__search(browser, delay_secs)) { 833aca7a94dSNamhyung Kim show_help: 834aca7a94dSNamhyung Kim ui_helpline__puts(help); 835aca7a94dSNamhyung Kim } 836aca7a94dSNamhyung Kim continue; 837aca7a94dSNamhyung Kim case 'n': 83805e8b080SArnaldo Carvalho de Melo if (browser->searching_backwards ? 83905e8b080SArnaldo Carvalho de Melo annotate_browser__continue_search_reverse(browser, delay_secs) : 84005e8b080SArnaldo Carvalho de Melo annotate_browser__continue_search(browser, delay_secs)) 841aca7a94dSNamhyung Kim goto show_help; 842aca7a94dSNamhyung Kim continue; 843aca7a94dSNamhyung Kim case '?': 84405e8b080SArnaldo Carvalho de Melo if (annotate_browser__search_reverse(browser, delay_secs)) 845aca7a94dSNamhyung Kim goto show_help; 846aca7a94dSNamhyung Kim continue; 847e9823b21SArnaldo Carvalho de Melo case 'D': { 848e9823b21SArnaldo Carvalho de Melo static int seq; 849e9823b21SArnaldo Carvalho de Melo ui_helpline__pop(); 850e9823b21SArnaldo Carvalho de Melo ui_helpline__fpush("%d: nr_ent=%d, height=%d, idx=%d, top_idx=%d, nr_asm_entries=%d", 85105e8b080SArnaldo Carvalho de Melo seq++, browser->b.nr_entries, 85205e8b080SArnaldo Carvalho de Melo browser->b.height, 85305e8b080SArnaldo Carvalho de Melo browser->b.index, 85405e8b080SArnaldo Carvalho de Melo browser->b.top_idx, 85505e8b080SArnaldo Carvalho de Melo browser->nr_asm_entries); 856e9823b21SArnaldo Carvalho de Melo } 857e9823b21SArnaldo Carvalho de Melo continue; 858aca7a94dSNamhyung Kim case K_ENTER: 859aca7a94dSNamhyung Kim case K_RIGHT: 86005e8b080SArnaldo Carvalho de Melo if (browser->selection == NULL) 861aca7a94dSNamhyung Kim ui_helpline__puts("Huh? No selection. Report to linux-kernel@vger.kernel.org"); 86205e8b080SArnaldo Carvalho de Melo else if (browser->selection->offset == -1) 863aca7a94dSNamhyung Kim ui_helpline__puts("Actions are only available for assembly lines."); 86475b49202SArnaldo Carvalho de Melo else if (!browser->selection->ins.ops) 865c4cceae3SArnaldo Carvalho de Melo goto show_sup_ins; 86675b49202SArnaldo Carvalho de Melo else if (ins__is_ret(&browser->selection->ins)) 867c4cceae3SArnaldo Carvalho de Melo goto out; 8686ef94929SNaveen N. Rao else if (!(annotate_browser__jump(browser) || 869db8fd07aSNamhyung Kim annotate_browser__callq(browser, evsel, hbt))) { 870c4cceae3SArnaldo Carvalho de Melo show_sup_ins: 8716ef94929SNaveen N. Rao ui_helpline__puts("Actions are only available for function call/return & jump/branch instructions."); 872c4cceae3SArnaldo Carvalho de Melo } 873aca7a94dSNamhyung Kim continue; 8740c4a5bceSMartin Liška case 't': 8750c4a5bceSMartin Liška annotate_browser__opts.show_total_period = 8760c4a5bceSMartin Liška !annotate_browser__opts.show_total_period; 8770c4a5bceSMartin Liška annotate_browser__update_addr_width(browser); 8780c4a5bceSMartin Liška continue; 879aca7a94dSNamhyung Kim case K_LEFT: 880aca7a94dSNamhyung Kim case K_ESC: 881aca7a94dSNamhyung Kim case 'q': 882aca7a94dSNamhyung Kim case CTRL('c'): 883aca7a94dSNamhyung Kim goto out; 884aca7a94dSNamhyung Kim default: 885aca7a94dSNamhyung Kim continue; 886aca7a94dSNamhyung Kim } 887aca7a94dSNamhyung Kim 888aca7a94dSNamhyung Kim if (nd != NULL) 88905e8b080SArnaldo Carvalho de Melo annotate_browser__set_rb_top(browser, nd); 890aca7a94dSNamhyung Kim } 891aca7a94dSNamhyung Kim out: 89205e8b080SArnaldo Carvalho de Melo ui_browser__hide(&browser->b); 893aca7a94dSNamhyung Kim return key; 894aca7a94dSNamhyung Kim } 895aca7a94dSNamhyung Kim 896d5dbc518SArnaldo Carvalho de Melo int map_symbol__tui_annotate(struct map_symbol *ms, struct perf_evsel *evsel, 897d5dbc518SArnaldo Carvalho de Melo struct hist_browser_timer *hbt) 898d5dbc518SArnaldo Carvalho de Melo { 8990c4a5bceSMartin Liška /* Set default value for show_total_period. */ 9000c4a5bceSMartin Liška annotate_browser__opts.show_total_period = 9010c4a5bceSMartin Liška symbol_conf.show_total_period; 9020c4a5bceSMartin Liška 903d5dbc518SArnaldo Carvalho de Melo return symbol__tui_annotate(ms->sym, ms->map, evsel, hbt); 904d5dbc518SArnaldo Carvalho de Melo } 905d5dbc518SArnaldo Carvalho de Melo 906db8fd07aSNamhyung Kim int hist_entry__tui_annotate(struct hist_entry *he, struct perf_evsel *evsel, 9079783adf7SNamhyung Kim struct hist_browser_timer *hbt) 908aca7a94dSNamhyung Kim { 909ed426915SNamhyung Kim /* reset abort key so that it can get Ctrl-C as a key */ 910ed426915SNamhyung Kim SLang_reset_tty(); 911ed426915SNamhyung Kim SLang_init_tty(0, 0, 0); 912ed426915SNamhyung Kim 913d5dbc518SArnaldo Carvalho de Melo return map_symbol__tui_annotate(&he->ms, evsel, hbt); 914aca7a94dSNamhyung Kim } 915aca7a94dSNamhyung Kim 91630e863bbSAndi Kleen 91730e863bbSAndi Kleen static unsigned count_insn(struct annotate_browser *browser, u64 start, u64 end) 91830e863bbSAndi Kleen { 91930e863bbSAndi Kleen unsigned n_insn = 0; 92030e863bbSAndi Kleen u64 offset; 92130e863bbSAndi Kleen 92230e863bbSAndi Kleen for (offset = start; offset <= end; offset++) { 92330e863bbSAndi Kleen if (browser->offsets[offset]) 92430e863bbSAndi Kleen n_insn++; 92530e863bbSAndi Kleen } 92630e863bbSAndi Kleen return n_insn; 92730e863bbSAndi Kleen } 92830e863bbSAndi Kleen 92930e863bbSAndi Kleen static void count_and_fill(struct annotate_browser *browser, u64 start, u64 end, 93030e863bbSAndi Kleen struct cyc_hist *ch) 93130e863bbSAndi Kleen { 93230e863bbSAndi Kleen unsigned n_insn; 93330e863bbSAndi Kleen u64 offset; 93430e863bbSAndi Kleen 93530e863bbSAndi Kleen n_insn = count_insn(browser, start, end); 93630e863bbSAndi Kleen if (n_insn && ch->num && ch->cycles) { 93730e863bbSAndi Kleen float ipc = n_insn / ((double)ch->cycles / (double)ch->num); 93830e863bbSAndi Kleen 93930e863bbSAndi Kleen /* Hide data when there are too many overlaps. */ 94030e863bbSAndi Kleen if (ch->reset >= 0x7fff || ch->reset >= ch->num / 2) 94130e863bbSAndi Kleen return; 94230e863bbSAndi Kleen 94330e863bbSAndi Kleen for (offset = start; offset <= end; offset++) { 94430e863bbSAndi Kleen struct disasm_line *dl = browser->offsets[offset]; 94530e863bbSAndi Kleen 94630e863bbSAndi Kleen if (dl) 94730e863bbSAndi Kleen dl->ipc = ipc; 94830e863bbSAndi Kleen } 94930e863bbSAndi Kleen } 95030e863bbSAndi Kleen } 95130e863bbSAndi Kleen 95230e863bbSAndi Kleen /* 95330e863bbSAndi Kleen * This should probably be in util/annotate.c to share with the tty 95430e863bbSAndi Kleen * annotate, but right now we need the per byte offsets arrays, 95530e863bbSAndi Kleen * which are only here. 95630e863bbSAndi Kleen */ 95730e863bbSAndi Kleen static void annotate__compute_ipc(struct annotate_browser *browser, size_t size, 95830e863bbSAndi Kleen struct symbol *sym) 95930e863bbSAndi Kleen { 96030e863bbSAndi Kleen u64 offset; 96130e863bbSAndi Kleen struct annotation *notes = symbol__annotation(sym); 96230e863bbSAndi Kleen 96330e863bbSAndi Kleen if (!notes->src || !notes->src->cycles_hist) 96430e863bbSAndi Kleen return; 96530e863bbSAndi Kleen 96630e863bbSAndi Kleen pthread_mutex_lock(¬es->lock); 96730e863bbSAndi Kleen for (offset = 0; offset < size; ++offset) { 96830e863bbSAndi Kleen struct cyc_hist *ch; 96930e863bbSAndi Kleen 97030e863bbSAndi Kleen ch = ¬es->src->cycles_hist[offset]; 97130e863bbSAndi Kleen if (ch && ch->cycles) { 97230e863bbSAndi Kleen struct disasm_line *dl; 97330e863bbSAndi Kleen 97430e863bbSAndi Kleen if (ch->have_start) 97530e863bbSAndi Kleen count_and_fill(browser, ch->start, offset, ch); 97630e863bbSAndi Kleen dl = browser->offsets[offset]; 97730e863bbSAndi Kleen if (dl && ch->num_aggr) 97830e863bbSAndi Kleen dl->cycles = ch->cycles_aggr / ch->num_aggr; 97930e863bbSAndi Kleen browser->have_cycles = true; 98030e863bbSAndi Kleen } 98130e863bbSAndi Kleen } 98230e863bbSAndi Kleen pthread_mutex_unlock(¬es->lock); 98330e863bbSAndi Kleen } 98430e863bbSAndi Kleen 985b793a401SArnaldo Carvalho de Melo static void annotate_browser__mark_jump_targets(struct annotate_browser *browser, 986b793a401SArnaldo Carvalho de Melo size_t size) 987b793a401SArnaldo Carvalho de Melo { 988b793a401SArnaldo Carvalho de Melo u64 offset; 98932ae1efdSNamhyung Kim struct map_symbol *ms = browser->b.priv; 99032ae1efdSNamhyung Kim struct symbol *sym = ms->sym; 99132ae1efdSNamhyung Kim 99232ae1efdSNamhyung Kim /* PLT symbols contain external offsets */ 99332ae1efdSNamhyung Kim if (strstr(sym->name, "@plt")) 99432ae1efdSNamhyung Kim return; 995b793a401SArnaldo Carvalho de Melo 996b793a401SArnaldo Carvalho de Melo for (offset = 0; offset < size; ++offset) { 997b793a401SArnaldo Carvalho de Melo struct disasm_line *dl = browser->offsets[offset], *dlt; 998b793a401SArnaldo Carvalho de Melo struct browser_disasm_line *bdlt; 999b793a401SArnaldo Carvalho de Melo 1000865c66c4SFrederik Deweerdt if (!disasm_line__is_valid_jump(dl, sym)) 1001b793a401SArnaldo Carvalho de Melo continue; 1002b793a401SArnaldo Carvalho de Melo 100344d1a3edSArnaldo Carvalho de Melo dlt = browser->offsets[dl->ops.target.offset]; 10049481ede9SArnaldo Carvalho de Melo /* 10059481ede9SArnaldo Carvalho de Melo * FIXME: Oops, no jump target? Buggy disassembler? Or do we 10069481ede9SArnaldo Carvalho de Melo * have to adjust to the previous offset? 10079481ede9SArnaldo Carvalho de Melo */ 10089481ede9SArnaldo Carvalho de Melo if (dlt == NULL) 10099481ede9SArnaldo Carvalho de Melo continue; 10109481ede9SArnaldo Carvalho de Melo 1011b793a401SArnaldo Carvalho de Melo bdlt = disasm_line__browser(dlt); 10122402e4a9SArnaldo Carvalho de Melo if (++bdlt->jump_sources > browser->max_jump_sources) 10132402e4a9SArnaldo Carvalho de Melo browser->max_jump_sources = bdlt->jump_sources; 10142402e4a9SArnaldo Carvalho de Melo 10152402e4a9SArnaldo Carvalho de Melo ++browser->nr_jumps; 1016b793a401SArnaldo Carvalho de Melo } 1017b793a401SArnaldo Carvalho de Melo } 1018b793a401SArnaldo Carvalho de Melo 10192402e4a9SArnaldo Carvalho de Melo static inline int width_jumps(int n) 10202402e4a9SArnaldo Carvalho de Melo { 10212402e4a9SArnaldo Carvalho de Melo if (n >= 100) 10222402e4a9SArnaldo Carvalho de Melo return 5; 10232402e4a9SArnaldo Carvalho de Melo if (n / 10) 10242402e4a9SArnaldo Carvalho de Melo return 2; 10252402e4a9SArnaldo Carvalho de Melo return 1; 10262402e4a9SArnaldo Carvalho de Melo } 10272402e4a9SArnaldo Carvalho de Melo 1028db8fd07aSNamhyung Kim int symbol__tui_annotate(struct symbol *sym, struct map *map, 1029db8fd07aSNamhyung Kim struct perf_evsel *evsel, 10309783adf7SNamhyung Kim struct hist_browser_timer *hbt) 1031aca7a94dSNamhyung Kim { 103229ed6e76SArnaldo Carvalho de Melo struct disasm_line *pos, *n; 1033aca7a94dSNamhyung Kim struct annotation *notes; 1034c0a58fb2SSamuel Liao size_t size; 1035aca7a94dSNamhyung Kim struct map_symbol ms = { 1036aca7a94dSNamhyung Kim .map = map, 1037aca7a94dSNamhyung Kim .sym = sym, 1038aca7a94dSNamhyung Kim }; 1039aca7a94dSNamhyung Kim struct annotate_browser browser = { 1040aca7a94dSNamhyung Kim .b = { 1041a3f895beSArnaldo Carvalho de Melo .refresh = annotate_browser__refresh, 1042aca7a94dSNamhyung Kim .seek = ui_browser__list_head_seek, 1043aca7a94dSNamhyung Kim .write = annotate_browser__write, 104429ed6e76SArnaldo Carvalho de Melo .filter = disasm_line__filter, 1045aca7a94dSNamhyung Kim .priv = &ms, 1046aca7a94dSNamhyung Kim .use_navkeypressed = true, 1047aca7a94dSNamhyung Kim }, 1048aca7a94dSNamhyung Kim }; 1049ee51d851SArnaldo Carvalho de Melo int ret = -1, err; 1050c7e7b610SNamhyung Kim int nr_pcnt = 1; 1051c7e7b610SNamhyung Kim size_t sizeof_bdl = sizeof(struct browser_disasm_line); 1052aca7a94dSNamhyung Kim 1053aca7a94dSNamhyung Kim if (sym == NULL) 1054aca7a94dSNamhyung Kim return -1; 1055aca7a94dSNamhyung Kim 1056c0a58fb2SSamuel Liao size = symbol__size(sym); 1057c0a58fb2SSamuel Liao 1058aca7a94dSNamhyung Kim if (map->dso->annotate_warned) 1059aca7a94dSNamhyung Kim return -1; 1060aca7a94dSNamhyung Kim 1061b793a401SArnaldo Carvalho de Melo browser.offsets = zalloc(size * sizeof(struct disasm_line *)); 1062b793a401SArnaldo Carvalho de Melo if (browser.offsets == NULL) { 1063b793a401SArnaldo Carvalho de Melo ui__error("Not enough memory!"); 1064b793a401SArnaldo Carvalho de Melo return -1; 1065b793a401SArnaldo Carvalho de Melo } 1066b793a401SArnaldo Carvalho de Melo 1067c7e7b610SNamhyung Kim if (perf_evsel__is_group_event(evsel)) { 1068c7e7b610SNamhyung Kim nr_pcnt = evsel->nr_members; 10690c4a5bceSMartin Liška sizeof_bdl += sizeof(struct disasm_line_samples) * 10700c4a5bceSMartin Liška (nr_pcnt - 1); 1071c7e7b610SNamhyung Kim } 1072c7e7b610SNamhyung Kim 1073786c1b51SArnaldo Carvalho de Melo err = symbol__disassemble(sym, map, perf_evsel__env_arch(evsel), sizeof_bdl); 1074ee51d851SArnaldo Carvalho de Melo if (err) { 1075ee51d851SArnaldo Carvalho de Melo char msg[BUFSIZ]; 1076ee51d851SArnaldo Carvalho de Melo symbol__strerror_disassemble(sym, map, err, msg, sizeof(msg)); 1077ee51d851SArnaldo Carvalho de Melo ui__error("Couldn't annotate %s:\n%s", sym->name, msg); 1078b793a401SArnaldo Carvalho de Melo goto out_free_offsets; 1079aca7a94dSNamhyung Kim } 1080aca7a94dSNamhyung Kim 10817727a925SArnaldo Carvalho de Melo ui_helpline__push("Press ESC to exit"); 1082aca7a94dSNamhyung Kim 1083aca7a94dSNamhyung Kim notes = symbol__annotation(sym); 1084aca7a94dSNamhyung Kim browser.start = map__rip_2objdump(map, sym->start); 1085aca7a94dSNamhyung Kim 1086aca7a94dSNamhyung Kim list_for_each_entry(pos, ¬es->src->source, node) { 1087887c0066SArnaldo Carvalho de Melo struct browser_disasm_line *bpos; 1088aca7a94dSNamhyung Kim size_t line_len = strlen(pos->line); 1089aca7a94dSNamhyung Kim 1090aca7a94dSNamhyung Kim if (browser.b.width < line_len) 1091aca7a94dSNamhyung Kim browser.b.width = line_len; 1092887c0066SArnaldo Carvalho de Melo bpos = disasm_line__browser(pos); 1093887c0066SArnaldo Carvalho de Melo bpos->idx = browser.nr_entries++; 1094b793a401SArnaldo Carvalho de Melo if (pos->offset != -1) { 1095887c0066SArnaldo Carvalho de Melo bpos->idx_asm = browser.nr_asm_entries++; 109697148a97SArnaldo Carvalho de Melo /* 109797148a97SArnaldo Carvalho de Melo * FIXME: short term bandaid to cope with assembly 109897148a97SArnaldo Carvalho de Melo * routines that comes with labels in the same column 109997148a97SArnaldo Carvalho de Melo * as the address in objdump, sigh. 110097148a97SArnaldo Carvalho de Melo * 110197148a97SArnaldo Carvalho de Melo * E.g. copy_user_generic_unrolled 110297148a97SArnaldo Carvalho de Melo */ 110397148a97SArnaldo Carvalho de Melo if (pos->offset < (s64)size) 1104b793a401SArnaldo Carvalho de Melo browser.offsets[pos->offset] = pos; 1105b793a401SArnaldo Carvalho de Melo } else 1106887c0066SArnaldo Carvalho de Melo bpos->idx_asm = -1; 1107aca7a94dSNamhyung Kim } 1108aca7a94dSNamhyung Kim 1109b793a401SArnaldo Carvalho de Melo annotate_browser__mark_jump_targets(&browser, size); 111030e863bbSAndi Kleen annotate__compute_ipc(&browser, size, sym); 1111b793a401SArnaldo Carvalho de Melo 11122402e4a9SArnaldo Carvalho de Melo browser.addr_width = browser.target_width = browser.min_addr_width = hex_width(size); 111383b1f2aaSArnaldo Carvalho de Melo browser.max_addr_width = hex_width(sym->end); 11142402e4a9SArnaldo Carvalho de Melo browser.jumps_width = width_jumps(browser.max_jump_sources); 1115c7e7b610SNamhyung Kim browser.nr_events = nr_pcnt; 1116aca7a94dSNamhyung Kim browser.b.nr_entries = browser.nr_entries; 1117aca7a94dSNamhyung Kim browser.b.entries = ¬es->src->source, 1118aca7a94dSNamhyung Kim browser.b.width += 18; /* Percentage */ 1119e9823b21SArnaldo Carvalho de Melo 1120e9823b21SArnaldo Carvalho de Melo if (annotate_browser__opts.hide_src_code) 1121e9823b21SArnaldo Carvalho de Melo annotate_browser__init_asm_mode(&browser); 1122e9823b21SArnaldo Carvalho de Melo 1123e9823b21SArnaldo Carvalho de Melo annotate_browser__update_addr_width(&browser); 1124e9823b21SArnaldo Carvalho de Melo 1125db8fd07aSNamhyung Kim ret = annotate_browser__run(&browser, evsel, hbt); 1126aca7a94dSNamhyung Kim list_for_each_entry_safe(pos, n, ¬es->src->source, node) { 1127aca7a94dSNamhyung Kim list_del(&pos->node); 112829ed6e76SArnaldo Carvalho de Melo disasm_line__free(pos); 1129aca7a94dSNamhyung Kim } 1130b793a401SArnaldo Carvalho de Melo 1131b793a401SArnaldo Carvalho de Melo out_free_offsets: 1132b793a401SArnaldo Carvalho de Melo free(browser.offsets); 1133aca7a94dSNamhyung Kim return ret; 1134aca7a94dSNamhyung Kim } 1135c323cf04SArnaldo Carvalho de Melo 1136c323cf04SArnaldo Carvalho de Melo #define ANNOTATE_CFG(n) \ 1137c323cf04SArnaldo Carvalho de Melo { .name = #n, .value = &annotate_browser__opts.n, } 1138c323cf04SArnaldo Carvalho de Melo 1139c323cf04SArnaldo Carvalho de Melo /* 1140c323cf04SArnaldo Carvalho de Melo * Keep the entries sorted, they are bsearch'ed 1141c323cf04SArnaldo Carvalho de Melo */ 11427c3102b8SArnaldo Carvalho de Melo static struct annotate_config { 1143c323cf04SArnaldo Carvalho de Melo const char *name; 1144c323cf04SArnaldo Carvalho de Melo bool *value; 1145c323cf04SArnaldo Carvalho de Melo } annotate__configs[] = { 1146c323cf04SArnaldo Carvalho de Melo ANNOTATE_CFG(hide_src_code), 1147c323cf04SArnaldo Carvalho de Melo ANNOTATE_CFG(jump_arrows), 1148e592488cSAndi Kleen ANNOTATE_CFG(show_linenr), 1149c323cf04SArnaldo Carvalho de Melo ANNOTATE_CFG(show_nr_jumps), 11500c4a5bceSMartin Liška ANNOTATE_CFG(show_total_period), 115139ff7cdbSNamhyung Kim ANNOTATE_CFG(use_offset), 1152c323cf04SArnaldo Carvalho de Melo }; 1153c323cf04SArnaldo Carvalho de Melo 1154c323cf04SArnaldo Carvalho de Melo #undef ANNOTATE_CFG 1155c323cf04SArnaldo Carvalho de Melo 1156c323cf04SArnaldo Carvalho de Melo static int annotate_config__cmp(const void *name, const void *cfgp) 1157c323cf04SArnaldo Carvalho de Melo { 11587c3102b8SArnaldo Carvalho de Melo const struct annotate_config *cfg = cfgp; 1159c323cf04SArnaldo Carvalho de Melo 1160c323cf04SArnaldo Carvalho de Melo return strcmp(name, cfg->name); 1161c323cf04SArnaldo Carvalho de Melo } 1162c323cf04SArnaldo Carvalho de Melo 11631d037ca1SIrina Tirdea static int annotate__config(const char *var, const char *value, 11641d037ca1SIrina Tirdea void *data __maybe_unused) 1165c323cf04SArnaldo Carvalho de Melo { 11667c3102b8SArnaldo Carvalho de Melo struct annotate_config *cfg; 1167c323cf04SArnaldo Carvalho de Melo const char *name; 1168c323cf04SArnaldo Carvalho de Melo 1169c323cf04SArnaldo Carvalho de Melo if (prefixcmp(var, "annotate.") != 0) 1170c323cf04SArnaldo Carvalho de Melo return 0; 1171c323cf04SArnaldo Carvalho de Melo 1172c323cf04SArnaldo Carvalho de Melo name = var + 9; 1173c323cf04SArnaldo Carvalho de Melo cfg = bsearch(name, annotate__configs, ARRAY_SIZE(annotate__configs), 11747c3102b8SArnaldo Carvalho de Melo sizeof(struct annotate_config), annotate_config__cmp); 1175c323cf04SArnaldo Carvalho de Melo 1176c323cf04SArnaldo Carvalho de Melo if (cfg == NULL) 1177f06cff7cSArnaldo Carvalho de Melo ui__warning("%s variable unknown, ignoring...", var); 1178f06cff7cSArnaldo Carvalho de Melo else 1179c323cf04SArnaldo Carvalho de Melo *cfg->value = perf_config_bool(name, value); 1180c323cf04SArnaldo Carvalho de Melo return 0; 1181c323cf04SArnaldo Carvalho de Melo } 1182c323cf04SArnaldo Carvalho de Melo 1183c323cf04SArnaldo Carvalho de Melo void annotate_browser__init(void) 1184c323cf04SArnaldo Carvalho de Melo { 1185c323cf04SArnaldo Carvalho de Melo perf_config(annotate__config, NULL); 1186c323cf04SArnaldo Carvalho de Melo } 1187