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