perf kallsyms: Introduce tool to look for extended symbol information on the running...
authorArnaldo Carvalho de Melo <acme@redhat.com>
Thu, 5 Jan 2017 18:33:32 +0000 (15:33 -0300)
committerArnaldo Carvalho de Melo <acme@redhat.com>
Wed, 11 Jan 2017 19:48:01 +0000 (16:48 -0300)
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>
tools/perf/Build
tools/perf/Documentation/perf-kallsyms.txt [new file with mode: 0644]
tools/perf/builtin-help.c
tools/perf/builtin-kallsyms.c [new file with mode: 0644]
tools/perf/builtin.h
tools/perf/command-list.txt
tools/perf/perf.c

index b12d5d1666e3c1502c66308e9c535679a3189b29..0b48806f93c270114d68b11aaf5fa3ad768d9ff7 100644 (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
diff --git a/tools/perf/Documentation/perf-kallsyms.txt b/tools/perf/Documentation/perf-kallsyms.txt
new file mode 100644 (file)
index 0000000..954ea9e
--- /dev/null
@@ -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.
index 3bdb2c78a21b3f0118d0c7a376222b7bb96c4735..93da24a638befc75e1a06ece1cdb93c6a0fa9131 100644 (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
diff --git a/tools/perf/builtin-kallsyms.c b/tools/perf/builtin-kallsyms.c
new file mode 100644 (file)
index 0000000..224bfc4
--- /dev/null
@@ -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);
+}
index 0bcf68e98ccc2e992e005b41f0e6a9fcaf9b4e27..b55f5be486a1a322ff54729055eb5a2e3f4c3464 100644 (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);
index ab5cbaa170d0d882510e58d1d4e57e44c8843b3f..fb45613dba9e64121e0415bac1aa538757657d70 100644 (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
index aa23b3347d6b1f36dbe59f072d0f61caa7479d3d..13c8a7db055ed3c0cd12e13c0d2e2dada3998e34 100644 (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 },