perf kallsyms: Introduce tool to look for extended symbol information on the running kernel

Its similar to doing grep on a /proc/kallsyms, but it also shows extra
information like the path to the kernel module and the unrelocated
addresses in it, to help in diagnosing problems.

It is also helps demonstrate the use of the symbols routines so that
tool writers can use them more effectively.

Using it:

  $ perf kallsyms e1000_xmit_frame netif_rx usb_stor_set_xfer_buf
  e1000_xmit_frame: [e1000e] /lib/modules/4.9.0+/kernel/drivers/net/ethernet/intel/e1000e/e1000e.ko 0xffffffffc046fc10-0xffffffffc0470bb0 (0x19c80-0x1ac20)
  netif_rx: [kernel] [kernel.kallsyms] 0xffffffff916f03a0-0xffffffff916f0410 (0xffffffff916f03a0-0xffffffff916f0410)
  usb_stor_set_xfer_buf: [usb_storage] /lib/modules/4.9.0+/kernel/drivers/usb/storage/usb-storage.ko 0xffffffffc057aea0-0xffffffffc057af19 (0xf10-0xf89)
  $

Cc: Adrian Hunter <adrian.hunter@intel.com>
Cc: David Ahern <dsahern@gmail.com>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: Masami Hiramatsu <mhiramat@kernel.org>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Wang Nan <wangnan0@huawei.com>
Link: http://lkml.kernel.org/n/tip-79bk9pakujn4l4vq0f90klv3@git.kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
This commit is contained in:
Arnaldo Carvalho de Melo 2017-01-05 15:33:32 -03:00
parent 7d132caaf9
commit 355637717d
7 changed files with 96 additions and 1 deletions

View file

@ -7,6 +7,7 @@ perf-y += builtin-help.o
perf-y += builtin-sched.o
perf-y += builtin-buildid-list.o
perf-y += builtin-buildid-cache.o
perf-y += builtin-kallsyms.o
perf-y += builtin-list.o
perf-y += builtin-record.o
perf-y += builtin-report.o

View file

@ -0,0 +1,24 @@
perf-kallsyms(1)
==============
NAME
----
perf-kallsyms - Searches running kernel for symbols
SYNOPSIS
--------
[verse]
'perf kallsyms <options> symbol_name[,symbol_name...]'
DESCRIPTION
-----------
This command searches the running kernel kallsyms file for the given symbol(s)
and prints information about it, including the DSO, the kallsyms begin/end
addresses and the addresses in the ELF kallsyms symbol table (for symbols in
modules).
OPTIONS
-------
-v::
--verbose=::
Increase verbosity level, showing details about symbol table loading, etc.

View file

@ -434,7 +434,7 @@ int cmd_help(int argc, const char **argv, const char *prefix __maybe_unused)
const char * const builtin_help_subcommands[] = {
"buildid-cache", "buildid-list", "diff", "evlist", "help", "list",
"record", "report", "bench", "stat", "timechart", "top", "annotate",
"script", "sched", "kmem", "lock", "kvm", "test", "inject", "mem", "data",
"script", "sched", "kallsyms", "kmem", "lock", "kvm", "test", "inject", "mem", "data",
#ifdef HAVE_LIBELF_SUPPORT
"probe",
#endif

View file

@ -0,0 +1,67 @@
/*
* builtin-kallsyms.c
*
* Builtin command: Look for a symbol in the running kernel and its modules
*
* Copyright (C) 2017, Red Hat Inc, Arnaldo Carvalho de Melo <acme@redhat.com>
*
* Released under the GPL v2. (and only v2, not any later version)
*/
#include "builtin.h"
#include <linux/compiler.h>
#include <subcmd/parse-options.h>
#include "debug.h"
#include "machine.h"
#include "symbol.h"
static int __cmd_kallsyms(int argc, const char **argv)
{
int i;
struct machine *machine = machine__new_kallsyms();
if (machine == NULL) {
pr_err("Couldn't read /proc/kallsyms\n");
return -1;
}
for (i = 0; i < argc; ++i) {
struct map *map;
struct symbol *symbol = machine__find_kernel_function_by_name(machine, argv[i], &map);
if (symbol == NULL) {
printf("%s: not found\n", argv[i]);
continue;
}
printf("%s: %s %s %#" PRIx64 "-%#" PRIx64 " (%#" PRIx64 "-%#" PRIx64")\n",
symbol->name, map->dso->short_name, map->dso->long_name,
map->unmap_ip(map, symbol->start), map->unmap_ip(map, symbol->end),
symbol->start, symbol->end);
}
machine__delete(machine);
return 0;
}
int cmd_kallsyms(int argc, const char **argv, const char *prefix __maybe_unused)
{
const struct option options[] = {
OPT_INCR('v', "verbose", &verbose, "be more verbose (show counter open errors, etc)"),
OPT_END()
};
const char * const kallsyms_usage[] = {
"perf kallsyms [<options>] symbol_name",
NULL
};
argc = parse_options(argc, argv, options, kallsyms_usage, 0);
if (argc < 1)
usage_with_options(kallsyms_usage, options);
symbol_conf.sort_by_name = true;
symbol_conf.try_vmlinux_path = (symbol_conf.vmlinux_name == NULL);
if (symbol__init(NULL) < 0)
return -1;
return __cmd_kallsyms(argc, argv);
}

View file

@ -23,6 +23,7 @@ int cmd_diff(int argc, const char **argv, const char *prefix);
int cmd_evlist(int argc, const char **argv, const char *prefix);
int cmd_help(int argc, const char **argv, const char *prefix);
int cmd_sched(int argc, const char **argv, const char *prefix);
int cmd_kallsyms(int argc, const char **argv, const char *prefix);
int cmd_list(int argc, const char **argv, const char *prefix);
int cmd_record(int argc, const char **argv, const char *prefix);
int cmd_report(int argc, const char **argv, const char *prefix);

View file

@ -12,6 +12,7 @@ perf-diff mainporcelain common
perf-config mainporcelain common
perf-evlist mainporcelain common
perf-inject mainporcelain common
perf-kallsyms mainporcelain common
perf-kmem mainporcelain common
perf-kvm mainporcelain common
perf-list mainporcelain common

View file

@ -47,6 +47,7 @@ static struct cmd_struct commands[] = {
{ "diff", cmd_diff, 0 },
{ "evlist", cmd_evlist, 0 },
{ "help", cmd_help, 0 },
{ "kallsyms", cmd_kallsyms, 0 },
{ "list", cmd_list, 0 },
{ "record", cmd_record, 0 },
{ "report", cmd_report, 0 },