Commit 14a8fd7c authored by Masami Hiramatsu's avatar Masami Hiramatsu Committed by Steven Rostedt
Browse files

perf probe: Support adding probes on offline kernel modules



Support adding probes on offline kernel modules. This enables
perf-probe to trace kernel-module init functions via perf-probe.
If user gives the path of module with -m option, perf-probe
expects the module is offline.
This feature works with --add, --funcs, and --vars.

E.g)
 # perf probe -m /lib/modules/`uname -r`/kernel/fs/btrfs/btrfs.ko \
   -a "extent_io_init:5 extent_state_cache"
 Add new events:
   probe:extent_io_init (on extent_io_init:5 with extent_state_cache)
   probe:extent_io_init_1 (on extent_io_init:5 with extent_state_cache)

 You can now use it on all perf tools, such as:

         perf record -e probe:extent_io_init_1 -aR sleep 1

Signed-off-by: default avatarMasami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Ingo Molnar <mingo@elte.hu>
Cc: Arnaldo Carvalho de Melo <acme@ghostprotocols.net>
Link: http://lkml.kernel.org/r/20110627072751.6528.10230.stgit@fedora15


Signed-off-by: default avatarSteven Rostedt <rostedt@goodmis.org>
parent 190b57fc
Loading
Loading
Loading
Loading
+4 −2
Original line number Diff line number Diff line
@@ -34,9 +34,11 @@ OPTIONS
	Specify vmlinux path which has debuginfo (Dwarf binary).

-m::
--module=MODNAME::
--module=MODNAME|PATH::
	Specify module name in which perf-probe searches probe points
	or lines.
	or lines. If a path of module file is passed, perf-probe
	treat it as an offline module (this means you can add a probe on
        a module which has not been loaded yet).

-s::
--source=PATH::
+2 −1
Original line number Diff line number Diff line
@@ -242,7 +242,8 @@ static const struct option options[] = {
	OPT_STRING('s', "source", &symbol_conf.source_prefix,
		   "directory", "path to kernel source"),
	OPT_STRING('m', "module", &params.target_module,
		   "modname", "target module name"),
		   "modname|path",
		   "target module name (for online) or path (for offline)"),
#endif
	OPT__DRY_RUN(&probe_event_dry_run),
	OPT_INTEGER('\0', "max-probes", &params.max_probe_points,
+43 −9
Original line number Diff line number Diff line
@@ -117,6 +117,10 @@ static struct map *kernel_get_module_map(const char *module)
	struct rb_node *nd;
	struct map_groups *grp = &machine.kmaps;

	/* A file path -- this is an offline module */
	if (module && strchr(module, '/'))
		return machine__new_module(&machine, 0, module);

	if (!module)
		module = "kernel";

@@ -173,13 +177,20 @@ const char *kernel_get_module_path(const char *module)
/* Open new debuginfo of given module */
static struct debuginfo *open_debuginfo(const char *module)
{
	const char *path = kernel_get_module_path(module);
	const char *path;

	/* A file path -- this is an offline module */
	if (module && strchr(module, '/'))
		path = module;
	else {
		path = kernel_get_module_path(module);

		if (!path) {
			pr_err("Failed to find path of %s module.\n",
			       module ?: "kernel");
			return NULL;
		}
	}
	return debuginfo__new(path);
}

@@ -229,13 +240,36 @@ static int kprobe_convert_to_perf_probe(struct probe_trace_point *tp,
static int add_module_to_probe_trace_events(struct probe_trace_event *tevs,
					    int ntevs, const char *module)
{
	int i;
	int i, ret = 0;
	char *tmp;

	if (!module)
		return 0;

	tmp = strrchr(module, '/');
	if (tmp) {
		/* This is a module path -- get the module name */
		module = strdup(tmp + 1);
		if (!module)
			return -ENOMEM;
		tmp = strchr(module, '.');
		if (tmp)
			*tmp = '\0';
		tmp = (char *)module;	/* For free() */
	}

	for (i = 0; i < ntevs; i++) {
		tevs[i].point.module = strdup(module);
		if (!tevs[i].point.module)
			return -ENOMEM;
		if (!tevs[i].point.module) {
			ret = -ENOMEM;
			break;
		}
	return 0;
	}

	if (tmp)
		free(tmp);

	return ret;
}

/* Try to find perf_probe_event with debuginfo */