aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMasami Hiramatsu <masami.hiramatsu.pt@hitachi.com>2011-06-27 03:27:51 -0400
committerSteven Rostedt <rostedt@goodmis.org>2011-07-15 16:25:12 -0400
commit14a8fd7ceea6915c613746203d6e9a2bf273f16c (patch)
tree738803bc847efa3a17e9076922f06ceaca20d8f0
parent190b57fcb9c5fed5414935a174094f534fc510bc (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.txt6
-rw-r--r--tools/perf/builtin-probe.c3
-rw-r--r--tools/perf/util/probe-event.c52
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", &params.target_module, 244 OPT_STRING('m', "module", &params.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", &params.max_probe_points, 249 OPT_INTEGER('\0', "max-probes", &params.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 */
174static struct debuginfo *open_debuginfo(const char *module) 178static 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,
229static int add_module_to_probe_trace_events(struct probe_trace_event *tevs, 240static 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 */