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; 32aca7a94dSNamhyung Kim bool searching_backwards; 33aca7a94dSNamhyung Kim char search_bf[128]; 34aca7a94dSNamhyung Kim }; 35aca7a94dSNamhyung Kim 3695aa89d9SArnaldo Carvalho de Melo static inline struct annotation *browser__annotation(struct ui_browser *browser) 3795aa89d9SArnaldo Carvalho de Melo { 3895aa89d9SArnaldo Carvalho de Melo struct map_symbol *ms = browser->priv; 3995aa89d9SArnaldo Carvalho de Melo return symbol__annotation(ms->sym); 4095aa89d9SArnaldo Carvalho de Melo } 4195aa89d9SArnaldo Carvalho de Melo 4216932d77SArnaldo Carvalho de Melo static bool disasm_line__filter(struct ui_browser *browser, void *entry) 43aca7a94dSNamhyung Kim { 4495aa89d9SArnaldo Carvalho de Melo struct annotation *notes = browser__annotation(browser); 45d5490b96SJiri Olsa struct annotation_line *al = list_entry(entry, struct annotation_line, node); 469b80d1f9SArnaldo Carvalho de Melo return annotation_line__filter(al, notes); 47aca7a94dSNamhyung Kim } 48aca7a94dSNamhyung Kim 4927feb761SArnaldo Carvalho de Melo static int ui_browser__jumps_percent_color(struct ui_browser *browser, int nr, bool current) 502402e4a9SArnaldo Carvalho de Melo { 5127feb761SArnaldo Carvalho de Melo struct annotation *notes = browser__annotation(browser); 52bc1c0f3dSArnaldo Carvalho de Melo 5327feb761SArnaldo Carvalho de Melo if (current && (!browser->use_navkeypressed || browser->navkeypressed)) 542402e4a9SArnaldo Carvalho de Melo return HE_COLORSET_SELECTED; 55bc1c0f3dSArnaldo Carvalho de Melo if (nr == notes->max_jump_sources) 562402e4a9SArnaldo Carvalho de Melo return HE_COLORSET_TOP; 572402e4a9SArnaldo Carvalho de Melo if (nr > 1) 582402e4a9SArnaldo Carvalho de Melo return HE_COLORSET_MEDIUM; 592402e4a9SArnaldo Carvalho de Melo return HE_COLORSET_NORMAL; 602402e4a9SArnaldo Carvalho de Melo } 612402e4a9SArnaldo Carvalho de Melo 62a1e9b74cSArnaldo Carvalho de Melo static int ui_browser__set_jumps_percent_color(void *browser, int nr, bool current) 632402e4a9SArnaldo Carvalho de Melo { 6427feb761SArnaldo Carvalho de Melo int color = ui_browser__jumps_percent_color(browser, nr, current); 6527feb761SArnaldo Carvalho de Melo return ui_browser__set_color(browser, color); 662402e4a9SArnaldo Carvalho de Melo } 672402e4a9SArnaldo Carvalho de Melo 68a1e9b74cSArnaldo Carvalho de Melo static int annotate_browser__set_color(void *browser, int color) 69aca7a94dSNamhyung Kim { 70a1e9b74cSArnaldo Carvalho de Melo return ui_browser__set_color(browser, color); 714ea08b52SArnaldo Carvalho de Melo } 724ea08b52SArnaldo Carvalho de Melo 73a1e9b74cSArnaldo Carvalho de Melo static void annotate_browser__write_graph(void *browser, int graph) 74a1e9b74cSArnaldo Carvalho de Melo { 75a1e9b74cSArnaldo Carvalho de Melo ui_browser__write_graph(browser, graph); 76a5433b3eSJiri Olsa } 77a5433b3eSJiri Olsa 782ba5eca1SArnaldo Carvalho de Melo static void annotate_browser__set_percent_color(void *browser, double percent, bool current) 792ba5eca1SArnaldo Carvalho de Melo { 802ba5eca1SArnaldo Carvalho de Melo ui_browser__set_percent_color(browser, percent, current); 812ba5eca1SArnaldo Carvalho de Melo } 822ba5eca1SArnaldo Carvalho de Melo 832ba5eca1SArnaldo Carvalho de Melo static void annotate_browser__printf(void *browser, const char *fmt, ...) 842ba5eca1SArnaldo Carvalho de Melo { 852ba5eca1SArnaldo Carvalho de Melo va_list args; 862ba5eca1SArnaldo Carvalho de Melo 872ba5eca1SArnaldo Carvalho de Melo va_start(args, fmt); 882ba5eca1SArnaldo Carvalho de Melo ui_browser__vprintf(browser, fmt, args); 892ba5eca1SArnaldo Carvalho de Melo va_end(args); 902ba5eca1SArnaldo Carvalho de Melo } 912ba5eca1SArnaldo Carvalho de Melo 92a5433b3eSJiri Olsa static void annotate_browser__write(struct ui_browser *browser, void *entry, int row) 93a5433b3eSJiri Olsa { 94a5433b3eSJiri Olsa struct annotate_browser *ab = container_of(browser, struct annotate_browser, b); 9595aa89d9SArnaldo Carvalho de Melo struct annotation *notes = browser__annotation(browser); 96a5433b3eSJiri Olsa struct annotation_line *al = list_entry(entry, struct annotation_line, node); 97c298304bSArnaldo Carvalho de Melo struct annotation_write_ops ops = { 98c298304bSArnaldo Carvalho de Melo .first_line = row == 0, 99c298304bSArnaldo Carvalho de Melo .current_entry = ui_browser__is_current_entry(browser, row), 100c298304bSArnaldo Carvalho de Melo .change_color = (!notes->options->hide_src_code && 101c298304bSArnaldo Carvalho de Melo (!ops.current_entry || 102c298304bSArnaldo Carvalho de Melo (browser->use_navkeypressed && 103c298304bSArnaldo Carvalho de Melo !browser->navkeypressed))), 104c298304bSArnaldo Carvalho de Melo .width = browser->width, 105c298304bSArnaldo Carvalho de Melo .obj = browser, 106c298304bSArnaldo Carvalho de Melo .set_color = annotate_browser__set_color, 107c298304bSArnaldo Carvalho de Melo .set_percent_color = annotate_browser__set_percent_color, 108c298304bSArnaldo Carvalho de Melo .set_jumps_percent_color = ui_browser__set_jumps_percent_color, 109c298304bSArnaldo Carvalho de Melo .printf = annotate_browser__printf, 110c298304bSArnaldo Carvalho de Melo .write_graph = annotate_browser__write_graph, 111c298304bSArnaldo Carvalho de Melo }; 112a5433b3eSJiri Olsa 113a5433b3eSJiri Olsa /* The scroll bar isn't being used */ 114a5433b3eSJiri Olsa if (!browser->navkeypressed) 115c298304bSArnaldo Carvalho de Melo ops.width += 1; 116a5433b3eSJiri Olsa 117c298304bSArnaldo Carvalho de Melo annotation_line__write(al, notes, &ops); 118aca7a94dSNamhyung Kim 119c298304bSArnaldo Carvalho de Melo if (ops.current_entry) 120a5433b3eSJiri Olsa ab->selection = al; 121aca7a94dSNamhyung Kim } 122aca7a94dSNamhyung Kim 1237e63a13aSJin Yao static bool is_fused(struct annotate_browser *ab, struct disasm_line *cursor) 1247e63a13aSJin Yao { 125a17c4ca0SJiri Olsa struct disasm_line *pos = list_prev_entry(cursor, al.node); 1267e63a13aSJin Yao const char *name; 1277e63a13aSJin Yao 1287e63a13aSJin Yao if (!pos) 1297e63a13aSJin Yao return false; 1307e63a13aSJin Yao 1317e63a13aSJin Yao if (ins__is_lock(&pos->ins)) 1327e63a13aSJin Yao name = pos->ops.locked.ins.name; 1337e63a13aSJin Yao else 1347e63a13aSJin Yao name = pos->ins.name; 1357e63a13aSJin Yao 1367e63a13aSJin Yao if (!name || !cursor->ins.name) 1377e63a13aSJin Yao return false; 1387e63a13aSJin Yao 1397e63a13aSJin Yao return ins__is_fused(ab->arch, name, cursor->ins.name); 1407e63a13aSJin Yao } 1417e63a13aSJin Yao 1429d1ef56dSArnaldo Carvalho de Melo static void annotate_browser__draw_current_jump(struct ui_browser *browser) 143a3f895beSArnaldo Carvalho de Melo { 144a3f895beSArnaldo Carvalho de Melo struct annotate_browser *ab = container_of(browser, struct annotate_browser, b); 1457bcbcd58SJiri Olsa struct disasm_line *cursor = disasm_line(ab->selection); 146a5ef2702SJiri Olsa struct annotation_line *target; 14783b1f2aaSArnaldo Carvalho de Melo unsigned int from, to; 14832ae1efdSNamhyung Kim struct map_symbol *ms = ab->b.priv; 14932ae1efdSNamhyung Kim struct symbol *sym = ms->sym; 1500e83a7e9SArnaldo Carvalho de Melo struct annotation *notes = symbol__annotation(sym); 1516af612d2SArnaldo Carvalho de Melo u8 pcnt_width = annotation__pcnt_width(notes); 15200ea0eb2SArnaldo Carvalho de Melo int width; 15332ae1efdSNamhyung Kim 15432ae1efdSNamhyung Kim /* PLT symbols contain external offsets */ 15532ae1efdSNamhyung Kim if (strstr(sym->name, "@plt")) 15632ae1efdSNamhyung Kim return; 157a3f895beSArnaldo Carvalho de Melo 1582eff0611SArnaldo Carvalho de Melo if (!disasm_line__is_valid_local_jump(cursor, sym)) 159a3f895beSArnaldo Carvalho de Melo return; 160a3f895beSArnaldo Carvalho de Melo 1619c04409dSArnaldo Carvalho de Melo /* 1629c04409dSArnaldo Carvalho de Melo * This first was seen with a gcc function, _cpp_lex_token, that 1639c04409dSArnaldo Carvalho de Melo * has the usual jumps: 1649c04409dSArnaldo Carvalho de Melo * 1659c04409dSArnaldo Carvalho de Melo * │1159e6c: ↓ jne 115aa32 <_cpp_lex_token@@Base+0xf92> 1669c04409dSArnaldo Carvalho de Melo * 1679c04409dSArnaldo Carvalho de Melo * I.e. jumps to a label inside that function (_cpp_lex_token), and 1689c04409dSArnaldo Carvalho de Melo * those works, but also this kind: 1699c04409dSArnaldo Carvalho de Melo * 1709c04409dSArnaldo Carvalho de Melo * │1159e8b: ↓ jne c469be <cpp_named_operator2name@@Base+0xa72> 1719c04409dSArnaldo Carvalho de Melo * 1729c04409dSArnaldo Carvalho de Melo * I.e. jumps to another function, outside _cpp_lex_token, which 1739c04409dSArnaldo Carvalho de Melo * are not being correctly handled generating as a side effect references 1749c04409dSArnaldo Carvalho de Melo * to ab->offset[] entries that are set to NULL, so to make this code 1759c04409dSArnaldo Carvalho de Melo * more robust, check that here. 1769c04409dSArnaldo Carvalho de Melo * 1779c04409dSArnaldo Carvalho de Melo * A proper fix for will be put in place, looking at the function 1789c04409dSArnaldo Carvalho de Melo * name right after the '<' token and probably treating this like a 1799c04409dSArnaldo Carvalho de Melo * 'call' instruction. 1809c04409dSArnaldo Carvalho de Melo */ 1819d6bb41dSArnaldo Carvalho de Melo target = notes->offsets[cursor->ops.target.offset]; 1829c04409dSArnaldo Carvalho de Melo if (target == NULL) { 1839d6bb41dSArnaldo Carvalho de Melo ui_helpline__printf("WARN: jump target inconsistency, press 'o', notes->offsets[%#x] = NULL\n", 1849c04409dSArnaldo Carvalho de Melo cursor->ops.target.offset); 1859c04409dSArnaldo Carvalho de Melo return; 1869c04409dSArnaldo Carvalho de Melo } 1879d1ef56dSArnaldo Carvalho de Melo 18816932d77SArnaldo Carvalho de Melo if (notes->options->hide_src_code) { 1894850c92eSArnaldo Carvalho de Melo from = cursor->al.idx_asm; 1904850c92eSArnaldo Carvalho de Melo to = target->idx_asm; 191a3f895beSArnaldo Carvalho de Melo } else { 1924850c92eSArnaldo Carvalho de Melo from = (u64)cursor->al.idx; 1934850c92eSArnaldo Carvalho de Melo to = (u64)target->idx; 194a3f895beSArnaldo Carvalho de Melo } 195a3f895beSArnaldo Carvalho de Melo 1960e83a7e9SArnaldo Carvalho de Melo width = annotation__cycles_width(notes); 197b40982e8SJin Yao 19878ce08dfSTaeung Song ui_browser__set_color(browser, HE_COLORSET_JUMP_ARROWS); 199b40982e8SJin Yao __ui_browser__line_arrow(browser, 2009761e86eSArnaldo Carvalho de Melo pcnt_width + 2 + notes->widths.addr + width, 201c7e7b610SNamhyung Kim from, to); 2027e63a13aSJin Yao 2037e63a13aSJin Yao if (is_fused(ab, cursor)) { 2047e63a13aSJin Yao ui_browser__mark_fused(browser, 2059761e86eSArnaldo Carvalho de Melo pcnt_width + 3 + notes->widths.addr + width, 2067e63a13aSJin Yao from - 1, 2077e63a13aSJin Yao to > from ? true : false); 2087e63a13aSJin Yao } 209a3f895beSArnaldo Carvalho de Melo } 210a3f895beSArnaldo Carvalho de Melo 211a3f895beSArnaldo Carvalho de Melo static unsigned int annotate_browser__refresh(struct ui_browser *browser) 212a3f895beSArnaldo Carvalho de Melo { 21395aa89d9SArnaldo Carvalho de Melo struct annotation *notes = browser__annotation(browser); 214a3f895beSArnaldo Carvalho de Melo int ret = ui_browser__list_head_refresh(browser); 2156af612d2SArnaldo Carvalho de Melo int pcnt_width = annotation__pcnt_width(notes); 216a3f895beSArnaldo Carvalho de Melo 21716932d77SArnaldo Carvalho de Melo if (notes->options->jump_arrows) 2189d1ef56dSArnaldo Carvalho de Melo annotate_browser__draw_current_jump(browser); 219a3f895beSArnaldo Carvalho de Melo 22083b1f2aaSArnaldo Carvalho de Melo ui_browser__set_color(browser, HE_COLORSET_NORMAL); 221c7e7b610SNamhyung Kim __ui_browser__vline(browser, pcnt_width, 0, browser->height - 1); 222a3f895beSArnaldo Carvalho de Melo return ret; 223a3f895beSArnaldo Carvalho de Melo } 224a3f895beSArnaldo Carvalho de Melo 225b15636c6SJiri Olsa static int disasm__cmp(struct annotation_line *a, struct annotation_line *b) 226c7e7b610SNamhyung Kim { 227c7e7b610SNamhyung Kim int i; 228c7e7b610SNamhyung Kim 229b15636c6SJiri Olsa for (i = 0; i < a->samples_nr; i++) { 2300c4a5bceSMartin Liška if (a->samples[i].percent == b->samples[i].percent) 231c7e7b610SNamhyung Kim continue; 2320c4a5bceSMartin Liška return a->samples[i].percent < b->samples[i].percent; 233c7e7b610SNamhyung Kim } 234c7e7b610SNamhyung Kim return 0; 235c7e7b610SNamhyung Kim } 236c7e7b610SNamhyung Kim 237b15636c6SJiri Olsa static void disasm_rb_tree__insert(struct rb_root *root, struct annotation_line *al) 238aca7a94dSNamhyung Kim { 23929ed6e76SArnaldo Carvalho de Melo struct rb_node **p = &root->rb_node; 240aca7a94dSNamhyung Kim struct rb_node *parent = NULL; 2413ab6db8dSJiri Olsa struct annotation_line *l; 242aca7a94dSNamhyung Kim 243aca7a94dSNamhyung Kim while (*p != NULL) { 244aca7a94dSNamhyung Kim parent = *p; 2453ab6db8dSJiri Olsa l = rb_entry(parent, struct annotation_line, rb_node); 246c7e7b610SNamhyung Kim 247b15636c6SJiri Olsa if (disasm__cmp(al, l)) 248aca7a94dSNamhyung Kim p = &(*p)->rb_left; 249aca7a94dSNamhyung Kim else 250aca7a94dSNamhyung Kim p = &(*p)->rb_right; 251aca7a94dSNamhyung Kim } 2523ab6db8dSJiri Olsa rb_link_node(&al->rb_node, parent, p); 2533ab6db8dSJiri Olsa rb_insert_color(&al->rb_node, root); 254aca7a94dSNamhyung Kim } 255aca7a94dSNamhyung Kim 25605e8b080SArnaldo Carvalho de Melo static void annotate_browser__set_top(struct annotate_browser *browser, 257ec03a77dSJiri Olsa struct annotation_line *pos, u32 idx) 258aca7a94dSNamhyung Kim { 2599b80d1f9SArnaldo Carvalho de Melo struct annotation *notes = browser__annotation(&browser->b); 260aca7a94dSNamhyung Kim unsigned back; 261aca7a94dSNamhyung Kim 26205e8b080SArnaldo Carvalho de Melo ui_browser__refresh_dimensions(&browser->b); 26305e8b080SArnaldo Carvalho de Melo back = browser->b.height / 2; 26405e8b080SArnaldo Carvalho de Melo browser->b.top_idx = browser->b.index = idx; 265aca7a94dSNamhyung Kim 26605e8b080SArnaldo Carvalho de Melo while (browser->b.top_idx != 0 && back != 0) { 267ec03a77dSJiri Olsa pos = list_entry(pos->node.prev, struct annotation_line, node); 268aca7a94dSNamhyung Kim 2699b80d1f9SArnaldo Carvalho de Melo if (annotation_line__filter(pos, notes)) 270aca7a94dSNamhyung Kim continue; 271aca7a94dSNamhyung Kim 27205e8b080SArnaldo Carvalho de Melo --browser->b.top_idx; 273aca7a94dSNamhyung Kim --back; 274aca7a94dSNamhyung Kim } 275aca7a94dSNamhyung Kim 276ec03a77dSJiri Olsa browser->b.top = pos; 27705e8b080SArnaldo Carvalho de Melo browser->b.navkeypressed = true; 278aca7a94dSNamhyung Kim } 279aca7a94dSNamhyung Kim 280aca7a94dSNamhyung Kim static void annotate_browser__set_rb_top(struct annotate_browser *browser, 281aca7a94dSNamhyung Kim struct rb_node *nd) 282aca7a94dSNamhyung Kim { 28395aa89d9SArnaldo Carvalho de Melo struct annotation *notes = browser__annotation(&browser->b); 2844850c92eSArnaldo Carvalho de Melo struct annotation_line * pos = rb_entry(nd, struct annotation_line, rb_node); 2854850c92eSArnaldo Carvalho de Melo u32 idx = pos->idx; 286aca7a94dSNamhyung Kim 28716932d77SArnaldo Carvalho de Melo if (notes->options->hide_src_code) 2884850c92eSArnaldo Carvalho de Melo idx = pos->idx_asm; 289a44b45f2SArnaldo Carvalho de Melo annotate_browser__set_top(browser, pos, idx); 290aca7a94dSNamhyung Kim browser->curr_hot = nd; 291aca7a94dSNamhyung Kim } 292aca7a94dSNamhyung Kim 293aca7a94dSNamhyung Kim static void annotate_browser__calc_percent(struct annotate_browser *browser, 294db8fd07aSNamhyung Kim struct perf_evsel *evsel) 295aca7a94dSNamhyung Kim { 296aca7a94dSNamhyung Kim struct map_symbol *ms = browser->b.priv; 297aca7a94dSNamhyung Kim struct symbol *sym = ms->sym; 298aca7a94dSNamhyung Kim struct annotation *notes = symbol__annotation(sym); 299c4c72436SJiri Olsa struct disasm_line *pos; 300aca7a94dSNamhyung Kim 301aca7a94dSNamhyung Kim browser->entries = RB_ROOT; 302aca7a94dSNamhyung Kim 303aca7a94dSNamhyung Kim pthread_mutex_lock(¬es->lock); 304aca7a94dSNamhyung Kim 305e425da6cSJiri Olsa symbol__calc_percent(sym, evsel); 306e425da6cSJiri Olsa 307a17c4ca0SJiri Olsa list_for_each_entry(pos, ¬es->src->source, al.node) { 308c7e7b610SNamhyung Kim double max_percent = 0.0; 309c7e7b610SNamhyung Kim int i; 310e64aa75bSNamhyung Kim 311d5490b96SJiri Olsa if (pos->al.offset == -1) { 3125b12adc8SJiri Olsa RB_CLEAR_NODE(&pos->al.rb_node); 313e64aa75bSNamhyung Kim continue; 314e64aa75bSNamhyung Kim } 315e64aa75bSNamhyung Kim 316b15636c6SJiri Olsa for (i = 0; i < pos->al.samples_nr; i++) { 317e425da6cSJiri Olsa struct annotation_data *sample = &pos->al.samples[i]; 3180c4a5bceSMartin Liška 3193ab6db8dSJiri Olsa if (max_percent < sample->percent) 3203ab6db8dSJiri Olsa max_percent = sample->percent; 321c7e7b610SNamhyung Kim } 322c7e7b610SNamhyung Kim 32337236d5eSJiri Olsa if (max_percent < 0.01 && pos->al.ipc == 0) { 3245b12adc8SJiri Olsa RB_CLEAR_NODE(&pos->al.rb_node); 325aca7a94dSNamhyung Kim continue; 326aca7a94dSNamhyung Kim } 327b15636c6SJiri Olsa disasm_rb_tree__insert(&browser->entries, &pos->al); 328aca7a94dSNamhyung Kim } 329aca7a94dSNamhyung Kim pthread_mutex_unlock(¬es->lock); 330aca7a94dSNamhyung Kim 331aca7a94dSNamhyung Kim browser->curr_hot = rb_last(&browser->entries); 332aca7a94dSNamhyung Kim } 333aca7a94dSNamhyung Kim 334aca7a94dSNamhyung Kim static bool annotate_browser__toggle_source(struct annotate_browser *browser) 335aca7a94dSNamhyung Kim { 33695aa89d9SArnaldo Carvalho de Melo struct annotation *notes = browser__annotation(&browser->b); 337ec03a77dSJiri Olsa struct annotation_line *al; 338aca7a94dSNamhyung Kim off_t offset = browser->b.index - browser->b.top_idx; 339aca7a94dSNamhyung Kim 340aca7a94dSNamhyung Kim browser->b.seek(&browser->b, offset, SEEK_CUR); 341ec03a77dSJiri Olsa al = list_entry(browser->b.top, struct annotation_line, node); 342aca7a94dSNamhyung Kim 34316932d77SArnaldo Carvalho de Melo if (notes->options->hide_src_code) { 3444850c92eSArnaldo Carvalho de Melo if (al->idx_asm < offset) 3454850c92eSArnaldo Carvalho de Melo offset = al->idx; 346aca7a94dSNamhyung Kim 3471cf5f98aSArnaldo Carvalho de Melo browser->b.nr_entries = notes->nr_entries; 34816932d77SArnaldo Carvalho de Melo notes->options->hide_src_code = false; 349aca7a94dSNamhyung Kim browser->b.seek(&browser->b, -offset, SEEK_CUR); 3504850c92eSArnaldo Carvalho de Melo browser->b.top_idx = al->idx - offset; 3514850c92eSArnaldo Carvalho de Melo browser->b.index = al->idx; 352aca7a94dSNamhyung Kim } else { 3534850c92eSArnaldo Carvalho de Melo if (al->idx_asm < 0) { 354aca7a94dSNamhyung Kim ui_helpline__puts("Only available for assembly lines."); 355aca7a94dSNamhyung Kim browser->b.seek(&browser->b, -offset, SEEK_CUR); 356aca7a94dSNamhyung Kim return false; 357aca7a94dSNamhyung Kim } 358aca7a94dSNamhyung Kim 3594850c92eSArnaldo Carvalho de Melo if (al->idx_asm < offset) 3604850c92eSArnaldo Carvalho de Melo offset = al->idx_asm; 361aca7a94dSNamhyung Kim 3621cf5f98aSArnaldo Carvalho de Melo browser->b.nr_entries = notes->nr_asm_entries; 36316932d77SArnaldo Carvalho de Melo notes->options->hide_src_code = true; 364aca7a94dSNamhyung Kim browser->b.seek(&browser->b, -offset, SEEK_CUR); 3654850c92eSArnaldo Carvalho de Melo browser->b.top_idx = al->idx_asm - offset; 3664850c92eSArnaldo Carvalho de Melo browser->b.index = al->idx_asm; 367aca7a94dSNamhyung Kim } 368aca7a94dSNamhyung Kim 369aca7a94dSNamhyung Kim return true; 370aca7a94dSNamhyung Kim } 371aca7a94dSNamhyung Kim 3721cf5f98aSArnaldo Carvalho de Melo static void ui_browser__init_asm_mode(struct ui_browser *browser) 373e9823b21SArnaldo Carvalho de Melo { 3741cf5f98aSArnaldo Carvalho de Melo struct annotation *notes = browser__annotation(browser); 3751cf5f98aSArnaldo Carvalho de Melo ui_browser__reset_index(browser); 3761cf5f98aSArnaldo Carvalho de Melo browser->nr_entries = notes->nr_asm_entries; 377e9823b21SArnaldo Carvalho de Melo } 378e9823b21SArnaldo Carvalho de Melo 37934f77abcSAdrian Hunter #define SYM_TITLE_MAX_SIZE (PATH_MAX + 64) 38034f77abcSAdrian Hunter 38134f77abcSAdrian Hunter static int sym_title(struct symbol *sym, struct map *map, char *title, 38234f77abcSAdrian Hunter size_t sz) 38334f77abcSAdrian Hunter { 38434f77abcSAdrian Hunter return snprintf(title, sz, "%s %s", sym->name, map->dso->long_name); 38534f77abcSAdrian Hunter } 38634f77abcSAdrian Hunter 387*e4cc91b8SArnaldo Carvalho de Melo /* 388*e4cc91b8SArnaldo Carvalho de Melo * This can be called from external jumps, i.e. jumps from one functon 389*e4cc91b8SArnaldo Carvalho de Melo * to another, like from the kernel's entry_SYSCALL_64 function to the 390*e4cc91b8SArnaldo Carvalho de Melo * swapgs_restore_regs_and_return_to_usermode() function. 391*e4cc91b8SArnaldo Carvalho de Melo * 392*e4cc91b8SArnaldo Carvalho de Melo * So all we check here is that dl->ops.target.sym is set, if it is, just 393*e4cc91b8SArnaldo Carvalho de Melo * go to that function and when exiting from its disassembly, come back 394*e4cc91b8SArnaldo Carvalho de Melo * to the calling function. 395*e4cc91b8SArnaldo Carvalho de Melo */ 396db8fd07aSNamhyung Kim static bool annotate_browser__callq(struct annotate_browser *browser, 397db8fd07aSNamhyung Kim struct perf_evsel *evsel, 3989783adf7SNamhyung Kim struct hist_browser_timer *hbt) 399aca7a94dSNamhyung Kim { 400aca7a94dSNamhyung Kim struct map_symbol *ms = browser->b.priv; 4017bcbcd58SJiri Olsa struct disasm_line *dl = disasm_line(browser->selection); 402aca7a94dSNamhyung Kim struct annotation *notes; 40334f77abcSAdrian Hunter char title[SYM_TITLE_MAX_SIZE]; 404aca7a94dSNamhyung Kim 405696703afSArnaldo Carvalho de Melo if (!dl->ops.target.sym) { 406aca7a94dSNamhyung Kim ui_helpline__puts("The called function was not found."); 407aca7a94dSNamhyung Kim return true; 408aca7a94dSNamhyung Kim } 409aca7a94dSNamhyung Kim 410696703afSArnaldo Carvalho de Melo notes = symbol__annotation(dl->ops.target.sym); 411aca7a94dSNamhyung Kim pthread_mutex_lock(¬es->lock); 412aca7a94dSNamhyung Kim 413696703afSArnaldo Carvalho de Melo if (notes->src == NULL && symbol__alloc_hist(dl->ops.target.sym) < 0) { 414aca7a94dSNamhyung Kim pthread_mutex_unlock(¬es->lock); 415aca7a94dSNamhyung Kim ui__warning("Not enough memory for annotating '%s' symbol!\n", 416696703afSArnaldo Carvalho de Melo dl->ops.target.sym->name); 417aca7a94dSNamhyung Kim return true; 418aca7a94dSNamhyung Kim } 419aca7a94dSNamhyung Kim 420aca7a94dSNamhyung Kim pthread_mutex_unlock(¬es->lock); 421696703afSArnaldo Carvalho de Melo symbol__tui_annotate(dl->ops.target.sym, ms->map, evsel, hbt); 4221179e11bSAdrian Hunter sym_title(ms->sym, ms->map, title, sizeof(title)); 42334f77abcSAdrian Hunter ui_browser__show_title(&browser->b, title); 424aca7a94dSNamhyung Kim return true; 425aca7a94dSNamhyung Kim } 426aca7a94dSNamhyung Kim 42729ed6e76SArnaldo Carvalho de Melo static 42829ed6e76SArnaldo Carvalho de Melo struct disasm_line *annotate_browser__find_offset(struct annotate_browser *browser, 429aca7a94dSNamhyung Kim s64 offset, s64 *idx) 430aca7a94dSNamhyung Kim { 43195aa89d9SArnaldo Carvalho de Melo struct annotation *notes = browser__annotation(&browser->b); 43229ed6e76SArnaldo Carvalho de Melo struct disasm_line *pos; 433aca7a94dSNamhyung Kim 434aca7a94dSNamhyung Kim *idx = 0; 435a17c4ca0SJiri Olsa list_for_each_entry(pos, ¬es->src->source, al.node) { 436d5490b96SJiri Olsa if (pos->al.offset == offset) 437aca7a94dSNamhyung Kim return pos; 4389b80d1f9SArnaldo Carvalho de Melo if (!annotation_line__filter(&pos->al, notes)) 439aca7a94dSNamhyung Kim ++*idx; 440aca7a94dSNamhyung Kim } 441aca7a94dSNamhyung Kim 442aca7a94dSNamhyung Kim return NULL; 443aca7a94dSNamhyung Kim } 444aca7a94dSNamhyung Kim 445*e4cc91b8SArnaldo Carvalho de Melo static bool annotate_browser__jump(struct annotate_browser *browser, 446*e4cc91b8SArnaldo Carvalho de Melo struct perf_evsel *evsel, 447*e4cc91b8SArnaldo Carvalho de Melo struct hist_browser_timer *hbt) 448aca7a94dSNamhyung Kim { 4497bcbcd58SJiri Olsa struct disasm_line *dl = disasm_line(browser->selection); 4505252b1aeSArnaldo Carvalho de Melo u64 offset; 4514f9d0325SArnaldo Carvalho de Melo s64 idx; 452aca7a94dSNamhyung Kim 45375b49202SArnaldo Carvalho de Melo if (!ins__is_jump(&dl->ins)) 454aca7a94dSNamhyung Kim return false; 455aca7a94dSNamhyung Kim 456*e4cc91b8SArnaldo Carvalho de Melo if (dl->ops.target.outside) { 457*e4cc91b8SArnaldo Carvalho de Melo annotate_browser__callq(browser, evsel, hbt); 458*e4cc91b8SArnaldo Carvalho de Melo return true; 459*e4cc91b8SArnaldo Carvalho de Melo } 460*e4cc91b8SArnaldo Carvalho de Melo 4615252b1aeSArnaldo Carvalho de Melo offset = dl->ops.target.offset; 4625252b1aeSArnaldo Carvalho de Melo dl = annotate_browser__find_offset(browser, offset, &idx); 46329ed6e76SArnaldo Carvalho de Melo if (dl == NULL) { 4645252b1aeSArnaldo Carvalho de Melo ui_helpline__printf("Invalid jump offset: %" PRIx64, offset); 465aca7a94dSNamhyung Kim return true; 466aca7a94dSNamhyung Kim } 467aca7a94dSNamhyung Kim 468ec03a77dSJiri Olsa annotate_browser__set_top(browser, &dl->al, idx); 469aca7a94dSNamhyung Kim 470aca7a94dSNamhyung Kim return true; 471aca7a94dSNamhyung Kim } 472aca7a94dSNamhyung Kim 47329ed6e76SArnaldo Carvalho de Melo static 4749213afbdSJiri Olsa struct annotation_line *annotate_browser__find_string(struct annotate_browser *browser, 475aca7a94dSNamhyung Kim char *s, s64 *idx) 476aca7a94dSNamhyung Kim { 47795aa89d9SArnaldo Carvalho de Melo struct annotation *notes = browser__annotation(&browser->b); 4789213afbdSJiri Olsa struct annotation_line *al = browser->selection; 479aca7a94dSNamhyung Kim 480aca7a94dSNamhyung Kim *idx = browser->b.index; 4819213afbdSJiri Olsa list_for_each_entry_continue(al, ¬es->src->source, node) { 4829b80d1f9SArnaldo Carvalho de Melo if (annotation_line__filter(al, notes)) 483aca7a94dSNamhyung Kim continue; 484aca7a94dSNamhyung Kim 485aca7a94dSNamhyung Kim ++*idx; 486aca7a94dSNamhyung Kim 4879213afbdSJiri Olsa if (al->line && strstr(al->line, s) != NULL) 4889213afbdSJiri Olsa return al; 489aca7a94dSNamhyung Kim } 490aca7a94dSNamhyung Kim 491aca7a94dSNamhyung Kim return NULL; 492aca7a94dSNamhyung Kim } 493aca7a94dSNamhyung Kim 494aca7a94dSNamhyung Kim static bool __annotate_browser__search(struct annotate_browser *browser) 495aca7a94dSNamhyung Kim { 4969213afbdSJiri Olsa struct annotation_line *al; 497aca7a94dSNamhyung Kim s64 idx; 498aca7a94dSNamhyung Kim 4999213afbdSJiri Olsa al = annotate_browser__find_string(browser, browser->search_bf, &idx); 5009213afbdSJiri Olsa if (al == NULL) { 501aca7a94dSNamhyung Kim ui_helpline__puts("String not found!"); 502aca7a94dSNamhyung Kim return false; 503aca7a94dSNamhyung Kim } 504aca7a94dSNamhyung Kim 505ec03a77dSJiri Olsa annotate_browser__set_top(browser, al, idx); 506aca7a94dSNamhyung Kim browser->searching_backwards = false; 507aca7a94dSNamhyung Kim return true; 508aca7a94dSNamhyung Kim } 509aca7a94dSNamhyung Kim 51029ed6e76SArnaldo Carvalho de Melo static 5119213afbdSJiri Olsa struct annotation_line *annotate_browser__find_string_reverse(struct annotate_browser *browser, 512aca7a94dSNamhyung Kim char *s, s64 *idx) 513aca7a94dSNamhyung Kim { 51495aa89d9SArnaldo Carvalho de Melo struct annotation *notes = browser__annotation(&browser->b); 5159213afbdSJiri Olsa struct annotation_line *al = browser->selection; 516aca7a94dSNamhyung Kim 517aca7a94dSNamhyung Kim *idx = browser->b.index; 5189213afbdSJiri Olsa list_for_each_entry_continue_reverse(al, ¬es->src->source, node) { 5199b80d1f9SArnaldo Carvalho de Melo if (annotation_line__filter(al, notes)) 520aca7a94dSNamhyung Kim continue; 521aca7a94dSNamhyung Kim 522aca7a94dSNamhyung Kim --*idx; 523aca7a94dSNamhyung Kim 5249213afbdSJiri Olsa if (al->line && strstr(al->line, s) != NULL) 5259213afbdSJiri Olsa return al; 526aca7a94dSNamhyung Kim } 527aca7a94dSNamhyung Kim 528aca7a94dSNamhyung Kim return NULL; 529aca7a94dSNamhyung Kim } 530aca7a94dSNamhyung Kim 531aca7a94dSNamhyung Kim static bool __annotate_browser__search_reverse(struct annotate_browser *browser) 532aca7a94dSNamhyung Kim { 5339213afbdSJiri Olsa struct annotation_line *al; 534aca7a94dSNamhyung Kim s64 idx; 535aca7a94dSNamhyung Kim 5369213afbdSJiri Olsa al = annotate_browser__find_string_reverse(browser, browser->search_bf, &idx); 5379213afbdSJiri Olsa if (al == NULL) { 538aca7a94dSNamhyung Kim ui_helpline__puts("String not found!"); 539aca7a94dSNamhyung Kim return false; 540aca7a94dSNamhyung Kim } 541aca7a94dSNamhyung Kim 542ec03a77dSJiri Olsa annotate_browser__set_top(browser, al, idx); 543aca7a94dSNamhyung Kim browser->searching_backwards = true; 544aca7a94dSNamhyung Kim return true; 545aca7a94dSNamhyung Kim } 546aca7a94dSNamhyung Kim 547aca7a94dSNamhyung Kim static bool annotate_browser__search_window(struct annotate_browser *browser, 548aca7a94dSNamhyung Kim int delay_secs) 549aca7a94dSNamhyung Kim { 550aca7a94dSNamhyung Kim if (ui_browser__input_window("Search", "String: ", browser->search_bf, 551aca7a94dSNamhyung Kim "ENTER: OK, ESC: Cancel", 552aca7a94dSNamhyung Kim delay_secs * 2) != K_ENTER || 553aca7a94dSNamhyung Kim !*browser->search_bf) 554aca7a94dSNamhyung Kim return false; 555aca7a94dSNamhyung Kim 556aca7a94dSNamhyung Kim return true; 557aca7a94dSNamhyung Kim } 558aca7a94dSNamhyung Kim 559aca7a94dSNamhyung Kim static bool annotate_browser__search(struct annotate_browser *browser, int delay_secs) 560aca7a94dSNamhyung Kim { 561aca7a94dSNamhyung Kim if (annotate_browser__search_window(browser, delay_secs)) 562aca7a94dSNamhyung Kim return __annotate_browser__search(browser); 563aca7a94dSNamhyung Kim 564aca7a94dSNamhyung Kim return false; 565aca7a94dSNamhyung Kim } 566aca7a94dSNamhyung Kim 567aca7a94dSNamhyung Kim static bool annotate_browser__continue_search(struct annotate_browser *browser, 568aca7a94dSNamhyung Kim int delay_secs) 569aca7a94dSNamhyung Kim { 570aca7a94dSNamhyung Kim if (!*browser->search_bf) 571aca7a94dSNamhyung Kim return annotate_browser__search(browser, delay_secs); 572aca7a94dSNamhyung Kim 573aca7a94dSNamhyung Kim return __annotate_browser__search(browser); 574aca7a94dSNamhyung Kim } 575aca7a94dSNamhyung Kim 576aca7a94dSNamhyung Kim static bool annotate_browser__search_reverse(struct annotate_browser *browser, 577aca7a94dSNamhyung Kim int delay_secs) 578aca7a94dSNamhyung Kim { 579aca7a94dSNamhyung Kim if (annotate_browser__search_window(browser, delay_secs)) 580aca7a94dSNamhyung Kim return __annotate_browser__search_reverse(browser); 581aca7a94dSNamhyung Kim 582aca7a94dSNamhyung Kim return false; 583aca7a94dSNamhyung Kim } 584aca7a94dSNamhyung Kim 585aca7a94dSNamhyung Kim static 586aca7a94dSNamhyung Kim bool annotate_browser__continue_search_reverse(struct annotate_browser *browser, 587aca7a94dSNamhyung Kim int delay_secs) 588aca7a94dSNamhyung Kim { 589aca7a94dSNamhyung Kim if (!*browser->search_bf) 590aca7a94dSNamhyung Kim return annotate_browser__search_reverse(browser, delay_secs); 591aca7a94dSNamhyung Kim 592aca7a94dSNamhyung Kim return __annotate_browser__search_reverse(browser); 593aca7a94dSNamhyung Kim } 594aca7a94dSNamhyung Kim 595db8fd07aSNamhyung Kim static int annotate_browser__run(struct annotate_browser *browser, 596db8fd07aSNamhyung Kim struct perf_evsel *evsel, 5979783adf7SNamhyung Kim struct hist_browser_timer *hbt) 598aca7a94dSNamhyung Kim { 599aca7a94dSNamhyung Kim struct rb_node *nd = NULL; 60005e8b080SArnaldo Carvalho de Melo struct map_symbol *ms = browser->b.priv; 601aca7a94dSNamhyung Kim struct symbol *sym = ms->sym; 60216932d77SArnaldo Carvalho de Melo struct annotation *notes = symbol__annotation(ms->sym); 60354e7a4e8SArnaldo Carvalho de Melo const char *help = "Press 'h' for help on key bindings"; 6049783adf7SNamhyung Kim int delay_secs = hbt ? hbt->refresh : 0; 605aca7a94dSNamhyung Kim int key; 60634f77abcSAdrian Hunter char title[SYM_TITLE_MAX_SIZE]; 607aca7a94dSNamhyung Kim 60834f77abcSAdrian Hunter sym_title(sym, ms->map, title, sizeof(title)); 60934f77abcSAdrian Hunter if (ui_browser__show(&browser->b, title, help) < 0) 610aca7a94dSNamhyung Kim return -1; 611aca7a94dSNamhyung Kim 612db8fd07aSNamhyung Kim annotate_browser__calc_percent(browser, evsel); 613aca7a94dSNamhyung Kim 61405e8b080SArnaldo Carvalho de Melo if (browser->curr_hot) { 61505e8b080SArnaldo Carvalho de Melo annotate_browser__set_rb_top(browser, browser->curr_hot); 61605e8b080SArnaldo Carvalho de Melo browser->b.navkeypressed = false; 617aca7a94dSNamhyung Kim } 618aca7a94dSNamhyung Kim 61905e8b080SArnaldo Carvalho de Melo nd = browser->curr_hot; 620aca7a94dSNamhyung Kim 621aca7a94dSNamhyung Kim while (1) { 62205e8b080SArnaldo Carvalho de Melo key = ui_browser__run(&browser->b, delay_secs); 623aca7a94dSNamhyung Kim 624aca7a94dSNamhyung Kim if (delay_secs != 0) { 625db8fd07aSNamhyung Kim annotate_browser__calc_percent(browser, evsel); 626aca7a94dSNamhyung Kim /* 627aca7a94dSNamhyung Kim * Current line focus got out of the list of most active 628aca7a94dSNamhyung Kim * lines, NULL it so that if TAB|UNTAB is pressed, we 629aca7a94dSNamhyung Kim * move to curr_hot (current hottest line). 630aca7a94dSNamhyung Kim */ 631aca7a94dSNamhyung Kim if (nd != NULL && RB_EMPTY_NODE(nd)) 632aca7a94dSNamhyung Kim nd = NULL; 633aca7a94dSNamhyung Kim } 634aca7a94dSNamhyung Kim 635aca7a94dSNamhyung Kim switch (key) { 636aca7a94dSNamhyung Kim case K_TIMER: 6379783adf7SNamhyung Kim if (hbt) 6389783adf7SNamhyung Kim hbt->timer(hbt->arg); 639aca7a94dSNamhyung Kim 640aca7a94dSNamhyung Kim if (delay_secs != 0) 641db8fd07aSNamhyung Kim symbol__annotate_decay_histogram(sym, evsel->idx); 642aca7a94dSNamhyung Kim continue; 643aca7a94dSNamhyung Kim case K_TAB: 644aca7a94dSNamhyung Kim if (nd != NULL) { 645aca7a94dSNamhyung Kim nd = rb_prev(nd); 646aca7a94dSNamhyung Kim if (nd == NULL) 64705e8b080SArnaldo Carvalho de Melo nd = rb_last(&browser->entries); 648aca7a94dSNamhyung Kim } else 64905e8b080SArnaldo Carvalho de Melo nd = browser->curr_hot; 650aca7a94dSNamhyung Kim break; 651aca7a94dSNamhyung Kim case K_UNTAB: 652d4913cbdSMarkus Trippelsdorf if (nd != NULL) { 653aca7a94dSNamhyung Kim nd = rb_next(nd); 654aca7a94dSNamhyung Kim if (nd == NULL) 65505e8b080SArnaldo Carvalho de Melo nd = rb_first(&browser->entries); 656d4913cbdSMarkus Trippelsdorf } else 65705e8b080SArnaldo Carvalho de Melo nd = browser->curr_hot; 658aca7a94dSNamhyung Kim break; 65954e7a4e8SArnaldo Carvalho de Melo case K_F1: 660aca7a94dSNamhyung Kim case 'h': 66105e8b080SArnaldo Carvalho de Melo ui_browser__help_window(&browser->b, 66254e7a4e8SArnaldo Carvalho de Melo "UP/DOWN/PGUP\n" 66354e7a4e8SArnaldo Carvalho de Melo "PGDN/SPACE Navigate\n" 66454e7a4e8SArnaldo Carvalho de Melo "q/ESC/CTRL+C Exit\n\n" 6657727a925SArnaldo Carvalho de Melo "ENTER Go to target\n" 6667727a925SArnaldo Carvalho de Melo "ESC Exit\n" 667eba9fac0SArnaldo Carvalho de Melo "H Go to hottest instruction\n" 668eba9fac0SArnaldo Carvalho de Melo "TAB/shift+TAB Cycle thru hottest instructions\n" 66954e7a4e8SArnaldo Carvalho de Melo "j Toggle showing jump to target arrows\n" 67054e7a4e8SArnaldo Carvalho de Melo "J Toggle showing number of jump sources on targets\n" 67154e7a4e8SArnaldo Carvalho de Melo "n Search next string\n" 67254e7a4e8SArnaldo Carvalho de Melo "o Toggle disassembler output/simplified view\n" 67354e7a4e8SArnaldo Carvalho de Melo "s Toggle source code view\n" 6743a555c77STaeung Song "t Circulate percent, total period, samples view\n" 67554e7a4e8SArnaldo Carvalho de Melo "/ Search string\n" 676e592488cSAndi Kleen "k Toggle line numbers\n" 677d9bd7665SArnaldo Carvalho de Melo "P Print to [symbol_name].annotation file.\n" 67879ee47faSFeng Tang "r Run available scripts\n" 679fcd9fef9SArnaldo Carvalho de Melo "? Search string backwards\n"); 68054e7a4e8SArnaldo Carvalho de Melo continue; 68179ee47faSFeng Tang case 'r': 68279ee47faSFeng Tang { 68379ee47faSFeng Tang script_browse(NULL); 68479ee47faSFeng Tang continue; 68579ee47faSFeng Tang } 686e592488cSAndi Kleen case 'k': 68716932d77SArnaldo Carvalho de Melo notes->options->show_linenr = !notes->options->show_linenr; 688e592488cSAndi Kleen break; 68954e7a4e8SArnaldo Carvalho de Melo case 'H': 69005e8b080SArnaldo Carvalho de Melo nd = browser->curr_hot; 691aca7a94dSNamhyung Kim break; 692aca7a94dSNamhyung Kim case 's': 69305e8b080SArnaldo Carvalho de Melo if (annotate_browser__toggle_source(browser)) 694aca7a94dSNamhyung Kim ui_helpline__puts(help); 695aca7a94dSNamhyung Kim continue; 696aca7a94dSNamhyung Kim case 'o': 69716932d77SArnaldo Carvalho de Melo notes->options->use_offset = !notes->options->use_offset; 6989761e86eSArnaldo Carvalho de Melo annotation__update_column_widths(notes); 699aca7a94dSNamhyung Kim continue; 7009d1ef56dSArnaldo Carvalho de Melo case 'j': 70116932d77SArnaldo Carvalho de Melo notes->options->jump_arrows = !notes->options->jump_arrows; 7029d1ef56dSArnaldo Carvalho de Melo continue; 7032402e4a9SArnaldo Carvalho de Melo case 'J': 70416932d77SArnaldo Carvalho de Melo notes->options->show_nr_jumps = !notes->options->show_nr_jumps; 7059761e86eSArnaldo Carvalho de Melo annotation__update_column_widths(notes); 706e9823b21SArnaldo Carvalho de Melo continue; 707aca7a94dSNamhyung Kim case '/': 70805e8b080SArnaldo Carvalho de Melo if (annotate_browser__search(browser, delay_secs)) { 709aca7a94dSNamhyung Kim show_help: 710aca7a94dSNamhyung Kim ui_helpline__puts(help); 711aca7a94dSNamhyung Kim } 712aca7a94dSNamhyung Kim continue; 713aca7a94dSNamhyung Kim case 'n': 71405e8b080SArnaldo Carvalho de Melo if (browser->searching_backwards ? 71505e8b080SArnaldo Carvalho de Melo annotate_browser__continue_search_reverse(browser, delay_secs) : 71605e8b080SArnaldo Carvalho de Melo annotate_browser__continue_search(browser, delay_secs)) 717aca7a94dSNamhyung Kim goto show_help; 718aca7a94dSNamhyung Kim continue; 719aca7a94dSNamhyung Kim case '?': 72005e8b080SArnaldo Carvalho de Melo if (annotate_browser__search_reverse(browser, delay_secs)) 721aca7a94dSNamhyung Kim goto show_help; 722aca7a94dSNamhyung Kim continue; 723e9823b21SArnaldo Carvalho de Melo case 'D': { 724e9823b21SArnaldo Carvalho de Melo static int seq; 725e9823b21SArnaldo Carvalho de Melo ui_helpline__pop(); 726e9823b21SArnaldo Carvalho de Melo ui_helpline__fpush("%d: nr_ent=%d, height=%d, idx=%d, top_idx=%d, nr_asm_entries=%d", 72705e8b080SArnaldo Carvalho de Melo seq++, browser->b.nr_entries, 72805e8b080SArnaldo Carvalho de Melo browser->b.height, 72905e8b080SArnaldo Carvalho de Melo browser->b.index, 73005e8b080SArnaldo Carvalho de Melo browser->b.top_idx, 7311cf5f98aSArnaldo Carvalho de Melo notes->nr_asm_entries); 732e9823b21SArnaldo Carvalho de Melo } 733e9823b21SArnaldo Carvalho de Melo continue; 734aca7a94dSNamhyung Kim case K_ENTER: 735aca7a94dSNamhyung Kim case K_RIGHT: 7367bcbcd58SJiri Olsa { 7377bcbcd58SJiri Olsa struct disasm_line *dl = disasm_line(browser->selection); 7387bcbcd58SJiri Olsa 73905e8b080SArnaldo Carvalho de Melo if (browser->selection == NULL) 740aca7a94dSNamhyung Kim ui_helpline__puts("Huh? No selection. Report to linux-kernel@vger.kernel.org"); 7417bcbcd58SJiri Olsa else if (browser->selection->offset == -1) 742aca7a94dSNamhyung Kim ui_helpline__puts("Actions are only available for assembly lines."); 7437bcbcd58SJiri Olsa else if (!dl->ins.ops) 744c4cceae3SArnaldo Carvalho de Melo goto show_sup_ins; 7457bcbcd58SJiri Olsa else if (ins__is_ret(&dl->ins)) 746c4cceae3SArnaldo Carvalho de Melo goto out; 747*e4cc91b8SArnaldo Carvalho de Melo else if (!(annotate_browser__jump(browser, evsel, hbt) || 748db8fd07aSNamhyung Kim annotate_browser__callq(browser, evsel, hbt))) { 749c4cceae3SArnaldo Carvalho de Melo show_sup_ins: 7506ef94929SNaveen N. Rao ui_helpline__puts("Actions are only available for function call/return & jump/branch instructions."); 751c4cceae3SArnaldo Carvalho de Melo } 752aca7a94dSNamhyung Kim continue; 7537bcbcd58SJiri Olsa } 754d9bd7665SArnaldo Carvalho de Melo case 'P': 755d9bd7665SArnaldo Carvalho de Melo map_symbol__annotation_dump(ms, evsel); 756d9bd7665SArnaldo Carvalho de Melo continue; 7570c4a5bceSMartin Liška case 't': 75816932d77SArnaldo Carvalho de Melo if (notes->options->show_total_period) { 75916932d77SArnaldo Carvalho de Melo notes->options->show_total_period = false; 76016932d77SArnaldo Carvalho de Melo notes->options->show_nr_samples = true; 76116932d77SArnaldo Carvalho de Melo } else if (notes->options->show_nr_samples) 76216932d77SArnaldo Carvalho de Melo notes->options->show_nr_samples = false; 7633a555c77STaeung Song else 76416932d77SArnaldo Carvalho de Melo notes->options->show_total_period = true; 7659761e86eSArnaldo Carvalho de Melo annotation__update_column_widths(notes); 7660c4a5bceSMartin Liška continue; 767aca7a94dSNamhyung Kim case K_LEFT: 768aca7a94dSNamhyung Kim case K_ESC: 769aca7a94dSNamhyung Kim case 'q': 770aca7a94dSNamhyung Kim case CTRL('c'): 771aca7a94dSNamhyung Kim goto out; 772aca7a94dSNamhyung Kim default: 773aca7a94dSNamhyung Kim continue; 774aca7a94dSNamhyung Kim } 775aca7a94dSNamhyung Kim 776aca7a94dSNamhyung Kim if (nd != NULL) 77705e8b080SArnaldo Carvalho de Melo annotate_browser__set_rb_top(browser, nd); 778aca7a94dSNamhyung Kim } 779aca7a94dSNamhyung Kim out: 78005e8b080SArnaldo Carvalho de Melo ui_browser__hide(&browser->b); 781aca7a94dSNamhyung Kim return key; 782aca7a94dSNamhyung Kim } 783aca7a94dSNamhyung Kim 784d5dbc518SArnaldo Carvalho de Melo int map_symbol__tui_annotate(struct map_symbol *ms, struct perf_evsel *evsel, 785d5dbc518SArnaldo Carvalho de Melo struct hist_browser_timer *hbt) 786d5dbc518SArnaldo Carvalho de Melo { 787d5dbc518SArnaldo Carvalho de Melo return symbol__tui_annotate(ms->sym, ms->map, evsel, hbt); 788d5dbc518SArnaldo Carvalho de Melo } 789d5dbc518SArnaldo Carvalho de Melo 790db8fd07aSNamhyung Kim int hist_entry__tui_annotate(struct hist_entry *he, struct perf_evsel *evsel, 7919783adf7SNamhyung Kim struct hist_browser_timer *hbt) 792aca7a94dSNamhyung Kim { 793ed426915SNamhyung Kim /* reset abort key so that it can get Ctrl-C as a key */ 794ed426915SNamhyung Kim SLang_reset_tty(); 795ed426915SNamhyung Kim SLang_init_tty(0, 0, 0); 796ed426915SNamhyung Kim 797d5dbc518SArnaldo Carvalho de Melo return map_symbol__tui_annotate(&he->ms, evsel, hbt); 798aca7a94dSNamhyung Kim } 799aca7a94dSNamhyung Kim 800db8fd07aSNamhyung Kim int symbol__tui_annotate(struct symbol *sym, struct map *map, 801db8fd07aSNamhyung Kim struct perf_evsel *evsel, 8029783adf7SNamhyung Kim struct hist_browser_timer *hbt) 803aca7a94dSNamhyung Kim { 8049d6bb41dSArnaldo Carvalho de Melo struct annotation *notes = symbol__annotation(sym); 805aca7a94dSNamhyung Kim struct map_symbol ms = { 806aca7a94dSNamhyung Kim .map = map, 807aca7a94dSNamhyung Kim .sym = sym, 808aca7a94dSNamhyung Kim }; 809aca7a94dSNamhyung Kim struct annotate_browser browser = { 810aca7a94dSNamhyung Kim .b = { 811a3f895beSArnaldo Carvalho de Melo .refresh = annotate_browser__refresh, 812aca7a94dSNamhyung Kim .seek = ui_browser__list_head_seek, 813aca7a94dSNamhyung Kim .write = annotate_browser__write, 81429ed6e76SArnaldo Carvalho de Melo .filter = disasm_line__filter, 815aca7a94dSNamhyung Kim .priv = &ms, 816aca7a94dSNamhyung Kim .use_navkeypressed = true, 817aca7a94dSNamhyung Kim }, 818aca7a94dSNamhyung Kim }; 819ee51d851SArnaldo Carvalho de Melo int ret = -1, err; 820aca7a94dSNamhyung Kim 821aca7a94dSNamhyung Kim if (sym == NULL) 822aca7a94dSNamhyung Kim return -1; 823aca7a94dSNamhyung Kim 824aca7a94dSNamhyung Kim if (map->dso->annotate_warned) 825aca7a94dSNamhyung Kim return -1; 826aca7a94dSNamhyung Kim 8277f0b6fdeSArnaldo Carvalho de Melo err = symbol__annotate2(sym, map, evsel, &annotation__default_options, &browser.arch); 828ee51d851SArnaldo Carvalho de Melo if (err) { 829ee51d851SArnaldo Carvalho de Melo char msg[BUFSIZ]; 830ee51d851SArnaldo Carvalho de Melo symbol__strerror_disassemble(sym, map, err, msg, sizeof(msg)); 831ee51d851SArnaldo Carvalho de Melo ui__error("Couldn't annotate %s:\n%s", sym->name, msg); 832b793a401SArnaldo Carvalho de Melo goto out_free_offsets; 833aca7a94dSNamhyung Kim } 834aca7a94dSNamhyung Kim 8357727a925SArnaldo Carvalho de Melo ui_helpline__push("Press ESC to exit"); 836aca7a94dSNamhyung Kim 8375bc49f61SArnaldo Carvalho de Melo browser.b.width = notes->max_line_len; 8381cf5f98aSArnaldo Carvalho de Melo browser.b.nr_entries = notes->nr_entries; 839aca7a94dSNamhyung Kim browser.b.entries = ¬es->src->source, 840aca7a94dSNamhyung Kim browser.b.width += 18; /* Percentage */ 841e9823b21SArnaldo Carvalho de Melo 84216932d77SArnaldo Carvalho de Melo if (notes->options->hide_src_code) 8431cf5f98aSArnaldo Carvalho de Melo ui_browser__init_asm_mode(&browser.b); 844e9823b21SArnaldo Carvalho de Melo 845db8fd07aSNamhyung Kim ret = annotate_browser__run(&browser, evsel, hbt); 846f8eb37bdSJiri Olsa 847f8eb37bdSJiri Olsa annotated_source__purge(notes->src); 848b793a401SArnaldo Carvalho de Melo 849b793a401SArnaldo Carvalho de Melo out_free_offsets: 8509d6bb41dSArnaldo Carvalho de Melo zfree(¬es->offsets); 851aca7a94dSNamhyung Kim return ret; 852aca7a94dSNamhyung Kim } 853