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" 1269fb09f6SJin Yao #include "../../util/evlist.h" 13fd20e811SArnaldo Carvalho de Melo #include <inttypes.h> 14aca7a94dSNamhyung Kim #include <pthread.h> 15877a7a11SArnaldo Carvalho de Melo #include <linux/kernel.h> 168e99b6d4SArnaldo Carvalho de Melo #include <linux/string.h> 17b0742e90SArnaldo Carvalho de Melo #include <sys/ttydefaults.h> 18aca7a94dSNamhyung Kim 190c4a5bceSMartin Liška struct disasm_line_samples { 200c4a5bceSMartin Liška double percent; 21bb79a232SArnaldo Carvalho de Melo struct sym_hist_entry he; 220c4a5bceSMartin Liška }; 230c4a5bceSMartin Liška 24dcaa3948SJin Yao struct arch; 25dcaa3948SJin Yao 26aca7a94dSNamhyung Kim struct annotate_browser { 27aca7a94dSNamhyung Kim struct ui_browser b; 28aca7a94dSNamhyung Kim struct rb_root entries; 29aca7a94dSNamhyung Kim struct rb_node *curr_hot; 307bcbcd58SJiri Olsa struct annotation_line *selection; 31dcaa3948SJin Yao struct arch *arch; 32cd0cccbaSArnaldo Carvalho de Melo struct annotation_options *opts; 33aca7a94dSNamhyung Kim bool searching_backwards; 34aca7a94dSNamhyung Kim char search_bf[128]; 35aca7a94dSNamhyung Kim }; 36aca7a94dSNamhyung Kim 3795aa89d9SArnaldo Carvalho de Melo static inline struct annotation *browser__annotation(struct ui_browser *browser) 3895aa89d9SArnaldo Carvalho de Melo { 3995aa89d9SArnaldo Carvalho de Melo struct map_symbol *ms = browser->priv; 4095aa89d9SArnaldo Carvalho de Melo return symbol__annotation(ms->sym); 4195aa89d9SArnaldo Carvalho de Melo } 4295aa89d9SArnaldo Carvalho de Melo 4316932d77SArnaldo Carvalho de Melo static bool disasm_line__filter(struct ui_browser *browser, void *entry) 44aca7a94dSNamhyung Kim { 4595aa89d9SArnaldo Carvalho de Melo struct annotation *notes = browser__annotation(browser); 46d5490b96SJiri Olsa struct annotation_line *al = list_entry(entry, struct annotation_line, node); 479b80d1f9SArnaldo Carvalho de Melo return annotation_line__filter(al, notes); 48aca7a94dSNamhyung Kim } 49aca7a94dSNamhyung Kim 5027feb761SArnaldo Carvalho de Melo static int ui_browser__jumps_percent_color(struct ui_browser *browser, int nr, bool current) 512402e4a9SArnaldo Carvalho de Melo { 5227feb761SArnaldo Carvalho de Melo struct annotation *notes = browser__annotation(browser); 53bc1c0f3dSArnaldo Carvalho de Melo 5427feb761SArnaldo Carvalho de Melo if (current && (!browser->use_navkeypressed || browser->navkeypressed)) 552402e4a9SArnaldo Carvalho de Melo return HE_COLORSET_SELECTED; 56bc1c0f3dSArnaldo Carvalho de Melo if (nr == notes->max_jump_sources) 572402e4a9SArnaldo Carvalho de Melo return HE_COLORSET_TOP; 582402e4a9SArnaldo Carvalho de Melo if (nr > 1) 592402e4a9SArnaldo Carvalho de Melo return HE_COLORSET_MEDIUM; 602402e4a9SArnaldo Carvalho de Melo return HE_COLORSET_NORMAL; 612402e4a9SArnaldo Carvalho de Melo } 622402e4a9SArnaldo Carvalho de Melo 63a1e9b74cSArnaldo Carvalho de Melo static int ui_browser__set_jumps_percent_color(void *browser, int nr, bool current) 642402e4a9SArnaldo Carvalho de Melo { 6527feb761SArnaldo Carvalho de Melo int color = ui_browser__jumps_percent_color(browser, nr, current); 6627feb761SArnaldo Carvalho de Melo return ui_browser__set_color(browser, color); 672402e4a9SArnaldo Carvalho de Melo } 682402e4a9SArnaldo Carvalho de Melo 69a1e9b74cSArnaldo Carvalho de Melo static int annotate_browser__set_color(void *browser, int color) 70aca7a94dSNamhyung Kim { 71a1e9b74cSArnaldo Carvalho de Melo return ui_browser__set_color(browser, color); 724ea08b52SArnaldo Carvalho de Melo } 734ea08b52SArnaldo Carvalho de Melo 74a1e9b74cSArnaldo Carvalho de Melo static void annotate_browser__write_graph(void *browser, int graph) 75a1e9b74cSArnaldo Carvalho de Melo { 76a1e9b74cSArnaldo Carvalho de Melo ui_browser__write_graph(browser, graph); 77a5433b3eSJiri Olsa } 78a5433b3eSJiri Olsa 792ba5eca1SArnaldo Carvalho de Melo static void annotate_browser__set_percent_color(void *browser, double percent, bool current) 802ba5eca1SArnaldo Carvalho de Melo { 812ba5eca1SArnaldo Carvalho de Melo ui_browser__set_percent_color(browser, percent, current); 822ba5eca1SArnaldo Carvalho de Melo } 832ba5eca1SArnaldo Carvalho de Melo 842ba5eca1SArnaldo Carvalho de Melo static void annotate_browser__printf(void *browser, const char *fmt, ...) 852ba5eca1SArnaldo Carvalho de Melo { 862ba5eca1SArnaldo Carvalho de Melo va_list args; 872ba5eca1SArnaldo Carvalho de Melo 882ba5eca1SArnaldo Carvalho de Melo va_start(args, fmt); 892ba5eca1SArnaldo Carvalho de Melo ui_browser__vprintf(browser, fmt, args); 902ba5eca1SArnaldo Carvalho de Melo va_end(args); 912ba5eca1SArnaldo Carvalho de Melo } 922ba5eca1SArnaldo Carvalho de Melo 93a5433b3eSJiri Olsa static void annotate_browser__write(struct ui_browser *browser, void *entry, int row) 94a5433b3eSJiri Olsa { 95a5433b3eSJiri Olsa struct annotate_browser *ab = container_of(browser, struct annotate_browser, b); 9695aa89d9SArnaldo Carvalho de Melo struct annotation *notes = browser__annotation(browser); 97a5433b3eSJiri Olsa struct annotation_line *al = list_entry(entry, struct annotation_line, node); 98c298304bSArnaldo Carvalho de Melo struct annotation_write_ops ops = { 99c298304bSArnaldo Carvalho de Melo .first_line = row == 0, 100c298304bSArnaldo Carvalho de Melo .current_entry = ui_browser__is_current_entry(browser, row), 101c298304bSArnaldo Carvalho de Melo .change_color = (!notes->options->hide_src_code && 102c298304bSArnaldo Carvalho de Melo (!ops.current_entry || 103c298304bSArnaldo Carvalho de Melo (browser->use_navkeypressed && 104c298304bSArnaldo Carvalho de Melo !browser->navkeypressed))), 105c298304bSArnaldo Carvalho de Melo .width = browser->width, 106c298304bSArnaldo Carvalho de Melo .obj = browser, 107c298304bSArnaldo Carvalho de Melo .set_color = annotate_browser__set_color, 108c298304bSArnaldo Carvalho de Melo .set_percent_color = annotate_browser__set_percent_color, 109c298304bSArnaldo Carvalho de Melo .set_jumps_percent_color = ui_browser__set_jumps_percent_color, 110c298304bSArnaldo Carvalho de Melo .printf = annotate_browser__printf, 111c298304bSArnaldo Carvalho de Melo .write_graph = annotate_browser__write_graph, 112c298304bSArnaldo Carvalho de Melo }; 113a5433b3eSJiri Olsa 114a5433b3eSJiri Olsa /* The scroll bar isn't being used */ 115a5433b3eSJiri Olsa if (!browser->navkeypressed) 116c298304bSArnaldo Carvalho de Melo ops.width += 1; 117a5433b3eSJiri Olsa 1184c650ddcSJiri Olsa annotation_line__write(al, notes, &ops, ab->opts); 119aca7a94dSNamhyung Kim 120c298304bSArnaldo Carvalho de Melo if (ops.current_entry) 121a5433b3eSJiri Olsa ab->selection = al; 122aca7a94dSNamhyung Kim } 123aca7a94dSNamhyung Kim 1247e63a13aSJin Yao static bool is_fused(struct annotate_browser *ab, struct disasm_line *cursor) 1257e63a13aSJin Yao { 126a17c4ca0SJiri Olsa struct disasm_line *pos = list_prev_entry(cursor, al.node); 1277e63a13aSJin Yao const char *name; 1287e63a13aSJin Yao 1297e63a13aSJin Yao if (!pos) 1307e63a13aSJin Yao return false; 1317e63a13aSJin Yao 1327e63a13aSJin Yao if (ins__is_lock(&pos->ins)) 1337e63a13aSJin Yao name = pos->ops.locked.ins.name; 1347e63a13aSJin Yao else 1357e63a13aSJin Yao name = pos->ins.name; 1367e63a13aSJin Yao 1377e63a13aSJin Yao if (!name || !cursor->ins.name) 1387e63a13aSJin Yao return false; 1397e63a13aSJin Yao 1407e63a13aSJin Yao return ins__is_fused(ab->arch, name, cursor->ins.name); 1417e63a13aSJin Yao } 1427e63a13aSJin Yao 1439d1ef56dSArnaldo Carvalho de Melo static void annotate_browser__draw_current_jump(struct ui_browser *browser) 144a3f895beSArnaldo Carvalho de Melo { 145a3f895beSArnaldo Carvalho de Melo struct annotate_browser *ab = container_of(browser, struct annotate_browser, b); 1467bcbcd58SJiri Olsa struct disasm_line *cursor = disasm_line(ab->selection); 147a5ef2702SJiri Olsa struct annotation_line *target; 14883b1f2aaSArnaldo Carvalho de Melo unsigned int from, to; 14932ae1efdSNamhyung Kim struct map_symbol *ms = ab->b.priv; 15032ae1efdSNamhyung Kim struct symbol *sym = ms->sym; 1510e83a7e9SArnaldo Carvalho de Melo struct annotation *notes = symbol__annotation(sym); 1526af612d2SArnaldo Carvalho de Melo u8 pcnt_width = annotation__pcnt_width(notes); 15300ea0eb2SArnaldo Carvalho de Melo int width; 15432ae1efdSNamhyung Kim 15532ae1efdSNamhyung Kim /* PLT symbols contain external offsets */ 15632ae1efdSNamhyung Kim if (strstr(sym->name, "@plt")) 15732ae1efdSNamhyung Kim return; 158a3f895beSArnaldo Carvalho de Melo 1592eff0611SArnaldo Carvalho de Melo if (!disasm_line__is_valid_local_jump(cursor, sym)) 160a3f895beSArnaldo Carvalho de Melo return; 161a3f895beSArnaldo Carvalho de Melo 1629c04409dSArnaldo Carvalho de Melo /* 1639c04409dSArnaldo Carvalho de Melo * This first was seen with a gcc function, _cpp_lex_token, that 1649c04409dSArnaldo Carvalho de Melo * has the usual jumps: 1659c04409dSArnaldo Carvalho de Melo * 1669c04409dSArnaldo Carvalho de Melo * │1159e6c: ↓ jne 115aa32 <_cpp_lex_token@@Base+0xf92> 1679c04409dSArnaldo Carvalho de Melo * 1689c04409dSArnaldo Carvalho de Melo * I.e. jumps to a label inside that function (_cpp_lex_token), and 1699c04409dSArnaldo Carvalho de Melo * those works, but also this kind: 1709c04409dSArnaldo Carvalho de Melo * 1719c04409dSArnaldo Carvalho de Melo * │1159e8b: ↓ jne c469be <cpp_named_operator2name@@Base+0xa72> 1729c04409dSArnaldo Carvalho de Melo * 1739c04409dSArnaldo Carvalho de Melo * I.e. jumps to another function, outside _cpp_lex_token, which 1749c04409dSArnaldo Carvalho de Melo * are not being correctly handled generating as a side effect references 1759c04409dSArnaldo Carvalho de Melo * to ab->offset[] entries that are set to NULL, so to make this code 1769c04409dSArnaldo Carvalho de Melo * more robust, check that here. 1779c04409dSArnaldo Carvalho de Melo * 1789c04409dSArnaldo Carvalho de Melo * A proper fix for will be put in place, looking at the function 1799c04409dSArnaldo Carvalho de Melo * name right after the '<' token and probably treating this like a 1809c04409dSArnaldo Carvalho de Melo * 'call' instruction. 1819c04409dSArnaldo Carvalho de Melo */ 1829d6bb41dSArnaldo Carvalho de Melo target = notes->offsets[cursor->ops.target.offset]; 1839c04409dSArnaldo Carvalho de Melo if (target == NULL) { 1849d6bb41dSArnaldo Carvalho de Melo ui_helpline__printf("WARN: jump target inconsistency, press 'o', notes->offsets[%#x] = NULL\n", 1859c04409dSArnaldo Carvalho de Melo cursor->ops.target.offset); 1869c04409dSArnaldo Carvalho de Melo return; 1879c04409dSArnaldo Carvalho de Melo } 1889d1ef56dSArnaldo Carvalho de Melo 18916932d77SArnaldo Carvalho de Melo if (notes->options->hide_src_code) { 1904850c92eSArnaldo Carvalho de Melo from = cursor->al.idx_asm; 1914850c92eSArnaldo Carvalho de Melo to = target->idx_asm; 192a3f895beSArnaldo Carvalho de Melo } else { 1934850c92eSArnaldo Carvalho de Melo from = (u64)cursor->al.idx; 1944850c92eSArnaldo Carvalho de Melo to = (u64)target->idx; 195a3f895beSArnaldo Carvalho de Melo } 196a3f895beSArnaldo Carvalho de Melo 1970e83a7e9SArnaldo Carvalho de Melo width = annotation__cycles_width(notes); 198b40982e8SJin Yao 19978ce08dfSTaeung Song ui_browser__set_color(browser, HE_COLORSET_JUMP_ARROWS); 200b40982e8SJin Yao __ui_browser__line_arrow(browser, 2019761e86eSArnaldo Carvalho de Melo pcnt_width + 2 + notes->widths.addr + width, 202c7e7b610SNamhyung Kim from, to); 2037e63a13aSJin Yao 2047e63a13aSJin Yao if (is_fused(ab, cursor)) { 2057e63a13aSJin Yao ui_browser__mark_fused(browser, 2069761e86eSArnaldo Carvalho de Melo pcnt_width + 3 + notes->widths.addr + width, 2077e63a13aSJin Yao from - 1, 2087e63a13aSJin Yao to > from ? true : false); 2097e63a13aSJin Yao } 210a3f895beSArnaldo Carvalho de Melo } 211a3f895beSArnaldo Carvalho de Melo 212a3f895beSArnaldo Carvalho de Melo static unsigned int annotate_browser__refresh(struct ui_browser *browser) 213a3f895beSArnaldo Carvalho de Melo { 21495aa89d9SArnaldo Carvalho de Melo struct annotation *notes = browser__annotation(browser); 215a3f895beSArnaldo Carvalho de Melo int ret = ui_browser__list_head_refresh(browser); 2166af612d2SArnaldo Carvalho de Melo int pcnt_width = annotation__pcnt_width(notes); 217a3f895beSArnaldo Carvalho de Melo 21816932d77SArnaldo Carvalho de Melo if (notes->options->jump_arrows) 2199d1ef56dSArnaldo Carvalho de Melo annotate_browser__draw_current_jump(browser); 220a3f895beSArnaldo Carvalho de Melo 22183b1f2aaSArnaldo Carvalho de Melo ui_browser__set_color(browser, HE_COLORSET_NORMAL); 222e726c851SArnaldo Carvalho de Melo __ui_browser__vline(browser, pcnt_width, 0, browser->rows - 1); 223a3f895beSArnaldo Carvalho de Melo return ret; 224a3f895beSArnaldo Carvalho de Melo } 225a3f895beSArnaldo Carvalho de Melo 226b15636c6SJiri Olsa static int disasm__cmp(struct annotation_line *a, struct annotation_line *b) 227c7e7b610SNamhyung Kim { 228c7e7b610SNamhyung Kim int i; 229c7e7b610SNamhyung Kim 230c2f938baSJiri Olsa for (i = 0; i < a->data_nr; i++) { 231c2f938baSJiri Olsa if (a->data[i].percent == b->data[i].percent) 232c7e7b610SNamhyung Kim continue; 233c2f938baSJiri Olsa return a->data[i].percent < b->data[i].percent; 234c7e7b610SNamhyung Kim } 235c7e7b610SNamhyung Kim return 0; 236c7e7b610SNamhyung Kim } 237c7e7b610SNamhyung Kim 238b15636c6SJiri Olsa static void disasm_rb_tree__insert(struct rb_root *root, struct annotation_line *al) 239aca7a94dSNamhyung Kim { 24029ed6e76SArnaldo Carvalho de Melo struct rb_node **p = &root->rb_node; 241aca7a94dSNamhyung Kim struct rb_node *parent = NULL; 2423ab6db8dSJiri Olsa struct annotation_line *l; 243aca7a94dSNamhyung Kim 244aca7a94dSNamhyung Kim while (*p != NULL) { 245aca7a94dSNamhyung Kim parent = *p; 2463ab6db8dSJiri Olsa l = rb_entry(parent, struct annotation_line, rb_node); 247c7e7b610SNamhyung Kim 248b15636c6SJiri Olsa if (disasm__cmp(al, l)) 249aca7a94dSNamhyung Kim p = &(*p)->rb_left; 250aca7a94dSNamhyung Kim else 251aca7a94dSNamhyung Kim p = &(*p)->rb_right; 252aca7a94dSNamhyung Kim } 2533ab6db8dSJiri Olsa rb_link_node(&al->rb_node, parent, p); 2543ab6db8dSJiri Olsa rb_insert_color(&al->rb_node, root); 255aca7a94dSNamhyung Kim } 256aca7a94dSNamhyung Kim 25705e8b080SArnaldo Carvalho de Melo static void annotate_browser__set_top(struct annotate_browser *browser, 258ec03a77dSJiri Olsa struct annotation_line *pos, u32 idx) 259aca7a94dSNamhyung Kim { 2609b80d1f9SArnaldo Carvalho de Melo struct annotation *notes = browser__annotation(&browser->b); 261aca7a94dSNamhyung Kim unsigned back; 262aca7a94dSNamhyung Kim 26305e8b080SArnaldo Carvalho de Melo ui_browser__refresh_dimensions(&browser->b); 26405e8b080SArnaldo Carvalho de Melo back = browser->b.height / 2; 26505e8b080SArnaldo Carvalho de Melo browser->b.top_idx = browser->b.index = idx; 266aca7a94dSNamhyung Kim 26705e8b080SArnaldo Carvalho de Melo while (browser->b.top_idx != 0 && back != 0) { 268ec03a77dSJiri Olsa pos = list_entry(pos->node.prev, struct annotation_line, node); 269aca7a94dSNamhyung Kim 2709b80d1f9SArnaldo Carvalho de Melo if (annotation_line__filter(pos, notes)) 271aca7a94dSNamhyung Kim continue; 272aca7a94dSNamhyung Kim 27305e8b080SArnaldo Carvalho de Melo --browser->b.top_idx; 274aca7a94dSNamhyung Kim --back; 275aca7a94dSNamhyung Kim } 276aca7a94dSNamhyung Kim 277ec03a77dSJiri Olsa browser->b.top = pos; 27805e8b080SArnaldo Carvalho de Melo browser->b.navkeypressed = true; 279aca7a94dSNamhyung Kim } 280aca7a94dSNamhyung Kim 281aca7a94dSNamhyung Kim static void annotate_browser__set_rb_top(struct annotate_browser *browser, 282aca7a94dSNamhyung Kim struct rb_node *nd) 283aca7a94dSNamhyung Kim { 28495aa89d9SArnaldo Carvalho de Melo struct annotation *notes = browser__annotation(&browser->b); 2854850c92eSArnaldo Carvalho de Melo struct annotation_line * pos = rb_entry(nd, struct annotation_line, rb_node); 2864850c92eSArnaldo Carvalho de Melo u32 idx = pos->idx; 287aca7a94dSNamhyung Kim 28816932d77SArnaldo Carvalho de Melo if (notes->options->hide_src_code) 2894850c92eSArnaldo Carvalho de Melo idx = pos->idx_asm; 290a44b45f2SArnaldo Carvalho de Melo annotate_browser__set_top(browser, pos, idx); 291aca7a94dSNamhyung Kim browser->curr_hot = nd; 292aca7a94dSNamhyung Kim } 293aca7a94dSNamhyung Kim 294aca7a94dSNamhyung Kim static void annotate_browser__calc_percent(struct annotate_browser *browser, 295db8fd07aSNamhyung Kim struct perf_evsel *evsel) 296aca7a94dSNamhyung Kim { 297aca7a94dSNamhyung Kim struct map_symbol *ms = browser->b.priv; 298aca7a94dSNamhyung Kim struct symbol *sym = ms->sym; 299aca7a94dSNamhyung Kim struct annotation *notes = symbol__annotation(sym); 300c4c72436SJiri Olsa struct disasm_line *pos; 301aca7a94dSNamhyung Kim 302aca7a94dSNamhyung Kim browser->entries = RB_ROOT; 303aca7a94dSNamhyung Kim 304aca7a94dSNamhyung Kim pthread_mutex_lock(¬es->lock); 305aca7a94dSNamhyung Kim 306e425da6cSJiri Olsa symbol__calc_percent(sym, evsel); 307e425da6cSJiri Olsa 308a17c4ca0SJiri Olsa list_for_each_entry(pos, ¬es->src->source, al.node) { 309c7e7b610SNamhyung Kim double max_percent = 0.0; 310c7e7b610SNamhyung Kim int i; 311e64aa75bSNamhyung Kim 312d5490b96SJiri Olsa if (pos->al.offset == -1) { 3135b12adc8SJiri Olsa RB_CLEAR_NODE(&pos->al.rb_node); 314e64aa75bSNamhyung Kim continue; 315e64aa75bSNamhyung Kim } 316e64aa75bSNamhyung Kim 317c2f938baSJiri Olsa for (i = 0; i < pos->al.data_nr; i++) { 3186d9f0c2dSJiri Olsa double percent; 3190c4a5bceSMartin Liška 3206d9f0c2dSJiri Olsa percent = annotation_data__percent(&pos->al.data[i], 321*d4265b1aSJiri Olsa browser->opts->percent_type); 3226d9f0c2dSJiri Olsa 3236d9f0c2dSJiri Olsa if (max_percent < percent) 3246d9f0c2dSJiri Olsa max_percent = percent; 325c7e7b610SNamhyung Kim } 326c7e7b610SNamhyung Kim 32737236d5eSJiri Olsa if (max_percent < 0.01 && pos->al.ipc == 0) { 3285b12adc8SJiri Olsa RB_CLEAR_NODE(&pos->al.rb_node); 329aca7a94dSNamhyung Kim continue; 330aca7a94dSNamhyung Kim } 331b15636c6SJiri Olsa disasm_rb_tree__insert(&browser->entries, &pos->al); 332aca7a94dSNamhyung Kim } 333aca7a94dSNamhyung Kim pthread_mutex_unlock(¬es->lock); 334aca7a94dSNamhyung Kim 335aca7a94dSNamhyung Kim browser->curr_hot = rb_last(&browser->entries); 336aca7a94dSNamhyung Kim } 337aca7a94dSNamhyung Kim 338aca7a94dSNamhyung Kim static bool annotate_browser__toggle_source(struct annotate_browser *browser) 339aca7a94dSNamhyung Kim { 34095aa89d9SArnaldo Carvalho de Melo struct annotation *notes = browser__annotation(&browser->b); 341ec03a77dSJiri Olsa struct annotation_line *al; 342aca7a94dSNamhyung Kim off_t offset = browser->b.index - browser->b.top_idx; 343aca7a94dSNamhyung Kim 344aca7a94dSNamhyung Kim browser->b.seek(&browser->b, offset, SEEK_CUR); 345ec03a77dSJiri Olsa al = list_entry(browser->b.top, struct annotation_line, node); 346aca7a94dSNamhyung Kim 34716932d77SArnaldo Carvalho de Melo if (notes->options->hide_src_code) { 3484850c92eSArnaldo Carvalho de Melo if (al->idx_asm < offset) 3494850c92eSArnaldo Carvalho de Melo offset = al->idx; 350aca7a94dSNamhyung Kim 3511cf5f98aSArnaldo Carvalho de Melo browser->b.nr_entries = notes->nr_entries; 35216932d77SArnaldo Carvalho de Melo notes->options->hide_src_code = false; 353aca7a94dSNamhyung Kim browser->b.seek(&browser->b, -offset, SEEK_CUR); 3544850c92eSArnaldo Carvalho de Melo browser->b.top_idx = al->idx - offset; 3554850c92eSArnaldo Carvalho de Melo browser->b.index = al->idx; 356aca7a94dSNamhyung Kim } else { 3574850c92eSArnaldo Carvalho de Melo if (al->idx_asm < 0) { 358aca7a94dSNamhyung Kim ui_helpline__puts("Only available for assembly lines."); 359aca7a94dSNamhyung Kim browser->b.seek(&browser->b, -offset, SEEK_CUR); 360aca7a94dSNamhyung Kim return false; 361aca7a94dSNamhyung Kim } 362aca7a94dSNamhyung Kim 3634850c92eSArnaldo Carvalho de Melo if (al->idx_asm < offset) 3644850c92eSArnaldo Carvalho de Melo offset = al->idx_asm; 365aca7a94dSNamhyung Kim 3661cf5f98aSArnaldo Carvalho de Melo browser->b.nr_entries = notes->nr_asm_entries; 36716932d77SArnaldo Carvalho de Melo notes->options->hide_src_code = true; 368aca7a94dSNamhyung Kim browser->b.seek(&browser->b, -offset, SEEK_CUR); 3694850c92eSArnaldo Carvalho de Melo browser->b.top_idx = al->idx_asm - offset; 3704850c92eSArnaldo Carvalho de Melo browser->b.index = al->idx_asm; 371aca7a94dSNamhyung Kim } 372aca7a94dSNamhyung Kim 373aca7a94dSNamhyung Kim return true; 374aca7a94dSNamhyung Kim } 375aca7a94dSNamhyung Kim 3761cf5f98aSArnaldo Carvalho de Melo static void ui_browser__init_asm_mode(struct ui_browser *browser) 377e9823b21SArnaldo Carvalho de Melo { 3781cf5f98aSArnaldo Carvalho de Melo struct annotation *notes = browser__annotation(browser); 3791cf5f98aSArnaldo Carvalho de Melo ui_browser__reset_index(browser); 3801cf5f98aSArnaldo Carvalho de Melo browser->nr_entries = notes->nr_asm_entries; 381e9823b21SArnaldo Carvalho de Melo } 382e9823b21SArnaldo Carvalho de Melo 38334f77abcSAdrian Hunter #define SYM_TITLE_MAX_SIZE (PATH_MAX + 64) 38434f77abcSAdrian Hunter 38534f77abcSAdrian Hunter static int sym_title(struct symbol *sym, struct map *map, char *title, 38634f77abcSAdrian Hunter size_t sz) 38734f77abcSAdrian Hunter { 38834f77abcSAdrian Hunter return snprintf(title, sz, "%s %s", sym->name, map->dso->long_name); 38934f77abcSAdrian Hunter } 39034f77abcSAdrian Hunter 391e4cc91b8SArnaldo Carvalho de Melo /* 392e4cc91b8SArnaldo Carvalho de Melo * This can be called from external jumps, i.e. jumps from one functon 393e4cc91b8SArnaldo Carvalho de Melo * to another, like from the kernel's entry_SYSCALL_64 function to the 394e4cc91b8SArnaldo Carvalho de Melo * swapgs_restore_regs_and_return_to_usermode() function. 395e4cc91b8SArnaldo Carvalho de Melo * 396e4cc91b8SArnaldo Carvalho de Melo * So all we check here is that dl->ops.target.sym is set, if it is, just 397e4cc91b8SArnaldo Carvalho de Melo * go to that function and when exiting from its disassembly, come back 398e4cc91b8SArnaldo Carvalho de Melo * to the calling function. 399e4cc91b8SArnaldo Carvalho de Melo */ 400db8fd07aSNamhyung Kim static bool annotate_browser__callq(struct annotate_browser *browser, 401db8fd07aSNamhyung Kim struct perf_evsel *evsel, 4029783adf7SNamhyung Kim struct hist_browser_timer *hbt) 403aca7a94dSNamhyung Kim { 404aca7a94dSNamhyung Kim struct map_symbol *ms = browser->b.priv; 4057bcbcd58SJiri Olsa struct disasm_line *dl = disasm_line(browser->selection); 406aca7a94dSNamhyung Kim struct annotation *notes; 40734f77abcSAdrian Hunter char title[SYM_TITLE_MAX_SIZE]; 408aca7a94dSNamhyung Kim 409696703afSArnaldo Carvalho de Melo if (!dl->ops.target.sym) { 410aca7a94dSNamhyung Kim ui_helpline__puts("The called function was not found."); 411aca7a94dSNamhyung Kim return true; 412aca7a94dSNamhyung Kim } 413aca7a94dSNamhyung Kim 414696703afSArnaldo Carvalho de Melo notes = symbol__annotation(dl->ops.target.sym); 415aca7a94dSNamhyung Kim pthread_mutex_lock(¬es->lock); 416aca7a94dSNamhyung Kim 41714c8dde1SArnaldo Carvalho de Melo if (!symbol__hists(dl->ops.target.sym, evsel->evlist->nr_entries)) { 418aca7a94dSNamhyung Kim pthread_mutex_unlock(¬es->lock); 419aca7a94dSNamhyung Kim ui__warning("Not enough memory for annotating '%s' symbol!\n", 420696703afSArnaldo Carvalho de Melo dl->ops.target.sym->name); 421aca7a94dSNamhyung Kim return true; 422aca7a94dSNamhyung Kim } 423aca7a94dSNamhyung Kim 424aca7a94dSNamhyung Kim pthread_mutex_unlock(¬es->lock); 425cd0cccbaSArnaldo Carvalho de Melo symbol__tui_annotate(dl->ops.target.sym, ms->map, evsel, hbt, browser->opts); 4261179e11bSAdrian Hunter sym_title(ms->sym, ms->map, title, sizeof(title)); 42734f77abcSAdrian Hunter ui_browser__show_title(&browser->b, title); 428aca7a94dSNamhyung Kim return true; 429aca7a94dSNamhyung Kim } 430aca7a94dSNamhyung Kim 43129ed6e76SArnaldo Carvalho de Melo static 43229ed6e76SArnaldo Carvalho de Melo struct disasm_line *annotate_browser__find_offset(struct annotate_browser *browser, 433aca7a94dSNamhyung Kim s64 offset, s64 *idx) 434aca7a94dSNamhyung Kim { 43595aa89d9SArnaldo Carvalho de Melo struct annotation *notes = browser__annotation(&browser->b); 43629ed6e76SArnaldo Carvalho de Melo struct disasm_line *pos; 437aca7a94dSNamhyung Kim 438aca7a94dSNamhyung Kim *idx = 0; 439a17c4ca0SJiri Olsa list_for_each_entry(pos, ¬es->src->source, al.node) { 440d5490b96SJiri Olsa if (pos->al.offset == offset) 441aca7a94dSNamhyung Kim return pos; 4429b80d1f9SArnaldo Carvalho de Melo if (!annotation_line__filter(&pos->al, notes)) 443aca7a94dSNamhyung Kim ++*idx; 444aca7a94dSNamhyung Kim } 445aca7a94dSNamhyung Kim 446aca7a94dSNamhyung Kim return NULL; 447aca7a94dSNamhyung Kim } 448aca7a94dSNamhyung Kim 449e4cc91b8SArnaldo Carvalho de Melo static bool annotate_browser__jump(struct annotate_browser *browser, 450e4cc91b8SArnaldo Carvalho de Melo struct perf_evsel *evsel, 451e4cc91b8SArnaldo Carvalho de Melo struct hist_browser_timer *hbt) 452aca7a94dSNamhyung Kim { 4537bcbcd58SJiri Olsa struct disasm_line *dl = disasm_line(browser->selection); 4545252b1aeSArnaldo Carvalho de Melo u64 offset; 4554f9d0325SArnaldo Carvalho de Melo s64 idx; 456aca7a94dSNamhyung Kim 45775b49202SArnaldo Carvalho de Melo if (!ins__is_jump(&dl->ins)) 458aca7a94dSNamhyung Kim return false; 459aca7a94dSNamhyung Kim 460e4cc91b8SArnaldo Carvalho de Melo if (dl->ops.target.outside) { 461e4cc91b8SArnaldo Carvalho de Melo annotate_browser__callq(browser, evsel, hbt); 462e4cc91b8SArnaldo Carvalho de Melo return true; 463e4cc91b8SArnaldo Carvalho de Melo } 464e4cc91b8SArnaldo Carvalho de Melo 4655252b1aeSArnaldo Carvalho de Melo offset = dl->ops.target.offset; 4665252b1aeSArnaldo Carvalho de Melo dl = annotate_browser__find_offset(browser, offset, &idx); 46729ed6e76SArnaldo Carvalho de Melo if (dl == NULL) { 4685252b1aeSArnaldo Carvalho de Melo ui_helpline__printf("Invalid jump offset: %" PRIx64, offset); 469aca7a94dSNamhyung Kim return true; 470aca7a94dSNamhyung Kim } 471aca7a94dSNamhyung Kim 472ec03a77dSJiri Olsa annotate_browser__set_top(browser, &dl->al, idx); 473aca7a94dSNamhyung Kim 474aca7a94dSNamhyung Kim return true; 475aca7a94dSNamhyung Kim } 476aca7a94dSNamhyung Kim 47729ed6e76SArnaldo Carvalho de Melo static 4789213afbdSJiri Olsa struct annotation_line *annotate_browser__find_string(struct annotate_browser *browser, 479aca7a94dSNamhyung Kim char *s, s64 *idx) 480aca7a94dSNamhyung Kim { 48195aa89d9SArnaldo Carvalho de Melo struct annotation *notes = browser__annotation(&browser->b); 4829213afbdSJiri Olsa struct annotation_line *al = browser->selection; 483aca7a94dSNamhyung Kim 484aca7a94dSNamhyung Kim *idx = browser->b.index; 4859213afbdSJiri Olsa list_for_each_entry_continue(al, ¬es->src->source, node) { 4869b80d1f9SArnaldo Carvalho de Melo if (annotation_line__filter(al, notes)) 487aca7a94dSNamhyung Kim continue; 488aca7a94dSNamhyung Kim 489aca7a94dSNamhyung Kim ++*idx; 490aca7a94dSNamhyung Kim 4919213afbdSJiri Olsa if (al->line && strstr(al->line, s) != NULL) 4929213afbdSJiri Olsa return al; 493aca7a94dSNamhyung Kim } 494aca7a94dSNamhyung Kim 495aca7a94dSNamhyung Kim return NULL; 496aca7a94dSNamhyung Kim } 497aca7a94dSNamhyung Kim 498aca7a94dSNamhyung Kim static bool __annotate_browser__search(struct annotate_browser *browser) 499aca7a94dSNamhyung Kim { 5009213afbdSJiri Olsa struct annotation_line *al; 501aca7a94dSNamhyung Kim s64 idx; 502aca7a94dSNamhyung Kim 5039213afbdSJiri Olsa al = annotate_browser__find_string(browser, browser->search_bf, &idx); 5049213afbdSJiri Olsa if (al == NULL) { 505aca7a94dSNamhyung Kim ui_helpline__puts("String not found!"); 506aca7a94dSNamhyung Kim return false; 507aca7a94dSNamhyung Kim } 508aca7a94dSNamhyung Kim 509ec03a77dSJiri Olsa annotate_browser__set_top(browser, al, idx); 510aca7a94dSNamhyung Kim browser->searching_backwards = false; 511aca7a94dSNamhyung Kim return true; 512aca7a94dSNamhyung Kim } 513aca7a94dSNamhyung Kim 51429ed6e76SArnaldo Carvalho de Melo static 5159213afbdSJiri Olsa struct annotation_line *annotate_browser__find_string_reverse(struct annotate_browser *browser, 516aca7a94dSNamhyung Kim char *s, s64 *idx) 517aca7a94dSNamhyung Kim { 51895aa89d9SArnaldo Carvalho de Melo struct annotation *notes = browser__annotation(&browser->b); 5199213afbdSJiri Olsa struct annotation_line *al = browser->selection; 520aca7a94dSNamhyung Kim 521aca7a94dSNamhyung Kim *idx = browser->b.index; 5229213afbdSJiri Olsa list_for_each_entry_continue_reverse(al, ¬es->src->source, node) { 5239b80d1f9SArnaldo Carvalho de Melo if (annotation_line__filter(al, notes)) 524aca7a94dSNamhyung Kim continue; 525aca7a94dSNamhyung Kim 526aca7a94dSNamhyung Kim --*idx; 527aca7a94dSNamhyung Kim 5289213afbdSJiri Olsa if (al->line && strstr(al->line, s) != NULL) 5299213afbdSJiri Olsa return al; 530aca7a94dSNamhyung Kim } 531aca7a94dSNamhyung Kim 532aca7a94dSNamhyung Kim return NULL; 533aca7a94dSNamhyung Kim } 534aca7a94dSNamhyung Kim 535aca7a94dSNamhyung Kim static bool __annotate_browser__search_reverse(struct annotate_browser *browser) 536aca7a94dSNamhyung Kim { 5379213afbdSJiri Olsa struct annotation_line *al; 538aca7a94dSNamhyung Kim s64 idx; 539aca7a94dSNamhyung Kim 5409213afbdSJiri Olsa al = annotate_browser__find_string_reverse(browser, browser->search_bf, &idx); 5419213afbdSJiri Olsa if (al == NULL) { 542aca7a94dSNamhyung Kim ui_helpline__puts("String not found!"); 543aca7a94dSNamhyung Kim return false; 544aca7a94dSNamhyung Kim } 545aca7a94dSNamhyung Kim 546ec03a77dSJiri Olsa annotate_browser__set_top(browser, al, idx); 547aca7a94dSNamhyung Kim browser->searching_backwards = true; 548aca7a94dSNamhyung Kim return true; 549aca7a94dSNamhyung Kim } 550aca7a94dSNamhyung Kim 551aca7a94dSNamhyung Kim static bool annotate_browser__search_window(struct annotate_browser *browser, 552aca7a94dSNamhyung Kim int delay_secs) 553aca7a94dSNamhyung Kim { 554aca7a94dSNamhyung Kim if (ui_browser__input_window("Search", "String: ", browser->search_bf, 555aca7a94dSNamhyung Kim "ENTER: OK, ESC: Cancel", 556aca7a94dSNamhyung Kim delay_secs * 2) != K_ENTER || 557aca7a94dSNamhyung Kim !*browser->search_bf) 558aca7a94dSNamhyung Kim return false; 559aca7a94dSNamhyung Kim 560aca7a94dSNamhyung Kim return true; 561aca7a94dSNamhyung Kim } 562aca7a94dSNamhyung Kim 563aca7a94dSNamhyung Kim static bool annotate_browser__search(struct annotate_browser *browser, int delay_secs) 564aca7a94dSNamhyung Kim { 565aca7a94dSNamhyung Kim if (annotate_browser__search_window(browser, delay_secs)) 566aca7a94dSNamhyung Kim return __annotate_browser__search(browser); 567aca7a94dSNamhyung Kim 568aca7a94dSNamhyung Kim return false; 569aca7a94dSNamhyung Kim } 570aca7a94dSNamhyung Kim 571aca7a94dSNamhyung Kim static bool annotate_browser__continue_search(struct annotate_browser *browser, 572aca7a94dSNamhyung Kim int delay_secs) 573aca7a94dSNamhyung Kim { 574aca7a94dSNamhyung Kim if (!*browser->search_bf) 575aca7a94dSNamhyung Kim return annotate_browser__search(browser, delay_secs); 576aca7a94dSNamhyung Kim 577aca7a94dSNamhyung Kim return __annotate_browser__search(browser); 578aca7a94dSNamhyung Kim } 579aca7a94dSNamhyung Kim 580aca7a94dSNamhyung Kim static bool annotate_browser__search_reverse(struct annotate_browser *browser, 581aca7a94dSNamhyung Kim int delay_secs) 582aca7a94dSNamhyung Kim { 583aca7a94dSNamhyung Kim if (annotate_browser__search_window(browser, delay_secs)) 584aca7a94dSNamhyung Kim return __annotate_browser__search_reverse(browser); 585aca7a94dSNamhyung Kim 586aca7a94dSNamhyung Kim return false; 587aca7a94dSNamhyung Kim } 588aca7a94dSNamhyung Kim 589aca7a94dSNamhyung Kim static 590aca7a94dSNamhyung Kim bool annotate_browser__continue_search_reverse(struct annotate_browser *browser, 591aca7a94dSNamhyung Kim int delay_secs) 592aca7a94dSNamhyung Kim { 593aca7a94dSNamhyung Kim if (!*browser->search_bf) 594aca7a94dSNamhyung Kim return annotate_browser__search_reverse(browser, delay_secs); 595aca7a94dSNamhyung Kim 596aca7a94dSNamhyung Kim return __annotate_browser__search_reverse(browser); 597aca7a94dSNamhyung Kim } 598aca7a94dSNamhyung Kim 5996920e285SArnaldo Carvalho de Melo static int annotate_browser__show(struct ui_browser *browser, char *title, const char *help) 6006920e285SArnaldo Carvalho de Melo { 6016920e285SArnaldo Carvalho de Melo struct map_symbol *ms = browser->priv; 6026920e285SArnaldo Carvalho de Melo struct symbol *sym = ms->sym; 6036920e285SArnaldo Carvalho de Melo char symbol_dso[SYM_TITLE_MAX_SIZE]; 6046920e285SArnaldo Carvalho de Melo 6056920e285SArnaldo Carvalho de Melo if (ui_browser__show(browser, title, help) < 0) 6066920e285SArnaldo Carvalho de Melo return -1; 6076920e285SArnaldo Carvalho de Melo 6086920e285SArnaldo Carvalho de Melo sym_title(sym, ms->map, symbol_dso, sizeof(symbol_dso)); 6096920e285SArnaldo Carvalho de Melo 6106920e285SArnaldo Carvalho de Melo ui_browser__gotorc_title(browser, 0, 0); 6116920e285SArnaldo Carvalho de Melo ui_browser__set_color(browser, HE_COLORSET_ROOT); 6126920e285SArnaldo Carvalho de Melo ui_browser__write_nstring(browser, symbol_dso, browser->width + 1); 6136920e285SArnaldo Carvalho de Melo return 0; 6146920e285SArnaldo Carvalho de Melo } 6156920e285SArnaldo Carvalho de Melo 616db8fd07aSNamhyung Kim static int annotate_browser__run(struct annotate_browser *browser, 617db8fd07aSNamhyung Kim struct perf_evsel *evsel, 6189783adf7SNamhyung Kim struct hist_browser_timer *hbt) 619aca7a94dSNamhyung Kim { 620aca7a94dSNamhyung Kim struct rb_node *nd = NULL; 6216920e285SArnaldo Carvalho de Melo struct hists *hists = evsel__hists(evsel); 62205e8b080SArnaldo Carvalho de Melo struct map_symbol *ms = browser->b.priv; 623aca7a94dSNamhyung Kim struct symbol *sym = ms->sym; 62416932d77SArnaldo Carvalho de Melo struct annotation *notes = symbol__annotation(ms->sym); 62554e7a4e8SArnaldo Carvalho de Melo const char *help = "Press 'h' for help on key bindings"; 6269783adf7SNamhyung Kim int delay_secs = hbt ? hbt->refresh : 0; 6276920e285SArnaldo Carvalho de Melo char title[256]; 628aca7a94dSNamhyung Kim int key; 629aca7a94dSNamhyung Kim 6300683d13cSJiri Olsa hists__scnprintf_title(hists, title, sizeof(title)); 6316920e285SArnaldo Carvalho de Melo if (annotate_browser__show(&browser->b, title, help) < 0) 632aca7a94dSNamhyung Kim return -1; 633aca7a94dSNamhyung Kim 634db8fd07aSNamhyung Kim annotate_browser__calc_percent(browser, evsel); 635aca7a94dSNamhyung Kim 63605e8b080SArnaldo Carvalho de Melo if (browser->curr_hot) { 63705e8b080SArnaldo Carvalho de Melo annotate_browser__set_rb_top(browser, browser->curr_hot); 63805e8b080SArnaldo Carvalho de Melo browser->b.navkeypressed = false; 639aca7a94dSNamhyung Kim } 640aca7a94dSNamhyung Kim 64105e8b080SArnaldo Carvalho de Melo nd = browser->curr_hot; 642aca7a94dSNamhyung Kim 643aca7a94dSNamhyung Kim while (1) { 64405e8b080SArnaldo Carvalho de Melo key = ui_browser__run(&browser->b, delay_secs); 645aca7a94dSNamhyung Kim 646aca7a94dSNamhyung Kim if (delay_secs != 0) { 647db8fd07aSNamhyung Kim annotate_browser__calc_percent(browser, evsel); 648aca7a94dSNamhyung Kim /* 649aca7a94dSNamhyung Kim * Current line focus got out of the list of most active 650aca7a94dSNamhyung Kim * lines, NULL it so that if TAB|UNTAB is pressed, we 651aca7a94dSNamhyung Kim * move to curr_hot (current hottest line). 652aca7a94dSNamhyung Kim */ 653aca7a94dSNamhyung Kim if (nd != NULL && RB_EMPTY_NODE(nd)) 654aca7a94dSNamhyung Kim nd = NULL; 655aca7a94dSNamhyung Kim } 656aca7a94dSNamhyung Kim 657aca7a94dSNamhyung Kim switch (key) { 658aca7a94dSNamhyung Kim case K_TIMER: 6599783adf7SNamhyung Kim if (hbt) 6609783adf7SNamhyung Kim hbt->timer(hbt->arg); 661aca7a94dSNamhyung Kim 6626920e285SArnaldo Carvalho de Melo if (delay_secs != 0) { 663db8fd07aSNamhyung Kim symbol__annotate_decay_histogram(sym, evsel->idx); 6646920e285SArnaldo Carvalho de Melo hists__scnprintf_title(hists, title, sizeof(title)); 6656920e285SArnaldo Carvalho de Melo annotate_browser__show(&browser->b, title, help); 6666920e285SArnaldo Carvalho de Melo } 667aca7a94dSNamhyung Kim continue; 668aca7a94dSNamhyung Kim case K_TAB: 669aca7a94dSNamhyung Kim if (nd != NULL) { 670aca7a94dSNamhyung Kim nd = rb_prev(nd); 671aca7a94dSNamhyung Kim if (nd == NULL) 67205e8b080SArnaldo Carvalho de Melo nd = rb_last(&browser->entries); 673aca7a94dSNamhyung Kim } else 67405e8b080SArnaldo Carvalho de Melo nd = browser->curr_hot; 675aca7a94dSNamhyung Kim break; 676aca7a94dSNamhyung Kim case K_UNTAB: 677d4913cbdSMarkus Trippelsdorf if (nd != NULL) { 678aca7a94dSNamhyung Kim nd = rb_next(nd); 679aca7a94dSNamhyung Kim if (nd == NULL) 68005e8b080SArnaldo Carvalho de Melo nd = rb_first(&browser->entries); 681d4913cbdSMarkus Trippelsdorf } else 68205e8b080SArnaldo Carvalho de Melo nd = browser->curr_hot; 683aca7a94dSNamhyung Kim break; 68454e7a4e8SArnaldo Carvalho de Melo case K_F1: 685aca7a94dSNamhyung Kim case 'h': 68605e8b080SArnaldo Carvalho de Melo ui_browser__help_window(&browser->b, 68754e7a4e8SArnaldo Carvalho de Melo "UP/DOWN/PGUP\n" 68854e7a4e8SArnaldo Carvalho de Melo "PGDN/SPACE Navigate\n" 68954e7a4e8SArnaldo Carvalho de Melo "q/ESC/CTRL+C Exit\n\n" 6907727a925SArnaldo Carvalho de Melo "ENTER Go to target\n" 6917727a925SArnaldo Carvalho de Melo "ESC Exit\n" 692eba9fac0SArnaldo Carvalho de Melo "H Go to hottest instruction\n" 693eba9fac0SArnaldo Carvalho de Melo "TAB/shift+TAB Cycle thru hottest instructions\n" 69454e7a4e8SArnaldo Carvalho de Melo "j Toggle showing jump to target arrows\n" 69554e7a4e8SArnaldo Carvalho de Melo "J Toggle showing number of jump sources on targets\n" 69654e7a4e8SArnaldo Carvalho de Melo "n Search next string\n" 69754e7a4e8SArnaldo Carvalho de Melo "o Toggle disassembler output/simplified view\n" 69851f39603SArnaldo Carvalho de Melo "O Bump offset level (jump targets -> +call -> all -> cycle thru)\n" 69954e7a4e8SArnaldo Carvalho de Melo "s Toggle source code view\n" 7003a555c77STaeung Song "t Circulate percent, total period, samples view\n" 7013e71fc03SJin Yao "c Show min/max cycle\n" 70254e7a4e8SArnaldo Carvalho de Melo "/ Search string\n" 703e592488cSAndi Kleen "k Toggle line numbers\n" 704d9bd7665SArnaldo Carvalho de Melo "P Print to [symbol_name].annotation file.\n" 70579ee47faSFeng Tang "r Run available scripts\n" 706fcd9fef9SArnaldo Carvalho de Melo "? Search string backwards\n"); 70754e7a4e8SArnaldo Carvalho de Melo continue; 70879ee47faSFeng Tang case 'r': 70979ee47faSFeng Tang { 71079ee47faSFeng Tang script_browse(NULL); 71179ee47faSFeng Tang continue; 71279ee47faSFeng Tang } 713e592488cSAndi Kleen case 'k': 71416932d77SArnaldo Carvalho de Melo notes->options->show_linenr = !notes->options->show_linenr; 715e592488cSAndi Kleen break; 71654e7a4e8SArnaldo Carvalho de Melo case 'H': 71705e8b080SArnaldo Carvalho de Melo nd = browser->curr_hot; 718aca7a94dSNamhyung Kim break; 719aca7a94dSNamhyung Kim case 's': 72005e8b080SArnaldo Carvalho de Melo if (annotate_browser__toggle_source(browser)) 721aca7a94dSNamhyung Kim ui_helpline__puts(help); 722aca7a94dSNamhyung Kim continue; 723aca7a94dSNamhyung Kim case 'o': 72416932d77SArnaldo Carvalho de Melo notes->options->use_offset = !notes->options->use_offset; 7259761e86eSArnaldo Carvalho de Melo annotation__update_column_widths(notes); 726aca7a94dSNamhyung Kim continue; 72751f39603SArnaldo Carvalho de Melo case 'O': 72851f39603SArnaldo Carvalho de Melo if (++notes->options->offset_level > ANNOTATION__MAX_OFFSET_LEVEL) 72951f39603SArnaldo Carvalho de Melo notes->options->offset_level = ANNOTATION__MIN_OFFSET_LEVEL; 73051f39603SArnaldo Carvalho de Melo continue; 7319d1ef56dSArnaldo Carvalho de Melo case 'j': 73216932d77SArnaldo Carvalho de Melo notes->options->jump_arrows = !notes->options->jump_arrows; 7339d1ef56dSArnaldo Carvalho de Melo continue; 7342402e4a9SArnaldo Carvalho de Melo case 'J': 73516932d77SArnaldo Carvalho de Melo notes->options->show_nr_jumps = !notes->options->show_nr_jumps; 7369761e86eSArnaldo Carvalho de Melo annotation__update_column_widths(notes); 737e9823b21SArnaldo Carvalho de Melo continue; 738aca7a94dSNamhyung Kim case '/': 73905e8b080SArnaldo Carvalho de Melo if (annotate_browser__search(browser, delay_secs)) { 740aca7a94dSNamhyung Kim show_help: 741aca7a94dSNamhyung Kim ui_helpline__puts(help); 742aca7a94dSNamhyung Kim } 743aca7a94dSNamhyung Kim continue; 744aca7a94dSNamhyung Kim case 'n': 74505e8b080SArnaldo Carvalho de Melo if (browser->searching_backwards ? 74605e8b080SArnaldo Carvalho de Melo annotate_browser__continue_search_reverse(browser, delay_secs) : 74705e8b080SArnaldo Carvalho de Melo annotate_browser__continue_search(browser, delay_secs)) 748aca7a94dSNamhyung Kim goto show_help; 749aca7a94dSNamhyung Kim continue; 750aca7a94dSNamhyung Kim case '?': 75105e8b080SArnaldo Carvalho de Melo if (annotate_browser__search_reverse(browser, delay_secs)) 752aca7a94dSNamhyung Kim goto show_help; 753aca7a94dSNamhyung Kim continue; 754e9823b21SArnaldo Carvalho de Melo case 'D': { 755e9823b21SArnaldo Carvalho de Melo static int seq; 756e9823b21SArnaldo Carvalho de Melo ui_helpline__pop(); 757e9823b21SArnaldo Carvalho de Melo ui_helpline__fpush("%d: nr_ent=%d, height=%d, idx=%d, top_idx=%d, nr_asm_entries=%d", 75805e8b080SArnaldo Carvalho de Melo seq++, browser->b.nr_entries, 75905e8b080SArnaldo Carvalho de Melo browser->b.height, 76005e8b080SArnaldo Carvalho de Melo browser->b.index, 76105e8b080SArnaldo Carvalho de Melo browser->b.top_idx, 7621cf5f98aSArnaldo Carvalho de Melo notes->nr_asm_entries); 763e9823b21SArnaldo Carvalho de Melo } 764e9823b21SArnaldo Carvalho de Melo continue; 765aca7a94dSNamhyung Kim case K_ENTER: 766aca7a94dSNamhyung Kim case K_RIGHT: 7677bcbcd58SJiri Olsa { 7687bcbcd58SJiri Olsa struct disasm_line *dl = disasm_line(browser->selection); 7697bcbcd58SJiri Olsa 77005e8b080SArnaldo Carvalho de Melo if (browser->selection == NULL) 771aca7a94dSNamhyung Kim ui_helpline__puts("Huh? No selection. Report to linux-kernel@vger.kernel.org"); 7727bcbcd58SJiri Olsa else if (browser->selection->offset == -1) 773aca7a94dSNamhyung Kim ui_helpline__puts("Actions are only available for assembly lines."); 7747bcbcd58SJiri Olsa else if (!dl->ins.ops) 775c4cceae3SArnaldo Carvalho de Melo goto show_sup_ins; 7767bcbcd58SJiri Olsa else if (ins__is_ret(&dl->ins)) 777c4cceae3SArnaldo Carvalho de Melo goto out; 778e4cc91b8SArnaldo Carvalho de Melo else if (!(annotate_browser__jump(browser, evsel, hbt) || 779db8fd07aSNamhyung Kim annotate_browser__callq(browser, evsel, hbt))) { 780c4cceae3SArnaldo Carvalho de Melo show_sup_ins: 7816ef94929SNaveen N. Rao ui_helpline__puts("Actions are only available for function call/return & jump/branch instructions."); 782c4cceae3SArnaldo Carvalho de Melo } 783aca7a94dSNamhyung Kim continue; 7847bcbcd58SJiri Olsa } 785d9bd7665SArnaldo Carvalho de Melo case 'P': 7864c650ddcSJiri Olsa map_symbol__annotation_dump(ms, evsel, browser->opts); 787d9bd7665SArnaldo Carvalho de Melo continue; 7880c4a5bceSMartin Liška case 't': 78916932d77SArnaldo Carvalho de Melo if (notes->options->show_total_period) { 79016932d77SArnaldo Carvalho de Melo notes->options->show_total_period = false; 79116932d77SArnaldo Carvalho de Melo notes->options->show_nr_samples = true; 79216932d77SArnaldo Carvalho de Melo } else if (notes->options->show_nr_samples) 79316932d77SArnaldo Carvalho de Melo notes->options->show_nr_samples = false; 7943a555c77STaeung Song else 79516932d77SArnaldo Carvalho de Melo notes->options->show_total_period = true; 7969761e86eSArnaldo Carvalho de Melo annotation__update_column_widths(notes); 7970c4a5bceSMartin Liška continue; 7983e71fc03SJin Yao case 'c': 7993e71fc03SJin Yao if (notes->options->show_minmax_cycle) 8003e71fc03SJin Yao notes->options->show_minmax_cycle = false; 8013e71fc03SJin Yao else 8023e71fc03SJin Yao notes->options->show_minmax_cycle = true; 8033e71fc03SJin Yao annotation__update_column_widths(notes); 8043e71fc03SJin Yao continue; 805aca7a94dSNamhyung Kim case K_LEFT: 806aca7a94dSNamhyung Kim case K_ESC: 807aca7a94dSNamhyung Kim case 'q': 808aca7a94dSNamhyung Kim case CTRL('c'): 809aca7a94dSNamhyung Kim goto out; 810aca7a94dSNamhyung Kim default: 811aca7a94dSNamhyung Kim continue; 812aca7a94dSNamhyung Kim } 813aca7a94dSNamhyung Kim 814aca7a94dSNamhyung Kim if (nd != NULL) 81505e8b080SArnaldo Carvalho de Melo annotate_browser__set_rb_top(browser, nd); 816aca7a94dSNamhyung Kim } 817aca7a94dSNamhyung Kim out: 81805e8b080SArnaldo Carvalho de Melo ui_browser__hide(&browser->b); 819aca7a94dSNamhyung Kim return key; 820aca7a94dSNamhyung Kim } 821aca7a94dSNamhyung Kim 822d5dbc518SArnaldo Carvalho de Melo int map_symbol__tui_annotate(struct map_symbol *ms, struct perf_evsel *evsel, 823cd0cccbaSArnaldo Carvalho de Melo struct hist_browser_timer *hbt, 824cd0cccbaSArnaldo Carvalho de Melo struct annotation_options *opts) 825d5dbc518SArnaldo Carvalho de Melo { 826cd0cccbaSArnaldo Carvalho de Melo return symbol__tui_annotate(ms->sym, ms->map, evsel, hbt, opts); 827d5dbc518SArnaldo Carvalho de Melo } 828d5dbc518SArnaldo Carvalho de Melo 829db8fd07aSNamhyung Kim int hist_entry__tui_annotate(struct hist_entry *he, struct perf_evsel *evsel, 830cd0cccbaSArnaldo Carvalho de Melo struct hist_browser_timer *hbt, 831cd0cccbaSArnaldo Carvalho de Melo struct annotation_options *opts) 832aca7a94dSNamhyung Kim { 833ed426915SNamhyung Kim /* reset abort key so that it can get Ctrl-C as a key */ 834ed426915SNamhyung Kim SLang_reset_tty(); 835ed426915SNamhyung Kim SLang_init_tty(0, 0, 0); 836ed426915SNamhyung Kim 837cd0cccbaSArnaldo Carvalho de Melo return map_symbol__tui_annotate(&he->ms, evsel, hbt, opts); 838aca7a94dSNamhyung Kim } 839aca7a94dSNamhyung Kim 840db8fd07aSNamhyung Kim int symbol__tui_annotate(struct symbol *sym, struct map *map, 841db8fd07aSNamhyung Kim struct perf_evsel *evsel, 842cd0cccbaSArnaldo Carvalho de Melo struct hist_browser_timer *hbt, 843cd0cccbaSArnaldo Carvalho de Melo struct annotation_options *opts) 844aca7a94dSNamhyung Kim { 8459d6bb41dSArnaldo Carvalho de Melo struct annotation *notes = symbol__annotation(sym); 846aca7a94dSNamhyung Kim struct map_symbol ms = { 847aca7a94dSNamhyung Kim .map = map, 848aca7a94dSNamhyung Kim .sym = sym, 849aca7a94dSNamhyung Kim }; 850aca7a94dSNamhyung Kim struct annotate_browser browser = { 851aca7a94dSNamhyung Kim .b = { 852a3f895beSArnaldo Carvalho de Melo .refresh = annotate_browser__refresh, 853aca7a94dSNamhyung Kim .seek = ui_browser__list_head_seek, 854aca7a94dSNamhyung Kim .write = annotate_browser__write, 85529ed6e76SArnaldo Carvalho de Melo .filter = disasm_line__filter, 8566920e285SArnaldo Carvalho de Melo .extra_title_lines = 1, /* for hists__scnprintf_title() */ 857aca7a94dSNamhyung Kim .priv = &ms, 858aca7a94dSNamhyung Kim .use_navkeypressed = true, 859aca7a94dSNamhyung Kim }, 860cd0cccbaSArnaldo Carvalho de Melo .opts = opts, 861aca7a94dSNamhyung Kim }; 862ee51d851SArnaldo Carvalho de Melo int ret = -1, err; 863aca7a94dSNamhyung Kim 864aca7a94dSNamhyung Kim if (sym == NULL) 865aca7a94dSNamhyung Kim return -1; 866aca7a94dSNamhyung Kim 867aca7a94dSNamhyung Kim if (map->dso->annotate_warned) 868aca7a94dSNamhyung Kim return -1; 869aca7a94dSNamhyung Kim 870cd0cccbaSArnaldo Carvalho de Melo err = symbol__annotate2(sym, map, evsel, opts, &browser.arch); 871ee51d851SArnaldo Carvalho de Melo if (err) { 872ee51d851SArnaldo Carvalho de Melo char msg[BUFSIZ]; 873ee51d851SArnaldo Carvalho de Melo symbol__strerror_disassemble(sym, map, err, msg, sizeof(msg)); 874ee51d851SArnaldo Carvalho de Melo ui__error("Couldn't annotate %s:\n%s", sym->name, msg); 875b793a401SArnaldo Carvalho de Melo goto out_free_offsets; 876aca7a94dSNamhyung Kim } 877aca7a94dSNamhyung Kim 8787727a925SArnaldo Carvalho de Melo ui_helpline__push("Press ESC to exit"); 879aca7a94dSNamhyung Kim 8805bc49f61SArnaldo Carvalho de Melo browser.b.width = notes->max_line_len; 8811cf5f98aSArnaldo Carvalho de Melo browser.b.nr_entries = notes->nr_entries; 882aca7a94dSNamhyung Kim browser.b.entries = ¬es->src->source, 883aca7a94dSNamhyung Kim browser.b.width += 18; /* Percentage */ 884e9823b21SArnaldo Carvalho de Melo 88516932d77SArnaldo Carvalho de Melo if (notes->options->hide_src_code) 8861cf5f98aSArnaldo Carvalho de Melo ui_browser__init_asm_mode(&browser.b); 887e9823b21SArnaldo Carvalho de Melo 888db8fd07aSNamhyung Kim ret = annotate_browser__run(&browser, evsel, hbt); 889f8eb37bdSJiri Olsa 890f8eb37bdSJiri Olsa annotated_source__purge(notes->src); 891b793a401SArnaldo Carvalho de Melo 892b793a401SArnaldo Carvalho de Melo out_free_offsets: 8939d6bb41dSArnaldo Carvalho de Melo zfree(¬es->offsets); 894aca7a94dSNamhyung Kim return ret; 895aca7a94dSNamhyung Kim } 896