mirror of
https://github.com/Fishwaldo/Star64_linux.git
synced 2025-06-28 17:41:50 +00:00
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: Masami 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: Steven Rostedt <rostedt@goodmis.org>
This commit is contained in:
parent
190b57fcb9
commit
14a8fd7cee
3 changed files with 49 additions and 12 deletions
|
@ -34,9 +34,11 @@ OPTIONS
|
||||||
Specify vmlinux path which has debuginfo (Dwarf binary).
|
Specify vmlinux path which has debuginfo (Dwarf binary).
|
||||||
|
|
||||||
-m::
|
-m::
|
||||||
--module=MODNAME::
|
--module=MODNAME|PATH::
|
||||||
Specify module name in which perf-probe searches probe points
|
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::
|
-s::
|
||||||
--source=PATH::
|
--source=PATH::
|
||||||
|
|
|
@ -242,7 +242,8 @@ static const struct option options[] = {
|
||||||
OPT_STRING('s', "source", &symbol_conf.source_prefix,
|
OPT_STRING('s', "source", &symbol_conf.source_prefix,
|
||||||
"directory", "path to kernel source"),
|
"directory", "path to kernel source"),
|
||||||
OPT_STRING('m', "module", ¶ms.target_module,
|
OPT_STRING('m', "module", ¶ms.target_module,
|
||||||
"modname", "target module name"),
|
"modname|path",
|
||||||
|
"target module name (for online) or path (for offline)"),
|
||||||
#endif
|
#endif
|
||||||
OPT__DRY_RUN(&probe_event_dry_run),
|
OPT__DRY_RUN(&probe_event_dry_run),
|
||||||
OPT_INTEGER('\0', "max-probes", ¶ms.max_probe_points,
|
OPT_INTEGER('\0', "max-probes", ¶ms.max_probe_points,
|
||||||
|
|
|
@ -117,6 +117,10 @@ static struct map *kernel_get_module_map(const char *module)
|
||||||
struct rb_node *nd;
|
struct rb_node *nd;
|
||||||
struct map_groups *grp = &machine.kmaps;
|
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)
|
if (!module)
|
||||||
module = "kernel";
|
module = "kernel";
|
||||||
|
|
||||||
|
@ -173,13 +177,20 @@ const char *kernel_get_module_path(const char *module)
|
||||||
/* Open new debuginfo of given module */
|
/* Open new debuginfo of given module */
|
||||||
static struct debuginfo *open_debuginfo(const char *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) {
|
if (!path) {
|
||||||
pr_err("Failed to find path of %s module.\n",
|
pr_err("Failed to find path of %s module.\n",
|
||||||
module ?: "kernel");
|
module ?: "kernel");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return debuginfo__new(path);
|
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,
|
static int add_module_to_probe_trace_events(struct probe_trace_event *tevs,
|
||||||
int ntevs, const char *module)
|
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++) {
|
for (i = 0; i < ntevs; i++) {
|
||||||
tevs[i].point.module = strdup(module);
|
tevs[i].point.module = strdup(module);
|
||||||
if (!tevs[i].point.module)
|
if (!tevs[i].point.module) {
|
||||||
return -ENOMEM;
|
ret = -ENOMEM;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
return 0;
|
}
|
||||||
|
|
||||||
|
if (tmp)
|
||||||
|
free(tmp);
|
||||||
|
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Try to find perf_probe_event with debuginfo */
|
/* Try to find perf_probe_event with debuginfo */
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue