Commit 14a8fd7ceea6915c613746203d6e9a2bf273f16c

Authored by Masami Hiramatsu
Committed by Steven Rostedt
1 parent 190b57fcb9

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>

Showing 3 changed files with 49 additions and 12 deletions Side-by-side Diff

tools/perf/Documentation/perf-probe.txt
... ... @@ -34,9 +34,11 @@
34 34 Specify vmlinux path which has debuginfo (Dwarf binary).
35 35  
36 36 -m::
37   ---module=MODNAME::
  37 +--module=MODNAME|PATH::
38 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 43 -s::
42 44 --source=PATH::
tools/perf/builtin-probe.c
... ... @@ -242,7 +242,8 @@
242 242 OPT_STRING('s', "source", &symbol_conf.source_prefix,
243 243 "directory", "path to kernel source"),
244 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 247 #endif
247 248 OPT__DRY_RUN(&probe_event_dry_run),
248 249 OPT_INTEGER('\0', "max-probes", &params.max_probe_points,
tools/perf/util/probe-event.c
... ... @@ -117,6 +117,10 @@
117 117 struct rb_node *nd;
118 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 124 if (!module)
121 125 module = "kernel";
122 126  
123 127  
... ... @@ -173,12 +177,19 @@
173 177 /* Open new debuginfo of given module */
174 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) {
179   - pr_err("Failed to find path of %s module.\n",
180   - module ?: "kernel");
181   - return NULL;
  182 + /* A file path -- this is an offline module */
  183 + if (module && strchr(module, '/'))
  184 + path = module;
  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 194 return debuginfo__new(path);
184 195 }
185 196  
186 197  
... ... @@ -229,13 +240,36 @@
229 240 static int add_module_to_probe_trace_events(struct probe_trace_event *tevs,
230 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 261 for (i = 0; i < ntevs; i++) {
234 262 tevs[i].point.module = strdup(module);
235   - if (!tevs[i].point.module)
236   - return -ENOMEM;
  263 + if (!tevs[i].point.module) {
  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 275 /* Try to find perf_probe_event with debuginfo */