1e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng#include "../../util/util.h" 2e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng#include "../browser.h" 3e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng#include "../helpline.h" 4e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng#include "../libslang.h" 5e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng#include "../ui.h" 6e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng#include "../util.h" 7e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng#include "../../util/annotate.h" 8e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng#include "../../util/hist.h" 9e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng#include "../../util/sort.h" 10e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng#include "../../util/symbol.h" 11e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng#include "../../util/evsel.h" 12e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng#include <pthread.h> 13e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 14e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstruct browser_disasm_line { 15e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng struct rb_node rb_node; 16e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng u32 idx; 17e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng int idx_asm; 18e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng int jump_sources; 19e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng /* 20e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng * actual length of this array is saved on the nr_events field 21e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng * of the struct annotate_browser 22e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng */ 23e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng double percent[1]; 24e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng}; 25e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 26e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstatic struct annotate_browser_opt { 27e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng bool hide_src_code, 28e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng use_offset, 29e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng jump_arrows, 30e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng show_nr_jumps; 31e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng} annotate_browser__opts = { 32e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng .use_offset = true, 33e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng .jump_arrows = true, 34e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng}; 35e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 36e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstruct annotate_browser { 37e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng struct ui_browser b; 38e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng struct rb_root entries; 39e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng struct rb_node *curr_hot; 40e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng struct disasm_line *selection; 41e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng struct disasm_line **offsets; 42e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng int nr_events; 43e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng u64 start; 44e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng int nr_asm_entries; 45e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng int nr_entries; 46e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng int max_jump_sources; 47e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng int nr_jumps; 48e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng bool searching_backwards; 49e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng u8 addr_width; 50e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng u8 jumps_width; 51e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng u8 target_width; 52e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng u8 min_addr_width; 53e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng u8 max_addr_width; 54e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng char search_bf[128]; 55e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng}; 56e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 57e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstatic inline struct browser_disasm_line *disasm_line__browser(struct disasm_line *dl) 58e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{ 59e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return (struct browser_disasm_line *)(dl + 1); 60e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng} 61e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 62e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstatic bool disasm_line__filter(struct ui_browser *browser __maybe_unused, 63e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng void *entry) 64e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{ 65e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (annotate_browser__opts.hide_src_code) { 66e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng struct disasm_line *dl = list_entry(entry, struct disasm_line, node); 67e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return dl->offset == -1; 68e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng } 69e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 70e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return false; 71e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng} 72e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 73e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstatic int annotate_browser__jumps_percent_color(struct annotate_browser *browser, 74e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng int nr, bool current) 75e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{ 76e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (current && (!browser->b.use_navkeypressed || browser->b.navkeypressed)) 77e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return HE_COLORSET_SELECTED; 78e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (nr == browser->max_jump_sources) 79e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return HE_COLORSET_TOP; 80e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (nr > 1) 81e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return HE_COLORSET_MEDIUM; 82e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return HE_COLORSET_NORMAL; 83e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng} 84e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 85e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstatic int annotate_browser__set_jumps_percent_color(struct annotate_browser *browser, 86e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng int nr, bool current) 87e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{ 88e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng int color = annotate_browser__jumps_percent_color(browser, nr, current); 89e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return ui_browser__set_color(&browser->b, color); 90e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng} 91e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 92e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstatic void annotate_browser__write(struct ui_browser *browser, void *entry, int row) 93e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{ 94e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng struct annotate_browser *ab = container_of(browser, struct annotate_browser, b); 95e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng struct disasm_line *dl = list_entry(entry, struct disasm_line, node); 96e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng struct browser_disasm_line *bdl = disasm_line__browser(dl); 97e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng bool current_entry = ui_browser__is_current_entry(browser, row); 98e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng bool change_color = (!annotate_browser__opts.hide_src_code && 99e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng (!current_entry || (browser->use_navkeypressed && 100e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng !browser->navkeypressed))); 101e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng int width = browser->width, printed; 102e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng int i, pcnt_width = 7 * ab->nr_events; 103e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng double percent_max = 0.0; 104e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng char bf[256]; 105e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 106e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng for (i = 0; i < ab->nr_events; i++) { 107e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (bdl->percent[i] > percent_max) 108e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng percent_max = bdl->percent[i]; 109e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng } 110e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 111e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (dl->offset != -1 && percent_max != 0.0) { 112e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng for (i = 0; i < ab->nr_events; i++) { 113e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng ui_browser__set_percent_color(browser, bdl->percent[i], 114e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng current_entry); 115e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng slsmg_printf("%6.2f ", bdl->percent[i]); 116e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng } 117e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng } else { 118e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng ui_browser__set_percent_color(browser, 0, current_entry); 119e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng slsmg_write_nstring(" ", pcnt_width); 120e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng } 121e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 122e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng SLsmg_write_char(' '); 123e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 124e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng /* The scroll bar isn't being used */ 125e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (!browser->navkeypressed) 126e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng width += 1; 127e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 128e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (!*dl->line) 129e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng slsmg_write_nstring(" ", width - pcnt_width); 130e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng else if (dl->offset == -1) { 131e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng printed = scnprintf(bf, sizeof(bf), "%*s ", 132e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng ab->addr_width, " "); 133e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng slsmg_write_nstring(bf, printed); 134e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng slsmg_write_nstring(dl->line, width - printed - pcnt_width + 1); 135e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng } else { 136e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng u64 addr = dl->offset; 137e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng int color = -1; 138e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 139e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (!annotate_browser__opts.use_offset) 140e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng addr += ab->start; 141e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 142e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (!annotate_browser__opts.use_offset) { 143e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng printed = scnprintf(bf, sizeof(bf), "%" PRIx64 ": ", addr); 144e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng } else { 145e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (bdl->jump_sources) { 146e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (annotate_browser__opts.show_nr_jumps) { 147e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng int prev; 148e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng printed = scnprintf(bf, sizeof(bf), "%*d ", 149e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng ab->jumps_width, 150e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng bdl->jump_sources); 151e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng prev = annotate_browser__set_jumps_percent_color(ab, bdl->jump_sources, 152e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng current_entry); 153e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng slsmg_write_nstring(bf, printed); 154e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng ui_browser__set_color(browser, prev); 155e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng } 156e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 157e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng printed = scnprintf(bf, sizeof(bf), "%*" PRIx64 ": ", 158e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng ab->target_width, addr); 159e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng } else { 160e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng printed = scnprintf(bf, sizeof(bf), "%*s ", 161e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng ab->addr_width, " "); 162e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng } 163e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng } 164e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 165e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (change_color) 166e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng color = ui_browser__set_color(browser, HE_COLORSET_ADDR); 167e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng slsmg_write_nstring(bf, printed); 168e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (change_color) 169e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng ui_browser__set_color(browser, color); 170e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (dl->ins && dl->ins->ops->scnprintf) { 171e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (ins__is_jump(dl->ins)) { 172e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng bool fwd = dl->ops.target.offset > (u64)dl->offset; 173e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 174e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng ui_browser__write_graph(browser, fwd ? SLSMG_DARROW_CHAR : 175e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng SLSMG_UARROW_CHAR); 176e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng SLsmg_write_char(' '); 177e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng } else if (ins__is_call(dl->ins)) { 178e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng ui_browser__write_graph(browser, SLSMG_RARROW_CHAR); 179e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng SLsmg_write_char(' '); 180e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng } else { 181e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng slsmg_write_nstring(" ", 2); 182e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng } 183e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng } else { 184e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (strcmp(dl->name, "retq")) { 185e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng slsmg_write_nstring(" ", 2); 186e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng } else { 187e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng ui_browser__write_graph(browser, SLSMG_LARROW_CHAR); 188e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng SLsmg_write_char(' '); 189e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng } 190e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng } 191e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 192e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng disasm_line__scnprintf(dl, bf, sizeof(bf), !annotate_browser__opts.use_offset); 193e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng slsmg_write_nstring(bf, width - pcnt_width - 3 - printed); 194e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng } 195e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 196e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (current_entry) 197e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng ab->selection = dl; 198e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng} 199e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 200e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstatic bool disasm_line__is_valid_jump(struct disasm_line *dl, struct symbol *sym) 201e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{ 202e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (!dl || !dl->ins || !ins__is_jump(dl->ins) 203e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng || !disasm_line__has_offset(dl) 204e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng || dl->ops.target.offset >= symbol__size(sym)) 205e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return false; 206e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 207e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return true; 208e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng} 209e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 210e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstatic void annotate_browser__draw_current_jump(struct ui_browser *browser) 211e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{ 212e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng struct annotate_browser *ab = container_of(browser, struct annotate_browser, b); 213e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng struct disasm_line *cursor = ab->selection, *target; 214e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng struct browser_disasm_line *btarget, *bcursor; 215e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng unsigned int from, to; 216e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng struct map_symbol *ms = ab->b.priv; 217e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng struct symbol *sym = ms->sym; 218e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng u8 pcnt_width = 7; 219e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 220e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng /* PLT symbols contain external offsets */ 221e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (strstr(sym->name, "@plt")) 222e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return; 223e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 224e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (!disasm_line__is_valid_jump(cursor, sym)) 225e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return; 226e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 227e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng target = ab->offsets[cursor->ops.target.offset]; 228e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (!target) 229e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return; 230e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 231e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng bcursor = disasm_line__browser(cursor); 232e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng btarget = disasm_line__browser(target); 233e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 234e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (annotate_browser__opts.hide_src_code) { 235e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng from = bcursor->idx_asm; 236e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng to = btarget->idx_asm; 237e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng } else { 238e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng from = (u64)bcursor->idx; 239e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng to = (u64)btarget->idx; 240e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng } 241e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 242e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng pcnt_width *= ab->nr_events; 243e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 244e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng ui_browser__set_color(browser, HE_COLORSET_CODE); 245e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng __ui_browser__line_arrow(browser, pcnt_width + 2 + ab->addr_width, 246e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng from, to); 247e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng} 248e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 249e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstatic unsigned int annotate_browser__refresh(struct ui_browser *browser) 250e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{ 251e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng struct annotate_browser *ab = container_of(browser, struct annotate_browser, b); 252e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng int ret = ui_browser__list_head_refresh(browser); 253e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng int pcnt_width; 254e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 255e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng pcnt_width = 7 * ab->nr_events; 256e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 257e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (annotate_browser__opts.jump_arrows) 258e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng annotate_browser__draw_current_jump(browser); 259e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 260e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng ui_browser__set_color(browser, HE_COLORSET_NORMAL); 261e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng __ui_browser__vline(browser, pcnt_width, 0, browser->height - 1); 262e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return ret; 263e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng} 264e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 265e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstatic int disasm__cmp(struct browser_disasm_line *a, 266e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng struct browser_disasm_line *b, int nr_pcnt) 267e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{ 268e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng int i; 269e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 270e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng for (i = 0; i < nr_pcnt; i++) { 271e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (a->percent[i] == b->percent[i]) 272e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng continue; 273e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return a->percent[i] < b->percent[i]; 274e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng } 275e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return 0; 276e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng} 277e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 278e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstatic void disasm_rb_tree__insert(struct rb_root *root, struct browser_disasm_line *bdl, 279e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng int nr_events) 280e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{ 281e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng struct rb_node **p = &root->rb_node; 282e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng struct rb_node *parent = NULL; 283e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng struct browser_disasm_line *l; 284e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 285e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng while (*p != NULL) { 286e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng parent = *p; 287e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng l = rb_entry(parent, struct browser_disasm_line, rb_node); 288e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 289e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (disasm__cmp(bdl, l, nr_events)) 290e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng p = &(*p)->rb_left; 291e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng else 292e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng p = &(*p)->rb_right; 293e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng } 294e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng rb_link_node(&bdl->rb_node, parent, p); 295e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng rb_insert_color(&bdl->rb_node, root); 296e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng} 297e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 298e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstatic void annotate_browser__set_top(struct annotate_browser *browser, 299e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng struct disasm_line *pos, u32 idx) 300e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{ 301e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng unsigned back; 302e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 303e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng ui_browser__refresh_dimensions(&browser->b); 304e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng back = browser->b.height / 2; 305e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng browser->b.top_idx = browser->b.index = idx; 306e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 307e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng while (browser->b.top_idx != 0 && back != 0) { 308e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng pos = list_entry(pos->node.prev, struct disasm_line, node); 309e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 310e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (disasm_line__filter(&browser->b, &pos->node)) 311e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng continue; 312e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 313e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng --browser->b.top_idx; 314e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng --back; 315e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng } 316e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 317e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng browser->b.top = pos; 318e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng browser->b.navkeypressed = true; 319e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng} 320e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 321e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstatic void annotate_browser__set_rb_top(struct annotate_browser *browser, 322e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng struct rb_node *nd) 323e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{ 324e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng struct browser_disasm_line *bpos; 325e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng struct disasm_line *pos; 326e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng u32 idx; 327e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 328e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng bpos = rb_entry(nd, struct browser_disasm_line, rb_node); 329e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng pos = ((struct disasm_line *)bpos) - 1; 330e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng idx = bpos->idx; 331e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (annotate_browser__opts.hide_src_code) 332e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng idx = bpos->idx_asm; 333e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng annotate_browser__set_top(browser, pos, idx); 334e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng browser->curr_hot = nd; 335e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng} 336e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 337e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstatic void annotate_browser__calc_percent(struct annotate_browser *browser, 338e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng struct perf_evsel *evsel) 339e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{ 340e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng struct map_symbol *ms = browser->b.priv; 341e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng struct symbol *sym = ms->sym; 342e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng struct annotation *notes = symbol__annotation(sym); 343e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng struct disasm_line *pos, *next; 344e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng s64 len = symbol__size(sym); 345e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 346e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng browser->entries = RB_ROOT; 347e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 348e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng pthread_mutex_lock(¬es->lock); 349e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 350e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng list_for_each_entry(pos, ¬es->src->source, node) { 351e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng struct browser_disasm_line *bpos = disasm_line__browser(pos); 352e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng const char *path = NULL; 353e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng double max_percent = 0.0; 354e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng int i; 355e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 356e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (pos->offset == -1) { 357e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng RB_CLEAR_NODE(&bpos->rb_node); 358e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng continue; 359e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng } 360e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 361e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng next = disasm__get_next_ip_line(¬es->src->source, pos); 362e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 363e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng for (i = 0; i < browser->nr_events; i++) { 364e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng bpos->percent[i] = disasm__calc_percent(notes, 365e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng evsel->idx + i, 366e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng pos->offset, 367e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng next ? next->offset : len, 368e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng &path); 369e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 370e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (max_percent < bpos->percent[i]) 371e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng max_percent = bpos->percent[i]; 372e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng } 373e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 374e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (max_percent < 0.01) { 375e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng RB_CLEAR_NODE(&bpos->rb_node); 376e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng continue; 377e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng } 378e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng disasm_rb_tree__insert(&browser->entries, bpos, 379e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng browser->nr_events); 380e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng } 381e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng pthread_mutex_unlock(¬es->lock); 382e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 383e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng browser->curr_hot = rb_last(&browser->entries); 384e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng} 385e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 386e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstatic bool annotate_browser__toggle_source(struct annotate_browser *browser) 387e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{ 388e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng struct disasm_line *dl; 389e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng struct browser_disasm_line *bdl; 390e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng off_t offset = browser->b.index - browser->b.top_idx; 391e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 392e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng browser->b.seek(&browser->b, offset, SEEK_CUR); 393e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng dl = list_entry(browser->b.top, struct disasm_line, node); 394e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng bdl = disasm_line__browser(dl); 395e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 396e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (annotate_browser__opts.hide_src_code) { 397e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (bdl->idx_asm < offset) 398e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng offset = bdl->idx; 399e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 400e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng browser->b.nr_entries = browser->nr_entries; 401e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng annotate_browser__opts.hide_src_code = false; 402e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng browser->b.seek(&browser->b, -offset, SEEK_CUR); 403e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng browser->b.top_idx = bdl->idx - offset; 404e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng browser->b.index = bdl->idx; 405e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng } else { 406e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (bdl->idx_asm < 0) { 407e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng ui_helpline__puts("Only available for assembly lines."); 408e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng browser->b.seek(&browser->b, -offset, SEEK_CUR); 409e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return false; 410e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng } 411e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 412e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (bdl->idx_asm < offset) 413e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng offset = bdl->idx_asm; 414e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 415e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng browser->b.nr_entries = browser->nr_asm_entries; 416e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng annotate_browser__opts.hide_src_code = true; 417e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng browser->b.seek(&browser->b, -offset, SEEK_CUR); 418e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng browser->b.top_idx = bdl->idx_asm - offset; 419e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng browser->b.index = bdl->idx_asm; 420e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng } 421e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 422e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return true; 423e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng} 424e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 425e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstatic void annotate_browser__init_asm_mode(struct annotate_browser *browser) 426e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{ 427e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng ui_browser__reset_index(&browser->b); 428e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng browser->b.nr_entries = browser->nr_asm_entries; 429e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng} 430e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 431e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng#define SYM_TITLE_MAX_SIZE (PATH_MAX + 64) 432e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 433e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstatic int sym_title(struct symbol *sym, struct map *map, char *title, 434e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng size_t sz) 435e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{ 436e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return snprintf(title, sz, "%s %s", sym->name, map->dso->long_name); 437e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng} 438e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 439e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstatic bool annotate_browser__callq(struct annotate_browser *browser, 440e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng struct perf_evsel *evsel, 441e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng struct hist_browser_timer *hbt) 442e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{ 443e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng struct map_symbol *ms = browser->b.priv; 444e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng struct disasm_line *dl = browser->selection; 445e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng struct symbol *sym = ms->sym; 446e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng struct annotation *notes; 447e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng struct symbol *target; 448e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng u64 ip; 449e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng char title[SYM_TITLE_MAX_SIZE]; 450e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 451e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (!ins__is_call(dl->ins)) 452e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return false; 453e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 454e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng ip = ms->map->map_ip(ms->map, dl->ops.target.addr); 455e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng target = map__find_symbol(ms->map, ip, NULL); 456e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (target == NULL) { 457e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng ui_helpline__puts("The called function was not found."); 458e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return true; 459e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng } 460e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 461e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng notes = symbol__annotation(target); 462e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng pthread_mutex_lock(¬es->lock); 463e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 464e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (notes->src == NULL && symbol__alloc_hist(target) < 0) { 465e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng pthread_mutex_unlock(¬es->lock); 466e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng ui__warning("Not enough memory for annotating '%s' symbol!\n", 467e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng target->name); 468e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return true; 469e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng } 470e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 471e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng pthread_mutex_unlock(¬es->lock); 472e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng symbol__tui_annotate(target, ms->map, evsel, hbt); 473e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng sym_title(sym, ms->map, title, sizeof(title)); 474e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng ui_browser__show_title(&browser->b, title); 475e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return true; 476e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng} 477e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 478e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstatic 479e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstruct disasm_line *annotate_browser__find_offset(struct annotate_browser *browser, 480e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng s64 offset, s64 *idx) 481e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{ 482e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng struct map_symbol *ms = browser->b.priv; 483e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng struct symbol *sym = ms->sym; 484e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng struct annotation *notes = symbol__annotation(sym); 485e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng struct disasm_line *pos; 486e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 487e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng *idx = 0; 488e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng list_for_each_entry(pos, ¬es->src->source, node) { 489e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (pos->offset == offset) 490e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return pos; 491e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (!disasm_line__filter(&browser->b, &pos->node)) 492e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng ++*idx; 493e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng } 494e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 495e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return NULL; 496e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng} 497e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 498e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstatic bool annotate_browser__jump(struct annotate_browser *browser) 499e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{ 500e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng struct disasm_line *dl = browser->selection; 501e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng s64 idx; 502e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 503e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (!ins__is_jump(dl->ins)) 504e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return false; 505e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 506e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng dl = annotate_browser__find_offset(browser, dl->ops.target.offset, &idx); 507e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (dl == NULL) { 508e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng ui_helpline__puts("Invalid jump offset"); 509e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return true; 510e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng } 511e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 512e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng annotate_browser__set_top(browser, dl, idx); 513e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 514e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return true; 515e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng} 516e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 517e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstatic 518e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstruct disasm_line *annotate_browser__find_string(struct annotate_browser *browser, 519e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng char *s, s64 *idx) 520e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{ 521e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng struct map_symbol *ms = browser->b.priv; 522e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng struct symbol *sym = ms->sym; 523e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng struct annotation *notes = symbol__annotation(sym); 524e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng struct disasm_line *pos = browser->selection; 525e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 526e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng *idx = browser->b.index; 527e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng list_for_each_entry_continue(pos, ¬es->src->source, node) { 528e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (disasm_line__filter(&browser->b, &pos->node)) 529e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng continue; 530e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 531e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng ++*idx; 532e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 533e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (pos->line && strstr(pos->line, s) != NULL) 534e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return pos; 535e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng } 536e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 537e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return NULL; 538e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng} 539e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 540e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstatic bool __annotate_browser__search(struct annotate_browser *browser) 541e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{ 542e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng struct disasm_line *dl; 543e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng s64 idx; 544e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 545e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng dl = annotate_browser__find_string(browser, browser->search_bf, &idx); 546e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (dl == NULL) { 547e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng ui_helpline__puts("String not found!"); 548e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return false; 549e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng } 550e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 551e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng annotate_browser__set_top(browser, dl, idx); 552e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng browser->searching_backwards = false; 553e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return true; 554e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng} 555e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 556e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstatic 557e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstruct disasm_line *annotate_browser__find_string_reverse(struct annotate_browser *browser, 558e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng char *s, s64 *idx) 559e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{ 560e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng struct map_symbol *ms = browser->b.priv; 561e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng struct symbol *sym = ms->sym; 562e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng struct annotation *notes = symbol__annotation(sym); 563e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng struct disasm_line *pos = browser->selection; 564e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 565e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng *idx = browser->b.index; 566e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng list_for_each_entry_continue_reverse(pos, ¬es->src->source, node) { 567e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (disasm_line__filter(&browser->b, &pos->node)) 568e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng continue; 569e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 570e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng --*idx; 571e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 572e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (pos->line && strstr(pos->line, s) != NULL) 573e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return pos; 574e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng } 575e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 576e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return NULL; 577e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng} 578e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 579e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstatic bool __annotate_browser__search_reverse(struct annotate_browser *browser) 580e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{ 581e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng struct disasm_line *dl; 582e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng s64 idx; 583e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 584e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng dl = annotate_browser__find_string_reverse(browser, browser->search_bf, &idx); 585e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (dl == NULL) { 586e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng ui_helpline__puts("String not found!"); 587e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return false; 588e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng } 589e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 590e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng annotate_browser__set_top(browser, dl, idx); 591e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng browser->searching_backwards = true; 592e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return true; 593e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng} 594e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 595e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstatic bool annotate_browser__search_window(struct annotate_browser *browser, 596e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng int delay_secs) 597e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{ 598e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (ui_browser__input_window("Search", "String: ", browser->search_bf, 599e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng "ENTER: OK, ESC: Cancel", 600e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng delay_secs * 2) != K_ENTER || 601e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng !*browser->search_bf) 602e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return false; 603e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 604e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return true; 605e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng} 606e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 607e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstatic bool annotate_browser__search(struct annotate_browser *browser, int delay_secs) 608e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{ 609e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (annotate_browser__search_window(browser, delay_secs)) 610e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return __annotate_browser__search(browser); 611e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 612e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return false; 613e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng} 614e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 615e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstatic bool annotate_browser__continue_search(struct annotate_browser *browser, 616e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng int delay_secs) 617e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{ 618e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (!*browser->search_bf) 619e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return annotate_browser__search(browser, delay_secs); 620e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 621e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return __annotate_browser__search(browser); 622e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng} 623e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 624e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstatic bool annotate_browser__search_reverse(struct annotate_browser *browser, 625e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng int delay_secs) 626e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{ 627e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (annotate_browser__search_window(browser, delay_secs)) 628e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return __annotate_browser__search_reverse(browser); 629e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 630e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return false; 631e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng} 632e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 633e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstatic 634e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengbool annotate_browser__continue_search_reverse(struct annotate_browser *browser, 635e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng int delay_secs) 636e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{ 637e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (!*browser->search_bf) 638e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return annotate_browser__search_reverse(browser, delay_secs); 639e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 640e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return __annotate_browser__search_reverse(browser); 641e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng} 642e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 643e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstatic void annotate_browser__update_addr_width(struct annotate_browser *browser) 644e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{ 645e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (annotate_browser__opts.use_offset) 646e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng browser->target_width = browser->min_addr_width; 647e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng else 648e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng browser->target_width = browser->max_addr_width; 649e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 650e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng browser->addr_width = browser->target_width; 651e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 652e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (annotate_browser__opts.show_nr_jumps) 653e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng browser->addr_width += browser->jumps_width + 1; 654e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng} 655e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 656e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstatic int annotate_browser__run(struct annotate_browser *browser, 657e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng struct perf_evsel *evsel, 658e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng struct hist_browser_timer *hbt) 659e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{ 660e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng struct rb_node *nd = NULL; 661e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng struct map_symbol *ms = browser->b.priv; 662e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng struct symbol *sym = ms->sym; 663e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng const char *help = "Press 'h' for help on key bindings"; 664e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng int delay_secs = hbt ? hbt->refresh : 0; 665e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng int key; 666e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng char title[SYM_TITLE_MAX_SIZE]; 667e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 668e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng sym_title(sym, ms->map, title, sizeof(title)); 669e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (ui_browser__show(&browser->b, title, help) < 0) 670e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return -1; 671e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 672e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng annotate_browser__calc_percent(browser, evsel); 673e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 674e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (browser->curr_hot) { 675e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng annotate_browser__set_rb_top(browser, browser->curr_hot); 676e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng browser->b.navkeypressed = false; 677e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng } 678e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 679e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng nd = browser->curr_hot; 680e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 681e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng while (1) { 682e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng key = ui_browser__run(&browser->b, delay_secs); 683e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 684e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (delay_secs != 0) { 685e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng annotate_browser__calc_percent(browser, evsel); 686e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng /* 687e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng * Current line focus got out of the list of most active 688e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng * lines, NULL it so that if TAB|UNTAB is pressed, we 689e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng * move to curr_hot (current hottest line). 690e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng */ 691e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (nd != NULL && RB_EMPTY_NODE(nd)) 692e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng nd = NULL; 693e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng } 694e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 695e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng switch (key) { 696e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng case K_TIMER: 697e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (hbt) 698e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng hbt->timer(hbt->arg); 699e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 700e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (delay_secs != 0) 701e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng symbol__annotate_decay_histogram(sym, evsel->idx); 702e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng continue; 703e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng case K_TAB: 704e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (nd != NULL) { 705e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng nd = rb_prev(nd); 706e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (nd == NULL) 707e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng nd = rb_last(&browser->entries); 708e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng } else 709e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng nd = browser->curr_hot; 710e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng break; 711e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng case K_UNTAB: 712e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (nd != NULL) 713e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng nd = rb_next(nd); 714e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (nd == NULL) 715e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng nd = rb_first(&browser->entries); 716e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng else 717e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng nd = browser->curr_hot; 718e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng break; 719e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng case K_F1: 720e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng case 'h': 721e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng ui_browser__help_window(&browser->b, 722e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng "UP/DOWN/PGUP\n" 723e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng "PGDN/SPACE Navigate\n" 724e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng "q/ESC/CTRL+C Exit\n\n" 725e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng "-> Go to target\n" 726e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng "<- Exit\n" 727e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng "H Cycle thru hottest instructions\n" 728e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng "j Toggle showing jump to target arrows\n" 729e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng "J Toggle showing number of jump sources on targets\n" 730e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng "n Search next string\n" 731e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng "o Toggle disassembler output/simplified view\n" 732e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng "s Toggle source code view\n" 733e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng "/ Search string\n" 734e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng "r Run available scripts\n" 735e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng "? Search string backwards\n"); 736e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng continue; 737e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng case 'r': 738e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng { 739e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng script_browse(NULL); 740e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng continue; 741e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng } 742e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng case 'H': 743e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng nd = browser->curr_hot; 744e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng break; 745e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng case 's': 746e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (annotate_browser__toggle_source(browser)) 747e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng ui_helpline__puts(help); 748e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng continue; 749e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng case 'o': 750e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng annotate_browser__opts.use_offset = !annotate_browser__opts.use_offset; 751e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng annotate_browser__update_addr_width(browser); 752e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng continue; 753e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng case 'j': 754e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng annotate_browser__opts.jump_arrows = !annotate_browser__opts.jump_arrows; 755e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng continue; 756e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng case 'J': 757e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng annotate_browser__opts.show_nr_jumps = !annotate_browser__opts.show_nr_jumps; 758e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng annotate_browser__update_addr_width(browser); 759e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng continue; 760e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng case '/': 761e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (annotate_browser__search(browser, delay_secs)) { 762e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengshow_help: 763e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng ui_helpline__puts(help); 764e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng } 765e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng continue; 766e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng case 'n': 767e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (browser->searching_backwards ? 768e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng annotate_browser__continue_search_reverse(browser, delay_secs) : 769e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng annotate_browser__continue_search(browser, delay_secs)) 770e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng goto show_help; 771e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng continue; 772e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng case '?': 773e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (annotate_browser__search_reverse(browser, delay_secs)) 774e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng goto show_help; 775e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng continue; 776e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng case 'D': { 777e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng static int seq; 778e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng ui_helpline__pop(); 779e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng ui_helpline__fpush("%d: nr_ent=%d, height=%d, idx=%d, top_idx=%d, nr_asm_entries=%d", 780e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng seq++, browser->b.nr_entries, 781e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng browser->b.height, 782e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng browser->b.index, 783e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng browser->b.top_idx, 784e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng browser->nr_asm_entries); 785e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng } 786e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng continue; 787e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng case K_ENTER: 788e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng case K_RIGHT: 789e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (browser->selection == NULL) 790e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng ui_helpline__puts("Huh? No selection. Report to linux-kernel@vger.kernel.org"); 791e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng else if (browser->selection->offset == -1) 792e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng ui_helpline__puts("Actions are only available for assembly lines."); 793e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng else if (!browser->selection->ins) { 794e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (strcmp(browser->selection->name, "retq")) 795e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng goto show_sup_ins; 796e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng goto out; 797e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng } else if (!(annotate_browser__jump(browser) || 798e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng annotate_browser__callq(browser, evsel, hbt))) { 799e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengshow_sup_ins: 800e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng ui_helpline__puts("Actions are only available for 'callq', 'retq' & jump instructions."); 801e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng } 802e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng continue; 803e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng case K_LEFT: 804e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng case K_ESC: 805e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng case 'q': 806e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng case CTRL('c'): 807e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng goto out; 808e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng default: 809e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng continue; 810e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng } 811e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 812e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (nd != NULL) 813e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng annotate_browser__set_rb_top(browser, nd); 814e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng } 815e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengout: 816e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng ui_browser__hide(&browser->b); 817e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return key; 818e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng} 819e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 820e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengint hist_entry__tui_annotate(struct hist_entry *he, struct perf_evsel *evsel, 821e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng struct hist_browser_timer *hbt) 822e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{ 823e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return symbol__tui_annotate(he->ms.sym, he->ms.map, evsel, hbt); 824e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng} 825e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 826e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstatic void annotate_browser__mark_jump_targets(struct annotate_browser *browser, 827e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng size_t size) 828e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{ 829e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng u64 offset; 830e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng struct map_symbol *ms = browser->b.priv; 831e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng struct symbol *sym = ms->sym; 832e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 833e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng /* PLT symbols contain external offsets */ 834e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (strstr(sym->name, "@plt")) 835e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return; 836e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 837e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng for (offset = 0; offset < size; ++offset) { 838e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng struct disasm_line *dl = browser->offsets[offset], *dlt; 839e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng struct browser_disasm_line *bdlt; 840e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 841e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (!disasm_line__is_valid_jump(dl, sym)) 842e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng continue; 843e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 844e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng dlt = browser->offsets[dl->ops.target.offset]; 845e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng /* 846e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng * FIXME: Oops, no jump target? Buggy disassembler? Or do we 847e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng * have to adjust to the previous offset? 848e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng */ 849e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (dlt == NULL) 850e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng continue; 851e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 852e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng bdlt = disasm_line__browser(dlt); 853e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (++bdlt->jump_sources > browser->max_jump_sources) 854e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng browser->max_jump_sources = bdlt->jump_sources; 855e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 856e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng ++browser->nr_jumps; 857e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng } 858e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 859e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng} 860e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 861e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstatic inline int width_jumps(int n) 862e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{ 863e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (n >= 100) 864e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return 5; 865e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (n / 10) 866e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return 2; 867e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return 1; 868e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng} 869e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 870e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengint symbol__tui_annotate(struct symbol *sym, struct map *map, 871e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng struct perf_evsel *evsel, 872e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng struct hist_browser_timer *hbt) 873e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{ 874e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng struct disasm_line *pos, *n; 875e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng struct annotation *notes; 876e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng size_t size; 877e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng struct map_symbol ms = { 878e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng .map = map, 879e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng .sym = sym, 880e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng }; 881e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng struct annotate_browser browser = { 882e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng .b = { 883e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng .refresh = annotate_browser__refresh, 884e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng .seek = ui_browser__list_head_seek, 885e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng .write = annotate_browser__write, 886e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng .filter = disasm_line__filter, 887e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng .priv = &ms, 888e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng .use_navkeypressed = true, 889e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng }, 890e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng }; 891e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng int ret = -1; 892e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng int nr_pcnt = 1; 893e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng size_t sizeof_bdl = sizeof(struct browser_disasm_line); 894e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 895e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (sym == NULL) 896e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return -1; 897e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 898e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng size = symbol__size(sym); 899e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 900e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (map->dso->annotate_warned) 901e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return -1; 902e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 903e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng browser.offsets = zalloc(size * sizeof(struct disasm_line *)); 904e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (browser.offsets == NULL) { 905e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng ui__error("Not enough memory!"); 906e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return -1; 907e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng } 908e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 909e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (perf_evsel__is_group_event(evsel)) { 910e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng nr_pcnt = evsel->nr_members; 911e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng sizeof_bdl += sizeof(double) * (nr_pcnt - 1); 912e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng } 913e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 914e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (symbol__annotate(sym, map, sizeof_bdl) < 0) { 915e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng ui__error("%s", ui_helpline__last_msg); 916e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng goto out_free_offsets; 917e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng } 918e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 919e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng ui_helpline__push("Press <- or ESC to exit"); 920e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 921e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng notes = symbol__annotation(sym); 922e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng browser.start = map__rip_2objdump(map, sym->start); 923e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 924e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng list_for_each_entry(pos, ¬es->src->source, node) { 925e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng struct browser_disasm_line *bpos; 926e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng size_t line_len = strlen(pos->line); 927e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 928e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (browser.b.width < line_len) 929e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng browser.b.width = line_len; 930e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng bpos = disasm_line__browser(pos); 931e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng bpos->idx = browser.nr_entries++; 932e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (pos->offset != -1) { 933e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng bpos->idx_asm = browser.nr_asm_entries++; 934e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng /* 935e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng * FIXME: short term bandaid to cope with assembly 936e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng * routines that comes with labels in the same column 937e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng * as the address in objdump, sigh. 938e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng * 939e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng * E.g. copy_user_generic_unrolled 940e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng */ 941e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (pos->offset < (s64)size) 942e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng browser.offsets[pos->offset] = pos; 943e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng } else 944e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng bpos->idx_asm = -1; 945e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng } 946e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 947e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng annotate_browser__mark_jump_targets(&browser, size); 948e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 949e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng browser.addr_width = browser.target_width = browser.min_addr_width = hex_width(size); 950e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng browser.max_addr_width = hex_width(sym->end); 951e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng browser.jumps_width = width_jumps(browser.max_jump_sources); 952e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng browser.nr_events = nr_pcnt; 953e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng browser.b.nr_entries = browser.nr_entries; 954e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng browser.b.entries = ¬es->src->source, 955e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng browser.b.width += 18; /* Percentage */ 956e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 957e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (annotate_browser__opts.hide_src_code) 958e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng annotate_browser__init_asm_mode(&browser); 959e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 960e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng annotate_browser__update_addr_width(&browser); 961e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 962e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng ret = annotate_browser__run(&browser, evsel, hbt); 963e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng list_for_each_entry_safe(pos, n, ¬es->src->source, node) { 964e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng list_del(&pos->node); 965e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng disasm_line__free(pos); 966e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng } 967e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 968e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengout_free_offsets: 969e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng free(browser.offsets); 970e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return ret; 971e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng} 972e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 973e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng#define ANNOTATE_CFG(n) \ 974e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng { .name = #n, .value = &annotate_browser__opts.n, } 975e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 976e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng/* 977e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng * Keep the entries sorted, they are bsearch'ed 978e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng */ 979e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstatic struct annotate_config { 980e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng const char *name; 981e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng bool *value; 982e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng} annotate__configs[] = { 983e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng ANNOTATE_CFG(hide_src_code), 984e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng ANNOTATE_CFG(jump_arrows), 985e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng ANNOTATE_CFG(show_nr_jumps), 986e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng ANNOTATE_CFG(use_offset), 987e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng}; 988e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 989e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng#undef ANNOTATE_CFG 990e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 991e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstatic int annotate_config__cmp(const void *name, const void *cfgp) 992e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{ 993e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng const struct annotate_config *cfg = cfgp; 994e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 995e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return strcmp(name, cfg->name); 996e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng} 997e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 998e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstatic int annotate__config(const char *var, const char *value, 999e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng void *data __maybe_unused) 1000e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{ 1001e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng struct annotate_config *cfg; 1002e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng const char *name; 1003e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 1004e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (prefixcmp(var, "annotate.") != 0) 1005e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return 0; 1006e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 1007e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng name = var + 9; 1008e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng cfg = bsearch(name, annotate__configs, ARRAY_SIZE(annotate__configs), 1009e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng sizeof(struct annotate_config), annotate_config__cmp); 1010e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 1011e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (cfg == NULL) 1012e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return -1; 1013e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 1014e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng *cfg->value = perf_config_bool(name, value); 1015e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return 0; 1016e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng} 1017e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 1018e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengvoid annotate_browser__init(void) 1019e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{ 1020e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng perf_config(annotate__config, NULL); 1021e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng} 1022