1b2441318SGreg Kroah-Hartman // SPDX-License-Identifier: GPL-2.0 2aca7a94dSNamhyung Kim #include "../../util/util.h" 3aca7a94dSNamhyung Kim #include "../browser.h" 4aca7a94dSNamhyung Kim #include "../helpline.h" 5aca7a94dSNamhyung Kim #include "../ui.h" 6aca7a94dSNamhyung Kim #include "../util.h" 7aca7a94dSNamhyung Kim #include "../../util/annotate.h" 8aca7a94dSNamhyung Kim #include "../../util/hist.h" 9aca7a94dSNamhyung Kim #include "../../util/sort.h" 10aca7a94dSNamhyung Kim #include "../../util/symbol.h" 11db8fd07aSNamhyung Kim #include "../../util/evsel.h" 1241840d21STaeung Song #include "../../util/config.h" 1369fb09f6SJin Yao #include "../../util/evlist.h" 14fd20e811SArnaldo Carvalho de Melo #include <inttypes.h> 15aca7a94dSNamhyung Kim #include <pthread.h> 16877a7a11SArnaldo Carvalho de Melo #include <linux/kernel.h> 178e99b6d4SArnaldo Carvalho de Melo #include <linux/string.h> 18b0742e90SArnaldo Carvalho de Melo #include <sys/ttydefaults.h> 19aca7a94dSNamhyung Kim 200c4a5bceSMartin Liška struct disasm_line_samples { 210c4a5bceSMartin Liška double percent; 22bb79a232SArnaldo Carvalho de Melo struct sym_hist_entry he; 230c4a5bceSMartin Liška }; 240c4a5bceSMartin Liška 2598bc80b0SArnaldo Carvalho de Melo static struct annotation_options annotate_browser__opts = { 26e9823b21SArnaldo Carvalho de Melo .use_offset = true, 27e9823b21SArnaldo Carvalho de Melo .jump_arrows = true, 28e9823b21SArnaldo Carvalho de Melo }; 29e9823b21SArnaldo Carvalho de Melo 30dcaa3948SJin Yao struct arch; 31dcaa3948SJin Yao 32aca7a94dSNamhyung Kim struct annotate_browser { 33aca7a94dSNamhyung Kim struct ui_browser b; 34aca7a94dSNamhyung Kim struct rb_root entries; 35aca7a94dSNamhyung Kim struct rb_node *curr_hot; 367bcbcd58SJiri Olsa struct annotation_line *selection; 37dcaa3948SJin Yao struct arch *arch; 38aca7a94dSNamhyung Kim bool searching_backwards; 39aca7a94dSNamhyung Kim char search_bf[128]; 40aca7a94dSNamhyung Kim }; 41aca7a94dSNamhyung Kim 4295aa89d9SArnaldo Carvalho de Melo static inline struct annotation *browser__annotation(struct ui_browser *browser) 4395aa89d9SArnaldo Carvalho de Melo { 4495aa89d9SArnaldo Carvalho de Melo struct map_symbol *ms = browser->priv; 4595aa89d9SArnaldo Carvalho de Melo return symbol__annotation(ms->sym); 4695aa89d9SArnaldo Carvalho de Melo } 4795aa89d9SArnaldo Carvalho de Melo 4816932d77SArnaldo Carvalho de Melo static bool disasm_line__filter(struct ui_browser *browser, void *entry) 49aca7a94dSNamhyung Kim { 5095aa89d9SArnaldo Carvalho de Melo struct annotation *notes = browser__annotation(browser); 51d5490b96SJiri Olsa struct annotation_line *al = list_entry(entry, struct annotation_line, node); 52*9b80d1f9SArnaldo Carvalho de Melo return annotation_line__filter(al, notes); 53aca7a94dSNamhyung Kim } 54aca7a94dSNamhyung Kim 5527feb761SArnaldo Carvalho de Melo static int ui_browser__jumps_percent_color(struct ui_browser *browser, int nr, bool current) 562402e4a9SArnaldo Carvalho de Melo { 5727feb761SArnaldo Carvalho de Melo struct annotation *notes = browser__annotation(browser); 58bc1c0f3dSArnaldo Carvalho de Melo 5927feb761SArnaldo Carvalho de Melo if (current && (!browser->use_navkeypressed || browser->navkeypressed)) 602402e4a9SArnaldo Carvalho de Melo return HE_COLORSET_SELECTED; 61bc1c0f3dSArnaldo Carvalho de Melo if (nr == notes->max_jump_sources) 622402e4a9SArnaldo Carvalho de Melo return HE_COLORSET_TOP; 632402e4a9SArnaldo Carvalho de Melo if (nr > 1) 642402e4a9SArnaldo Carvalho de Melo return HE_COLORSET_MEDIUM; 652402e4a9SArnaldo Carvalho de Melo return HE_COLORSET_NORMAL; 662402e4a9SArnaldo Carvalho de Melo } 672402e4a9SArnaldo Carvalho de Melo 68a1e9b74cSArnaldo Carvalho de Melo static int ui_browser__set_jumps_percent_color(void *browser, int nr, bool current) 692402e4a9SArnaldo Carvalho de Melo { 7027feb761SArnaldo Carvalho de Melo int color = ui_browser__jumps_percent_color(browser, nr, current); 7127feb761SArnaldo Carvalho de Melo return ui_browser__set_color(browser, color); 722402e4a9SArnaldo Carvalho de Melo } 732402e4a9SArnaldo Carvalho de Melo 74a1e9b74cSArnaldo Carvalho de Melo static int annotate_browser__set_color(void *browser, int color) 75aca7a94dSNamhyung Kim { 76a1e9b74cSArnaldo Carvalho de Melo return ui_browser__set_color(browser, color); 774ea08b52SArnaldo Carvalho de Melo } 784ea08b52SArnaldo Carvalho de Melo 79a1e9b74cSArnaldo Carvalho de Melo static void annotate_browser__write_graph(void *browser, int graph) 80a1e9b74cSArnaldo Carvalho de Melo { 81a1e9b74cSArnaldo Carvalho de Melo ui_browser__write_graph(browser, graph); 82a5433b3eSJiri Olsa } 83a5433b3eSJiri Olsa 842ba5eca1SArnaldo Carvalho de Melo static void annotate_browser__set_percent_color(void *browser, double percent, bool current) 852ba5eca1SArnaldo Carvalho de Melo { 862ba5eca1SArnaldo Carvalho de Melo ui_browser__set_percent_color(browser, percent, current); 872ba5eca1SArnaldo Carvalho de Melo } 882ba5eca1SArnaldo Carvalho de Melo 892ba5eca1SArnaldo Carvalho de Melo static void annotate_browser__printf(void *browser, const char *fmt, ...) 902ba5eca1SArnaldo Carvalho de Melo { 912ba5eca1SArnaldo Carvalho de Melo va_list args; 922ba5eca1SArnaldo Carvalho de Melo 932ba5eca1SArnaldo Carvalho de Melo va_start(args, fmt); 942ba5eca1SArnaldo Carvalho de Melo ui_browser__vprintf(browser, fmt, args); 952ba5eca1SArnaldo Carvalho de Melo va_end(args); 962ba5eca1SArnaldo Carvalho de Melo } 972ba5eca1SArnaldo Carvalho de Melo 98a5433b3eSJiri Olsa static void annotate_browser__write(struct ui_browser *browser, void *entry, int row) 99a5433b3eSJiri Olsa { 100a5433b3eSJiri Olsa struct annotate_browser *ab = container_of(browser, struct annotate_browser, b); 10195aa89d9SArnaldo Carvalho de Melo struct annotation *notes = browser__annotation(browser); 102a5433b3eSJiri Olsa struct annotation_line *al = list_entry(entry, struct annotation_line, node); 103c298304bSArnaldo Carvalho de Melo struct annotation_write_ops ops = { 104c298304bSArnaldo Carvalho de Melo .first_line = row == 0, 105c298304bSArnaldo Carvalho de Melo .current_entry = ui_browser__is_current_entry(browser, row), 106c298304bSArnaldo Carvalho de Melo .change_color = (!notes->options->hide_src_code && 107c298304bSArnaldo Carvalho de Melo (!ops.current_entry || 108c298304bSArnaldo Carvalho de Melo (browser->use_navkeypressed && 109c298304bSArnaldo Carvalho de Melo !browser->navkeypressed))), 110c298304bSArnaldo Carvalho de Melo .width = browser->width, 111c298304bSArnaldo Carvalho de Melo .obj = browser, 112c298304bSArnaldo Carvalho de Melo .set_color = annotate_browser__set_color, 113c298304bSArnaldo Carvalho de Melo .set_percent_color = annotate_browser__set_percent_color, 114c298304bSArnaldo Carvalho de Melo .set_jumps_percent_color = ui_browser__set_jumps_percent_color, 115c298304bSArnaldo Carvalho de Melo .printf = annotate_browser__printf, 116c298304bSArnaldo Carvalho de Melo .write_graph = annotate_browser__write_graph, 117c298304bSArnaldo Carvalho de Melo }; 118a5433b3eSJiri Olsa 119a5433b3eSJiri Olsa /* The scroll bar isn't being used */ 120a5433b3eSJiri Olsa if (!browser->navkeypressed) 121c298304bSArnaldo Carvalho de Melo ops.width += 1; 122a5433b3eSJiri Olsa 123c298304bSArnaldo Carvalho de Melo annotation_line__write(al, notes, &ops); 124aca7a94dSNamhyung Kim 125c298304bSArnaldo Carvalho de Melo if (ops.current_entry) 126a5433b3eSJiri Olsa ab->selection = al; 127aca7a94dSNamhyung Kim } 128aca7a94dSNamhyung Kim 1297e63a13aSJin Yao static bool is_fused(struct annotate_browser *ab, struct disasm_line *cursor) 1307e63a13aSJin Yao { 131a17c4ca0SJiri Olsa struct disasm_line *pos = list_prev_entry(cursor, al.node); 1327e63a13aSJin Yao const char *name; 1337e63a13aSJin Yao 1347e63a13aSJin Yao if (!pos) 1357e63a13aSJin Yao return false; 1367e63a13aSJin Yao 1377e63a13aSJin Yao if (ins__is_lock(&pos->ins)) 1387e63a13aSJin Yao name = pos->ops.locked.ins.name; 1397e63a13aSJin Yao else 1407e63a13aSJin Yao name = pos->ins.name; 1417e63a13aSJin Yao 1427e63a13aSJin Yao if (!name || !cursor->ins.name) 1437e63a13aSJin Yao return false; 1447e63a13aSJin Yao 1457e63a13aSJin Yao return ins__is_fused(ab->arch, name, cursor->ins.name); 1467e63a13aSJin Yao } 1477e63a13aSJin Yao 1489d1ef56dSArnaldo Carvalho de Melo static void annotate_browser__draw_current_jump(struct ui_browser *browser) 149a3f895beSArnaldo Carvalho de Melo { 150a3f895beSArnaldo Carvalho de Melo struct annotate_browser *ab = container_of(browser, struct annotate_browser, b); 1517bcbcd58SJiri Olsa struct disasm_line *cursor = disasm_line(ab->selection); 152a5ef2702SJiri Olsa struct annotation_line *target; 15383b1f2aaSArnaldo Carvalho de Melo unsigned int from, to; 15432ae1efdSNamhyung Kim struct map_symbol *ms = ab->b.priv; 15532ae1efdSNamhyung Kim struct symbol *sym = ms->sym; 1560e83a7e9SArnaldo Carvalho de Melo struct annotation *notes = symbol__annotation(sym); 1576af612d2SArnaldo Carvalho de Melo u8 pcnt_width = annotation__pcnt_width(notes); 15800ea0eb2SArnaldo Carvalho de Melo int width; 15932ae1efdSNamhyung Kim 16032ae1efdSNamhyung Kim /* PLT symbols contain external offsets */ 16132ae1efdSNamhyung Kim if (strstr(sym->name, "@plt")) 16232ae1efdSNamhyung Kim return; 163a3f895beSArnaldo Carvalho de Melo 164865c66c4SFrederik Deweerdt if (!disasm_line__is_valid_jump(cursor, sym)) 165a3f895beSArnaldo Carvalho de Melo return; 166a3f895beSArnaldo Carvalho de Melo 1679c04409dSArnaldo Carvalho de Melo /* 1689c04409dSArnaldo Carvalho de Melo * This first was seen with a gcc function, _cpp_lex_token, that 1699c04409dSArnaldo Carvalho de Melo * has the usual jumps: 1709c04409dSArnaldo Carvalho de Melo * 1719c04409dSArnaldo Carvalho de Melo * │1159e6c: ↓ jne 115aa32 <_cpp_lex_token@@Base+0xf92> 1729c04409dSArnaldo Carvalho de Melo * 1739c04409dSArnaldo Carvalho de Melo * I.e. jumps to a label inside that function (_cpp_lex_token), and 1749c04409dSArnaldo Carvalho de Melo * those works, but also this kind: 1759c04409dSArnaldo Carvalho de Melo * 1769c04409dSArnaldo Carvalho de Melo * │1159e8b: ↓ jne c469be <cpp_named_operator2name@@Base+0xa72> 1779c04409dSArnaldo Carvalho de Melo * 1789c04409dSArnaldo Carvalho de Melo * I.e. jumps to another function, outside _cpp_lex_token, which 1799c04409dSArnaldo Carvalho de Melo * are not being correctly handled generating as a side effect references 1809c04409dSArnaldo Carvalho de Melo * to ab->offset[] entries that are set to NULL, so to make this code 1819c04409dSArnaldo Carvalho de Melo * more robust, check that here. 1829c04409dSArnaldo Carvalho de Melo * 1839c04409dSArnaldo Carvalho de Melo * A proper fix for will be put in place, looking at the function 1849c04409dSArnaldo Carvalho de Melo * name right after the '<' token and probably treating this like a 1859c04409dSArnaldo Carvalho de Melo * 'call' instruction. 1869c04409dSArnaldo Carvalho de Melo */ 1879d6bb41dSArnaldo Carvalho de Melo target = notes->offsets[cursor->ops.target.offset]; 1889c04409dSArnaldo Carvalho de Melo if (target == NULL) { 1899d6bb41dSArnaldo Carvalho de Melo ui_helpline__printf("WARN: jump target inconsistency, press 'o', notes->offsets[%#x] = NULL\n", 1909c04409dSArnaldo Carvalho de Melo cursor->ops.target.offset); 1919c04409dSArnaldo Carvalho de Melo return; 1929c04409dSArnaldo Carvalho de Melo } 1939d1ef56dSArnaldo Carvalho de Melo 19416932d77SArnaldo Carvalho de Melo if (notes->options->hide_src_code) { 1954850c92eSArnaldo Carvalho de Melo from = cursor->al.idx_asm; 1964850c92eSArnaldo Carvalho de Melo to = target->idx_asm; 197a3f895beSArnaldo Carvalho de Melo } else { 1984850c92eSArnaldo Carvalho de Melo from = (u64)cursor->al.idx; 1994850c92eSArnaldo Carvalho de Melo to = (u64)target->idx; 200a3f895beSArnaldo Carvalho de Melo } 201a3f895beSArnaldo Carvalho de Melo 2020e83a7e9SArnaldo Carvalho de Melo width = annotation__cycles_width(notes); 203b40982e8SJin Yao 20478ce08dfSTaeung Song ui_browser__set_color(browser, HE_COLORSET_JUMP_ARROWS); 205b40982e8SJin Yao __ui_browser__line_arrow(browser, 2069761e86eSArnaldo Carvalho de Melo pcnt_width + 2 + notes->widths.addr + width, 207c7e7b610SNamhyung Kim from, to); 2087e63a13aSJin Yao 2097e63a13aSJin Yao if (is_fused(ab, cursor)) { 2107e63a13aSJin Yao ui_browser__mark_fused(browser, 2119761e86eSArnaldo Carvalho de Melo pcnt_width + 3 + notes->widths.addr + width, 2127e63a13aSJin Yao from - 1, 2137e63a13aSJin Yao to > from ? true : false); 2147e63a13aSJin Yao } 215a3f895beSArnaldo Carvalho de Melo } 216a3f895beSArnaldo Carvalho de Melo 217a3f895beSArnaldo Carvalho de Melo static unsigned int annotate_browser__refresh(struct ui_browser *browser) 218a3f895beSArnaldo Carvalho de Melo { 21995aa89d9SArnaldo Carvalho de Melo struct annotation *notes = browser__annotation(browser); 220a3f895beSArnaldo Carvalho de Melo int ret = ui_browser__list_head_refresh(browser); 2216af612d2SArnaldo Carvalho de Melo int pcnt_width = annotation__pcnt_width(notes); 222a3f895beSArnaldo Carvalho de Melo 22316932d77SArnaldo Carvalho de Melo if (notes->options->jump_arrows) 2249d1ef56dSArnaldo Carvalho de Melo annotate_browser__draw_current_jump(browser); 225a3f895beSArnaldo Carvalho de Melo 22683b1f2aaSArnaldo Carvalho de Melo ui_browser__set_color(browser, HE_COLORSET_NORMAL); 227c7e7b610SNamhyung Kim __ui_browser__vline(browser, pcnt_width, 0, browser->height - 1); 228a3f895beSArnaldo Carvalho de Melo return ret; 229a3f895beSArnaldo Carvalho de Melo } 230a3f895beSArnaldo Carvalho de Melo 231b15636c6SJiri Olsa static int disasm__cmp(struct annotation_line *a, struct annotation_line *b) 232c7e7b610SNamhyung Kim { 233c7e7b610SNamhyung Kim int i; 234c7e7b610SNamhyung Kim 235b15636c6SJiri Olsa for (i = 0; i < a->samples_nr; i++) { 2360c4a5bceSMartin Liška if (a->samples[i].percent == b->samples[i].percent) 237c7e7b610SNamhyung Kim continue; 2380c4a5bceSMartin Liška return a->samples[i].percent < b->samples[i].percent; 239c7e7b610SNamhyung Kim } 240c7e7b610SNamhyung Kim return 0; 241c7e7b610SNamhyung Kim } 242c7e7b610SNamhyung Kim 243b15636c6SJiri Olsa static void disasm_rb_tree__insert(struct rb_root *root, struct annotation_line *al) 244aca7a94dSNamhyung Kim { 24529ed6e76SArnaldo Carvalho de Melo struct rb_node **p = &root->rb_node; 246aca7a94dSNamhyung Kim struct rb_node *parent = NULL; 2473ab6db8dSJiri Olsa struct annotation_line *l; 248aca7a94dSNamhyung Kim 249aca7a94dSNamhyung Kim while (*p != NULL) { 250aca7a94dSNamhyung Kim parent = *p; 2513ab6db8dSJiri Olsa l = rb_entry(parent, struct annotation_line, rb_node); 252c7e7b610SNamhyung Kim 253b15636c6SJiri Olsa if (disasm__cmp(al, l)) 254aca7a94dSNamhyung Kim p = &(*p)->rb_left; 255aca7a94dSNamhyung Kim else 256aca7a94dSNamhyung Kim p = &(*p)->rb_right; 257aca7a94dSNamhyung Kim } 2583ab6db8dSJiri Olsa rb_link_node(&al->rb_node, parent, p); 2593ab6db8dSJiri Olsa rb_insert_color(&al->rb_node, root); 260aca7a94dSNamhyung Kim } 261aca7a94dSNamhyung Kim 26205e8b080SArnaldo Carvalho de Melo static void annotate_browser__set_top(struct annotate_browser *browser, 263ec03a77dSJiri Olsa struct annotation_line *pos, u32 idx) 264aca7a94dSNamhyung Kim { 265*9b80d1f9SArnaldo Carvalho de Melo struct annotation *notes = browser__annotation(&browser->b); 266aca7a94dSNamhyung Kim unsigned back; 267aca7a94dSNamhyung Kim 26805e8b080SArnaldo Carvalho de Melo ui_browser__refresh_dimensions(&browser->b); 26905e8b080SArnaldo Carvalho de Melo back = browser->b.height / 2; 27005e8b080SArnaldo Carvalho de Melo browser->b.top_idx = browser->b.index = idx; 271aca7a94dSNamhyung Kim 27205e8b080SArnaldo Carvalho de Melo while (browser->b.top_idx != 0 && back != 0) { 273ec03a77dSJiri Olsa pos = list_entry(pos->node.prev, struct annotation_line, node); 274aca7a94dSNamhyung Kim 275*9b80d1f9SArnaldo Carvalho de Melo if (annotation_line__filter(pos, notes)) 276aca7a94dSNamhyung Kim continue; 277aca7a94dSNamhyung Kim 27805e8b080SArnaldo Carvalho de Melo --browser->b.top_idx; 279aca7a94dSNamhyung Kim --back; 280aca7a94dSNamhyung Kim } 281aca7a94dSNamhyung Kim 282ec03a77dSJiri Olsa browser->b.top = pos; 28305e8b080SArnaldo Carvalho de Melo browser->b.navkeypressed = true; 284aca7a94dSNamhyung Kim } 285aca7a94dSNamhyung Kim 286aca7a94dSNamhyung Kim static void annotate_browser__set_rb_top(struct annotate_browser *browser, 287aca7a94dSNamhyung Kim struct rb_node *nd) 288aca7a94dSNamhyung Kim { 28995aa89d9SArnaldo Carvalho de Melo struct annotation *notes = browser__annotation(&browser->b); 2904850c92eSArnaldo Carvalho de Melo struct annotation_line * pos = rb_entry(nd, struct annotation_line, rb_node); 2914850c92eSArnaldo Carvalho de Melo u32 idx = pos->idx; 292aca7a94dSNamhyung Kim 29316932d77SArnaldo Carvalho de Melo if (notes->options->hide_src_code) 2944850c92eSArnaldo Carvalho de Melo idx = pos->idx_asm; 295a44b45f2SArnaldo Carvalho de Melo annotate_browser__set_top(browser, pos, idx); 296aca7a94dSNamhyung Kim browser->curr_hot = nd; 297aca7a94dSNamhyung Kim } 298aca7a94dSNamhyung Kim 299aca7a94dSNamhyung Kim static void annotate_browser__calc_percent(struct annotate_browser *browser, 300db8fd07aSNamhyung Kim struct perf_evsel *evsel) 301aca7a94dSNamhyung Kim { 302aca7a94dSNamhyung Kim struct map_symbol *ms = browser->b.priv; 303aca7a94dSNamhyung Kim struct symbol *sym = ms->sym; 304aca7a94dSNamhyung Kim struct annotation *notes = symbol__annotation(sym); 305c4c72436SJiri Olsa struct disasm_line *pos; 306aca7a94dSNamhyung Kim 307aca7a94dSNamhyung Kim browser->entries = RB_ROOT; 308aca7a94dSNamhyung Kim 309aca7a94dSNamhyung Kim pthread_mutex_lock(¬es->lock); 310aca7a94dSNamhyung Kim 311e425da6cSJiri Olsa symbol__calc_percent(sym, evsel); 312e425da6cSJiri Olsa 313a17c4ca0SJiri Olsa list_for_each_entry(pos, ¬es->src->source, al.node) { 314c7e7b610SNamhyung Kim double max_percent = 0.0; 315c7e7b610SNamhyung Kim int i; 316e64aa75bSNamhyung Kim 317d5490b96SJiri Olsa if (pos->al.offset == -1) { 3185b12adc8SJiri Olsa RB_CLEAR_NODE(&pos->al.rb_node); 319e64aa75bSNamhyung Kim continue; 320e64aa75bSNamhyung Kim } 321e64aa75bSNamhyung Kim 322b15636c6SJiri Olsa for (i = 0; i < pos->al.samples_nr; i++) { 323e425da6cSJiri Olsa struct annotation_data *sample = &pos->al.samples[i]; 3240c4a5bceSMartin Liška 3253ab6db8dSJiri Olsa if (max_percent < sample->percent) 3263ab6db8dSJiri Olsa max_percent = sample->percent; 327c7e7b610SNamhyung Kim } 328c7e7b610SNamhyung Kim 32937236d5eSJiri Olsa if (max_percent < 0.01 && pos->al.ipc == 0) { 3305b12adc8SJiri Olsa RB_CLEAR_NODE(&pos->al.rb_node); 331aca7a94dSNamhyung Kim continue; 332aca7a94dSNamhyung Kim } 333b15636c6SJiri Olsa disasm_rb_tree__insert(&browser->entries, &pos->al); 334aca7a94dSNamhyung Kim } 335aca7a94dSNamhyung Kim pthread_mutex_unlock(¬es->lock); 336aca7a94dSNamhyung Kim 337aca7a94dSNamhyung Kim browser->curr_hot = rb_last(&browser->entries); 338aca7a94dSNamhyung Kim } 339aca7a94dSNamhyung Kim 340aca7a94dSNamhyung Kim static bool annotate_browser__toggle_source(struct annotate_browser *browser) 341aca7a94dSNamhyung Kim { 34295aa89d9SArnaldo Carvalho de Melo struct annotation *notes = browser__annotation(&browser->b); 343ec03a77dSJiri Olsa struct annotation_line *al; 344aca7a94dSNamhyung Kim off_t offset = browser->b.index - browser->b.top_idx; 345aca7a94dSNamhyung Kim 346aca7a94dSNamhyung Kim browser->b.seek(&browser->b, offset, SEEK_CUR); 347ec03a77dSJiri Olsa al = list_entry(browser->b.top, struct annotation_line, node); 348aca7a94dSNamhyung Kim 34916932d77SArnaldo Carvalho de Melo if (notes->options->hide_src_code) { 3504850c92eSArnaldo Carvalho de Melo if (al->idx_asm < offset) 3514850c92eSArnaldo Carvalho de Melo offset = al->idx; 352aca7a94dSNamhyung Kim 3531cf5f98aSArnaldo Carvalho de Melo browser->b.nr_entries = notes->nr_entries; 35416932d77SArnaldo Carvalho de Melo notes->options->hide_src_code = false; 355aca7a94dSNamhyung Kim browser->b.seek(&browser->b, -offset, SEEK_CUR); 3564850c92eSArnaldo Carvalho de Melo browser->b.top_idx = al->idx - offset; 3574850c92eSArnaldo Carvalho de Melo browser->b.index = al->idx; 358aca7a94dSNamhyung Kim } else { 3594850c92eSArnaldo Carvalho de Melo if (al->idx_asm < 0) { 360aca7a94dSNamhyung Kim ui_helpline__puts("Only available for assembly lines."); 361aca7a94dSNamhyung Kim browser->b.seek(&browser->b, -offset, SEEK_CUR); 362aca7a94dSNamhyung Kim return false; 363aca7a94dSNamhyung Kim } 364aca7a94dSNamhyung Kim 3654850c92eSArnaldo Carvalho de Melo if (al->idx_asm < offset) 3664850c92eSArnaldo Carvalho de Melo offset = al->idx_asm; 367aca7a94dSNamhyung Kim 3681cf5f98aSArnaldo Carvalho de Melo browser->b.nr_entries = notes->nr_asm_entries; 36916932d77SArnaldo Carvalho de Melo notes->options->hide_src_code = true; 370aca7a94dSNamhyung Kim browser->b.seek(&browser->b, -offset, SEEK_CUR); 3714850c92eSArnaldo Carvalho de Melo browser->b.top_idx = al->idx_asm - offset; 3724850c92eSArnaldo Carvalho de Melo browser->b.index = al->idx_asm; 373aca7a94dSNamhyung Kim } 374aca7a94dSNamhyung Kim 375aca7a94dSNamhyung Kim return true; 376aca7a94dSNamhyung Kim } 377aca7a94dSNamhyung Kim 3781cf5f98aSArnaldo Carvalho de Melo static void ui_browser__init_asm_mode(struct ui_browser *browser) 379e9823b21SArnaldo Carvalho de Melo { 3801cf5f98aSArnaldo Carvalho de Melo struct annotation *notes = browser__annotation(browser); 3811cf5f98aSArnaldo Carvalho de Melo ui_browser__reset_index(browser); 3821cf5f98aSArnaldo Carvalho de Melo browser->nr_entries = notes->nr_asm_entries; 383e9823b21SArnaldo Carvalho de Melo } 384e9823b21SArnaldo Carvalho de Melo 38534f77abcSAdrian Hunter #define SYM_TITLE_MAX_SIZE (PATH_MAX + 64) 38634f77abcSAdrian Hunter 38734f77abcSAdrian Hunter static int sym_title(struct symbol *sym, struct map *map, char *title, 38834f77abcSAdrian Hunter size_t sz) 38934f77abcSAdrian Hunter { 39034f77abcSAdrian Hunter return snprintf(title, sz, "%s %s", sym->name, map->dso->long_name); 39134f77abcSAdrian Hunter } 39234f77abcSAdrian Hunter 393db8fd07aSNamhyung Kim static bool annotate_browser__callq(struct annotate_browser *browser, 394db8fd07aSNamhyung Kim struct perf_evsel *evsel, 3959783adf7SNamhyung Kim struct hist_browser_timer *hbt) 396aca7a94dSNamhyung Kim { 397aca7a94dSNamhyung Kim struct map_symbol *ms = browser->b.priv; 3987bcbcd58SJiri Olsa struct disasm_line *dl = disasm_line(browser->selection); 399aca7a94dSNamhyung Kim struct annotation *notes; 40034f77abcSAdrian Hunter char title[SYM_TITLE_MAX_SIZE]; 401aca7a94dSNamhyung Kim 40275b49202SArnaldo Carvalho de Melo if (!ins__is_call(&dl->ins)) 403aca7a94dSNamhyung Kim return false; 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; 438*9b80d1f9SArnaldo 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 445aca7a94dSNamhyung Kim static bool annotate_browser__jump(struct annotate_browser *browser) 446aca7a94dSNamhyung Kim { 4477bcbcd58SJiri Olsa struct disasm_line *dl = disasm_line(browser->selection); 4485252b1aeSArnaldo Carvalho de Melo u64 offset; 4494f9d0325SArnaldo Carvalho de Melo s64 idx; 450aca7a94dSNamhyung Kim 45175b49202SArnaldo Carvalho de Melo if (!ins__is_jump(&dl->ins)) 452aca7a94dSNamhyung Kim return false; 453aca7a94dSNamhyung Kim 4545252b1aeSArnaldo Carvalho de Melo offset = dl->ops.target.offset; 4555252b1aeSArnaldo Carvalho de Melo dl = annotate_browser__find_offset(browser, offset, &idx); 45629ed6e76SArnaldo Carvalho de Melo if (dl == NULL) { 4575252b1aeSArnaldo Carvalho de Melo ui_helpline__printf("Invalid jump offset: %" PRIx64, offset); 458aca7a94dSNamhyung Kim return true; 459aca7a94dSNamhyung Kim } 460aca7a94dSNamhyung Kim 461ec03a77dSJiri Olsa annotate_browser__set_top(browser, &dl->al, idx); 462aca7a94dSNamhyung Kim 463aca7a94dSNamhyung Kim return true; 464aca7a94dSNamhyung Kim } 465aca7a94dSNamhyung Kim 46629ed6e76SArnaldo Carvalho de Melo static 4679213afbdSJiri Olsa struct annotation_line *annotate_browser__find_string(struct annotate_browser *browser, 468aca7a94dSNamhyung Kim char *s, s64 *idx) 469aca7a94dSNamhyung Kim { 47095aa89d9SArnaldo Carvalho de Melo struct annotation *notes = browser__annotation(&browser->b); 4719213afbdSJiri Olsa struct annotation_line *al = browser->selection; 472aca7a94dSNamhyung Kim 473aca7a94dSNamhyung Kim *idx = browser->b.index; 4749213afbdSJiri Olsa list_for_each_entry_continue(al, ¬es->src->source, node) { 475*9b80d1f9SArnaldo Carvalho de Melo if (annotation_line__filter(al, notes)) 476aca7a94dSNamhyung Kim continue; 477aca7a94dSNamhyung Kim 478aca7a94dSNamhyung Kim ++*idx; 479aca7a94dSNamhyung Kim 4809213afbdSJiri Olsa if (al->line && strstr(al->line, s) != NULL) 4819213afbdSJiri Olsa return al; 482aca7a94dSNamhyung Kim } 483aca7a94dSNamhyung Kim 484aca7a94dSNamhyung Kim return NULL; 485aca7a94dSNamhyung Kim } 486aca7a94dSNamhyung Kim 487aca7a94dSNamhyung Kim static bool __annotate_browser__search(struct annotate_browser *browser) 488aca7a94dSNamhyung Kim { 4899213afbdSJiri Olsa struct annotation_line *al; 490aca7a94dSNamhyung Kim s64 idx; 491aca7a94dSNamhyung Kim 4929213afbdSJiri Olsa al = annotate_browser__find_string(browser, browser->search_bf, &idx); 4939213afbdSJiri Olsa if (al == NULL) { 494aca7a94dSNamhyung Kim ui_helpline__puts("String not found!"); 495aca7a94dSNamhyung Kim return false; 496aca7a94dSNamhyung Kim } 497aca7a94dSNamhyung Kim 498ec03a77dSJiri Olsa annotate_browser__set_top(browser, al, idx); 499aca7a94dSNamhyung Kim browser->searching_backwards = false; 500aca7a94dSNamhyung Kim return true; 501aca7a94dSNamhyung Kim } 502aca7a94dSNamhyung Kim 50329ed6e76SArnaldo Carvalho de Melo static 5049213afbdSJiri Olsa struct annotation_line *annotate_browser__find_string_reverse(struct annotate_browser *browser, 505aca7a94dSNamhyung Kim char *s, s64 *idx) 506aca7a94dSNamhyung Kim { 50795aa89d9SArnaldo Carvalho de Melo struct annotation *notes = browser__annotation(&browser->b); 5089213afbdSJiri Olsa struct annotation_line *al = browser->selection; 509aca7a94dSNamhyung Kim 510aca7a94dSNamhyung Kim *idx = browser->b.index; 5119213afbdSJiri Olsa list_for_each_entry_continue_reverse(al, ¬es->src->source, node) { 512*9b80d1f9SArnaldo Carvalho de Melo if (annotation_line__filter(al, notes)) 513aca7a94dSNamhyung Kim continue; 514aca7a94dSNamhyung Kim 515aca7a94dSNamhyung Kim --*idx; 516aca7a94dSNamhyung Kim 5179213afbdSJiri Olsa if (al->line && strstr(al->line, s) != NULL) 5189213afbdSJiri Olsa return al; 519aca7a94dSNamhyung Kim } 520aca7a94dSNamhyung Kim 521aca7a94dSNamhyung Kim return NULL; 522aca7a94dSNamhyung Kim } 523aca7a94dSNamhyung Kim 524aca7a94dSNamhyung Kim static bool __annotate_browser__search_reverse(struct annotate_browser *browser) 525aca7a94dSNamhyung Kim { 5269213afbdSJiri Olsa struct annotation_line *al; 527aca7a94dSNamhyung Kim s64 idx; 528aca7a94dSNamhyung Kim 5299213afbdSJiri Olsa al = annotate_browser__find_string_reverse(browser, browser->search_bf, &idx); 5309213afbdSJiri Olsa if (al == NULL) { 531aca7a94dSNamhyung Kim ui_helpline__puts("String not found!"); 532aca7a94dSNamhyung Kim return false; 533aca7a94dSNamhyung Kim } 534aca7a94dSNamhyung Kim 535ec03a77dSJiri Olsa annotate_browser__set_top(browser, al, idx); 536aca7a94dSNamhyung Kim browser->searching_backwards = true; 537aca7a94dSNamhyung Kim return true; 538aca7a94dSNamhyung Kim } 539aca7a94dSNamhyung Kim 540aca7a94dSNamhyung Kim static bool annotate_browser__search_window(struct annotate_browser *browser, 541aca7a94dSNamhyung Kim int delay_secs) 542aca7a94dSNamhyung Kim { 543aca7a94dSNamhyung Kim if (ui_browser__input_window("Search", "String: ", browser->search_bf, 544aca7a94dSNamhyung Kim "ENTER: OK, ESC: Cancel", 545aca7a94dSNamhyung Kim delay_secs * 2) != K_ENTER || 546aca7a94dSNamhyung Kim !*browser->search_bf) 547aca7a94dSNamhyung Kim return false; 548aca7a94dSNamhyung Kim 549aca7a94dSNamhyung Kim return true; 550aca7a94dSNamhyung Kim } 551aca7a94dSNamhyung Kim 552aca7a94dSNamhyung Kim static bool annotate_browser__search(struct annotate_browser *browser, int delay_secs) 553aca7a94dSNamhyung Kim { 554aca7a94dSNamhyung Kim if (annotate_browser__search_window(browser, delay_secs)) 555aca7a94dSNamhyung Kim return __annotate_browser__search(browser); 556aca7a94dSNamhyung Kim 557aca7a94dSNamhyung Kim return false; 558aca7a94dSNamhyung Kim } 559aca7a94dSNamhyung Kim 560aca7a94dSNamhyung Kim static bool annotate_browser__continue_search(struct annotate_browser *browser, 561aca7a94dSNamhyung Kim int delay_secs) 562aca7a94dSNamhyung Kim { 563aca7a94dSNamhyung Kim if (!*browser->search_bf) 564aca7a94dSNamhyung Kim return annotate_browser__search(browser, delay_secs); 565aca7a94dSNamhyung Kim 566aca7a94dSNamhyung Kim return __annotate_browser__search(browser); 567aca7a94dSNamhyung Kim } 568aca7a94dSNamhyung Kim 569aca7a94dSNamhyung Kim static bool annotate_browser__search_reverse(struct annotate_browser *browser, 570aca7a94dSNamhyung Kim int delay_secs) 571aca7a94dSNamhyung Kim { 572aca7a94dSNamhyung Kim if (annotate_browser__search_window(browser, delay_secs)) 573aca7a94dSNamhyung Kim return __annotate_browser__search_reverse(browser); 574aca7a94dSNamhyung Kim 575aca7a94dSNamhyung Kim return false; 576aca7a94dSNamhyung Kim } 577aca7a94dSNamhyung Kim 578aca7a94dSNamhyung Kim static 579aca7a94dSNamhyung Kim bool annotate_browser__continue_search_reverse(struct annotate_browser *browser, 580aca7a94dSNamhyung Kim int delay_secs) 581aca7a94dSNamhyung Kim { 582aca7a94dSNamhyung Kim if (!*browser->search_bf) 583aca7a94dSNamhyung Kim return annotate_browser__search_reverse(browser, delay_secs); 584aca7a94dSNamhyung Kim 585aca7a94dSNamhyung Kim return __annotate_browser__search_reverse(browser); 586aca7a94dSNamhyung Kim } 587aca7a94dSNamhyung Kim 588db8fd07aSNamhyung Kim static int annotate_browser__run(struct annotate_browser *browser, 589db8fd07aSNamhyung Kim struct perf_evsel *evsel, 5909783adf7SNamhyung Kim struct hist_browser_timer *hbt) 591aca7a94dSNamhyung Kim { 592aca7a94dSNamhyung Kim struct rb_node *nd = NULL; 59305e8b080SArnaldo Carvalho de Melo struct map_symbol *ms = browser->b.priv; 594aca7a94dSNamhyung Kim struct symbol *sym = ms->sym; 59516932d77SArnaldo Carvalho de Melo struct annotation *notes = symbol__annotation(ms->sym); 59654e7a4e8SArnaldo Carvalho de Melo const char *help = "Press 'h' for help on key bindings"; 5979783adf7SNamhyung Kim int delay_secs = hbt ? hbt->refresh : 0; 598aca7a94dSNamhyung Kim int key; 59934f77abcSAdrian Hunter char title[SYM_TITLE_MAX_SIZE]; 600aca7a94dSNamhyung Kim 60134f77abcSAdrian Hunter sym_title(sym, ms->map, title, sizeof(title)); 60234f77abcSAdrian Hunter if (ui_browser__show(&browser->b, title, help) < 0) 603aca7a94dSNamhyung Kim return -1; 604aca7a94dSNamhyung Kim 605db8fd07aSNamhyung Kim annotate_browser__calc_percent(browser, evsel); 606aca7a94dSNamhyung Kim 60705e8b080SArnaldo Carvalho de Melo if (browser->curr_hot) { 60805e8b080SArnaldo Carvalho de Melo annotate_browser__set_rb_top(browser, browser->curr_hot); 60905e8b080SArnaldo Carvalho de Melo browser->b.navkeypressed = false; 610aca7a94dSNamhyung Kim } 611aca7a94dSNamhyung Kim 61205e8b080SArnaldo Carvalho de Melo nd = browser->curr_hot; 613aca7a94dSNamhyung Kim 614aca7a94dSNamhyung Kim while (1) { 61505e8b080SArnaldo Carvalho de Melo key = ui_browser__run(&browser->b, delay_secs); 616aca7a94dSNamhyung Kim 617aca7a94dSNamhyung Kim if (delay_secs != 0) { 618db8fd07aSNamhyung Kim annotate_browser__calc_percent(browser, evsel); 619aca7a94dSNamhyung Kim /* 620aca7a94dSNamhyung Kim * Current line focus got out of the list of most active 621aca7a94dSNamhyung Kim * lines, NULL it so that if TAB|UNTAB is pressed, we 622aca7a94dSNamhyung Kim * move to curr_hot (current hottest line). 623aca7a94dSNamhyung Kim */ 624aca7a94dSNamhyung Kim if (nd != NULL && RB_EMPTY_NODE(nd)) 625aca7a94dSNamhyung Kim nd = NULL; 626aca7a94dSNamhyung Kim } 627aca7a94dSNamhyung Kim 628aca7a94dSNamhyung Kim switch (key) { 629aca7a94dSNamhyung Kim case K_TIMER: 6309783adf7SNamhyung Kim if (hbt) 6319783adf7SNamhyung Kim hbt->timer(hbt->arg); 632aca7a94dSNamhyung Kim 633aca7a94dSNamhyung Kim if (delay_secs != 0) 634db8fd07aSNamhyung Kim symbol__annotate_decay_histogram(sym, evsel->idx); 635aca7a94dSNamhyung Kim continue; 636aca7a94dSNamhyung Kim case K_TAB: 637aca7a94dSNamhyung Kim if (nd != NULL) { 638aca7a94dSNamhyung Kim nd = rb_prev(nd); 639aca7a94dSNamhyung Kim if (nd == NULL) 64005e8b080SArnaldo Carvalho de Melo nd = rb_last(&browser->entries); 641aca7a94dSNamhyung Kim } else 64205e8b080SArnaldo Carvalho de Melo nd = browser->curr_hot; 643aca7a94dSNamhyung Kim break; 644aca7a94dSNamhyung Kim case K_UNTAB: 645d4913cbdSMarkus Trippelsdorf if (nd != NULL) { 646aca7a94dSNamhyung Kim nd = rb_next(nd); 647aca7a94dSNamhyung Kim if (nd == NULL) 64805e8b080SArnaldo Carvalho de Melo nd = rb_first(&browser->entries); 649d4913cbdSMarkus Trippelsdorf } else 65005e8b080SArnaldo Carvalho de Melo nd = browser->curr_hot; 651aca7a94dSNamhyung Kim break; 65254e7a4e8SArnaldo Carvalho de Melo case K_F1: 653aca7a94dSNamhyung Kim case 'h': 65405e8b080SArnaldo Carvalho de Melo ui_browser__help_window(&browser->b, 65554e7a4e8SArnaldo Carvalho de Melo "UP/DOWN/PGUP\n" 65654e7a4e8SArnaldo Carvalho de Melo "PGDN/SPACE Navigate\n" 65754e7a4e8SArnaldo Carvalho de Melo "q/ESC/CTRL+C Exit\n\n" 6587727a925SArnaldo Carvalho de Melo "ENTER Go to target\n" 6597727a925SArnaldo Carvalho de Melo "ESC Exit\n" 660eba9fac0SArnaldo Carvalho de Melo "H Go to hottest instruction\n" 661eba9fac0SArnaldo Carvalho de Melo "TAB/shift+TAB Cycle thru hottest instructions\n" 66254e7a4e8SArnaldo Carvalho de Melo "j Toggle showing jump to target arrows\n" 66354e7a4e8SArnaldo Carvalho de Melo "J Toggle showing number of jump sources on targets\n" 66454e7a4e8SArnaldo Carvalho de Melo "n Search next string\n" 66554e7a4e8SArnaldo Carvalho de Melo "o Toggle disassembler output/simplified view\n" 66654e7a4e8SArnaldo Carvalho de Melo "s Toggle source code view\n" 6673a555c77STaeung Song "t Circulate percent, total period, samples view\n" 66854e7a4e8SArnaldo Carvalho de Melo "/ Search string\n" 669e592488cSAndi Kleen "k Toggle line numbers\n" 67079ee47faSFeng Tang "r Run available scripts\n" 671fcd9fef9SArnaldo Carvalho de Melo "? Search string backwards\n"); 67254e7a4e8SArnaldo Carvalho de Melo continue; 67379ee47faSFeng Tang case 'r': 67479ee47faSFeng Tang { 67579ee47faSFeng Tang script_browse(NULL); 67679ee47faSFeng Tang continue; 67779ee47faSFeng Tang } 678e592488cSAndi Kleen case 'k': 67916932d77SArnaldo Carvalho de Melo notes->options->show_linenr = !notes->options->show_linenr; 680e592488cSAndi Kleen break; 68154e7a4e8SArnaldo Carvalho de Melo case 'H': 68205e8b080SArnaldo Carvalho de Melo nd = browser->curr_hot; 683aca7a94dSNamhyung Kim break; 684aca7a94dSNamhyung Kim case 's': 68505e8b080SArnaldo Carvalho de Melo if (annotate_browser__toggle_source(browser)) 686aca7a94dSNamhyung Kim ui_helpline__puts(help); 687aca7a94dSNamhyung Kim continue; 688aca7a94dSNamhyung Kim case 'o': 68916932d77SArnaldo Carvalho de Melo notes->options->use_offset = !notes->options->use_offset; 6909761e86eSArnaldo Carvalho de Melo annotation__update_column_widths(notes); 691aca7a94dSNamhyung Kim continue; 6929d1ef56dSArnaldo Carvalho de Melo case 'j': 69316932d77SArnaldo Carvalho de Melo notes->options->jump_arrows = !notes->options->jump_arrows; 6949d1ef56dSArnaldo Carvalho de Melo continue; 6952402e4a9SArnaldo Carvalho de Melo case 'J': 69616932d77SArnaldo Carvalho de Melo notes->options->show_nr_jumps = !notes->options->show_nr_jumps; 6979761e86eSArnaldo Carvalho de Melo annotation__update_column_widths(notes); 698e9823b21SArnaldo Carvalho de Melo continue; 699aca7a94dSNamhyung Kim case '/': 70005e8b080SArnaldo Carvalho de Melo if (annotate_browser__search(browser, delay_secs)) { 701aca7a94dSNamhyung Kim show_help: 702aca7a94dSNamhyung Kim ui_helpline__puts(help); 703aca7a94dSNamhyung Kim } 704aca7a94dSNamhyung Kim continue; 705aca7a94dSNamhyung Kim case 'n': 70605e8b080SArnaldo Carvalho de Melo if (browser->searching_backwards ? 70705e8b080SArnaldo Carvalho de Melo annotate_browser__continue_search_reverse(browser, delay_secs) : 70805e8b080SArnaldo Carvalho de Melo annotate_browser__continue_search(browser, delay_secs)) 709aca7a94dSNamhyung Kim goto show_help; 710aca7a94dSNamhyung Kim continue; 711aca7a94dSNamhyung Kim case '?': 71205e8b080SArnaldo Carvalho de Melo if (annotate_browser__search_reverse(browser, delay_secs)) 713aca7a94dSNamhyung Kim goto show_help; 714aca7a94dSNamhyung Kim continue; 715e9823b21SArnaldo Carvalho de Melo case 'D': { 716e9823b21SArnaldo Carvalho de Melo static int seq; 717e9823b21SArnaldo Carvalho de Melo ui_helpline__pop(); 718e9823b21SArnaldo Carvalho de Melo ui_helpline__fpush("%d: nr_ent=%d, height=%d, idx=%d, top_idx=%d, nr_asm_entries=%d", 71905e8b080SArnaldo Carvalho de Melo seq++, browser->b.nr_entries, 72005e8b080SArnaldo Carvalho de Melo browser->b.height, 72105e8b080SArnaldo Carvalho de Melo browser->b.index, 72205e8b080SArnaldo Carvalho de Melo browser->b.top_idx, 7231cf5f98aSArnaldo Carvalho de Melo notes->nr_asm_entries); 724e9823b21SArnaldo Carvalho de Melo } 725e9823b21SArnaldo Carvalho de Melo continue; 726aca7a94dSNamhyung Kim case K_ENTER: 727aca7a94dSNamhyung Kim case K_RIGHT: 7287bcbcd58SJiri Olsa { 7297bcbcd58SJiri Olsa struct disasm_line *dl = disasm_line(browser->selection); 7307bcbcd58SJiri Olsa 73105e8b080SArnaldo Carvalho de Melo if (browser->selection == NULL) 732aca7a94dSNamhyung Kim ui_helpline__puts("Huh? No selection. Report to linux-kernel@vger.kernel.org"); 7337bcbcd58SJiri Olsa else if (browser->selection->offset == -1) 734aca7a94dSNamhyung Kim ui_helpline__puts("Actions are only available for assembly lines."); 7357bcbcd58SJiri Olsa else if (!dl->ins.ops) 736c4cceae3SArnaldo Carvalho de Melo goto show_sup_ins; 7377bcbcd58SJiri Olsa else if (ins__is_ret(&dl->ins)) 738c4cceae3SArnaldo Carvalho de Melo goto out; 7396ef94929SNaveen N. Rao else if (!(annotate_browser__jump(browser) || 740db8fd07aSNamhyung Kim annotate_browser__callq(browser, evsel, hbt))) { 741c4cceae3SArnaldo Carvalho de Melo show_sup_ins: 7426ef94929SNaveen N. Rao ui_helpline__puts("Actions are only available for function call/return & jump/branch instructions."); 743c4cceae3SArnaldo Carvalho de Melo } 744aca7a94dSNamhyung Kim continue; 7457bcbcd58SJiri Olsa } 7460c4a5bceSMartin Liška case 't': 74716932d77SArnaldo Carvalho de Melo if (notes->options->show_total_period) { 74816932d77SArnaldo Carvalho de Melo notes->options->show_total_period = false; 74916932d77SArnaldo Carvalho de Melo notes->options->show_nr_samples = true; 75016932d77SArnaldo Carvalho de Melo } else if (notes->options->show_nr_samples) 75116932d77SArnaldo Carvalho de Melo notes->options->show_nr_samples = false; 7523a555c77STaeung Song else 75316932d77SArnaldo Carvalho de Melo notes->options->show_total_period = true; 7549761e86eSArnaldo Carvalho de Melo annotation__update_column_widths(notes); 7550c4a5bceSMartin Liška continue; 756aca7a94dSNamhyung Kim case K_LEFT: 757aca7a94dSNamhyung Kim case K_ESC: 758aca7a94dSNamhyung Kim case 'q': 759aca7a94dSNamhyung Kim case CTRL('c'): 760aca7a94dSNamhyung Kim goto out; 761aca7a94dSNamhyung Kim default: 762aca7a94dSNamhyung Kim continue; 763aca7a94dSNamhyung Kim } 764aca7a94dSNamhyung Kim 765aca7a94dSNamhyung Kim if (nd != NULL) 76605e8b080SArnaldo Carvalho de Melo annotate_browser__set_rb_top(browser, nd); 767aca7a94dSNamhyung Kim } 768aca7a94dSNamhyung Kim out: 76905e8b080SArnaldo Carvalho de Melo ui_browser__hide(&browser->b); 770aca7a94dSNamhyung Kim return key; 771aca7a94dSNamhyung Kim } 772aca7a94dSNamhyung Kim 773d5dbc518SArnaldo Carvalho de Melo int map_symbol__tui_annotate(struct map_symbol *ms, struct perf_evsel *evsel, 774d5dbc518SArnaldo Carvalho de Melo struct hist_browser_timer *hbt) 775d5dbc518SArnaldo Carvalho de Melo { 7769cef4b0bSTaeung Song /* Set default value for show_total_period and show_nr_samples */ 7770c4a5bceSMartin Liška annotate_browser__opts.show_total_period = 7780c4a5bceSMartin Liška symbol_conf.show_total_period; 7799cef4b0bSTaeung Song annotate_browser__opts.show_nr_samples = 7809cef4b0bSTaeung Song symbol_conf.show_nr_samples; 7810c4a5bceSMartin Liška 782d5dbc518SArnaldo Carvalho de Melo return symbol__tui_annotate(ms->sym, ms->map, evsel, hbt); 783d5dbc518SArnaldo Carvalho de Melo } 784d5dbc518SArnaldo Carvalho de Melo 785db8fd07aSNamhyung Kim int hist_entry__tui_annotate(struct hist_entry *he, struct perf_evsel *evsel, 7869783adf7SNamhyung Kim struct hist_browser_timer *hbt) 787aca7a94dSNamhyung Kim { 788ed426915SNamhyung Kim /* reset abort key so that it can get Ctrl-C as a key */ 789ed426915SNamhyung Kim SLang_reset_tty(); 790ed426915SNamhyung Kim SLang_init_tty(0, 0, 0); 791ed426915SNamhyung Kim 792d5dbc518SArnaldo Carvalho de Melo return map_symbol__tui_annotate(&he->ms, evsel, hbt); 793aca7a94dSNamhyung Kim } 794aca7a94dSNamhyung Kim 795db8fd07aSNamhyung Kim int symbol__tui_annotate(struct symbol *sym, struct map *map, 796db8fd07aSNamhyung Kim struct perf_evsel *evsel, 7979783adf7SNamhyung Kim struct hist_browser_timer *hbt) 798aca7a94dSNamhyung Kim { 7999d6bb41dSArnaldo Carvalho de Melo struct annotation *notes = symbol__annotation(sym); 800aca7a94dSNamhyung Kim struct map_symbol ms = { 801aca7a94dSNamhyung Kim .map = map, 802aca7a94dSNamhyung Kim .sym = sym, 803aca7a94dSNamhyung Kim }; 804aca7a94dSNamhyung Kim struct annotate_browser browser = { 805aca7a94dSNamhyung Kim .b = { 806a3f895beSArnaldo Carvalho de Melo .refresh = annotate_browser__refresh, 807aca7a94dSNamhyung Kim .seek = ui_browser__list_head_seek, 808aca7a94dSNamhyung Kim .write = annotate_browser__write, 80929ed6e76SArnaldo Carvalho de Melo .filter = disasm_line__filter, 810aca7a94dSNamhyung Kim .priv = &ms, 811aca7a94dSNamhyung Kim .use_navkeypressed = true, 812aca7a94dSNamhyung Kim }, 813aca7a94dSNamhyung Kim }; 814ee51d851SArnaldo Carvalho de Melo int ret = -1, err; 815aca7a94dSNamhyung Kim 816aca7a94dSNamhyung Kim if (sym == NULL) 817aca7a94dSNamhyung Kim return -1; 818aca7a94dSNamhyung Kim 819aca7a94dSNamhyung Kim if (map->dso->annotate_warned) 820aca7a94dSNamhyung Kim return -1; 821aca7a94dSNamhyung Kim 822ecda45bdSArnaldo Carvalho de Melo err = symbol__annotate2(sym, map, evsel, &annotate_browser__opts, &browser.arch); 823ee51d851SArnaldo Carvalho de Melo if (err) { 824ee51d851SArnaldo Carvalho de Melo char msg[BUFSIZ]; 825ee51d851SArnaldo Carvalho de Melo symbol__strerror_disassemble(sym, map, err, msg, sizeof(msg)); 826ee51d851SArnaldo Carvalho de Melo ui__error("Couldn't annotate %s:\n%s", sym->name, msg); 827b793a401SArnaldo Carvalho de Melo goto out_free_offsets; 828aca7a94dSNamhyung Kim } 829aca7a94dSNamhyung Kim 8307727a925SArnaldo Carvalho de Melo ui_helpline__push("Press ESC to exit"); 831aca7a94dSNamhyung Kim 8325bc49f61SArnaldo Carvalho de Melo browser.b.width = notes->max_line_len; 8331cf5f98aSArnaldo Carvalho de Melo browser.b.nr_entries = notes->nr_entries; 834aca7a94dSNamhyung Kim browser.b.entries = ¬es->src->source, 835aca7a94dSNamhyung Kim browser.b.width += 18; /* Percentage */ 836e9823b21SArnaldo Carvalho de Melo 83716932d77SArnaldo Carvalho de Melo if (notes->options->hide_src_code) 8381cf5f98aSArnaldo Carvalho de Melo ui_browser__init_asm_mode(&browser.b); 839e9823b21SArnaldo Carvalho de Melo 840db8fd07aSNamhyung Kim ret = annotate_browser__run(&browser, evsel, hbt); 841f8eb37bdSJiri Olsa 842f8eb37bdSJiri Olsa annotated_source__purge(notes->src); 843b793a401SArnaldo Carvalho de Melo 844b793a401SArnaldo Carvalho de Melo out_free_offsets: 8459d6bb41dSArnaldo Carvalho de Melo zfree(¬es->offsets); 846aca7a94dSNamhyung Kim return ret; 847aca7a94dSNamhyung Kim } 848c323cf04SArnaldo Carvalho de Melo 849c323cf04SArnaldo Carvalho de Melo #define ANNOTATE_CFG(n) \ 850c323cf04SArnaldo Carvalho de Melo { .name = #n, .value = &annotate_browser__opts.n, } 851c323cf04SArnaldo Carvalho de Melo 852c323cf04SArnaldo Carvalho de Melo /* 853c323cf04SArnaldo Carvalho de Melo * Keep the entries sorted, they are bsearch'ed 854c323cf04SArnaldo Carvalho de Melo */ 8557c3102b8SArnaldo Carvalho de Melo static struct annotate_config { 856c323cf04SArnaldo Carvalho de Melo const char *name; 857c323cf04SArnaldo Carvalho de Melo bool *value; 858c323cf04SArnaldo Carvalho de Melo } annotate__configs[] = { 859c323cf04SArnaldo Carvalho de Melo ANNOTATE_CFG(hide_src_code), 860c323cf04SArnaldo Carvalho de Melo ANNOTATE_CFG(jump_arrows), 861e592488cSAndi Kleen ANNOTATE_CFG(show_linenr), 862c323cf04SArnaldo Carvalho de Melo ANNOTATE_CFG(show_nr_jumps), 8639cef4b0bSTaeung Song ANNOTATE_CFG(show_nr_samples), 8640c4a5bceSMartin Liška ANNOTATE_CFG(show_total_period), 86539ff7cdbSNamhyung Kim ANNOTATE_CFG(use_offset), 866c323cf04SArnaldo Carvalho de Melo }; 867c323cf04SArnaldo Carvalho de Melo 868c323cf04SArnaldo Carvalho de Melo #undef ANNOTATE_CFG 869c323cf04SArnaldo Carvalho de Melo 870c323cf04SArnaldo Carvalho de Melo static int annotate_config__cmp(const void *name, const void *cfgp) 871c323cf04SArnaldo Carvalho de Melo { 8727c3102b8SArnaldo Carvalho de Melo const struct annotate_config *cfg = cfgp; 873c323cf04SArnaldo Carvalho de Melo 874c323cf04SArnaldo Carvalho de Melo return strcmp(name, cfg->name); 875c323cf04SArnaldo Carvalho de Melo } 876c323cf04SArnaldo Carvalho de Melo 8771d037ca1SIrina Tirdea static int annotate__config(const char *var, const char *value, 8781d037ca1SIrina Tirdea void *data __maybe_unused) 879c323cf04SArnaldo Carvalho de Melo { 8807c3102b8SArnaldo Carvalho de Melo struct annotate_config *cfg; 881c323cf04SArnaldo Carvalho de Melo const char *name; 882c323cf04SArnaldo Carvalho de Melo 8838e99b6d4SArnaldo Carvalho de Melo if (!strstarts(var, "annotate.")) 884c323cf04SArnaldo Carvalho de Melo return 0; 885c323cf04SArnaldo Carvalho de Melo 886c323cf04SArnaldo Carvalho de Melo name = var + 9; 887c323cf04SArnaldo Carvalho de Melo cfg = bsearch(name, annotate__configs, ARRAY_SIZE(annotate__configs), 8887c3102b8SArnaldo Carvalho de Melo sizeof(struct annotate_config), annotate_config__cmp); 889c323cf04SArnaldo Carvalho de Melo 890c323cf04SArnaldo Carvalho de Melo if (cfg == NULL) 891f06cff7cSArnaldo Carvalho de Melo ui__warning("%s variable unknown, ignoring...", var); 892f06cff7cSArnaldo Carvalho de Melo else 893c323cf04SArnaldo Carvalho de Melo *cfg->value = perf_config_bool(name, value); 894c323cf04SArnaldo Carvalho de Melo return 0; 895c323cf04SArnaldo Carvalho de Melo } 896c323cf04SArnaldo Carvalho de Melo 897c323cf04SArnaldo Carvalho de Melo void annotate_browser__init(void) 898c323cf04SArnaldo Carvalho de Melo { 899c323cf04SArnaldo Carvalho de Melo perf_config(annotate__config, NULL); 900c323cf04SArnaldo Carvalho de Melo } 901