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.orgSigned-off-by: default avatarArnaldo Carvalho de Melo <acme@redhat.com>
parent 7d132caa
...@@ -7,6 +7,7 @@ perf-y += builtin-help.o ...@@ -7,6 +7,7 @@ perf-y += builtin-help.o
perf-y += builtin-sched.o perf-y += builtin-sched.o
perf-y += builtin-buildid-list.o perf-y += builtin-buildid-list.o
perf-y += builtin-buildid-cache.o perf-y += builtin-buildid-cache.o
perf-y += builtin-kallsyms.o
perf-y += builtin-list.o perf-y += builtin-list.o
perf-y += builtin-record.o perf-y += builtin-record.o
perf-y += builtin-report.o perf-y += builtin-report.o
......
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.
...@@ -434,7 +434,7 @@ int cmd_help(int argc, const char **argv, const char *prefix __maybe_unused) ...@@ -434,7 +434,7 @@ int cmd_help(int argc, const char **argv, const char *prefix __maybe_unused)
const char * const builtin_help_subcommands[] = { const char * const builtin_help_subcommands[] = {
"buildid-cache", "buildid-list", "diff", "evlist", "help", "list", "buildid-cache", "buildid-list", "diff", "evlist", "help", "list",
"record", "report", "bench", "stat", "timechart", "top", "annotate", "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 #ifdef HAVE_LIBELF_SUPPORT
"probe", "probe",
#endif #endif
......
/*
* 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);
}
...@@ -23,6 +23,7 @@ int cmd_diff(int argc, const char **argv, const char *prefix); ...@@ -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_evlist(int argc, const char **argv, const char *prefix);
int cmd_help(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_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_list(int argc, const char **argv, const char *prefix);
int cmd_record(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); int cmd_report(int argc, const char **argv, const char *prefix);
......
...@@ -12,6 +12,7 @@ perf-diff mainporcelain common ...@@ -12,6 +12,7 @@ perf-diff mainporcelain common
perf-config mainporcelain common perf-config mainporcelain common
perf-evlist mainporcelain common perf-evlist mainporcelain common
perf-inject mainporcelain common perf-inject mainporcelain common
perf-kallsyms mainporcelain common
perf-kmem mainporcelain common perf-kmem mainporcelain common
perf-kvm mainporcelain common perf-kvm mainporcelain common
perf-list mainporcelain common perf-list mainporcelain common
......
...@@ -47,6 +47,7 @@ static struct cmd_struct commands[] = { ...@@ -47,6 +47,7 @@ static struct cmd_struct commands[] = {
{ "diff", cmd_diff, 0 }, { "diff", cmd_diff, 0 },
{ "evlist", cmd_evlist, 0 }, { "evlist", cmd_evlist, 0 },
{ "help", cmd_help, 0 }, { "help", cmd_help, 0 },
{ "kallsyms", cmd_kallsyms, 0 },
{ "list", cmd_list, 0 }, { "list", cmd_list, 0 },
{ "record", cmd_record, 0 }, { "record", cmd_record, 0 },
{ "report", cmd_report, 0 }, { "report", cmd_report, 0 },
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment