mirror of
https://github.com/torvalds/linux.git
synced 2026-06-03 12:03:54 +02:00
We got the sane_ctype.h headers from git and kept using it so far, but since that code originally came from the kernel sources to the git sources, perhaps its better to just use the one in the kernel, so that we can leverage tools/perf/check_headers.sh to be notified when our copy gets out of sync, i.e. when fixes or goodies are added to the code we've copied. This will help with things like tools/lib/string.c where we want to have more things in common with the kernel, such as strim(), skip_spaces(), etc so as to go on removing the things that we have in tools/perf/util/ and instead using the code in the kernel, indirectly and removing things like EXPORT_SYMBOL(), etc, getting notified when fixes and improvements are made to the original code. Hopefully this also should help with reducing the difference of code hosted in tools/ to the one in the kernel proper. Cc: Adrian Hunter <adrian.hunter@intel.com> Cc: Jiri Olsa <jolsa@kernel.org> Cc: Namhyung Kim <namhyung@kernel.org> Link: https://lkml.kernel.org/n/tip-7k9868l713wqtgo01xxygn12@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
134 lines
3.3 KiB
C
134 lines
3.3 KiB
C
// SPDX-License-Identifier: GPL-2.0
|
|
#include <elf.h>
|
|
#include <inttypes.h>
|
|
#include <sys/ttydefaults.h>
|
|
#include <string.h>
|
|
#include <linux/bitops.h>
|
|
#include "../../util/util.h"
|
|
#include "../../util/debug.h"
|
|
#include "../../util/map.h"
|
|
#include "../../util/symbol.h"
|
|
#include "../browser.h"
|
|
#include "../helpline.h"
|
|
#include "../keysyms.h"
|
|
#include "map.h"
|
|
|
|
#include <linux/ctype.h>
|
|
|
|
struct map_browser {
|
|
struct ui_browser b;
|
|
struct map *map;
|
|
u8 addrlen;
|
|
};
|
|
|
|
static void map_browser__write(struct ui_browser *browser, void *nd, int row)
|
|
{
|
|
struct symbol *sym = rb_entry(nd, struct symbol, rb_node);
|
|
struct map_browser *mb = container_of(browser, struct map_browser, b);
|
|
bool current_entry = ui_browser__is_current_entry(browser, row);
|
|
int width;
|
|
|
|
ui_browser__set_percent_color(browser, 0, current_entry);
|
|
ui_browser__printf(browser, "%*" PRIx64 " %*" PRIx64 " %c ",
|
|
mb->addrlen, sym->start, mb->addrlen, sym->end,
|
|
sym->binding == STB_GLOBAL ? 'g' :
|
|
sym->binding == STB_LOCAL ? 'l' : 'w');
|
|
width = browser->width - ((mb->addrlen * 2) + 4);
|
|
if (width > 0)
|
|
ui_browser__write_nstring(browser, sym->name, width);
|
|
}
|
|
|
|
/* FIXME uber-kludgy, see comment on cmd_report... */
|
|
static u32 *symbol__browser_index(struct symbol *browser)
|
|
{
|
|
return ((void *)browser) - sizeof(struct rb_node) - sizeof(u32);
|
|
}
|
|
|
|
static int map_browser__search(struct map_browser *browser)
|
|
{
|
|
char target[512];
|
|
struct symbol *sym;
|
|
int err = ui_browser__input_window("Search by name/addr",
|
|
"Prefix with 0x to search by address",
|
|
target, "ENTER: OK, ESC: Cancel", 0);
|
|
if (err != K_ENTER)
|
|
return -1;
|
|
|
|
if (target[0] == '0' && tolower(target[1]) == 'x') {
|
|
u64 addr = strtoull(target, NULL, 16);
|
|
sym = map__find_symbol(browser->map, addr);
|
|
} else
|
|
sym = map__find_symbol_by_name(browser->map, target);
|
|
|
|
if (sym != NULL) {
|
|
u32 *idx = symbol__browser_index(sym);
|
|
|
|
browser->b.top = &sym->rb_node;
|
|
browser->b.index = browser->b.top_idx = *idx;
|
|
} else
|
|
ui_helpline__fpush("%s not found!", target);
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int map_browser__run(struct map_browser *browser)
|
|
{
|
|
int key;
|
|
|
|
if (ui_browser__show(&browser->b, browser->map->dso->long_name,
|
|
"Press ESC to exit, %s / to search",
|
|
verbose > 0 ? "" : "restart with -v to use") < 0)
|
|
return -1;
|
|
|
|
while (1) {
|
|
key = ui_browser__run(&browser->b, 0);
|
|
|
|
switch (key) {
|
|
case '/':
|
|
if (verbose > 0)
|
|
map_browser__search(browser);
|
|
default:
|
|
break;
|
|
case K_LEFT:
|
|
case K_ESC:
|
|
case 'q':
|
|
case CTRL('c'):
|
|
goto out;
|
|
}
|
|
}
|
|
out:
|
|
ui_browser__hide(&browser->b);
|
|
return key;
|
|
}
|
|
|
|
int map__browse(struct map *map)
|
|
{
|
|
struct map_browser mb = {
|
|
.b = {
|
|
.entries = &map->dso->symbols,
|
|
.refresh = ui_browser__rb_tree_refresh,
|
|
.seek = ui_browser__rb_tree_seek,
|
|
.write = map_browser__write,
|
|
},
|
|
.map = map,
|
|
};
|
|
struct rb_node *nd;
|
|
char tmp[BITS_PER_LONG / 4];
|
|
u64 maxaddr = 0;
|
|
|
|
for (nd = rb_first(mb.b.entries); nd; nd = rb_next(nd)) {
|
|
struct symbol *pos = rb_entry(nd, struct symbol, rb_node);
|
|
|
|
if (maxaddr < pos->end)
|
|
maxaddr = pos->end;
|
|
if (verbose > 0) {
|
|
u32 *idx = symbol__browser_index(pos);
|
|
*idx = mb.b.nr_entries;
|
|
}
|
|
++mb.b.nr_entries;
|
|
}
|
|
|
|
mb.addrlen = snprintf(tmp, sizeof(tmp), "%" PRIx64, maxaddr);
|
|
return map_browser__run(&mb);
|
|
}
|