1b2441318SGreg Kroah-Hartman // SPDX-License-Identifier: GPL-2.0 2aca7a94dSNamhyung Kim #include "../../util/util.h" 3aca7a94dSNamhyung Kim #include "../browser.h" 4aca7a94dSNamhyung Kim #include "../helpline.h" 5aca7a94dSNamhyung Kim #include "../ui.h" 6aca7a94dSNamhyung Kim #include "../util.h" 7aca7a94dSNamhyung Kim #include "../../util/annotate.h" 8aca7a94dSNamhyung Kim #include "../../util/hist.h" 9aca7a94dSNamhyung Kim #include "../../util/sort.h" 10aca7a94dSNamhyung Kim #include "../../util/symbol.h" 11db8fd07aSNamhyung Kim #include "../../util/evsel.h" 1241840d21STaeung Song #include "../../util/config.h" 1369fb09f6SJin Yao #include "../../util/evlist.h" 14fd20e811SArnaldo Carvalho de Melo #include <inttypes.h> 15aca7a94dSNamhyung Kim #include <pthread.h> 16877a7a11SArnaldo Carvalho de Melo #include <linux/kernel.h> 178e99b6d4SArnaldo Carvalho de Melo #include <linux/string.h> 18b0742e90SArnaldo Carvalho de Melo #include <sys/ttydefaults.h> 19aca7a94dSNamhyung Kim 200c4a5bceSMartin Liška struct disasm_line_samples { 210c4a5bceSMartin Liška double percent; 22bb79a232SArnaldo Carvalho de Melo struct sym_hist_entry he; 230c4a5bceSMartin Liška }; 240c4a5bceSMartin Liška 25f8f4aaeaSAndi Kleen #define IPC_WIDTH 6 26f8f4aaeaSAndi Kleen #define CYCLES_WIDTH 6 27f8f4aaeaSAndi Kleen 280d957970SJiri Olsa struct browser_line { 29b793a401SArnaldo Carvalho de Melo u32 idx; 30b793a401SArnaldo Carvalho de Melo int idx_asm; 317d5b12f5SArnaldo Carvalho de Melo int jump_sources; 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, 409cef4b0bSTaeung Song show_nr_samples, 410c4a5bceSMartin Liška show_total_period; 42e9823b21SArnaldo Carvalho de Melo } annotate_browser__opts = { 43e9823b21SArnaldo Carvalho de Melo .use_offset = true, 44e9823b21SArnaldo Carvalho de Melo .jump_arrows = true, 45e9823b21SArnaldo Carvalho de Melo }; 46e9823b21SArnaldo Carvalho de Melo 47dcaa3948SJin Yao struct arch; 48dcaa3948SJin Yao 49aca7a94dSNamhyung Kim struct annotate_browser { 50aca7a94dSNamhyung Kim struct ui_browser b; 51aca7a94dSNamhyung Kim struct rb_root entries; 52aca7a94dSNamhyung Kim struct rb_node *curr_hot; 537bcbcd58SJiri Olsa struct annotation_line *selection; 54e1b60b5bSJiri Olsa struct annotation_line **offsets; 55dcaa3948SJin Yao struct arch *arch; 56c7e7b610SNamhyung Kim int nr_events; 57aca7a94dSNamhyung Kim u64 start; 58aca7a94dSNamhyung Kim int nr_asm_entries; 59aca7a94dSNamhyung Kim int nr_entries; 602402e4a9SArnaldo Carvalho de Melo int max_jump_sources; 612402e4a9SArnaldo Carvalho de Melo int nr_jumps; 62aca7a94dSNamhyung Kim bool searching_backwards; 6330e863bbSAndi Kleen bool have_cycles; 6483b1f2aaSArnaldo Carvalho de Melo u8 addr_width; 652402e4a9SArnaldo Carvalho de Melo u8 jumps_width; 662402e4a9SArnaldo Carvalho de Melo u8 target_width; 6783b1f2aaSArnaldo Carvalho de Melo u8 min_addr_width; 6883b1f2aaSArnaldo Carvalho de Melo u8 max_addr_width; 69aca7a94dSNamhyung Kim char search_bf[128]; 70aca7a94dSNamhyung Kim }; 71aca7a94dSNamhyung Kim 72a5ef2702SJiri Olsa static inline struct browser_line *browser_line(struct annotation_line *al) 73aca7a94dSNamhyung Kim { 74a5ef2702SJiri Olsa void *ptr = al; 75a5ef2702SJiri Olsa 76a5ef2702SJiri Olsa ptr = container_of(al, struct disasm_line, al); 77a5ef2702SJiri Olsa return ptr - sizeof(struct browser_line); 78aca7a94dSNamhyung Kim } 79aca7a94dSNamhyung Kim 801d037ca1SIrina Tirdea static bool disasm_line__filter(struct ui_browser *browser __maybe_unused, 811d037ca1SIrina Tirdea void *entry) 82aca7a94dSNamhyung Kim { 83e9823b21SArnaldo Carvalho de Melo if (annotate_browser__opts.hide_src_code) { 84d5490b96SJiri Olsa struct annotation_line *al = list_entry(entry, struct annotation_line, node); 85d5490b96SJiri Olsa 86d5490b96SJiri Olsa return al->offset == -1; 87aca7a94dSNamhyung Kim } 88aca7a94dSNamhyung Kim 89aca7a94dSNamhyung Kim return false; 90aca7a94dSNamhyung Kim } 91aca7a94dSNamhyung Kim 922402e4a9SArnaldo Carvalho de Melo static int annotate_browser__jumps_percent_color(struct annotate_browser *browser, 932402e4a9SArnaldo Carvalho de Melo int nr, bool current) 942402e4a9SArnaldo Carvalho de Melo { 952402e4a9SArnaldo Carvalho de Melo if (current && (!browser->b.use_navkeypressed || browser->b.navkeypressed)) 962402e4a9SArnaldo Carvalho de Melo return HE_COLORSET_SELECTED; 972402e4a9SArnaldo Carvalho de Melo if (nr == browser->max_jump_sources) 982402e4a9SArnaldo Carvalho de Melo return HE_COLORSET_TOP; 992402e4a9SArnaldo Carvalho de Melo if (nr > 1) 1002402e4a9SArnaldo Carvalho de Melo return HE_COLORSET_MEDIUM; 1012402e4a9SArnaldo Carvalho de Melo return HE_COLORSET_NORMAL; 1022402e4a9SArnaldo Carvalho de Melo } 1032402e4a9SArnaldo Carvalho de Melo 1042402e4a9SArnaldo Carvalho de Melo static int annotate_browser__set_jumps_percent_color(struct annotate_browser *browser, 1052402e4a9SArnaldo Carvalho de Melo int nr, bool current) 1062402e4a9SArnaldo Carvalho de Melo { 1072402e4a9SArnaldo Carvalho de Melo int color = annotate_browser__jumps_percent_color(browser, nr, current); 1082402e4a9SArnaldo Carvalho de Melo return ui_browser__set_color(&browser->b, color); 1092402e4a9SArnaldo Carvalho de Melo } 1102402e4a9SArnaldo Carvalho de Melo 111f8f4aaeaSAndi Kleen static int annotate_browser__pcnt_width(struct annotate_browser *ab) 112f8f4aaeaSAndi Kleen { 1133861c4a4SArnaldo Carvalho de Melo return (annotate_browser__opts.show_total_period ? 12 : 7) * ab->nr_events; 114bc1e5d60SArnaldo Carvalho de Melo } 115f8f4aaeaSAndi Kleen 116bc1e5d60SArnaldo Carvalho de Melo static int annotate_browser__cycles_width(struct annotate_browser *ab) 117bc1e5d60SArnaldo Carvalho de Melo { 118bc1e5d60SArnaldo Carvalho de Melo return ab->have_cycles ? IPC_WIDTH + CYCLES_WIDTH : 0; 119f8f4aaeaSAndi Kleen } 120f8f4aaeaSAndi Kleen 12105e8b080SArnaldo Carvalho de Melo static void annotate_browser__write(struct ui_browser *browser, void *entry, int row) 122aca7a94dSNamhyung Kim { 12305e8b080SArnaldo Carvalho de Melo struct annotate_browser *ab = container_of(browser, struct annotate_browser, b); 124a17c4ca0SJiri Olsa struct disasm_line *dl = list_entry(entry, struct disasm_line, al.node); 125a5ef2702SJiri Olsa struct browser_line *bdl = browser_line(&dl->al); 12605e8b080SArnaldo Carvalho de Melo bool current_entry = ui_browser__is_current_entry(browser, row); 127e9823b21SArnaldo Carvalho de Melo bool change_color = (!annotate_browser__opts.hide_src_code && 12805e8b080SArnaldo Carvalho de Melo (!current_entry || (browser->use_navkeypressed && 12905e8b080SArnaldo Carvalho de Melo !browser->navkeypressed))); 13005e8b080SArnaldo Carvalho de Melo int width = browser->width, printed; 131bc1e5d60SArnaldo Carvalho de Melo int i, pcnt_width = annotate_browser__pcnt_width(ab), 132bc1e5d60SArnaldo Carvalho de Melo cycles_width = annotate_browser__cycles_width(ab); 133c7e7b610SNamhyung Kim double percent_max = 0.0; 13483b1f2aaSArnaldo Carvalho de Melo char bf[256]; 135ec27ae18SJin Yao bool show_title = false; 136aca7a94dSNamhyung Kim 137c7e7b610SNamhyung Kim for (i = 0; i < ab->nr_events; i++) { 1383ab6db8dSJiri Olsa if (dl->al.samples[i].percent > percent_max) 1393ab6db8dSJiri Olsa percent_max = dl->al.samples[i].percent; 140c7e7b610SNamhyung Kim } 141c7e7b610SNamhyung Kim 142d5490b96SJiri Olsa if ((row == 0) && (dl->al.offset == -1 || percent_max == 0.0)) { 143ec27ae18SJin Yao if (ab->have_cycles) { 14437236d5eSJiri Olsa if (dl->al.ipc == 0.0 && dl->al.cycles == 0) 145ec27ae18SJin Yao show_title = true; 146ec27ae18SJin Yao } else 147ec27ae18SJin Yao show_title = true; 148ec27ae18SJin Yao } 149ec27ae18SJin Yao 150d5490b96SJiri Olsa if (dl->al.offset != -1 && percent_max != 0.0) { 151c7e7b610SNamhyung Kim for (i = 0; i < ab->nr_events; i++) { 1520c4a5bceSMartin Liška ui_browser__set_percent_color(browser, 1533ab6db8dSJiri Olsa dl->al.samples[i].percent, 154c7e7b610SNamhyung Kim current_entry); 155517dfdb3SArnaldo Carvalho de Melo if (annotate_browser__opts.show_total_period) { 1563861c4a4SArnaldo Carvalho de Melo ui_browser__printf(browser, "%11" PRIu64 " ", 1573ab6db8dSJiri Olsa dl->al.samples[i].he.period); 1589cef4b0bSTaeung Song } else if (annotate_browser__opts.show_nr_samples) { 1599cef4b0bSTaeung Song ui_browser__printf(browser, "%6" PRIu64 " ", 1603ab6db8dSJiri Olsa dl->al.samples[i].he.nr_samples); 161517dfdb3SArnaldo Carvalho de Melo } else { 162517dfdb3SArnaldo Carvalho de Melo ui_browser__printf(browser, "%6.2f ", 1633ab6db8dSJiri Olsa dl->al.samples[i].percent); 164517dfdb3SArnaldo Carvalho de Melo } 165c7e7b610SNamhyung Kim } 166aca7a94dSNamhyung Kim } else { 16705e8b080SArnaldo Carvalho de Melo ui_browser__set_percent_color(browser, 0, current_entry); 168ec27ae18SJin Yao 169ec27ae18SJin Yao if (!show_title) 170bc1e5d60SArnaldo Carvalho de Melo ui_browser__write_nstring(browser, " ", pcnt_width); 1713861c4a4SArnaldo Carvalho de Melo else { 1723861c4a4SArnaldo Carvalho de Melo ui_browser__printf(browser, "%*s", pcnt_width, 1739cef4b0bSTaeung Song annotate_browser__opts.show_total_period ? "Period" : 1749cef4b0bSTaeung Song annotate_browser__opts.show_nr_samples ? "Samples" : "Percent"); 1753861c4a4SArnaldo Carvalho de Melo } 176f8f4aaeaSAndi Kleen } 177f8f4aaeaSAndi Kleen if (ab->have_cycles) { 17837236d5eSJiri Olsa if (dl->al.ipc) 17937236d5eSJiri Olsa ui_browser__printf(browser, "%*.2f ", IPC_WIDTH - 1, dl->al.ipc); 180ec27ae18SJin Yao else if (!show_title) 18126270a00SArnaldo Carvalho de Melo ui_browser__write_nstring(browser, " ", IPC_WIDTH); 182ec27ae18SJin Yao else 183ec27ae18SJin Yao ui_browser__printf(browser, "%*s ", IPC_WIDTH - 1, "IPC"); 184ec27ae18SJin Yao 18537236d5eSJiri Olsa if (dl->al.cycles) 186517dfdb3SArnaldo Carvalho de Melo ui_browser__printf(browser, "%*" PRIu64 " ", 18737236d5eSJiri Olsa CYCLES_WIDTH - 1, dl->al.cycles); 188ec27ae18SJin Yao else if (!show_title) 18926270a00SArnaldo Carvalho de Melo ui_browser__write_nstring(browser, " ", CYCLES_WIDTH); 190ec27ae18SJin Yao else 191ec27ae18SJin Yao ui_browser__printf(browser, "%*s ", CYCLES_WIDTH - 1, "Cycle"); 192aca7a94dSNamhyung Kim } 193aca7a94dSNamhyung Kim 194cf2dacc5SArnaldo Carvalho de Melo SLsmg_write_char(' '); 195aca7a94dSNamhyung Kim 196aca7a94dSNamhyung Kim /* The scroll bar isn't being used */ 19705e8b080SArnaldo Carvalho de Melo if (!browser->navkeypressed) 198aca7a94dSNamhyung Kim width += 1; 199aca7a94dSNamhyung Kim 200d5490b96SJiri Olsa if (!*dl->al.line) 201bc1e5d60SArnaldo Carvalho de Melo ui_browser__write_nstring(browser, " ", width - pcnt_width - cycles_width); 202d5490b96SJiri Olsa else if (dl->al.offset == -1) { 203d5490b96SJiri Olsa if (dl->al.line_nr && annotate_browser__opts.show_linenr) 204e592488cSAndi Kleen printed = scnprintf(bf, sizeof(bf), "%-*d ", 205d5490b96SJiri Olsa ab->addr_width + 1, dl->al.line_nr); 206e592488cSAndi Kleen else 20783b1f2aaSArnaldo Carvalho de Melo printed = scnprintf(bf, sizeof(bf), "%*s ", 20883b1f2aaSArnaldo Carvalho de Melo ab->addr_width, " "); 20926270a00SArnaldo Carvalho de Melo ui_browser__write_nstring(browser, bf, printed); 210d5490b96SJiri Olsa ui_browser__write_nstring(browser, dl->al.line, width - printed - pcnt_width - cycles_width + 1); 21183b1f2aaSArnaldo Carvalho de Melo } else { 212d5490b96SJiri Olsa u64 addr = dl->al.offset; 21383b1f2aaSArnaldo Carvalho de Melo int color = -1; 214aca7a94dSNamhyung Kim 215e9823b21SArnaldo Carvalho de Melo if (!annotate_browser__opts.use_offset) 216aca7a94dSNamhyung Kim addr += ab->start; 217aca7a94dSNamhyung Kim 218e9823b21SArnaldo Carvalho de Melo if (!annotate_browser__opts.use_offset) { 219aca7a94dSNamhyung Kim printed = scnprintf(bf, sizeof(bf), "%" PRIx64 ": ", addr); 22061e04b33SArnaldo Carvalho de Melo } else { 2217d5b12f5SArnaldo Carvalho de Melo if (bdl->jump_sources) { 222e9823b21SArnaldo Carvalho de Melo if (annotate_browser__opts.show_nr_jumps) { 2232402e4a9SArnaldo Carvalho de Melo int prev; 2242402e4a9SArnaldo Carvalho de Melo printed = scnprintf(bf, sizeof(bf), "%*d ", 2252402e4a9SArnaldo Carvalho de Melo ab->jumps_width, 2262402e4a9SArnaldo Carvalho de Melo bdl->jump_sources); 2272402e4a9SArnaldo Carvalho de Melo prev = annotate_browser__set_jumps_percent_color(ab, bdl->jump_sources, 2282402e4a9SArnaldo Carvalho de Melo current_entry); 22926270a00SArnaldo Carvalho de Melo ui_browser__write_nstring(browser, bf, printed); 23005e8b080SArnaldo Carvalho de Melo ui_browser__set_color(browser, prev); 2312402e4a9SArnaldo Carvalho de Melo } 2322402e4a9SArnaldo Carvalho de Melo 23361e04b33SArnaldo Carvalho de Melo printed = scnprintf(bf, sizeof(bf), "%*" PRIx64 ": ", 2342402e4a9SArnaldo Carvalho de Melo ab->target_width, addr); 23561e04b33SArnaldo Carvalho de Melo } else { 23661e04b33SArnaldo Carvalho de Melo printed = scnprintf(bf, sizeof(bf), "%*s ", 23783b1f2aaSArnaldo Carvalho de Melo ab->addr_width, " "); 23861e04b33SArnaldo Carvalho de Melo } 23961e04b33SArnaldo Carvalho de Melo } 240b793a401SArnaldo Carvalho de Melo 241aca7a94dSNamhyung Kim if (change_color) 24205e8b080SArnaldo Carvalho de Melo color = ui_browser__set_color(browser, HE_COLORSET_ADDR); 24326270a00SArnaldo Carvalho de Melo ui_browser__write_nstring(browser, bf, printed); 244aca7a94dSNamhyung Kim if (change_color) 24505e8b080SArnaldo Carvalho de Melo ui_browser__set_color(browser, color); 24675b49202SArnaldo Carvalho de Melo if (dl->ins.ops && dl->ins.ops->scnprintf) { 24775b49202SArnaldo Carvalho de Melo if (ins__is_jump(&dl->ins)) { 248d5490b96SJiri Olsa bool fwd = dl->ops.target.offset > dl->al.offset; 24951a0d455SArnaldo Carvalho de Melo 25005e8b080SArnaldo Carvalho de Melo ui_browser__write_graph(browser, fwd ? SLSMG_DARROW_CHAR : 25151a0d455SArnaldo Carvalho de Melo SLSMG_UARROW_CHAR); 25251a0d455SArnaldo Carvalho de Melo SLsmg_write_char(' '); 25375b49202SArnaldo Carvalho de Melo } else if (ins__is_call(&dl->ins)) { 25405e8b080SArnaldo Carvalho de Melo ui_browser__write_graph(browser, SLSMG_RARROW_CHAR); 25588298f5aSArnaldo Carvalho de Melo SLsmg_write_char(' '); 25675b49202SArnaldo Carvalho de Melo } else if (ins__is_ret(&dl->ins)) { 25705e8b080SArnaldo Carvalho de Melo ui_browser__write_graph(browser, SLSMG_LARROW_CHAR); 2584ea08b52SArnaldo Carvalho de Melo SLsmg_write_char(' '); 2596ef94929SNaveen N. Rao } else { 2606ef94929SNaveen N. Rao ui_browser__write_nstring(browser, " ", 2); 2614ea08b52SArnaldo Carvalho de Melo } 2626ef94929SNaveen N. Rao } else { 2636ef94929SNaveen N. Rao ui_browser__write_nstring(browser, " ", 2); 2644ea08b52SArnaldo Carvalho de Melo } 2654ea08b52SArnaldo Carvalho de Melo 266e9823b21SArnaldo Carvalho de Melo disasm_line__scnprintf(dl, bf, sizeof(bf), !annotate_browser__opts.use_offset); 267bc1e5d60SArnaldo Carvalho de Melo ui_browser__write_nstring(browser, bf, width - pcnt_width - cycles_width - 3 - printed); 268aca7a94dSNamhyung Kim } 269aca7a94dSNamhyung Kim 270aca7a94dSNamhyung Kim if (current_entry) 2717bcbcd58SJiri Olsa ab->selection = &dl->al; 272aca7a94dSNamhyung Kim } 273aca7a94dSNamhyung Kim 274865c66c4SFrederik Deweerdt static bool disasm_line__is_valid_jump(struct disasm_line *dl, struct symbol *sym) 275865c66c4SFrederik Deweerdt { 27675b49202SArnaldo Carvalho de Melo if (!dl || !dl->ins.ops || !ins__is_jump(&dl->ins) 277865c66c4SFrederik Deweerdt || !disasm_line__has_offset(dl) 278e216874cSRavi Bangoria || dl->ops.target.offset < 0 279e216874cSRavi Bangoria || dl->ops.target.offset >= (s64)symbol__size(sym)) 280865c66c4SFrederik Deweerdt return false; 281865c66c4SFrederik Deweerdt 282865c66c4SFrederik Deweerdt return true; 283865c66c4SFrederik Deweerdt } 284865c66c4SFrederik Deweerdt 2857e63a13aSJin Yao static bool is_fused(struct annotate_browser *ab, struct disasm_line *cursor) 2867e63a13aSJin Yao { 287a17c4ca0SJiri Olsa struct disasm_line *pos = list_prev_entry(cursor, al.node); 2887e63a13aSJin Yao const char *name; 2897e63a13aSJin Yao 2907e63a13aSJin Yao if (!pos) 2917e63a13aSJin Yao return false; 2927e63a13aSJin Yao 2937e63a13aSJin Yao if (ins__is_lock(&pos->ins)) 2947e63a13aSJin Yao name = pos->ops.locked.ins.name; 2957e63a13aSJin Yao else 2967e63a13aSJin Yao name = pos->ins.name; 2977e63a13aSJin Yao 2987e63a13aSJin Yao if (!name || !cursor->ins.name) 2997e63a13aSJin Yao return false; 3007e63a13aSJin Yao 3017e63a13aSJin Yao return ins__is_fused(ab->arch, name, cursor->ins.name); 3027e63a13aSJin Yao } 3037e63a13aSJin Yao 3049d1ef56dSArnaldo Carvalho de Melo static void annotate_browser__draw_current_jump(struct ui_browser *browser) 305a3f895beSArnaldo Carvalho de Melo { 306a3f895beSArnaldo Carvalho de Melo struct annotate_browser *ab = container_of(browser, struct annotate_browser, b); 3077bcbcd58SJiri Olsa struct disasm_line *cursor = disasm_line(ab->selection); 308a5ef2702SJiri Olsa struct annotation_line *target; 3090d957970SJiri Olsa struct browser_line *btarget, *bcursor; 31083b1f2aaSArnaldo Carvalho de Melo unsigned int from, to; 31132ae1efdSNamhyung Kim struct map_symbol *ms = ab->b.priv; 31232ae1efdSNamhyung Kim struct symbol *sym = ms->sym; 313f8f4aaeaSAndi Kleen u8 pcnt_width = annotate_browser__pcnt_width(ab); 31432ae1efdSNamhyung Kim 31532ae1efdSNamhyung Kim /* PLT symbols contain external offsets */ 31632ae1efdSNamhyung Kim if (strstr(sym->name, "@plt")) 31732ae1efdSNamhyung Kim return; 318a3f895beSArnaldo Carvalho de Melo 319865c66c4SFrederik Deweerdt if (!disasm_line__is_valid_jump(cursor, sym)) 320a3f895beSArnaldo Carvalho de Melo return; 321a3f895beSArnaldo Carvalho de Melo 322a5ef2702SJiri Olsa target = ab->offsets[cursor->ops.target.offset]; 3239d1ef56dSArnaldo Carvalho de Melo 324a5ef2702SJiri Olsa bcursor = browser_line(&cursor->al); 325daf25d43SJiri Olsa btarget = browser_line(target); 3269d1ef56dSArnaldo Carvalho de Melo 327e9823b21SArnaldo Carvalho de Melo if (annotate_browser__opts.hide_src_code) { 3289d1ef56dSArnaldo Carvalho de Melo from = bcursor->idx_asm; 329a3f895beSArnaldo Carvalho de Melo to = btarget->idx_asm; 330a3f895beSArnaldo Carvalho de Melo } else { 3319d1ef56dSArnaldo Carvalho de Melo from = (u64)bcursor->idx; 332a3f895beSArnaldo Carvalho de Melo to = (u64)btarget->idx; 333a3f895beSArnaldo Carvalho de Melo } 334a3f895beSArnaldo Carvalho de Melo 33578ce08dfSTaeung Song ui_browser__set_color(browser, HE_COLORSET_JUMP_ARROWS); 336c7e7b610SNamhyung Kim __ui_browser__line_arrow(browser, pcnt_width + 2 + ab->addr_width, 337c7e7b610SNamhyung Kim from, to); 3387e63a13aSJin Yao 3397e63a13aSJin Yao if (is_fused(ab, cursor)) { 3407e63a13aSJin Yao ui_browser__mark_fused(browser, 3417e63a13aSJin Yao pcnt_width + 3 + ab->addr_width, 3427e63a13aSJin Yao from - 1, 3437e63a13aSJin Yao to > from ? true : false); 3447e63a13aSJin Yao } 345a3f895beSArnaldo Carvalho de Melo } 346a3f895beSArnaldo Carvalho de Melo 347a3f895beSArnaldo Carvalho de Melo static unsigned int annotate_browser__refresh(struct ui_browser *browser) 348a3f895beSArnaldo Carvalho de Melo { 349c7e7b610SNamhyung Kim struct annotate_browser *ab = container_of(browser, struct annotate_browser, b); 350a3f895beSArnaldo Carvalho de Melo int ret = ui_browser__list_head_refresh(browser); 351f8f4aaeaSAndi Kleen int pcnt_width = annotate_browser__pcnt_width(ab); 352a3f895beSArnaldo Carvalho de Melo 353e9823b21SArnaldo Carvalho de Melo if (annotate_browser__opts.jump_arrows) 3549d1ef56dSArnaldo Carvalho de Melo annotate_browser__draw_current_jump(browser); 355a3f895beSArnaldo Carvalho de Melo 35683b1f2aaSArnaldo Carvalho de Melo ui_browser__set_color(browser, HE_COLORSET_NORMAL); 357c7e7b610SNamhyung Kim __ui_browser__vline(browser, pcnt_width, 0, browser->height - 1); 358a3f895beSArnaldo Carvalho de Melo return ret; 359a3f895beSArnaldo Carvalho de Melo } 360a3f895beSArnaldo Carvalho de Melo 361b15636c6SJiri Olsa static int disasm__cmp(struct annotation_line *a, struct annotation_line *b) 362c7e7b610SNamhyung Kim { 363c7e7b610SNamhyung Kim int i; 364c7e7b610SNamhyung Kim 365b15636c6SJiri Olsa for (i = 0; i < a->samples_nr; i++) { 3660c4a5bceSMartin Liška if (a->samples[i].percent == b->samples[i].percent) 367c7e7b610SNamhyung Kim continue; 3680c4a5bceSMartin Liška return a->samples[i].percent < b->samples[i].percent; 369c7e7b610SNamhyung Kim } 370c7e7b610SNamhyung Kim return 0; 371c7e7b610SNamhyung Kim } 372c7e7b610SNamhyung Kim 373b15636c6SJiri Olsa static void disasm_rb_tree__insert(struct rb_root *root, struct annotation_line *al) 374aca7a94dSNamhyung Kim { 37529ed6e76SArnaldo Carvalho de Melo struct rb_node **p = &root->rb_node; 376aca7a94dSNamhyung Kim struct rb_node *parent = NULL; 3773ab6db8dSJiri Olsa struct annotation_line *l; 378aca7a94dSNamhyung Kim 379aca7a94dSNamhyung Kim while (*p != NULL) { 380aca7a94dSNamhyung Kim parent = *p; 3813ab6db8dSJiri Olsa l = rb_entry(parent, struct annotation_line, rb_node); 382c7e7b610SNamhyung Kim 383b15636c6SJiri Olsa if (disasm__cmp(al, l)) 384aca7a94dSNamhyung Kim p = &(*p)->rb_left; 385aca7a94dSNamhyung Kim else 386aca7a94dSNamhyung Kim p = &(*p)->rb_right; 387aca7a94dSNamhyung Kim } 3883ab6db8dSJiri Olsa rb_link_node(&al->rb_node, parent, p); 3893ab6db8dSJiri Olsa rb_insert_color(&al->rb_node, root); 390aca7a94dSNamhyung Kim } 391aca7a94dSNamhyung Kim 39205e8b080SArnaldo Carvalho de Melo static void annotate_browser__set_top(struct annotate_browser *browser, 393*ec03a77dSJiri Olsa struct annotation_line *pos, u32 idx) 394aca7a94dSNamhyung Kim { 395aca7a94dSNamhyung Kim unsigned back; 396aca7a94dSNamhyung Kim 39705e8b080SArnaldo Carvalho de Melo ui_browser__refresh_dimensions(&browser->b); 39805e8b080SArnaldo Carvalho de Melo back = browser->b.height / 2; 39905e8b080SArnaldo Carvalho de Melo browser->b.top_idx = browser->b.index = idx; 400aca7a94dSNamhyung Kim 40105e8b080SArnaldo Carvalho de Melo while (browser->b.top_idx != 0 && back != 0) { 402*ec03a77dSJiri Olsa pos = list_entry(pos->node.prev, struct annotation_line, node); 403aca7a94dSNamhyung Kim 404*ec03a77dSJiri Olsa if (disasm_line__filter(&browser->b, &pos->node)) 405aca7a94dSNamhyung Kim continue; 406aca7a94dSNamhyung Kim 40705e8b080SArnaldo Carvalho de Melo --browser->b.top_idx; 408aca7a94dSNamhyung Kim --back; 409aca7a94dSNamhyung Kim } 410aca7a94dSNamhyung Kim 411*ec03a77dSJiri Olsa browser->b.top = pos; 41205e8b080SArnaldo Carvalho de Melo browser->b.navkeypressed = true; 413aca7a94dSNamhyung Kim } 414aca7a94dSNamhyung Kim 415aca7a94dSNamhyung Kim static void annotate_browser__set_rb_top(struct annotate_browser *browser, 416aca7a94dSNamhyung Kim struct rb_node *nd) 417aca7a94dSNamhyung Kim { 4180d957970SJiri Olsa struct browser_line *bpos; 419*ec03a77dSJiri Olsa struct annotation_line *pos; 420a44b45f2SArnaldo Carvalho de Melo u32 idx; 421aca7a94dSNamhyung Kim 422*ec03a77dSJiri Olsa pos = rb_entry(nd, struct annotation_line, rb_node); 423*ec03a77dSJiri Olsa bpos = browser_line(pos); 4245b12adc8SJiri Olsa 425a44b45f2SArnaldo Carvalho de Melo idx = bpos->idx; 426e9823b21SArnaldo Carvalho de Melo if (annotate_browser__opts.hide_src_code) 427a44b45f2SArnaldo Carvalho de Melo idx = bpos->idx_asm; 428a44b45f2SArnaldo Carvalho de Melo annotate_browser__set_top(browser, pos, idx); 429aca7a94dSNamhyung Kim browser->curr_hot = nd; 430aca7a94dSNamhyung Kim } 431aca7a94dSNamhyung Kim 432aca7a94dSNamhyung Kim static void annotate_browser__calc_percent(struct annotate_browser *browser, 433db8fd07aSNamhyung Kim struct perf_evsel *evsel) 434aca7a94dSNamhyung Kim { 435aca7a94dSNamhyung Kim struct map_symbol *ms = browser->b.priv; 436aca7a94dSNamhyung Kim struct symbol *sym = ms->sym; 437aca7a94dSNamhyung Kim struct annotation *notes = symbol__annotation(sym); 438c4c72436SJiri Olsa struct disasm_line *pos; 439aca7a94dSNamhyung Kim 440aca7a94dSNamhyung Kim browser->entries = RB_ROOT; 441aca7a94dSNamhyung Kim 442aca7a94dSNamhyung Kim pthread_mutex_lock(¬es->lock); 443aca7a94dSNamhyung Kim 444e425da6cSJiri Olsa symbol__calc_percent(sym, evsel); 445e425da6cSJiri Olsa 446a17c4ca0SJiri Olsa list_for_each_entry(pos, ¬es->src->source, al.node) { 447c7e7b610SNamhyung Kim double max_percent = 0.0; 448c7e7b610SNamhyung Kim int i; 449e64aa75bSNamhyung Kim 450d5490b96SJiri Olsa if (pos->al.offset == -1) { 4515b12adc8SJiri Olsa RB_CLEAR_NODE(&pos->al.rb_node); 452e64aa75bSNamhyung Kim continue; 453e64aa75bSNamhyung Kim } 454e64aa75bSNamhyung Kim 455b15636c6SJiri Olsa for (i = 0; i < pos->al.samples_nr; i++) { 456e425da6cSJiri Olsa struct annotation_data *sample = &pos->al.samples[i]; 4570c4a5bceSMartin Liška 4583ab6db8dSJiri Olsa if (max_percent < sample->percent) 4593ab6db8dSJiri Olsa max_percent = sample->percent; 460c7e7b610SNamhyung Kim } 461c7e7b610SNamhyung Kim 46237236d5eSJiri Olsa if (max_percent < 0.01 && pos->al.ipc == 0) { 4635b12adc8SJiri Olsa RB_CLEAR_NODE(&pos->al.rb_node); 464aca7a94dSNamhyung Kim continue; 465aca7a94dSNamhyung Kim } 466b15636c6SJiri Olsa disasm_rb_tree__insert(&browser->entries, &pos->al); 467aca7a94dSNamhyung Kim } 468aca7a94dSNamhyung Kim pthread_mutex_unlock(¬es->lock); 469aca7a94dSNamhyung Kim 470aca7a94dSNamhyung Kim browser->curr_hot = rb_last(&browser->entries); 471aca7a94dSNamhyung Kim } 472aca7a94dSNamhyung Kim 473aca7a94dSNamhyung Kim static bool annotate_browser__toggle_source(struct annotate_browser *browser) 474aca7a94dSNamhyung Kim { 475*ec03a77dSJiri Olsa struct annotation_line *al; 476a5ef2702SJiri Olsa struct browser_line *bl; 477aca7a94dSNamhyung Kim off_t offset = browser->b.index - browser->b.top_idx; 478aca7a94dSNamhyung Kim 479aca7a94dSNamhyung Kim browser->b.seek(&browser->b, offset, SEEK_CUR); 480*ec03a77dSJiri Olsa al = list_entry(browser->b.top, struct annotation_line, node); 481*ec03a77dSJiri Olsa bl = browser_line(al); 482aca7a94dSNamhyung Kim 483e9823b21SArnaldo Carvalho de Melo if (annotate_browser__opts.hide_src_code) { 484a5ef2702SJiri Olsa if (bl->idx_asm < offset) 485a5ef2702SJiri Olsa offset = bl->idx; 486aca7a94dSNamhyung Kim 487aca7a94dSNamhyung Kim browser->b.nr_entries = browser->nr_entries; 488e9823b21SArnaldo Carvalho de Melo annotate_browser__opts.hide_src_code = false; 489aca7a94dSNamhyung Kim browser->b.seek(&browser->b, -offset, SEEK_CUR); 490a5ef2702SJiri Olsa browser->b.top_idx = bl->idx - offset; 491a5ef2702SJiri Olsa browser->b.index = bl->idx; 492aca7a94dSNamhyung Kim } else { 493a5ef2702SJiri Olsa if (bl->idx_asm < 0) { 494aca7a94dSNamhyung Kim ui_helpline__puts("Only available for assembly lines."); 495aca7a94dSNamhyung Kim browser->b.seek(&browser->b, -offset, SEEK_CUR); 496aca7a94dSNamhyung Kim return false; 497aca7a94dSNamhyung Kim } 498aca7a94dSNamhyung Kim 499a5ef2702SJiri Olsa if (bl->idx_asm < offset) 500a5ef2702SJiri Olsa offset = bl->idx_asm; 501aca7a94dSNamhyung Kim 502aca7a94dSNamhyung Kim browser->b.nr_entries = browser->nr_asm_entries; 503e9823b21SArnaldo Carvalho de Melo annotate_browser__opts.hide_src_code = true; 504aca7a94dSNamhyung Kim browser->b.seek(&browser->b, -offset, SEEK_CUR); 505a5ef2702SJiri Olsa browser->b.top_idx = bl->idx_asm - offset; 506a5ef2702SJiri Olsa browser->b.index = bl->idx_asm; 507aca7a94dSNamhyung Kim } 508aca7a94dSNamhyung Kim 509aca7a94dSNamhyung Kim return true; 510aca7a94dSNamhyung Kim } 511aca7a94dSNamhyung Kim 512e9823b21SArnaldo Carvalho de Melo static void annotate_browser__init_asm_mode(struct annotate_browser *browser) 513e9823b21SArnaldo Carvalho de Melo { 514e9823b21SArnaldo Carvalho de Melo ui_browser__reset_index(&browser->b); 515e9823b21SArnaldo Carvalho de Melo browser->b.nr_entries = browser->nr_asm_entries; 516e9823b21SArnaldo Carvalho de Melo } 517e9823b21SArnaldo Carvalho de Melo 51834f77abcSAdrian Hunter #define SYM_TITLE_MAX_SIZE (PATH_MAX + 64) 51934f77abcSAdrian Hunter 52034f77abcSAdrian Hunter static int sym_title(struct symbol *sym, struct map *map, char *title, 52134f77abcSAdrian Hunter size_t sz) 52234f77abcSAdrian Hunter { 52334f77abcSAdrian Hunter return snprintf(title, sz, "%s %s", sym->name, map->dso->long_name); 52434f77abcSAdrian Hunter } 52534f77abcSAdrian Hunter 526db8fd07aSNamhyung Kim static bool annotate_browser__callq(struct annotate_browser *browser, 527db8fd07aSNamhyung Kim struct perf_evsel *evsel, 5289783adf7SNamhyung Kim struct hist_browser_timer *hbt) 529aca7a94dSNamhyung Kim { 530aca7a94dSNamhyung Kim struct map_symbol *ms = browser->b.priv; 5317bcbcd58SJiri Olsa struct disasm_line *dl = disasm_line(browser->selection); 532aca7a94dSNamhyung Kim struct annotation *notes; 5331179e11bSAdrian Hunter struct addr_map_symbol target = { 5341179e11bSAdrian Hunter .map = ms->map, 5351d5077bdSAdrian Hunter .addr = map__objdump_2mem(ms->map, dl->ops.target.addr), 5361179e11bSAdrian Hunter }; 53734f77abcSAdrian Hunter char title[SYM_TITLE_MAX_SIZE]; 538aca7a94dSNamhyung Kim 53975b49202SArnaldo Carvalho de Melo if (!ins__is_call(&dl->ins)) 540aca7a94dSNamhyung Kim return false; 541aca7a94dSNamhyung Kim 542be39db9fSArnaldo Carvalho de Melo if (map_groups__find_ams(&target) || 5431d5077bdSAdrian Hunter map__rip_2objdump(target.map, target.map->map_ip(target.map, 5441d5077bdSAdrian Hunter target.addr)) != 5451d5077bdSAdrian Hunter dl->ops.target.addr) { 546aca7a94dSNamhyung Kim ui_helpline__puts("The called function was not found."); 547aca7a94dSNamhyung Kim return true; 548aca7a94dSNamhyung Kim } 549aca7a94dSNamhyung Kim 5501179e11bSAdrian Hunter notes = symbol__annotation(target.sym); 551aca7a94dSNamhyung Kim pthread_mutex_lock(¬es->lock); 552aca7a94dSNamhyung Kim 5531179e11bSAdrian Hunter if (notes->src == NULL && symbol__alloc_hist(target.sym) < 0) { 554aca7a94dSNamhyung Kim pthread_mutex_unlock(¬es->lock); 555aca7a94dSNamhyung Kim ui__warning("Not enough memory for annotating '%s' symbol!\n", 5561179e11bSAdrian Hunter target.sym->name); 557aca7a94dSNamhyung Kim return true; 558aca7a94dSNamhyung Kim } 559aca7a94dSNamhyung Kim 560aca7a94dSNamhyung Kim pthread_mutex_unlock(¬es->lock); 5611179e11bSAdrian Hunter symbol__tui_annotate(target.sym, target.map, evsel, hbt); 5621179e11bSAdrian Hunter sym_title(ms->sym, ms->map, title, sizeof(title)); 56334f77abcSAdrian Hunter ui_browser__show_title(&browser->b, title); 564aca7a94dSNamhyung Kim return true; 565aca7a94dSNamhyung Kim } 566aca7a94dSNamhyung Kim 56729ed6e76SArnaldo Carvalho de Melo static 56829ed6e76SArnaldo Carvalho de Melo struct disasm_line *annotate_browser__find_offset(struct annotate_browser *browser, 569aca7a94dSNamhyung Kim s64 offset, s64 *idx) 570aca7a94dSNamhyung Kim { 571aca7a94dSNamhyung Kim struct map_symbol *ms = browser->b.priv; 572aca7a94dSNamhyung Kim struct symbol *sym = ms->sym; 573aca7a94dSNamhyung Kim struct annotation *notes = symbol__annotation(sym); 57429ed6e76SArnaldo Carvalho de Melo struct disasm_line *pos; 575aca7a94dSNamhyung Kim 576aca7a94dSNamhyung Kim *idx = 0; 577a17c4ca0SJiri Olsa list_for_each_entry(pos, ¬es->src->source, al.node) { 578d5490b96SJiri Olsa if (pos->al.offset == offset) 579aca7a94dSNamhyung Kim return pos; 580a17c4ca0SJiri Olsa if (!disasm_line__filter(&browser->b, &pos->al.node)) 581aca7a94dSNamhyung Kim ++*idx; 582aca7a94dSNamhyung Kim } 583aca7a94dSNamhyung Kim 584aca7a94dSNamhyung Kim return NULL; 585aca7a94dSNamhyung Kim } 586aca7a94dSNamhyung Kim 587aca7a94dSNamhyung Kim static bool annotate_browser__jump(struct annotate_browser *browser) 588aca7a94dSNamhyung Kim { 5897bcbcd58SJiri Olsa struct disasm_line *dl = disasm_line(browser->selection); 5905252b1aeSArnaldo Carvalho de Melo u64 offset; 5914f9d0325SArnaldo Carvalho de Melo s64 idx; 592aca7a94dSNamhyung Kim 59375b49202SArnaldo Carvalho de Melo if (!ins__is_jump(&dl->ins)) 594aca7a94dSNamhyung Kim return false; 595aca7a94dSNamhyung Kim 5965252b1aeSArnaldo Carvalho de Melo offset = dl->ops.target.offset; 5975252b1aeSArnaldo Carvalho de Melo dl = annotate_browser__find_offset(browser, offset, &idx); 59829ed6e76SArnaldo Carvalho de Melo if (dl == NULL) { 5995252b1aeSArnaldo Carvalho de Melo ui_helpline__printf("Invalid jump offset: %" PRIx64, offset); 600aca7a94dSNamhyung Kim return true; 601aca7a94dSNamhyung Kim } 602aca7a94dSNamhyung Kim 603*ec03a77dSJiri Olsa annotate_browser__set_top(browser, &dl->al, idx); 604aca7a94dSNamhyung Kim 605aca7a94dSNamhyung Kim return true; 606aca7a94dSNamhyung Kim } 607aca7a94dSNamhyung Kim 60829ed6e76SArnaldo Carvalho de Melo static 6099213afbdSJiri Olsa struct annotation_line *annotate_browser__find_string(struct annotate_browser *browser, 610aca7a94dSNamhyung Kim char *s, s64 *idx) 611aca7a94dSNamhyung Kim { 612aca7a94dSNamhyung Kim struct map_symbol *ms = browser->b.priv; 613aca7a94dSNamhyung Kim struct symbol *sym = ms->sym; 614aca7a94dSNamhyung Kim struct annotation *notes = symbol__annotation(sym); 6159213afbdSJiri Olsa struct annotation_line *al = browser->selection; 616aca7a94dSNamhyung Kim 617aca7a94dSNamhyung Kim *idx = browser->b.index; 6189213afbdSJiri Olsa list_for_each_entry_continue(al, ¬es->src->source, node) { 6199213afbdSJiri Olsa if (disasm_line__filter(&browser->b, &al->node)) 620aca7a94dSNamhyung Kim continue; 621aca7a94dSNamhyung Kim 622aca7a94dSNamhyung Kim ++*idx; 623aca7a94dSNamhyung Kim 6249213afbdSJiri Olsa if (al->line && strstr(al->line, s) != NULL) 6259213afbdSJiri Olsa return al; 626aca7a94dSNamhyung Kim } 627aca7a94dSNamhyung Kim 628aca7a94dSNamhyung Kim return NULL; 629aca7a94dSNamhyung Kim } 630aca7a94dSNamhyung Kim 631aca7a94dSNamhyung Kim static bool __annotate_browser__search(struct annotate_browser *browser) 632aca7a94dSNamhyung Kim { 6339213afbdSJiri Olsa struct annotation_line *al; 634aca7a94dSNamhyung Kim s64 idx; 635aca7a94dSNamhyung Kim 6369213afbdSJiri Olsa al = annotate_browser__find_string(browser, browser->search_bf, &idx); 6379213afbdSJiri Olsa if (al == NULL) { 638aca7a94dSNamhyung Kim ui_helpline__puts("String not found!"); 639aca7a94dSNamhyung Kim return false; 640aca7a94dSNamhyung Kim } 641aca7a94dSNamhyung Kim 642*ec03a77dSJiri Olsa annotate_browser__set_top(browser, al, idx); 643aca7a94dSNamhyung Kim browser->searching_backwards = false; 644aca7a94dSNamhyung Kim return true; 645aca7a94dSNamhyung Kim } 646aca7a94dSNamhyung Kim 64729ed6e76SArnaldo Carvalho de Melo static 6489213afbdSJiri Olsa struct annotation_line *annotate_browser__find_string_reverse(struct annotate_browser *browser, 649aca7a94dSNamhyung Kim char *s, s64 *idx) 650aca7a94dSNamhyung Kim { 651aca7a94dSNamhyung Kim struct map_symbol *ms = browser->b.priv; 652aca7a94dSNamhyung Kim struct symbol *sym = ms->sym; 653aca7a94dSNamhyung Kim struct annotation *notes = symbol__annotation(sym); 6549213afbdSJiri Olsa struct annotation_line *al = browser->selection; 655aca7a94dSNamhyung Kim 656aca7a94dSNamhyung Kim *idx = browser->b.index; 6579213afbdSJiri Olsa list_for_each_entry_continue_reverse(al, ¬es->src->source, node) { 6589213afbdSJiri Olsa if (disasm_line__filter(&browser->b, &al->node)) 659aca7a94dSNamhyung Kim continue; 660aca7a94dSNamhyung Kim 661aca7a94dSNamhyung Kim --*idx; 662aca7a94dSNamhyung Kim 6639213afbdSJiri Olsa if (al->line && strstr(al->line, s) != NULL) 6649213afbdSJiri Olsa return al; 665aca7a94dSNamhyung Kim } 666aca7a94dSNamhyung Kim 667aca7a94dSNamhyung Kim return NULL; 668aca7a94dSNamhyung Kim } 669aca7a94dSNamhyung Kim 670aca7a94dSNamhyung Kim static bool __annotate_browser__search_reverse(struct annotate_browser *browser) 671aca7a94dSNamhyung Kim { 6729213afbdSJiri Olsa struct annotation_line *al; 673aca7a94dSNamhyung Kim s64 idx; 674aca7a94dSNamhyung Kim 6759213afbdSJiri Olsa al = annotate_browser__find_string_reverse(browser, browser->search_bf, &idx); 6769213afbdSJiri Olsa if (al == NULL) { 677aca7a94dSNamhyung Kim ui_helpline__puts("String not found!"); 678aca7a94dSNamhyung Kim return false; 679aca7a94dSNamhyung Kim } 680aca7a94dSNamhyung Kim 681*ec03a77dSJiri Olsa annotate_browser__set_top(browser, al, idx); 682aca7a94dSNamhyung Kim browser->searching_backwards = true; 683aca7a94dSNamhyung Kim return true; 684aca7a94dSNamhyung Kim } 685aca7a94dSNamhyung Kim 686aca7a94dSNamhyung Kim static bool annotate_browser__search_window(struct annotate_browser *browser, 687aca7a94dSNamhyung Kim int delay_secs) 688aca7a94dSNamhyung Kim { 689aca7a94dSNamhyung Kim if (ui_browser__input_window("Search", "String: ", browser->search_bf, 690aca7a94dSNamhyung Kim "ENTER: OK, ESC: Cancel", 691aca7a94dSNamhyung Kim delay_secs * 2) != K_ENTER || 692aca7a94dSNamhyung Kim !*browser->search_bf) 693aca7a94dSNamhyung Kim return false; 694aca7a94dSNamhyung Kim 695aca7a94dSNamhyung Kim return true; 696aca7a94dSNamhyung Kim } 697aca7a94dSNamhyung Kim 698aca7a94dSNamhyung Kim static bool annotate_browser__search(struct annotate_browser *browser, int delay_secs) 699aca7a94dSNamhyung Kim { 700aca7a94dSNamhyung Kim if (annotate_browser__search_window(browser, delay_secs)) 701aca7a94dSNamhyung Kim return __annotate_browser__search(browser); 702aca7a94dSNamhyung Kim 703aca7a94dSNamhyung Kim return false; 704aca7a94dSNamhyung Kim } 705aca7a94dSNamhyung Kim 706aca7a94dSNamhyung Kim static bool annotate_browser__continue_search(struct annotate_browser *browser, 707aca7a94dSNamhyung Kim int delay_secs) 708aca7a94dSNamhyung Kim { 709aca7a94dSNamhyung Kim if (!*browser->search_bf) 710aca7a94dSNamhyung Kim return annotate_browser__search(browser, delay_secs); 711aca7a94dSNamhyung Kim 712aca7a94dSNamhyung Kim return __annotate_browser__search(browser); 713aca7a94dSNamhyung Kim } 714aca7a94dSNamhyung Kim 715aca7a94dSNamhyung Kim static bool annotate_browser__search_reverse(struct annotate_browser *browser, 716aca7a94dSNamhyung Kim int delay_secs) 717aca7a94dSNamhyung Kim { 718aca7a94dSNamhyung Kim if (annotate_browser__search_window(browser, delay_secs)) 719aca7a94dSNamhyung Kim return __annotate_browser__search_reverse(browser); 720aca7a94dSNamhyung Kim 721aca7a94dSNamhyung Kim return false; 722aca7a94dSNamhyung Kim } 723aca7a94dSNamhyung Kim 724aca7a94dSNamhyung Kim static 725aca7a94dSNamhyung Kim bool annotate_browser__continue_search_reverse(struct annotate_browser *browser, 726aca7a94dSNamhyung Kim int delay_secs) 727aca7a94dSNamhyung Kim { 728aca7a94dSNamhyung Kim if (!*browser->search_bf) 729aca7a94dSNamhyung Kim return annotate_browser__search_reverse(browser, delay_secs); 730aca7a94dSNamhyung Kim 731aca7a94dSNamhyung Kim return __annotate_browser__search_reverse(browser); 732aca7a94dSNamhyung Kim } 733aca7a94dSNamhyung Kim 734e9823b21SArnaldo Carvalho de Melo static void annotate_browser__update_addr_width(struct annotate_browser *browser) 735e9823b21SArnaldo Carvalho de Melo { 736e9823b21SArnaldo Carvalho de Melo if (annotate_browser__opts.use_offset) 737e9823b21SArnaldo Carvalho de Melo browser->target_width = browser->min_addr_width; 738e9823b21SArnaldo Carvalho de Melo else 739e9823b21SArnaldo Carvalho de Melo browser->target_width = browser->max_addr_width; 740e9823b21SArnaldo Carvalho de Melo 741e9823b21SArnaldo Carvalho de Melo browser->addr_width = browser->target_width; 742e9823b21SArnaldo Carvalho de Melo 743e9823b21SArnaldo Carvalho de Melo if (annotate_browser__opts.show_nr_jumps) 744e9823b21SArnaldo Carvalho de Melo browser->addr_width += browser->jumps_width + 1; 745e9823b21SArnaldo Carvalho de Melo } 746e9823b21SArnaldo Carvalho de Melo 747db8fd07aSNamhyung Kim static int annotate_browser__run(struct annotate_browser *browser, 748db8fd07aSNamhyung Kim struct perf_evsel *evsel, 7499783adf7SNamhyung Kim struct hist_browser_timer *hbt) 750aca7a94dSNamhyung Kim { 751aca7a94dSNamhyung Kim struct rb_node *nd = NULL; 75205e8b080SArnaldo Carvalho de Melo struct map_symbol *ms = browser->b.priv; 753aca7a94dSNamhyung Kim struct symbol *sym = ms->sym; 75454e7a4e8SArnaldo Carvalho de Melo const char *help = "Press 'h' for help on key bindings"; 7559783adf7SNamhyung Kim int delay_secs = hbt ? hbt->refresh : 0; 756aca7a94dSNamhyung Kim int key; 75734f77abcSAdrian Hunter char title[SYM_TITLE_MAX_SIZE]; 758aca7a94dSNamhyung Kim 75934f77abcSAdrian Hunter sym_title(sym, ms->map, title, sizeof(title)); 76034f77abcSAdrian Hunter if (ui_browser__show(&browser->b, title, help) < 0) 761aca7a94dSNamhyung Kim return -1; 762aca7a94dSNamhyung Kim 763db8fd07aSNamhyung Kim annotate_browser__calc_percent(browser, evsel); 764aca7a94dSNamhyung Kim 76505e8b080SArnaldo Carvalho de Melo if (browser->curr_hot) { 76605e8b080SArnaldo Carvalho de Melo annotate_browser__set_rb_top(browser, browser->curr_hot); 76705e8b080SArnaldo Carvalho de Melo browser->b.navkeypressed = false; 768aca7a94dSNamhyung Kim } 769aca7a94dSNamhyung Kim 77005e8b080SArnaldo Carvalho de Melo nd = browser->curr_hot; 771aca7a94dSNamhyung Kim 772aca7a94dSNamhyung Kim while (1) { 77305e8b080SArnaldo Carvalho de Melo key = ui_browser__run(&browser->b, delay_secs); 774aca7a94dSNamhyung Kim 775aca7a94dSNamhyung Kim if (delay_secs != 0) { 776db8fd07aSNamhyung Kim annotate_browser__calc_percent(browser, evsel); 777aca7a94dSNamhyung Kim /* 778aca7a94dSNamhyung Kim * Current line focus got out of the list of most active 779aca7a94dSNamhyung Kim * lines, NULL it so that if TAB|UNTAB is pressed, we 780aca7a94dSNamhyung Kim * move to curr_hot (current hottest line). 781aca7a94dSNamhyung Kim */ 782aca7a94dSNamhyung Kim if (nd != NULL && RB_EMPTY_NODE(nd)) 783aca7a94dSNamhyung Kim nd = NULL; 784aca7a94dSNamhyung Kim } 785aca7a94dSNamhyung Kim 786aca7a94dSNamhyung Kim switch (key) { 787aca7a94dSNamhyung Kim case K_TIMER: 7889783adf7SNamhyung Kim if (hbt) 7899783adf7SNamhyung Kim hbt->timer(hbt->arg); 790aca7a94dSNamhyung Kim 791aca7a94dSNamhyung Kim if (delay_secs != 0) 792db8fd07aSNamhyung Kim symbol__annotate_decay_histogram(sym, evsel->idx); 793aca7a94dSNamhyung Kim continue; 794aca7a94dSNamhyung Kim case K_TAB: 795aca7a94dSNamhyung Kim if (nd != NULL) { 796aca7a94dSNamhyung Kim nd = rb_prev(nd); 797aca7a94dSNamhyung Kim if (nd == NULL) 79805e8b080SArnaldo Carvalho de Melo nd = rb_last(&browser->entries); 799aca7a94dSNamhyung Kim } else 80005e8b080SArnaldo Carvalho de Melo nd = browser->curr_hot; 801aca7a94dSNamhyung Kim break; 802aca7a94dSNamhyung Kim case K_UNTAB: 803d4913cbdSMarkus Trippelsdorf if (nd != NULL) { 804aca7a94dSNamhyung Kim nd = rb_next(nd); 805aca7a94dSNamhyung Kim if (nd == NULL) 80605e8b080SArnaldo Carvalho de Melo nd = rb_first(&browser->entries); 807d4913cbdSMarkus Trippelsdorf } else 80805e8b080SArnaldo Carvalho de Melo nd = browser->curr_hot; 809aca7a94dSNamhyung Kim break; 81054e7a4e8SArnaldo Carvalho de Melo case K_F1: 811aca7a94dSNamhyung Kim case 'h': 81205e8b080SArnaldo Carvalho de Melo ui_browser__help_window(&browser->b, 81354e7a4e8SArnaldo Carvalho de Melo "UP/DOWN/PGUP\n" 81454e7a4e8SArnaldo Carvalho de Melo "PGDN/SPACE Navigate\n" 81554e7a4e8SArnaldo Carvalho de Melo "q/ESC/CTRL+C Exit\n\n" 8167727a925SArnaldo Carvalho de Melo "ENTER Go to target\n" 8177727a925SArnaldo Carvalho de Melo "ESC Exit\n" 818eba9fac0SArnaldo Carvalho de Melo "H Go to hottest instruction\n" 819eba9fac0SArnaldo Carvalho de Melo "TAB/shift+TAB Cycle thru hottest instructions\n" 82054e7a4e8SArnaldo Carvalho de Melo "j Toggle showing jump to target arrows\n" 82154e7a4e8SArnaldo Carvalho de Melo "J Toggle showing number of jump sources on targets\n" 82254e7a4e8SArnaldo Carvalho de Melo "n Search next string\n" 82354e7a4e8SArnaldo Carvalho de Melo "o Toggle disassembler output/simplified view\n" 82454e7a4e8SArnaldo Carvalho de Melo "s Toggle source code view\n" 8253a555c77STaeung Song "t Circulate percent, total period, samples view\n" 82654e7a4e8SArnaldo Carvalho de Melo "/ Search string\n" 827e592488cSAndi Kleen "k Toggle line numbers\n" 82879ee47faSFeng Tang "r Run available scripts\n" 829fcd9fef9SArnaldo Carvalho de Melo "? Search string backwards\n"); 83054e7a4e8SArnaldo Carvalho de Melo continue; 83179ee47faSFeng Tang case 'r': 83279ee47faSFeng Tang { 83379ee47faSFeng Tang script_browse(NULL); 83479ee47faSFeng Tang continue; 83579ee47faSFeng Tang } 836e592488cSAndi Kleen case 'k': 837e592488cSAndi Kleen annotate_browser__opts.show_linenr = 838e592488cSAndi Kleen !annotate_browser__opts.show_linenr; 839e592488cSAndi Kleen break; 84054e7a4e8SArnaldo Carvalho de Melo case 'H': 84105e8b080SArnaldo Carvalho de Melo nd = browser->curr_hot; 842aca7a94dSNamhyung Kim break; 843aca7a94dSNamhyung Kim case 's': 84405e8b080SArnaldo Carvalho de Melo if (annotate_browser__toggle_source(browser)) 845aca7a94dSNamhyung Kim ui_helpline__puts(help); 846aca7a94dSNamhyung Kim continue; 847aca7a94dSNamhyung Kim case 'o': 848e9823b21SArnaldo Carvalho de Melo annotate_browser__opts.use_offset = !annotate_browser__opts.use_offset; 84905e8b080SArnaldo Carvalho de Melo annotate_browser__update_addr_width(browser); 850aca7a94dSNamhyung Kim continue; 8519d1ef56dSArnaldo Carvalho de Melo case 'j': 852e9823b21SArnaldo Carvalho de Melo annotate_browser__opts.jump_arrows = !annotate_browser__opts.jump_arrows; 8539d1ef56dSArnaldo Carvalho de Melo continue; 8542402e4a9SArnaldo Carvalho de Melo case 'J': 855e9823b21SArnaldo Carvalho de Melo annotate_browser__opts.show_nr_jumps = !annotate_browser__opts.show_nr_jumps; 85605e8b080SArnaldo Carvalho de Melo annotate_browser__update_addr_width(browser); 857e9823b21SArnaldo Carvalho de Melo continue; 858aca7a94dSNamhyung Kim case '/': 85905e8b080SArnaldo Carvalho de Melo if (annotate_browser__search(browser, delay_secs)) { 860aca7a94dSNamhyung Kim show_help: 861aca7a94dSNamhyung Kim ui_helpline__puts(help); 862aca7a94dSNamhyung Kim } 863aca7a94dSNamhyung Kim continue; 864aca7a94dSNamhyung Kim case 'n': 86505e8b080SArnaldo Carvalho de Melo if (browser->searching_backwards ? 86605e8b080SArnaldo Carvalho de Melo annotate_browser__continue_search_reverse(browser, delay_secs) : 86705e8b080SArnaldo Carvalho de Melo annotate_browser__continue_search(browser, delay_secs)) 868aca7a94dSNamhyung Kim goto show_help; 869aca7a94dSNamhyung Kim continue; 870aca7a94dSNamhyung Kim case '?': 87105e8b080SArnaldo Carvalho de Melo if (annotate_browser__search_reverse(browser, delay_secs)) 872aca7a94dSNamhyung Kim goto show_help; 873aca7a94dSNamhyung Kim continue; 874e9823b21SArnaldo Carvalho de Melo case 'D': { 875e9823b21SArnaldo Carvalho de Melo static int seq; 876e9823b21SArnaldo Carvalho de Melo ui_helpline__pop(); 877e9823b21SArnaldo Carvalho de Melo ui_helpline__fpush("%d: nr_ent=%d, height=%d, idx=%d, top_idx=%d, nr_asm_entries=%d", 87805e8b080SArnaldo Carvalho de Melo seq++, browser->b.nr_entries, 87905e8b080SArnaldo Carvalho de Melo browser->b.height, 88005e8b080SArnaldo Carvalho de Melo browser->b.index, 88105e8b080SArnaldo Carvalho de Melo browser->b.top_idx, 88205e8b080SArnaldo Carvalho de Melo browser->nr_asm_entries); 883e9823b21SArnaldo Carvalho de Melo } 884e9823b21SArnaldo Carvalho de Melo continue; 885aca7a94dSNamhyung Kim case K_ENTER: 886aca7a94dSNamhyung Kim case K_RIGHT: 8877bcbcd58SJiri Olsa { 8887bcbcd58SJiri Olsa struct disasm_line *dl = disasm_line(browser->selection); 8897bcbcd58SJiri Olsa 89005e8b080SArnaldo Carvalho de Melo if (browser->selection == NULL) 891aca7a94dSNamhyung Kim ui_helpline__puts("Huh? No selection. Report to linux-kernel@vger.kernel.org"); 8927bcbcd58SJiri Olsa else if (browser->selection->offset == -1) 893aca7a94dSNamhyung Kim ui_helpline__puts("Actions are only available for assembly lines."); 8947bcbcd58SJiri Olsa else if (!dl->ins.ops) 895c4cceae3SArnaldo Carvalho de Melo goto show_sup_ins; 8967bcbcd58SJiri Olsa else if (ins__is_ret(&dl->ins)) 897c4cceae3SArnaldo Carvalho de Melo goto out; 8986ef94929SNaveen N. Rao else if (!(annotate_browser__jump(browser) || 899db8fd07aSNamhyung Kim annotate_browser__callq(browser, evsel, hbt))) { 900c4cceae3SArnaldo Carvalho de Melo show_sup_ins: 9016ef94929SNaveen N. Rao ui_helpline__puts("Actions are only available for function call/return & jump/branch instructions."); 902c4cceae3SArnaldo Carvalho de Melo } 903aca7a94dSNamhyung Kim continue; 9047bcbcd58SJiri Olsa } 9050c4a5bceSMartin Liška case 't': 9063a555c77STaeung Song if (annotate_browser__opts.show_total_period) { 9073a555c77STaeung Song annotate_browser__opts.show_total_period = false; 9083a555c77STaeung Song annotate_browser__opts.show_nr_samples = true; 9093a555c77STaeung Song } else if (annotate_browser__opts.show_nr_samples) 9103a555c77STaeung Song annotate_browser__opts.show_nr_samples = false; 9113a555c77STaeung Song else 9123a555c77STaeung Song annotate_browser__opts.show_total_period = true; 9130c4a5bceSMartin Liška annotate_browser__update_addr_width(browser); 9140c4a5bceSMartin Liška continue; 915aca7a94dSNamhyung Kim case K_LEFT: 916aca7a94dSNamhyung Kim case K_ESC: 917aca7a94dSNamhyung Kim case 'q': 918aca7a94dSNamhyung Kim case CTRL('c'): 919aca7a94dSNamhyung Kim goto out; 920aca7a94dSNamhyung Kim default: 921aca7a94dSNamhyung Kim continue; 922aca7a94dSNamhyung Kim } 923aca7a94dSNamhyung Kim 924aca7a94dSNamhyung Kim if (nd != NULL) 92505e8b080SArnaldo Carvalho de Melo annotate_browser__set_rb_top(browser, nd); 926aca7a94dSNamhyung Kim } 927aca7a94dSNamhyung Kim out: 92805e8b080SArnaldo Carvalho de Melo ui_browser__hide(&browser->b); 929aca7a94dSNamhyung Kim return key; 930aca7a94dSNamhyung Kim } 931aca7a94dSNamhyung Kim 932d5dbc518SArnaldo Carvalho de Melo int map_symbol__tui_annotate(struct map_symbol *ms, struct perf_evsel *evsel, 933d5dbc518SArnaldo Carvalho de Melo struct hist_browser_timer *hbt) 934d5dbc518SArnaldo Carvalho de Melo { 9359cef4b0bSTaeung Song /* Set default value for show_total_period and show_nr_samples */ 9360c4a5bceSMartin Liška annotate_browser__opts.show_total_period = 9370c4a5bceSMartin Liška symbol_conf.show_total_period; 9389cef4b0bSTaeung Song annotate_browser__opts.show_nr_samples = 9399cef4b0bSTaeung Song symbol_conf.show_nr_samples; 9400c4a5bceSMartin Liška 941d5dbc518SArnaldo Carvalho de Melo return symbol__tui_annotate(ms->sym, ms->map, evsel, hbt); 942d5dbc518SArnaldo Carvalho de Melo } 943d5dbc518SArnaldo Carvalho de Melo 944db8fd07aSNamhyung Kim int hist_entry__tui_annotate(struct hist_entry *he, struct perf_evsel *evsel, 9459783adf7SNamhyung Kim struct hist_browser_timer *hbt) 946aca7a94dSNamhyung Kim { 947ed426915SNamhyung Kim /* reset abort key so that it can get Ctrl-C as a key */ 948ed426915SNamhyung Kim SLang_reset_tty(); 949ed426915SNamhyung Kim SLang_init_tty(0, 0, 0); 950ed426915SNamhyung Kim 951d5dbc518SArnaldo Carvalho de Melo return map_symbol__tui_annotate(&he->ms, evsel, hbt); 952aca7a94dSNamhyung Kim } 953aca7a94dSNamhyung Kim 95430e863bbSAndi Kleen 95530e863bbSAndi Kleen static unsigned count_insn(struct annotate_browser *browser, u64 start, u64 end) 95630e863bbSAndi Kleen { 95730e863bbSAndi Kleen unsigned n_insn = 0; 95830e863bbSAndi Kleen u64 offset; 95930e863bbSAndi Kleen 96030e863bbSAndi Kleen for (offset = start; offset <= end; offset++) { 96130e863bbSAndi Kleen if (browser->offsets[offset]) 96230e863bbSAndi Kleen n_insn++; 96330e863bbSAndi Kleen } 96430e863bbSAndi Kleen return n_insn; 96530e863bbSAndi Kleen } 96630e863bbSAndi Kleen 96730e863bbSAndi Kleen static void count_and_fill(struct annotate_browser *browser, u64 start, u64 end, 96830e863bbSAndi Kleen struct cyc_hist *ch) 96930e863bbSAndi Kleen { 97030e863bbSAndi Kleen unsigned n_insn; 97130e863bbSAndi Kleen u64 offset; 97230e863bbSAndi Kleen 97330e863bbSAndi Kleen n_insn = count_insn(browser, start, end); 97430e863bbSAndi Kleen if (n_insn && ch->num && ch->cycles) { 97530e863bbSAndi Kleen float ipc = n_insn / ((double)ch->cycles / (double)ch->num); 97630e863bbSAndi Kleen 97730e863bbSAndi Kleen /* Hide data when there are too many overlaps. */ 97830e863bbSAndi Kleen if (ch->reset >= 0x7fff || ch->reset >= ch->num / 2) 97930e863bbSAndi Kleen return; 98030e863bbSAndi Kleen 98130e863bbSAndi Kleen for (offset = start; offset <= end; offset++) { 982e1b60b5bSJiri Olsa struct annotation_line *al = browser->offsets[offset]; 98330e863bbSAndi Kleen 984e1b60b5bSJiri Olsa if (al) 985e1b60b5bSJiri Olsa al->ipc = ipc; 98630e863bbSAndi Kleen } 98730e863bbSAndi Kleen } 98830e863bbSAndi Kleen } 98930e863bbSAndi Kleen 99030e863bbSAndi Kleen /* 99130e863bbSAndi Kleen * This should probably be in util/annotate.c to share with the tty 99230e863bbSAndi Kleen * annotate, but right now we need the per byte offsets arrays, 99330e863bbSAndi Kleen * which are only here. 99430e863bbSAndi Kleen */ 99530e863bbSAndi Kleen static void annotate__compute_ipc(struct annotate_browser *browser, size_t size, 99630e863bbSAndi Kleen struct symbol *sym) 99730e863bbSAndi Kleen { 99830e863bbSAndi Kleen u64 offset; 99930e863bbSAndi Kleen struct annotation *notes = symbol__annotation(sym); 100030e863bbSAndi Kleen 100130e863bbSAndi Kleen if (!notes->src || !notes->src->cycles_hist) 100230e863bbSAndi Kleen return; 100330e863bbSAndi Kleen 100430e863bbSAndi Kleen pthread_mutex_lock(¬es->lock); 100530e863bbSAndi Kleen for (offset = 0; offset < size; ++offset) { 100630e863bbSAndi Kleen struct cyc_hist *ch; 100730e863bbSAndi Kleen 100830e863bbSAndi Kleen ch = ¬es->src->cycles_hist[offset]; 100930e863bbSAndi Kleen if (ch && ch->cycles) { 1010e1b60b5bSJiri Olsa struct annotation_line *al; 101130e863bbSAndi Kleen 101230e863bbSAndi Kleen if (ch->have_start) 101330e863bbSAndi Kleen count_and_fill(browser, ch->start, offset, ch); 1014e1b60b5bSJiri Olsa al = browser->offsets[offset]; 1015e1b60b5bSJiri Olsa if (al && ch->num_aggr) 1016e1b60b5bSJiri Olsa al->cycles = ch->cycles_aggr / ch->num_aggr; 101730e863bbSAndi Kleen browser->have_cycles = true; 101830e863bbSAndi Kleen } 101930e863bbSAndi Kleen } 102030e863bbSAndi Kleen pthread_mutex_unlock(¬es->lock); 102130e863bbSAndi Kleen } 102230e863bbSAndi Kleen 1023b793a401SArnaldo Carvalho de Melo static void annotate_browser__mark_jump_targets(struct annotate_browser *browser, 1024b793a401SArnaldo Carvalho de Melo size_t size) 1025b793a401SArnaldo Carvalho de Melo { 1026b793a401SArnaldo Carvalho de Melo u64 offset; 102732ae1efdSNamhyung Kim struct map_symbol *ms = browser->b.priv; 102832ae1efdSNamhyung Kim struct symbol *sym = ms->sym; 102932ae1efdSNamhyung Kim 103032ae1efdSNamhyung Kim /* PLT symbols contain external offsets */ 103132ae1efdSNamhyung Kim if (strstr(sym->name, "@plt")) 103232ae1efdSNamhyung Kim return; 1033b793a401SArnaldo Carvalho de Melo 1034b793a401SArnaldo Carvalho de Melo for (offset = 0; offset < size; ++offset) { 1035e1b60b5bSJiri Olsa struct annotation_line *al = browser->offsets[offset]; 1036a5ef2702SJiri Olsa struct disasm_line *dl; 1037a5ef2702SJiri Olsa struct browser_line *blt; 1038b793a401SArnaldo Carvalho de Melo 1039e1b60b5bSJiri Olsa dl = disasm_line(al); 1040e1b60b5bSJiri Olsa 1041865c66c4SFrederik Deweerdt if (!disasm_line__is_valid_jump(dl, sym)) 1042b793a401SArnaldo Carvalho de Melo continue; 1043b793a401SArnaldo Carvalho de Melo 1044e1b60b5bSJiri Olsa al = browser->offsets[dl->ops.target.offset]; 1045e1b60b5bSJiri Olsa 10469481ede9SArnaldo Carvalho de Melo /* 10479481ede9SArnaldo Carvalho de Melo * FIXME: Oops, no jump target? Buggy disassembler? Or do we 10489481ede9SArnaldo Carvalho de Melo * have to adjust to the previous offset? 10499481ede9SArnaldo Carvalho de Melo */ 1050a5ef2702SJiri Olsa if (al == NULL) 10519481ede9SArnaldo Carvalho de Melo continue; 10529481ede9SArnaldo Carvalho de Melo 1053a5ef2702SJiri Olsa blt = browser_line(al); 1054a5ef2702SJiri Olsa if (++blt->jump_sources > browser->max_jump_sources) 1055a5ef2702SJiri Olsa browser->max_jump_sources = blt->jump_sources; 10562402e4a9SArnaldo Carvalho de Melo 10572402e4a9SArnaldo Carvalho de Melo ++browser->nr_jumps; 1058b793a401SArnaldo Carvalho de Melo } 1059b793a401SArnaldo Carvalho de Melo } 1060b793a401SArnaldo Carvalho de Melo 10612402e4a9SArnaldo Carvalho de Melo static inline int width_jumps(int n) 10622402e4a9SArnaldo Carvalho de Melo { 10632402e4a9SArnaldo Carvalho de Melo if (n >= 100) 10642402e4a9SArnaldo Carvalho de Melo return 5; 10652402e4a9SArnaldo Carvalho de Melo if (n / 10) 10662402e4a9SArnaldo Carvalho de Melo return 2; 10672402e4a9SArnaldo Carvalho de Melo return 1; 10682402e4a9SArnaldo Carvalho de Melo } 10692402e4a9SArnaldo Carvalho de Melo 1070db8fd07aSNamhyung Kim int symbol__tui_annotate(struct symbol *sym, struct map *map, 1071db8fd07aSNamhyung Kim struct perf_evsel *evsel, 10729783adf7SNamhyung Kim struct hist_browser_timer *hbt) 1073aca7a94dSNamhyung Kim { 1074e1b60b5bSJiri Olsa struct annotation_line *al; 1075aca7a94dSNamhyung Kim struct annotation *notes; 1076c0a58fb2SSamuel Liao size_t size; 1077aca7a94dSNamhyung Kim struct map_symbol ms = { 1078aca7a94dSNamhyung Kim .map = map, 1079aca7a94dSNamhyung Kim .sym = sym, 1080aca7a94dSNamhyung Kim }; 1081aca7a94dSNamhyung Kim struct annotate_browser browser = { 1082aca7a94dSNamhyung Kim .b = { 1083a3f895beSArnaldo Carvalho de Melo .refresh = annotate_browser__refresh, 1084aca7a94dSNamhyung Kim .seek = ui_browser__list_head_seek, 1085aca7a94dSNamhyung Kim .write = annotate_browser__write, 108629ed6e76SArnaldo Carvalho de Melo .filter = disasm_line__filter, 1087aca7a94dSNamhyung Kim .priv = &ms, 1088aca7a94dSNamhyung Kim .use_navkeypressed = true, 1089aca7a94dSNamhyung Kim }, 1090aca7a94dSNamhyung Kim }; 1091ee51d851SArnaldo Carvalho de Melo int ret = -1, err; 1092c7e7b610SNamhyung Kim int nr_pcnt = 1; 1093aca7a94dSNamhyung Kim 1094aca7a94dSNamhyung Kim if (sym == NULL) 1095aca7a94dSNamhyung Kim return -1; 1096aca7a94dSNamhyung Kim 1097c0a58fb2SSamuel Liao size = symbol__size(sym); 1098c0a58fb2SSamuel Liao 1099aca7a94dSNamhyung Kim if (map->dso->annotate_warned) 1100aca7a94dSNamhyung Kim return -1; 1101aca7a94dSNamhyung Kim 1102e1b60b5bSJiri Olsa browser.offsets = zalloc(size * sizeof(struct annotation_line *)); 1103b793a401SArnaldo Carvalho de Melo if (browser.offsets == NULL) { 1104b793a401SArnaldo Carvalho de Melo ui__error("Not enough memory!"); 1105b793a401SArnaldo Carvalho de Melo return -1; 1106b793a401SArnaldo Carvalho de Melo } 1107b793a401SArnaldo Carvalho de Melo 11083ab6db8dSJiri Olsa if (perf_evsel__is_group_event(evsel)) 1109c7e7b610SNamhyung Kim nr_pcnt = evsel->nr_members; 1110c7e7b610SNamhyung Kim 1111d03a686eSJiri Olsa err = symbol__annotate(sym, map, evsel, 11120d957970SJiri Olsa sizeof(struct browser_line), &browser.arch, 111369fb09f6SJin Yao perf_evsel__env_cpuid(evsel)); 1114ee51d851SArnaldo Carvalho de Melo if (err) { 1115ee51d851SArnaldo Carvalho de Melo char msg[BUFSIZ]; 1116ee51d851SArnaldo Carvalho de Melo symbol__strerror_disassemble(sym, map, err, msg, sizeof(msg)); 1117ee51d851SArnaldo Carvalho de Melo ui__error("Couldn't annotate %s:\n%s", sym->name, msg); 1118b793a401SArnaldo Carvalho de Melo goto out_free_offsets; 1119aca7a94dSNamhyung Kim } 1120aca7a94dSNamhyung Kim 11217727a925SArnaldo Carvalho de Melo ui_helpline__push("Press ESC to exit"); 1122aca7a94dSNamhyung Kim 1123aca7a94dSNamhyung Kim notes = symbol__annotation(sym); 1124aca7a94dSNamhyung Kim browser.start = map__rip_2objdump(map, sym->start); 1125aca7a94dSNamhyung Kim 1126e1b60b5bSJiri Olsa list_for_each_entry(al, ¬es->src->source, node) { 11270d957970SJiri Olsa struct browser_line *bpos; 1128e1b60b5bSJiri Olsa size_t line_len = strlen(al->line); 1129aca7a94dSNamhyung Kim 1130aca7a94dSNamhyung Kim if (browser.b.width < line_len) 1131aca7a94dSNamhyung Kim browser.b.width = line_len; 1132a5ef2702SJiri Olsa bpos = browser_line(al); 1133887c0066SArnaldo Carvalho de Melo bpos->idx = browser.nr_entries++; 1134e1b60b5bSJiri Olsa if (al->offset != -1) { 1135887c0066SArnaldo Carvalho de Melo bpos->idx_asm = browser.nr_asm_entries++; 113697148a97SArnaldo Carvalho de Melo /* 113797148a97SArnaldo Carvalho de Melo * FIXME: short term bandaid to cope with assembly 113897148a97SArnaldo Carvalho de Melo * routines that comes with labels in the same column 113997148a97SArnaldo Carvalho de Melo * as the address in objdump, sigh. 114097148a97SArnaldo Carvalho de Melo * 114197148a97SArnaldo Carvalho de Melo * E.g. copy_user_generic_unrolled 114297148a97SArnaldo Carvalho de Melo */ 1143e1b60b5bSJiri Olsa if (al->offset < (s64)size) 1144e1b60b5bSJiri Olsa browser.offsets[al->offset] = al; 1145b793a401SArnaldo Carvalho de Melo } else 1146887c0066SArnaldo Carvalho de Melo bpos->idx_asm = -1; 1147aca7a94dSNamhyung Kim } 1148aca7a94dSNamhyung Kim 1149b793a401SArnaldo Carvalho de Melo annotate_browser__mark_jump_targets(&browser, size); 115030e863bbSAndi Kleen annotate__compute_ipc(&browser, size, sym); 1151b793a401SArnaldo Carvalho de Melo 11522402e4a9SArnaldo Carvalho de Melo browser.addr_width = browser.target_width = browser.min_addr_width = hex_width(size); 115383b1f2aaSArnaldo Carvalho de Melo browser.max_addr_width = hex_width(sym->end); 11542402e4a9SArnaldo Carvalho de Melo browser.jumps_width = width_jumps(browser.max_jump_sources); 1155c7e7b610SNamhyung Kim browser.nr_events = nr_pcnt; 1156aca7a94dSNamhyung Kim browser.b.nr_entries = browser.nr_entries; 1157aca7a94dSNamhyung Kim browser.b.entries = ¬es->src->source, 1158aca7a94dSNamhyung Kim browser.b.width += 18; /* Percentage */ 1159e9823b21SArnaldo Carvalho de Melo 1160e9823b21SArnaldo Carvalho de Melo if (annotate_browser__opts.hide_src_code) 1161e9823b21SArnaldo Carvalho de Melo annotate_browser__init_asm_mode(&browser); 1162e9823b21SArnaldo Carvalho de Melo 1163e9823b21SArnaldo Carvalho de Melo annotate_browser__update_addr_width(&browser); 1164e9823b21SArnaldo Carvalho de Melo 1165db8fd07aSNamhyung Kim ret = annotate_browser__run(&browser, evsel, hbt); 1166f8eb37bdSJiri Olsa 1167f8eb37bdSJiri Olsa annotated_source__purge(notes->src); 1168b793a401SArnaldo Carvalho de Melo 1169b793a401SArnaldo Carvalho de Melo out_free_offsets: 1170b793a401SArnaldo Carvalho de Melo free(browser.offsets); 1171aca7a94dSNamhyung Kim return ret; 1172aca7a94dSNamhyung Kim } 1173c323cf04SArnaldo Carvalho de Melo 1174c323cf04SArnaldo Carvalho de Melo #define ANNOTATE_CFG(n) \ 1175c323cf04SArnaldo Carvalho de Melo { .name = #n, .value = &annotate_browser__opts.n, } 1176c323cf04SArnaldo Carvalho de Melo 1177c323cf04SArnaldo Carvalho de Melo /* 1178c323cf04SArnaldo Carvalho de Melo * Keep the entries sorted, they are bsearch'ed 1179c323cf04SArnaldo Carvalho de Melo */ 11807c3102b8SArnaldo Carvalho de Melo static struct annotate_config { 1181c323cf04SArnaldo Carvalho de Melo const char *name; 1182c323cf04SArnaldo Carvalho de Melo bool *value; 1183c323cf04SArnaldo Carvalho de Melo } annotate__configs[] = { 1184c323cf04SArnaldo Carvalho de Melo ANNOTATE_CFG(hide_src_code), 1185c323cf04SArnaldo Carvalho de Melo ANNOTATE_CFG(jump_arrows), 1186e592488cSAndi Kleen ANNOTATE_CFG(show_linenr), 1187c323cf04SArnaldo Carvalho de Melo ANNOTATE_CFG(show_nr_jumps), 11889cef4b0bSTaeung Song ANNOTATE_CFG(show_nr_samples), 11890c4a5bceSMartin Liška ANNOTATE_CFG(show_total_period), 119039ff7cdbSNamhyung Kim ANNOTATE_CFG(use_offset), 1191c323cf04SArnaldo Carvalho de Melo }; 1192c323cf04SArnaldo Carvalho de Melo 1193c323cf04SArnaldo Carvalho de Melo #undef ANNOTATE_CFG 1194c323cf04SArnaldo Carvalho de Melo 1195c323cf04SArnaldo Carvalho de Melo static int annotate_config__cmp(const void *name, const void *cfgp) 1196c323cf04SArnaldo Carvalho de Melo { 11977c3102b8SArnaldo Carvalho de Melo const struct annotate_config *cfg = cfgp; 1198c323cf04SArnaldo Carvalho de Melo 1199c323cf04SArnaldo Carvalho de Melo return strcmp(name, cfg->name); 1200c323cf04SArnaldo Carvalho de Melo } 1201c323cf04SArnaldo Carvalho de Melo 12021d037ca1SIrina Tirdea static int annotate__config(const char *var, const char *value, 12031d037ca1SIrina Tirdea void *data __maybe_unused) 1204c323cf04SArnaldo Carvalho de Melo { 12057c3102b8SArnaldo Carvalho de Melo struct annotate_config *cfg; 1206c323cf04SArnaldo Carvalho de Melo const char *name; 1207c323cf04SArnaldo Carvalho de Melo 12088e99b6d4SArnaldo Carvalho de Melo if (!strstarts(var, "annotate.")) 1209c323cf04SArnaldo Carvalho de Melo return 0; 1210c323cf04SArnaldo Carvalho de Melo 1211c323cf04SArnaldo Carvalho de Melo name = var + 9; 1212c323cf04SArnaldo Carvalho de Melo cfg = bsearch(name, annotate__configs, ARRAY_SIZE(annotate__configs), 12137c3102b8SArnaldo Carvalho de Melo sizeof(struct annotate_config), annotate_config__cmp); 1214c323cf04SArnaldo Carvalho de Melo 1215c323cf04SArnaldo Carvalho de Melo if (cfg == NULL) 1216f06cff7cSArnaldo Carvalho de Melo ui__warning("%s variable unknown, ignoring...", var); 1217f06cff7cSArnaldo Carvalho de Melo else 1218c323cf04SArnaldo Carvalho de Melo *cfg->value = perf_config_bool(name, value); 1219c323cf04SArnaldo Carvalho de Melo return 0; 1220c323cf04SArnaldo Carvalho de Melo } 1221c323cf04SArnaldo Carvalho de Melo 1222c323cf04SArnaldo Carvalho de Melo void annotate_browser__init(void) 1223c323cf04SArnaldo Carvalho de Melo { 1224c323cf04SArnaldo Carvalho de Melo perf_config(annotate__config, NULL); 1225c323cf04SArnaldo Carvalho de Melo } 1226