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 250d957970SJiri Olsa struct browser_line { 26b793a401SArnaldo Carvalho de Melo u32 idx; 27b793a401SArnaldo Carvalho de Melo int idx_asm; 287d5b12f5SArnaldo Carvalho de Melo int jump_sources; 29b793a401SArnaldo Carvalho de Melo }; 30b793a401SArnaldo Carvalho de Melo 3198bc80b0SArnaldo Carvalho de Melo static struct annotation_options annotate_browser__opts = { 32e9823b21SArnaldo Carvalho de Melo .use_offset = true, 33e9823b21SArnaldo Carvalho de Melo .jump_arrows = true, 34e9823b21SArnaldo Carvalho de Melo }; 35e9823b21SArnaldo Carvalho de Melo 36dcaa3948SJin Yao struct arch; 37dcaa3948SJin Yao 38aca7a94dSNamhyung Kim struct annotate_browser { 39aca7a94dSNamhyung Kim struct ui_browser b; 40aca7a94dSNamhyung Kim struct rb_root entries; 41aca7a94dSNamhyung Kim struct rb_node *curr_hot; 427bcbcd58SJiri Olsa struct annotation_line *selection; 43dcaa3948SJin Yao struct arch *arch; 44aca7a94dSNamhyung Kim u64 start; 45aca7a94dSNamhyung Kim int nr_asm_entries; 46aca7a94dSNamhyung Kim int nr_entries; 472402e4a9SArnaldo Carvalho de Melo int max_jump_sources; 482402e4a9SArnaldo Carvalho de Melo int nr_jumps; 49aca7a94dSNamhyung Kim bool searching_backwards; 5083b1f2aaSArnaldo Carvalho de Melo u8 addr_width; 512402e4a9SArnaldo Carvalho de Melo u8 jumps_width; 522402e4a9SArnaldo Carvalho de Melo u8 target_width; 5383b1f2aaSArnaldo Carvalho de Melo u8 min_addr_width; 5483b1f2aaSArnaldo Carvalho de Melo u8 max_addr_width; 55aca7a94dSNamhyung Kim char search_bf[128]; 56aca7a94dSNamhyung Kim }; 57aca7a94dSNamhyung Kim 58a5ef2702SJiri Olsa static inline struct browser_line *browser_line(struct annotation_line *al) 59aca7a94dSNamhyung Kim { 60a5ef2702SJiri Olsa void *ptr = al; 61a5ef2702SJiri Olsa 62a5ef2702SJiri Olsa ptr = container_of(al, struct disasm_line, al); 63a5ef2702SJiri Olsa return ptr - sizeof(struct browser_line); 64aca7a94dSNamhyung Kim } 65aca7a94dSNamhyung Kim 66*16932d77SArnaldo Carvalho de Melo static bool disasm_line__filter(struct ui_browser *browser, void *entry) 67aca7a94dSNamhyung Kim { 68*16932d77SArnaldo Carvalho de Melo struct map_symbol *ms = browser->priv; 69*16932d77SArnaldo Carvalho de Melo struct annotation *notes = symbol__annotation(ms->sym); 70*16932d77SArnaldo Carvalho de Melo 71*16932d77SArnaldo Carvalho de Melo if (notes->options->hide_src_code) { 72d5490b96SJiri Olsa struct annotation_line *al = list_entry(entry, struct annotation_line, node); 73d5490b96SJiri Olsa 74d5490b96SJiri Olsa return al->offset == -1; 75aca7a94dSNamhyung Kim } 76aca7a94dSNamhyung Kim 77aca7a94dSNamhyung Kim return false; 78aca7a94dSNamhyung Kim } 79aca7a94dSNamhyung Kim 802402e4a9SArnaldo Carvalho de Melo static int annotate_browser__jumps_percent_color(struct annotate_browser *browser, 812402e4a9SArnaldo Carvalho de Melo int nr, bool current) 822402e4a9SArnaldo Carvalho de Melo { 832402e4a9SArnaldo Carvalho de Melo if (current && (!browser->b.use_navkeypressed || browser->b.navkeypressed)) 842402e4a9SArnaldo Carvalho de Melo return HE_COLORSET_SELECTED; 852402e4a9SArnaldo Carvalho de Melo if (nr == browser->max_jump_sources) 862402e4a9SArnaldo Carvalho de Melo return HE_COLORSET_TOP; 872402e4a9SArnaldo Carvalho de Melo if (nr > 1) 882402e4a9SArnaldo Carvalho de Melo return HE_COLORSET_MEDIUM; 892402e4a9SArnaldo Carvalho de Melo return HE_COLORSET_NORMAL; 902402e4a9SArnaldo Carvalho de Melo } 912402e4a9SArnaldo Carvalho de Melo 922402e4a9SArnaldo Carvalho de Melo static int annotate_browser__set_jumps_percent_color(struct annotate_browser *browser, 932402e4a9SArnaldo Carvalho de Melo int nr, bool current) 942402e4a9SArnaldo Carvalho de Melo { 952402e4a9SArnaldo Carvalho de Melo int color = annotate_browser__jumps_percent_color(browser, nr, current); 962402e4a9SArnaldo Carvalho de Melo return ui_browser__set_color(&browser->b, color); 972402e4a9SArnaldo Carvalho de Melo } 982402e4a9SArnaldo Carvalho de Melo 99f8f4aaeaSAndi Kleen static int annotate_browser__pcnt_width(struct annotate_browser *ab) 100f8f4aaeaSAndi Kleen { 1010553e83dSArnaldo Carvalho de Melo struct map_symbol *ms = ab->b.priv; 1020553e83dSArnaldo Carvalho de Melo struct annotation *notes = symbol__annotation(ms->sym); 103*16932d77SArnaldo Carvalho de Melo return (notes->options->show_total_period ? 12 : 7) * notes->nr_events; 104bc1e5d60SArnaldo Carvalho de Melo } 105f8f4aaeaSAndi Kleen 106a5433b3eSJiri Olsa static void disasm_line__write(struct disasm_line *dl, struct ui_browser *browser, 107a5433b3eSJiri Olsa char *bf, size_t size) 108aca7a94dSNamhyung Kim { 109*16932d77SArnaldo Carvalho de Melo struct map_symbol *ms = browser->priv; 110*16932d77SArnaldo Carvalho de Melo struct annotation *notes = symbol__annotation(ms->sym); 111*16932d77SArnaldo Carvalho de Melo 11275b49202SArnaldo Carvalho de Melo if (dl->ins.ops && dl->ins.ops->scnprintf) { 11375b49202SArnaldo Carvalho de Melo if (ins__is_jump(&dl->ins)) { 114d5490b96SJiri Olsa bool fwd = dl->ops.target.offset > dl->al.offset; 11551a0d455SArnaldo Carvalho de Melo 11605e8b080SArnaldo Carvalho de Melo ui_browser__write_graph(browser, fwd ? SLSMG_DARROW_CHAR : 11751a0d455SArnaldo Carvalho de Melo SLSMG_UARROW_CHAR); 11851a0d455SArnaldo Carvalho de Melo SLsmg_write_char(' '); 11975b49202SArnaldo Carvalho de Melo } else if (ins__is_call(&dl->ins)) { 12005e8b080SArnaldo Carvalho de Melo ui_browser__write_graph(browser, SLSMG_RARROW_CHAR); 12188298f5aSArnaldo Carvalho de Melo SLsmg_write_char(' '); 12275b49202SArnaldo Carvalho de Melo } else if (ins__is_ret(&dl->ins)) { 12305e8b080SArnaldo Carvalho de Melo ui_browser__write_graph(browser, SLSMG_LARROW_CHAR); 1244ea08b52SArnaldo Carvalho de Melo SLsmg_write_char(' '); 1256ef94929SNaveen N. Rao } else { 1266ef94929SNaveen N. Rao ui_browser__write_nstring(browser, " ", 2); 1274ea08b52SArnaldo Carvalho de Melo } 1286ef94929SNaveen N. Rao } else { 1296ef94929SNaveen N. Rao ui_browser__write_nstring(browser, " ", 2); 1304ea08b52SArnaldo Carvalho de Melo } 1314ea08b52SArnaldo Carvalho de Melo 132*16932d77SArnaldo Carvalho de Melo disasm_line__scnprintf(dl, bf, size, !notes->options->use_offset); 133a5433b3eSJiri Olsa } 134a5433b3eSJiri Olsa 135a5433b3eSJiri Olsa static void annotate_browser__write(struct ui_browser *browser, void *entry, int row) 136a5433b3eSJiri Olsa { 137a5433b3eSJiri Olsa struct annotate_browser *ab = container_of(browser, struct annotate_browser, b); 1380e83a7e9SArnaldo Carvalho de Melo struct map_symbol *ms = browser->priv; 1390e83a7e9SArnaldo Carvalho de Melo struct symbol *sym = ms->sym; 1400e83a7e9SArnaldo Carvalho de Melo struct annotation *notes = symbol__annotation(sym); 141a5433b3eSJiri Olsa struct annotation_line *al = list_entry(entry, struct annotation_line, node); 142a5433b3eSJiri Olsa struct browser_line *bl = browser_line(al); 143a5433b3eSJiri Olsa bool current_entry = ui_browser__is_current_entry(browser, row); 144*16932d77SArnaldo Carvalho de Melo bool change_color = (!notes->options->hide_src_code && 145a5433b3eSJiri Olsa (!current_entry || (browser->use_navkeypressed && 146a5433b3eSJiri Olsa !browser->navkeypressed))); 147a5433b3eSJiri Olsa int width = browser->width, printed; 148a5433b3eSJiri Olsa int i, pcnt_width = annotate_browser__pcnt_width(ab), 1490e83a7e9SArnaldo Carvalho de Melo cycles_width = annotation__cycles_width(notes); 150a5433b3eSJiri Olsa double percent_max = 0.0; 151a5433b3eSJiri Olsa char bf[256]; 152a5433b3eSJiri Olsa bool show_title = false; 153a5433b3eSJiri Olsa 1540553e83dSArnaldo Carvalho de Melo for (i = 0; i < notes->nr_events; i++) { 155a5433b3eSJiri Olsa if (al->samples[i].percent > percent_max) 156a5433b3eSJiri Olsa percent_max = al->samples[i].percent; 157a5433b3eSJiri Olsa } 158a5433b3eSJiri Olsa 159a5433b3eSJiri Olsa if ((row == 0) && (al->offset == -1 || percent_max == 0.0)) { 1600e83a7e9SArnaldo Carvalho de Melo if (notes->have_cycles) { 161a5433b3eSJiri Olsa if (al->ipc == 0.0 && al->cycles == 0) 162a5433b3eSJiri Olsa show_title = true; 163a5433b3eSJiri Olsa } else 164a5433b3eSJiri Olsa show_title = true; 165a5433b3eSJiri Olsa } 166a5433b3eSJiri Olsa 167a5433b3eSJiri Olsa if (al->offset != -1 && percent_max != 0.0) { 1680553e83dSArnaldo Carvalho de Melo for (i = 0; i < notes->nr_events; i++) { 169a5433b3eSJiri Olsa ui_browser__set_percent_color(browser, 170a5433b3eSJiri Olsa al->samples[i].percent, 171a5433b3eSJiri Olsa current_entry); 172*16932d77SArnaldo Carvalho de Melo if (notes->options->show_total_period) { 173a5433b3eSJiri Olsa ui_browser__printf(browser, "%11" PRIu64 " ", 174a5433b3eSJiri Olsa al->samples[i].he.period); 175*16932d77SArnaldo Carvalho de Melo } else if (notes->options->show_nr_samples) { 176a5433b3eSJiri Olsa ui_browser__printf(browser, "%6" PRIu64 " ", 177a5433b3eSJiri Olsa al->samples[i].he.nr_samples); 178a5433b3eSJiri Olsa } else { 179a5433b3eSJiri Olsa ui_browser__printf(browser, "%6.2f ", 180a5433b3eSJiri Olsa al->samples[i].percent); 181a5433b3eSJiri Olsa } 182a5433b3eSJiri Olsa } 183a5433b3eSJiri Olsa } else { 184a5433b3eSJiri Olsa ui_browser__set_percent_color(browser, 0, current_entry); 185a5433b3eSJiri Olsa 186a5433b3eSJiri Olsa if (!show_title) 187a5433b3eSJiri Olsa ui_browser__write_nstring(browser, " ", pcnt_width); 188a5433b3eSJiri Olsa else { 189a5433b3eSJiri Olsa ui_browser__printf(browser, "%*s", pcnt_width, 190*16932d77SArnaldo Carvalho de Melo notes->options->show_total_period ? "Period" : 191*16932d77SArnaldo Carvalho de Melo notes->options->show_nr_samples ? "Samples" : "Percent"); 192a5433b3eSJiri Olsa } 193a5433b3eSJiri Olsa } 1940e83a7e9SArnaldo Carvalho de Melo if (notes->have_cycles) { 195a5433b3eSJiri Olsa if (al->ipc) 196c426e584SArnaldo Carvalho de Melo ui_browser__printf(browser, "%*.2f ", ANNOTATION__IPC_WIDTH - 1, al->ipc); 197a5433b3eSJiri Olsa else if (!show_title) 198c426e584SArnaldo Carvalho de Melo ui_browser__write_nstring(browser, " ", ANNOTATION__IPC_WIDTH); 199a5433b3eSJiri Olsa else 200c426e584SArnaldo Carvalho de Melo ui_browser__printf(browser, "%*s ", ANNOTATION__IPC_WIDTH - 1, "IPC"); 201a5433b3eSJiri Olsa 202a5433b3eSJiri Olsa if (al->cycles) 203a5433b3eSJiri Olsa ui_browser__printf(browser, "%*" PRIu64 " ", 204c426e584SArnaldo Carvalho de Melo ANNOTATION__CYCLES_WIDTH - 1, al->cycles); 205a5433b3eSJiri Olsa else if (!show_title) 206c426e584SArnaldo Carvalho de Melo ui_browser__write_nstring(browser, " ", ANNOTATION__CYCLES_WIDTH); 207a5433b3eSJiri Olsa else 208c426e584SArnaldo Carvalho de Melo ui_browser__printf(browser, "%*s ", ANNOTATION__CYCLES_WIDTH - 1, "Cycle"); 209a5433b3eSJiri Olsa } 210a5433b3eSJiri Olsa 211a5433b3eSJiri Olsa SLsmg_write_char(' '); 212a5433b3eSJiri Olsa 213a5433b3eSJiri Olsa /* The scroll bar isn't being used */ 214a5433b3eSJiri Olsa if (!browser->navkeypressed) 215a5433b3eSJiri Olsa width += 1; 216a5433b3eSJiri Olsa 217a5433b3eSJiri Olsa if (!*al->line) 218a5433b3eSJiri Olsa ui_browser__write_nstring(browser, " ", width - pcnt_width - cycles_width); 219a5433b3eSJiri Olsa else if (al->offset == -1) { 220*16932d77SArnaldo Carvalho de Melo if (al->line_nr && notes->options->show_linenr) 221a5433b3eSJiri Olsa printed = scnprintf(bf, sizeof(bf), "%-*d ", 222a5433b3eSJiri Olsa ab->addr_width + 1, al->line_nr); 223a5433b3eSJiri Olsa else 224a5433b3eSJiri Olsa printed = scnprintf(bf, sizeof(bf), "%*s ", 225a5433b3eSJiri Olsa ab->addr_width, " "); 226a5433b3eSJiri Olsa ui_browser__write_nstring(browser, bf, printed); 227a5433b3eSJiri Olsa ui_browser__write_nstring(browser, al->line, width - printed - pcnt_width - cycles_width + 1); 228a5433b3eSJiri Olsa } else { 229a5433b3eSJiri Olsa u64 addr = al->offset; 230a5433b3eSJiri Olsa int color = -1; 231a5433b3eSJiri Olsa 232*16932d77SArnaldo Carvalho de Melo if (!notes->options->use_offset) 233a5433b3eSJiri Olsa addr += ab->start; 234a5433b3eSJiri Olsa 235*16932d77SArnaldo Carvalho de Melo if (!notes->options->use_offset) { 236a5433b3eSJiri Olsa printed = scnprintf(bf, sizeof(bf), "%" PRIx64 ": ", addr); 237a5433b3eSJiri Olsa } else { 238a5433b3eSJiri Olsa if (bl->jump_sources) { 239*16932d77SArnaldo Carvalho de Melo if (notes->options->show_nr_jumps) { 240a5433b3eSJiri Olsa int prev; 241a5433b3eSJiri Olsa printed = scnprintf(bf, sizeof(bf), "%*d ", 242a5433b3eSJiri Olsa ab->jumps_width, 243a5433b3eSJiri Olsa bl->jump_sources); 244a5433b3eSJiri Olsa prev = annotate_browser__set_jumps_percent_color(ab, bl->jump_sources, 245a5433b3eSJiri Olsa current_entry); 246a5433b3eSJiri Olsa ui_browser__write_nstring(browser, bf, printed); 247a5433b3eSJiri Olsa ui_browser__set_color(browser, prev); 248a5433b3eSJiri Olsa } 249a5433b3eSJiri Olsa 250a5433b3eSJiri Olsa printed = scnprintf(bf, sizeof(bf), "%*" PRIx64 ": ", 251a5433b3eSJiri Olsa ab->target_width, addr); 252a5433b3eSJiri Olsa } else { 253a5433b3eSJiri Olsa printed = scnprintf(bf, sizeof(bf), "%*s ", 254a5433b3eSJiri Olsa ab->addr_width, " "); 255a5433b3eSJiri Olsa } 256a5433b3eSJiri Olsa } 257a5433b3eSJiri Olsa 258a5433b3eSJiri Olsa if (change_color) 259a5433b3eSJiri Olsa color = ui_browser__set_color(browser, HE_COLORSET_ADDR); 260a5433b3eSJiri Olsa ui_browser__write_nstring(browser, bf, printed); 261a5433b3eSJiri Olsa if (change_color) 262a5433b3eSJiri Olsa ui_browser__set_color(browser, color); 263a5433b3eSJiri Olsa 264a5433b3eSJiri Olsa disasm_line__write(disasm_line(al), browser, bf, sizeof(bf)); 265a5433b3eSJiri Olsa 266bc1e5d60SArnaldo Carvalho de Melo ui_browser__write_nstring(browser, bf, width - pcnt_width - cycles_width - 3 - printed); 267aca7a94dSNamhyung Kim } 268aca7a94dSNamhyung Kim 269aca7a94dSNamhyung Kim if (current_entry) 270a5433b3eSJiri Olsa ab->selection = al; 271aca7a94dSNamhyung Kim } 272aca7a94dSNamhyung Kim 273865c66c4SFrederik Deweerdt static bool disasm_line__is_valid_jump(struct disasm_line *dl, struct symbol *sym) 274865c66c4SFrederik Deweerdt { 27575b49202SArnaldo Carvalho de Melo if (!dl || !dl->ins.ops || !ins__is_jump(&dl->ins) 276865c66c4SFrederik Deweerdt || !disasm_line__has_offset(dl) 277e216874cSRavi Bangoria || dl->ops.target.offset < 0 278e216874cSRavi Bangoria || dl->ops.target.offset >= (s64)symbol__size(sym)) 279865c66c4SFrederik Deweerdt return false; 280865c66c4SFrederik Deweerdt 281865c66c4SFrederik Deweerdt return true; 282865c66c4SFrederik Deweerdt } 283865c66c4SFrederik Deweerdt 2847e63a13aSJin Yao static bool is_fused(struct annotate_browser *ab, struct disasm_line *cursor) 2857e63a13aSJin Yao { 286a17c4ca0SJiri Olsa struct disasm_line *pos = list_prev_entry(cursor, al.node); 2877e63a13aSJin Yao const char *name; 2887e63a13aSJin Yao 2897e63a13aSJin Yao if (!pos) 2907e63a13aSJin Yao return false; 2917e63a13aSJin Yao 2927e63a13aSJin Yao if (ins__is_lock(&pos->ins)) 2937e63a13aSJin Yao name = pos->ops.locked.ins.name; 2947e63a13aSJin Yao else 2957e63a13aSJin Yao name = pos->ins.name; 2967e63a13aSJin Yao 2977e63a13aSJin Yao if (!name || !cursor->ins.name) 2987e63a13aSJin Yao return false; 2997e63a13aSJin Yao 3007e63a13aSJin Yao return ins__is_fused(ab->arch, name, cursor->ins.name); 3017e63a13aSJin Yao } 3027e63a13aSJin Yao 3039d1ef56dSArnaldo Carvalho de Melo static void annotate_browser__draw_current_jump(struct ui_browser *browser) 304a3f895beSArnaldo Carvalho de Melo { 305a3f895beSArnaldo Carvalho de Melo struct annotate_browser *ab = container_of(browser, struct annotate_browser, b); 3067bcbcd58SJiri Olsa struct disasm_line *cursor = disasm_line(ab->selection); 307a5ef2702SJiri Olsa struct annotation_line *target; 3080d957970SJiri Olsa struct browser_line *btarget, *bcursor; 30983b1f2aaSArnaldo Carvalho de Melo unsigned int from, to; 31032ae1efdSNamhyung Kim struct map_symbol *ms = ab->b.priv; 31132ae1efdSNamhyung Kim struct symbol *sym = ms->sym; 3120e83a7e9SArnaldo Carvalho de Melo struct annotation *notes = symbol__annotation(sym); 313f8f4aaeaSAndi Kleen u8 pcnt_width = annotate_browser__pcnt_width(ab); 31400ea0eb2SArnaldo Carvalho de Melo int width; 31532ae1efdSNamhyung Kim 31632ae1efdSNamhyung Kim /* PLT symbols contain external offsets */ 31732ae1efdSNamhyung Kim if (strstr(sym->name, "@plt")) 31832ae1efdSNamhyung Kim return; 319a3f895beSArnaldo Carvalho de Melo 320865c66c4SFrederik Deweerdt if (!disasm_line__is_valid_jump(cursor, sym)) 321a3f895beSArnaldo Carvalho de Melo return; 322a3f895beSArnaldo Carvalho de Melo 3239c04409dSArnaldo Carvalho de Melo /* 3249c04409dSArnaldo Carvalho de Melo * This first was seen with a gcc function, _cpp_lex_token, that 3259c04409dSArnaldo Carvalho de Melo * has the usual jumps: 3269c04409dSArnaldo Carvalho de Melo * 3279c04409dSArnaldo Carvalho de Melo * │1159e6c: ↓ jne 115aa32 <_cpp_lex_token@@Base+0xf92> 3289c04409dSArnaldo Carvalho de Melo * 3299c04409dSArnaldo Carvalho de Melo * I.e. jumps to a label inside that function (_cpp_lex_token), and 3309c04409dSArnaldo Carvalho de Melo * those works, but also this kind: 3319c04409dSArnaldo Carvalho de Melo * 3329c04409dSArnaldo Carvalho de Melo * │1159e8b: ↓ jne c469be <cpp_named_operator2name@@Base+0xa72> 3339c04409dSArnaldo Carvalho de Melo * 3349c04409dSArnaldo Carvalho de Melo * I.e. jumps to another function, outside _cpp_lex_token, which 3359c04409dSArnaldo Carvalho de Melo * are not being correctly handled generating as a side effect references 3369c04409dSArnaldo Carvalho de Melo * to ab->offset[] entries that are set to NULL, so to make this code 3379c04409dSArnaldo Carvalho de Melo * more robust, check that here. 3389c04409dSArnaldo Carvalho de Melo * 3399c04409dSArnaldo Carvalho de Melo * A proper fix for will be put in place, looking at the function 3409c04409dSArnaldo Carvalho de Melo * name right after the '<' token and probably treating this like a 3419c04409dSArnaldo Carvalho de Melo * 'call' instruction. 3429c04409dSArnaldo Carvalho de Melo */ 3439d6bb41dSArnaldo Carvalho de Melo target = notes->offsets[cursor->ops.target.offset]; 3449c04409dSArnaldo Carvalho de Melo if (target == NULL) { 3459d6bb41dSArnaldo Carvalho de Melo ui_helpline__printf("WARN: jump target inconsistency, press 'o', notes->offsets[%#x] = NULL\n", 3469c04409dSArnaldo Carvalho de Melo cursor->ops.target.offset); 3479c04409dSArnaldo Carvalho de Melo return; 3489c04409dSArnaldo Carvalho de Melo } 3499d1ef56dSArnaldo Carvalho de Melo 350a5ef2702SJiri Olsa bcursor = browser_line(&cursor->al); 351daf25d43SJiri Olsa btarget = browser_line(target); 3529d1ef56dSArnaldo Carvalho de Melo 353*16932d77SArnaldo Carvalho de Melo if (notes->options->hide_src_code) { 3549d1ef56dSArnaldo Carvalho de Melo from = bcursor->idx_asm; 355a3f895beSArnaldo Carvalho de Melo to = btarget->idx_asm; 356a3f895beSArnaldo Carvalho de Melo } else { 3579d1ef56dSArnaldo Carvalho de Melo from = (u64)bcursor->idx; 358a3f895beSArnaldo Carvalho de Melo to = (u64)btarget->idx; 359a3f895beSArnaldo Carvalho de Melo } 360a3f895beSArnaldo Carvalho de Melo 3610e83a7e9SArnaldo Carvalho de Melo width = annotation__cycles_width(notes); 362b40982e8SJin Yao 36378ce08dfSTaeung Song ui_browser__set_color(browser, HE_COLORSET_JUMP_ARROWS); 364b40982e8SJin Yao __ui_browser__line_arrow(browser, 365b40982e8SJin Yao pcnt_width + 2 + ab->addr_width + width, 366c7e7b610SNamhyung Kim from, to); 3677e63a13aSJin Yao 3687e63a13aSJin Yao if (is_fused(ab, cursor)) { 3697e63a13aSJin Yao ui_browser__mark_fused(browser, 370b40982e8SJin Yao pcnt_width + 3 + ab->addr_width + width, 3717e63a13aSJin Yao from - 1, 3727e63a13aSJin Yao to > from ? true : false); 3737e63a13aSJin Yao } 374a3f895beSArnaldo Carvalho de Melo } 375a3f895beSArnaldo Carvalho de Melo 376a3f895beSArnaldo Carvalho de Melo static unsigned int annotate_browser__refresh(struct ui_browser *browser) 377a3f895beSArnaldo Carvalho de Melo { 378c7e7b610SNamhyung Kim struct annotate_browser *ab = container_of(browser, struct annotate_browser, b); 379*16932d77SArnaldo Carvalho de Melo struct map_symbol *ms = browser->priv; 380*16932d77SArnaldo Carvalho de Melo struct annotation *notes = symbol__annotation(ms->sym); 381a3f895beSArnaldo Carvalho de Melo int ret = ui_browser__list_head_refresh(browser); 382f8f4aaeaSAndi Kleen int pcnt_width = annotate_browser__pcnt_width(ab); 383a3f895beSArnaldo Carvalho de Melo 384*16932d77SArnaldo Carvalho de Melo if (notes->options->jump_arrows) 3859d1ef56dSArnaldo Carvalho de Melo annotate_browser__draw_current_jump(browser); 386a3f895beSArnaldo Carvalho de Melo 38783b1f2aaSArnaldo Carvalho de Melo ui_browser__set_color(browser, HE_COLORSET_NORMAL); 388c7e7b610SNamhyung Kim __ui_browser__vline(browser, pcnt_width, 0, browser->height - 1); 389a3f895beSArnaldo Carvalho de Melo return ret; 390a3f895beSArnaldo Carvalho de Melo } 391a3f895beSArnaldo Carvalho de Melo 392b15636c6SJiri Olsa static int disasm__cmp(struct annotation_line *a, struct annotation_line *b) 393c7e7b610SNamhyung Kim { 394c7e7b610SNamhyung Kim int i; 395c7e7b610SNamhyung Kim 396b15636c6SJiri Olsa for (i = 0; i < a->samples_nr; i++) { 3970c4a5bceSMartin Liška if (a->samples[i].percent == b->samples[i].percent) 398c7e7b610SNamhyung Kim continue; 3990c4a5bceSMartin Liška return a->samples[i].percent < b->samples[i].percent; 400c7e7b610SNamhyung Kim } 401c7e7b610SNamhyung Kim return 0; 402c7e7b610SNamhyung Kim } 403c7e7b610SNamhyung Kim 404b15636c6SJiri Olsa static void disasm_rb_tree__insert(struct rb_root *root, struct annotation_line *al) 405aca7a94dSNamhyung Kim { 40629ed6e76SArnaldo Carvalho de Melo struct rb_node **p = &root->rb_node; 407aca7a94dSNamhyung Kim struct rb_node *parent = NULL; 4083ab6db8dSJiri Olsa struct annotation_line *l; 409aca7a94dSNamhyung Kim 410aca7a94dSNamhyung Kim while (*p != NULL) { 411aca7a94dSNamhyung Kim parent = *p; 4123ab6db8dSJiri Olsa l = rb_entry(parent, struct annotation_line, rb_node); 413c7e7b610SNamhyung Kim 414b15636c6SJiri Olsa if (disasm__cmp(al, l)) 415aca7a94dSNamhyung Kim p = &(*p)->rb_left; 416aca7a94dSNamhyung Kim else 417aca7a94dSNamhyung Kim p = &(*p)->rb_right; 418aca7a94dSNamhyung Kim } 4193ab6db8dSJiri Olsa rb_link_node(&al->rb_node, parent, p); 4203ab6db8dSJiri Olsa rb_insert_color(&al->rb_node, root); 421aca7a94dSNamhyung Kim } 422aca7a94dSNamhyung Kim 42305e8b080SArnaldo Carvalho de Melo static void annotate_browser__set_top(struct annotate_browser *browser, 424ec03a77dSJiri Olsa struct annotation_line *pos, u32 idx) 425aca7a94dSNamhyung Kim { 426aca7a94dSNamhyung Kim unsigned back; 427aca7a94dSNamhyung Kim 42805e8b080SArnaldo Carvalho de Melo ui_browser__refresh_dimensions(&browser->b); 42905e8b080SArnaldo Carvalho de Melo back = browser->b.height / 2; 43005e8b080SArnaldo Carvalho de Melo browser->b.top_idx = browser->b.index = idx; 431aca7a94dSNamhyung Kim 43205e8b080SArnaldo Carvalho de Melo while (browser->b.top_idx != 0 && back != 0) { 433ec03a77dSJiri Olsa pos = list_entry(pos->node.prev, struct annotation_line, node); 434aca7a94dSNamhyung Kim 435ec03a77dSJiri Olsa if (disasm_line__filter(&browser->b, &pos->node)) 436aca7a94dSNamhyung Kim continue; 437aca7a94dSNamhyung Kim 43805e8b080SArnaldo Carvalho de Melo --browser->b.top_idx; 439aca7a94dSNamhyung Kim --back; 440aca7a94dSNamhyung Kim } 441aca7a94dSNamhyung Kim 442ec03a77dSJiri Olsa browser->b.top = pos; 44305e8b080SArnaldo Carvalho de Melo browser->b.navkeypressed = true; 444aca7a94dSNamhyung Kim } 445aca7a94dSNamhyung Kim 446aca7a94dSNamhyung Kim static void annotate_browser__set_rb_top(struct annotate_browser *browser, 447aca7a94dSNamhyung Kim struct rb_node *nd) 448aca7a94dSNamhyung Kim { 449*16932d77SArnaldo Carvalho de Melo struct map_symbol *ms = browser->b.priv; 450*16932d77SArnaldo Carvalho de Melo struct annotation *notes = symbol__annotation(ms->sym); 4510d957970SJiri Olsa struct browser_line *bpos; 452ec03a77dSJiri Olsa struct annotation_line *pos; 453a44b45f2SArnaldo Carvalho de Melo u32 idx; 454aca7a94dSNamhyung Kim 455ec03a77dSJiri Olsa pos = rb_entry(nd, struct annotation_line, rb_node); 456ec03a77dSJiri Olsa bpos = browser_line(pos); 4575b12adc8SJiri Olsa 458a44b45f2SArnaldo Carvalho de Melo idx = bpos->idx; 459*16932d77SArnaldo Carvalho de Melo if (notes->options->hide_src_code) 460a44b45f2SArnaldo Carvalho de Melo idx = bpos->idx_asm; 461a44b45f2SArnaldo Carvalho de Melo annotate_browser__set_top(browser, pos, idx); 462aca7a94dSNamhyung Kim browser->curr_hot = nd; 463aca7a94dSNamhyung Kim } 464aca7a94dSNamhyung Kim 465aca7a94dSNamhyung Kim static void annotate_browser__calc_percent(struct annotate_browser *browser, 466db8fd07aSNamhyung Kim struct perf_evsel *evsel) 467aca7a94dSNamhyung Kim { 468aca7a94dSNamhyung Kim struct map_symbol *ms = browser->b.priv; 469aca7a94dSNamhyung Kim struct symbol *sym = ms->sym; 470aca7a94dSNamhyung Kim struct annotation *notes = symbol__annotation(sym); 471c4c72436SJiri Olsa struct disasm_line *pos; 472aca7a94dSNamhyung Kim 473aca7a94dSNamhyung Kim browser->entries = RB_ROOT; 474aca7a94dSNamhyung Kim 475aca7a94dSNamhyung Kim pthread_mutex_lock(¬es->lock); 476aca7a94dSNamhyung Kim 477e425da6cSJiri Olsa symbol__calc_percent(sym, evsel); 478e425da6cSJiri Olsa 479a17c4ca0SJiri Olsa list_for_each_entry(pos, ¬es->src->source, al.node) { 480c7e7b610SNamhyung Kim double max_percent = 0.0; 481c7e7b610SNamhyung Kim int i; 482e64aa75bSNamhyung Kim 483d5490b96SJiri Olsa if (pos->al.offset == -1) { 4845b12adc8SJiri Olsa RB_CLEAR_NODE(&pos->al.rb_node); 485e64aa75bSNamhyung Kim continue; 486e64aa75bSNamhyung Kim } 487e64aa75bSNamhyung Kim 488b15636c6SJiri Olsa for (i = 0; i < pos->al.samples_nr; i++) { 489e425da6cSJiri Olsa struct annotation_data *sample = &pos->al.samples[i]; 4900c4a5bceSMartin Liška 4913ab6db8dSJiri Olsa if (max_percent < sample->percent) 4923ab6db8dSJiri Olsa max_percent = sample->percent; 493c7e7b610SNamhyung Kim } 494c7e7b610SNamhyung Kim 49537236d5eSJiri Olsa if (max_percent < 0.01 && pos->al.ipc == 0) { 4965b12adc8SJiri Olsa RB_CLEAR_NODE(&pos->al.rb_node); 497aca7a94dSNamhyung Kim continue; 498aca7a94dSNamhyung Kim } 499b15636c6SJiri Olsa disasm_rb_tree__insert(&browser->entries, &pos->al); 500aca7a94dSNamhyung Kim } 501aca7a94dSNamhyung Kim pthread_mutex_unlock(¬es->lock); 502aca7a94dSNamhyung Kim 503aca7a94dSNamhyung Kim browser->curr_hot = rb_last(&browser->entries); 504aca7a94dSNamhyung Kim } 505aca7a94dSNamhyung Kim 506aca7a94dSNamhyung Kim static bool annotate_browser__toggle_source(struct annotate_browser *browser) 507aca7a94dSNamhyung Kim { 508*16932d77SArnaldo Carvalho de Melo struct map_symbol *ms = browser->b.priv; 509*16932d77SArnaldo Carvalho de Melo struct annotation *notes = symbol__annotation(ms->sym); 510ec03a77dSJiri Olsa struct annotation_line *al; 511a5ef2702SJiri Olsa struct browser_line *bl; 512aca7a94dSNamhyung Kim off_t offset = browser->b.index - browser->b.top_idx; 513aca7a94dSNamhyung Kim 514aca7a94dSNamhyung Kim browser->b.seek(&browser->b, offset, SEEK_CUR); 515ec03a77dSJiri Olsa al = list_entry(browser->b.top, struct annotation_line, node); 516ec03a77dSJiri Olsa bl = browser_line(al); 517aca7a94dSNamhyung Kim 518*16932d77SArnaldo Carvalho de Melo if (notes->options->hide_src_code) { 519a5ef2702SJiri Olsa if (bl->idx_asm < offset) 520a5ef2702SJiri Olsa offset = bl->idx; 521aca7a94dSNamhyung Kim 522aca7a94dSNamhyung Kim browser->b.nr_entries = browser->nr_entries; 523*16932d77SArnaldo Carvalho de Melo notes->options->hide_src_code = false; 524aca7a94dSNamhyung Kim browser->b.seek(&browser->b, -offset, SEEK_CUR); 525a5ef2702SJiri Olsa browser->b.top_idx = bl->idx - offset; 526a5ef2702SJiri Olsa browser->b.index = bl->idx; 527aca7a94dSNamhyung Kim } else { 528a5ef2702SJiri Olsa if (bl->idx_asm < 0) { 529aca7a94dSNamhyung Kim ui_helpline__puts("Only available for assembly lines."); 530aca7a94dSNamhyung Kim browser->b.seek(&browser->b, -offset, SEEK_CUR); 531aca7a94dSNamhyung Kim return false; 532aca7a94dSNamhyung Kim } 533aca7a94dSNamhyung Kim 534a5ef2702SJiri Olsa if (bl->idx_asm < offset) 535a5ef2702SJiri Olsa offset = bl->idx_asm; 536aca7a94dSNamhyung Kim 537aca7a94dSNamhyung Kim browser->b.nr_entries = browser->nr_asm_entries; 538*16932d77SArnaldo Carvalho de Melo notes->options->hide_src_code = true; 539aca7a94dSNamhyung Kim browser->b.seek(&browser->b, -offset, SEEK_CUR); 540a5ef2702SJiri Olsa browser->b.top_idx = bl->idx_asm - offset; 541a5ef2702SJiri Olsa browser->b.index = bl->idx_asm; 542aca7a94dSNamhyung Kim } 543aca7a94dSNamhyung Kim 544aca7a94dSNamhyung Kim return true; 545aca7a94dSNamhyung Kim } 546aca7a94dSNamhyung Kim 547e9823b21SArnaldo Carvalho de Melo static void annotate_browser__init_asm_mode(struct annotate_browser *browser) 548e9823b21SArnaldo Carvalho de Melo { 549e9823b21SArnaldo Carvalho de Melo ui_browser__reset_index(&browser->b); 550e9823b21SArnaldo Carvalho de Melo browser->b.nr_entries = browser->nr_asm_entries; 551e9823b21SArnaldo Carvalho de Melo } 552e9823b21SArnaldo Carvalho de Melo 55334f77abcSAdrian Hunter #define SYM_TITLE_MAX_SIZE (PATH_MAX + 64) 55434f77abcSAdrian Hunter 55534f77abcSAdrian Hunter static int sym_title(struct symbol *sym, struct map *map, char *title, 55634f77abcSAdrian Hunter size_t sz) 55734f77abcSAdrian Hunter { 55834f77abcSAdrian Hunter return snprintf(title, sz, "%s %s", sym->name, map->dso->long_name); 55934f77abcSAdrian Hunter } 56034f77abcSAdrian Hunter 561db8fd07aSNamhyung Kim static bool annotate_browser__callq(struct annotate_browser *browser, 562db8fd07aSNamhyung Kim struct perf_evsel *evsel, 5639783adf7SNamhyung Kim struct hist_browser_timer *hbt) 564aca7a94dSNamhyung Kim { 565aca7a94dSNamhyung Kim struct map_symbol *ms = browser->b.priv; 5667bcbcd58SJiri Olsa struct disasm_line *dl = disasm_line(browser->selection); 567aca7a94dSNamhyung Kim struct annotation *notes; 56834f77abcSAdrian Hunter char title[SYM_TITLE_MAX_SIZE]; 569aca7a94dSNamhyung Kim 57075b49202SArnaldo Carvalho de Melo if (!ins__is_call(&dl->ins)) 571aca7a94dSNamhyung Kim return false; 572aca7a94dSNamhyung Kim 573696703afSArnaldo Carvalho de Melo if (!dl->ops.target.sym) { 574aca7a94dSNamhyung Kim ui_helpline__puts("The called function was not found."); 575aca7a94dSNamhyung Kim return true; 576aca7a94dSNamhyung Kim } 577aca7a94dSNamhyung Kim 578696703afSArnaldo Carvalho de Melo notes = symbol__annotation(dl->ops.target.sym); 579aca7a94dSNamhyung Kim pthread_mutex_lock(¬es->lock); 580aca7a94dSNamhyung Kim 581696703afSArnaldo Carvalho de Melo if (notes->src == NULL && symbol__alloc_hist(dl->ops.target.sym) < 0) { 582aca7a94dSNamhyung Kim pthread_mutex_unlock(¬es->lock); 583aca7a94dSNamhyung Kim ui__warning("Not enough memory for annotating '%s' symbol!\n", 584696703afSArnaldo Carvalho de Melo dl->ops.target.sym->name); 585aca7a94dSNamhyung Kim return true; 586aca7a94dSNamhyung Kim } 587aca7a94dSNamhyung Kim 588aca7a94dSNamhyung Kim pthread_mutex_unlock(¬es->lock); 589696703afSArnaldo Carvalho de Melo symbol__tui_annotate(dl->ops.target.sym, ms->map, evsel, hbt); 5901179e11bSAdrian Hunter sym_title(ms->sym, ms->map, title, sizeof(title)); 59134f77abcSAdrian Hunter ui_browser__show_title(&browser->b, title); 592aca7a94dSNamhyung Kim return true; 593aca7a94dSNamhyung Kim } 594aca7a94dSNamhyung Kim 59529ed6e76SArnaldo Carvalho de Melo static 59629ed6e76SArnaldo Carvalho de Melo struct disasm_line *annotate_browser__find_offset(struct annotate_browser *browser, 597aca7a94dSNamhyung Kim s64 offset, s64 *idx) 598aca7a94dSNamhyung Kim { 599aca7a94dSNamhyung Kim struct map_symbol *ms = browser->b.priv; 600aca7a94dSNamhyung Kim struct symbol *sym = ms->sym; 601aca7a94dSNamhyung Kim struct annotation *notes = symbol__annotation(sym); 60229ed6e76SArnaldo Carvalho de Melo struct disasm_line *pos; 603aca7a94dSNamhyung Kim 604aca7a94dSNamhyung Kim *idx = 0; 605a17c4ca0SJiri Olsa list_for_each_entry(pos, ¬es->src->source, al.node) { 606d5490b96SJiri Olsa if (pos->al.offset == offset) 607aca7a94dSNamhyung Kim return pos; 608a17c4ca0SJiri Olsa if (!disasm_line__filter(&browser->b, &pos->al.node)) 609aca7a94dSNamhyung Kim ++*idx; 610aca7a94dSNamhyung Kim } 611aca7a94dSNamhyung Kim 612aca7a94dSNamhyung Kim return NULL; 613aca7a94dSNamhyung Kim } 614aca7a94dSNamhyung Kim 615aca7a94dSNamhyung Kim static bool annotate_browser__jump(struct annotate_browser *browser) 616aca7a94dSNamhyung Kim { 6177bcbcd58SJiri Olsa struct disasm_line *dl = disasm_line(browser->selection); 6185252b1aeSArnaldo Carvalho de Melo u64 offset; 6194f9d0325SArnaldo Carvalho de Melo s64 idx; 620aca7a94dSNamhyung Kim 62175b49202SArnaldo Carvalho de Melo if (!ins__is_jump(&dl->ins)) 622aca7a94dSNamhyung Kim return false; 623aca7a94dSNamhyung Kim 6245252b1aeSArnaldo Carvalho de Melo offset = dl->ops.target.offset; 6255252b1aeSArnaldo Carvalho de Melo dl = annotate_browser__find_offset(browser, offset, &idx); 62629ed6e76SArnaldo Carvalho de Melo if (dl == NULL) { 6275252b1aeSArnaldo Carvalho de Melo ui_helpline__printf("Invalid jump offset: %" PRIx64, offset); 628aca7a94dSNamhyung Kim return true; 629aca7a94dSNamhyung Kim } 630aca7a94dSNamhyung Kim 631ec03a77dSJiri Olsa annotate_browser__set_top(browser, &dl->al, idx); 632aca7a94dSNamhyung Kim 633aca7a94dSNamhyung Kim return true; 634aca7a94dSNamhyung Kim } 635aca7a94dSNamhyung Kim 63629ed6e76SArnaldo Carvalho de Melo static 6379213afbdSJiri Olsa struct annotation_line *annotate_browser__find_string(struct annotate_browser *browser, 638aca7a94dSNamhyung Kim char *s, s64 *idx) 639aca7a94dSNamhyung Kim { 640aca7a94dSNamhyung Kim struct map_symbol *ms = browser->b.priv; 641aca7a94dSNamhyung Kim struct symbol *sym = ms->sym; 642aca7a94dSNamhyung Kim struct annotation *notes = symbol__annotation(sym); 6439213afbdSJiri Olsa struct annotation_line *al = browser->selection; 644aca7a94dSNamhyung Kim 645aca7a94dSNamhyung Kim *idx = browser->b.index; 6469213afbdSJiri Olsa list_for_each_entry_continue(al, ¬es->src->source, node) { 6479213afbdSJiri Olsa if (disasm_line__filter(&browser->b, &al->node)) 648aca7a94dSNamhyung Kim continue; 649aca7a94dSNamhyung Kim 650aca7a94dSNamhyung Kim ++*idx; 651aca7a94dSNamhyung Kim 6529213afbdSJiri Olsa if (al->line && strstr(al->line, s) != NULL) 6539213afbdSJiri Olsa return al; 654aca7a94dSNamhyung Kim } 655aca7a94dSNamhyung Kim 656aca7a94dSNamhyung Kim return NULL; 657aca7a94dSNamhyung Kim } 658aca7a94dSNamhyung Kim 659aca7a94dSNamhyung Kim static bool __annotate_browser__search(struct annotate_browser *browser) 660aca7a94dSNamhyung Kim { 6619213afbdSJiri Olsa struct annotation_line *al; 662aca7a94dSNamhyung Kim s64 idx; 663aca7a94dSNamhyung Kim 6649213afbdSJiri Olsa al = annotate_browser__find_string(browser, browser->search_bf, &idx); 6659213afbdSJiri Olsa if (al == NULL) { 666aca7a94dSNamhyung Kim ui_helpline__puts("String not found!"); 667aca7a94dSNamhyung Kim return false; 668aca7a94dSNamhyung Kim } 669aca7a94dSNamhyung Kim 670ec03a77dSJiri Olsa annotate_browser__set_top(browser, al, idx); 671aca7a94dSNamhyung Kim browser->searching_backwards = false; 672aca7a94dSNamhyung Kim return true; 673aca7a94dSNamhyung Kim } 674aca7a94dSNamhyung Kim 67529ed6e76SArnaldo Carvalho de Melo static 6769213afbdSJiri Olsa struct annotation_line *annotate_browser__find_string_reverse(struct annotate_browser *browser, 677aca7a94dSNamhyung Kim char *s, s64 *idx) 678aca7a94dSNamhyung Kim { 679aca7a94dSNamhyung Kim struct map_symbol *ms = browser->b.priv; 680aca7a94dSNamhyung Kim struct symbol *sym = ms->sym; 681aca7a94dSNamhyung Kim struct annotation *notes = symbol__annotation(sym); 6829213afbdSJiri Olsa struct annotation_line *al = browser->selection; 683aca7a94dSNamhyung Kim 684aca7a94dSNamhyung Kim *idx = browser->b.index; 6859213afbdSJiri Olsa list_for_each_entry_continue_reverse(al, ¬es->src->source, node) { 6869213afbdSJiri Olsa if (disasm_line__filter(&browser->b, &al->node)) 687aca7a94dSNamhyung Kim continue; 688aca7a94dSNamhyung Kim 689aca7a94dSNamhyung Kim --*idx; 690aca7a94dSNamhyung Kim 6919213afbdSJiri Olsa if (al->line && strstr(al->line, s) != NULL) 6929213afbdSJiri Olsa return al; 693aca7a94dSNamhyung Kim } 694aca7a94dSNamhyung Kim 695aca7a94dSNamhyung Kim return NULL; 696aca7a94dSNamhyung Kim } 697aca7a94dSNamhyung Kim 698aca7a94dSNamhyung Kim static bool __annotate_browser__search_reverse(struct annotate_browser *browser) 699aca7a94dSNamhyung Kim { 7009213afbdSJiri Olsa struct annotation_line *al; 701aca7a94dSNamhyung Kim s64 idx; 702aca7a94dSNamhyung Kim 7039213afbdSJiri Olsa al = annotate_browser__find_string_reverse(browser, browser->search_bf, &idx); 7049213afbdSJiri Olsa if (al == NULL) { 705aca7a94dSNamhyung Kim ui_helpline__puts("String not found!"); 706aca7a94dSNamhyung Kim return false; 707aca7a94dSNamhyung Kim } 708aca7a94dSNamhyung Kim 709ec03a77dSJiri Olsa annotate_browser__set_top(browser, al, idx); 710aca7a94dSNamhyung Kim browser->searching_backwards = true; 711aca7a94dSNamhyung Kim return true; 712aca7a94dSNamhyung Kim } 713aca7a94dSNamhyung Kim 714aca7a94dSNamhyung Kim static bool annotate_browser__search_window(struct annotate_browser *browser, 715aca7a94dSNamhyung Kim int delay_secs) 716aca7a94dSNamhyung Kim { 717aca7a94dSNamhyung Kim if (ui_browser__input_window("Search", "String: ", browser->search_bf, 718aca7a94dSNamhyung Kim "ENTER: OK, ESC: Cancel", 719aca7a94dSNamhyung Kim delay_secs * 2) != K_ENTER || 720aca7a94dSNamhyung Kim !*browser->search_bf) 721aca7a94dSNamhyung Kim return false; 722aca7a94dSNamhyung Kim 723aca7a94dSNamhyung Kim return true; 724aca7a94dSNamhyung Kim } 725aca7a94dSNamhyung Kim 726aca7a94dSNamhyung Kim static bool annotate_browser__search(struct annotate_browser *browser, int delay_secs) 727aca7a94dSNamhyung Kim { 728aca7a94dSNamhyung Kim if (annotate_browser__search_window(browser, delay_secs)) 729aca7a94dSNamhyung Kim return __annotate_browser__search(browser); 730aca7a94dSNamhyung Kim 731aca7a94dSNamhyung Kim return false; 732aca7a94dSNamhyung Kim } 733aca7a94dSNamhyung Kim 734aca7a94dSNamhyung Kim static bool annotate_browser__continue_search(struct annotate_browser *browser, 735aca7a94dSNamhyung Kim int delay_secs) 736aca7a94dSNamhyung Kim { 737aca7a94dSNamhyung Kim if (!*browser->search_bf) 738aca7a94dSNamhyung Kim return annotate_browser__search(browser, delay_secs); 739aca7a94dSNamhyung Kim 740aca7a94dSNamhyung Kim return __annotate_browser__search(browser); 741aca7a94dSNamhyung Kim } 742aca7a94dSNamhyung Kim 743aca7a94dSNamhyung Kim static bool annotate_browser__search_reverse(struct annotate_browser *browser, 744aca7a94dSNamhyung Kim int delay_secs) 745aca7a94dSNamhyung Kim { 746aca7a94dSNamhyung Kim if (annotate_browser__search_window(browser, delay_secs)) 747aca7a94dSNamhyung Kim return __annotate_browser__search_reverse(browser); 748aca7a94dSNamhyung Kim 749aca7a94dSNamhyung Kim return false; 750aca7a94dSNamhyung Kim } 751aca7a94dSNamhyung Kim 752aca7a94dSNamhyung Kim static 753aca7a94dSNamhyung Kim bool annotate_browser__continue_search_reverse(struct annotate_browser *browser, 754aca7a94dSNamhyung Kim int delay_secs) 755aca7a94dSNamhyung Kim { 756aca7a94dSNamhyung Kim if (!*browser->search_bf) 757aca7a94dSNamhyung Kim return annotate_browser__search_reverse(browser, delay_secs); 758aca7a94dSNamhyung Kim 759aca7a94dSNamhyung Kim return __annotate_browser__search_reverse(browser); 760aca7a94dSNamhyung Kim } 761aca7a94dSNamhyung Kim 762e9823b21SArnaldo Carvalho de Melo static void annotate_browser__update_addr_width(struct annotate_browser *browser) 763e9823b21SArnaldo Carvalho de Melo { 764*16932d77SArnaldo Carvalho de Melo struct map_symbol *ms = browser->b.priv; 765*16932d77SArnaldo Carvalho de Melo struct annotation *notes = symbol__annotation(ms->sym); 766*16932d77SArnaldo Carvalho de Melo 767*16932d77SArnaldo Carvalho de Melo if (notes->options->use_offset) 768e9823b21SArnaldo Carvalho de Melo browser->target_width = browser->min_addr_width; 769e9823b21SArnaldo Carvalho de Melo else 770e9823b21SArnaldo Carvalho de Melo browser->target_width = browser->max_addr_width; 771e9823b21SArnaldo Carvalho de Melo 772e9823b21SArnaldo Carvalho de Melo browser->addr_width = browser->target_width; 773e9823b21SArnaldo Carvalho de Melo 774*16932d77SArnaldo Carvalho de Melo if (notes->options->show_nr_jumps) 775e9823b21SArnaldo Carvalho de Melo browser->addr_width += browser->jumps_width + 1; 776e9823b21SArnaldo Carvalho de Melo } 777e9823b21SArnaldo Carvalho de Melo 778db8fd07aSNamhyung Kim static int annotate_browser__run(struct annotate_browser *browser, 779db8fd07aSNamhyung Kim struct perf_evsel *evsel, 7809783adf7SNamhyung Kim struct hist_browser_timer *hbt) 781aca7a94dSNamhyung Kim { 782aca7a94dSNamhyung Kim struct rb_node *nd = NULL; 78305e8b080SArnaldo Carvalho de Melo struct map_symbol *ms = browser->b.priv; 784aca7a94dSNamhyung Kim struct symbol *sym = ms->sym; 785*16932d77SArnaldo Carvalho de Melo struct annotation *notes = symbol__annotation(ms->sym); 78654e7a4e8SArnaldo Carvalho de Melo const char *help = "Press 'h' for help on key bindings"; 7879783adf7SNamhyung Kim int delay_secs = hbt ? hbt->refresh : 0; 788aca7a94dSNamhyung Kim int key; 78934f77abcSAdrian Hunter char title[SYM_TITLE_MAX_SIZE]; 790aca7a94dSNamhyung Kim 79134f77abcSAdrian Hunter sym_title(sym, ms->map, title, sizeof(title)); 79234f77abcSAdrian Hunter if (ui_browser__show(&browser->b, title, help) < 0) 793aca7a94dSNamhyung Kim return -1; 794aca7a94dSNamhyung Kim 795db8fd07aSNamhyung Kim annotate_browser__calc_percent(browser, evsel); 796aca7a94dSNamhyung Kim 79705e8b080SArnaldo Carvalho de Melo if (browser->curr_hot) { 79805e8b080SArnaldo Carvalho de Melo annotate_browser__set_rb_top(browser, browser->curr_hot); 79905e8b080SArnaldo Carvalho de Melo browser->b.navkeypressed = false; 800aca7a94dSNamhyung Kim } 801aca7a94dSNamhyung Kim 80205e8b080SArnaldo Carvalho de Melo nd = browser->curr_hot; 803aca7a94dSNamhyung Kim 804aca7a94dSNamhyung Kim while (1) { 80505e8b080SArnaldo Carvalho de Melo key = ui_browser__run(&browser->b, delay_secs); 806aca7a94dSNamhyung Kim 807aca7a94dSNamhyung Kim if (delay_secs != 0) { 808db8fd07aSNamhyung Kim annotate_browser__calc_percent(browser, evsel); 809aca7a94dSNamhyung Kim /* 810aca7a94dSNamhyung Kim * Current line focus got out of the list of most active 811aca7a94dSNamhyung Kim * lines, NULL it so that if TAB|UNTAB is pressed, we 812aca7a94dSNamhyung Kim * move to curr_hot (current hottest line). 813aca7a94dSNamhyung Kim */ 814aca7a94dSNamhyung Kim if (nd != NULL && RB_EMPTY_NODE(nd)) 815aca7a94dSNamhyung Kim nd = NULL; 816aca7a94dSNamhyung Kim } 817aca7a94dSNamhyung Kim 818aca7a94dSNamhyung Kim switch (key) { 819aca7a94dSNamhyung Kim case K_TIMER: 8209783adf7SNamhyung Kim if (hbt) 8219783adf7SNamhyung Kim hbt->timer(hbt->arg); 822aca7a94dSNamhyung Kim 823aca7a94dSNamhyung Kim if (delay_secs != 0) 824db8fd07aSNamhyung Kim symbol__annotate_decay_histogram(sym, evsel->idx); 825aca7a94dSNamhyung Kim continue; 826aca7a94dSNamhyung Kim case K_TAB: 827aca7a94dSNamhyung Kim if (nd != NULL) { 828aca7a94dSNamhyung Kim nd = rb_prev(nd); 829aca7a94dSNamhyung Kim if (nd == NULL) 83005e8b080SArnaldo Carvalho de Melo nd = rb_last(&browser->entries); 831aca7a94dSNamhyung Kim } else 83205e8b080SArnaldo Carvalho de Melo nd = browser->curr_hot; 833aca7a94dSNamhyung Kim break; 834aca7a94dSNamhyung Kim case K_UNTAB: 835d4913cbdSMarkus Trippelsdorf if (nd != NULL) { 836aca7a94dSNamhyung Kim nd = rb_next(nd); 837aca7a94dSNamhyung Kim if (nd == NULL) 83805e8b080SArnaldo Carvalho de Melo nd = rb_first(&browser->entries); 839d4913cbdSMarkus Trippelsdorf } else 84005e8b080SArnaldo Carvalho de Melo nd = browser->curr_hot; 841aca7a94dSNamhyung Kim break; 84254e7a4e8SArnaldo Carvalho de Melo case K_F1: 843aca7a94dSNamhyung Kim case 'h': 84405e8b080SArnaldo Carvalho de Melo ui_browser__help_window(&browser->b, 84554e7a4e8SArnaldo Carvalho de Melo "UP/DOWN/PGUP\n" 84654e7a4e8SArnaldo Carvalho de Melo "PGDN/SPACE Navigate\n" 84754e7a4e8SArnaldo Carvalho de Melo "q/ESC/CTRL+C Exit\n\n" 8487727a925SArnaldo Carvalho de Melo "ENTER Go to target\n" 8497727a925SArnaldo Carvalho de Melo "ESC Exit\n" 850eba9fac0SArnaldo Carvalho de Melo "H Go to hottest instruction\n" 851eba9fac0SArnaldo Carvalho de Melo "TAB/shift+TAB Cycle thru hottest instructions\n" 85254e7a4e8SArnaldo Carvalho de Melo "j Toggle showing jump to target arrows\n" 85354e7a4e8SArnaldo Carvalho de Melo "J Toggle showing number of jump sources on targets\n" 85454e7a4e8SArnaldo Carvalho de Melo "n Search next string\n" 85554e7a4e8SArnaldo Carvalho de Melo "o Toggle disassembler output/simplified view\n" 85654e7a4e8SArnaldo Carvalho de Melo "s Toggle source code view\n" 8573a555c77STaeung Song "t Circulate percent, total period, samples view\n" 85854e7a4e8SArnaldo Carvalho de Melo "/ Search string\n" 859e592488cSAndi Kleen "k Toggle line numbers\n" 86079ee47faSFeng Tang "r Run available scripts\n" 861fcd9fef9SArnaldo Carvalho de Melo "? Search string backwards\n"); 86254e7a4e8SArnaldo Carvalho de Melo continue; 86379ee47faSFeng Tang case 'r': 86479ee47faSFeng Tang { 86579ee47faSFeng Tang script_browse(NULL); 86679ee47faSFeng Tang continue; 86779ee47faSFeng Tang } 868e592488cSAndi Kleen case 'k': 869*16932d77SArnaldo Carvalho de Melo notes->options->show_linenr = !notes->options->show_linenr; 870e592488cSAndi Kleen break; 87154e7a4e8SArnaldo Carvalho de Melo case 'H': 87205e8b080SArnaldo Carvalho de Melo nd = browser->curr_hot; 873aca7a94dSNamhyung Kim break; 874aca7a94dSNamhyung Kim case 's': 87505e8b080SArnaldo Carvalho de Melo if (annotate_browser__toggle_source(browser)) 876aca7a94dSNamhyung Kim ui_helpline__puts(help); 877aca7a94dSNamhyung Kim continue; 878aca7a94dSNamhyung Kim case 'o': 879*16932d77SArnaldo Carvalho de Melo notes->options->use_offset = !notes->options->use_offset; 88005e8b080SArnaldo Carvalho de Melo annotate_browser__update_addr_width(browser); 881aca7a94dSNamhyung Kim continue; 8829d1ef56dSArnaldo Carvalho de Melo case 'j': 883*16932d77SArnaldo Carvalho de Melo notes->options->jump_arrows = !notes->options->jump_arrows; 8849d1ef56dSArnaldo Carvalho de Melo continue; 8852402e4a9SArnaldo Carvalho de Melo case 'J': 886*16932d77SArnaldo Carvalho de Melo notes->options->show_nr_jumps = !notes->options->show_nr_jumps; 88705e8b080SArnaldo Carvalho de Melo annotate_browser__update_addr_width(browser); 888e9823b21SArnaldo Carvalho de Melo continue; 889aca7a94dSNamhyung Kim case '/': 89005e8b080SArnaldo Carvalho de Melo if (annotate_browser__search(browser, delay_secs)) { 891aca7a94dSNamhyung Kim show_help: 892aca7a94dSNamhyung Kim ui_helpline__puts(help); 893aca7a94dSNamhyung Kim } 894aca7a94dSNamhyung Kim continue; 895aca7a94dSNamhyung Kim case 'n': 89605e8b080SArnaldo Carvalho de Melo if (browser->searching_backwards ? 89705e8b080SArnaldo Carvalho de Melo annotate_browser__continue_search_reverse(browser, delay_secs) : 89805e8b080SArnaldo Carvalho de Melo annotate_browser__continue_search(browser, delay_secs)) 899aca7a94dSNamhyung Kim goto show_help; 900aca7a94dSNamhyung Kim continue; 901aca7a94dSNamhyung Kim case '?': 90205e8b080SArnaldo Carvalho de Melo if (annotate_browser__search_reverse(browser, delay_secs)) 903aca7a94dSNamhyung Kim goto show_help; 904aca7a94dSNamhyung Kim continue; 905e9823b21SArnaldo Carvalho de Melo case 'D': { 906e9823b21SArnaldo Carvalho de Melo static int seq; 907e9823b21SArnaldo Carvalho de Melo ui_helpline__pop(); 908e9823b21SArnaldo Carvalho de Melo ui_helpline__fpush("%d: nr_ent=%d, height=%d, idx=%d, top_idx=%d, nr_asm_entries=%d", 90905e8b080SArnaldo Carvalho de Melo seq++, browser->b.nr_entries, 91005e8b080SArnaldo Carvalho de Melo browser->b.height, 91105e8b080SArnaldo Carvalho de Melo browser->b.index, 91205e8b080SArnaldo Carvalho de Melo browser->b.top_idx, 91305e8b080SArnaldo Carvalho de Melo browser->nr_asm_entries); 914e9823b21SArnaldo Carvalho de Melo } 915e9823b21SArnaldo Carvalho de Melo continue; 916aca7a94dSNamhyung Kim case K_ENTER: 917aca7a94dSNamhyung Kim case K_RIGHT: 9187bcbcd58SJiri Olsa { 9197bcbcd58SJiri Olsa struct disasm_line *dl = disasm_line(browser->selection); 9207bcbcd58SJiri Olsa 92105e8b080SArnaldo Carvalho de Melo if (browser->selection == NULL) 922aca7a94dSNamhyung Kim ui_helpline__puts("Huh? No selection. Report to linux-kernel@vger.kernel.org"); 9237bcbcd58SJiri Olsa else if (browser->selection->offset == -1) 924aca7a94dSNamhyung Kim ui_helpline__puts("Actions are only available for assembly lines."); 9257bcbcd58SJiri Olsa else if (!dl->ins.ops) 926c4cceae3SArnaldo Carvalho de Melo goto show_sup_ins; 9277bcbcd58SJiri Olsa else if (ins__is_ret(&dl->ins)) 928c4cceae3SArnaldo Carvalho de Melo goto out; 9296ef94929SNaveen N. Rao else if (!(annotate_browser__jump(browser) || 930db8fd07aSNamhyung Kim annotate_browser__callq(browser, evsel, hbt))) { 931c4cceae3SArnaldo Carvalho de Melo show_sup_ins: 9326ef94929SNaveen N. Rao ui_helpline__puts("Actions are only available for function call/return & jump/branch instructions."); 933c4cceae3SArnaldo Carvalho de Melo } 934aca7a94dSNamhyung Kim continue; 9357bcbcd58SJiri Olsa } 9360c4a5bceSMartin Liška case 't': 937*16932d77SArnaldo Carvalho de Melo if (notes->options->show_total_period) { 938*16932d77SArnaldo Carvalho de Melo notes->options->show_total_period = false; 939*16932d77SArnaldo Carvalho de Melo notes->options->show_nr_samples = true; 940*16932d77SArnaldo Carvalho de Melo } else if (notes->options->show_nr_samples) 941*16932d77SArnaldo Carvalho de Melo notes->options->show_nr_samples = false; 9423a555c77STaeung Song else 943*16932d77SArnaldo Carvalho de Melo notes->options->show_total_period = true; 9440c4a5bceSMartin Liška annotate_browser__update_addr_width(browser); 9450c4a5bceSMartin Liška continue; 946aca7a94dSNamhyung Kim case K_LEFT: 947aca7a94dSNamhyung Kim case K_ESC: 948aca7a94dSNamhyung Kim case 'q': 949aca7a94dSNamhyung Kim case CTRL('c'): 950aca7a94dSNamhyung Kim goto out; 951aca7a94dSNamhyung Kim default: 952aca7a94dSNamhyung Kim continue; 953aca7a94dSNamhyung Kim } 954aca7a94dSNamhyung Kim 955aca7a94dSNamhyung Kim if (nd != NULL) 95605e8b080SArnaldo Carvalho de Melo annotate_browser__set_rb_top(browser, nd); 957aca7a94dSNamhyung Kim } 958aca7a94dSNamhyung Kim out: 95905e8b080SArnaldo Carvalho de Melo ui_browser__hide(&browser->b); 960aca7a94dSNamhyung Kim return key; 961aca7a94dSNamhyung Kim } 962aca7a94dSNamhyung Kim 963d5dbc518SArnaldo Carvalho de Melo int map_symbol__tui_annotate(struct map_symbol *ms, struct perf_evsel *evsel, 964d5dbc518SArnaldo Carvalho de Melo struct hist_browser_timer *hbt) 965d5dbc518SArnaldo Carvalho de Melo { 9669cef4b0bSTaeung Song /* Set default value for show_total_period and show_nr_samples */ 9670c4a5bceSMartin Liška annotate_browser__opts.show_total_period = 9680c4a5bceSMartin Liška symbol_conf.show_total_period; 9699cef4b0bSTaeung Song annotate_browser__opts.show_nr_samples = 9709cef4b0bSTaeung Song symbol_conf.show_nr_samples; 9710c4a5bceSMartin Liška 972d5dbc518SArnaldo Carvalho de Melo return symbol__tui_annotate(ms->sym, ms->map, evsel, hbt); 973d5dbc518SArnaldo Carvalho de Melo } 974d5dbc518SArnaldo Carvalho de Melo 975db8fd07aSNamhyung Kim int hist_entry__tui_annotate(struct hist_entry *he, struct perf_evsel *evsel, 9769783adf7SNamhyung Kim struct hist_browser_timer *hbt) 977aca7a94dSNamhyung Kim { 978ed426915SNamhyung Kim /* reset abort key so that it can get Ctrl-C as a key */ 979ed426915SNamhyung Kim SLang_reset_tty(); 980ed426915SNamhyung Kim SLang_init_tty(0, 0, 0); 981ed426915SNamhyung Kim 982d5dbc518SArnaldo Carvalho de Melo return map_symbol__tui_annotate(&he->ms, evsel, hbt); 983aca7a94dSNamhyung Kim } 984aca7a94dSNamhyung Kim 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; 9919d6bb41dSArnaldo Carvalho de Melo struct annotation *notes = symbol__annotation(sym); 99232ae1efdSNamhyung Kim 99332ae1efdSNamhyung Kim /* PLT symbols contain external offsets */ 99432ae1efdSNamhyung Kim if (strstr(sym->name, "@plt")) 99532ae1efdSNamhyung Kim return; 996b793a401SArnaldo Carvalho de Melo 997b793a401SArnaldo Carvalho de Melo for (offset = 0; offset < size; ++offset) { 9989d6bb41dSArnaldo Carvalho de Melo struct annotation_line *al = notes->offsets[offset]; 999a5ef2702SJiri Olsa struct disasm_line *dl; 1000a5ef2702SJiri Olsa struct browser_line *blt; 1001b793a401SArnaldo Carvalho de Melo 1002e1b60b5bSJiri Olsa dl = disasm_line(al); 1003e1b60b5bSJiri Olsa 1004865c66c4SFrederik Deweerdt if (!disasm_line__is_valid_jump(dl, sym)) 1005b793a401SArnaldo Carvalho de Melo continue; 1006b793a401SArnaldo Carvalho de Melo 10079d6bb41dSArnaldo Carvalho de Melo al = notes->offsets[dl->ops.target.offset]; 1008e1b60b5bSJiri Olsa 10099481ede9SArnaldo Carvalho de Melo /* 10109481ede9SArnaldo Carvalho de Melo * FIXME: Oops, no jump target? Buggy disassembler? Or do we 10119481ede9SArnaldo Carvalho de Melo * have to adjust to the previous offset? 10129481ede9SArnaldo Carvalho de Melo */ 1013a5ef2702SJiri Olsa if (al == NULL) 10149481ede9SArnaldo Carvalho de Melo continue; 10159481ede9SArnaldo Carvalho de Melo 1016a5ef2702SJiri Olsa blt = browser_line(al); 1017a5ef2702SJiri Olsa if (++blt->jump_sources > browser->max_jump_sources) 1018a5ef2702SJiri Olsa browser->max_jump_sources = blt->jump_sources; 10192402e4a9SArnaldo Carvalho de Melo 10202402e4a9SArnaldo Carvalho de Melo ++browser->nr_jumps; 1021b793a401SArnaldo Carvalho de Melo } 1022b793a401SArnaldo Carvalho de Melo } 1023b793a401SArnaldo Carvalho de Melo 10242402e4a9SArnaldo Carvalho de Melo static inline int width_jumps(int n) 10252402e4a9SArnaldo Carvalho de Melo { 10262402e4a9SArnaldo Carvalho de Melo if (n >= 100) 10272402e4a9SArnaldo Carvalho de Melo return 5; 10282402e4a9SArnaldo Carvalho de Melo if (n / 10) 10292402e4a9SArnaldo Carvalho de Melo return 2; 10302402e4a9SArnaldo Carvalho de Melo return 1; 10312402e4a9SArnaldo Carvalho de Melo } 10322402e4a9SArnaldo Carvalho de Melo 1033db8fd07aSNamhyung Kim int symbol__tui_annotate(struct symbol *sym, struct map *map, 1034db8fd07aSNamhyung Kim struct perf_evsel *evsel, 10359783adf7SNamhyung Kim struct hist_browser_timer *hbt) 1036aca7a94dSNamhyung Kim { 1037e1b60b5bSJiri Olsa struct annotation_line *al; 10389d6bb41dSArnaldo Carvalho de Melo struct annotation *notes = symbol__annotation(sym); 1039c0a58fb2SSamuel Liao size_t size; 1040aca7a94dSNamhyung Kim struct map_symbol ms = { 1041aca7a94dSNamhyung Kim .map = map, 1042aca7a94dSNamhyung Kim .sym = sym, 1043aca7a94dSNamhyung Kim }; 1044aca7a94dSNamhyung Kim struct annotate_browser browser = { 1045aca7a94dSNamhyung Kim .b = { 1046a3f895beSArnaldo Carvalho de Melo .refresh = annotate_browser__refresh, 1047aca7a94dSNamhyung Kim .seek = ui_browser__list_head_seek, 1048aca7a94dSNamhyung Kim .write = annotate_browser__write, 104929ed6e76SArnaldo Carvalho de Melo .filter = disasm_line__filter, 1050aca7a94dSNamhyung Kim .priv = &ms, 1051aca7a94dSNamhyung Kim .use_navkeypressed = true, 1052aca7a94dSNamhyung Kim }, 1053aca7a94dSNamhyung Kim }; 1054ee51d851SArnaldo Carvalho de Melo int ret = -1, err; 1055c7e7b610SNamhyung Kim int nr_pcnt = 1; 1056aca7a94dSNamhyung Kim 1057aca7a94dSNamhyung Kim if (sym == NULL) 1058aca7a94dSNamhyung Kim return -1; 1059aca7a94dSNamhyung Kim 1060c0a58fb2SSamuel Liao size = symbol__size(sym); 1061c0a58fb2SSamuel Liao 1062aca7a94dSNamhyung Kim if (map->dso->annotate_warned) 1063aca7a94dSNamhyung Kim return -1; 1064aca7a94dSNamhyung Kim 1065*16932d77SArnaldo Carvalho de Melo notes->options = &annotate_browser__opts; 1066*16932d77SArnaldo Carvalho de Melo 10679d6bb41dSArnaldo Carvalho de Melo notes->offsets = zalloc(size * sizeof(struct annotation_line *)); 10689d6bb41dSArnaldo Carvalho de Melo if (notes->offsets == NULL) { 1069b793a401SArnaldo Carvalho de Melo ui__error("Not enough memory!"); 1070b793a401SArnaldo Carvalho de Melo return -1; 1071b793a401SArnaldo Carvalho de Melo } 1072b793a401SArnaldo Carvalho de Melo 10733ab6db8dSJiri Olsa if (perf_evsel__is_group_event(evsel)) 1074c7e7b610SNamhyung Kim nr_pcnt = evsel->nr_members; 1075c7e7b610SNamhyung Kim 10765449f13cSArnaldo Carvalho de Melo err = symbol__annotate(sym, map, evsel, sizeof(struct browser_line), &browser.arch); 1077ee51d851SArnaldo Carvalho de Melo if (err) { 1078ee51d851SArnaldo Carvalho de Melo char msg[BUFSIZ]; 1079ee51d851SArnaldo Carvalho de Melo symbol__strerror_disassemble(sym, map, err, msg, sizeof(msg)); 1080ee51d851SArnaldo Carvalho de Melo ui__error("Couldn't annotate %s:\n%s", sym->name, msg); 1081b793a401SArnaldo Carvalho de Melo goto out_free_offsets; 1082aca7a94dSNamhyung Kim } 1083aca7a94dSNamhyung Kim 108405d3f1a1SJiri Olsa symbol__calc_percent(sym, evsel); 108505d3f1a1SJiri Olsa 10867727a925SArnaldo Carvalho de Melo ui_helpline__push("Press ESC to exit"); 1087aca7a94dSNamhyung Kim 1088aca7a94dSNamhyung Kim browser.start = map__rip_2objdump(map, sym->start); 1089aca7a94dSNamhyung Kim 1090e1b60b5bSJiri Olsa list_for_each_entry(al, ¬es->src->source, node) { 10910d957970SJiri Olsa struct browser_line *bpos; 1092e1b60b5bSJiri Olsa size_t line_len = strlen(al->line); 1093aca7a94dSNamhyung Kim 1094aca7a94dSNamhyung Kim if (browser.b.width < line_len) 1095aca7a94dSNamhyung Kim browser.b.width = line_len; 1096a5ef2702SJiri Olsa bpos = browser_line(al); 1097887c0066SArnaldo Carvalho de Melo bpos->idx = browser.nr_entries++; 1098e1b60b5bSJiri Olsa if (al->offset != -1) { 1099887c0066SArnaldo Carvalho de Melo bpos->idx_asm = browser.nr_asm_entries++; 110097148a97SArnaldo Carvalho de Melo /* 110197148a97SArnaldo Carvalho de Melo * FIXME: short term bandaid to cope with assembly 110297148a97SArnaldo Carvalho de Melo * routines that comes with labels in the same column 110397148a97SArnaldo Carvalho de Melo * as the address in objdump, sigh. 110497148a97SArnaldo Carvalho de Melo * 110597148a97SArnaldo Carvalho de Melo * E.g. copy_user_generic_unrolled 110697148a97SArnaldo Carvalho de Melo */ 1107e1b60b5bSJiri Olsa if (al->offset < (s64)size) 11089d6bb41dSArnaldo Carvalho de Melo notes->offsets[al->offset] = al; 1109b793a401SArnaldo Carvalho de Melo } else 1110887c0066SArnaldo Carvalho de Melo bpos->idx_asm = -1; 1111aca7a94dSNamhyung Kim } 1112aca7a94dSNamhyung Kim 1113b793a401SArnaldo Carvalho de Melo annotate_browser__mark_jump_targets(&browser, size); 1114f56c083bSArnaldo Carvalho de Melo annotation__compute_ipc(notes, size); 1115b793a401SArnaldo Carvalho de Melo 11162402e4a9SArnaldo Carvalho de Melo browser.addr_width = browser.target_width = browser.min_addr_width = hex_width(size); 111783b1f2aaSArnaldo Carvalho de Melo browser.max_addr_width = hex_width(sym->end); 11182402e4a9SArnaldo Carvalho de Melo browser.jumps_width = width_jumps(browser.max_jump_sources); 11190553e83dSArnaldo Carvalho de Melo notes->nr_events = nr_pcnt; 1120aca7a94dSNamhyung Kim browser.b.nr_entries = browser.nr_entries; 1121aca7a94dSNamhyung Kim browser.b.entries = ¬es->src->source, 1122aca7a94dSNamhyung Kim browser.b.width += 18; /* Percentage */ 1123e9823b21SArnaldo Carvalho de Melo 1124*16932d77SArnaldo Carvalho de Melo if (notes->options->hide_src_code) 1125e9823b21SArnaldo Carvalho de Melo annotate_browser__init_asm_mode(&browser); 1126e9823b21SArnaldo Carvalho de Melo 1127e9823b21SArnaldo Carvalho de Melo annotate_browser__update_addr_width(&browser); 1128e9823b21SArnaldo Carvalho de Melo 1129db8fd07aSNamhyung Kim ret = annotate_browser__run(&browser, evsel, hbt); 1130f8eb37bdSJiri Olsa 1131f8eb37bdSJiri Olsa annotated_source__purge(notes->src); 1132b793a401SArnaldo Carvalho de Melo 1133b793a401SArnaldo Carvalho de Melo out_free_offsets: 11349d6bb41dSArnaldo Carvalho de Melo zfree(¬es->offsets); 1135aca7a94dSNamhyung Kim return ret; 1136aca7a94dSNamhyung Kim } 1137c323cf04SArnaldo Carvalho de Melo 1138c323cf04SArnaldo Carvalho de Melo #define ANNOTATE_CFG(n) \ 1139c323cf04SArnaldo Carvalho de Melo { .name = #n, .value = &annotate_browser__opts.n, } 1140c323cf04SArnaldo Carvalho de Melo 1141c323cf04SArnaldo Carvalho de Melo /* 1142c323cf04SArnaldo Carvalho de Melo * Keep the entries sorted, they are bsearch'ed 1143c323cf04SArnaldo Carvalho de Melo */ 11447c3102b8SArnaldo Carvalho de Melo static struct annotate_config { 1145c323cf04SArnaldo Carvalho de Melo const char *name; 1146c323cf04SArnaldo Carvalho de Melo bool *value; 1147c323cf04SArnaldo Carvalho de Melo } annotate__configs[] = { 1148c323cf04SArnaldo Carvalho de Melo ANNOTATE_CFG(hide_src_code), 1149c323cf04SArnaldo Carvalho de Melo ANNOTATE_CFG(jump_arrows), 1150e592488cSAndi Kleen ANNOTATE_CFG(show_linenr), 1151c323cf04SArnaldo Carvalho de Melo ANNOTATE_CFG(show_nr_jumps), 11529cef4b0bSTaeung Song ANNOTATE_CFG(show_nr_samples), 11530c4a5bceSMartin Liška ANNOTATE_CFG(show_total_period), 115439ff7cdbSNamhyung Kim ANNOTATE_CFG(use_offset), 1155c323cf04SArnaldo Carvalho de Melo }; 1156c323cf04SArnaldo Carvalho de Melo 1157c323cf04SArnaldo Carvalho de Melo #undef ANNOTATE_CFG 1158c323cf04SArnaldo Carvalho de Melo 1159c323cf04SArnaldo Carvalho de Melo static int annotate_config__cmp(const void *name, const void *cfgp) 1160c323cf04SArnaldo Carvalho de Melo { 11617c3102b8SArnaldo Carvalho de Melo const struct annotate_config *cfg = cfgp; 1162c323cf04SArnaldo Carvalho de Melo 1163c323cf04SArnaldo Carvalho de Melo return strcmp(name, cfg->name); 1164c323cf04SArnaldo Carvalho de Melo } 1165c323cf04SArnaldo Carvalho de Melo 11661d037ca1SIrina Tirdea static int annotate__config(const char *var, const char *value, 11671d037ca1SIrina Tirdea void *data __maybe_unused) 1168c323cf04SArnaldo Carvalho de Melo { 11697c3102b8SArnaldo Carvalho de Melo struct annotate_config *cfg; 1170c323cf04SArnaldo Carvalho de Melo const char *name; 1171c323cf04SArnaldo Carvalho de Melo 11728e99b6d4SArnaldo Carvalho de Melo if (!strstarts(var, "annotate.")) 1173c323cf04SArnaldo Carvalho de Melo return 0; 1174c323cf04SArnaldo Carvalho de Melo 1175c323cf04SArnaldo Carvalho de Melo name = var + 9; 1176c323cf04SArnaldo Carvalho de Melo cfg = bsearch(name, annotate__configs, ARRAY_SIZE(annotate__configs), 11777c3102b8SArnaldo Carvalho de Melo sizeof(struct annotate_config), annotate_config__cmp); 1178c323cf04SArnaldo Carvalho de Melo 1179c323cf04SArnaldo Carvalho de Melo if (cfg == NULL) 1180f06cff7cSArnaldo Carvalho de Melo ui__warning("%s variable unknown, ignoring...", var); 1181f06cff7cSArnaldo Carvalho de Melo else 1182c323cf04SArnaldo Carvalho de Melo *cfg->value = perf_config_bool(name, value); 1183c323cf04SArnaldo Carvalho de Melo return 0; 1184c323cf04SArnaldo Carvalho de Melo } 1185c323cf04SArnaldo Carvalho de Melo 1186c323cf04SArnaldo Carvalho de Melo void annotate_browser__init(void) 1187c323cf04SArnaldo Carvalho de Melo { 1188c323cf04SArnaldo Carvalho de Melo perf_config(annotate__config, NULL); 1189c323cf04SArnaldo Carvalho de Melo } 1190