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" 10*1101f69aSArnaldo Carvalho de Melo #include "../../util/map.h" 11aca7a94dSNamhyung Kim #include "../../util/symbol.h" 12db8fd07aSNamhyung Kim #include "../../util/evsel.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> 193e0d7953SJiri Olsa #include <asm/bug.h> 20aca7a94dSNamhyung Kim 210c4a5bceSMartin Liška struct disasm_line_samples { 220c4a5bceSMartin Liška double percent; 23bb79a232SArnaldo Carvalho de Melo struct sym_hist_entry he; 240c4a5bceSMartin Liška }; 250c4a5bceSMartin Liška 26dcaa3948SJin Yao struct arch; 27dcaa3948SJin Yao 28aca7a94dSNamhyung Kim struct annotate_browser { 29aca7a94dSNamhyung Kim struct ui_browser b; 30aca7a94dSNamhyung Kim struct rb_root entries; 31aca7a94dSNamhyung Kim struct rb_node *curr_hot; 327bcbcd58SJiri Olsa struct annotation_line *selection; 33dcaa3948SJin Yao struct arch *arch; 34cd0cccbaSArnaldo Carvalho de Melo struct annotation_options *opts; 35aca7a94dSNamhyung Kim bool searching_backwards; 36aca7a94dSNamhyung Kim char search_bf[128]; 37aca7a94dSNamhyung Kim }; 38aca7a94dSNamhyung Kim 3995aa89d9SArnaldo Carvalho de Melo static inline struct annotation *browser__annotation(struct ui_browser *browser) 4095aa89d9SArnaldo Carvalho de Melo { 4195aa89d9SArnaldo Carvalho de Melo struct map_symbol *ms = browser->priv; 4295aa89d9SArnaldo Carvalho de Melo return symbol__annotation(ms->sym); 4395aa89d9SArnaldo Carvalho de Melo } 4495aa89d9SArnaldo Carvalho de Melo 4516932d77SArnaldo Carvalho de Melo static bool disasm_line__filter(struct ui_browser *browser, void *entry) 46aca7a94dSNamhyung Kim { 4795aa89d9SArnaldo Carvalho de Melo struct annotation *notes = browser__annotation(browser); 48d5490b96SJiri Olsa struct annotation_line *al = list_entry(entry, struct annotation_line, node); 499b80d1f9SArnaldo Carvalho de Melo return annotation_line__filter(al, notes); 50aca7a94dSNamhyung Kim } 51aca7a94dSNamhyung Kim 5227feb761SArnaldo Carvalho de Melo static int ui_browser__jumps_percent_color(struct ui_browser *browser, int nr, bool current) 532402e4a9SArnaldo Carvalho de Melo { 5427feb761SArnaldo Carvalho de Melo struct annotation *notes = browser__annotation(browser); 55bc1c0f3dSArnaldo Carvalho de Melo 5627feb761SArnaldo Carvalho de Melo if (current && (!browser->use_navkeypressed || browser->navkeypressed)) 572402e4a9SArnaldo Carvalho de Melo return HE_COLORSET_SELECTED; 58bc1c0f3dSArnaldo Carvalho de Melo if (nr == notes->max_jump_sources) 592402e4a9SArnaldo Carvalho de Melo return HE_COLORSET_TOP; 602402e4a9SArnaldo Carvalho de Melo if (nr > 1) 612402e4a9SArnaldo Carvalho de Melo return HE_COLORSET_MEDIUM; 622402e4a9SArnaldo Carvalho de Melo return HE_COLORSET_NORMAL; 632402e4a9SArnaldo Carvalho de Melo } 642402e4a9SArnaldo Carvalho de Melo 65a1e9b74cSArnaldo Carvalho de Melo static int ui_browser__set_jumps_percent_color(void *browser, int nr, bool current) 662402e4a9SArnaldo Carvalho de Melo { 6727feb761SArnaldo Carvalho de Melo int color = ui_browser__jumps_percent_color(browser, nr, current); 6827feb761SArnaldo Carvalho de Melo return ui_browser__set_color(browser, color); 692402e4a9SArnaldo Carvalho de Melo } 702402e4a9SArnaldo Carvalho de Melo 71a1e9b74cSArnaldo Carvalho de Melo static int annotate_browser__set_color(void *browser, int color) 72aca7a94dSNamhyung Kim { 73a1e9b74cSArnaldo Carvalho de Melo return ui_browser__set_color(browser, color); 744ea08b52SArnaldo Carvalho de Melo } 754ea08b52SArnaldo Carvalho de Melo 76a1e9b74cSArnaldo Carvalho de Melo static void annotate_browser__write_graph(void *browser, int graph) 77a1e9b74cSArnaldo Carvalho de Melo { 78a1e9b74cSArnaldo Carvalho de Melo ui_browser__write_graph(browser, graph); 79a5433b3eSJiri Olsa } 80a5433b3eSJiri Olsa 812ba5eca1SArnaldo Carvalho de Melo static void annotate_browser__set_percent_color(void *browser, double percent, bool current) 822ba5eca1SArnaldo Carvalho de Melo { 832ba5eca1SArnaldo Carvalho de Melo ui_browser__set_percent_color(browser, percent, current); 842ba5eca1SArnaldo Carvalho de Melo } 852ba5eca1SArnaldo Carvalho de Melo 862ba5eca1SArnaldo Carvalho de Melo static void annotate_browser__printf(void *browser, const char *fmt, ...) 872ba5eca1SArnaldo Carvalho de Melo { 882ba5eca1SArnaldo Carvalho de Melo va_list args; 892ba5eca1SArnaldo Carvalho de Melo 902ba5eca1SArnaldo Carvalho de Melo va_start(args, fmt); 912ba5eca1SArnaldo Carvalho de Melo ui_browser__vprintf(browser, fmt, args); 922ba5eca1SArnaldo Carvalho de Melo va_end(args); 932ba5eca1SArnaldo Carvalho de Melo } 942ba5eca1SArnaldo Carvalho de Melo 95a5433b3eSJiri Olsa static void annotate_browser__write(struct ui_browser *browser, void *entry, int row) 96a5433b3eSJiri Olsa { 97a5433b3eSJiri Olsa struct annotate_browser *ab = container_of(browser, struct annotate_browser, b); 9895aa89d9SArnaldo Carvalho de Melo struct annotation *notes = browser__annotation(browser); 99a5433b3eSJiri Olsa struct annotation_line *al = list_entry(entry, struct annotation_line, node); 100c298304bSArnaldo Carvalho de Melo struct annotation_write_ops ops = { 101c298304bSArnaldo Carvalho de Melo .first_line = row == 0, 102c298304bSArnaldo Carvalho de Melo .current_entry = ui_browser__is_current_entry(browser, row), 103c298304bSArnaldo Carvalho de Melo .change_color = (!notes->options->hide_src_code && 104c298304bSArnaldo Carvalho de Melo (!ops.current_entry || 105c298304bSArnaldo Carvalho de Melo (browser->use_navkeypressed && 106c298304bSArnaldo Carvalho de Melo !browser->navkeypressed))), 107c298304bSArnaldo Carvalho de Melo .width = browser->width, 108c298304bSArnaldo Carvalho de Melo .obj = browser, 109c298304bSArnaldo Carvalho de Melo .set_color = annotate_browser__set_color, 110c298304bSArnaldo Carvalho de Melo .set_percent_color = annotate_browser__set_percent_color, 111c298304bSArnaldo Carvalho de Melo .set_jumps_percent_color = ui_browser__set_jumps_percent_color, 112c298304bSArnaldo Carvalho de Melo .printf = annotate_browser__printf, 113c298304bSArnaldo Carvalho de Melo .write_graph = annotate_browser__write_graph, 114c298304bSArnaldo Carvalho de Melo }; 115a5433b3eSJiri Olsa 116a5433b3eSJiri Olsa /* The scroll bar isn't being used */ 117a5433b3eSJiri Olsa if (!browser->navkeypressed) 118c298304bSArnaldo Carvalho de Melo ops.width += 1; 119a5433b3eSJiri Olsa 1204c650ddcSJiri Olsa annotation_line__write(al, notes, &ops, ab->opts); 121aca7a94dSNamhyung Kim 122c298304bSArnaldo Carvalho de Melo if (ops.current_entry) 123a5433b3eSJiri Olsa ab->selection = al; 124aca7a94dSNamhyung Kim } 125aca7a94dSNamhyung Kim 1267e63a13aSJin Yao static bool is_fused(struct annotate_browser *ab, struct disasm_line *cursor) 1277e63a13aSJin Yao { 128a17c4ca0SJiri Olsa struct disasm_line *pos = list_prev_entry(cursor, al.node); 1297e63a13aSJin Yao const char *name; 1307e63a13aSJin Yao 1317e63a13aSJin Yao if (!pos) 1327e63a13aSJin Yao return false; 1337e63a13aSJin Yao 1347e63a13aSJin Yao if (ins__is_lock(&pos->ins)) 1357e63a13aSJin Yao name = pos->ops.locked.ins.name; 1367e63a13aSJin Yao else 1377e63a13aSJin Yao name = pos->ins.name; 1387e63a13aSJin Yao 1397e63a13aSJin Yao if (!name || !cursor->ins.name) 1407e63a13aSJin Yao return false; 1417e63a13aSJin Yao 1427e63a13aSJin Yao return ins__is_fused(ab->arch, name, cursor->ins.name); 1437e63a13aSJin Yao } 1447e63a13aSJin Yao 1459d1ef56dSArnaldo Carvalho de Melo static void annotate_browser__draw_current_jump(struct ui_browser *browser) 146a3f895beSArnaldo Carvalho de Melo { 147a3f895beSArnaldo Carvalho de Melo struct annotate_browser *ab = container_of(browser, struct annotate_browser, b); 1487bcbcd58SJiri Olsa struct disasm_line *cursor = disasm_line(ab->selection); 149a5ef2702SJiri Olsa struct annotation_line *target; 15083b1f2aaSArnaldo Carvalho de Melo unsigned int from, to; 15132ae1efdSNamhyung Kim struct map_symbol *ms = ab->b.priv; 15232ae1efdSNamhyung Kim struct symbol *sym = ms->sym; 1530e83a7e9SArnaldo Carvalho de Melo struct annotation *notes = symbol__annotation(sym); 1546af612d2SArnaldo Carvalho de Melo u8 pcnt_width = annotation__pcnt_width(notes); 15500ea0eb2SArnaldo Carvalho de Melo int width; 15632ae1efdSNamhyung Kim 15732ae1efdSNamhyung Kim /* PLT symbols contain external offsets */ 15832ae1efdSNamhyung Kim if (strstr(sym->name, "@plt")) 15932ae1efdSNamhyung Kim return; 160a3f895beSArnaldo Carvalho de Melo 1612eff0611SArnaldo Carvalho de Melo if (!disasm_line__is_valid_local_jump(cursor, sym)) 162a3f895beSArnaldo Carvalho de Melo return; 163a3f895beSArnaldo Carvalho de Melo 1649c04409dSArnaldo Carvalho de Melo /* 1659c04409dSArnaldo Carvalho de Melo * This first was seen with a gcc function, _cpp_lex_token, that 1669c04409dSArnaldo Carvalho de Melo * has the usual jumps: 1679c04409dSArnaldo Carvalho de Melo * 1689c04409dSArnaldo Carvalho de Melo * │1159e6c: ↓ jne 115aa32 <_cpp_lex_token@@Base+0xf92> 1699c04409dSArnaldo Carvalho de Melo * 1709c04409dSArnaldo Carvalho de Melo * I.e. jumps to a label inside that function (_cpp_lex_token), and 1719c04409dSArnaldo Carvalho de Melo * those works, but also this kind: 1729c04409dSArnaldo Carvalho de Melo * 1739c04409dSArnaldo Carvalho de Melo * │1159e8b: ↓ jne c469be <cpp_named_operator2name@@Base+0xa72> 1749c04409dSArnaldo Carvalho de Melo * 1759c04409dSArnaldo Carvalho de Melo * I.e. jumps to another function, outside _cpp_lex_token, which 1769c04409dSArnaldo Carvalho de Melo * are not being correctly handled generating as a side effect references 1779c04409dSArnaldo Carvalho de Melo * to ab->offset[] entries that are set to NULL, so to make this code 1789c04409dSArnaldo Carvalho de Melo * more robust, check that here. 1799c04409dSArnaldo Carvalho de Melo * 1809c04409dSArnaldo Carvalho de Melo * A proper fix for will be put in place, looking at the function 1819c04409dSArnaldo Carvalho de Melo * name right after the '<' token and probably treating this like a 1829c04409dSArnaldo Carvalho de Melo * 'call' instruction. 1839c04409dSArnaldo Carvalho de Melo */ 1849d6bb41dSArnaldo Carvalho de Melo target = notes->offsets[cursor->ops.target.offset]; 1859c04409dSArnaldo Carvalho de Melo if (target == NULL) { 1869d6bb41dSArnaldo Carvalho de Melo ui_helpline__printf("WARN: jump target inconsistency, press 'o', notes->offsets[%#x] = NULL\n", 1879c04409dSArnaldo Carvalho de Melo cursor->ops.target.offset); 1889c04409dSArnaldo Carvalho de Melo return; 1899c04409dSArnaldo Carvalho de Melo } 1909d1ef56dSArnaldo Carvalho de Melo 19116932d77SArnaldo Carvalho de Melo if (notes->options->hide_src_code) { 1924850c92eSArnaldo Carvalho de Melo from = cursor->al.idx_asm; 1934850c92eSArnaldo Carvalho de Melo to = target->idx_asm; 194a3f895beSArnaldo Carvalho de Melo } else { 1954850c92eSArnaldo Carvalho de Melo from = (u64)cursor->al.idx; 1964850c92eSArnaldo Carvalho de Melo to = (u64)target->idx; 197a3f895beSArnaldo Carvalho de Melo } 198a3f895beSArnaldo Carvalho de Melo 1990e83a7e9SArnaldo Carvalho de Melo width = annotation__cycles_width(notes); 200b40982e8SJin Yao 20178ce08dfSTaeung Song ui_browser__set_color(browser, HE_COLORSET_JUMP_ARROWS); 202b40982e8SJin Yao __ui_browser__line_arrow(browser, 2039761e86eSArnaldo Carvalho de Melo pcnt_width + 2 + notes->widths.addr + width, 204c7e7b610SNamhyung Kim from, to); 2057e63a13aSJin Yao 2067e63a13aSJin Yao if (is_fused(ab, cursor)) { 2077e63a13aSJin Yao ui_browser__mark_fused(browser, 2089761e86eSArnaldo Carvalho de Melo pcnt_width + 3 + notes->widths.addr + width, 2097e63a13aSJin Yao from - 1, 2107e63a13aSJin Yao to > from ? true : false); 2117e63a13aSJin Yao } 212a3f895beSArnaldo Carvalho de Melo } 213a3f895beSArnaldo Carvalho de Melo 214a3f895beSArnaldo Carvalho de Melo static unsigned int annotate_browser__refresh(struct ui_browser *browser) 215a3f895beSArnaldo Carvalho de Melo { 21695aa89d9SArnaldo Carvalho de Melo struct annotation *notes = browser__annotation(browser); 217a3f895beSArnaldo Carvalho de Melo int ret = ui_browser__list_head_refresh(browser); 2186af612d2SArnaldo Carvalho de Melo int pcnt_width = annotation__pcnt_width(notes); 219a3f895beSArnaldo Carvalho de Melo 22016932d77SArnaldo Carvalho de Melo if (notes->options->jump_arrows) 2219d1ef56dSArnaldo Carvalho de Melo annotate_browser__draw_current_jump(browser); 222a3f895beSArnaldo Carvalho de Melo 22383b1f2aaSArnaldo Carvalho de Melo ui_browser__set_color(browser, HE_COLORSET_NORMAL); 224e726c851SArnaldo Carvalho de Melo __ui_browser__vline(browser, pcnt_width, 0, browser->rows - 1); 225a3f895beSArnaldo Carvalho de Melo return ret; 226a3f895beSArnaldo Carvalho de Melo } 227a3f895beSArnaldo Carvalho de Melo 228da06d568SHe Kuang static double disasm__cmp(struct annotation_line *a, struct annotation_line *b, 229da06d568SHe Kuang int percent_type) 230c7e7b610SNamhyung Kim { 231c7e7b610SNamhyung Kim int i; 232c7e7b610SNamhyung Kim 233c2f938baSJiri Olsa for (i = 0; i < a->data_nr; i++) { 234da06d568SHe Kuang if (a->data[i].percent[percent_type] == b->data[i].percent[percent_type]) 235c7e7b610SNamhyung Kim continue; 236da06d568SHe Kuang return a->data[i].percent[percent_type] - 237da06d568SHe Kuang b->data[i].percent[percent_type]; 238c7e7b610SNamhyung Kim } 239c7e7b610SNamhyung Kim return 0; 240c7e7b610SNamhyung Kim } 241c7e7b610SNamhyung Kim 242da06d568SHe Kuang static void disasm_rb_tree__insert(struct annotate_browser *browser, 243da06d568SHe Kuang struct annotation_line *al) 244aca7a94dSNamhyung Kim { 245da06d568SHe Kuang struct rb_root *root = &browser->entries; 24629ed6e76SArnaldo Carvalho de Melo struct rb_node **p = &root->rb_node; 247aca7a94dSNamhyung Kim struct rb_node *parent = NULL; 2483ab6db8dSJiri Olsa struct annotation_line *l; 249aca7a94dSNamhyung Kim 250aca7a94dSNamhyung Kim while (*p != NULL) { 251aca7a94dSNamhyung Kim parent = *p; 2523ab6db8dSJiri Olsa l = rb_entry(parent, struct annotation_line, rb_node); 253c7e7b610SNamhyung Kim 254da06d568SHe Kuang if (disasm__cmp(al, l, browser->opts->percent_type) < 0) 255aca7a94dSNamhyung Kim p = &(*p)->rb_left; 256aca7a94dSNamhyung Kim else 257aca7a94dSNamhyung Kim p = &(*p)->rb_right; 258aca7a94dSNamhyung Kim } 2593ab6db8dSJiri Olsa rb_link_node(&al->rb_node, parent, p); 2603ab6db8dSJiri Olsa rb_insert_color(&al->rb_node, root); 261aca7a94dSNamhyung Kim } 262aca7a94dSNamhyung Kim 26305e8b080SArnaldo Carvalho de Melo static void annotate_browser__set_top(struct annotate_browser *browser, 264ec03a77dSJiri Olsa struct annotation_line *pos, u32 idx) 265aca7a94dSNamhyung Kim { 2669b80d1f9SArnaldo Carvalho de Melo struct annotation *notes = browser__annotation(&browser->b); 267aca7a94dSNamhyung Kim unsigned back; 268aca7a94dSNamhyung Kim 26905e8b080SArnaldo Carvalho de Melo ui_browser__refresh_dimensions(&browser->b); 27005e8b080SArnaldo Carvalho de Melo back = browser->b.height / 2; 27105e8b080SArnaldo Carvalho de Melo browser->b.top_idx = browser->b.index = idx; 272aca7a94dSNamhyung Kim 27305e8b080SArnaldo Carvalho de Melo while (browser->b.top_idx != 0 && back != 0) { 274ec03a77dSJiri Olsa pos = list_entry(pos->node.prev, struct annotation_line, node); 275aca7a94dSNamhyung Kim 2769b80d1f9SArnaldo Carvalho de Melo if (annotation_line__filter(pos, notes)) 277aca7a94dSNamhyung Kim continue; 278aca7a94dSNamhyung Kim 27905e8b080SArnaldo Carvalho de Melo --browser->b.top_idx; 280aca7a94dSNamhyung Kim --back; 281aca7a94dSNamhyung Kim } 282aca7a94dSNamhyung Kim 283ec03a77dSJiri Olsa browser->b.top = pos; 28405e8b080SArnaldo Carvalho de Melo browser->b.navkeypressed = true; 285aca7a94dSNamhyung Kim } 286aca7a94dSNamhyung Kim 287aca7a94dSNamhyung Kim static void annotate_browser__set_rb_top(struct annotate_browser *browser, 288aca7a94dSNamhyung Kim struct rb_node *nd) 289aca7a94dSNamhyung Kim { 29095aa89d9SArnaldo Carvalho de Melo struct annotation *notes = browser__annotation(&browser->b); 2914850c92eSArnaldo Carvalho de Melo struct annotation_line * pos = rb_entry(nd, struct annotation_line, rb_node); 2924850c92eSArnaldo Carvalho de Melo u32 idx = pos->idx; 293aca7a94dSNamhyung Kim 29416932d77SArnaldo Carvalho de Melo if (notes->options->hide_src_code) 2954850c92eSArnaldo Carvalho de Melo idx = pos->idx_asm; 296a44b45f2SArnaldo Carvalho de Melo annotate_browser__set_top(browser, pos, idx); 297aca7a94dSNamhyung Kim browser->curr_hot = nd; 298aca7a94dSNamhyung Kim } 299aca7a94dSNamhyung Kim 300aca7a94dSNamhyung Kim static void annotate_browser__calc_percent(struct annotate_browser *browser, 301db8fd07aSNamhyung Kim struct perf_evsel *evsel) 302aca7a94dSNamhyung Kim { 303aca7a94dSNamhyung Kim struct map_symbol *ms = browser->b.priv; 304aca7a94dSNamhyung Kim struct symbol *sym = ms->sym; 305aca7a94dSNamhyung Kim struct annotation *notes = symbol__annotation(sym); 306c4c72436SJiri Olsa struct disasm_line *pos; 307aca7a94dSNamhyung Kim 308aca7a94dSNamhyung Kim browser->entries = RB_ROOT; 309aca7a94dSNamhyung Kim 310aca7a94dSNamhyung Kim pthread_mutex_lock(¬es->lock); 311aca7a94dSNamhyung Kim 312e425da6cSJiri Olsa symbol__calc_percent(sym, evsel); 313e425da6cSJiri Olsa 314a17c4ca0SJiri Olsa list_for_each_entry(pos, ¬es->src->source, al.node) { 315c7e7b610SNamhyung Kim double max_percent = 0.0; 316c7e7b610SNamhyung Kim int i; 317e64aa75bSNamhyung Kim 318d5490b96SJiri Olsa if (pos->al.offset == -1) { 3195b12adc8SJiri Olsa RB_CLEAR_NODE(&pos->al.rb_node); 320e64aa75bSNamhyung Kim continue; 321e64aa75bSNamhyung Kim } 322e64aa75bSNamhyung Kim 323c2f938baSJiri Olsa for (i = 0; i < pos->al.data_nr; i++) { 3246d9f0c2dSJiri Olsa double percent; 3250c4a5bceSMartin Liška 3266d9f0c2dSJiri Olsa percent = annotation_data__percent(&pos->al.data[i], 327d4265b1aSJiri Olsa browser->opts->percent_type); 3286d9f0c2dSJiri Olsa 3296d9f0c2dSJiri Olsa if (max_percent < percent) 3306d9f0c2dSJiri Olsa max_percent = percent; 331c7e7b610SNamhyung Kim } 332c7e7b610SNamhyung Kim 33337236d5eSJiri Olsa if (max_percent < 0.01 && pos->al.ipc == 0) { 3345b12adc8SJiri Olsa RB_CLEAR_NODE(&pos->al.rb_node); 335aca7a94dSNamhyung Kim continue; 336aca7a94dSNamhyung Kim } 337da06d568SHe Kuang disasm_rb_tree__insert(browser, &pos->al); 338aca7a94dSNamhyung Kim } 339aca7a94dSNamhyung Kim pthread_mutex_unlock(¬es->lock); 340aca7a94dSNamhyung Kim 341aca7a94dSNamhyung Kim browser->curr_hot = rb_last(&browser->entries); 342aca7a94dSNamhyung Kim } 343aca7a94dSNamhyung Kim 344aca7a94dSNamhyung Kim static bool annotate_browser__toggle_source(struct annotate_browser *browser) 345aca7a94dSNamhyung Kim { 34695aa89d9SArnaldo Carvalho de Melo struct annotation *notes = browser__annotation(&browser->b); 347ec03a77dSJiri Olsa struct annotation_line *al; 348aca7a94dSNamhyung Kim off_t offset = browser->b.index - browser->b.top_idx; 349aca7a94dSNamhyung Kim 350aca7a94dSNamhyung Kim browser->b.seek(&browser->b, offset, SEEK_CUR); 351ec03a77dSJiri Olsa al = list_entry(browser->b.top, struct annotation_line, node); 352aca7a94dSNamhyung Kim 35316932d77SArnaldo Carvalho de Melo if (notes->options->hide_src_code) { 3544850c92eSArnaldo Carvalho de Melo if (al->idx_asm < offset) 3554850c92eSArnaldo Carvalho de Melo offset = al->idx; 356aca7a94dSNamhyung Kim 3571cf5f98aSArnaldo Carvalho de Melo browser->b.nr_entries = notes->nr_entries; 35816932d77SArnaldo Carvalho de Melo notes->options->hide_src_code = false; 359aca7a94dSNamhyung Kim browser->b.seek(&browser->b, -offset, SEEK_CUR); 3604850c92eSArnaldo Carvalho de Melo browser->b.top_idx = al->idx - offset; 3614850c92eSArnaldo Carvalho de Melo browser->b.index = al->idx; 362aca7a94dSNamhyung Kim } else { 3634850c92eSArnaldo Carvalho de Melo if (al->idx_asm < 0) { 364aca7a94dSNamhyung Kim ui_helpline__puts("Only available for assembly lines."); 365aca7a94dSNamhyung Kim browser->b.seek(&browser->b, -offset, SEEK_CUR); 366aca7a94dSNamhyung Kim return false; 367aca7a94dSNamhyung Kim } 368aca7a94dSNamhyung Kim 3694850c92eSArnaldo Carvalho de Melo if (al->idx_asm < offset) 3704850c92eSArnaldo Carvalho de Melo offset = al->idx_asm; 371aca7a94dSNamhyung Kim 3721cf5f98aSArnaldo Carvalho de Melo browser->b.nr_entries = notes->nr_asm_entries; 37316932d77SArnaldo Carvalho de Melo notes->options->hide_src_code = true; 374aca7a94dSNamhyung Kim browser->b.seek(&browser->b, -offset, SEEK_CUR); 3754850c92eSArnaldo Carvalho de Melo browser->b.top_idx = al->idx_asm - offset; 3764850c92eSArnaldo Carvalho de Melo browser->b.index = al->idx_asm; 377aca7a94dSNamhyung Kim } 378aca7a94dSNamhyung Kim 379aca7a94dSNamhyung Kim return true; 380aca7a94dSNamhyung Kim } 381aca7a94dSNamhyung Kim 3821cf5f98aSArnaldo Carvalho de Melo static void ui_browser__init_asm_mode(struct ui_browser *browser) 383e9823b21SArnaldo Carvalho de Melo { 3841cf5f98aSArnaldo Carvalho de Melo struct annotation *notes = browser__annotation(browser); 3851cf5f98aSArnaldo Carvalho de Melo ui_browser__reset_index(browser); 3861cf5f98aSArnaldo Carvalho de Melo browser->nr_entries = notes->nr_asm_entries; 387e9823b21SArnaldo Carvalho de Melo } 388e9823b21SArnaldo Carvalho de Melo 38934f77abcSAdrian Hunter #define SYM_TITLE_MAX_SIZE (PATH_MAX + 64) 39034f77abcSAdrian Hunter 39134f77abcSAdrian Hunter static int sym_title(struct symbol *sym, struct map *map, char *title, 3923e0d7953SJiri Olsa size_t sz, int percent_type) 39334f77abcSAdrian Hunter { 3943e0d7953SJiri Olsa return snprintf(title, sz, "%s %s [Percent: %s]", sym->name, map->dso->long_name, 3953e0d7953SJiri Olsa percent_type_str(percent_type)); 39634f77abcSAdrian Hunter } 39734f77abcSAdrian Hunter 398e4cc91b8SArnaldo Carvalho de Melo /* 399e4cc91b8SArnaldo Carvalho de Melo * This can be called from external jumps, i.e. jumps from one functon 400e4cc91b8SArnaldo Carvalho de Melo * to another, like from the kernel's entry_SYSCALL_64 function to the 401e4cc91b8SArnaldo Carvalho de Melo * swapgs_restore_regs_and_return_to_usermode() function. 402e4cc91b8SArnaldo Carvalho de Melo * 403e4cc91b8SArnaldo Carvalho de Melo * So all we check here is that dl->ops.target.sym is set, if it is, just 404e4cc91b8SArnaldo Carvalho de Melo * go to that function and when exiting from its disassembly, come back 405e4cc91b8SArnaldo Carvalho de Melo * to the calling function. 406e4cc91b8SArnaldo Carvalho de Melo */ 407db8fd07aSNamhyung Kim static bool annotate_browser__callq(struct annotate_browser *browser, 408db8fd07aSNamhyung Kim struct perf_evsel *evsel, 4099783adf7SNamhyung Kim struct hist_browser_timer *hbt) 410aca7a94dSNamhyung Kim { 411aca7a94dSNamhyung Kim struct map_symbol *ms = browser->b.priv; 4127bcbcd58SJiri Olsa struct disasm_line *dl = disasm_line(browser->selection); 413aca7a94dSNamhyung Kim struct annotation *notes; 41434f77abcSAdrian Hunter char title[SYM_TITLE_MAX_SIZE]; 415aca7a94dSNamhyung Kim 416696703afSArnaldo Carvalho de Melo if (!dl->ops.target.sym) { 417aca7a94dSNamhyung Kim ui_helpline__puts("The called function was not found."); 418aca7a94dSNamhyung Kim return true; 419aca7a94dSNamhyung Kim } 420aca7a94dSNamhyung Kim 421696703afSArnaldo Carvalho de Melo notes = symbol__annotation(dl->ops.target.sym); 422aca7a94dSNamhyung Kim pthread_mutex_lock(¬es->lock); 423aca7a94dSNamhyung Kim 42414c8dde1SArnaldo Carvalho de Melo if (!symbol__hists(dl->ops.target.sym, evsel->evlist->nr_entries)) { 425aca7a94dSNamhyung Kim pthread_mutex_unlock(¬es->lock); 426aca7a94dSNamhyung Kim ui__warning("Not enough memory for annotating '%s' symbol!\n", 427696703afSArnaldo Carvalho de Melo dl->ops.target.sym->name); 428aca7a94dSNamhyung Kim return true; 429aca7a94dSNamhyung Kim } 430aca7a94dSNamhyung Kim 431aca7a94dSNamhyung Kim pthread_mutex_unlock(¬es->lock); 432cd0cccbaSArnaldo Carvalho de Melo symbol__tui_annotate(dl->ops.target.sym, ms->map, evsel, hbt, browser->opts); 4333e0d7953SJiri Olsa sym_title(ms->sym, ms->map, title, sizeof(title), browser->opts->percent_type); 43434f77abcSAdrian Hunter ui_browser__show_title(&browser->b, title); 435aca7a94dSNamhyung Kim return true; 436aca7a94dSNamhyung Kim } 437aca7a94dSNamhyung Kim 43829ed6e76SArnaldo Carvalho de Melo static 43929ed6e76SArnaldo Carvalho de Melo struct disasm_line *annotate_browser__find_offset(struct annotate_browser *browser, 440aca7a94dSNamhyung Kim s64 offset, s64 *idx) 441aca7a94dSNamhyung Kim { 44295aa89d9SArnaldo Carvalho de Melo struct annotation *notes = browser__annotation(&browser->b); 44329ed6e76SArnaldo Carvalho de Melo struct disasm_line *pos; 444aca7a94dSNamhyung Kim 445aca7a94dSNamhyung Kim *idx = 0; 446a17c4ca0SJiri Olsa list_for_each_entry(pos, ¬es->src->source, al.node) { 447d5490b96SJiri Olsa if (pos->al.offset == offset) 448aca7a94dSNamhyung Kim return pos; 4499b80d1f9SArnaldo Carvalho de Melo if (!annotation_line__filter(&pos->al, notes)) 450aca7a94dSNamhyung Kim ++*idx; 451aca7a94dSNamhyung Kim } 452aca7a94dSNamhyung Kim 453aca7a94dSNamhyung Kim return NULL; 454aca7a94dSNamhyung Kim } 455aca7a94dSNamhyung Kim 456e4cc91b8SArnaldo Carvalho de Melo static bool annotate_browser__jump(struct annotate_browser *browser, 457e4cc91b8SArnaldo Carvalho de Melo struct perf_evsel *evsel, 458e4cc91b8SArnaldo Carvalho de Melo struct hist_browser_timer *hbt) 459aca7a94dSNamhyung Kim { 4607bcbcd58SJiri Olsa struct disasm_line *dl = disasm_line(browser->selection); 4615252b1aeSArnaldo Carvalho de Melo u64 offset; 4624f9d0325SArnaldo Carvalho de Melo s64 idx; 463aca7a94dSNamhyung Kim 46475b49202SArnaldo Carvalho de Melo if (!ins__is_jump(&dl->ins)) 465aca7a94dSNamhyung Kim return false; 466aca7a94dSNamhyung Kim 467e4cc91b8SArnaldo Carvalho de Melo if (dl->ops.target.outside) { 468e4cc91b8SArnaldo Carvalho de Melo annotate_browser__callq(browser, evsel, hbt); 469e4cc91b8SArnaldo Carvalho de Melo return true; 470e4cc91b8SArnaldo Carvalho de Melo } 471e4cc91b8SArnaldo Carvalho de Melo 4725252b1aeSArnaldo Carvalho de Melo offset = dl->ops.target.offset; 4735252b1aeSArnaldo Carvalho de Melo dl = annotate_browser__find_offset(browser, offset, &idx); 47429ed6e76SArnaldo Carvalho de Melo if (dl == NULL) { 4755252b1aeSArnaldo Carvalho de Melo ui_helpline__printf("Invalid jump offset: %" PRIx64, offset); 476aca7a94dSNamhyung Kim return true; 477aca7a94dSNamhyung Kim } 478aca7a94dSNamhyung Kim 479ec03a77dSJiri Olsa annotate_browser__set_top(browser, &dl->al, idx); 480aca7a94dSNamhyung Kim 481aca7a94dSNamhyung Kim return true; 482aca7a94dSNamhyung Kim } 483aca7a94dSNamhyung Kim 48429ed6e76SArnaldo Carvalho de Melo static 4859213afbdSJiri Olsa struct annotation_line *annotate_browser__find_string(struct annotate_browser *browser, 486aca7a94dSNamhyung Kim char *s, s64 *idx) 487aca7a94dSNamhyung Kim { 48895aa89d9SArnaldo Carvalho de Melo struct annotation *notes = browser__annotation(&browser->b); 4899213afbdSJiri Olsa struct annotation_line *al = browser->selection; 490aca7a94dSNamhyung Kim 491aca7a94dSNamhyung Kim *idx = browser->b.index; 4929213afbdSJiri Olsa list_for_each_entry_continue(al, ¬es->src->source, node) { 4939b80d1f9SArnaldo Carvalho de Melo if (annotation_line__filter(al, notes)) 494aca7a94dSNamhyung Kim continue; 495aca7a94dSNamhyung Kim 496aca7a94dSNamhyung Kim ++*idx; 497aca7a94dSNamhyung Kim 4989213afbdSJiri Olsa if (al->line && strstr(al->line, s) != NULL) 4999213afbdSJiri Olsa return al; 500aca7a94dSNamhyung Kim } 501aca7a94dSNamhyung Kim 502aca7a94dSNamhyung Kim return NULL; 503aca7a94dSNamhyung Kim } 504aca7a94dSNamhyung Kim 505aca7a94dSNamhyung Kim static bool __annotate_browser__search(struct annotate_browser *browser) 506aca7a94dSNamhyung Kim { 5079213afbdSJiri Olsa struct annotation_line *al; 508aca7a94dSNamhyung Kim s64 idx; 509aca7a94dSNamhyung Kim 5109213afbdSJiri Olsa al = annotate_browser__find_string(browser, browser->search_bf, &idx); 5119213afbdSJiri Olsa if (al == NULL) { 512aca7a94dSNamhyung Kim ui_helpline__puts("String not found!"); 513aca7a94dSNamhyung Kim return false; 514aca7a94dSNamhyung Kim } 515aca7a94dSNamhyung Kim 516ec03a77dSJiri Olsa annotate_browser__set_top(browser, al, idx); 517aca7a94dSNamhyung Kim browser->searching_backwards = false; 518aca7a94dSNamhyung Kim return true; 519aca7a94dSNamhyung Kim } 520aca7a94dSNamhyung Kim 52129ed6e76SArnaldo Carvalho de Melo static 5229213afbdSJiri Olsa struct annotation_line *annotate_browser__find_string_reverse(struct annotate_browser *browser, 523aca7a94dSNamhyung Kim char *s, s64 *idx) 524aca7a94dSNamhyung Kim { 52595aa89d9SArnaldo Carvalho de Melo struct annotation *notes = browser__annotation(&browser->b); 5269213afbdSJiri Olsa struct annotation_line *al = browser->selection; 527aca7a94dSNamhyung Kim 528aca7a94dSNamhyung Kim *idx = browser->b.index; 5299213afbdSJiri Olsa list_for_each_entry_continue_reverse(al, ¬es->src->source, node) { 5309b80d1f9SArnaldo Carvalho de Melo if (annotation_line__filter(al, notes)) 531aca7a94dSNamhyung Kim continue; 532aca7a94dSNamhyung Kim 533aca7a94dSNamhyung Kim --*idx; 534aca7a94dSNamhyung Kim 5359213afbdSJiri Olsa if (al->line && strstr(al->line, s) != NULL) 5369213afbdSJiri Olsa return al; 537aca7a94dSNamhyung Kim } 538aca7a94dSNamhyung Kim 539aca7a94dSNamhyung Kim return NULL; 540aca7a94dSNamhyung Kim } 541aca7a94dSNamhyung Kim 542aca7a94dSNamhyung Kim static bool __annotate_browser__search_reverse(struct annotate_browser *browser) 543aca7a94dSNamhyung Kim { 5449213afbdSJiri Olsa struct annotation_line *al; 545aca7a94dSNamhyung Kim s64 idx; 546aca7a94dSNamhyung Kim 5479213afbdSJiri Olsa al = annotate_browser__find_string_reverse(browser, browser->search_bf, &idx); 5489213afbdSJiri Olsa if (al == NULL) { 549aca7a94dSNamhyung Kim ui_helpline__puts("String not found!"); 550aca7a94dSNamhyung Kim return false; 551aca7a94dSNamhyung Kim } 552aca7a94dSNamhyung Kim 553ec03a77dSJiri Olsa annotate_browser__set_top(browser, al, idx); 554aca7a94dSNamhyung Kim browser->searching_backwards = true; 555aca7a94dSNamhyung Kim return true; 556aca7a94dSNamhyung Kim } 557aca7a94dSNamhyung Kim 558aca7a94dSNamhyung Kim static bool annotate_browser__search_window(struct annotate_browser *browser, 559aca7a94dSNamhyung Kim int delay_secs) 560aca7a94dSNamhyung Kim { 561aca7a94dSNamhyung Kim if (ui_browser__input_window("Search", "String: ", browser->search_bf, 562aca7a94dSNamhyung Kim "ENTER: OK, ESC: Cancel", 563aca7a94dSNamhyung Kim delay_secs * 2) != K_ENTER || 564aca7a94dSNamhyung Kim !*browser->search_bf) 565aca7a94dSNamhyung Kim return false; 566aca7a94dSNamhyung Kim 567aca7a94dSNamhyung Kim return true; 568aca7a94dSNamhyung Kim } 569aca7a94dSNamhyung Kim 570aca7a94dSNamhyung Kim static bool annotate_browser__search(struct annotate_browser *browser, int delay_secs) 571aca7a94dSNamhyung Kim { 572aca7a94dSNamhyung Kim if (annotate_browser__search_window(browser, delay_secs)) 573aca7a94dSNamhyung Kim return __annotate_browser__search(browser); 574aca7a94dSNamhyung Kim 575aca7a94dSNamhyung Kim return false; 576aca7a94dSNamhyung Kim } 577aca7a94dSNamhyung Kim 578aca7a94dSNamhyung Kim static bool annotate_browser__continue_search(struct annotate_browser *browser, 579aca7a94dSNamhyung Kim int delay_secs) 580aca7a94dSNamhyung Kim { 581aca7a94dSNamhyung Kim if (!*browser->search_bf) 582aca7a94dSNamhyung Kim return annotate_browser__search(browser, delay_secs); 583aca7a94dSNamhyung Kim 584aca7a94dSNamhyung Kim return __annotate_browser__search(browser); 585aca7a94dSNamhyung Kim } 586aca7a94dSNamhyung Kim 587aca7a94dSNamhyung Kim static bool annotate_browser__search_reverse(struct annotate_browser *browser, 588aca7a94dSNamhyung Kim int delay_secs) 589aca7a94dSNamhyung Kim { 590aca7a94dSNamhyung Kim if (annotate_browser__search_window(browser, delay_secs)) 591aca7a94dSNamhyung Kim return __annotate_browser__search_reverse(browser); 592aca7a94dSNamhyung Kim 593aca7a94dSNamhyung Kim return false; 594aca7a94dSNamhyung Kim } 595aca7a94dSNamhyung Kim 596aca7a94dSNamhyung Kim static 597aca7a94dSNamhyung Kim bool annotate_browser__continue_search_reverse(struct annotate_browser *browser, 598aca7a94dSNamhyung Kim int delay_secs) 599aca7a94dSNamhyung Kim { 600aca7a94dSNamhyung Kim if (!*browser->search_bf) 601aca7a94dSNamhyung Kim return annotate_browser__search_reverse(browser, delay_secs); 602aca7a94dSNamhyung Kim 603aca7a94dSNamhyung Kim return __annotate_browser__search_reverse(browser); 604aca7a94dSNamhyung Kim } 605aca7a94dSNamhyung Kim 6066920e285SArnaldo Carvalho de Melo static int annotate_browser__show(struct ui_browser *browser, char *title, const char *help) 6076920e285SArnaldo Carvalho de Melo { 6083e0d7953SJiri Olsa struct annotate_browser *ab = container_of(browser, struct annotate_browser, b); 6096920e285SArnaldo Carvalho de Melo struct map_symbol *ms = browser->priv; 6106920e285SArnaldo Carvalho de Melo struct symbol *sym = ms->sym; 6116920e285SArnaldo Carvalho de Melo char symbol_dso[SYM_TITLE_MAX_SIZE]; 6126920e285SArnaldo Carvalho de Melo 6136920e285SArnaldo Carvalho de Melo if (ui_browser__show(browser, title, help) < 0) 6146920e285SArnaldo Carvalho de Melo return -1; 6156920e285SArnaldo Carvalho de Melo 6163e0d7953SJiri Olsa sym_title(sym, ms->map, symbol_dso, sizeof(symbol_dso), ab->opts->percent_type); 6176920e285SArnaldo Carvalho de Melo 6186920e285SArnaldo Carvalho de Melo ui_browser__gotorc_title(browser, 0, 0); 6196920e285SArnaldo Carvalho de Melo ui_browser__set_color(browser, HE_COLORSET_ROOT); 6206920e285SArnaldo Carvalho de Melo ui_browser__write_nstring(browser, symbol_dso, browser->width + 1); 6216920e285SArnaldo Carvalho de Melo return 0; 6226920e285SArnaldo Carvalho de Melo } 6236920e285SArnaldo Carvalho de Melo 6243e0d7953SJiri Olsa static void 6253e0d7953SJiri Olsa switch_percent_type(struct annotation_options *opts, bool base) 6263e0d7953SJiri Olsa { 6273e0d7953SJiri Olsa switch (opts->percent_type) { 6283e0d7953SJiri Olsa case PERCENT_HITS_LOCAL: 6293e0d7953SJiri Olsa if (base) 6303e0d7953SJiri Olsa opts->percent_type = PERCENT_PERIOD_LOCAL; 6313e0d7953SJiri Olsa else 6323e0d7953SJiri Olsa opts->percent_type = PERCENT_HITS_GLOBAL; 6333e0d7953SJiri Olsa break; 6343e0d7953SJiri Olsa case PERCENT_HITS_GLOBAL: 6353e0d7953SJiri Olsa if (base) 6363e0d7953SJiri Olsa opts->percent_type = PERCENT_PERIOD_GLOBAL; 6373e0d7953SJiri Olsa else 6383e0d7953SJiri Olsa opts->percent_type = PERCENT_HITS_LOCAL; 6393e0d7953SJiri Olsa break; 6403e0d7953SJiri Olsa case PERCENT_PERIOD_LOCAL: 6413e0d7953SJiri Olsa if (base) 6423e0d7953SJiri Olsa opts->percent_type = PERCENT_HITS_LOCAL; 6433e0d7953SJiri Olsa else 6443e0d7953SJiri Olsa opts->percent_type = PERCENT_PERIOD_GLOBAL; 6453e0d7953SJiri Olsa break; 6463e0d7953SJiri Olsa case PERCENT_PERIOD_GLOBAL: 6473e0d7953SJiri Olsa if (base) 6483e0d7953SJiri Olsa opts->percent_type = PERCENT_HITS_GLOBAL; 6493e0d7953SJiri Olsa else 6503e0d7953SJiri Olsa opts->percent_type = PERCENT_PERIOD_LOCAL; 6513e0d7953SJiri Olsa break; 6523e0d7953SJiri Olsa default: 6533e0d7953SJiri Olsa WARN_ON(1); 6543e0d7953SJiri Olsa } 6553e0d7953SJiri Olsa } 6563e0d7953SJiri Olsa 657db8fd07aSNamhyung Kim static int annotate_browser__run(struct annotate_browser *browser, 658db8fd07aSNamhyung Kim struct perf_evsel *evsel, 6599783adf7SNamhyung Kim struct hist_browser_timer *hbt) 660aca7a94dSNamhyung Kim { 661aca7a94dSNamhyung Kim struct rb_node *nd = NULL; 6626920e285SArnaldo Carvalho de Melo struct hists *hists = evsel__hists(evsel); 66305e8b080SArnaldo Carvalho de Melo struct map_symbol *ms = browser->b.priv; 664aca7a94dSNamhyung Kim struct symbol *sym = ms->sym; 66516932d77SArnaldo Carvalho de Melo struct annotation *notes = symbol__annotation(ms->sym); 66654e7a4e8SArnaldo Carvalho de Melo const char *help = "Press 'h' for help on key bindings"; 6679783adf7SNamhyung Kim int delay_secs = hbt ? hbt->refresh : 0; 6686920e285SArnaldo Carvalho de Melo char title[256]; 669aca7a94dSNamhyung Kim int key; 670aca7a94dSNamhyung Kim 6710683d13cSJiri Olsa hists__scnprintf_title(hists, title, sizeof(title)); 6726920e285SArnaldo Carvalho de Melo if (annotate_browser__show(&browser->b, title, help) < 0) 673aca7a94dSNamhyung Kim return -1; 674aca7a94dSNamhyung Kim 675db8fd07aSNamhyung Kim annotate_browser__calc_percent(browser, evsel); 676aca7a94dSNamhyung Kim 67705e8b080SArnaldo Carvalho de Melo if (browser->curr_hot) { 67805e8b080SArnaldo Carvalho de Melo annotate_browser__set_rb_top(browser, browser->curr_hot); 67905e8b080SArnaldo Carvalho de Melo browser->b.navkeypressed = false; 680aca7a94dSNamhyung Kim } 681aca7a94dSNamhyung Kim 68205e8b080SArnaldo Carvalho de Melo nd = browser->curr_hot; 683aca7a94dSNamhyung Kim 684aca7a94dSNamhyung Kim while (1) { 68505e8b080SArnaldo Carvalho de Melo key = ui_browser__run(&browser->b, delay_secs); 686aca7a94dSNamhyung Kim 687aca7a94dSNamhyung Kim if (delay_secs != 0) { 688db8fd07aSNamhyung Kim annotate_browser__calc_percent(browser, evsel); 689aca7a94dSNamhyung Kim /* 690aca7a94dSNamhyung Kim * Current line focus got out of the list of most active 691aca7a94dSNamhyung Kim * lines, NULL it so that if TAB|UNTAB is pressed, we 692aca7a94dSNamhyung Kim * move to curr_hot (current hottest line). 693aca7a94dSNamhyung Kim */ 694aca7a94dSNamhyung Kim if (nd != NULL && RB_EMPTY_NODE(nd)) 695aca7a94dSNamhyung Kim nd = NULL; 696aca7a94dSNamhyung Kim } 697aca7a94dSNamhyung Kim 698aca7a94dSNamhyung Kim switch (key) { 699aca7a94dSNamhyung Kim case K_TIMER: 7009783adf7SNamhyung Kim if (hbt) 7019783adf7SNamhyung Kim hbt->timer(hbt->arg); 702aca7a94dSNamhyung Kim 7036920e285SArnaldo Carvalho de Melo if (delay_secs != 0) { 704db8fd07aSNamhyung Kim symbol__annotate_decay_histogram(sym, evsel->idx); 7056920e285SArnaldo Carvalho de Melo hists__scnprintf_title(hists, title, sizeof(title)); 7066920e285SArnaldo Carvalho de Melo annotate_browser__show(&browser->b, title, help); 7076920e285SArnaldo Carvalho de Melo } 708aca7a94dSNamhyung Kim continue; 709aca7a94dSNamhyung Kim case K_TAB: 710aca7a94dSNamhyung Kim if (nd != NULL) { 711aca7a94dSNamhyung Kim nd = rb_prev(nd); 712aca7a94dSNamhyung Kim if (nd == NULL) 71305e8b080SArnaldo Carvalho de Melo nd = rb_last(&browser->entries); 714aca7a94dSNamhyung Kim } else 71505e8b080SArnaldo Carvalho de Melo nd = browser->curr_hot; 716aca7a94dSNamhyung Kim break; 717aca7a94dSNamhyung Kim case K_UNTAB: 718d4913cbdSMarkus Trippelsdorf if (nd != NULL) { 719aca7a94dSNamhyung Kim nd = rb_next(nd); 720aca7a94dSNamhyung Kim if (nd == NULL) 72105e8b080SArnaldo Carvalho de Melo nd = rb_first(&browser->entries); 722d4913cbdSMarkus Trippelsdorf } else 72305e8b080SArnaldo Carvalho de Melo nd = browser->curr_hot; 724aca7a94dSNamhyung Kim break; 72554e7a4e8SArnaldo Carvalho de Melo case K_F1: 726aca7a94dSNamhyung Kim case 'h': 72705e8b080SArnaldo Carvalho de Melo ui_browser__help_window(&browser->b, 72854e7a4e8SArnaldo Carvalho de Melo "UP/DOWN/PGUP\n" 72954e7a4e8SArnaldo Carvalho de Melo "PGDN/SPACE Navigate\n" 73054e7a4e8SArnaldo Carvalho de Melo "q/ESC/CTRL+C Exit\n\n" 7317727a925SArnaldo Carvalho de Melo "ENTER Go to target\n" 7327727a925SArnaldo Carvalho de Melo "ESC Exit\n" 733eba9fac0SArnaldo Carvalho de Melo "H Go to hottest instruction\n" 734eba9fac0SArnaldo Carvalho de Melo "TAB/shift+TAB Cycle thru hottest instructions\n" 73554e7a4e8SArnaldo Carvalho de Melo "j Toggle showing jump to target arrows\n" 73654e7a4e8SArnaldo Carvalho de Melo "J Toggle showing number of jump sources on targets\n" 73754e7a4e8SArnaldo Carvalho de Melo "n Search next string\n" 73854e7a4e8SArnaldo Carvalho de Melo "o Toggle disassembler output/simplified view\n" 73951f39603SArnaldo Carvalho de Melo "O Bump offset level (jump targets -> +call -> all -> cycle thru)\n" 74054e7a4e8SArnaldo Carvalho de Melo "s Toggle source code view\n" 7413a555c77STaeung Song "t Circulate percent, total period, samples view\n" 7423e71fc03SJin Yao "c Show min/max cycle\n" 74354e7a4e8SArnaldo Carvalho de Melo "/ Search string\n" 744e592488cSAndi Kleen "k Toggle line numbers\n" 745d9bd7665SArnaldo Carvalho de Melo "P Print to [symbol_name].annotation file.\n" 74679ee47faSFeng Tang "r Run available scripts\n" 7473e0d7953SJiri Olsa "p Toggle percent type [local/global]\n" 7483e0d7953SJiri Olsa "b Toggle percent base [period/hits]\n" 749fcd9fef9SArnaldo Carvalho de Melo "? Search string backwards\n"); 75054e7a4e8SArnaldo Carvalho de Melo continue; 75179ee47faSFeng Tang case 'r': 75279ee47faSFeng Tang { 75379ee47faSFeng Tang script_browse(NULL); 75479ee47faSFeng Tang continue; 75579ee47faSFeng Tang } 756e592488cSAndi Kleen case 'k': 75716932d77SArnaldo Carvalho de Melo notes->options->show_linenr = !notes->options->show_linenr; 758e592488cSAndi Kleen break; 75954e7a4e8SArnaldo Carvalho de Melo case 'H': 76005e8b080SArnaldo Carvalho de Melo nd = browser->curr_hot; 761aca7a94dSNamhyung Kim break; 762aca7a94dSNamhyung Kim case 's': 76305e8b080SArnaldo Carvalho de Melo if (annotate_browser__toggle_source(browser)) 764aca7a94dSNamhyung Kim ui_helpline__puts(help); 765aca7a94dSNamhyung Kim continue; 766aca7a94dSNamhyung Kim case 'o': 76716932d77SArnaldo Carvalho de Melo notes->options->use_offset = !notes->options->use_offset; 7689761e86eSArnaldo Carvalho de Melo annotation__update_column_widths(notes); 769aca7a94dSNamhyung Kim continue; 77051f39603SArnaldo Carvalho de Melo case 'O': 77151f39603SArnaldo Carvalho de Melo if (++notes->options->offset_level > ANNOTATION__MAX_OFFSET_LEVEL) 77251f39603SArnaldo Carvalho de Melo notes->options->offset_level = ANNOTATION__MIN_OFFSET_LEVEL; 77351f39603SArnaldo Carvalho de Melo continue; 7749d1ef56dSArnaldo Carvalho de Melo case 'j': 77516932d77SArnaldo Carvalho de Melo notes->options->jump_arrows = !notes->options->jump_arrows; 7769d1ef56dSArnaldo Carvalho de Melo continue; 7772402e4a9SArnaldo Carvalho de Melo case 'J': 77816932d77SArnaldo Carvalho de Melo notes->options->show_nr_jumps = !notes->options->show_nr_jumps; 7799761e86eSArnaldo Carvalho de Melo annotation__update_column_widths(notes); 780e9823b21SArnaldo Carvalho de Melo continue; 781aca7a94dSNamhyung Kim case '/': 78205e8b080SArnaldo Carvalho de Melo if (annotate_browser__search(browser, delay_secs)) { 783aca7a94dSNamhyung Kim show_help: 784aca7a94dSNamhyung Kim ui_helpline__puts(help); 785aca7a94dSNamhyung Kim } 786aca7a94dSNamhyung Kim continue; 787aca7a94dSNamhyung Kim case 'n': 78805e8b080SArnaldo Carvalho de Melo if (browser->searching_backwards ? 78905e8b080SArnaldo Carvalho de Melo annotate_browser__continue_search_reverse(browser, delay_secs) : 79005e8b080SArnaldo Carvalho de Melo annotate_browser__continue_search(browser, delay_secs)) 791aca7a94dSNamhyung Kim goto show_help; 792aca7a94dSNamhyung Kim continue; 793aca7a94dSNamhyung Kim case '?': 79405e8b080SArnaldo Carvalho de Melo if (annotate_browser__search_reverse(browser, delay_secs)) 795aca7a94dSNamhyung Kim goto show_help; 796aca7a94dSNamhyung Kim continue; 797e9823b21SArnaldo Carvalho de Melo case 'D': { 798e9823b21SArnaldo Carvalho de Melo static int seq; 799e9823b21SArnaldo Carvalho de Melo ui_helpline__pop(); 800e9823b21SArnaldo Carvalho de Melo ui_helpline__fpush("%d: nr_ent=%d, height=%d, idx=%d, top_idx=%d, nr_asm_entries=%d", 80105e8b080SArnaldo Carvalho de Melo seq++, browser->b.nr_entries, 80205e8b080SArnaldo Carvalho de Melo browser->b.height, 80305e8b080SArnaldo Carvalho de Melo browser->b.index, 80405e8b080SArnaldo Carvalho de Melo browser->b.top_idx, 8051cf5f98aSArnaldo Carvalho de Melo notes->nr_asm_entries); 806e9823b21SArnaldo Carvalho de Melo } 807e9823b21SArnaldo Carvalho de Melo continue; 808aca7a94dSNamhyung Kim case K_ENTER: 809aca7a94dSNamhyung Kim case K_RIGHT: 8107bcbcd58SJiri Olsa { 8117bcbcd58SJiri Olsa struct disasm_line *dl = disasm_line(browser->selection); 8127bcbcd58SJiri Olsa 81305e8b080SArnaldo Carvalho de Melo if (browser->selection == NULL) 814aca7a94dSNamhyung Kim ui_helpline__puts("Huh? No selection. Report to linux-kernel@vger.kernel.org"); 8157bcbcd58SJiri Olsa else if (browser->selection->offset == -1) 816aca7a94dSNamhyung Kim ui_helpline__puts("Actions are only available for assembly lines."); 8177bcbcd58SJiri Olsa else if (!dl->ins.ops) 818c4cceae3SArnaldo Carvalho de Melo goto show_sup_ins; 8197bcbcd58SJiri Olsa else if (ins__is_ret(&dl->ins)) 820c4cceae3SArnaldo Carvalho de Melo goto out; 821e4cc91b8SArnaldo Carvalho de Melo else if (!(annotate_browser__jump(browser, evsel, hbt) || 822db8fd07aSNamhyung Kim annotate_browser__callq(browser, evsel, hbt))) { 823c4cceae3SArnaldo Carvalho de Melo show_sup_ins: 8246ef94929SNaveen N. Rao ui_helpline__puts("Actions are only available for function call/return & jump/branch instructions."); 825c4cceae3SArnaldo Carvalho de Melo } 826aca7a94dSNamhyung Kim continue; 8277bcbcd58SJiri Olsa } 828d9bd7665SArnaldo Carvalho de Melo case 'P': 8294c650ddcSJiri Olsa map_symbol__annotation_dump(ms, evsel, browser->opts); 830d9bd7665SArnaldo Carvalho de Melo continue; 8310c4a5bceSMartin Liška case 't': 83216932d77SArnaldo Carvalho de Melo if (notes->options->show_total_period) { 83316932d77SArnaldo Carvalho de Melo notes->options->show_total_period = false; 83416932d77SArnaldo Carvalho de Melo notes->options->show_nr_samples = true; 83516932d77SArnaldo Carvalho de Melo } else if (notes->options->show_nr_samples) 83616932d77SArnaldo Carvalho de Melo notes->options->show_nr_samples = false; 8373a555c77STaeung Song else 83816932d77SArnaldo Carvalho de Melo notes->options->show_total_period = true; 8399761e86eSArnaldo Carvalho de Melo annotation__update_column_widths(notes); 8400c4a5bceSMartin Liška continue; 8413e71fc03SJin Yao case 'c': 8423e71fc03SJin Yao if (notes->options->show_minmax_cycle) 8433e71fc03SJin Yao notes->options->show_minmax_cycle = false; 8443e71fc03SJin Yao else 8453e71fc03SJin Yao notes->options->show_minmax_cycle = true; 8463e71fc03SJin Yao annotation__update_column_widths(notes); 8473e71fc03SJin Yao continue; 8483e0d7953SJiri Olsa case 'p': 8493e0d7953SJiri Olsa case 'b': 8503e0d7953SJiri Olsa switch_percent_type(browser->opts, key == 'b'); 8513e0d7953SJiri Olsa hists__scnprintf_title(hists, title, sizeof(title)); 8523e0d7953SJiri Olsa annotate_browser__show(&browser->b, title, help); 8533e0d7953SJiri Olsa continue; 854aca7a94dSNamhyung Kim case K_LEFT: 855aca7a94dSNamhyung Kim case K_ESC: 856aca7a94dSNamhyung Kim case 'q': 857aca7a94dSNamhyung Kim case CTRL('c'): 858aca7a94dSNamhyung Kim goto out; 859aca7a94dSNamhyung Kim default: 860aca7a94dSNamhyung Kim continue; 861aca7a94dSNamhyung Kim } 862aca7a94dSNamhyung Kim 863aca7a94dSNamhyung Kim if (nd != NULL) 86405e8b080SArnaldo Carvalho de Melo annotate_browser__set_rb_top(browser, nd); 865aca7a94dSNamhyung Kim } 866aca7a94dSNamhyung Kim out: 86705e8b080SArnaldo Carvalho de Melo ui_browser__hide(&browser->b); 868aca7a94dSNamhyung Kim return key; 869aca7a94dSNamhyung Kim } 870aca7a94dSNamhyung Kim 871d5dbc518SArnaldo Carvalho de Melo int map_symbol__tui_annotate(struct map_symbol *ms, struct perf_evsel *evsel, 872cd0cccbaSArnaldo Carvalho de Melo struct hist_browser_timer *hbt, 873cd0cccbaSArnaldo Carvalho de Melo struct annotation_options *opts) 874d5dbc518SArnaldo Carvalho de Melo { 875cd0cccbaSArnaldo Carvalho de Melo return symbol__tui_annotate(ms->sym, ms->map, evsel, hbt, opts); 876d5dbc518SArnaldo Carvalho de Melo } 877d5dbc518SArnaldo Carvalho de Melo 878db8fd07aSNamhyung Kim int hist_entry__tui_annotate(struct hist_entry *he, struct perf_evsel *evsel, 879cd0cccbaSArnaldo Carvalho de Melo struct hist_browser_timer *hbt, 880cd0cccbaSArnaldo Carvalho de Melo struct annotation_options *opts) 881aca7a94dSNamhyung Kim { 882ed426915SNamhyung Kim /* reset abort key so that it can get Ctrl-C as a key */ 883ed426915SNamhyung Kim SLang_reset_tty(); 884ed426915SNamhyung Kim SLang_init_tty(0, 0, 0); 885ed426915SNamhyung Kim 886cd0cccbaSArnaldo Carvalho de Melo return map_symbol__tui_annotate(&he->ms, evsel, hbt, opts); 887aca7a94dSNamhyung Kim } 888aca7a94dSNamhyung Kim 889db8fd07aSNamhyung Kim int symbol__tui_annotate(struct symbol *sym, struct map *map, 890db8fd07aSNamhyung Kim struct perf_evsel *evsel, 891cd0cccbaSArnaldo Carvalho de Melo struct hist_browser_timer *hbt, 892cd0cccbaSArnaldo Carvalho de Melo struct annotation_options *opts) 893aca7a94dSNamhyung Kim { 8949d6bb41dSArnaldo Carvalho de Melo struct annotation *notes = symbol__annotation(sym); 895aca7a94dSNamhyung Kim struct map_symbol ms = { 896aca7a94dSNamhyung Kim .map = map, 897aca7a94dSNamhyung Kim .sym = sym, 898aca7a94dSNamhyung Kim }; 899aca7a94dSNamhyung Kim struct annotate_browser browser = { 900aca7a94dSNamhyung Kim .b = { 901a3f895beSArnaldo Carvalho de Melo .refresh = annotate_browser__refresh, 902aca7a94dSNamhyung Kim .seek = ui_browser__list_head_seek, 903aca7a94dSNamhyung Kim .write = annotate_browser__write, 90429ed6e76SArnaldo Carvalho de Melo .filter = disasm_line__filter, 9056920e285SArnaldo Carvalho de Melo .extra_title_lines = 1, /* for hists__scnprintf_title() */ 906aca7a94dSNamhyung Kim .priv = &ms, 907aca7a94dSNamhyung Kim .use_navkeypressed = true, 908aca7a94dSNamhyung Kim }, 909cd0cccbaSArnaldo Carvalho de Melo .opts = opts, 910aca7a94dSNamhyung Kim }; 911ee51d851SArnaldo Carvalho de Melo int ret = -1, err; 912aca7a94dSNamhyung Kim 913aca7a94dSNamhyung Kim if (sym == NULL) 914aca7a94dSNamhyung Kim return -1; 915aca7a94dSNamhyung Kim 916aca7a94dSNamhyung Kim if (map->dso->annotate_warned) 917aca7a94dSNamhyung Kim return -1; 918aca7a94dSNamhyung Kim 919cd0cccbaSArnaldo Carvalho de Melo err = symbol__annotate2(sym, map, evsel, opts, &browser.arch); 920ee51d851SArnaldo Carvalho de Melo if (err) { 921ee51d851SArnaldo Carvalho de Melo char msg[BUFSIZ]; 922ee51d851SArnaldo Carvalho de Melo symbol__strerror_disassemble(sym, map, err, msg, sizeof(msg)); 923ee51d851SArnaldo Carvalho de Melo ui__error("Couldn't annotate %s:\n%s", sym->name, msg); 924b793a401SArnaldo Carvalho de Melo goto out_free_offsets; 925aca7a94dSNamhyung Kim } 926aca7a94dSNamhyung Kim 9277727a925SArnaldo Carvalho de Melo ui_helpline__push("Press ESC to exit"); 928aca7a94dSNamhyung Kim 9295bc49f61SArnaldo Carvalho de Melo browser.b.width = notes->max_line_len; 9301cf5f98aSArnaldo Carvalho de Melo browser.b.nr_entries = notes->nr_entries; 931aca7a94dSNamhyung Kim browser.b.entries = ¬es->src->source, 932aca7a94dSNamhyung Kim browser.b.width += 18; /* Percentage */ 933e9823b21SArnaldo Carvalho de Melo 93416932d77SArnaldo Carvalho de Melo if (notes->options->hide_src_code) 9351cf5f98aSArnaldo Carvalho de Melo ui_browser__init_asm_mode(&browser.b); 936e9823b21SArnaldo Carvalho de Melo 937db8fd07aSNamhyung Kim ret = annotate_browser__run(&browser, evsel, hbt); 938f8eb37bdSJiri Olsa 939f8eb37bdSJiri Olsa annotated_source__purge(notes->src); 940b793a401SArnaldo Carvalho de Melo 941b793a401SArnaldo Carvalho de Melo out_free_offsets: 9429d6bb41dSArnaldo Carvalho de Melo zfree(¬es->offsets); 943aca7a94dSNamhyung Kim return ret; 944aca7a94dSNamhyung Kim } 945