From: Arnaldo Carvalho de Melo <[email protected]>

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 <[email protected]>
Cc: David Ahern <[email protected]>
Cc: Jiri Olsa <[email protected]>
Cc: Masami Hiramatsu <[email protected]>
Cc: Namhyung Kim <[email protected]>
Cc: Wang Nan <[email protected]>
Link: http://lkml.kernel.org/n/[email protected]
Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
---
 tools/perf/Build                           |  1 +
 tools/perf/Documentation/perf-kallsyms.txt | 24 +++++++++++
 tools/perf/builtin-help.c                  |  2 +-
 tools/perf/builtin-kallsyms.c              | 67 ++++++++++++++++++++++++++++++
 tools/perf/builtin.h                       |  1 +
 tools/perf/command-list.txt                |  1 +
 tools/perf/perf.c                          |  1 +
 7 files changed, 96 insertions(+), 1 deletion(-)
 create mode 100644 tools/perf/Documentation/perf-kallsyms.txt
 create mode 100644 tools/perf/builtin-kallsyms.c

diff --git a/tools/perf/Build b/tools/perf/Build
index b12d5d1666e3..0b48806f93c2 100644
--- a/tools/perf/Build
+++ b/tools/perf/Build
@@ -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
index 000000000000..954ea9e21236
--- /dev/null
+++ b/tools/perf/Documentation/perf-kallsyms.txt
@@ -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.
diff --git a/tools/perf/builtin-help.c b/tools/perf/builtin-help.c
index 3bdb2c78a21b..93da24a638be 100644
--- a/tools/perf/builtin-help.c
+++ b/tools/perf/builtin-help.c
@@ -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
index 000000000000..224bfc454b4a
--- /dev/null
+++ b/tools/perf/builtin-kallsyms.c
@@ -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 <[email protected]>
+ *
+ * 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);
+}
diff --git a/tools/perf/builtin.h b/tools/perf/builtin.h
index 0bcf68e98ccc..b55f5be486a1 100644
--- a/tools/perf/builtin.h
+++ b/tools/perf/builtin.h
@@ -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);
diff --git a/tools/perf/command-list.txt b/tools/perf/command-list.txt
index ab5cbaa170d0..fb45613dba9e 100644
--- a/tools/perf/command-list.txt
+++ b/tools/perf/command-list.txt
@@ -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
diff --git a/tools/perf/perf.c b/tools/perf/perf.c
index aa23b3347d6b..13c8a7db055e 100644
--- a/tools/perf/perf.c
+++ b/tools/perf/perf.c
@@ -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 },
-- 
2.9.3

Reply via email to