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