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; 44c7e7b610SNamhyung Kim int nr_events; 45aca7a94dSNamhyung Kim u64 start; 46aca7a94dSNamhyung Kim int nr_asm_entries; 47aca7a94dSNamhyung Kim int nr_entries; 482402e4a9SArnaldo Carvalho de Melo int max_jump_sources; 492402e4a9SArnaldo Carvalho de Melo int nr_jumps; 50aca7a94dSNamhyung Kim bool searching_backwards; 5183b1f2aaSArnaldo Carvalho de Melo u8 addr_width; 522402e4a9SArnaldo Carvalho de Melo u8 jumps_width; 532402e4a9SArnaldo Carvalho de Melo u8 target_width; 5483b1f2aaSArnaldo Carvalho de Melo u8 min_addr_width; 5583b1f2aaSArnaldo Carvalho de Melo u8 max_addr_width; 56aca7a94dSNamhyung Kim char search_bf[128]; 57aca7a94dSNamhyung Kim }; 58aca7a94dSNamhyung Kim 59a5ef2702SJiri Olsa static inline struct browser_line *browser_line(struct annotation_line *al) 60aca7a94dSNamhyung Kim { 61a5ef2702SJiri Olsa void *ptr = al; 62a5ef2702SJiri Olsa 63a5ef2702SJiri Olsa ptr = container_of(al, struct disasm_line, al); 64a5ef2702SJiri Olsa return ptr - sizeof(struct browser_line); 65aca7a94dSNamhyung Kim } 66aca7a94dSNamhyung Kim 671d037ca1SIrina Tirdea static bool disasm_line__filter(struct ui_browser *browser __maybe_unused, 681d037ca1SIrina Tirdea void *entry) 69aca7a94dSNamhyung Kim { 70e9823b21SArnaldo Carvalho de Melo if (annotate_browser__opts.hide_src_code) { 71d5490b96SJiri Olsa struct annotation_line *al = list_entry(entry, struct annotation_line, node); 72d5490b96SJiri Olsa 73d5490b96SJiri Olsa return al->offset == -1; 74aca7a94dSNamhyung Kim } 75aca7a94dSNamhyung Kim 76aca7a94dSNamhyung Kim return false; 77aca7a94dSNamhyung Kim } 78aca7a94dSNamhyung Kim 792402e4a9SArnaldo Carvalho de Melo static int annotate_browser__jumps_percent_color(struct annotate_browser *browser, 802402e4a9SArnaldo Carvalho de Melo int nr, bool current) 812402e4a9SArnaldo Carvalho de Melo { 822402e4a9SArnaldo Carvalho de Melo if (current && (!browser->b.use_navkeypressed || browser->b.navkeypressed)) 832402e4a9SArnaldo Carvalho de Melo return HE_COLORSET_SELECTED; 842402e4a9SArnaldo Carvalho de Melo if (nr == browser->max_jump_sources) 852402e4a9SArnaldo Carvalho de Melo return HE_COLORSET_TOP; 862402e4a9SArnaldo Carvalho de Melo if (nr > 1) 872402e4a9SArnaldo Carvalho de Melo return HE_COLORSET_MEDIUM; 882402e4a9SArnaldo Carvalho de Melo return HE_COLORSET_NORMAL; 892402e4a9SArnaldo Carvalho de Melo } 902402e4a9SArnaldo Carvalho de Melo 912402e4a9SArnaldo Carvalho de Melo static int annotate_browser__set_jumps_percent_color(struct annotate_browser *browser, 922402e4a9SArnaldo Carvalho de Melo int nr, bool current) 932402e4a9SArnaldo Carvalho de Melo { 942402e4a9SArnaldo Carvalho de Melo int color = annotate_browser__jumps_percent_color(browser, nr, current); 952402e4a9SArnaldo Carvalho de Melo return ui_browser__set_color(&browser->b, color); 962402e4a9SArnaldo Carvalho de Melo } 972402e4a9SArnaldo Carvalho de Melo 98f8f4aaeaSAndi Kleen static int annotate_browser__pcnt_width(struct annotate_browser *ab) 99f8f4aaeaSAndi Kleen { 1003861c4a4SArnaldo Carvalho de Melo return (annotate_browser__opts.show_total_period ? 12 : 7) * ab->nr_events; 101bc1e5d60SArnaldo Carvalho de Melo } 102f8f4aaeaSAndi Kleen 103a5433b3eSJiri Olsa static void disasm_line__write(struct disasm_line *dl, struct ui_browser *browser, 104a5433b3eSJiri Olsa char *bf, size_t size) 105aca7a94dSNamhyung Kim { 10675b49202SArnaldo Carvalho de Melo if (dl->ins.ops && dl->ins.ops->scnprintf) { 10775b49202SArnaldo Carvalho de Melo if (ins__is_jump(&dl->ins)) { 108d5490b96SJiri Olsa bool fwd = dl->ops.target.offset > dl->al.offset; 10951a0d455SArnaldo Carvalho de Melo 11005e8b080SArnaldo Carvalho de Melo ui_browser__write_graph(browser, fwd ? SLSMG_DARROW_CHAR : 11151a0d455SArnaldo Carvalho de Melo SLSMG_UARROW_CHAR); 11251a0d455SArnaldo Carvalho de Melo SLsmg_write_char(' '); 11375b49202SArnaldo Carvalho de Melo } else if (ins__is_call(&dl->ins)) { 11405e8b080SArnaldo Carvalho de Melo ui_browser__write_graph(browser, SLSMG_RARROW_CHAR); 11588298f5aSArnaldo Carvalho de Melo SLsmg_write_char(' '); 11675b49202SArnaldo Carvalho de Melo } else if (ins__is_ret(&dl->ins)) { 11705e8b080SArnaldo Carvalho de Melo ui_browser__write_graph(browser, SLSMG_LARROW_CHAR); 1184ea08b52SArnaldo Carvalho de Melo SLsmg_write_char(' '); 1196ef94929SNaveen N. Rao } else { 1206ef94929SNaveen N. Rao ui_browser__write_nstring(browser, " ", 2); 1214ea08b52SArnaldo Carvalho de Melo } 1226ef94929SNaveen N. Rao } else { 1236ef94929SNaveen N. Rao ui_browser__write_nstring(browser, " ", 2); 1244ea08b52SArnaldo Carvalho de Melo } 1254ea08b52SArnaldo Carvalho de Melo 126a5433b3eSJiri Olsa disasm_line__scnprintf(dl, bf, size, !annotate_browser__opts.use_offset); 127a5433b3eSJiri Olsa } 128a5433b3eSJiri Olsa 129a5433b3eSJiri Olsa static void annotate_browser__write(struct ui_browser *browser, void *entry, int row) 130a5433b3eSJiri Olsa { 131a5433b3eSJiri Olsa struct annotate_browser *ab = container_of(browser, struct annotate_browser, b); 1320e83a7e9SArnaldo Carvalho de Melo struct map_symbol *ms = browser->priv; 1330e83a7e9SArnaldo Carvalho de Melo struct symbol *sym = ms->sym; 1340e83a7e9SArnaldo Carvalho de Melo struct annotation *notes = symbol__annotation(sym); 135a5433b3eSJiri Olsa struct annotation_line *al = list_entry(entry, struct annotation_line, node); 136a5433b3eSJiri Olsa struct browser_line *bl = browser_line(al); 137a5433b3eSJiri Olsa bool current_entry = ui_browser__is_current_entry(browser, row); 138a5433b3eSJiri Olsa bool change_color = (!annotate_browser__opts.hide_src_code && 139a5433b3eSJiri Olsa (!current_entry || (browser->use_navkeypressed && 140a5433b3eSJiri Olsa !browser->navkeypressed))); 141a5433b3eSJiri Olsa int width = browser->width, printed; 142a5433b3eSJiri Olsa int i, pcnt_width = annotate_browser__pcnt_width(ab), 1430e83a7e9SArnaldo Carvalho de Melo cycles_width = annotation__cycles_width(notes); 144a5433b3eSJiri Olsa double percent_max = 0.0; 145a5433b3eSJiri Olsa char bf[256]; 146a5433b3eSJiri Olsa bool show_title = false; 147a5433b3eSJiri Olsa 148a5433b3eSJiri Olsa for (i = 0; i < ab->nr_events; i++) { 149a5433b3eSJiri Olsa if (al->samples[i].percent > percent_max) 150a5433b3eSJiri Olsa percent_max = al->samples[i].percent; 151a5433b3eSJiri Olsa } 152a5433b3eSJiri Olsa 153a5433b3eSJiri Olsa if ((row == 0) && (al->offset == -1 || percent_max == 0.0)) { 1540e83a7e9SArnaldo Carvalho de Melo if (notes->have_cycles) { 155a5433b3eSJiri Olsa if (al->ipc == 0.0 && al->cycles == 0) 156a5433b3eSJiri Olsa show_title = true; 157a5433b3eSJiri Olsa } else 158a5433b3eSJiri Olsa show_title = true; 159a5433b3eSJiri Olsa } 160a5433b3eSJiri Olsa 161a5433b3eSJiri Olsa if (al->offset != -1 && percent_max != 0.0) { 162a5433b3eSJiri Olsa for (i = 0; i < ab->nr_events; i++) { 163a5433b3eSJiri Olsa ui_browser__set_percent_color(browser, 164a5433b3eSJiri Olsa al->samples[i].percent, 165a5433b3eSJiri Olsa current_entry); 166a5433b3eSJiri Olsa if (annotate_browser__opts.show_total_period) { 167a5433b3eSJiri Olsa ui_browser__printf(browser, "%11" PRIu64 " ", 168a5433b3eSJiri Olsa al->samples[i].he.period); 169a5433b3eSJiri Olsa } else if (annotate_browser__opts.show_nr_samples) { 170a5433b3eSJiri Olsa ui_browser__printf(browser, "%6" PRIu64 " ", 171a5433b3eSJiri Olsa al->samples[i].he.nr_samples); 172a5433b3eSJiri Olsa } else { 173a5433b3eSJiri Olsa ui_browser__printf(browser, "%6.2f ", 174a5433b3eSJiri Olsa al->samples[i].percent); 175a5433b3eSJiri Olsa } 176a5433b3eSJiri Olsa } 177a5433b3eSJiri Olsa } else { 178a5433b3eSJiri Olsa ui_browser__set_percent_color(browser, 0, current_entry); 179a5433b3eSJiri Olsa 180a5433b3eSJiri Olsa if (!show_title) 181a5433b3eSJiri Olsa ui_browser__write_nstring(browser, " ", pcnt_width); 182a5433b3eSJiri Olsa else { 183a5433b3eSJiri Olsa ui_browser__printf(browser, "%*s", pcnt_width, 184a5433b3eSJiri Olsa annotate_browser__opts.show_total_period ? "Period" : 185a5433b3eSJiri Olsa annotate_browser__opts.show_nr_samples ? "Samples" : "Percent"); 186a5433b3eSJiri Olsa } 187a5433b3eSJiri Olsa } 1880e83a7e9SArnaldo Carvalho de Melo if (notes->have_cycles) { 189a5433b3eSJiri Olsa if (al->ipc) 190c426e584SArnaldo Carvalho de Melo ui_browser__printf(browser, "%*.2f ", ANNOTATION__IPC_WIDTH - 1, al->ipc); 191a5433b3eSJiri Olsa else if (!show_title) 192c426e584SArnaldo Carvalho de Melo ui_browser__write_nstring(browser, " ", ANNOTATION__IPC_WIDTH); 193a5433b3eSJiri Olsa else 194c426e584SArnaldo Carvalho de Melo ui_browser__printf(browser, "%*s ", ANNOTATION__IPC_WIDTH - 1, "IPC"); 195a5433b3eSJiri Olsa 196a5433b3eSJiri Olsa if (al->cycles) 197a5433b3eSJiri Olsa ui_browser__printf(browser, "%*" PRIu64 " ", 198c426e584SArnaldo Carvalho de Melo ANNOTATION__CYCLES_WIDTH - 1, al->cycles); 199a5433b3eSJiri Olsa else if (!show_title) 200c426e584SArnaldo Carvalho de Melo ui_browser__write_nstring(browser, " ", ANNOTATION__CYCLES_WIDTH); 201a5433b3eSJiri Olsa else 202c426e584SArnaldo Carvalho de Melo ui_browser__printf(browser, "%*s ", ANNOTATION__CYCLES_WIDTH - 1, "Cycle"); 203a5433b3eSJiri Olsa } 204a5433b3eSJiri Olsa 205a5433b3eSJiri Olsa SLsmg_write_char(' '); 206a5433b3eSJiri Olsa 207a5433b3eSJiri Olsa /* The scroll bar isn't being used */ 208a5433b3eSJiri Olsa if (!browser->navkeypressed) 209a5433b3eSJiri Olsa width += 1; 210a5433b3eSJiri Olsa 211a5433b3eSJiri Olsa if (!*al->line) 212a5433b3eSJiri Olsa ui_browser__write_nstring(browser, " ", width - pcnt_width - cycles_width); 213a5433b3eSJiri Olsa else if (al->offset == -1) { 214a5433b3eSJiri Olsa if (al->line_nr && annotate_browser__opts.show_linenr) 215a5433b3eSJiri Olsa printed = scnprintf(bf, sizeof(bf), "%-*d ", 216a5433b3eSJiri Olsa ab->addr_width + 1, al->line_nr); 217a5433b3eSJiri Olsa else 218a5433b3eSJiri Olsa printed = scnprintf(bf, sizeof(bf), "%*s ", 219a5433b3eSJiri Olsa ab->addr_width, " "); 220a5433b3eSJiri Olsa ui_browser__write_nstring(browser, bf, printed); 221a5433b3eSJiri Olsa ui_browser__write_nstring(browser, al->line, width - printed - pcnt_width - cycles_width + 1); 222a5433b3eSJiri Olsa } else { 223a5433b3eSJiri Olsa u64 addr = al->offset; 224a5433b3eSJiri Olsa int color = -1; 225a5433b3eSJiri Olsa 226a5433b3eSJiri Olsa if (!annotate_browser__opts.use_offset) 227a5433b3eSJiri Olsa addr += ab->start; 228a5433b3eSJiri Olsa 229a5433b3eSJiri Olsa if (!annotate_browser__opts.use_offset) { 230a5433b3eSJiri Olsa printed = scnprintf(bf, sizeof(bf), "%" PRIx64 ": ", addr); 231a5433b3eSJiri Olsa } else { 232a5433b3eSJiri Olsa if (bl->jump_sources) { 233a5433b3eSJiri Olsa if (annotate_browser__opts.show_nr_jumps) { 234a5433b3eSJiri Olsa int prev; 235a5433b3eSJiri Olsa printed = scnprintf(bf, sizeof(bf), "%*d ", 236a5433b3eSJiri Olsa ab->jumps_width, 237a5433b3eSJiri Olsa bl->jump_sources); 238a5433b3eSJiri Olsa prev = annotate_browser__set_jumps_percent_color(ab, bl->jump_sources, 239a5433b3eSJiri Olsa current_entry); 240a5433b3eSJiri Olsa ui_browser__write_nstring(browser, bf, printed); 241a5433b3eSJiri Olsa ui_browser__set_color(browser, prev); 242a5433b3eSJiri Olsa } 243a5433b3eSJiri Olsa 244a5433b3eSJiri Olsa printed = scnprintf(bf, sizeof(bf), "%*" PRIx64 ": ", 245a5433b3eSJiri Olsa ab->target_width, addr); 246a5433b3eSJiri Olsa } else { 247a5433b3eSJiri Olsa printed = scnprintf(bf, sizeof(bf), "%*s ", 248a5433b3eSJiri Olsa ab->addr_width, " "); 249a5433b3eSJiri Olsa } 250a5433b3eSJiri Olsa } 251a5433b3eSJiri Olsa 252a5433b3eSJiri Olsa if (change_color) 253a5433b3eSJiri Olsa color = ui_browser__set_color(browser, HE_COLORSET_ADDR); 254a5433b3eSJiri Olsa ui_browser__write_nstring(browser, bf, printed); 255a5433b3eSJiri Olsa if (change_color) 256a5433b3eSJiri Olsa ui_browser__set_color(browser, color); 257a5433b3eSJiri Olsa 258a5433b3eSJiri Olsa disasm_line__write(disasm_line(al), browser, bf, sizeof(bf)); 259a5433b3eSJiri Olsa 260bc1e5d60SArnaldo Carvalho de Melo ui_browser__write_nstring(browser, bf, width - pcnt_width - cycles_width - 3 - printed); 261aca7a94dSNamhyung Kim } 262aca7a94dSNamhyung Kim 263aca7a94dSNamhyung Kim if (current_entry) 264a5433b3eSJiri Olsa ab->selection = al; 265aca7a94dSNamhyung Kim } 266aca7a94dSNamhyung Kim 267865c66c4SFrederik Deweerdt static bool disasm_line__is_valid_jump(struct disasm_line *dl, struct symbol *sym) 268865c66c4SFrederik Deweerdt { 26975b49202SArnaldo Carvalho de Melo if (!dl || !dl->ins.ops || !ins__is_jump(&dl->ins) 270865c66c4SFrederik Deweerdt || !disasm_line__has_offset(dl) 271e216874cSRavi Bangoria || dl->ops.target.offset < 0 272e216874cSRavi Bangoria || dl->ops.target.offset >= (s64)symbol__size(sym)) 273865c66c4SFrederik Deweerdt return false; 274865c66c4SFrederik Deweerdt 275865c66c4SFrederik Deweerdt return true; 276865c66c4SFrederik Deweerdt } 277865c66c4SFrederik Deweerdt 2787e63a13aSJin Yao static bool is_fused(struct annotate_browser *ab, struct disasm_line *cursor) 2797e63a13aSJin Yao { 280a17c4ca0SJiri Olsa struct disasm_line *pos = list_prev_entry(cursor, al.node); 2817e63a13aSJin Yao const char *name; 2827e63a13aSJin Yao 2837e63a13aSJin Yao if (!pos) 2847e63a13aSJin Yao return false; 2857e63a13aSJin Yao 2867e63a13aSJin Yao if (ins__is_lock(&pos->ins)) 2877e63a13aSJin Yao name = pos->ops.locked.ins.name; 2887e63a13aSJin Yao else 2897e63a13aSJin Yao name = pos->ins.name; 2907e63a13aSJin Yao 2917e63a13aSJin Yao if (!name || !cursor->ins.name) 2927e63a13aSJin Yao return false; 2937e63a13aSJin Yao 2947e63a13aSJin Yao return ins__is_fused(ab->arch, name, cursor->ins.name); 2957e63a13aSJin Yao } 2967e63a13aSJin Yao 2979d1ef56dSArnaldo Carvalho de Melo static void annotate_browser__draw_current_jump(struct ui_browser *browser) 298a3f895beSArnaldo Carvalho de Melo { 299a3f895beSArnaldo Carvalho de Melo struct annotate_browser *ab = container_of(browser, struct annotate_browser, b); 3007bcbcd58SJiri Olsa struct disasm_line *cursor = disasm_line(ab->selection); 301a5ef2702SJiri Olsa struct annotation_line *target; 3020d957970SJiri Olsa struct browser_line *btarget, *bcursor; 30383b1f2aaSArnaldo Carvalho de Melo unsigned int from, to; 30432ae1efdSNamhyung Kim struct map_symbol *ms = ab->b.priv; 30532ae1efdSNamhyung Kim struct symbol *sym = ms->sym; 3060e83a7e9SArnaldo Carvalho de Melo struct annotation *notes = symbol__annotation(sym); 307f8f4aaeaSAndi Kleen u8 pcnt_width = annotate_browser__pcnt_width(ab); 30800ea0eb2SArnaldo Carvalho de Melo int width; 30932ae1efdSNamhyung Kim 31032ae1efdSNamhyung Kim /* PLT symbols contain external offsets */ 31132ae1efdSNamhyung Kim if (strstr(sym->name, "@plt")) 31232ae1efdSNamhyung Kim return; 313a3f895beSArnaldo Carvalho de Melo 314865c66c4SFrederik Deweerdt if (!disasm_line__is_valid_jump(cursor, sym)) 315a3f895beSArnaldo Carvalho de Melo return; 316a3f895beSArnaldo Carvalho de Melo 3179c04409dSArnaldo Carvalho de Melo /* 3189c04409dSArnaldo Carvalho de Melo * This first was seen with a gcc function, _cpp_lex_token, that 3199c04409dSArnaldo Carvalho de Melo * has the usual jumps: 3209c04409dSArnaldo Carvalho de Melo * 3219c04409dSArnaldo Carvalho de Melo * │1159e6c: ↓ jne 115aa32 <_cpp_lex_token@@Base+0xf92> 3229c04409dSArnaldo Carvalho de Melo * 3239c04409dSArnaldo Carvalho de Melo * I.e. jumps to a label inside that function (_cpp_lex_token), and 3249c04409dSArnaldo Carvalho de Melo * those works, but also this kind: 3259c04409dSArnaldo Carvalho de Melo * 3269c04409dSArnaldo Carvalho de Melo * │1159e8b: ↓ jne c469be <cpp_named_operator2name@@Base+0xa72> 3279c04409dSArnaldo Carvalho de Melo * 3289c04409dSArnaldo Carvalho de Melo * I.e. jumps to another function, outside _cpp_lex_token, which 3299c04409dSArnaldo Carvalho de Melo * are not being correctly handled generating as a side effect references 3309c04409dSArnaldo Carvalho de Melo * to ab->offset[] entries that are set to NULL, so to make this code 3319c04409dSArnaldo Carvalho de Melo * more robust, check that here. 3329c04409dSArnaldo Carvalho de Melo * 3339c04409dSArnaldo Carvalho de Melo * A proper fix for will be put in place, looking at the function 3349c04409dSArnaldo Carvalho de Melo * name right after the '<' token and probably treating this like a 3359c04409dSArnaldo Carvalho de Melo * 'call' instruction. 3369c04409dSArnaldo Carvalho de Melo */ 3379d6bb41dSArnaldo Carvalho de Melo target = notes->offsets[cursor->ops.target.offset]; 3389c04409dSArnaldo Carvalho de Melo if (target == NULL) { 3399d6bb41dSArnaldo Carvalho de Melo ui_helpline__printf("WARN: jump target inconsistency, press 'o', notes->offsets[%#x] = NULL\n", 3409c04409dSArnaldo Carvalho de Melo cursor->ops.target.offset); 3419c04409dSArnaldo Carvalho de Melo return; 3429c04409dSArnaldo Carvalho de Melo } 3439d1ef56dSArnaldo Carvalho de Melo 344a5ef2702SJiri Olsa bcursor = browser_line(&cursor->al); 345daf25d43SJiri Olsa btarget = browser_line(target); 3469d1ef56dSArnaldo Carvalho de Melo 347e9823b21SArnaldo Carvalho de Melo if (annotate_browser__opts.hide_src_code) { 3489d1ef56dSArnaldo Carvalho de Melo from = bcursor->idx_asm; 349a3f895beSArnaldo Carvalho de Melo to = btarget->idx_asm; 350a3f895beSArnaldo Carvalho de Melo } else { 3519d1ef56dSArnaldo Carvalho de Melo from = (u64)bcursor->idx; 352a3f895beSArnaldo Carvalho de Melo to = (u64)btarget->idx; 353a3f895beSArnaldo Carvalho de Melo } 354a3f895beSArnaldo Carvalho de Melo 3550e83a7e9SArnaldo Carvalho de Melo width = annotation__cycles_width(notes); 356b40982e8SJin Yao 35778ce08dfSTaeung Song ui_browser__set_color(browser, HE_COLORSET_JUMP_ARROWS); 358b40982e8SJin Yao __ui_browser__line_arrow(browser, 359b40982e8SJin Yao pcnt_width + 2 + ab->addr_width + width, 360c7e7b610SNamhyung Kim from, to); 3617e63a13aSJin Yao 3627e63a13aSJin Yao if (is_fused(ab, cursor)) { 3637e63a13aSJin Yao ui_browser__mark_fused(browser, 364b40982e8SJin Yao pcnt_width + 3 + ab->addr_width + width, 3657e63a13aSJin Yao from - 1, 3667e63a13aSJin Yao to > from ? true : false); 3677e63a13aSJin Yao } 368a3f895beSArnaldo Carvalho de Melo } 369a3f895beSArnaldo Carvalho de Melo 370a3f895beSArnaldo Carvalho de Melo static unsigned int annotate_browser__refresh(struct ui_browser *browser) 371a3f895beSArnaldo Carvalho de Melo { 372c7e7b610SNamhyung Kim struct annotate_browser *ab = container_of(browser, struct annotate_browser, b); 373a3f895beSArnaldo Carvalho de Melo int ret = ui_browser__list_head_refresh(browser); 374f8f4aaeaSAndi Kleen int pcnt_width = annotate_browser__pcnt_width(ab); 375a3f895beSArnaldo Carvalho de Melo 376e9823b21SArnaldo Carvalho de Melo if (annotate_browser__opts.jump_arrows) 3779d1ef56dSArnaldo Carvalho de Melo annotate_browser__draw_current_jump(browser); 378a3f895beSArnaldo Carvalho de Melo 37983b1f2aaSArnaldo Carvalho de Melo ui_browser__set_color(browser, HE_COLORSET_NORMAL); 380c7e7b610SNamhyung Kim __ui_browser__vline(browser, pcnt_width, 0, browser->height - 1); 381a3f895beSArnaldo Carvalho de Melo return ret; 382a3f895beSArnaldo Carvalho de Melo } 383a3f895beSArnaldo Carvalho de Melo 384b15636c6SJiri Olsa static int disasm__cmp(struct annotation_line *a, struct annotation_line *b) 385c7e7b610SNamhyung Kim { 386c7e7b610SNamhyung Kim int i; 387c7e7b610SNamhyung Kim 388b15636c6SJiri Olsa for (i = 0; i < a->samples_nr; i++) { 3890c4a5bceSMartin Liška if (a->samples[i].percent == b->samples[i].percent) 390c7e7b610SNamhyung Kim continue; 3910c4a5bceSMartin Liška return a->samples[i].percent < b->samples[i].percent; 392c7e7b610SNamhyung Kim } 393c7e7b610SNamhyung Kim return 0; 394c7e7b610SNamhyung Kim } 395c7e7b610SNamhyung Kim 396b15636c6SJiri Olsa static void disasm_rb_tree__insert(struct rb_root *root, struct annotation_line *al) 397aca7a94dSNamhyung Kim { 39829ed6e76SArnaldo Carvalho de Melo struct rb_node **p = &root->rb_node; 399aca7a94dSNamhyung Kim struct rb_node *parent = NULL; 4003ab6db8dSJiri Olsa struct annotation_line *l; 401aca7a94dSNamhyung Kim 402aca7a94dSNamhyung Kim while (*p != NULL) { 403aca7a94dSNamhyung Kim parent = *p; 4043ab6db8dSJiri Olsa l = rb_entry(parent, struct annotation_line, rb_node); 405c7e7b610SNamhyung Kim 406b15636c6SJiri Olsa if (disasm__cmp(al, l)) 407aca7a94dSNamhyung Kim p = &(*p)->rb_left; 408aca7a94dSNamhyung Kim else 409aca7a94dSNamhyung Kim p = &(*p)->rb_right; 410aca7a94dSNamhyung Kim } 4113ab6db8dSJiri Olsa rb_link_node(&al->rb_node, parent, p); 4123ab6db8dSJiri Olsa rb_insert_color(&al->rb_node, root); 413aca7a94dSNamhyung Kim } 414aca7a94dSNamhyung Kim 41505e8b080SArnaldo Carvalho de Melo static void annotate_browser__set_top(struct annotate_browser *browser, 416ec03a77dSJiri Olsa struct annotation_line *pos, u32 idx) 417aca7a94dSNamhyung Kim { 418aca7a94dSNamhyung Kim unsigned back; 419aca7a94dSNamhyung Kim 42005e8b080SArnaldo Carvalho de Melo ui_browser__refresh_dimensions(&browser->b); 42105e8b080SArnaldo Carvalho de Melo back = browser->b.height / 2; 42205e8b080SArnaldo Carvalho de Melo browser->b.top_idx = browser->b.index = idx; 423aca7a94dSNamhyung Kim 42405e8b080SArnaldo Carvalho de Melo while (browser->b.top_idx != 0 && back != 0) { 425ec03a77dSJiri Olsa pos = list_entry(pos->node.prev, struct annotation_line, node); 426aca7a94dSNamhyung Kim 427ec03a77dSJiri Olsa if (disasm_line__filter(&browser->b, &pos->node)) 428aca7a94dSNamhyung Kim continue; 429aca7a94dSNamhyung Kim 43005e8b080SArnaldo Carvalho de Melo --browser->b.top_idx; 431aca7a94dSNamhyung Kim --back; 432aca7a94dSNamhyung Kim } 433aca7a94dSNamhyung Kim 434ec03a77dSJiri Olsa browser->b.top = pos; 43505e8b080SArnaldo Carvalho de Melo browser->b.navkeypressed = true; 436aca7a94dSNamhyung Kim } 437aca7a94dSNamhyung Kim 438aca7a94dSNamhyung Kim static void annotate_browser__set_rb_top(struct annotate_browser *browser, 439aca7a94dSNamhyung Kim struct rb_node *nd) 440aca7a94dSNamhyung Kim { 4410d957970SJiri Olsa struct browser_line *bpos; 442ec03a77dSJiri Olsa struct annotation_line *pos; 443a44b45f2SArnaldo Carvalho de Melo u32 idx; 444aca7a94dSNamhyung Kim 445ec03a77dSJiri Olsa pos = rb_entry(nd, struct annotation_line, rb_node); 446ec03a77dSJiri Olsa bpos = browser_line(pos); 4475b12adc8SJiri Olsa 448a44b45f2SArnaldo Carvalho de Melo idx = bpos->idx; 449e9823b21SArnaldo Carvalho de Melo if (annotate_browser__opts.hide_src_code) 450a44b45f2SArnaldo Carvalho de Melo idx = bpos->idx_asm; 451a44b45f2SArnaldo Carvalho de Melo annotate_browser__set_top(browser, pos, idx); 452aca7a94dSNamhyung Kim browser->curr_hot = nd; 453aca7a94dSNamhyung Kim } 454aca7a94dSNamhyung Kim 455aca7a94dSNamhyung Kim static void annotate_browser__calc_percent(struct annotate_browser *browser, 456db8fd07aSNamhyung Kim struct perf_evsel *evsel) 457aca7a94dSNamhyung Kim { 458aca7a94dSNamhyung Kim struct map_symbol *ms = browser->b.priv; 459aca7a94dSNamhyung Kim struct symbol *sym = ms->sym; 460aca7a94dSNamhyung Kim struct annotation *notes = symbol__annotation(sym); 461c4c72436SJiri Olsa struct disasm_line *pos; 462aca7a94dSNamhyung Kim 463aca7a94dSNamhyung Kim browser->entries = RB_ROOT; 464aca7a94dSNamhyung Kim 465aca7a94dSNamhyung Kim pthread_mutex_lock(¬es->lock); 466aca7a94dSNamhyung Kim 467e425da6cSJiri Olsa symbol__calc_percent(sym, evsel); 468e425da6cSJiri Olsa 469a17c4ca0SJiri Olsa list_for_each_entry(pos, ¬es->src->source, al.node) { 470c7e7b610SNamhyung Kim double max_percent = 0.0; 471c7e7b610SNamhyung Kim int i; 472e64aa75bSNamhyung Kim 473d5490b96SJiri Olsa if (pos->al.offset == -1) { 4745b12adc8SJiri Olsa RB_CLEAR_NODE(&pos->al.rb_node); 475e64aa75bSNamhyung Kim continue; 476e64aa75bSNamhyung Kim } 477e64aa75bSNamhyung Kim 478b15636c6SJiri Olsa for (i = 0; i < pos->al.samples_nr; i++) { 479e425da6cSJiri Olsa struct annotation_data *sample = &pos->al.samples[i]; 4800c4a5bceSMartin Liška 4813ab6db8dSJiri Olsa if (max_percent < sample->percent) 4823ab6db8dSJiri Olsa max_percent = sample->percent; 483c7e7b610SNamhyung Kim } 484c7e7b610SNamhyung Kim 48537236d5eSJiri Olsa if (max_percent < 0.01 && pos->al.ipc == 0) { 4865b12adc8SJiri Olsa RB_CLEAR_NODE(&pos->al.rb_node); 487aca7a94dSNamhyung Kim continue; 488aca7a94dSNamhyung Kim } 489b15636c6SJiri Olsa disasm_rb_tree__insert(&browser->entries, &pos->al); 490aca7a94dSNamhyung Kim } 491aca7a94dSNamhyung Kim pthread_mutex_unlock(¬es->lock); 492aca7a94dSNamhyung Kim 493aca7a94dSNamhyung Kim browser->curr_hot = rb_last(&browser->entries); 494aca7a94dSNamhyung Kim } 495aca7a94dSNamhyung Kim 496aca7a94dSNamhyung Kim static bool annotate_browser__toggle_source(struct annotate_browser *browser) 497aca7a94dSNamhyung Kim { 498ec03a77dSJiri Olsa struct annotation_line *al; 499a5ef2702SJiri Olsa struct browser_line *bl; 500aca7a94dSNamhyung Kim off_t offset = browser->b.index - browser->b.top_idx; 501aca7a94dSNamhyung Kim 502aca7a94dSNamhyung Kim browser->b.seek(&browser->b, offset, SEEK_CUR); 503ec03a77dSJiri Olsa al = list_entry(browser->b.top, struct annotation_line, node); 504ec03a77dSJiri Olsa bl = browser_line(al); 505aca7a94dSNamhyung Kim 506e9823b21SArnaldo Carvalho de Melo if (annotate_browser__opts.hide_src_code) { 507a5ef2702SJiri Olsa if (bl->idx_asm < offset) 508a5ef2702SJiri Olsa offset = bl->idx; 509aca7a94dSNamhyung Kim 510aca7a94dSNamhyung Kim browser->b.nr_entries = browser->nr_entries; 511e9823b21SArnaldo Carvalho de Melo annotate_browser__opts.hide_src_code = false; 512aca7a94dSNamhyung Kim browser->b.seek(&browser->b, -offset, SEEK_CUR); 513a5ef2702SJiri Olsa browser->b.top_idx = bl->idx - offset; 514a5ef2702SJiri Olsa browser->b.index = bl->idx; 515aca7a94dSNamhyung Kim } else { 516a5ef2702SJiri Olsa if (bl->idx_asm < 0) { 517aca7a94dSNamhyung Kim ui_helpline__puts("Only available for assembly lines."); 518aca7a94dSNamhyung Kim browser->b.seek(&browser->b, -offset, SEEK_CUR); 519aca7a94dSNamhyung Kim return false; 520aca7a94dSNamhyung Kim } 521aca7a94dSNamhyung Kim 522a5ef2702SJiri Olsa if (bl->idx_asm < offset) 523a5ef2702SJiri Olsa offset = bl->idx_asm; 524aca7a94dSNamhyung Kim 525aca7a94dSNamhyung Kim browser->b.nr_entries = browser->nr_asm_entries; 526e9823b21SArnaldo Carvalho de Melo annotate_browser__opts.hide_src_code = true; 527aca7a94dSNamhyung Kim browser->b.seek(&browser->b, -offset, SEEK_CUR); 528a5ef2702SJiri Olsa browser->b.top_idx = bl->idx_asm - offset; 529a5ef2702SJiri Olsa browser->b.index = bl->idx_asm; 530aca7a94dSNamhyung Kim } 531aca7a94dSNamhyung Kim 532aca7a94dSNamhyung Kim return true; 533aca7a94dSNamhyung Kim } 534aca7a94dSNamhyung Kim 535e9823b21SArnaldo Carvalho de Melo static void annotate_browser__init_asm_mode(struct annotate_browser *browser) 536e9823b21SArnaldo Carvalho de Melo { 537e9823b21SArnaldo Carvalho de Melo ui_browser__reset_index(&browser->b); 538e9823b21SArnaldo Carvalho de Melo browser->b.nr_entries = browser->nr_asm_entries; 539e9823b21SArnaldo Carvalho de Melo } 540e9823b21SArnaldo Carvalho de Melo 54134f77abcSAdrian Hunter #define SYM_TITLE_MAX_SIZE (PATH_MAX + 64) 54234f77abcSAdrian Hunter 54334f77abcSAdrian Hunter static int sym_title(struct symbol *sym, struct map *map, char *title, 54434f77abcSAdrian Hunter size_t sz) 54534f77abcSAdrian Hunter { 54634f77abcSAdrian Hunter return snprintf(title, sz, "%s %s", sym->name, map->dso->long_name); 54734f77abcSAdrian Hunter } 54834f77abcSAdrian Hunter 549db8fd07aSNamhyung Kim static bool annotate_browser__callq(struct annotate_browser *browser, 550db8fd07aSNamhyung Kim struct perf_evsel *evsel, 5519783adf7SNamhyung Kim struct hist_browser_timer *hbt) 552aca7a94dSNamhyung Kim { 553aca7a94dSNamhyung Kim struct map_symbol *ms = browser->b.priv; 5547bcbcd58SJiri Olsa struct disasm_line *dl = disasm_line(browser->selection); 555aca7a94dSNamhyung Kim struct annotation *notes; 55634f77abcSAdrian Hunter char title[SYM_TITLE_MAX_SIZE]; 557aca7a94dSNamhyung Kim 55875b49202SArnaldo Carvalho de Melo if (!ins__is_call(&dl->ins)) 559aca7a94dSNamhyung Kim return false; 560aca7a94dSNamhyung Kim 561696703afSArnaldo Carvalho de Melo if (!dl->ops.target.sym) { 562aca7a94dSNamhyung Kim ui_helpline__puts("The called function was not found."); 563aca7a94dSNamhyung Kim return true; 564aca7a94dSNamhyung Kim } 565aca7a94dSNamhyung Kim 566696703afSArnaldo Carvalho de Melo notes = symbol__annotation(dl->ops.target.sym); 567aca7a94dSNamhyung Kim pthread_mutex_lock(¬es->lock); 568aca7a94dSNamhyung Kim 569696703afSArnaldo Carvalho de Melo if (notes->src == NULL && symbol__alloc_hist(dl->ops.target.sym) < 0) { 570aca7a94dSNamhyung Kim pthread_mutex_unlock(¬es->lock); 571aca7a94dSNamhyung Kim ui__warning("Not enough memory for annotating '%s' symbol!\n", 572696703afSArnaldo Carvalho de Melo dl->ops.target.sym->name); 573aca7a94dSNamhyung Kim return true; 574aca7a94dSNamhyung Kim } 575aca7a94dSNamhyung Kim 576aca7a94dSNamhyung Kim pthread_mutex_unlock(¬es->lock); 577696703afSArnaldo Carvalho de Melo symbol__tui_annotate(dl->ops.target.sym, ms->map, evsel, hbt); 5781179e11bSAdrian Hunter sym_title(ms->sym, ms->map, title, sizeof(title)); 57934f77abcSAdrian Hunter ui_browser__show_title(&browser->b, title); 580aca7a94dSNamhyung Kim return true; 581aca7a94dSNamhyung Kim } 582aca7a94dSNamhyung Kim 58329ed6e76SArnaldo Carvalho de Melo static 58429ed6e76SArnaldo Carvalho de Melo struct disasm_line *annotate_browser__find_offset(struct annotate_browser *browser, 585aca7a94dSNamhyung Kim s64 offset, s64 *idx) 586aca7a94dSNamhyung Kim { 587aca7a94dSNamhyung Kim struct map_symbol *ms = browser->b.priv; 588aca7a94dSNamhyung Kim struct symbol *sym = ms->sym; 589aca7a94dSNamhyung Kim struct annotation *notes = symbol__annotation(sym); 59029ed6e76SArnaldo Carvalho de Melo struct disasm_line *pos; 591aca7a94dSNamhyung Kim 592aca7a94dSNamhyung Kim *idx = 0; 593a17c4ca0SJiri Olsa list_for_each_entry(pos, ¬es->src->source, al.node) { 594d5490b96SJiri Olsa if (pos->al.offset == offset) 595aca7a94dSNamhyung Kim return pos; 596a17c4ca0SJiri Olsa if (!disasm_line__filter(&browser->b, &pos->al.node)) 597aca7a94dSNamhyung Kim ++*idx; 598aca7a94dSNamhyung Kim } 599aca7a94dSNamhyung Kim 600aca7a94dSNamhyung Kim return NULL; 601aca7a94dSNamhyung Kim } 602aca7a94dSNamhyung Kim 603aca7a94dSNamhyung Kim static bool annotate_browser__jump(struct annotate_browser *browser) 604aca7a94dSNamhyung Kim { 6057bcbcd58SJiri Olsa struct disasm_line *dl = disasm_line(browser->selection); 6065252b1aeSArnaldo Carvalho de Melo u64 offset; 6074f9d0325SArnaldo Carvalho de Melo s64 idx; 608aca7a94dSNamhyung Kim 60975b49202SArnaldo Carvalho de Melo if (!ins__is_jump(&dl->ins)) 610aca7a94dSNamhyung Kim return false; 611aca7a94dSNamhyung Kim 6125252b1aeSArnaldo Carvalho de Melo offset = dl->ops.target.offset; 6135252b1aeSArnaldo Carvalho de Melo dl = annotate_browser__find_offset(browser, offset, &idx); 61429ed6e76SArnaldo Carvalho de Melo if (dl == NULL) { 6155252b1aeSArnaldo Carvalho de Melo ui_helpline__printf("Invalid jump offset: %" PRIx64, offset); 616aca7a94dSNamhyung Kim return true; 617aca7a94dSNamhyung Kim } 618aca7a94dSNamhyung Kim 619ec03a77dSJiri Olsa annotate_browser__set_top(browser, &dl->al, idx); 620aca7a94dSNamhyung Kim 621aca7a94dSNamhyung Kim return true; 622aca7a94dSNamhyung Kim } 623aca7a94dSNamhyung Kim 62429ed6e76SArnaldo Carvalho de Melo static 6259213afbdSJiri Olsa struct annotation_line *annotate_browser__find_string(struct annotate_browser *browser, 626aca7a94dSNamhyung Kim char *s, s64 *idx) 627aca7a94dSNamhyung Kim { 628aca7a94dSNamhyung Kim struct map_symbol *ms = browser->b.priv; 629aca7a94dSNamhyung Kim struct symbol *sym = ms->sym; 630aca7a94dSNamhyung Kim struct annotation *notes = symbol__annotation(sym); 6319213afbdSJiri Olsa struct annotation_line *al = browser->selection; 632aca7a94dSNamhyung Kim 633aca7a94dSNamhyung Kim *idx = browser->b.index; 6349213afbdSJiri Olsa list_for_each_entry_continue(al, ¬es->src->source, node) { 6359213afbdSJiri Olsa if (disasm_line__filter(&browser->b, &al->node)) 636aca7a94dSNamhyung Kim continue; 637aca7a94dSNamhyung Kim 638aca7a94dSNamhyung Kim ++*idx; 639aca7a94dSNamhyung Kim 6409213afbdSJiri Olsa if (al->line && strstr(al->line, s) != NULL) 6419213afbdSJiri Olsa return al; 642aca7a94dSNamhyung Kim } 643aca7a94dSNamhyung Kim 644aca7a94dSNamhyung Kim return NULL; 645aca7a94dSNamhyung Kim } 646aca7a94dSNamhyung Kim 647aca7a94dSNamhyung Kim static bool __annotate_browser__search(struct annotate_browser *browser) 648aca7a94dSNamhyung Kim { 6499213afbdSJiri Olsa struct annotation_line *al; 650aca7a94dSNamhyung Kim s64 idx; 651aca7a94dSNamhyung Kim 6529213afbdSJiri Olsa al = annotate_browser__find_string(browser, browser->search_bf, &idx); 6539213afbdSJiri Olsa if (al == NULL) { 654aca7a94dSNamhyung Kim ui_helpline__puts("String not found!"); 655aca7a94dSNamhyung Kim return false; 656aca7a94dSNamhyung Kim } 657aca7a94dSNamhyung Kim 658ec03a77dSJiri Olsa annotate_browser__set_top(browser, al, idx); 659aca7a94dSNamhyung Kim browser->searching_backwards = false; 660aca7a94dSNamhyung Kim return true; 661aca7a94dSNamhyung Kim } 662aca7a94dSNamhyung Kim 66329ed6e76SArnaldo Carvalho de Melo static 6649213afbdSJiri Olsa struct annotation_line *annotate_browser__find_string_reverse(struct annotate_browser *browser, 665aca7a94dSNamhyung Kim char *s, s64 *idx) 666aca7a94dSNamhyung Kim { 667aca7a94dSNamhyung Kim struct map_symbol *ms = browser->b.priv; 668aca7a94dSNamhyung Kim struct symbol *sym = ms->sym; 669aca7a94dSNamhyung Kim struct annotation *notes = symbol__annotation(sym); 6709213afbdSJiri Olsa struct annotation_line *al = browser->selection; 671aca7a94dSNamhyung Kim 672aca7a94dSNamhyung Kim *idx = browser->b.index; 6739213afbdSJiri Olsa list_for_each_entry_continue_reverse(al, ¬es->src->source, node) { 6749213afbdSJiri Olsa if (disasm_line__filter(&browser->b, &al->node)) 675aca7a94dSNamhyung Kim continue; 676aca7a94dSNamhyung Kim 677aca7a94dSNamhyung Kim --*idx; 678aca7a94dSNamhyung Kim 6799213afbdSJiri Olsa if (al->line && strstr(al->line, s) != NULL) 6809213afbdSJiri Olsa return al; 681aca7a94dSNamhyung Kim } 682aca7a94dSNamhyung Kim 683aca7a94dSNamhyung Kim return NULL; 684aca7a94dSNamhyung Kim } 685aca7a94dSNamhyung Kim 686aca7a94dSNamhyung Kim static bool __annotate_browser__search_reverse(struct annotate_browser *browser) 687aca7a94dSNamhyung Kim { 6889213afbdSJiri Olsa struct annotation_line *al; 689aca7a94dSNamhyung Kim s64 idx; 690aca7a94dSNamhyung Kim 6919213afbdSJiri Olsa al = annotate_browser__find_string_reverse(browser, browser->search_bf, &idx); 6929213afbdSJiri Olsa if (al == NULL) { 693aca7a94dSNamhyung Kim ui_helpline__puts("String not found!"); 694aca7a94dSNamhyung Kim return false; 695aca7a94dSNamhyung Kim } 696aca7a94dSNamhyung Kim 697ec03a77dSJiri Olsa annotate_browser__set_top(browser, al, idx); 698aca7a94dSNamhyung Kim browser->searching_backwards = true; 699aca7a94dSNamhyung Kim return true; 700aca7a94dSNamhyung Kim } 701aca7a94dSNamhyung Kim 702aca7a94dSNamhyung Kim static bool annotate_browser__search_window(struct annotate_browser *browser, 703aca7a94dSNamhyung Kim int delay_secs) 704aca7a94dSNamhyung Kim { 705aca7a94dSNamhyung Kim if (ui_browser__input_window("Search", "String: ", browser->search_bf, 706aca7a94dSNamhyung Kim "ENTER: OK, ESC: Cancel", 707aca7a94dSNamhyung Kim delay_secs * 2) != K_ENTER || 708aca7a94dSNamhyung Kim !*browser->search_bf) 709aca7a94dSNamhyung Kim return false; 710aca7a94dSNamhyung Kim 711aca7a94dSNamhyung Kim return true; 712aca7a94dSNamhyung Kim } 713aca7a94dSNamhyung Kim 714aca7a94dSNamhyung Kim static bool annotate_browser__search(struct annotate_browser *browser, int delay_secs) 715aca7a94dSNamhyung Kim { 716aca7a94dSNamhyung Kim if (annotate_browser__search_window(browser, delay_secs)) 717aca7a94dSNamhyung Kim return __annotate_browser__search(browser); 718aca7a94dSNamhyung Kim 719aca7a94dSNamhyung Kim return false; 720aca7a94dSNamhyung Kim } 721aca7a94dSNamhyung Kim 722aca7a94dSNamhyung Kim static bool annotate_browser__continue_search(struct annotate_browser *browser, 723aca7a94dSNamhyung Kim int delay_secs) 724aca7a94dSNamhyung Kim { 725aca7a94dSNamhyung Kim if (!*browser->search_bf) 726aca7a94dSNamhyung Kim return annotate_browser__search(browser, delay_secs); 727aca7a94dSNamhyung Kim 728aca7a94dSNamhyung Kim return __annotate_browser__search(browser); 729aca7a94dSNamhyung Kim } 730aca7a94dSNamhyung Kim 731aca7a94dSNamhyung Kim static bool annotate_browser__search_reverse(struct annotate_browser *browser, 732aca7a94dSNamhyung Kim int delay_secs) 733aca7a94dSNamhyung Kim { 734aca7a94dSNamhyung Kim if (annotate_browser__search_window(browser, delay_secs)) 735aca7a94dSNamhyung Kim return __annotate_browser__search_reverse(browser); 736aca7a94dSNamhyung Kim 737aca7a94dSNamhyung Kim return false; 738aca7a94dSNamhyung Kim } 739aca7a94dSNamhyung Kim 740aca7a94dSNamhyung Kim static 741aca7a94dSNamhyung Kim bool annotate_browser__continue_search_reverse(struct annotate_browser *browser, 742aca7a94dSNamhyung Kim int delay_secs) 743aca7a94dSNamhyung Kim { 744aca7a94dSNamhyung Kim if (!*browser->search_bf) 745aca7a94dSNamhyung Kim return annotate_browser__search_reverse(browser, delay_secs); 746aca7a94dSNamhyung Kim 747aca7a94dSNamhyung Kim return __annotate_browser__search_reverse(browser); 748aca7a94dSNamhyung Kim } 749aca7a94dSNamhyung Kim 750e9823b21SArnaldo Carvalho de Melo static void annotate_browser__update_addr_width(struct annotate_browser *browser) 751e9823b21SArnaldo Carvalho de Melo { 752e9823b21SArnaldo Carvalho de Melo if (annotate_browser__opts.use_offset) 753e9823b21SArnaldo Carvalho de Melo browser->target_width = browser->min_addr_width; 754e9823b21SArnaldo Carvalho de Melo else 755e9823b21SArnaldo Carvalho de Melo browser->target_width = browser->max_addr_width; 756e9823b21SArnaldo Carvalho de Melo 757e9823b21SArnaldo Carvalho de Melo browser->addr_width = browser->target_width; 758e9823b21SArnaldo Carvalho de Melo 759e9823b21SArnaldo Carvalho de Melo if (annotate_browser__opts.show_nr_jumps) 760e9823b21SArnaldo Carvalho de Melo browser->addr_width += browser->jumps_width + 1; 761e9823b21SArnaldo Carvalho de Melo } 762e9823b21SArnaldo Carvalho de Melo 763db8fd07aSNamhyung Kim static int annotate_browser__run(struct annotate_browser *browser, 764db8fd07aSNamhyung Kim struct perf_evsel *evsel, 7659783adf7SNamhyung Kim struct hist_browser_timer *hbt) 766aca7a94dSNamhyung Kim { 767aca7a94dSNamhyung Kim struct rb_node *nd = NULL; 76805e8b080SArnaldo Carvalho de Melo struct map_symbol *ms = browser->b.priv; 769aca7a94dSNamhyung Kim struct symbol *sym = ms->sym; 77054e7a4e8SArnaldo Carvalho de Melo const char *help = "Press 'h' for help on key bindings"; 7719783adf7SNamhyung Kim int delay_secs = hbt ? hbt->refresh : 0; 772aca7a94dSNamhyung Kim int key; 77334f77abcSAdrian Hunter char title[SYM_TITLE_MAX_SIZE]; 774aca7a94dSNamhyung Kim 77534f77abcSAdrian Hunter sym_title(sym, ms->map, title, sizeof(title)); 77634f77abcSAdrian Hunter if (ui_browser__show(&browser->b, title, help) < 0) 777aca7a94dSNamhyung Kim return -1; 778aca7a94dSNamhyung Kim 779db8fd07aSNamhyung Kim annotate_browser__calc_percent(browser, evsel); 780aca7a94dSNamhyung Kim 78105e8b080SArnaldo Carvalho de Melo if (browser->curr_hot) { 78205e8b080SArnaldo Carvalho de Melo annotate_browser__set_rb_top(browser, browser->curr_hot); 78305e8b080SArnaldo Carvalho de Melo browser->b.navkeypressed = false; 784aca7a94dSNamhyung Kim } 785aca7a94dSNamhyung Kim 78605e8b080SArnaldo Carvalho de Melo nd = browser->curr_hot; 787aca7a94dSNamhyung Kim 788aca7a94dSNamhyung Kim while (1) { 78905e8b080SArnaldo Carvalho de Melo key = ui_browser__run(&browser->b, delay_secs); 790aca7a94dSNamhyung Kim 791aca7a94dSNamhyung Kim if (delay_secs != 0) { 792db8fd07aSNamhyung Kim annotate_browser__calc_percent(browser, evsel); 793aca7a94dSNamhyung Kim /* 794aca7a94dSNamhyung Kim * Current line focus got out of the list of most active 795aca7a94dSNamhyung Kim * lines, NULL it so that if TAB|UNTAB is pressed, we 796aca7a94dSNamhyung Kim * move to curr_hot (current hottest line). 797aca7a94dSNamhyung Kim */ 798aca7a94dSNamhyung Kim if (nd != NULL && RB_EMPTY_NODE(nd)) 799aca7a94dSNamhyung Kim nd = NULL; 800aca7a94dSNamhyung Kim } 801aca7a94dSNamhyung Kim 802aca7a94dSNamhyung Kim switch (key) { 803aca7a94dSNamhyung Kim case K_TIMER: 8049783adf7SNamhyung Kim if (hbt) 8059783adf7SNamhyung Kim hbt->timer(hbt->arg); 806aca7a94dSNamhyung Kim 807aca7a94dSNamhyung Kim if (delay_secs != 0) 808db8fd07aSNamhyung Kim symbol__annotate_decay_histogram(sym, evsel->idx); 809aca7a94dSNamhyung Kim continue; 810aca7a94dSNamhyung Kim case K_TAB: 811aca7a94dSNamhyung Kim if (nd != NULL) { 812aca7a94dSNamhyung Kim nd = rb_prev(nd); 813aca7a94dSNamhyung Kim if (nd == NULL) 81405e8b080SArnaldo Carvalho de Melo nd = rb_last(&browser->entries); 815aca7a94dSNamhyung Kim } else 81605e8b080SArnaldo Carvalho de Melo nd = browser->curr_hot; 817aca7a94dSNamhyung Kim break; 818aca7a94dSNamhyung Kim case K_UNTAB: 819d4913cbdSMarkus Trippelsdorf if (nd != NULL) { 820aca7a94dSNamhyung Kim nd = rb_next(nd); 821aca7a94dSNamhyung Kim if (nd == NULL) 82205e8b080SArnaldo Carvalho de Melo nd = rb_first(&browser->entries); 823d4913cbdSMarkus Trippelsdorf } else 82405e8b080SArnaldo Carvalho de Melo nd = browser->curr_hot; 825aca7a94dSNamhyung Kim break; 82654e7a4e8SArnaldo Carvalho de Melo case K_F1: 827aca7a94dSNamhyung Kim case 'h': 82805e8b080SArnaldo Carvalho de Melo ui_browser__help_window(&browser->b, 82954e7a4e8SArnaldo Carvalho de Melo "UP/DOWN/PGUP\n" 83054e7a4e8SArnaldo Carvalho de Melo "PGDN/SPACE Navigate\n" 83154e7a4e8SArnaldo Carvalho de Melo "q/ESC/CTRL+C Exit\n\n" 8327727a925SArnaldo Carvalho de Melo "ENTER Go to target\n" 8337727a925SArnaldo Carvalho de Melo "ESC Exit\n" 834eba9fac0SArnaldo Carvalho de Melo "H Go to hottest instruction\n" 835eba9fac0SArnaldo Carvalho de Melo "TAB/shift+TAB Cycle thru hottest instructions\n" 83654e7a4e8SArnaldo Carvalho de Melo "j Toggle showing jump to target arrows\n" 83754e7a4e8SArnaldo Carvalho de Melo "J Toggle showing number of jump sources on targets\n" 83854e7a4e8SArnaldo Carvalho de Melo "n Search next string\n" 83954e7a4e8SArnaldo Carvalho de Melo "o Toggle disassembler output/simplified view\n" 84054e7a4e8SArnaldo Carvalho de Melo "s Toggle source code view\n" 8413a555c77STaeung Song "t Circulate percent, total period, samples view\n" 84254e7a4e8SArnaldo Carvalho de Melo "/ Search string\n" 843e592488cSAndi Kleen "k Toggle line numbers\n" 84479ee47faSFeng Tang "r Run available scripts\n" 845fcd9fef9SArnaldo Carvalho de Melo "? Search string backwards\n"); 84654e7a4e8SArnaldo Carvalho de Melo continue; 84779ee47faSFeng Tang case 'r': 84879ee47faSFeng Tang { 84979ee47faSFeng Tang script_browse(NULL); 85079ee47faSFeng Tang continue; 85179ee47faSFeng Tang } 852e592488cSAndi Kleen case 'k': 853e592488cSAndi Kleen annotate_browser__opts.show_linenr = 854e592488cSAndi Kleen !annotate_browser__opts.show_linenr; 855e592488cSAndi Kleen break; 85654e7a4e8SArnaldo Carvalho de Melo case 'H': 85705e8b080SArnaldo Carvalho de Melo nd = browser->curr_hot; 858aca7a94dSNamhyung Kim break; 859aca7a94dSNamhyung Kim case 's': 86005e8b080SArnaldo Carvalho de Melo if (annotate_browser__toggle_source(browser)) 861aca7a94dSNamhyung Kim ui_helpline__puts(help); 862aca7a94dSNamhyung Kim continue; 863aca7a94dSNamhyung Kim case 'o': 864e9823b21SArnaldo Carvalho de Melo annotate_browser__opts.use_offset = !annotate_browser__opts.use_offset; 86505e8b080SArnaldo Carvalho de Melo annotate_browser__update_addr_width(browser); 866aca7a94dSNamhyung Kim continue; 8679d1ef56dSArnaldo Carvalho de Melo case 'j': 868e9823b21SArnaldo Carvalho de Melo annotate_browser__opts.jump_arrows = !annotate_browser__opts.jump_arrows; 8699d1ef56dSArnaldo Carvalho de Melo continue; 8702402e4a9SArnaldo Carvalho de Melo case 'J': 871e9823b21SArnaldo Carvalho de Melo annotate_browser__opts.show_nr_jumps = !annotate_browser__opts.show_nr_jumps; 87205e8b080SArnaldo Carvalho de Melo annotate_browser__update_addr_width(browser); 873e9823b21SArnaldo Carvalho de Melo continue; 874aca7a94dSNamhyung Kim case '/': 87505e8b080SArnaldo Carvalho de Melo if (annotate_browser__search(browser, delay_secs)) { 876aca7a94dSNamhyung Kim show_help: 877aca7a94dSNamhyung Kim ui_helpline__puts(help); 878aca7a94dSNamhyung Kim } 879aca7a94dSNamhyung Kim continue; 880aca7a94dSNamhyung Kim case 'n': 88105e8b080SArnaldo Carvalho de Melo if (browser->searching_backwards ? 88205e8b080SArnaldo Carvalho de Melo annotate_browser__continue_search_reverse(browser, delay_secs) : 88305e8b080SArnaldo Carvalho de Melo annotate_browser__continue_search(browser, delay_secs)) 884aca7a94dSNamhyung Kim goto show_help; 885aca7a94dSNamhyung Kim continue; 886aca7a94dSNamhyung Kim case '?': 88705e8b080SArnaldo Carvalho de Melo if (annotate_browser__search_reverse(browser, delay_secs)) 888aca7a94dSNamhyung Kim goto show_help; 889aca7a94dSNamhyung Kim continue; 890e9823b21SArnaldo Carvalho de Melo case 'D': { 891e9823b21SArnaldo Carvalho de Melo static int seq; 892e9823b21SArnaldo Carvalho de Melo ui_helpline__pop(); 893e9823b21SArnaldo Carvalho de Melo ui_helpline__fpush("%d: nr_ent=%d, height=%d, idx=%d, top_idx=%d, nr_asm_entries=%d", 89405e8b080SArnaldo Carvalho de Melo seq++, browser->b.nr_entries, 89505e8b080SArnaldo Carvalho de Melo browser->b.height, 89605e8b080SArnaldo Carvalho de Melo browser->b.index, 89705e8b080SArnaldo Carvalho de Melo browser->b.top_idx, 89805e8b080SArnaldo Carvalho de Melo browser->nr_asm_entries); 899e9823b21SArnaldo Carvalho de Melo } 900e9823b21SArnaldo Carvalho de Melo continue; 901aca7a94dSNamhyung Kim case K_ENTER: 902aca7a94dSNamhyung Kim case K_RIGHT: 9037bcbcd58SJiri Olsa { 9047bcbcd58SJiri Olsa struct disasm_line *dl = disasm_line(browser->selection); 9057bcbcd58SJiri Olsa 90605e8b080SArnaldo Carvalho de Melo if (browser->selection == NULL) 907aca7a94dSNamhyung Kim ui_helpline__puts("Huh? No selection. Report to linux-kernel@vger.kernel.org"); 9087bcbcd58SJiri Olsa else if (browser->selection->offset == -1) 909aca7a94dSNamhyung Kim ui_helpline__puts("Actions are only available for assembly lines."); 9107bcbcd58SJiri Olsa else if (!dl->ins.ops) 911c4cceae3SArnaldo Carvalho de Melo goto show_sup_ins; 9127bcbcd58SJiri Olsa else if (ins__is_ret(&dl->ins)) 913c4cceae3SArnaldo Carvalho de Melo goto out; 9146ef94929SNaveen N. Rao else if (!(annotate_browser__jump(browser) || 915db8fd07aSNamhyung Kim annotate_browser__callq(browser, evsel, hbt))) { 916c4cceae3SArnaldo Carvalho de Melo show_sup_ins: 9176ef94929SNaveen N. Rao ui_helpline__puts("Actions are only available for function call/return & jump/branch instructions."); 918c4cceae3SArnaldo Carvalho de Melo } 919aca7a94dSNamhyung Kim continue; 9207bcbcd58SJiri Olsa } 9210c4a5bceSMartin Liška case 't': 9223a555c77STaeung Song if (annotate_browser__opts.show_total_period) { 9233a555c77STaeung Song annotate_browser__opts.show_total_period = false; 9243a555c77STaeung Song annotate_browser__opts.show_nr_samples = true; 9253a555c77STaeung Song } else if (annotate_browser__opts.show_nr_samples) 9263a555c77STaeung Song annotate_browser__opts.show_nr_samples = false; 9273a555c77STaeung Song else 9283a555c77STaeung Song annotate_browser__opts.show_total_period = true; 9290c4a5bceSMartin Liška annotate_browser__update_addr_width(browser); 9300c4a5bceSMartin Liška continue; 931aca7a94dSNamhyung Kim case K_LEFT: 932aca7a94dSNamhyung Kim case K_ESC: 933aca7a94dSNamhyung Kim case 'q': 934aca7a94dSNamhyung Kim case CTRL('c'): 935aca7a94dSNamhyung Kim goto out; 936aca7a94dSNamhyung Kim default: 937aca7a94dSNamhyung Kim continue; 938aca7a94dSNamhyung Kim } 939aca7a94dSNamhyung Kim 940aca7a94dSNamhyung Kim if (nd != NULL) 94105e8b080SArnaldo Carvalho de Melo annotate_browser__set_rb_top(browser, nd); 942aca7a94dSNamhyung Kim } 943aca7a94dSNamhyung Kim out: 94405e8b080SArnaldo Carvalho de Melo ui_browser__hide(&browser->b); 945aca7a94dSNamhyung Kim return key; 946aca7a94dSNamhyung Kim } 947aca7a94dSNamhyung Kim 948d5dbc518SArnaldo Carvalho de Melo int map_symbol__tui_annotate(struct map_symbol *ms, struct perf_evsel *evsel, 949d5dbc518SArnaldo Carvalho de Melo struct hist_browser_timer *hbt) 950d5dbc518SArnaldo Carvalho de Melo { 9519cef4b0bSTaeung Song /* Set default value for show_total_period and show_nr_samples */ 9520c4a5bceSMartin Liška annotate_browser__opts.show_total_period = 9530c4a5bceSMartin Liška symbol_conf.show_total_period; 9549cef4b0bSTaeung Song annotate_browser__opts.show_nr_samples = 9559cef4b0bSTaeung Song symbol_conf.show_nr_samples; 9560c4a5bceSMartin Liška 957d5dbc518SArnaldo Carvalho de Melo return symbol__tui_annotate(ms->sym, ms->map, evsel, hbt); 958d5dbc518SArnaldo Carvalho de Melo } 959d5dbc518SArnaldo Carvalho de Melo 960db8fd07aSNamhyung Kim int hist_entry__tui_annotate(struct hist_entry *he, struct perf_evsel *evsel, 9619783adf7SNamhyung Kim struct hist_browser_timer *hbt) 962aca7a94dSNamhyung Kim { 963ed426915SNamhyung Kim /* reset abort key so that it can get Ctrl-C as a key */ 964ed426915SNamhyung Kim SLang_reset_tty(); 965ed426915SNamhyung Kim SLang_init_tty(0, 0, 0); 966ed426915SNamhyung Kim 967d5dbc518SArnaldo Carvalho de Melo return map_symbol__tui_annotate(&he->ms, evsel, hbt); 968aca7a94dSNamhyung Kim } 969aca7a94dSNamhyung Kim 970b793a401SArnaldo Carvalho de Melo static void annotate_browser__mark_jump_targets(struct annotate_browser *browser, 971b793a401SArnaldo Carvalho de Melo size_t size) 972b793a401SArnaldo Carvalho de Melo { 973b793a401SArnaldo Carvalho de Melo u64 offset; 97432ae1efdSNamhyung Kim struct map_symbol *ms = browser->b.priv; 97532ae1efdSNamhyung Kim struct symbol *sym = ms->sym; 9769d6bb41dSArnaldo Carvalho de Melo struct annotation *notes = symbol__annotation(sym); 97732ae1efdSNamhyung Kim 97832ae1efdSNamhyung Kim /* PLT symbols contain external offsets */ 97932ae1efdSNamhyung Kim if (strstr(sym->name, "@plt")) 98032ae1efdSNamhyung Kim return; 981b793a401SArnaldo Carvalho de Melo 982b793a401SArnaldo Carvalho de Melo for (offset = 0; offset < size; ++offset) { 9839d6bb41dSArnaldo Carvalho de Melo struct annotation_line *al = notes->offsets[offset]; 984a5ef2702SJiri Olsa struct disasm_line *dl; 985a5ef2702SJiri Olsa struct browser_line *blt; 986b793a401SArnaldo Carvalho de Melo 987e1b60b5bSJiri Olsa dl = disasm_line(al); 988e1b60b5bSJiri Olsa 989865c66c4SFrederik Deweerdt if (!disasm_line__is_valid_jump(dl, sym)) 990b793a401SArnaldo Carvalho de Melo continue; 991b793a401SArnaldo Carvalho de Melo 9929d6bb41dSArnaldo Carvalho de Melo al = notes->offsets[dl->ops.target.offset]; 993e1b60b5bSJiri Olsa 9949481ede9SArnaldo Carvalho de Melo /* 9959481ede9SArnaldo Carvalho de Melo * FIXME: Oops, no jump target? Buggy disassembler? Or do we 9969481ede9SArnaldo Carvalho de Melo * have to adjust to the previous offset? 9979481ede9SArnaldo Carvalho de Melo */ 998a5ef2702SJiri Olsa if (al == NULL) 9999481ede9SArnaldo Carvalho de Melo continue; 10009481ede9SArnaldo Carvalho de Melo 1001a5ef2702SJiri Olsa blt = browser_line(al); 1002a5ef2702SJiri Olsa if (++blt->jump_sources > browser->max_jump_sources) 1003a5ef2702SJiri Olsa browser->max_jump_sources = blt->jump_sources; 10042402e4a9SArnaldo Carvalho de Melo 10052402e4a9SArnaldo Carvalho de Melo ++browser->nr_jumps; 1006b793a401SArnaldo Carvalho de Melo } 1007b793a401SArnaldo Carvalho de Melo } 1008b793a401SArnaldo Carvalho de Melo 10092402e4a9SArnaldo Carvalho de Melo static inline int width_jumps(int n) 10102402e4a9SArnaldo Carvalho de Melo { 10112402e4a9SArnaldo Carvalho de Melo if (n >= 100) 10122402e4a9SArnaldo Carvalho de Melo return 5; 10132402e4a9SArnaldo Carvalho de Melo if (n / 10) 10142402e4a9SArnaldo Carvalho de Melo return 2; 10152402e4a9SArnaldo Carvalho de Melo return 1; 10162402e4a9SArnaldo Carvalho de Melo } 10172402e4a9SArnaldo Carvalho de Melo 1018db8fd07aSNamhyung Kim int symbol__tui_annotate(struct symbol *sym, struct map *map, 1019db8fd07aSNamhyung Kim struct perf_evsel *evsel, 10209783adf7SNamhyung Kim struct hist_browser_timer *hbt) 1021aca7a94dSNamhyung Kim { 1022e1b60b5bSJiri Olsa struct annotation_line *al; 10239d6bb41dSArnaldo Carvalho de Melo struct annotation *notes = symbol__annotation(sym); 1024c0a58fb2SSamuel Liao size_t size; 1025aca7a94dSNamhyung Kim struct map_symbol ms = { 1026aca7a94dSNamhyung Kim .map = map, 1027aca7a94dSNamhyung Kim .sym = sym, 1028aca7a94dSNamhyung Kim }; 1029aca7a94dSNamhyung Kim struct annotate_browser browser = { 1030aca7a94dSNamhyung Kim .b = { 1031a3f895beSArnaldo Carvalho de Melo .refresh = annotate_browser__refresh, 1032aca7a94dSNamhyung Kim .seek = ui_browser__list_head_seek, 1033aca7a94dSNamhyung Kim .write = annotate_browser__write, 103429ed6e76SArnaldo Carvalho de Melo .filter = disasm_line__filter, 1035aca7a94dSNamhyung Kim .priv = &ms, 1036aca7a94dSNamhyung Kim .use_navkeypressed = true, 1037aca7a94dSNamhyung Kim }, 1038aca7a94dSNamhyung Kim }; 1039ee51d851SArnaldo Carvalho de Melo int ret = -1, err; 1040c7e7b610SNamhyung Kim int nr_pcnt = 1; 1041aca7a94dSNamhyung Kim 1042aca7a94dSNamhyung Kim if (sym == NULL) 1043aca7a94dSNamhyung Kim return -1; 1044aca7a94dSNamhyung Kim 1045c0a58fb2SSamuel Liao size = symbol__size(sym); 1046c0a58fb2SSamuel Liao 1047aca7a94dSNamhyung Kim if (map->dso->annotate_warned) 1048aca7a94dSNamhyung Kim return -1; 1049aca7a94dSNamhyung Kim 10509d6bb41dSArnaldo Carvalho de Melo notes->offsets = zalloc(size * sizeof(struct annotation_line *)); 10519d6bb41dSArnaldo Carvalho de Melo if (notes->offsets == NULL) { 1052b793a401SArnaldo Carvalho de Melo ui__error("Not enough memory!"); 1053b793a401SArnaldo Carvalho de Melo return -1; 1054b793a401SArnaldo Carvalho de Melo } 1055b793a401SArnaldo Carvalho de Melo 10563ab6db8dSJiri Olsa if (perf_evsel__is_group_event(evsel)) 1057c7e7b610SNamhyung Kim nr_pcnt = evsel->nr_members; 1058c7e7b610SNamhyung Kim 10595449f13cSArnaldo Carvalho de Melo err = symbol__annotate(sym, map, evsel, sizeof(struct browser_line), &browser.arch); 1060ee51d851SArnaldo Carvalho de Melo if (err) { 1061ee51d851SArnaldo Carvalho de Melo char msg[BUFSIZ]; 1062ee51d851SArnaldo Carvalho de Melo symbol__strerror_disassemble(sym, map, err, msg, sizeof(msg)); 1063ee51d851SArnaldo Carvalho de Melo ui__error("Couldn't annotate %s:\n%s", sym->name, msg); 1064b793a401SArnaldo Carvalho de Melo goto out_free_offsets; 1065aca7a94dSNamhyung Kim } 1066aca7a94dSNamhyung Kim 106705d3f1a1SJiri Olsa symbol__calc_percent(sym, evsel); 106805d3f1a1SJiri Olsa 10697727a925SArnaldo Carvalho de Melo ui_helpline__push("Press ESC to exit"); 1070aca7a94dSNamhyung Kim 1071aca7a94dSNamhyung Kim browser.start = map__rip_2objdump(map, sym->start); 1072aca7a94dSNamhyung Kim 1073e1b60b5bSJiri Olsa list_for_each_entry(al, ¬es->src->source, node) { 10740d957970SJiri Olsa struct browser_line *bpos; 1075e1b60b5bSJiri Olsa size_t line_len = strlen(al->line); 1076aca7a94dSNamhyung Kim 1077aca7a94dSNamhyung Kim if (browser.b.width < line_len) 1078aca7a94dSNamhyung Kim browser.b.width = line_len; 1079a5ef2702SJiri Olsa bpos = browser_line(al); 1080887c0066SArnaldo Carvalho de Melo bpos->idx = browser.nr_entries++; 1081e1b60b5bSJiri Olsa if (al->offset != -1) { 1082887c0066SArnaldo Carvalho de Melo bpos->idx_asm = browser.nr_asm_entries++; 108397148a97SArnaldo Carvalho de Melo /* 108497148a97SArnaldo Carvalho de Melo * FIXME: short term bandaid to cope with assembly 108597148a97SArnaldo Carvalho de Melo * routines that comes with labels in the same column 108697148a97SArnaldo Carvalho de Melo * as the address in objdump, sigh. 108797148a97SArnaldo Carvalho de Melo * 108897148a97SArnaldo Carvalho de Melo * E.g. copy_user_generic_unrolled 108997148a97SArnaldo Carvalho de Melo */ 1090e1b60b5bSJiri Olsa if (al->offset < (s64)size) 10919d6bb41dSArnaldo Carvalho de Melo notes->offsets[al->offset] = al; 1092b793a401SArnaldo Carvalho de Melo } else 1093887c0066SArnaldo Carvalho de Melo bpos->idx_asm = -1; 1094aca7a94dSNamhyung Kim } 1095aca7a94dSNamhyung Kim 1096b793a401SArnaldo Carvalho de Melo annotate_browser__mark_jump_targets(&browser, size); 1097*f56c083bSArnaldo Carvalho de Melo annotation__compute_ipc(notes, size); 1098b793a401SArnaldo Carvalho de Melo 10992402e4a9SArnaldo Carvalho de Melo browser.addr_width = browser.target_width = browser.min_addr_width = hex_width(size); 110083b1f2aaSArnaldo Carvalho de Melo browser.max_addr_width = hex_width(sym->end); 11012402e4a9SArnaldo Carvalho de Melo browser.jumps_width = width_jumps(browser.max_jump_sources); 1102c7e7b610SNamhyung Kim browser.nr_events = nr_pcnt; 1103aca7a94dSNamhyung Kim browser.b.nr_entries = browser.nr_entries; 1104aca7a94dSNamhyung Kim browser.b.entries = ¬es->src->source, 1105aca7a94dSNamhyung Kim browser.b.width += 18; /* Percentage */ 1106e9823b21SArnaldo Carvalho de Melo 1107e9823b21SArnaldo Carvalho de Melo if (annotate_browser__opts.hide_src_code) 1108e9823b21SArnaldo Carvalho de Melo annotate_browser__init_asm_mode(&browser); 1109e9823b21SArnaldo Carvalho de Melo 1110e9823b21SArnaldo Carvalho de Melo annotate_browser__update_addr_width(&browser); 1111e9823b21SArnaldo Carvalho de Melo 1112db8fd07aSNamhyung Kim ret = annotate_browser__run(&browser, evsel, hbt); 1113f8eb37bdSJiri Olsa 1114f8eb37bdSJiri Olsa annotated_source__purge(notes->src); 1115b793a401SArnaldo Carvalho de Melo 1116b793a401SArnaldo Carvalho de Melo out_free_offsets: 11179d6bb41dSArnaldo Carvalho de Melo zfree(¬es->offsets); 1118aca7a94dSNamhyung Kim return ret; 1119aca7a94dSNamhyung Kim } 1120c323cf04SArnaldo Carvalho de Melo 1121c323cf04SArnaldo Carvalho de Melo #define ANNOTATE_CFG(n) \ 1122c323cf04SArnaldo Carvalho de Melo { .name = #n, .value = &annotate_browser__opts.n, } 1123c323cf04SArnaldo Carvalho de Melo 1124c323cf04SArnaldo Carvalho de Melo /* 1125c323cf04SArnaldo Carvalho de Melo * Keep the entries sorted, they are bsearch'ed 1126c323cf04SArnaldo Carvalho de Melo */ 11277c3102b8SArnaldo Carvalho de Melo static struct annotate_config { 1128c323cf04SArnaldo Carvalho de Melo const char *name; 1129c323cf04SArnaldo Carvalho de Melo bool *value; 1130c323cf04SArnaldo Carvalho de Melo } annotate__configs[] = { 1131c323cf04SArnaldo Carvalho de Melo ANNOTATE_CFG(hide_src_code), 1132c323cf04SArnaldo Carvalho de Melo ANNOTATE_CFG(jump_arrows), 1133e592488cSAndi Kleen ANNOTATE_CFG(show_linenr), 1134c323cf04SArnaldo Carvalho de Melo ANNOTATE_CFG(show_nr_jumps), 11359cef4b0bSTaeung Song ANNOTATE_CFG(show_nr_samples), 11360c4a5bceSMartin Liška ANNOTATE_CFG(show_total_period), 113739ff7cdbSNamhyung Kim ANNOTATE_CFG(use_offset), 1138c323cf04SArnaldo Carvalho de Melo }; 1139c323cf04SArnaldo Carvalho de Melo 1140c323cf04SArnaldo Carvalho de Melo #undef ANNOTATE_CFG 1141c323cf04SArnaldo Carvalho de Melo 1142c323cf04SArnaldo Carvalho de Melo static int annotate_config__cmp(const void *name, const void *cfgp) 1143c323cf04SArnaldo Carvalho de Melo { 11447c3102b8SArnaldo Carvalho de Melo const struct annotate_config *cfg = cfgp; 1145c323cf04SArnaldo Carvalho de Melo 1146c323cf04SArnaldo Carvalho de Melo return strcmp(name, cfg->name); 1147c323cf04SArnaldo Carvalho de Melo } 1148c323cf04SArnaldo Carvalho de Melo 11491d037ca1SIrina Tirdea static int annotate__config(const char *var, const char *value, 11501d037ca1SIrina Tirdea void *data __maybe_unused) 1151c323cf04SArnaldo Carvalho de Melo { 11527c3102b8SArnaldo Carvalho de Melo struct annotate_config *cfg; 1153c323cf04SArnaldo Carvalho de Melo const char *name; 1154c323cf04SArnaldo Carvalho de Melo 11558e99b6d4SArnaldo Carvalho de Melo if (!strstarts(var, "annotate.")) 1156c323cf04SArnaldo Carvalho de Melo return 0; 1157c323cf04SArnaldo Carvalho de Melo 1158c323cf04SArnaldo Carvalho de Melo name = var + 9; 1159c323cf04SArnaldo Carvalho de Melo cfg = bsearch(name, annotate__configs, ARRAY_SIZE(annotate__configs), 11607c3102b8SArnaldo Carvalho de Melo sizeof(struct annotate_config), annotate_config__cmp); 1161c323cf04SArnaldo Carvalho de Melo 1162c323cf04SArnaldo Carvalho de Melo if (cfg == NULL) 1163f06cff7cSArnaldo Carvalho de Melo ui__warning("%s variable unknown, ignoring...", var); 1164f06cff7cSArnaldo Carvalho de Melo else 1165c323cf04SArnaldo Carvalho de Melo *cfg->value = perf_config_bool(name, value); 1166c323cf04SArnaldo Carvalho de Melo return 0; 1167c323cf04SArnaldo Carvalho de Melo } 1168c323cf04SArnaldo Carvalho de Melo 1169c323cf04SArnaldo Carvalho de Melo void annotate_browser__init(void) 1170c323cf04SArnaldo Carvalho de Melo { 1171c323cf04SArnaldo Carvalho de Melo perf_config(annotate__config, NULL); 1172c323cf04SArnaldo Carvalho de Melo } 1173