1 // SPDX-License-Identifier: GPL-2.0 2 #include <elf.h> 3 #include <inttypes.h> 4 #include <sys/ttydefaults.h> 5 #include <stdlib.h> 6 #include <string.h> 7 #include <linux/bitops.h> 8 #include "../../util/util.h" 9 #include "../../util/debug.h" 10 #include "../../util/map.h" 11 #include "../../util/dso.h" 12 #include "../../util/symbol.h" 13 #include "../browser.h" 14 #include "../helpline.h" 15 #include "../keysyms.h" 16 #include "map.h" 17 18 #include <linux/ctype.h> 19 20 struct map_browser { 21 struct ui_browser b; 22 struct map *map; 23 u8 addrlen; 24 }; 25 26 static void map_browser__write(struct ui_browser *browser, void *nd, int row) 27 { 28 struct symbol *sym = rb_entry(nd, struct symbol, rb_node); 29 struct map_browser *mb = container_of(browser, struct map_browser, b); 30 bool current_entry = ui_browser__is_current_entry(browser, row); 31 int width; 32 33 ui_browser__set_percent_color(browser, 0, current_entry); 34 ui_browser__printf(browser, "%*" PRIx64 " %*" PRIx64 " %c ", 35 mb->addrlen, sym->start, mb->addrlen, sym->end, 36 sym->binding == STB_GLOBAL ? 'g' : 37 sym->binding == STB_LOCAL ? 'l' : 'w'); 38 width = browser->width - ((mb->addrlen * 2) + 4); 39 if (width > 0) 40 ui_browser__write_nstring(browser, sym->name, width); 41 } 42 43 /* FIXME uber-kludgy, see comment on cmd_report... */ 44 static u32 *symbol__browser_index(struct symbol *browser) 45 { 46 return ((void *)browser) - sizeof(struct rb_node) - sizeof(u32); 47 } 48 49 static int map_browser__search(struct map_browser *browser) 50 { 51 char target[512]; 52 struct symbol *sym; 53 int err = ui_browser__input_window("Search by name/addr", 54 "Prefix with 0x to search by address", 55 target, "ENTER: OK, ESC: Cancel", 0); 56 if (err != K_ENTER) 57 return -1; 58 59 if (target[0] == '0' && tolower(target[1]) == 'x') { 60 u64 addr = strtoull(target, NULL, 16); 61 sym = map__find_symbol(browser->map, addr); 62 } else 63 sym = map__find_symbol_by_name(browser->map, target); 64 65 if (sym != NULL) { 66 u32 *idx = symbol__browser_index(sym); 67 68 browser->b.top = &sym->rb_node; 69 browser->b.index = browser->b.top_idx = *idx; 70 } else 71 ui_helpline__fpush("%s not found!", target); 72 73 return 0; 74 } 75 76 static int map_browser__run(struct map_browser *browser) 77 { 78 int key; 79 80 if (ui_browser__show(&browser->b, browser->map->dso->long_name, 81 "Press ESC to exit, %s / to search", 82 verbose > 0 ? "" : "restart with -v to use") < 0) 83 return -1; 84 85 while (1) { 86 key = ui_browser__run(&browser->b, 0); 87 88 switch (key) { 89 case '/': 90 if (verbose > 0) 91 map_browser__search(browser); 92 default: 93 break; 94 case K_LEFT: 95 case K_ESC: 96 case 'q': 97 case CTRL('c'): 98 goto out; 99 } 100 } 101 out: 102 ui_browser__hide(&browser->b); 103 return key; 104 } 105 106 int map__browse(struct map *map) 107 { 108 struct map_browser mb = { 109 .b = { 110 .entries = &map->dso->symbols, 111 .refresh = ui_browser__rb_tree_refresh, 112 .seek = ui_browser__rb_tree_seek, 113 .write = map_browser__write, 114 }, 115 .map = map, 116 }; 117 struct rb_node *nd; 118 char tmp[BITS_PER_LONG / 4]; 119 u64 maxaddr = 0; 120 121 for (nd = rb_first(mb.b.entries); nd; nd = rb_next(nd)) { 122 struct symbol *pos = rb_entry(nd, struct symbol, rb_node); 123 124 if (maxaddr < pos->end) 125 maxaddr = pos->end; 126 if (verbose > 0) { 127 u32 *idx = symbol__browser_index(pos); 128 *idx = mb.b.nr_entries; 129 } 130 ++mb.b.nr_entries; 131 } 132 133 mb.addrlen = snprintf(tmp, sizeof(tmp), "%" PRIx64, maxaddr); 134 return map_browser__run(&mb); 135 } 136