diff options
author | Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com> | 2011-06-27 03:27:51 -0400 |
---|---|---|
committer | Steven Rostedt <rostedt@goodmis.org> | 2011-07-15 16:25:12 -0400 |
commit | 14a8fd7ceea6915c613746203d6e9a2bf273f16c (patch) | |
tree | 738803bc847efa3a17e9076922f06ceaca20d8f0 | |
parent | 190b57fcb9c5fed5414935a174094f534fc510bc (diff) |
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>
-rw-r--r-- | tools/perf/Documentation/perf-probe.txt | 6 | ||||
-rw-r--r-- | tools/perf/builtin-probe.c | 3 | ||||
-rw-r--r-- | tools/perf/util/probe-event.c | 52 |
3 files changed, 49 insertions, 12 deletions
diff --git a/tools/perf/Documentation/perf-probe.txt b/tools/perf/Documentation/perf-probe.txt index 02bafce4b341..2780d9ce48bf 100644 --- a/tools/perf/Documentation/perf-probe.txt +++ b/tools/perf/Documentation/perf-probe.txt | |||
@@ -34,9 +34,11 @@ OPTIONS | |||
34 | Specify vmlinux path which has debuginfo (Dwarf binary). | 34 | Specify vmlinux path which has debuginfo (Dwarf binary). |
35 | 35 | ||
36 | -m:: | 36 | -m:: |
37 | --module=MODNAME:: | 37 | --module=MODNAME|PATH:: |
38 | Specify module name in which perf-probe searches probe points | 38 | Specify module name in which perf-probe searches probe points |
39 | or lines. | 39 | or lines. If a path of module file is passed, perf-probe |
40 | treat it as an offline module (this means you can add a probe on | ||
41 | a module which has not been loaded yet). | ||
40 | 42 | ||
41 | -s:: | 43 | -s:: |
42 | --source=PATH:: | 44 | --source=PATH:: |
diff --git a/tools/perf/builtin-probe.c b/tools/perf/builtin-probe.c index 2c0e64d0b4aa..5f2a5c7046df 100644 --- a/tools/perf/builtin-probe.c +++ b/tools/perf/builtin-probe.c | |||
@@ -242,7 +242,8 @@ static const struct option options[] = { | |||
242 | OPT_STRING('s', "source", &symbol_conf.source_prefix, | 242 | OPT_STRING('s', "source", &symbol_conf.source_prefix, |
243 | "directory", "path to kernel source"), | 243 | "directory", "path to kernel source"), |
244 | OPT_STRING('m', "module", ¶ms.target_module, | 244 | OPT_STRING('m', "module", ¶ms.target_module, |
245 | "modname", "target module name"), | 245 | "modname|path", |
246 | "target module name (for online) or path (for offline)"), | ||
246 | #endif | 247 | #endif |
247 | OPT__DRY_RUN(&probe_event_dry_run), | 248 | OPT__DRY_RUN(&probe_event_dry_run), |
248 | OPT_INTEGER('\0', "max-probes", ¶ms.max_probe_points, | 249 | OPT_INTEGER('\0', "max-probes", ¶ms.max_probe_points, |
diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c index ee3f41eec5c1..b82d54fa2c56 100644 --- a/tools/perf/util/probe-event.c +++ b/tools/perf/util/probe-event.c | |||
@@ -117,6 +117,10 @@ static struct map *kernel_get_module_map(const char *module) | |||
117 | struct rb_node *nd; | 117 | struct rb_node *nd; |
118 | struct map_groups *grp = &machine.kmaps; | 118 | struct map_groups *grp = &machine.kmaps; |
119 | 119 | ||
120 | /* A file path -- this is an offline module */ | ||
121 | if (module && strchr(module, '/')) | ||
122 | return machine__new_module(&machine, 0, module); | ||
123 | |||
120 | if (!module) | 124 | if (!module) |
121 | module = "kernel"; | 125 | module = "kernel"; |
122 | 126 | ||
@@ -173,12 +177,19 @@ const char *kernel_get_module_path(const char *module) | |||
173 | /* Open new debuginfo of given module */ | 177 | /* Open new debuginfo of given module */ |
174 | static struct debuginfo *open_debuginfo(const char *module) | 178 | static struct debuginfo *open_debuginfo(const char *module) |
175 | { | 179 | { |
176 | const char *path = kernel_get_module_path(module); | 180 | const char *path; |
177 | 181 | ||
178 | if (!path) { | 182 | /* A file path -- this is an offline module */ |
179 | pr_err("Failed to find path of %s module.\n", | 183 | if (module && strchr(module, '/')) |
180 | module ?: "kernel"); | 184 | path = module; |
181 | return NULL; | 185 | else { |
186 | path = kernel_get_module_path(module); | ||
187 | |||
188 | if (!path) { | ||
189 | pr_err("Failed to find path of %s module.\n", | ||
190 | module ?: "kernel"); | ||
191 | return NULL; | ||
192 | } | ||
182 | } | 193 | } |
183 | return debuginfo__new(path); | 194 | return debuginfo__new(path); |
184 | } | 195 | } |
@@ -229,13 +240,36 @@ static int kprobe_convert_to_perf_probe(struct probe_trace_point *tp, | |||
229 | static int add_module_to_probe_trace_events(struct probe_trace_event *tevs, | 240 | static int add_module_to_probe_trace_events(struct probe_trace_event *tevs, |
230 | int ntevs, const char *module) | 241 | int ntevs, const char *module) |
231 | { | 242 | { |
232 | int i; | 243 | int i, ret = 0; |
244 | char *tmp; | ||
245 | |||
246 | if (!module) | ||
247 | return 0; | ||
248 | |||
249 | tmp = strrchr(module, '/'); | ||
250 | if (tmp) { | ||
251 | /* This is a module path -- get the module name */ | ||
252 | module = strdup(tmp + 1); | ||
253 | if (!module) | ||
254 | return -ENOMEM; | ||
255 | tmp = strchr(module, '.'); | ||
256 | if (tmp) | ||
257 | *tmp = '\0'; | ||
258 | tmp = (char *)module; /* For free() */ | ||
259 | } | ||
260 | |||
233 | for (i = 0; i < ntevs; i++) { | 261 | for (i = 0; i < ntevs; i++) { |
234 | tevs[i].point.module = strdup(module); | 262 | tevs[i].point.module = strdup(module); |
235 | if (!tevs[i].point.module) | 263 | if (!tevs[i].point.module) { |
236 | return -ENOMEM; | 264 | ret = -ENOMEM; |
265 | break; | ||
266 | } | ||
237 | } | 267 | } |
238 | return 0; | 268 | |
269 | if (tmp) | ||
270 | free(tmp); | ||
271 | |||
272 | return ret; | ||
239 | } | 273 | } |
240 | 274 | ||
241 | /* Try to find perf_probe_event with debuginfo */ | 275 | /* Try to find perf_probe_event with debuginfo */ |