Commit 14a8fd7ceea6915c613746203d6e9a2bf273f16c
Committed by
Steven Rostedt
1 parent
190b57fcb9
Exists in
master
and in
38 other branches
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", ¶ms.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", ¶ms.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 */ |