Commit 35563771 authored by Arnaldo Carvalho de Melo's avatar Arnaldo Carvalho de Melo
Browse files

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: default avatarArnaldo Carvalho de Melo <acme@redhat.com>
parent 7d132caa
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -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
+24 −0
Original line number Diff line number Diff line
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.
+1 −1
Original line number Diff line number Diff line
@@ -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
+67 −0
Original line number Diff line number Diff line
/*
 * 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);
}
+1 −0
Original line number Diff line number Diff line
@@ -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);
Loading